Skip to content

Commit 3e7a3c8

Browse files
committed
svm: implement core reflection based JNIRegistrationUtil with JVCMI methods
1 parent baaa45c commit 3e7a3c8

File tree

11 files changed

+189
-172
lines changed

11 files changed

+189
-172
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JNIRegistrationUtil.java

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,28 @@
2424
*/
2525
package com.oracle.svm.core.jdk;
2626

27-
import java.lang.reflect.Constructor;
28-
import java.lang.reflect.Field;
29-
import java.lang.reflect.Method;
3027
import java.util.Collections;
3128
import java.util.Optional;
3229
import java.util.Set;
3330
import java.util.function.Consumer;
3431

35-
import org.graalvm.nativeimage.ImageSingletons;
3632
import org.graalvm.nativeimage.Platform;
3733
import org.graalvm.nativeimage.hosted.Feature.AfterAnalysisAccess;
3834
import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess;
3935
import org.graalvm.nativeimage.hosted.Feature.FeatureAccess;
40-
import org.graalvm.nativeimage.hosted.RuntimeJNIAccess;
41-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
4236
import org.graalvm.nativeimage.impl.InternalPlatform;
43-
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
4437

38+
import com.oracle.svm.core.feature.InternalFeature.InternalFeatureAccess;
4539
import com.oracle.svm.core.util.ConcurrentIdentityHashMap;
4640
import com.oracle.svm.core.util.VMError;
47-
import com.oracle.svm.util.ReflectionUtil;
41+
import com.oracle.svm.util.JVMCIReflectionUtil;
42+
import com.oracle.svm.util.JVMCIRuntimeClassInitializationSupport;
43+
import com.oracle.svm.util.dynamicaccess.JVMCIRuntimeJNIAccess;
44+
import com.oracle.svm.util.dynamicaccess.JVMCIRuntimeReflection;
45+
46+
import jdk.vm.ci.meta.ResolvedJavaField;
47+
import jdk.vm.ci.meta.ResolvedJavaMethod;
48+
import jdk.vm.ci.meta.ResolvedJavaType;
4849

