Skip to content

Conversation

filozof50
Copy link
Contributor

@filozof50 filozof50 commented Sep 13, 2021

In order to serialize and deserialize lambdas, methods serializeLambda (from lambda instance) and deserializeLambda (from class that captures lambda) needs to be registered for the runtime reflection. This is done in SerializationFeature class.

We have to make distinction between classes that needs to be registered for serialization and capturing classes that captures lambdas,
so in this PR new attribute for serialization-config.json file is intorduced as following:

"lambdaCapturingClass":CAPTURING_CLASS_NAME

The agent has been changed accordingly.

We also introduced new format for serialization configuration files in native image.

Example of the new format in serilaization configuration file can be found in the following file:
substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/doc-files/SerializationConfigurationFilesHelp.txt

@oubidar-Abderrahim
Copy link
Member

Thank you for contributing to GraalVM, this PR is tracked by GR-33824

declaringClass = Class.forName("java.lang.invoke.SerializedLambda");
// Checkstyle: resume
} catch (ClassNotFoundException e) {
e.printStackTrace();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use VMError.shouldNotReachHere

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as suggested.

Method serializeLambdaMethod = type.getJavaClass().getDeclaredMethod("writeReplace");
RuntimeReflection.register(serializeLambdaMethod);
} catch (NoSuchMethodException e) {
VMError.shouldNotReachHere("You have to register class from which you want lambdas to be serialized.");
Copy link
Member

@vjovanov vjovanov Sep 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use throw VMError.shouldNotReachHere in front so IDEs don't get confused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as suggested.

try {
RuntimeReflection.register(serializationTargetClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class));
} catch (NoSuchMethodException e) {
VMError.shouldNotReachHere("Method named $deserializeLambda$ must exist in capturing class (" + serializationTargetClass.getName() + ") of lambdas that have writeReplace method.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the capturing class ... the writeReplace method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as suggested.

@vjovanov
Copy link
Member

There is a segfault in one of the benchmarks when running with the agent:

mx --env ni-ce --kill-with-sigquit benchmark renaissance-native-image:page-rank -- --jvm=native-image --jvm-config=default-ce -Dnative-image.benchmark.extra-run-arg=-Xmx8g -- -r 1```

@@ -878,6 +878,76 @@ private static JNIObjectHandle shouldIncludeMethod(JNIEnvironment jni, JNIObject
return result;
}

private static boolean registerCapturingClass(JNIEnvironment jni, Breakpoint bp, InterceptedState state) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is hard for me to follow this code. I think a concise comment about what happens here would be nice. Alternatively, split the method in several calls that have a descriptive name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment added as suggested.

* recursively. Call ObjectStreamClass.getClassDataLayout0() can get all of them.
*/

JNIMethodId getClassDataLayout0MId = agent.handles().getJavaIoObjectStreamClassGetClassDataLayout0(jni, bp.clazz);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a good candidate as there is almost the same segment in: com.oracle.svm.agent.BreakpointInterceptor#objectStreamClassConstructor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New method created and called in all the places needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method has been removed in the last commit. When we get to SerializedLambda#readResolve method, method on ObjectStreamClass has already been called for proper capturing class. So, we do not need to search recursively again in that case and this method is sufficient now. We only need this check here, not in other places in code.

@@ -85,7 +86,8 @@ public void registerWithTargetConstructorClass(ConfigurationCondition condition,
}

@Override
public void registerWithTargetConstructorClass(ConfigurationCondition condition, String className, String customTargetConstructorClassName) {
public void registerWithTargetConstructorClass(ConfigurationCondition condition, String rawClassName, String customTargetConstructorClassName) {
String className = rawClassName.contains("$$Lambda$") ? rawClassName.split(LambdaUtils.SPLIT_BY_LAMBDA)[0] + "$$Lambda$" : rawClassName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"$$Lambda$" is a good candidate for LambdaUtils

Copy link
Contributor Author

@filozof50 filozof50 Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to LambdaUtils as suggested.

@@ -55,7 +56,14 @@ public SerializationConfigurationType(ConfigurationCondition condition, String q
public void printJson(JsonWriter writer) throws IOException {
writer.append('{').indent().newline();
ConfigurationConditionPrintable.printConditionAttribute(condition, writer);
writer.quote(SerializationConfigurationParser.NAME_KEY).append(':').quote(qualifiedJavaName);

if (qualifiedJavaName.contains("$$Lambda$") && !qualifiedJavaName.contains("/")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think abusing qualifiedJavaName is not necessary here. It can also lead to duplicates during writing. We need to put the new value properly in the model and then change the equality function to compare that as well.

Also, we need assertions that both can't be populated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New attribute isLambdaCapturingClass added to distinct lambda capturing classes from classes that should be registered for serialization.
Assertion added as suggested.

@@ -58,9 +59,10 @@ public void parseAndRegister(Reader reader) throws IOException {
}

private void parseSerializationDescriptorObject(Map<String, Object> data) {
checkAttributes(data, "serialization descriptor object", Collections.singleton(NAME_KEY), Arrays.asList(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY, CONDITIONAL_KEY));
checkMultipleOptionsAttributes(data, "serialization descriptor object", Collections.unmodifiableCollection(Arrays.asList(NAME_KEY, LAMBDA_CAPTURING_CLASS_KEY)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple is not accurate. They are exclusive options so maybe checkExclusiveOptionsAttributes.

This is also not overly general as it supports only a single option.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to Arrays.asList(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY, CONDITIONAL_KEY)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple is not accurate. They are exclusive options so maybe checkExclusiveOptionsAttributes.

This is also not overly general as it supports only a single option.

Changed as suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to Arrays.asList(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY, CONDITIONAL_KEY)?

It's been removed by mistake.

if (declaringClass.getName().contains("$$Lambda$")) {
try {
// Checkstyle: stop
declaringClass = Class.forName("java.lang.invoke.SerializedLambda");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we fetch this once in a final field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added final field serializedLambdaClass and used in proper places.

@graalvmbot
Copy link
Collaborator

Hello filozof50, thanks for contributing a PR to our project!

We use the Oracle Contributor Agreement to make the copyright of contributions clear. We don't have a record of you having signed this yet, based on your email address strahinja_stanojevic -(at)- matf -(dot)- bg -(dot)- ac -(dot)- rs. You can sign it at that link.

If you think you've already signed it, please comment below and we'll check.

@filozof50 filozof50 force-pushed the lambda-serialization-branch branch 4 times, most recently from b307da0 to c2ce091 Compare September 26, 2021 19:06
@filozof50
Copy link
Contributor Author

There is a segfault in one of the benchmarks when running with the agent:

mx --env ni-ce --kill-with-sigquit benchmark renaissance-native-image:page-rank -- --jvm=native-image --jvm-config=default-ce -Dnative-image.benchmark.extra-run-arg=-Xmx8g -- -r 1```

It's been fixed now.

@@ -51,6 +51,8 @@
public final class LambdaUtils {
private static final Pattern LAMBDA_PATTERN = Pattern.compile("\\$\\$Lambda\\$\\d+[/\\.][^/]+;");
private static final char[] HEX = "0123456789abcdef".toCharArray();
public static final String SPLIT_BY_LAMBDA = "\\$\\$Lambda\\$";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be expressed as Pattern.quote(LAMBDA_FUNCTIONS_NAME_PATTERN).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAMBDA_SPLIT_PATTERN would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be expressed as Pattern.quote(LAMBDA_FUNCTIONS_NAME_PATTERN).

It cannot. LambdaUtils class is needed in runtime, so this should stay String in order to finish build process successfully.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAMBDA_SPLIT_PATTERN would be better.

Changed as suggested.

@@ -51,6 +51,8 @@
public final class LambdaUtils {
private static final Pattern LAMBDA_PATTERN = Pattern.compile("\\$\\$Lambda\\$\\d+[/\\.][^/]+;");
private static final char[] HEX = "0123456789abcdef".toCharArray();
public static final String SPLIT_BY_LAMBDA = "\\$\\$Lambda\\$";
public static final String LAMBDA_FUNCTIONS_NAME_PATTERN = "$$Lambda$";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAMBDA_CLASS_NAME_PATTERN is maybe more accurate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use the LAMBDA_PATTERN above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LAMBDA_CLASS_NAME_PATTERN is maybe more accurate.

Changed as suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we use the LAMBDA_PATTERN above?

I expects ; at the end (not optional) which is not case in cases which are important for this PR. So, we need 2 new constants in LambdaUtils class.

@@ -51,6 +51,8 @@
public final class LambdaUtils {
private static final Pattern LAMBDA_PATTERN = Pattern.compile("\\$\\$Lambda\\$\\d+[/\\.][^/]+;");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use this one for all we need?

Copy link
Contributor Author

@filozof50 filozof50 Sep 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the explanation is in the comment above.

checkRemainingAttributes(map, type, requiredAttrs, optionalAttrs, unseenRequired);
}

protected void warnOrFail(String message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to move these functions, it will just mess up the history.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order of the functions is not changed now (comparing to master branch).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not true, you moved warnOrFail and checkAttributes before checkRemainingAttributes. Please move it back.

@@ -1000,8 +1029,10 @@ private static boolean objectStreamClassConstructor(JNIEnvironment jni, Breakpoi
* additional ObjectStreamClass instances (usually the super classes) are created
* recursively. Call ObjectStreamClass.getClassDataLayout0() can get all of them.
*/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

public void registerWithTargetConstructorClass(ConfigurationCondition condition, String className, String customTargetConstructorClassName) {
serializations.add(createConfigurationType(condition, className, customTargetConstructorClassName));
public void registerWithTargetConstructorClass(ConfigurationCondition condition, String rawClassName, String customTargetConstructorClassName) {
String className = rawClassName.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN) ? rawClassName.split(LambdaUtils.SPLIT_BY_LAMBDA)[0] + LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a need for appending $$Lambda$ here as you already have the boolean. I would keep the class name as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, fixed as suggested.

return serializations.contains(createConfigurationType(condition, serializationTargetClass, customTargetConstructorClass));
public boolean contains(ConfigurationCondition condition, String rawSerializationTargetClass, String customTargetConstructorClass) {
String serializationTargetClass = rawSerializationTargetClass.contains(LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN)
? rawSerializationTargetClass.split(LambdaUtils.SPLIT_BY_LAMBDA)[0] + LambdaUtils.LAMBDA_FUNCTIONS_NAME_PATTERN
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as suggested.

@filozof50 filozof50 force-pushed the lambda-serialization-branch branch from c2ce091 to baf5656 Compare September 30, 2021 12:17
Comment on lines 80 to 84
if (types.equals("types")) {
printSerializationTypes(writer);
} else {
printLambdaCapturingSerializationTypes(writer);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cleaner to pass in a Consumer<JsonWriter> to call, or since printSerializationTypes and printLambdaCapturingSerializationTypes is essentially the same, you could pass them as a JsonPrintable array or collection.
But I think you should actually be able to use JsonPrinter.printCollection here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used JsonPrintable list to make an abstraction here.

}

@Override
public int compareTo(SerializationConfigurationLambdaCapturingType other) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should instead use an actual Comparator class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used as suggested.

@@ -89,10 +90,13 @@ public int compareTo(SerializationConfigurationType other) {
if (compareName != 0) {
return compareName;
}
int compareCondition = condition.compareTo(other.condition);

int compareCondition = condition.compareTo(condition);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like it...

}
}

private void parseSerializationDescriptorObject(Map<String, Object> data, boolean lambdaCapturingType) {
checkAttributes(data, "serialization descriptor object", Collections.singleton(NAME_KEY), Arrays.asList(CUSTOM_TARGET_CONSTRUCTOR_CLASS_KEY, CONDITIONAL_KEY));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not accept a target constructor for lambda-capturing types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as suggested.

Comment on lines 82 to 92
private void parseSerializationTypes(List<Object> listOfSerializationTypes) {
for (Object serializationType : listOfSerializationTypes) {
parseSerializationDescriptorObject(asMap(serializationType, "third level of document must be serialization descriptor objects"), false);
}
}

private void parseLambdaCapturingTypes(List<Object> listOfLambdaCapturingTypes) {
for (Object lambdaCapturingType : listOfLambdaCapturingTypes) {
parseSerializationDescriptorObject(asMap(lambdaCapturingType, "third level of document must be serialization descriptor objects"), true);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simply pass a boolean instead of having two methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used an additional argument as suggested.

Comment on lines 39 to 43
private static final ByteArrayOutputStream byteArrayOutputStream;

static {
byteArrayOutputStream = new ByteArrayOutputStream();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt this is necessary and you should be able to create the stream in the test method and pass it to the serialize and deserialize methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stream passed as an argument.

Comment on lines 41 to 45
private static final ByteArrayOutputStream byteArrayOutputStream;

static {
byteArrayOutputStream = new ByteArrayOutputStream();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt this is necessary and you should be able to create the stream in the test method and pass it to the respective methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stream passed as an argument.

Comment on lines 65 to 66
Function<Integer, String> fn = (Function<Integer, String>) objectInputStream.readObject();
return fn;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why cast when you return Object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cast removed as suggested.


@AutomaticFeature
public class SerializationFeature implements Feature {
static final HashSet<Class<?>> capturingClasses = new HashSet<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be static.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be, because it is being referenced from inner class SerializationBuilder.

}
return true;
}

private static boolean isSerializable(JNIEnvironment env, JNIObjectHandle serializeTargetClass) {
JNIObjectHandle javaIoSerializable = agent.handles().findClass(env, "java/io/Serializable");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's still not a lazy lookup.

* which is of type {@code DirectHotSpotObjectConstantImpl}. That class is protected and it is
* not visible in the {@link SerializationFeature}. The only way to access fields and methods of
* this class is through the reflection. There are 2 different ways of getting lambda from the
* {@code ConstantNode#value}:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to go through SnippetReflectionProvider.asObject. You get the provider via GraalAccess.getOriginalProviders that you already call elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SnippetReflectionProvider.asObject used as suggested.

Comment on lines 170 to 185
* 1. For capturing classes from the JDK {@code ConstantNode#value} of type
* {@code DirectHotSpotObjectConstantImpl} has {@code DirectHotSpotObjectConstantImpl#object} of
* type {@code DirectMethodHandle$Constructor} on Java 17 and in previous versions. Lambda class
* can be extracted from {@code DirectMethodHandle$Constructor#initMethod} using the
* {@code MemberName#getDeclaringClass()} or from {@code DirectMethodHandle#member} using the
* {@code MemberName#getDeclaringClass()}. Since all of those classes are protected and are not
* in the same package as the {@link SerializationFeature}, the only way to get the lambda class
* is using the reflection.
*
* 2. For capturing classes that are user-defined classes, {@code ConstantNode#value} of type
* {@code DirectHotSpotObjectConstantImpl} has {@code DirectHotSpotObjectConstantImpl#object} of
* type {@code DirectMethodHandle$StaticAccessor} type. In that case, lambda class is stored in
* the {@code DirectMethodHandle$StaticAccessor#staticBase}. Since
* {@code DirectMethodHandle$StaticAccessor} is also protected class and cannot be imported in
* the {@link SerializationFeature}, it is not possible to get values from this field in any
* ways other than the reflection.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem plausible that this is the only way. Instead, it should be possible to get the declaring class of a constructor method handle by calling type().returnType() on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type.returnType() does not return what we expected it would. But I used some other reflection providers to get all the relevant information and to get lambdas from registered capturing classes.


public SerializationConfigurationLambdaCapturingType(ConfigurationCondition condition, String qualifiedJavaName) {
assert qualifiedJavaName.indexOf('/') == -1 : "Requires qualified Java name, not internal representation";
assert !qualifiedJavaName.startsWith("[") : "Requires Java source array syntax, for example java.lang.String[]";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The text doesn't make sense to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can an array be a capturing type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, it doesn't make sense. It's been removed.

private final String qualifiedJavaName;

public SerializationConfigurationLambdaCapturingType(ConfigurationCondition condition, String qualifiedJavaName) {
assert qualifiedJavaName.indexOf('/') == -1 : "Requires qualified Java name, not internal representation";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The articles are missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as suggested.

@filozof50 filozof50 changed the title WIP: Support for lambda functions serialization added Support for lambda class serialization Jan 31, 2022
}
]
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing EOL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as suggested.

-H:+AllowVMInspection \
--features=com.oracle.svm.test.AbstractServiceLoaderTest$TestFeature,com.oracle.svm.test.NoProviderConstructorServiceLoaderTest$TestFeature \
--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.containers=ALL-UNNAMED
Args=--initialize-at-run-time=com.oracle.svm.test --initialize-at-build-time=com.oracle.svm.test.AbstractClassSerializationTest,com.oracle.svm.test.SerializationRegistrationTest,com.oracle.svm.test.LambdaClassSerializationTest,com.oracle.svm.test.LambdaClassDeserializationTest --features=com.oracle.svm.test.SerializationRegistrationTestFeature -H:+AllowVMInspection --features=com.oracle.svm.test.AbstractServiceLoaderTest$TestFeature,com.oracle.svm.test.NoProviderConstructorServiceLoaderTest$TestFeature --features=com.oracle.svm.test.SerializationRegistrationTestFeature -H:+AllowVMInspection --features=com.oracle.svm.test.AbstractServiceLoaderTest$TestFeature,com.oracle.svm.test.NoProviderConstructorServiceLoaderTest$TestFeature --add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.containers=ALL-UNNAMED
Copy link
Member

@vjovanov vjovanov Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like an unrelated change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually added 2 classes for build time initialization.

private static StructuredGraph createMethodGraph(ResolvedJavaMethod method, DebugContext debug) {
StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug).method(method).build();
try (DebugContext.Scope ignored = debug.scope("ParsingToMaterializeLambdas")) {
GraphBuilderPhase lambdaParserPhase = new GraphBuilderPhase(buildLambdaParserConfig());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also put the GraphBuilderPhase in the abstraction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved as suggested.

@zakkak
Copy link
Collaborator

zakkak commented Jun 3, 2022

It looks like this PR has been integrated as b455f23.

Could someone please verify and close the PR if that's true?

@vjovanov vjovanov closed this Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants