/*
 * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.svm.core.option;

import java.util.Arrays;

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.log.Log;

A parser for the HotSpot-like memory sizing options "-Xmn", "-Xms", "-Xmx", "-Xss". Every option has a corresponding RuntimeOptionKey in SubstrateOptions. So, the resulting behavior is pretty much as if an APIOption was specified for a RuntimeOptionKey.
/** * A parser for the HotSpot-like memory sizing options "-Xmn", "-Xms", "-Xmx", "-Xss". Every option * has a corresponding {@link RuntimeOptionKey} in {@link SubstrateOptions}. So, the resulting * behavior is pretty much as if an {@link APIOption} was specified for a {@link RuntimeOptionKey}. */
public class XOptions { public static XOptions singleton() { return ImageSingletons.lookup(XOptions.class); } public static XFlag getXmn() { return XOptions.singleton().xmn; } public static XFlag getXms() { return XOptions.singleton().xms; } public static XFlag getXmx() { return XOptions.singleton().xmx; } public static XFlag getXss() { return XOptions.singleton().xss; }
The flag instances.
/** The flag instances. */
private final XFlag xmn; private final XFlag xmx; private final XFlag xms; private final XFlag xss;
For iterations over the flags.
/** For iterations over the flags. */
private final XFlag[] xFlagArray;
Private constructor during image building: clients use the image singleton.
/** Private constructor during image building: clients use the image singleton. */
@Platforms(Platform.HOSTED_ONLY.class) XOptions() { xmn = new XFlag("-X", "mn", "The maximum size of the young generation at run-time, in bytes."); xmx = new XFlag("-X", "mx", "The maximum heap size at run-time, in bytes."); xms = new XFlag("-X", "ms", "The minimum heap size at run-time, in bytes."); xss = new XFlag("-X", "ss", "The size of each thread stack at run-time, in bytes."); xFlagArray = new XFlag[]{xmn, xms, xmx, xss}; }
An X flag.
/** An X flag. */
public static class XFlag { private final String prefix; private final String name; private final String description; private long value; private long epoch;
The concatenation of the prefix and the name.
/** The concatenation of the prefix and the name. */
private final String prefixAndName;
Constructor.
/** Constructor. */
@Platforms(Platform.HOSTED_ONLY.class) XFlag(String prefix, String name, String description) { this.prefix = prefix; this.name = name; this.description = description; this.prefixAndName = prefix.concat(name); this.value = 0L; this.epoch = 0L; } public String getPrefix() { return prefix; } public String getName() { return name; } public String getPrefixAndName() { return prefixAndName; } public String getDescription() { return description; } public long getValue() { return value; } public long getEpoch() { return epoch; } public void setValue(long valueArg) { value = valueArg; epoch += 1L; } } /* Return the list of all the XFlags. */ public XFlag[] getXFlags() { /* Danger: Array results are not immutable. */ return xFlagArray; }
Parse the "-X" options out of a String[], returning the ones that are not "-X" options.
/** Parse the "-X" options out of a String[], returning the ones that are not "-X" options. */
public String[] parse(String[] args, boolean exitOnError) { int newIdx = 0; for (int oldIdx = 0; oldIdx < args.length; oldIdx += 1) { final String arg = args[oldIdx]; boolean parsed = false; for (XFlag xFlag : xFlagArray) { try { parsed |= parseWithNameAndPrefix(xFlag, arg); } catch (NumberFormatException nfe) { if (exitOnError) { Log.logStream().println("error: Wrong value for option '" + arg + "' is not a valid number."); System.exit(1); } else { throw new IllegalArgumentException("Illegal value for option '" + arg + "'", nfe); } } } if (!parsed) { assert newIdx <= oldIdx; args[newIdx] = arg; newIdx += 1; } } return (newIdx == args.length) ? args : Arrays.copyOf(args, newIdx); }
Try to parse the arg as the given xFlag. Returns true if successful, false otherwise. Throws NumberFormatException if the option was recognized, but the value was not a number.
/** * Try to parse the arg as the given xFlag. Returns true if successful, false otherwise. Throws * NumberFormatException if the option was recognized, but the value was not a number. */
private boolean parseWithNameAndPrefix(XFlag xFlag, String arg) throws NumberFormatException { if (arg.startsWith(xFlag.getPrefixAndName())) { final String valueString = arg.substring(xFlag.getPrefixAndName().length()); parseFromValueString(xFlag, valueString); return true; } return false; } /* Set from a String value, e.g., "2g". Returns true if successful, false otherwise. */ public void parseFromValueString(XFlag xFlag, String value) throws NumberFormatException { final long valueLong = SubstrateOptionsParser.parseLong(value); xFlag.setValue(valueLong); } }
Set up the singleton instance.
/** Set up the singleton instance. */
@AutomaticFeature class XOptionAccessFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { ImageSingletons.add(XOptions.class, new XOptions()); } }