4950
/**
5051
* Utility methods used by features that perform JNI registration.
@@ -72,52 +73,55 @@ protected static boolean isWindows() {
7273
}
7374

7475
protected static void initializeAtRunTime(FeatureAccess access, String... classNames) {
75-
RuntimeClassInitializationSupport classInitSupport = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
76+
InternalFeatureAccess internalAccess = (InternalFeatureAccess) access;
77+
JVMCIRuntimeClassInitializationSupport classInitSupport = JVMCIRuntimeClassInitializationSupport.singleton();
7678
for (String className : classNames) {
77-
classInitSupport.initializeAtRunTime(clazz(access, className), "for JDK native code support via JNI");
79+
classInitSupport.initializeAtRunTime(type(internalAccess, className), "for JDK native code support via JNI");
7880
}
7981
}
8082

81-
protected static Class<?> clazz(FeatureAccess access, String className) {
82-
Class<?> classByName = access.findClassByName(className);
83-
VMError.guarantee(classByName != null, "class %s not found", className);
84-
return classByName;
83+
protected static ResolvedJavaType type(FeatureAccess access, String className) {
84+
ResolvedJavaType typeByName = ((InternalFeatureAccess) access).findTypeByName(className);
85+
VMError.guarantee(typeByName != null, "class %s not found", className);
86+
return typeByName;
8587
}
8688

87-
protected static Optional<Class<?>> optionalClazz(FeatureAccess access, String className) {
88-
Class<?> classByName = access.findClassByName(className);
89-
return Optional.ofNullable(classByName);
89+
protected static Optional<? extends ResolvedJavaType> optionalType(FeatureAccess access, String className) {
90+
ResolvedJavaType typeByName = ((InternalFeatureAccess) access).findTypeByName(className);
91+
return Optional.ofNullable(typeByName);
9092
}
9193

92-
protected static Optional<Method> optionalMethod(FeatureAccess access, String className, String methodName, Class<?>... parameterTypes) {
93-
return optionalClazz(access, className)
94-
.flatMap(clazz -> Optional.ofNullable(ReflectionUtil.lookupMethod(true, clazz, methodName, parameterTypes)));
94+
protected static Optional<ResolvedJavaMethod> optionalMethod(FeatureAccess access, String className, String methodName, Class<?>... parameterTypes) {
95+
InternalFeatureAccess internalAccess = (InternalFeatureAccess) access;
96+
return optionalType(access, className)
97+
.flatMap(clazz -> Optional.ofNullable(JVMCIReflectionUtil.getUniqueDeclaredMethod(true, internalAccess.getMetaAccess(), clazz, methodName, parameterTypes)));
9598
}
9699

97-
protected static Method method(FeatureAccess access, String className, String methodName, Class<?>... parameterTypes) {
98-
return ReflectionUtil.lookupMethod(clazz(access, className), methodName, parameterTypes);
100+
protected static ResolvedJavaMethod method(FeatureAccess access, String className, String methodName, Class<?>... parameterTypes) {
101+
return JVMCIReflectionUtil.getUniqueDeclaredMethod(((InternalFeatureAccess) access).getMetaAccess(), type(access, className), methodName, parameterTypes);
99102
}
100103

101-
protected static Constructor<?> constructor(FeatureAccess access, String className, Class<?>... parameterTypes) {
102-
return ReflectionUtil.lookupConstructor(clazz(access, className), parameterTypes);
104+
protected static ResolvedJavaMethod constructor(FeatureAccess access, String className, Class<?>... parameterTypes) {
105+
return JVMCIReflectionUtil.getDeclaredConstructor(((InternalFeatureAccess) access).getMetaAccess(), type(access, className), parameterTypes);
103106
}
104107

105-
protected static Field[] fields(FeatureAccess access, String className, String... fieldNames) {
106-
Class<?> clazz = clazz(access, className);
107-
Field[] result = new Field[fieldNames.length];
108+
protected static ResolvedJavaField[] fields(FeatureAccess access, String className, String... fieldNames) {
109+
ResolvedJavaType type = type(access, className);
110+
ResolvedJavaField[] result = new ResolvedJavaField[fieldNames.length];
108111
for (int i = 0; i < fieldNames.length; i++) {
109-
result[i] = ReflectionUtil.lookupField(clazz, fieldNames[i]);
112+
result[i] = JVMCIReflectionUtil.getUniqueDeclaredField(type, fieldNames[i]);
110113
}
111114
return result;
112115
}
113116

114117
protected static void registerForThrowNew(FeatureAccess access, String... exceptionClassNames) {
118+
InternalFeatureAccess internalAccess = (InternalFeatureAccess) access;
115119
for (String exceptionClassName : exceptionClassNames) {
116-
RuntimeJNIAccess.register(clazz(access, exceptionClassName));
117-
RuntimeJNIAccess.register(constructor(access, exceptionClassName, String.class));
120+
JVMCIRuntimeJNIAccess.register(type(internalAccess, exceptionClassName));
121+
JVMCIRuntimeJNIAccess.register(constructor(internalAccess, exceptionClassName, String.class));
118122

119-
RuntimeReflection.register(clazz(access, exceptionClassName));
120-
RuntimeReflection.register(constructor(access, exceptionClassName, String.class));
123+
JVMCIRuntimeReflection.register(type(internalAccess, exceptionClassName));
124+
JVMCIRuntimeReflection.register(constructor(internalAccess, exceptionClassName, String.class));
121125
}
122126
}
123127

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

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@
8484
import javax.security.auth.login.Configuration;
8585

8686
import org.graalvm.nativeimage.ImageSingletons;
87-
import org.graalvm.nativeimage.hosted.RuntimeJNIAccess;
8887
import org.graalvm.nativeimage.hosted.RuntimeReflection;
8988
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
9089

@@ -113,13 +112,17 @@
113112
import com.oracle.svm.hosted.c.NativeLibraries;
114113
import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor;
115114
import com.oracle.svm.util.JVMCIReflectionUtil;
115+
import com.oracle.svm.util.JVMCIRuntimeClassInitializationSupport;
116116
import com.oracle.svm.util.ModuleSupport;
117+
import com.oracle.svm.util.OriginalMethodProvider;
117118
import com.oracle.svm.util.ReflectionUtil;
118119
import com.oracle.svm.util.TypeResult;
120+
import com.oracle.svm.util.dynamicaccess.JVMCIRuntimeJNIAccess;
119121

120122
import jdk.graal.compiler.debug.Assertions;
121123
import jdk.graal.compiler.options.Option;
122124
import jdk.internal.access.SharedSecrets;
125+
import jdk.vm.ci.meta.ResolvedJavaMethod;
123126
import sun.security.jca.ProviderList;
124127
import sun.security.provider.NativePRNG;
125128
import sun.security.x509.OIDMap;
@@ -269,7 +272,7 @@ public void afterRegistration(AfterRegistrationAccess a) {
269272
@Override
270273
public void duringSetup(DuringSetupAccess a) {
271274
DuringSetupAccessImpl access = (DuringSetupAccessImpl) a;
272-
RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
275+
JVMCIRuntimeClassInitializationSupport rci = JVMCIRuntimeClassInitializationSupport.singleton();
273276
oidTableField = access.findField("sun.security.util.ObjectIdentifier", "oidTable");
274277
oidMapField = access.findField(OIDMap.class, "oidMap");
275278
if (!FutureDefaultsOptions.securityProvidersInitializedAtRunTime()) {
@@ -281,8 +284,8 @@ public void duringSetup(DuringSetupAccess a) {
281284
} else {
282285
SecurityProvidersSupport support = SecurityProvidersSupport.singleton();
283286
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, SecuritySubstitutions.class, false, "java.base", "sun.security.ec");
284-
Constructor<?> sunECConstructor = constructor(a, "sun.security.ec.SunEC");
285-
support.setSunECConstructor(sunECConstructor);
287+
ResolvedJavaMethod sunECConstructor = constructor(a, "sun.security.ec.SunEC");
288+
support.setSunECConstructor((Constructor<?>) OriginalMethodProvider.getJavaMethod(sunECConstructor));
286289

287290
Properties securityProperties = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties();
288291
support.setSavedInitialSecurityProperties(securityProperties);
@@ -306,44 +309,44 @@ public void duringSetup(DuringSetupAccess a) {
306309
rci.initializeAtRunTime(NativePRNG.Blocking.class, "for substitutions");
307310
rci.initializeAtRunTime(NativePRNG.NonBlocking.class, "for substitutions");
308311

309-
rci.initializeAtRunTime(clazz(access, "sun.security.provider.SeedGenerator"), "for substitutions");
310-
rci.initializeAtRunTime(clazz(access, "sun.security.provider.SecureRandom$SeederHolder"), "for substitutions");
312+
rci.initializeAtRunTime(type(access, "sun.security.provider.SeedGenerator"), "for substitutions");
313+
rci.initializeAtRunTime(type(access, "sun.security.provider.SecureRandom$SeederHolder"), "for substitutions");
311314

312315
/*
313316
* sun.security.provider.AbstractDrbg$SeederHolder has a static final EntropySource seeder
314317
* field that needs to be initialized at run time because it captures the result of
315318
* SeedGenerator.getSystemEntropy().
316319
*/
317-
rci.initializeAtRunTime(clazz(access, "sun.security.provider.AbstractDrbg$SeederHolder"), "for substitutions");
320+
rci.initializeAtRunTime(type(access, "sun.security.provider.AbstractDrbg$SeederHolder"), "for substitutions");
318321
if (isMscapiModulePresent) {
319322
/* PRNG.<clinit> creates a Cleaner (see JDK-8210476), which starts its thread. */
320-
rci.initializeAtRunTime(clazz(access, "sun.security.mscapi.PRNG"), "for substitutions");
323+
rci.initializeAtRunTime(type(access, "sun.security.mscapi.PRNG"), "for substitutions");
321324
}
322-
rci.initializeAtRunTime(clazz(access, "sun.security.provider.FileInputStreamPool"), "for substitutions");
325+
rci.initializeAtRunTime(type(access, "sun.security.provider.FileInputStreamPool"), "for substitutions");
323326
/* java.util.UUID$Holder has a static final SecureRandom field. */
324-
rci.initializeAtRunTime(clazz(access, "java.util.UUID$Holder"), "for substitutions");
327+
rci.initializeAtRunTime(type(access, "java.util.UUID$Holder"), "for substitutions");
325328

