use of com.oracle.svm.util.ReflectionUtil.ReflectionUtilError in project graal by oracle.
the class Target_java_lang_reflect_RecordComponent method initEnumConstantsAtRuntime.
@Platforms(Platform.HOSTED_ONLY.class)
public void initEnumConstantsAtRuntime(Class<?> enumClass) {
/* Adapted from `Class.getEnumConstantsShared`. */
try {
Method values = ReflectionUtil.lookupMethod(enumClass, "values");
enumConstantsReference = new LazyFinalReference<>(() -> initEnumConstantsAtRuntime(values));
} catch (ReflectionUtilError e) {
/*
* This can happen when users concoct enum-like classes that don't comply with the enum
* spec.
*/
enumConstantsReference = null;
} catch (NoClassDefFoundError e) {
/*
* This can happen when an enum references a missing class. So, in order to match the
* JVM behaviour, we rethrow the error at runtime.
*/
String message = e.getMessage();
enumConstantsReference = new LazyFinalReference<>(() -> throwNoClassDefFoundErrorAtRuntime(message));
}
}
use of com.oracle.svm.util.ReflectionUtil.ReflectionUtilError in project graal by oracle.
the class RawStructureLayoutPlanner method planLayout.
/**
* Compute the offsets of each field.
*/
private void planLayout(RawStructureInfo info) {
/* Inherit from the parent type. */
int currentOffset = info.getParentInfo() != null ? info.getParentInfo().getSizeInfo().getProperty() : 0;
List<StructFieldInfo> fields = new ArrayList<>();
for (ElementInfo child : info.getChildren()) {
if (child instanceof StructFieldInfo) {
fields.add((StructFieldInfo) child);
} else if (child instanceof StructBitfieldInfo) {
throw UserError.abort("StructBitfield is currently not supported by RawStructures!");
}
}
/*
* Sort fields in field size descending order. Note that prior to this, the fields are
* already sorted in alphabetical order.
*/
fields.sort((f1, f2) -> f2.getSizeInfo().getProperty() - f1.getSizeInfo().getProperty());
for (StructFieldInfo finfo : fields) {
assert findParentFieldInfo(finfo, info.getParentInfo()) == null;
int fieldSize = finfo.getSizeInfo().getProperty();
currentOffset = alignOffset(currentOffset, fieldSize);
assert currentOffset % fieldSize == 0;
finfo.getOffsetInfo().setProperty(currentOffset);
currentOffset += fieldSize;
}
int totalSize;
Class<? extends IntUnaryOperator> sizeProviderClass = info.getAnnotatedElement().getAnnotation(RawStructure.class).sizeProvider();
if (sizeProviderClass == IntUnaryOperator.class) {
/* No sizeProvider specified in the annotation, so no adjustment necessary. */
totalSize = currentOffset;
} else {
IntUnaryOperator sizeProvider;
try {
sizeProvider = ReflectionUtil.newInstance(sizeProviderClass);
} catch (ReflectionUtilError ex) {
throw UserError.abort(ex.getCause(), "The size provider of @%s %s cannot be instantiated via no-argument constructor", RawStructure.class.getSimpleName(), info.getAnnotatedElement().toJavaName(true));
}
totalSize = sizeProvider.applyAsInt(currentOffset);
if (totalSize < currentOffset) {
throw UserError.abort("The size provider of @%s %s computed size %d which is smaller than the minimum size of %d", RawStructure.class.getSimpleName(), info.getAnnotatedElement().toJavaName(true), totalSize, currentOffset);
}
}
info.getSizeInfo().setProperty(totalSize);
info.setPlanned();
}
use of com.oracle.svm.util.ReflectionUtil.ReflectionUtilError in project graal by oracle.
the class FeatureHandler method registerFeature.
/**
* Instantiates the given feature class and (recursively) all feature classes it requires.
*
* @param access
*/
@SuppressWarnings("unchecked")
private void registerFeature(Class<?> baseFeatureClass, Function<Class<?>, Class<?>> specificClassProvider, IsInConfigurationAccessImpl access) {
if (!Feature.class.isAssignableFrom(baseFeatureClass)) {
throw UserError.abort("Class does not implement %s: %s", Feature.class.getName(), baseFeatureClass.getName());
}
if (registeredFeatures.contains(baseFeatureClass)) {
return;
}
/*
* Immediately add to the registeredFeatures to avoid infinite recursion in case of cyclic
* dependencies.
*/
registeredFeatures.add(baseFeatureClass);
Class<?> specificClass = specificClassProvider.apply(baseFeatureClass);
Class<?> featureClass = specificClass != null ? specificClass : baseFeatureClass;
Feature feature;
try {
feature = (Feature) ReflectionUtil.newInstance(featureClass);
} catch (ReflectionUtilError ex) {
throw UserError.abort(ex.getCause(), "Error instantiating Feature class %s. Ensure the class is not abstract and has a no-argument constructor.", featureClass.getTypeName());
}
if (!feature.isInConfiguration(access)) {
return;
}
/*
* All features are automatically added to the VMConfiguration, to allow convenient
* configuration checks.
*/
ImageSingletons.add((Class<Feature>) baseFeatureClass, feature);
/*
* First add dependent features so that initializers are executed in order of dependencies.
*/
for (Class<? extends Feature> requiredFeatureClass : feature.getRequiredFeatures()) {
registerFeature(requiredFeatureClass, specificClassProvider, access);
}
featureInstances.add(feature);
}
use of com.oracle.svm.util.ReflectionUtil.ReflectionUtilError in project graal by oracle.
the class NativeImageGeneratorRunner method buildImage.
@SuppressWarnings("try")
private int buildImage(ImageClassLoader classLoader) {
if (!verifyValidJavaVersionAndPlatform()) {
return 1;
}
HostedOptionParser optionParser = classLoader.classLoaderSupport.getHostedOptionParser();
OptionValues parsedHostedOptions = classLoader.classLoaderSupport.getParsedHostedOptions();
String imageName = SubstrateOptions.Name.getValue(parsedHostedOptions);
TimerCollection timerCollection = new TimerCollection(imageName);
Timer totalTimer = timerCollection.get(TimerCollection.Registry.TOTAL);
if (NativeImageOptions.ListCPUFeatures.getValue(parsedHostedOptions)) {
printCPUFeatures(classLoader.platform);
return 0;
}
ForkJoinPool analysisExecutor = null;
ForkJoinPool compilationExecutor = null;
ProgressReporter reporter = new ProgressReporter(parsedHostedOptions);
boolean wasSuccessfulBuild = false;
try (StopTimer ignored = totalTimer.start()) {
Timer classlistTimer = timerCollection.get(TimerCollection.Registry.CLASSLIST);
try (StopTimer ignored1 = classlistTimer.start()) {
classLoader.initAllClasses();
}
DebugContext debug = new DebugContext.Builder(parsedHostedOptions, new GraalDebugHandlersFactory(GraalAccess.getOriginalSnippetReflection())).build();
if (imageName.length() == 0) {
throw UserError.abort("No output file name specified. Use '%s'.", SubstrateOptionsParser.commandArgument(SubstrateOptions.Name, "<output-file>"));
}
try {
// print the time here to avoid interactions with flags processing
classlistTimer.print();
Map<Method, CEntryPointData> entryPoints = new HashMap<>();
Pair<Method, CEntryPointData> mainEntryPointData = Pair.empty();
JavaMainSupport javaMainSupport = null;
NativeImageKind imageKind;
boolean isStaticExecutable = SubstrateOptions.StaticExecutable.getValue(parsedHostedOptions);
boolean isSharedLibrary = SubstrateOptions.SharedLibrary.getValue(parsedHostedOptions);
if (isStaticExecutable && isSharedLibrary) {
throw UserError.abort("Cannot pass both option: %s and %s", SubstrateOptionsParser.commandArgument(SubstrateOptions.SharedLibrary, "+"), SubstrateOptionsParser.commandArgument(SubstrateOptions.StaticExecutable, "+"));
} else if (isSharedLibrary) {
imageKind = NativeImageKind.SHARED_LIBRARY;
} else if (isStaticExecutable) {
imageKind = NativeImageKind.STATIC_EXECUTABLE;
} else {
imageKind = NativeImageKind.EXECUTABLE;
}
String className = SubstrateOptions.Class.getValue(parsedHostedOptions);
String moduleName = SubstrateOptions.Module.getValue(parsedHostedOptions);
if (imageKind.isExecutable && moduleName.isEmpty() && className.isEmpty()) {
throw UserError.abort("Must specify main entry point class when building %s native image. Use '%s'.", imageKind, SubstrateOptionsParser.commandArgument(SubstrateOptions.Class, "<fully-qualified-class-name>"));
}
reporter.printStart(imageName, imageKind);
if (!className.isEmpty() || !moduleName.isEmpty()) {
Method mainEntryPoint;
Class<?> mainClass;
try {
Object mainModule = null;
if (!moduleName.isEmpty()) {
mainModule = classLoader.findModule(moduleName).orElseThrow(() -> UserError.abort("Module " + moduleName + " for mainclass not found."));
}
if (className.isEmpty()) {
className = classLoader.getMainClassFromModule(mainModule).orElseThrow(() -> UserError.abort("module %s does not have a ModuleMainClass attribute, use -m <module>/<main-class>", moduleName));
}
mainClass = classLoader.forName(className, mainModule);
if (mainClass == null) {
throw UserError.abort(classLoader.getMainClassNotFoundErrorMessage(className));
}
} catch (ClassNotFoundException ex) {
throw UserError.abort(classLoader.getMainClassNotFoundErrorMessage(className));
}
String mainEntryPointName = SubstrateOptions.Method.getValue(parsedHostedOptions);
if (mainEntryPointName.isEmpty()) {
throw UserError.abort("Must specify main entry point method when building %s native image. Use '%s'.", imageKind, SubstrateOptionsParser.commandArgument(SubstrateOptions.Method, "<method-name>"));
}
try {
/*
* First look for an main method with the C-level signature for arguments.
*/
mainEntryPoint = mainClass.getDeclaredMethod(mainEntryPointName, int.class, CCharPointerPointer.class);
} catch (NoSuchMethodException ignored2) {
Method javaMainMethod;
try {
/*
* If no C-level main method was found, look for a Java-level main
* method and use our wrapper to invoke it.
*/
javaMainMethod = ReflectionUtil.lookupMethod(mainClass, mainEntryPointName, String[].class);
} catch (ReflectionUtilError ex) {
throw UserError.abort(ex.getCause(), "Method '%s.%s' is declared as the main entry point but it can not be found. " + "Make sure that class '%s' is on the classpath and that method '%s(String[])' exists in that class.", mainClass.getName(), mainEntryPointName, mainClass.getName(), mainEntryPointName);
}
if (javaMainMethod.getReturnType() != void.class) {
throw UserError.abort("Java main method '%s.%s(String[])' does not have the return type 'void'.", mainClass.getName(), mainEntryPointName);
}
final int mainMethodModifiers = javaMainMethod.getModifiers();
if (!Modifier.isStatic(mainMethodModifiers)) {
throw UserError.abort("Java main method '%s.%s(String[])' is not static.", mainClass.getName(), mainEntryPointName);
}
if (!Modifier.isPublic(mainMethodModifiers)) {
throw UserError.abort("Java main method '%s.%s(String[])' is not public.", mainClass.getName(), mainEntryPointName);
}
javaMainSupport = new JavaMainSupport(javaMainMethod);
mainEntryPoint = JavaMainWrapper.class.getDeclaredMethod("run", int.class, CCharPointerPointer.class);
}
CEntryPoint annotation = mainEntryPoint.getAnnotation(CEntryPoint.class);
if (annotation == null) {
throw UserError.abort("Entry point must have the '@%s' annotation", CEntryPoint.class.getSimpleName());
}
Class<?>[] pt = mainEntryPoint.getParameterTypes();
if (pt.length != 2 || pt[0] != int.class || pt[1] != CCharPointerPointer.class || mainEntryPoint.getReturnType() != int.class) {
throw UserError.abort("Main entry point must have signature 'int main(int argc, CCharPointerPointer argv)'.");
}
mainEntryPointData = Pair.create(mainEntryPoint, CEntryPointData.create(mainEntryPoint, imageKind.mainEntryPointName));
}
int maxConcurrentThreads = NativeImageOptions.getMaximumNumberOfConcurrentThreads(parsedHostedOptions);
analysisExecutor = NativeImagePointsToAnalysis.createExecutor(debug, NativeImageOptions.getMaximumNumberOfAnalysisThreads(parsedHostedOptions));
compilationExecutor = NativeImagePointsToAnalysis.createExecutor(debug, maxConcurrentThreads);
generator = new NativeImageGenerator(classLoader, optionParser, mainEntryPointData, reporter);
generator.run(entryPoints, javaMainSupport, imageName, imageKind, SubstitutionProcessor.IDENTITY, compilationExecutor, analysisExecutor, optionParser.getRuntimeOptionNames(), timerCollection);
wasSuccessfulBuild = true;
} finally {
if (!wasSuccessfulBuild) {
reporter.printUnsuccessfulInitializeEnd();
}
}
} catch (InterruptImageBuilding e) {
if (analysisExecutor != null) {
analysisExecutor.shutdownNow();
}
if (compilationExecutor != null) {
compilationExecutor.shutdownNow();
}
throw e;
} catch (FallbackFeature.FallbackImageRequest e) {
if (FallbackExecutor.class.getName().equals(SubstrateOptions.Class.getValue())) {
NativeImageGeneratorRunner.reportFatalError(e, "FallbackImageRequest while building fallback image.");
return 1;
}
reportUserException(e, parsedHostedOptions, NativeImageGeneratorRunner::warn);
return 2;
} catch (ParsingError e) {
NativeImageGeneratorRunner.reportFatalError(e);
return 1;
} catch (UserException | AnalysisError e) {
reportUserError(e, parsedHostedOptions);
return 1;
} catch (ParallelExecutionException pee) {
boolean hasUserError = false;
for (Throwable exception : pee.getExceptions()) {
if (exception instanceof UserException) {
reportUserError(exception, parsedHostedOptions);
hasUserError = true;
} else if (exception instanceof AnalysisError && !(exception instanceof ParsingError)) {
reportUserError(exception, parsedHostedOptions);
hasUserError = true;
}
}
if (hasUserError) {
return 1;
}
if (pee.getExceptions().size() > 1) {
System.err.println(pee.getExceptions().size() + " fatal errors detected:");
}
for (Throwable exception : pee.getExceptions()) {
NativeImageGeneratorRunner.reportFatalError(exception);
}
return 1;
} catch (Throwable e) {
NativeImageGeneratorRunner.reportFatalError(e);
return 1;
} finally {
totalTimer.print();
if (imageName != null && generator != null) {
reporter.printEpilog(imageName, generator, wasSuccessfulBuild, parsedHostedOptions);
}
NativeImageGenerator.clearSystemPropertiesForImage();
ImageSingletonsSupportImpl.HostedManagement.clear();
}
return 0;
}
use of com.oracle.svm.util.ReflectionUtil.ReflectionUtilError in project graal by oracle.
the class APIOptionFeature method extractOption.
private static void extractOption(String optionPrefix, OptionDescriptor optionDescriptor, SortedMap<String, OptionInfo> apiOptions, Map<String, GroupInfo> groupInfos, Map<Class<? extends APIOptionGroup>, APIOptionGroup> groupInstances) {
try {
Field optionField = optionDescriptor.getDeclaringClass().getDeclaredField(optionDescriptor.getFieldName());
APIOption[] apiAnnotations = optionField.getAnnotationsByType(APIOption.class);
for (APIOption apiAnnotation : apiAnnotations) {
String builderOption = optionPrefix;
if (apiAnnotation.name().length <= 0) {
VMError.shouldNotReachHere(String.format("APIOption for %s does not provide a name entry", optionDescriptor.getLocation()));
}
String apiOptionName = APIOption.Utils.optionName(apiAnnotation.name()[0]);
String rawOptionName = optionDescriptor.getName();
APIOptionGroup group = null;
String defaultValue = null;
boolean booleanOption = false;
Class<?> optionValueType = optionDescriptor.getOptionValueType();
if (optionValueType.isArray()) {
VMError.guarantee(optionDescriptor.getOptionKey() instanceof HostedOptionKey, "Only HostedOptionKeys are allowed to have array type key values.");
optionValueType = optionValueType.getComponentType();
}
boolean hasFixedValue = apiAnnotation.fixedValue().length > 0;
if (optionValueType.equals(Boolean.class)) {
if (!apiAnnotation.group().equals(APIOption.NullGroup.class)) {
try {
Class<? extends APIOptionGroup> groupClass = apiAnnotation.group();
APIOptionGroup g = group = groupInstances.computeIfAbsent(groupClass, ReflectionUtil::newInstance);
String groupName = APIOption.Utils.groupName(group);
GroupInfo groupInfo = groupInfos.computeIfAbsent(groupName, (n) -> new GroupInfo(g));
if (group.helpText() == null || group.helpText().isEmpty()) {
VMError.shouldNotReachHere(String.format("APIOptionGroup %s(%s) needs to provide help text", groupClass.getName(), group.name()));
}
String groupMember = apiAnnotation.name()[0];
groupInfo.supportedValues.add(groupMember);
apiOptionName = groupName + groupMember;
Boolean isEnabled = (Boolean) optionDescriptor.getOptionKey().getDefaultValue();
if (isEnabled) {
groupInfo.defaultValues.add(groupMember);
/* Use OptionInfo.defaultValue to remember group default value */
defaultValue = groupMember;
}
} catch (ReflectionUtilError ex) {
throw VMError.shouldNotReachHere("Class specified as group for @APIOption " + apiOptionName + " cannot be loaded or instantiated: " + apiAnnotation.group().getTypeName(), ex.getCause());
}
}
if (apiAnnotation.kind().equals(APIOptionKind.Paths)) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOptionKind.Paths", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 0) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOption.defaultValue", apiOptionName, rawOptionName));
}
if (hasFixedValue) {
VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s) cannot use APIOption.fixedValue", apiOptionName, rawOptionName));
}
builderOption += apiAnnotation.kind().equals(APIOptionKind.Negated) ? "-" : "+";
builderOption += rawOptionName;
booleanOption = true;
} else {
if (!apiAnnotation.group().equals(APIOption.NullGroup.class)) {
VMError.shouldNotReachHere(String.format("Using @APIOption.group not supported for non-boolean APIOption %s(%s)", apiOptionName, rawOptionName));
}
if (apiAnnotation.kind().equals(APIOptionKind.Negated)) {
VMError.shouldNotReachHere(String.format("Non-boolean APIOption %s(%s) cannot use APIOptionKind.Negated", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 1) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) cannot have more than one APIOption.defaultValue", apiOptionName, rawOptionName));
}
if (apiAnnotation.fixedValue().length > 1) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) cannot have more than one APIOption.fixedValue", apiOptionName, rawOptionName));
}
if (hasFixedValue && apiAnnotation.defaultValue().length > 0) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) APIOption.defaultValue and APIOption.fixedValue cannot be combined", apiOptionName, rawOptionName));
}
if (apiAnnotation.defaultValue().length > 0) {
defaultValue = apiAnnotation.defaultValue()[0];
}
if (hasFixedValue) {
defaultValue = apiAnnotation.fixedValue()[0];
}
builderOption += rawOptionName;
builderOption += "=";
}
String helpText = optionDescriptor.getHelp();
if (!apiAnnotation.customHelp().isEmpty()) {
helpText = apiAnnotation.customHelp();
}
if (helpText == null || helpText.isEmpty()) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) needs to provide help text", apiOptionName, rawOptionName));
}
if (group == null) {
/* Regular help text needs to start with lower-case letter */
helpText = startLowerCase(helpText);
}
List<Function<Object, Object>> valueTransformers = new ArrayList<>(apiAnnotation.valueTransformer().length);
for (Class<? extends Function<Object, Object>> transformerClass : apiAnnotation.valueTransformer()) {
try {
valueTransformers.add(ReflectionUtil.newInstance(transformerClass));
} catch (ReflectionUtilError ex) {
throw VMError.shouldNotReachHere("Class specified as valueTransformer for @APIOption " + apiOptionName + " cannot be loaded or instantiated: " + transformerClass.getTypeName(), ex.getCause());
}
}
if (apiAnnotation.valueSeparator().length == 0) {
throw VMError.shouldNotReachHere(String.format("APIOption %s(%s) does not specify any valueSeparator", apiOptionName, rawOptionName));
}
for (char valueSeparator : apiAnnotation.valueSeparator()) {
if (valueSeparator == APIOption.WHITESPACE_SEPARATOR) {
String msgTail = " cannot use APIOption.WHITESPACE_SEPARATOR as value separator";
if (booleanOption) {
throw VMError.shouldNotReachHere(String.format("Boolean APIOption %s(%s)" + msgTail, apiOptionName, rawOptionName));
}
if (hasFixedValue) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) with fixed value" + msgTail, apiOptionName, rawOptionName));
}
if (defaultValue != null) {
VMError.shouldNotReachHere(String.format("APIOption %s(%s) with default value" + msgTail, apiOptionName, rawOptionName));
}
}
}
boolean defaultFinal = booleanOption || hasFixedValue;
apiOptions.put(apiOptionName, new APIOptionHandler.OptionInfo(apiAnnotation.name(), apiAnnotation.valueSeparator(), builderOption, defaultValue, helpText, apiAnnotation.kind().equals(APIOptionKind.Paths), defaultFinal, apiAnnotation.deprecated(), valueTransformers, group, apiAnnotation.extra()));
}
} catch (NoSuchFieldException e) {
/* Does not qualify as APIOption */
}
}
Aggregations