Skip to content
Permalink
Browse files
8265222: revisit foreign library loading
Reviewed-by: mcimadamore
  • Loading branch information
sundararajana committed May 6, 2021
1 parent db8a85d commit e8043ed7982e8609bcf0e5104cc37b5148caa40d
Showing with 280 additions and 635 deletions.
  1. +1 −1 src/java.base/share/classes/java/lang/ClassLoader.java
  2. +5 −0 src/java.base/share/classes/java/lang/System.java
  3. +2 −0 src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java
  4. +0 −15 src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java
  5. +0 −23 src/java.base/share/native/libjava/NativeLibraries.c
  6. +0 −2 src/java.base/share/native/libjava/jni_util.h
  7. +0 −4 src/java.base/unix/native/libjava/jni_util_md.c
  8. +0 −26 src/java.base/windows/native/libjava/jni_util_md.c
  9. +31 −3 src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java
  10. +0 −168 src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/LibraryLookup.java
  11. +6 −5 src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java
  12. +0 −152 src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/LibrariesHelper.java
  13. +12 −4 src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java
  14. +5 −5 test/jdk/java/foreign/SafeFunctionAccessTest.java
  15. +12 −11 test/jdk/java/foreign/StdLibTest.java
  16. +5 −4 test/jdk/java/foreign/TestDowncall.java
  17. +7 −6 test/jdk/java/foreign/TestIntrinsics.java
  18. +9 −144 test/jdk/java/foreign/TestLibraryLookup.java
  19. +0 −2 test/jdk/java/foreign/TestNulls.java
  20. +5 −4 test/jdk/java/foreign/TestUpcall.java
  21. +2 −3 test/jdk/java/foreign/TestUpcallHighArity.java
  22. +2 −3 test/jdk/java/foreign/TestUpcallStructScope.java
  23. +4 −3 test/jdk/java/foreign/TestVarArgs.java
  24. +67 −0 test/jdk/java/foreign/libStdLibTest.c
  25. +44 −0 test/jdk/java/foreign/libStdLibTest.h
  26. +2 −3 test/jdk/java/foreign/stackwalk/TestStackWalk.java
  27. +4 −2 test/jdk/java/foreign/valist/VaListTest.java
  28. +4 −5 test/jdk/java/foreign/virtual/TestVirtualCalls.java
  29. +1 −1 test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadConstant.java
  30. +11 −12 test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadHelper.java
  31. +1 −1 test/micro/org/openjdk/bench/jdk/incubator/foreign/CallOverheadVirtual.java
  32. +5 −7 test/micro/org/openjdk/bench/jdk/incubator/foreign/StrLenTest.java
  33. +7 −8 test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java
  34. +5 −4 test/micro/org/openjdk/bench/jdk/incubator/foreign/VaList.java
  35. +18 −0 test/micro/org/openjdk/bench/jdk/incubator/foreign/libStrLen.c
  36. +3 −4 test/micro/org/openjdk/bench/jdk/incubator/foreign/points/support/PanamaPoint.java
@@ -2426,7 +2426,7 @@ static NativeLibrary loadLibrary(Class<?> fromClass, String name) {
/*
* Invoked in the VM class linking code.
*/
private static long findNative(ClassLoader loader, String entryName) {
static long findNative(ClassLoader loader, String entryName) {
if (loader == null) {
return BootLoader.getNativeLibraries().find(entryName);
} else {
@@ -2344,6 +2344,11 @@ public Module addEnableNativeAccess(Module m) {
public boolean isEnableNativeAccess(Module m) {
return m.isEnableNativeAccess();
}

@Override
public long findNative(ClassLoader loader, String entry) {
return ClassLoader.findNative(loader, entry);
}
});
}
}
@@ -382,4 +382,6 @@
Module addEnableNativeAccess(Module m);

boolean isEnableNativeAccess(Module m);

long findNative(ClassLoader loader, String entry);
}
@@ -384,20 +384,6 @@ boolean open() {
}
}

public static final NativeLibrary defaultLibrary = new NativeLibraryImpl(Object.class, "<default>", true, true) {

@Override
boolean open() {
throw new UnsupportedOperationException("Cannot load default library");
}

@Override
public long find(String name) {
return NativeLibraries.findEntryInProcess(name);
}

};