326329
/* The classes below have a static final SecureRandom field. */
327-
rci.initializeAtRunTime(clazz(access, "sun.security.jca.JCAUtil$CachedSecureRandomHolder"), "for substitutions");
328-
rci.initializeAtRunTime(clazz(access, "com.sun.crypto.provider.SunJCE$SecureRandomHolder"), "for substitutions");
329-
optionalClazz(access, "sun.security.krb5.Confounder").ifPresent(clazz -> rci.initializeAtRunTime(clazz, "for substitutions"));
330-
optionalClazz(access, "sun.security.krb5.Config").ifPresent(clazz -> rci.initializeAtRunTime(clazz, "Reset the value of lazily initialized field sun.security.krb5.Config#singleton"));
330+
rci.initializeAtRunTime(type(access, "sun.security.jca.JCAUtil$CachedSecureRandomHolder"), "for substitutions");
331+
rci.initializeAtRunTime(type(access, "com.sun.crypto.provider.SunJCE$SecureRandomHolder"), "for substitutions");
332+
optionalType(access, "sun.security.krb5.Confounder").ifPresent(clazz -> rci.initializeAtRunTime(clazz, "for substitutions"));
333+
optionalType(access, "sun.security.krb5.Config").ifPresent(clazz -> rci.initializeAtRunTime(clazz, "Reset the value of lazily initialized field sun.security.krb5.Config#singleton"));
331334

