Skip to content

Commit 3ac17f1

Browse files
author
Mihailo Markovic
committed
Changed logic for fields and methods registration.
1 parent 6ec749e commit 3ac17f1

14 files changed

+152
-121
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.graalvm.nativeimage.hosted;
2+
3+
import java.lang.reflect.Executable;
4+
import java.lang.reflect.Field;
5+
6+
public interface DynamicJNIAccess {
7+
8+
/**
9+
* Registers the provided classes for both JNI access and reflection at runtime, if the
10+
* {@code condition} is satisfied.
11+
*/
12+
void register(RegistrationCondition condition, Class<?>... classes);
13+
14+
/**
15+
* Registers the provided methods for both JNI access and reflection at runtime, if the
16+
* {@code condition} is satisfied.
17+
* {@link ReflectionDynamicAccess#register(RegistrationCondition, Executable...)} is implicitly
18+
* called, thereby this method also registers the declaring classes of those methods, including
19+
* all their members, for runtime reflection queries.
20+
*/
21+
void register(RegistrationCondition condition, Executable... methods);
22+
23+
/**
24+
* Registers the provided fields for both JNI access and reflection at runtime, if the
25+
* {@code condition} is satisfied.
26+
* {@link ReflectionDynamicAccess#register(RegistrationCondition, Field...)} is implicitly
27+
* called, thereby this method also registers the declaring classes of those fields, including
28+
* all their members, for runtime reflection queries.
29+
*/
30+
void register(RegistrationCondition condition, Field... fields);
31+
}

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/Feature.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,24 @@ interface IsInConfigurationAccess extends FeatureAccess {
171171
*/
172172
@Platforms(Platform.HOSTED_ONLY.class)
173173
interface AfterRegistrationAccess extends FeatureAccess {
174+
174175
/**
175-
* Creates access for runtime registration. All registrations should happen in
176-
* {@link Feature#afterRegistration}
177-
*
176+
* Returns the access instance used to register elements for reflection at runtime. All
177+
* registrations should happen in {@link Feature#afterRegistration}.
178178
*/
179179
ReflectionDynamicAccess getReflectionDynamicAccess();
180180

181+
/**
182+
* Returns the access instance used to register resources for runtime access. All
183+
* registrations should happen in {@link Feature#afterRegistration}.
184+
*/
181185
ResourceDynamicAccess getResourceDynamicAccess();
186+
187+
/**
188+
* Returns the access instance used to register elements for JNI access at runtime. All
189+
* registrations should happen in {@link Feature#afterRegistration}.
190+
*/
191+
DynamicJNIAccess getDynamicJNIAccess();
182192
}
183193

184194
/**

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ReflectionDynamicAccess.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,17 @@ public interface ReflectionDynamicAccess {
4242
void registerClassLookup(RegistrationCondition condition, String className);
4343

4444
/**
45-
* Registers the provided methods for reflective invocation at runtime, if the {@code condition}
46-
* is satisfied. The methods will be invocable via
45+
* Registers the provided methods for reflective invocation at runtime, along with the declaring
46+
* classes of those methods, including all their members, for reflection queries at runtime, if
47+
* the {@code condition} is satisfied. The methods will be invocable via
4748
* {@link java.lang.reflect.Method#invoke(java.lang.Object, java.lang.Object...)}.
4849
*/
4950
void register(RegistrationCondition condition, Executable... methods);
5051

5152
/**
52-
* Registers the provided fields for reflective access at runtime, if the {@code condition} is
53-
* satisfied. The fields will be accessible via
53+
* Registers the provided fields for reflective access at runtime, along with the declaring
54+
* classes of those fields, including all their members, for reflection queries at runtime, if
55+
* the {@code condition} is satisfied. The fields will be accessible via
5456
* {@link java.lang.reflect.Field#set(java.lang.Object, java.lang.Object)} and
5557
* {@link java.lang.reflect.Field#get(Object)}.
5658
*/
@@ -63,8 +65,11 @@ public interface ReflectionDynamicAccess {
6365
void registerForSerialization(RegistrationCondition condition, Class<?>... classes);
6466

6567
/**
66-
* Registers the provided classes for both JNI access and reflection at runtime, if the
67-
* {@code condition} is satisfied.
68+
* Registers interfaces that defines {@link java.lang.reflect.Proxy} classes, if the
69+
* {@code condition} is satisfied. Proxy objects that match registered definition can be created
70+
* at runtime. The proxy class is fully defined by the interfaces it implements.
71+
*
72+
* @since 22.3
6873
*/
69-
void registerForJNIAccess(RegistrationCondition condition, Class<?>... classes);
74+
void registerProxy(RegistrationCondition condition, Class<?>... interfaces);
7075
}

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ public static void addResourceBundle(Module module, String bundleName) {
112112
}
113113

114114
private static String withModuleName(Module module, String str) {
115-
Objects.requireNonNull(module);
116115
Objects.requireNonNull(str);
117-
return (module.isNamed() ? module.getName() : "ALL-UNNAMED") + ":" + str;
116+
boolean isNamed = module != null && module.isNamed();
117+
return (isNamed) ? module.getName() + ":" + str : str;
118118
}
119119

120120
private RuntimeResourceAccess() {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.oracle.svm.hosted;
2+
3+
import com.oracle.svm.core.util.UserError;
4+
5+
public final class DynamicAccessSupport {
6+
private static boolean afterRegistrationFinished = false;
7+
8+
static void setAfterRegistrationFinished() {
9+
afterRegistrationFinished = true;
10+
}
11+
12+
public static void printUserError(String registrationEntry) {
13+
UserError.guarantee(!afterRegistrationFinished, "Registration for runtime access after Feature#afterRegistration is not allowed. You tried to register %s", registrationEntry);
14+
}
15+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.oracle.svm.hosted;
2+
3+
import java.lang.reflect.Executable;
4+
import java.lang.reflect.Field;
5+
import java.util.Arrays;
6+
7+
import org.graalvm.nativeimage.ImageSingletons;
8+
import org.graalvm.nativeimage.hosted.DynamicJNIAccess;
9+
import org.graalvm.nativeimage.hosted.RegistrationCondition;
10+
import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport;
11+
12+
public class DynamicJNIAccessImpl implements DynamicJNIAccess {
13+
14+
private InternalReflectionDynamicAccess rdaInstance;
15+
private RuntimeJNIAccessSupport rjaInstance;
16+
17+
DynamicJNIAccessImpl() {
18+
rdaInstance = new InternalReflectionDynamicAccess();
19+
rjaInstance = ImageSingletons.lookup(RuntimeJNIAccessSupport.class);
20+
}
21+
22+
@Override
23+
public void register(RegistrationCondition condition, Class<?>... classes) {
24+
DynamicAccessSupport.printUserError(Arrays.toString(classes));
25+
rdaInstance.register(condition, classes);
26+
rjaInstance.register(condition, classes);
27+
}
28+
29+
@Override
30+
public void register(RegistrationCondition condition, Executable... methods) {
31+
DynamicAccessSupport.printUserError(Arrays.toString(methods));
32+
rdaInstance.register(condition, methods);
33+
rjaInstance.register(condition, false, methods);
34+
}
35+
36+
@Override
37+
public void register(RegistrationCondition condition, Field... fields) {
38+
DynamicAccessSupport.printUserError(Arrays.toString(fields));
39+
rdaInstance.register(condition, fields);
40+
rjaInstance.register(condition, false, fields);
41+
}
42+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
import org.graalvm.collections.Pair;
4949
import org.graalvm.nativeimage.AnnotationAccess;
50+
import org.graalvm.nativeimage.hosted.DynamicJNIAccess;
5051
import org.graalvm.nativeimage.hosted.Feature;
5152
import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess;
5253
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
@@ -204,6 +205,11 @@ public ReflectionDynamicAccess getReflectionDynamicAccess() {
204205
public ResourceDynamicAccess getResourceDynamicAccess() {
205206
return new ResourceDynamicAccessImpl();
206207
}
208+
209+
@Override
210+
public DynamicJNIAccess getDynamicJNIAccess() {
211+
return new DynamicJNIAccessImpl();
212+
}
207213
}
208214

209215
abstract static class AnalysisAccessBase extends FeatureAccessImpl {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalReflectionDynamicAccess.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.graalvm.nativeimage.ImageSingletons;
77
import org.graalvm.nativeimage.hosted.ReflectionDynamicAccess;
88
import org.graalvm.nativeimage.hosted.RegistrationCondition;
9-
import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport;
9+
import org.graalvm.nativeimage.impl.RuntimeProxyCreationSupport;
1010
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
1111
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;
1212

@@ -44,11 +44,22 @@ public void registerClassLookup(RegistrationCondition condition, String classNam
4444

4545
@Override
4646
public void register(RegistrationCondition condition, Executable... methods) {
47+
Class<?>[] uniqueDeclaringClasses = java.util.Arrays.stream(methods)
48+
.map(Executable::getDeclaringClass)
49+
.distinct()
50+
.toArray(Class<?>[]::new);
51+
52+
register(condition, uniqueDeclaringClasses);
4753
rrsInstance.register(condition, false, methods);
4854
}
4955

5056
@Override
5157
public void register(RegistrationCondition condition, Field... fields) {
58+
Class<?>[] uniqueDeclaringClasses = java.util.Arrays.stream(fields)
59+
.map(Field::getDeclaringClass)
60+
.distinct()
61+
.toArray(Class<?>[]::new);
62+
register(condition, uniqueDeclaringClasses);
5263
rrsInstance.register(condition, false, fields);
5364
}
5465

@@ -59,8 +70,7 @@ public void registerForSerialization(RegistrationCondition condition, Class<?>..
5970
}
6071

6172
@Override
62-
public void registerForJNIAccess(RegistrationCondition condition, Class<?>... classes) {
63-
register(condition, classes);
64-
ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(condition, classes);
73+
public void registerProxy(RegistrationCondition condition, Class<?>... interfaces) {
74+
ImageSingletons.lookup(RuntimeProxyCreationSupport.class).addProxyClass(RegistrationCondition.always(), interfaces);
6575
}
6676
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalResourceDynamicAccess.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class InternalResourceDynamicAccess implements ResourceDynamicAccess {
1616

1717
@Override
1818
public void register(RegistrationCondition condition, Module module, String pattern) {
19+
Objects.requireNonNull(pattern);
1920
if (pattern.replace("\\*", "").contains("*")) {
2021
String moduleName = module == null ? null : module.getName();
2122
rrsInstance.addGlob(condition, moduleName, pattern, "Registered from API");
@@ -26,12 +27,8 @@ public void register(RegistrationCondition condition, Module module, String patt
2627

2728
@Override
2829
public void registerResourceBundle(RegistrationCondition condition, Module module, String bundleName) {
29-
rrsInstance.addResourceBundles(condition, resolveModuleName(module, bundleName));
30-
}
31-
32-
private static String resolveModuleName(Module module, String str) {
33-
Objects.requireNonNull(str);
34-
boolean isNamed = module == null ? false : module.isNamed();
35-
return ((isNamed) ? module.getName() : "ALL-UNNAMED") + ":" + str;
30+
Objects.requireNonNull(bundleName);
31+
String finalBundleName = (module != null && module.isNamed()) ? module.getName() + ":" + bundleName : bundleName;
32+
rrsInstance.addResourceBundles(condition, finalBundleName);
3633
}
3734
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -978,8 +978,7 @@ protected void setupNativeImage(String imageName, OptionValues options, Map<Meth
978978

979979
AfterRegistrationAccessImpl access = new AfterRegistrationAccessImpl(featureHandler, loader, originalMetaAccess, mainEntryPoint, debug);
980980
featureHandler.forEachFeature(feature -> feature.afterRegistration(access));
981-
ReflectionDynamicAccessImpl.setAfterRegistrationFinished();
982-
ResourceDynamicAccessImpl.setAfterRegistrationFinished();
981+
DynamicAccessSupport.setAfterRegistrationFinished();
983982
setDefaultLibCIfMissing();
984983
if (!Pair.<Method, CEntryPointData> empty().equals(access.getMainEntryPoint())) {
985984
setAndVerifyMainEntryPoint(access, entryPoints);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReflectionDynamicAccessImpl.java

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,64 +8,52 @@
88
import org.graalvm.nativeimage.hosted.ReflectionDynamicAccess;
99
import org.graalvm.nativeimage.hosted.RegistrationCondition;
1010

11-
import com.oracle.svm.core.util.UserError;
12-
1311
/**
1412
* Instance of this class is used to register classes, methods, and fields for reflection,
1513
* serialization and JNI access at runtime. It can only be created at
1614
* {@link Feature#afterRegistration} via {@link Feature.AfterRegistrationAccess}.
1715
*/
1816
public final class ReflectionDynamicAccessImpl implements ReflectionDynamicAccess {
1917

20-
private static boolean afterRegistrationFinished;
2118
private static InternalReflectionDynamicAccess rdaInstance;
2219

2320
public ReflectionDynamicAccessImpl() {
2421
rdaInstance = new InternalReflectionDynamicAccess();
25-
afterRegistrationFinished = false;
26-
}
27-
28-
public static void setAfterRegistrationFinished() {
29-
afterRegistrationFinished = true;
3022
}
3123

3224
@Override
3325
public void register(RegistrationCondition condition, Class<?>... classes) {
34-
printUserError(Arrays.toString(classes));
26+
DynamicAccessSupport.printUserError("following classes for reflection: " + Arrays.toString(classes));
3527
rdaInstance.register(condition, classes);
3628
}
3729

3830
@Override
3931
public void registerClassLookup(RegistrationCondition condition, String className) {
40-
printUserError(className + "for lookup");
32+
DynamicAccessSupport.printUserError("Following classes for lookup: " + className);
4133
rdaInstance.registerClassLookup(condition, className);
4234
}
4335

4436
@Override
4537
public void register(RegistrationCondition condition, Executable... methods) {
46-
printUserError(Arrays.toString(methods));
38+
DynamicAccessSupport.printUserError("following methods for reflection: " + Arrays.toString(methods));
4739
rdaInstance.register(condition, methods);
4840
}
4941

5042
@Override
5143
public void register(RegistrationCondition condition, Field... fields) {
52-
printUserError(Arrays.toString(fields));
44+
DynamicAccessSupport.printUserError("following fields for reflection: " + Arrays.toString(fields));
5345
rdaInstance.register(condition, fields);
5446
}
5547

5648
@Override
5749
public void registerForSerialization(RegistrationCondition condition, Class<?>... classes) {
58-
printUserError(Arrays.toString(classes));
50+
DynamicAccessSupport.printUserError("following classes for serialization: " + Arrays.toString(classes));
5951
rdaInstance.registerForSerialization(condition, classes);
6052
}
6153

6254
@Override
63-
public void registerForJNIAccess(RegistrationCondition condition, Class<?>... classes) {
64-
printUserError(Arrays.toString(classes));
65-
rdaInstance.registerForJNIAccess(condition, classes);
66-
}
67-
68-
private void printUserError(String registrationEntry) {
69-
UserError.guarantee(!afterRegistrationFinished, "Registration for runtime access after Feature#afterRegistration is not allowed. You tried to register: %s", registrationEntry);
55+
public void registerProxy(RegistrationCondition condition, Class<?>... interfaces) {
56+
DynamicAccessSupport.printUserError("following interfaces that define a dynamic proxy class: " + Arrays.toString(interfaces));
57+
rdaInstance.registerProxy(condition, interfaces);
7058
}
7159
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourceDynamicAccessImpl.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,25 @@
11
package com.oracle.svm.hosted;
22

3-
import org.graalvm.nativeimage.hosted.Feature;
43
import org.graalvm.nativeimage.hosted.RegistrationCondition;
54
import org.graalvm.nativeimage.hosted.ResourceDynamicAccess;
65

7-
import com.oracle.svm.core.util.UserError;
8-
9-
/**
10-
* Instance of this class is used to Java resources and ResourceBundles that should be accessible at
11-
* runtime. It can only be created at {@link Feature#afterRegistration} via
12-
* {@link Feature.AfterRegistrationAccess}.
13-
*/
146
public class ResourceDynamicAccessImpl implements ResourceDynamicAccess {
157

16-
private static boolean afterRegistrationFinished;
178
private static InternalResourceDynamicAccess rdaInstance;
189

1910
ResourceDynamicAccessImpl() {
2011
rdaInstance = new InternalResourceDynamicAccess();
21-
afterRegistrationFinished = false;
22-
}
23-
24-
public static void setAfterRegistrationFinished() {
25-
afterRegistrationFinished = true;
2612
}
2713

2814
@Override
2915
public void register(RegistrationCondition condition, Module module, String pattern) {
30-
UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register glob: %s", pattern);
16+
DynamicAccessSupport.printUserError(pattern);
3117
rdaInstance.register(condition, module, pattern);
3218
}
3319

3420
@Override
3521
public void registerResourceBundle(RegistrationCondition condition, Module module, String bundleName) {
36-
UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s",
37-
bundleName);
22+
DynamicAccessSupport.printUserError(bundleName);
3823
rdaInstance.registerResourceBundle(condition, module, bundleName);
3924
}
4025

0 commit comments

Comments
 (0)