You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: substratevm/LIMITATIONS.md
+1-1
Original file line number
Diff line number
Diff line change
@@ -39,7 +39,7 @@ Reflection
39
39
40
40
What: Calling `Class.forName()`; listing methods and fields of a class; invoking methods and accessing fields reflectively; most classes in the package `java.lang.reflect`.
41
41
42
-
Individual classes, methods, and fields that should be accessible via reflection must be specified during native image generation in a configuration file via the option `-H:ReflectionConfigurationFiles=`, or by using [`RuntimeReflection`](http://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/RuntimeReflection.html) from a [`Feature`](http://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/Feature.html). Elements (classes, methods, and fields) that are not included in a configuration cannot be accessed reflectively. For more details, read our [documentation on reflection](REFLECTION.md).
42
+
Individual classes, methods, and fields that should be accessible via reflection need to be known ahead-of-time. SubstrateVM tries to resolve these elements through a static analysis that detects calls to the reflection API. Where the analysis fails the program elements reflectively accessed at run time must be specified during native image generation in a configuration file via the option `-H:ReflectionConfigurationFiles=`, or by using [`RuntimeReflection`](http://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/RuntimeReflection.html) from a [`Feature`](http://www.graalvm.org/sdk/javadoc/org/graalvm/nativeimage/Feature.html). For more details, read our [documentation on reflection](REFLECTION.md).
43
43
44
44
During native image generation, reflection can be used without restrictions during native image generation, for example in static initializers.
Copy file name to clipboardexpand all lines: substratevm/REFLECTION.md
+49-10
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,54 @@
1
1
# Reflection on Substrate VM
2
2
3
-
Java reflection support (`java.lang.reflect`) enables Java code to examine its own classes, methods and fields and their properties at runtime. One useful application of this feature is the serialization of arbitrary data structures. Substrate VM has partial support for reflection and requires a configuration with those program elements that should be examinable at image runtime.
3
+
Java reflection support (the `java.lang.reflect.*` API) enables Java code to examine its own classes, methods and fields and their properties at runtime.
4
4
5
-
## Configuration
5
+
Substrate VM has partial support for reflection and it needs to know ahead of time the reflectively accessed program elements. Examining and accessing program elements through `java.lang.reflect.*` or loading classes with `Class.forName(String)` at run time requires preparing additional metadata for those program elements. (Note: We include here loading classes with `Class.forName(String)` since it is closely related to reflection.)
6
6
7
-
Examining and accessing program elements through `java.lang.reflect` at runtime requires preparing additional metadata for those program elements. A configuration that specifies those program elements must be provided during the image build as follows:
7
+
SubstrateVM tries to resolve the target elements through a static analysis that detects calls to the reflection API. Where the analysis fails the program elements reflectively accessed at run time must be specified using a manual configuration.
8
+
9
+
## Automatic detection
10
+
11
+
The analysis intercepts calls to `Class.forName(String)`, `Class.forName(String, ClassLoader)`, `Class.getDeclaredField(String)`, `Class.getField(String)`, `Class.getDeclaredMethod(String, Class[])`, `Class.getMethod(String, Class[])`, `Class.getDeclaredConstructor(Class[])` and `Class.getConstructor(Class[])`. If the arguments to these calls can be reduced to a constant we try to resolve the target elements. If the target elements can be resolved the calls are removed and instead the target elements are embedded in the code. If the target elements cannot be resolved, e.g., a class is not on the classpath or it doesn't declare a field/method/constructor, then the calls are replaced with a snippet that throws the appropriate exception at run time. The benefits are two fold. First, at run time there are no calls to the reflection API. Second, Graal can employ constant folding and optimize the code further.
12
+
13
+
The calls are intercepted and processed only when it can be unequivocally determined that the parameters can be reduced to a constant. For example the call `Class.forName(String)` will be replaced with a `Class` literal only if the `String` argument can be constant folded, assuming that the class is actually on the classpath. Additionally a call to `Class.getMethod(String, Class[])` will be processed only if the contents of the `Class[]` argument can be determined with certainty. The last restriction is due to the fact that Java doesn't have immutable arrays. Therefore all the changes to the array between the time it is allocated and the time it is passed as an argument need to be tracked. The analysis follows a simple rule: if all the writes to the array happen in linear sections of code, i.e., no control flow splits, then the array is effectively constant for the purpose of analyzing the call. That is why the analysis doesn't accept `Class[]` arguments coming from static fields since the contents of those can change at any time, even if the fields are final. Although this may seem too restrictive it covers the most commonly used patterns of reflection API calls. The only exception to the constant arguments rule is that the `ClassLoader` argument of `Class.forName(String, ClassLoader)` doesn't need to be a constant; it is ignored and instead a class loader that can load all the classes on the class path is used. The analysis runs to a fix point which means that a chain of calls like `Class.forName(String).getMethod(String, Class[])` will first replace the class constant and then the method effectively reducing this to a `java.lang.reflect.Method`.
14
+
15
+
Following are examples of calls that can be intercepted and replaced with the corresponding element:
@@ -13,8 +57,8 @@ where `reflectconfig` is a JSON file in the following format (use `--expert-opti
13
57
[
14
58
{
15
59
"name" : "java.lang.Class",
16
-
"allDeclaredConstructors" : true,
17
-
"allPublicConstructors" : true
60
+
"allDeclaredConstructors" : true,
61
+
"allPublicConstructors" : true
18
62
"allDeclaredMethods" : true,
19
63
"allPublicMethods" : true
20
64
},
@@ -60,10 +104,5 @@ Alternatively, a custom `Feature` implementation can register program elements b
60
104
}
61
105
62
106
63
-
## Limitations at Runtime
64
-
Dynamic class loading using `Class.forName()` is not available due to the ahead-of-time image generation model of Substrate VM.
65
-
66
-
See also our [list of general limitations](#LIMITATIONS.md).
67
-
68
107
## Use during Native Image Generation
69
108
Reflection can be used without restrictions during native image generation, for example in static initializers. At this point, code can collect information about methods and fields and store them in own data structures, which are then reflection-free at run time.
0 commit comments