332-
rci.initializeAtRunTime(clazz(access, "sun.security.jca.JCAUtil"), "JCAUtil.def holds a SecureRandom.");
335+
rci.initializeAtRunTime(type(access, "sun.security.jca.JCAUtil"), "JCAUtil.def holds a SecureRandom.");
333336

334337
/*
335338
* When SSLContextImpl$DefaultManagersHolder sets-up the TrustManager in its initializer it
336339
* gets the value of the -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword
337340
* properties from the build machine. Running its initialization at run time is required to
338341
* use the run time provided values.
339342
*/
340-
rci.initializeAtRunTime(clazz(access, "sun.security.ssl.SSLContextImpl$DefaultManagersHolder"), "for reading properties at run time");
343+
rci.initializeAtRunTime(type(access, "sun.security.ssl.SSLContextImpl$DefaultManagersHolder"), "for reading properties at run time");
341344

342345
/*
343346
* SSL debug logging enabled by javax.net.debug system property is set up during the class
344347
* initialization.
345348
*/
346-
rci.initializeAtRunTime(clazz(access, "sun.security.ssl.SSLLogger"), "for reading properties at run time");
349+
rci.initializeAtRunTime(type(access, "sun.security.ssl.SSLLogger"), "for reading properties at run time");
347350
}
348351

349352
@Override
@@ -381,7 +384,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
381384
}
382385

