Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.io.FileDescriptor;

import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.type.CCharPointer;
Expand All @@ -37,17 +38,30 @@
import com.oracle.svm.core.Isolates;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.jdk.JNIPlatformNativeLibrarySupport;
import com.oracle.svm.core.jdk.Jvm;
import com.oracle.svm.core.jdk.NativeLibrarySupport;
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.windows.headers.FileAPI;
import com.oracle.svm.core.windows.headers.LibLoaderAPI;
import com.oracle.svm.core.windows.headers.WinBase.HMODULE;
import com.oracle.svm.core.windows.headers.WinSock;

@AutomaticallyRegisteredFeature
@Platforms(Platform.WINDOWS.class)
class WindowsNativeLibraryFeature implements InternalFeature {
@Override
public void duringSetup(DuringSetupAccess access) {
if (JavaVersionUtil.JAVA_SPEC >= 19) {
NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("extnet");
}
}
}

@AutomaticallyRegisteredImageSingleton(PlatformNativeLibrarySupport.class)
class WindowsNativeLibrarySupport extends JNIPlatformNativeLibrarySupport {

Expand Down Expand Up @@ -86,6 +100,10 @@ private static void loadNetLibrary() {
} else {
NativeLibrarySupport.singleton().registerInitializedBuiltinLibrary("net");
}
if (JavaVersionUtil.JAVA_SPEC >= 19) {
NativeLibrarySupport.singleton().registerInitializedBuiltinLibrary("extnet");
System.loadLibrary("extnet");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.Equivalence;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer;
import org.graalvm.nativeimage.c.type.VoidPointer;
Expand Down Expand Up @@ -85,6 +87,10 @@ public boolean fillCGlobalDataMap(Collection<String> staticLibNames) {
// TODO: This check should be removed when all static libs will have JNI_OnLoad function
ArrayList<String> localStaticLibNames = new ArrayList<>(staticLibNames);
localStaticLibNames.retainAll(libsWithOnLoad);
if (JavaVersionUtil.JAVA_SPEC >= 19 && Platform.includedIn(Platform.WINDOWS.class)) {
/* libextnet on Windows (introduced in Java 19) does not contain an OnLoad method. */
localStaticLibNames.remove("extnet");
}
boolean mapIsChanged = false;
for (String libName : localStaticLibNames) {
if (!onLoadCGlobalDataMap.containsKey(libName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,24 @@
*/
package com.oracle.svm.core.methodhandles;

import org.graalvm.nativeimage.hosted.FieldValueTransformer;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.invoke.Target_java_lang_invoke_MemberName;
import com.oracle.svm.util.ReflectionUtil;

@TargetClass(className = "java.lang.invoke.LambdaForm")
public final class Target_java_lang_invoke_LambdaForm {

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)//
Target_java_lang_invoke_MemberName vmentry;

@Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Custom, declClass = LambdaFormCacheTransformer.class)//
volatile Object transformCache;

@Alias
native String lambdaName();

Expand Down Expand Up @@ -64,6 +70,19 @@ private boolean forceInterpretation() {
native Object interpretWithArguments(Object... argumentValues) throws Throwable;
}

final class LambdaFormCacheTransformer implements FieldValueTransformer {

@Override
public Object transform(Object receiver, Object originalValue) {
Class<?> lambdaFormClass = ReflectionUtil.lookupClass(false, "java.lang.invoke.LambdaForm");
if (lambdaFormClass.isInstance(originalValue)) {
// Stores the original LambdaForm for a customized one.
return originalValue;
}
return null;
}
}

@TargetClass(className = "java.lang.invoke.LambdaForm", innerClass = "NamedFunction")
final class Target_java_lang_invoke_LambdaForm_NamedFunction {
@Alias
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ final class Target_jdk_internal_vm_Continuation__WithoutLoom {
static boolean yield(Target_jdk_internal_vm_ContinuationScope scope) {
throw VMError.shouldNotReachHere();
}

@Substitute
static void pin() {
throw VMError.shouldNotReachHere();
}

@Substitute
static void unpin() {
throw VMError.shouldNotReachHere();
}
}

@TargetClass(className = "Continuation", classNameProvider = Package_jdk_internal_vm_helper.class, onlyWith = LoomJDK.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,13 @@ private static void registerSunMSCAPIConfig(BeforeAnalysisAccess a) {
"java.security.KeyException", "java.security.KeyStoreException", "java.security.ProviderException",
"java.security.SignatureException", "java.lang.OutOfMemoryError");

a.registerReachabilityHandler(SecurityServicesFeature::registerLoadKeysOrCertificateChains,
method(a, "sun.security.mscapi.CKeyStore", "loadKeysOrCertificateChains", String.class));
if (JavaVersionUtil.JAVA_SPEC >= 19) {
a.registerReachabilityHandler(SecurityServicesFeature::registerLoadKeysOrCertificateChains,
method(a, "sun.security.mscapi.CKeyStore", "loadKeysOrCertificateChains", String.class, int.class));
} else {
a.registerReachabilityHandler(SecurityServicesFeature::registerLoadKeysOrCertificateChains,
method(a, "sun.security.mscapi.CKeyStore", "loadKeysOrCertificateChains", String.class));
}
a.registerReachabilityHandler(SecurityServicesFeature::registerGenerateCKeyPair,
method(a, "sun.security.mscapi.CKeyPairGenerator$RSA", "generateCKeyPair", String.class, int.class, String.class));
a.registerReachabilityHandler(SecurityServicesFeature::registerCPrivateKeyOf,
Expand Down Expand Up @@ -612,12 +617,23 @@ private static Map<String, Set<Service>> computeAvailableServices() {
Map<String, Set<Service>> availableServices = new HashMap<>();
for (Provider provider : Security.getProviders()) {
for (Service s : provider.getServices()) {
availableServices.computeIfAbsent(s.getType(), t -> new HashSet<>()).add(s);
if (isValid(s)) {
availableServices.computeIfAbsent(s.getType(), t -> new HashSet<>()).add(s);
}
}
}
return availableServices;
}

/**
* Check is service is valid. See {@code java.security.Provider.Service#isValid()}.
*
* Presumably, this is only needed due to an upstream bug introduced in JDK 19 [GR-40544].
*/
private static boolean isValid(Service s) {
return (s.getType() != null) && (s.getAlgorithm() != null) && (s.getClassName() != null);
}

/**
* Return a Function which given the serviceType as a String will return the corresponding
* constructor parameter Class, or null.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,66 +50,40 @@
@Platforms({InternalPlatform.PLATFORM_JNI.class})
@AutomaticallyRegisteredFeature
class JNIRegistrationJavaNet extends JNIRegistrationUtil implements InternalFeature {

private boolean hasExtendedOptionsImpl;
private boolean hasPlatformSocketOptions;

@Override
public void duringSetup(DuringSetupAccess a) {
hasExtendedOptionsImpl = a.findClassByName("sun.net.ExtendedOptionsImpl") != null;
hasPlatformSocketOptions = a.findClassByName("jdk.net.ExtendedSocketOptions$PlatformSocketOptions") != null;

/* jdk.net.ExtendedSocketOptions is only available if the jdk.net module is loaded. */
this.hasPlatformSocketOptions = a.findClassByName("jdk.net.ExtendedSocketOptions$PlatformSocketOptions") != null;
rerunClassInit(a, "java.net.DatagramPacket", "java.net.InetAddress", "java.net.NetworkInterface",
/* Stores a default SSLContext in a static field. */
"javax.net.ssl.SSLContext");
if (JavaVersionUtil.JAVA_SPEC <= 17) {
if (JavaVersionUtil.JAVA_SPEC < 19) {
/* Removed by https://bugs.openjdk.java.net/browse/JDK-8253119 */
rerunClassInit(a, "java.net.SocketInputStream", "java.net.SocketOutputStream",
/* Caches networking properties. */
"java.net.DefaultDatagramSocketImplFactory");
}
if (isWindows()) {
rerunClassInit(a, "java.net.DualStackPlainDatagramSocketImpl", "java.net.TwoStacksPlainDatagramSocketImpl");
if (JavaVersionUtil.JAVA_SPEC <= 17) {
/* Removed by https://bugs.openjdk.java.net/browse/JDK-8253119 */
if (isWindows()) {
/* Caches networking properties. */
rerunClassInit(a, "java.net.PlainSocketImpl");
}
} else {
assert isPosix();
if (JavaVersionUtil.JAVA_SPEC <= 17) {
/* Removed by https://bugs.openjdk.java.net/browse/JDK-8253119 */
rerunClassInit(a, "java.net.PlainSocketImpl", "java.net.DualStackPlainDatagramSocketImpl", "java.net.TwoStacksPlainDatagramSocketImpl");
} else {
assert isPosix();
rerunClassInit(a, "java.net.PlainDatagramSocketImpl", "java.net.PlainSocketImpl");
}
if (hasExtendedOptionsImpl) {
rerunClassInit(a, "sun.net.ExtendedOptionsImpl");
}

if (JavaVersionUtil.JAVA_SPEC <= 17) {
/* Removed by https://bugs.openjdk.java.net/browse/JDK-8253119 */
rerunClassInit(a, "java.net.AbstractPlainDatagramSocketImpl", "java.net.AbstractPlainSocketImpl");
}
}

if (hasPlatformSocketOptions) {
/*
* The libextnet was actually introduced in Java 9, but the support for Linux and
* Darwin was added later in Java 10 and Java 11 respectively.
*/
rerunClassInit(a, "jdk.net.ExtendedSocketOptions", "jdk.net.ExtendedSocketOptions$PlatformSocketOptions");
/*
* Different JDK versions are not consistent about the "ext" in the package name. We
* need to support both variants.
*/
if (a.findClassByName("sun.net.ext.ExtendedSocketOptions") != null) {
rerunClassInit(a, "sun.net.ext.ExtendedSocketOptions");
} else {
rerunClassInit(a, "sun.net.ExtendedSocketOptions");
}
}
if (isDarwin()) {
/* Caches the default interface. */
rerunClassInit(a, "java.net.DefaultInterface");
}
if (this.hasPlatformSocketOptions && (isPosix() || JavaVersionUtil.JAVA_SPEC >= 19)) {
/*
* The libextnet was actually introduced in Java 9, but the support for Linux, Darwin
* and Windows was added later in Java 10, Java 11 and Java 19 respectively.
*/
rerunClassInit(a, "jdk.net.ExtendedSocketOptions", "jdk.net.ExtendedSocketOptions$PlatformSocketOptions", "sun.net.ext.ExtendedSocketOptions");
}
if (isDarwin()) {
/* Caches the default interface. */
rerunClassInit(a, "java.net.DefaultInterface");
}
}

Expand Down Expand Up @@ -184,16 +158,10 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
method(a, "java.net.PlainSocketImpl", "localAddress", int.class, clazz(a, "java.net.InetAddressContainer")));
}
}
if (isPosix()) {
if (hasExtendedOptionsImpl) {
a.registerReachabilityHandler(JNIRegistrationJavaNet::registerExtendedOptionsImplInit,
method(a, "sun.net.ExtendedOptionsImpl", "init"));
}
if (hasPlatformSocketOptions) {
/* Support for the libextnet. */
a.registerReachabilityHandler(JNIRegistrationJavaNet::registerPlatformSocketOptionsCreate,
method(a, "jdk.net.ExtendedSocketOptions$PlatformSocketOptions", "create"));
}
if (this.hasPlatformSocketOptions && (isPosix() || JavaVersionUtil.JAVA_SPEC >= 19)) {
/* Support for the libextnet. */
a.registerReachabilityHandler(JNIRegistrationJavaNet::registerPlatformSocketOptionsCreate,
method(a, "jdk.net.ExtendedSocketOptions$PlatformSocketOptions", "create"));
}

a.registerReachabilityHandler(JNIRegistrationJavaNet::registerDefaultProxySelectorInit, method(a, "sun.net.spi.DefaultProxySelector", "init"));
Expand Down Expand Up @@ -310,22 +278,15 @@ private static void registerDualStackPlainSocketImplLocalAddress(DuringAnalysisA
RuntimeJNIAccess.register(fields(a, "java.net.InetAddressContainer", "addr"));
}

private static void registerExtendedOptionsImplInit(DuringAnalysisAccess a) {
RuntimeJNIAccess.register(clazz(a, "jdk.net.SocketFlow"));
RuntimeJNIAccess.register(fields(a, "jdk.net.SocketFlow", "status", "priority", "bandwidth"));

RuntimeJNIAccess.register(clazz(a, "jdk.net.SocketFlow$Status"));
RuntimeJNIAccess.register(fields(a, "jdk.net.SocketFlow$Status", "NO_STATUS", "OK", "NO_PERMISSION", "NOT_CONNECTED", "NOT_SUPPORTED", "ALREADY_CREATED", "IN_PROGRESS", "OTHER"));
}

private static void registerPlatformSocketOptionsCreate(DuringAnalysisAccess a) {
String implClassName;
if (isLinux()) {
implClassName = "jdk.net.LinuxSocketOptions";
} else if (isDarwin()) {
implClassName = "jdk.net.MacOSXSocketOptions";
} else {
throw VMError.shouldNotReachHere("Unexpected platform");
VMError.guarantee(isWindows(), "Unexpected platform");
implClassName = "jdk.net.WindowsSocketOptions";
}
RuntimeReflection.register(clazz(a, implClassName));
RuntimeReflection.register(constructor(a, implClassName));
Expand Down