-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Support dynamic class loading #2442
Conversation
61af582
to
397df00
Compare
397df00
to
1b2203d
Compare
40eeed9
to
c9b96ff
Compare
8c088b7
to
5371bc8
Compare
Thank you for your contribution @ziyilin ! Before I go into details, I'd like to discuss the overall design (and I'd also appreciate input from @christianwimmer). The current design, as I understand it, dumps class files for defined classes directly and immediately to a separate directory, bypassing the mechanism for writing trace events and generating configuration files. I understand the tracing approach involves some additional overhead, but it would provide better opportunities for tracking dynamically loaded classes and their metadata (like the hash code) and loading them during the image build. The current approach requires manual changes to the class path and uses a fake
|
The original design was for quick implementation to support the business requirement. I agree all things should be kept together in a single system. The option 1 seems good to me. In option 1, the json configuration file acts as an index, and the raw classes can be stored in a subdirectory independently. The configuration file is small so it's feasible for human reading and checking, the independently stored class files are also more flexible for future extension. |
Hi @ziyilin, I have made a rebase of your PR to test it out with our benchmarks. It works in all of the cases there. The link to the fixed-up version is here: https://github.com/vjovanov/graal/tree/dynamicClassLoading I am running the tests now and will keep you posted on the results. Amazing work! |
fefa1fe
to
98f8014
Compare
@vjovanov Is there any review updates? |
@ziyilin I'm looking into it. |
substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java
Outdated
Show resolved
Hide resolved
if (isDynamicallyGenerated) { | ||
if (!justAdded) { | ||
unsupportedExceptions.add("Class " + definedClassName + " has been defined before. Multiple definitions are not supported.\n" + | ||
ClassLoaderDefineClassSupport.getStackTrace(jni).toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not an issue that needs to be handled or reported in the agent, but should be reported during the image build or at image runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsupportedExceptions
and reportExceptions
are unused now.
substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java
Outdated
Show resolved
Hide resolved
substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java
Outdated
Show resolved
Hide resolved
substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java
Outdated
Show resolved
Hide resolved
...ratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_ClassLoader.java
Show resolved
Hide resolved
substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java
Outdated
Show resolved
Hide resolved
...eflect/src/com/oracle/svm/reflect/dynamicclassloading/hosted/DynamicClassLoadingFeature.java
Outdated
Show resolved
Hide resolved
if (featureName.equals("dynamicClassLoading") && location instanceof URL) { | ||
dynamicClassLoadingDirs.add((URL) location); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not clean and the static field will not work when there is more than one image build in the process (server mode). You might need to add a method to collect the locations and return them so you can use them in the feature's afterRegistration
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the dynamicClassLoadingDirs
. The original way is to fetch the dumped class file from all possible locations setting by -H:DynamicClassesConfigurationFiles=
and -H:DynamicClassesConfigurationResources=
, but the class file should be located in the dynClasses
directory under the configuration file's directory. So we only need to follow the location of the currently parsed dynamicClass configuration file to look for the dumped class files.
...eflect/src/com/oracle/svm/reflect/dynamicclassloading/hosted/DynamicClassLoadingFeature.java
Outdated
Show resolved
Hide resolved
132bac9
to
74f6442
Compare
Support dynamic class loading for native image
74f6442
to
a13778c
Compare
@peter-hofer I have dealed with all comments, please take a look. Thanks. |
@ziyilin , thanks, I will. |
@ziyilin : looks good now, thanks again for your contribution. I'll take care of it from here 🙂 |
@peter-hofer Great! Thank you for your reviewing. |
Is there any guidance on how to use this feature? Seems like the option was renamed from Error log:
|
Is it possible, that the option now is named a13778c#diff-573485114a4aca2da43e2c66f93f17a7621b9fe3601acb8ac3d2fb35c99c4456R200 I did not try it. Would be great to have some documentation :-) |
@dzou @dthommes we renamed this feature predefined classes because there really is not much dynamic about this mechanism at image runtime. You can enable tracking in the agent with option |
Overview
This patch supports
java.lang.ClassLoader.defineClass(String name, byte[] b, int off, int len)
based dynamic class loading in native image. It is separated from the previous PR (#2323).The basic idea for supporting dynamic class loading is dumping classes generated at run time in a beforehand run with native-image-agent to a specified directory which is added to the classpath for building native image.
This is implemented in 3 steps:
java.lang.ClassLoader.postDefineClass
by native-image-agent to dump the dynamically generated class to file system.Features:
-agentlib:native-image-agent=dynamic-class-dump-dir=
to specify where to dump the dynamically generated classes, the default value is "dynClass" if not specified.java.lang.ClassLoader.defineClass
is invoked. It is the user's job to make sure the dynamic generated class' name is constant through Agent runtime and native image runtime. The patch has supported the null name scenario.Limitations:
This patch does not support defineClass with specified ProtectionDomain.
It is possible the jar on classpath has a different signature file from dynamically generated class and fail the check in
java.lang.ClassLoader.checkCerts(String name, CodeSource cs)
at native-image build time. Current solution is to manually delete jar's signature file before building. This limitation can be shown by test: testWithSignedJar.zipIt is possible the dynamically generated class contents are changing from run to run. We make a class contents check at runtime based on the byte array's hash code to assure the runtime defined class is the same as the previously prepared one. But this check excludes SourceFile attribute because it often varies from runs but doesn't affect runtime behavior. This limitation can be shown by test: testChangedClass.zip
Tests:
This patch can be tested by
testDynamicLoading.zip