383386
if (isPosix()) {
384-
Optional<Method> optMethodGetUnixInfo = optionalMethod(access, "com.sun.security.auth.module.UnixSystem", "getUnixInfo");
387+
Optional<ResolvedJavaMethod> optMethodGetUnixInfo = optionalMethod(access, "com.sun.security.auth.module.UnixSystem", "getUnixInfo");
385388
optMethodGetUnixInfo.ifPresent(m -> {
386389
access.registerReachabilityHandler(SecurityServicesFeature::linkJaas, m);
387390
/* Resolve calls to com_sun_security_auth_module_UnixSystem* as builtIn. */
@@ -390,7 +393,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
390393
}
391394

392395
if (isMscapiModulePresent) {
393-
access.registerReachabilityHandler(SecurityServicesFeature::registerSunMSCAPIConfig, clazz(access, "sun.security.mscapi.SunMSCAPI"));
396+
access.registerReachabilityHandler(SecurityServicesFeature::registerSunMSCAPIConfig, type(access, "sun.security.mscapi.SunMSCAPI"));
394397
/* Resolve calls to sun_security_mscapi* as builtIn. */
395398
PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_security_mscapi");
396399
}
@@ -544,26 +547,26 @@ private static void registerSunMSCAPIConfig(BeforeAnalysisAccess a) {
544547
}
545548

546549
private static void registerLoadKeysOrCertificateChains(DuringAnalysisAccess a) {
547-
RuntimeJNIAccess.register(constructor(a, "java.util.ArrayList"));
548-
RuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateCertificate", byte[].class, Collection.class));
549-
RuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateCertificateChain", String.class, Collection.class));
550-
RuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateKeyAndCertificateChain", boolean.class, String.class, long.class, long.class, int.class, Collection.class));
550+
JVMCIRuntimeJNIAccess.register(constructor(a, "java.util.ArrayList"));
551+
JVMCIRuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateCertificate", byte[].class, Collection.class));
552+
JVMCIRuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateCertificateChain", String.class, Collection.class));
553+
JVMCIRuntimeJNIAccess.register(method(a, "sun.security.mscapi.CKeyStore", "generateKeyAndCertificateChain", boolean.class, String.class, long.class, long.class, int.class, Collection.class));
551554
}
552555

553556
private static void registerGenerateCKeyPair(DuringAnalysisAccess a) {
554-
RuntimeJNIAccess.register(constructor(a, "sun.security.mscapi.CKeyPair", String.class, long.class, long.class, int.class));
557+
JVMCIRuntimeJNIAccess.register(constructor(a, "sun.security.mscapi.CKeyPair", String.class, long.class, long.class, int.class));
555558
}
556559

557560
private static void registerCPrivateKeyOf(DuringAnalysisAccess a) {
558-
RuntimeJNIAccess.register(method(a, "sun.security.mscapi.CPrivateKey", "of", String.class, long.class, long.class, int.class));
561+
JVMCIRuntimeJNIAccess.register(method(a, "sun.security.mscapi.CPrivateKey", "of", String.class, long.class, long.class, int.class));
559562
}
560563

561564
private static void registerCPublicKeyOf(DuringAnalysisAccess a) {
562-
RuntimeJNIAccess.register(method(a, "sun.security.mscapi.CPublicKey", "of", String.class, long.class, long.class, int.class));
565+
JVMCIRuntimeJNIAccess.register(method(a, "sun.security.mscapi.CPublicKey", "of", String.class, long.class, long.class, int.class));
563566
}
564567

565568
private static void linkJaas(DuringAnalysisAccess a) {
566-
RuntimeJNIAccess.register(fields(a, "com.sun.security.auth.module.UnixSystem", "username", "uid", "gid", "groups"));
569+
JVMCIRuntimeJNIAccess.register(fields(a, "com.sun.security.auth.module.UnixSystem", "username", "uid", "gid", "groups"));
567570

568571
NativeLibraries nativeLibraries = ((DuringAnalysisAccessImpl) a).getNativeLibraries();
569572
/* We can statically link jaas, thus we classify it as builtIn library */
@@ -657,8 +660,8 @@ private void registerServiceReachabilityHandlers(BeforeAnalysisAccess access) {
657660
* java.security.Provider.Service.newInstance() directly. On Open JDK
658661
* SecureRandom.getInstance() is used instead.
659662
*/
660-
Optional<Method> defaultSecureRandomService = optionalMethod(access, "java.security.Provider", "getDefaultSecureRandomService");
661-
defaultSecureRandomService.ifPresent(m -> access.registerMethodOverrideReachabilityHandler((a, t) -> registerServices(a, t, SECURE_RANDOM_SERVICE), m));
663+
Optional<ResolvedJavaMethod> defaultSecureRandomService = optionalMethod(access, "java.security.Provider", "getDefaultSecureRandomService");
664+
defaultSecureRandomService.ifPresent(m -> access.registerMethodOverrideReachabilityHandler((a, t) -> registerServices(a, t, SECURE_RANDOM_SERVICE), OriginalMethodProvider.getJavaMethod(m)));
662665
}
663666

664667
private void registerServices(DuringAnalysisAccess access, Object trigger, Class<?> serviceClass) {

0 commit comments

Comments
 (0)