/*
* The run() method will be invoked when this class loader becomes
* phantom reachable to unload the native library.
@@ -478,5 +464,4 @@ public void run() {
private static native void unload(String name, boolean isBuiltin, boolean isJNI, long handle);
private static native String findBuiltinLib(String name);
private static native long findEntry0(NativeLibraryImpl lib, String name);
private static native long findEntryInProcess(String name);
}
@@ -246,29 +246,6 @@ Java_jdk_internal_loader_NativeLibraries_findEntry0
return res;
}

/*
* Class: jdk_internal_loader_NativeLibraries
* Method: findEntryInProcess
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL
Java_jdk_internal_loader_NativeLibraries_findEntryInProcess
(JNIEnv *env, jclass cls, jstring name)
{
const char *cname;
jlong res;

if (!initIDs(env))
return jlong_zero;

cname = (*env)->GetStringUTFChars(env, name, 0);
if (cname == 0)
return jlong_zero;
res = ptr_to_jlong(findEntryInProcess(cname));
(*env)->ReleaseStringUTFChars(env, name, cname);
return res;
}

/*
* Class: jdk_internal_loader_NativeLibraries
* Method: findBuiltinLib
@@ -333,8 +333,6 @@ JNIEXPORT void InitializeEncoding(JNIEnv *env, const char *name);

void* getProcessHandle();

void* findEntryInProcess(const char* name);

void buildJniFunctionName(const char *sym, const char *cname,
char *jniEntryName);

@@ -51,10 +51,6 @@ void* getProcessHandle() {
return procHandle;
}

void* findEntryInProcess(const char* name) {
return JVM_FindLibraryEntry(RTLD_DEFAULT, name);
}

void buildJniFunctionName(const char *sym, const char *cname,
char *jniEntryName) {
strcpy(jniEntryName, sym);
@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <psapi.h>
#include <locale.h>

#include "jni.h"
@@ -36,31 +35,6 @@ void* getProcessHandle() {
return (void*)GetModuleHandle(NULL);
}

/*
* Windows doesn't have an RTLD_DEFAULT equivalent, so in stead we have to
* iterate over all the modules loaded by the process to implement the
* default library behaviour.
*/
void* findEntryInProcess(const char* name) {
HANDLE hProcess = GetCurrentProcess();

HMODULE hMods[1024];
DWORD cbNeeded; // array size in bytes

// first come, first served
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
HMODULE mod = hMods[i];
FARPROC proc = GetProcAddress(mod, name);
if(proc != NULL) {
return proc;
}
}
}

return NULL;
}

/*
* Windows symbols can be simple like JNI_OnLoad or __stdcall format
* like _JNI_OnLoad@8. We need to handle both.
@@ -25,6 +25,8 @@
*/
package jdk.incubator.foreign;

import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.NativeMemorySegmentImpl;
import jdk.internal.foreign.PlatformLayouts;
import jdk.internal.foreign.abi.SharedUtils;
@@ -36,6 +38,7 @@
import java.lang.invoke.MethodType;
import java.nio.charset.Charset;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;

import static jdk.internal.foreign.PlatformLayouts.*;
@@ -126,6 +129,31 @@ static CLinker getInstance() {
return SharedUtils.getSystemLinker();
}


/**
* Finds the address of a symbol with given name in one of the native libraries associated with the caller's
* classloader (that is, libraries loaded using {@link System#loadLibrary} or {@link System#load}).
*
* <p>
* This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
* Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
*
* @param name the name of the symbol to be searched.
* @return the address of a symbol with given name in one of the native libraries associated with the caller's
* classloader (if any).
*/
@CallerSensitive
public static Optional<MemoryAddress> findNative(String name) {
Reflection.ensureNativeAccess(Reflection.getCallerClass());
ClassLoader loader = Reflection.getCallerClass().getClassLoader();
Objects.requireNonNull(name);
JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess();
MemoryAddress addr = MemoryAddress.ofLong(javaLangAccess.findNative(loader, name));
return addr == MemoryAddress.NULL? Optional.empty() : Optional.of(addr);
}

/**
* Obtains a foreign method handle, with the given type and featuring the given function descriptor,
* which can be used to call a target foreign function at the given address.
@@ -139,7 +167,7 @@ static CLinker getInstance() {
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
*
* @see LibraryLookup#lookup(String)
* @see CLinker#findNative(String)
*
* @param symbol downcall symbol.
* @param type the method type.
@@ -161,7 +189,7 @@ static CLinker getInstance() {
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
*
* @see LibraryLookup#lookup(String)
* @see CLinker#findNative(String)
*
* @param symbol downcall symbol.
* @param allocator the segment allocator.
@@ -187,7 +215,7 @@ static CLinker getInstance() {
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
**
* @see LibraryLookup#lookup(String)
* @see CLinker#findNative(String)
*
* @param type the method type.
* @param function the function descriptor.

This file was deleted.

0 comments on commit e8043ed

Please sign in to comment.