Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusing error message about schema when building native image. #1573

Closed
wants to merge 9 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,9 @@ public ReflectionConfigurationParser(ReflectionConfigurationParserDelegate<T> de

@Override
public void parseAndRegister(Reader reader) throws IOException {
try {
JSONParser parser = new JSONParser(reader);
Object json = parser.parse();
parseClassArray(asList(json, "first level of document must be an array of class descriptors"));
} catch (NoClassDefFoundError e) {
throw e;
}
JSONParser parser = new JSONParser(reader);
Object json = parser.parse();
parseClassArray(asList(json, "first level of document must be an array of class descriptors"));
}

private void parseClassArray(List<Object> classes) {
Expand All @@ -81,7 +77,7 @@ private void parseClass(Map<String, Object> data) {

T clazz = delegate.resolveType(className);
if (clazz == null) {
handleError("Could not resolve " + className + " for reflection configuration.");
handleClasspathError("Class " + className + " not found in the classpath");
return;
}
delegate.registerType(clazz);
Expand Down Expand Up @@ -134,7 +130,7 @@ private void parseClass(Map<String, Object> data) {
delegate.getTypeName(clazz));
}
} catch (NoClassDefFoundError e) {
handleError("Could not register " + delegate.getTypeName(clazz) + ": " + name + " for reflection. Reason: " + formatError(e) + ".");
handleClasspathError("Could not register " + delegate.getTypeName(clazz) + ": " + name + " for reflection. Reason: " + formatError(e) + ".");
}
}
}
Expand Down Expand Up @@ -169,9 +165,9 @@ private void parseField(Map<String, Object> data, T clazz) {
try {
delegate.registerField(clazz, fieldName, allowWrite, allowUnsafeAccess);
} catch (NoSuchFieldException e) {
handleError("Field " + delegate.getTypeName(clazz) + "." + fieldName + " not found.");
handleParsingError("Field " + delegate.getTypeName(clazz) + "." + fieldName + " not found.");
} catch (NoClassDefFoundError e) {
handleError("Could not register field " + delegate.getTypeName(clazz) + "." + fieldName + " for reflection. Reason: " + formatError(e) + ".");
handleClasspathError("Could not register field " + delegate.getTypeName(clazz) + "." + fieldName + " for reflection. Reason: " + formatError(e) + ".");
}
}

Expand Down Expand Up @@ -209,9 +205,9 @@ private void parseMethod(Map<String, Object> data, T clazz) {
delegate.registerMethod(clazz, methodName, methodParameterTypes);
}
} catch (NoSuchMethodException e) {
handleError("Method " + formatMethod(clazz, methodName, methodParameterTypes) + " not found.");
handleParsingError("Method " + formatMethod(clazz, methodName, methodParameterTypes) + " not found.");
} catch (NoClassDefFoundError e) {
handleError("Could not register method " + formatMethod(clazz, methodName, methodParameterTypes) + " for reflection. Reason: " + formatError(e) + ".");
handleClasspathError("Could not register method " + formatMethod(clazz, methodName, methodParameterTypes) + " for reflection. Reason: " + formatError(e) + ".");
}
} else {
try {
Expand All @@ -225,7 +221,7 @@ private void parseMethod(Map<String, Object> data, T clazz) {
throw new JSONParserException("Method " + delegate.getTypeName(clazz) + "." + methodName + " not found");
}
} catch (NoClassDefFoundError e) {
handleError("Could not register method " + delegate.getTypeName(clazz) + "." + methodName + " for reflection. Reason: " + formatError(e) + ".");
handleClasspathError("Could not register method " + delegate.getTypeName(clazz) + "." + methodName + " for reflection. Reason: " + formatError(e) + ".");
}
}
}
Expand All @@ -252,13 +248,27 @@ private String formatMethod(T clazz, String methodName, List<T> paramTypes) {
return delegate.getTypeName(clazz) + "." + methodName + "(" + parameterTypeNames + ")";
}

private void handleError(String message) {
private void handleClasspathError(String message) {
// Checkstyle: stop
if (this.allowIncompleteClasspath) {
System.out.println("WARNING: " + message);
} else {
throw new JSONParserException(message + " To allow unresolvable reflection configuration, use option -H:+AllowIncompleteClasspath");
throw new NoClassDefFoundError(composeErrorMessage(message));
}
// Checkstyle: resume
}

private void handleParsingError(String message) {
// Checkstyle: stop
if (this.allowIncompleteClasspath) {
System.out.println("WARNING: " + message);
} else {
throw new JSONParserException(composeErrorMessage(message));
}
// Checkstyle: resume
}

private static String composeErrorMessage(String message) {
return message + " To allow unresolvable reflection configuration, use option -H:+AllowIncompleteClasspath";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import com.oracle.svm.hosted.NativeImageOptions;
import org.graalvm.nativeimage.impl.ReflectionRegistry;

import com.oracle.svm.core.configure.ConfigurationFiles;
Expand All @@ -53,7 +54,6 @@
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.json.JSONParserException;
import com.oracle.svm.hosted.ImageClassLoader;
import com.oracle.svm.hosted.NativeImageOptions;

public final class ConfigurationParserUtils {

Expand Down Expand Up @@ -130,14 +130,22 @@ public boolean tryAdvance(Consumer<? super URL> action) {
private static void doParseAndRegister(ConfigurationParser parser, Reader reader, String featureName, Object location, HostedOptionKey<String[]> option) {
try {
parser.parseAndRegister(reader);
} catch (NoClassDefFoundError e) {
String errorMessage = unwrapErrorMessage(e);
throw UserError.abort(errorMessage);
} catch (IOException | JSONParserException e) {
String errorMessage = e.getMessage();
if (errorMessage == null || errorMessage.isEmpty()) {
errorMessage = e.toString();
}
String errorMessage = unwrapErrorMessage(e);
throw UserError.abort("Error parsing " + featureName + " configuration in " + location + ":\n" + errorMessage +
"\nVerify that the configuration matches the schema described in the " +
SubstrateOptionsParser.commandArgument(PrintFlags, "+") + " output for option " + option.getName() + ".");
SubstrateOptionsParser.commandArgument(PrintFlags, "<option-category>(User, Expert, Debug)") + " output for option " + option.getName() + ".");
}
}

private static String unwrapErrorMessage(Throwable e) {
String errorMessage = e.getMessage();
if (errorMessage == null || errorMessage.isEmpty()) {
errorMessage = e.toString();
}
return errorMessage;
}
}