提交 0c5454bf 编写于 作者: A alanb

8005716: Enhance JNI specification to allow support of static JNI libraries in Embedded JREs

Reviewed-by: dlong, alanb, mduigou
Contributed-by: bill.pittore@oracle.com, bob.vandette@oracle.com
上级 714d218d
...@@ -133,6 +133,7 @@ SUNWprivate_1.1 { ...@@ -133,6 +133,7 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_find; Java_java_lang_ClassLoader_00024NativeLibrary_find;
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
......
...@@ -133,6 +133,7 @@ SUNWprivate_1.1 { ...@@ -133,6 +133,7 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_find; Java_java_lang_ClassLoader_00024NativeLibrary_find;
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1683,22 +1683,29 @@ public abstract class ClassLoader { ...@@ -1683,22 +1683,29 @@ public abstract class ClassLoader {
private int jniVersion; private int jniVersion;
// the class from which the library is loaded, also indicates // the class from which the library is loaded, also indicates
// the loader this native library belongs. // the loader this native library belongs.
private Class<?> fromClass; private final Class<?> fromClass;
// the canonicalized name of the native library. // the canonicalized name of the native library.
// or static library name
String name; String name;
// Indicates if the native library is linked into the VM
boolean isBuiltin;
// Indicates if the native library is loaded
boolean loaded;
native void load(String name, boolean isBuiltin);
native void load(String name);
native long find(String name); native long find(String name);
native void unload(); native void unload(String name, boolean isBuiltin);
static native String findBuiltinLib(String name);
public NativeLibrary(Class<?> fromClass, String name) { public NativeLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
this.name = name; this.name = name;
this.fromClass = fromClass; this.fromClass = fromClass;
this.isBuiltin = isBuiltin;
} }
protected void finalize() { protected void finalize() {
synchronized (loadedLibraryNames) { synchronized (loadedLibraryNames) {
if (fromClass.getClassLoader() != null && handle != 0) { if (fromClass.getClassLoader() != null && loaded) {
/* remove the native library name */ /* remove the native library name */
int size = loadedLibraryNames.size(); int size = loadedLibraryNames.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
...@@ -1710,7 +1717,7 @@ public abstract class ClassLoader { ...@@ -1710,7 +1717,7 @@ public abstract class ClassLoader {
/* unload the library. */ /* unload the library. */
ClassLoader.nativeLibraryContext.push(this); ClassLoader.nativeLibraryContext.push(this);
try { try {
unload(); unload(name, isBuiltin);
} finally { } finally {
ClassLoader.nativeLibraryContext.pop(); ClassLoader.nativeLibraryContext.pop();
} }
...@@ -1830,20 +1837,24 @@ public abstract class ClassLoader { ...@@ -1830,20 +1837,24 @@ public abstract class ClassLoader {
} }
private static boolean loadLibrary0(Class<?> fromClass, final File file) { private static boolean loadLibrary0(Class<?> fromClass, final File file) {
boolean exists = AccessController.doPrivileged( // Check to see if we're attempting to access a static library
new PrivilegedAction<Object>() { String name = NativeLibrary.findBuiltinLib(file.getName());
public Object run() { boolean isBuiltin = (name != null);
return file.exists() ? Boolean.TRUE : null; if (!isBuiltin) {
}}) boolean exists = AccessController.doPrivileged(
!= null; new PrivilegedAction<Object>() {
if (!exists) { public Object run() {
return false; return file.exists() ? Boolean.TRUE : null;
} }})
String name; != null;
try { if (!exists) {
name = file.getCanonicalPath(); return false;
} catch (IOException e) { }
return false; try {
name = file.getCanonicalPath();
} catch (IOException e) {
return false;
}
} }
ClassLoader loader = ClassLoader loader =
(fromClass == null) ? null : fromClass.getClassLoader(); (fromClass == null) ? null : fromClass.getClassLoader();
...@@ -1891,14 +1902,14 @@ public abstract class ClassLoader { ...@@ -1891,14 +1902,14 @@ public abstract class ClassLoader {
} }
} }
} }
NativeLibrary lib = new NativeLibrary(fromClass, name); NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
nativeLibraryContext.push(lib); nativeLibraryContext.push(lib);
try { try {
lib.load(name); lib.load(name, isBuiltin);
} finally { } finally {
nativeLibraryContext.pop(); nativeLibraryContext.pop();
} }
if (lib.handle != 0) { if (lib.loaded) {
loadedLibraryNames.addElement(name); loadedLibraryNames.addElement(name);
libs.addElement(lib); libs.addElement(lib);
return true; return true;
......
/* /*
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -749,10 +749,21 @@ public class Runtime { ...@@ -749,10 +749,21 @@ public class Runtime {
public native void traceMethodCalls(boolean on); public native void traceMethodCalls(boolean on);
/** /**
* Loads the specified filename as a dynamic library. The filename * Loads the native library specified by the filename argument. The filename
* argument must be a complete path name, * argument must be an absolute path name.
* (for example * (for example
* <code>Runtime.getRuntime().load("/home/avh/lib/libX11.so");</code>). * <code>Runtime.getRuntime().load("/home/avh/lib/libX11.so");</code>).
*
* If the filename argument, when stripped of any platform-specific library
* prefix, path, and file extension, indicates a library whose name is,
* for example, L, and a native library called L is statically linked
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the file
* system. See the JNI Specification for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
* <p> * <p>
* First, if there is a security manager, its <code>checkLink</code> * First, if there is a security manager, its <code>checkLink</code>
* method is called with the <code>filename</code> as its argument. * method is called with the <code>filename</code> as its argument.
...@@ -769,7 +780,10 @@ public class Runtime { ...@@ -769,7 +780,10 @@ public class Runtime {
* @exception SecurityException if a security manager exists and its * @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow * <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library * loading of the specified dynamic library
* @exception UnsatisfiedLinkError if the file does not exist. * @exception UnsatisfiedLinkError if either the filename is not an
* absolute path name, the native library is not statically
* linked with the VM, or the library cannot be mapped to
* a native library image by the host system.
* @exception NullPointerException if <code>filename</code> is * @exception NullPointerException if <code>filename</code> is
* <code>null</code> * <code>null</code>
* @see java.lang.Runtime#getRuntime() * @see java.lang.Runtime#getRuntime()
...@@ -793,12 +807,16 @@ public class Runtime { ...@@ -793,12 +807,16 @@ public class Runtime {
} }
/** /**
* Loads the dynamic library with the specified library name. * Loads the native library specified by the <code>libname</code>
* A file containing native code is loaded from the local file system * argument. The <code>libname</code> argument must not contain any platform
* from a place where library files are conventionally obtained. The * specific prefix, file extension or path. If a native library
* details of this process are implementation-dependent. The * called <code>libname</code> is statically linked with the VM, then the
* mapping from a library name to a specific filename is done in a * JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
* system-specific manner. * See the JNI Specification for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
* dependent manner.
* <p> * <p>
* First, if there is a security manager, its <code>checkLink</code> * First, if there is a security manager, its <code>checkLink</code>
* method is called with the <code>libname</code> as its argument. * method is called with the <code>libname</code> as its argument.
...@@ -823,7 +841,10 @@ public class Runtime { ...@@ -823,7 +841,10 @@ public class Runtime {
* @exception SecurityException if a security manager exists and its * @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow * <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library * loading of the specified dynamic library
* @exception UnsatisfiedLinkError if the library does not exist. * @exception UnsatisfiedLinkError if either the libname argument
* contains a file path, the native library is not statically
* linked with the VM, or the library cannot be mapped to a
* native library image by the host system.
* @exception NullPointerException if <code>libname</code> is * @exception NullPointerException if <code>libname</code> is
* <code>null</code> * <code>null</code>
* @see java.lang.SecurityException * @see java.lang.SecurityException
......
...@@ -1037,9 +1037,21 @@ public final class System { ...@@ -1037,9 +1037,21 @@ public final class System {
} }
/** /**
* Loads a code file with the specified filename from the local file * Loads the native library specified by the filename argument. The filename
* system as a dynamic library. The filename * argument must be an absolute path name.
* argument must be a complete path name. *
* If the filename argument, when stripped of any platform-specific library
* prefix, path, and file extension, indicates a library whose name is,
* for example, L, and a native library called L is statically linked
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the
* file system.
* See the JNI Specification for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
*
* <p> * <p>
* The call <code>System.load(name)</code> is effectively equivalent * The call <code>System.load(name)</code> is effectively equivalent
* to the call: * to the call:
...@@ -1051,7 +1063,10 @@ public final class System { ...@@ -1051,7 +1063,10 @@ public final class System {
* @exception SecurityException if a security manager exists and its * @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow * <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library * loading of the specified dynamic library
* @exception UnsatisfiedLinkError if the file does not exist. * @exception UnsatisfiedLinkError if either the filename is not an
* absolute path name, the native library is not statically
* linked with the VM, or the library cannot be mapped to
* a native library image by the host system.
* @exception NullPointerException if <code>filename</code> is * @exception NullPointerException if <code>filename</code> is
* <code>null</code> * <code>null</code>
* @see java.lang.Runtime#load(java.lang.String) * @see java.lang.Runtime#load(java.lang.String)
...@@ -1062,9 +1077,16 @@ public final class System { ...@@ -1062,9 +1077,16 @@ public final class System {
} }
/** /**
* Loads the system library specified by the <code>libname</code> * Loads the native library specified by the <code>libname</code>
* argument. The manner in which a library name is mapped to the * argument. The <code>libname</code> argument must not contain any platform
* actual system library is system dependent. * specific prefix, file extension or path. If a native library
* called <code>libname</code> is statically linked with the VM, then the
* JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
* See the JNI Specification for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
* dependent manner.
* <p> * <p>
* The call <code>System.loadLibrary(name)</code> is effectively * The call <code>System.loadLibrary(name)</code> is effectively
* equivalent to the call * equivalent to the call
...@@ -1076,7 +1098,10 @@ public final class System { ...@@ -1076,7 +1098,10 @@ public final class System {
* @exception SecurityException if a security manager exists and its * @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow * <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library * loading of the specified dynamic library
* @exception UnsatisfiedLinkError if the library does not exist. * @exception UnsatisfiedLinkError if either the libname argument
* contains a file path, the native library is not statically
* linked with the VM, or the library cannot be mapped to a
* native library image by the host system.
* @exception NullPointerException if <code>libname</code> is * @exception NullPointerException if <code>libname</code> is
* <code>null</code> * <code>null</code>
* @see java.lang.Runtime#loadLibrary(java.lang.String) * @see java.lang.Runtime#loadLibrary(java.lang.String)
......
/* /*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1951,6 +1951,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved); ...@@ -1951,6 +1951,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved);
#define JNI_VERSION_1_2 0x00010002 #define JNI_VERSION_1_2 0x00010002
#define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_4 0x00010004
#define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_6 0x00010006
#define JNI_VERSION_1_8 0x00010008
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
......
/* /*
* Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -339,6 +339,10 @@ int getFastEncoding(); ...@@ -339,6 +339,10 @@ int getFastEncoding();
void initializeEncoding(); void initializeEncoding();
void* getProcessHandle();
void buildJniFunctionName(const char *sym, const char *cname,
char *jniEntryName);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
......
/* /*
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "jvm.h" #include "jvm.h"
#include "java_lang_ClassLoader.h" #include "java_lang_ClassLoader.h"
#include "java_lang_ClassLoader_NativeLibrary.h" #include "java_lang_ClassLoader_NativeLibrary.h"
#include <string.h>
/* defined in libverify.so/verify.dll (src file common/check_format.c) */ /* defined in libverify.so/verify.dll (src file common/check_format.c) */
extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed); extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
...@@ -286,6 +287,8 @@ Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader, ...@@ -286,6 +287,8 @@ Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,
static jfieldID handleID; static jfieldID handleID;
static jfieldID jniVersionID; static jfieldID jniVersionID;
static jfieldID loadedID;
static void *procHandle;
static jboolean initIDs(JNIEnv *env) static jboolean initIDs(JNIEnv *env)
{ {
...@@ -300,6 +303,10 @@ static jboolean initIDs(JNIEnv *env) ...@@ -300,6 +303,10 @@ static jboolean initIDs(JNIEnv *env)
jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I");
if (jniVersionID == 0) if (jniVersionID == 0)
return JNI_FALSE; return JNI_FALSE;
loadedID = (*env)->GetFieldID(env, this, "loaded", "Z");
if (loadedID == 0)
return JNI_FALSE;
procHandle = getProcessHandle();
} }
return JNI_TRUE; return JNI_TRUE;
} }
...@@ -307,14 +314,60 @@ static jboolean initIDs(JNIEnv *env) ...@@ -307,14 +314,60 @@ static jboolean initIDs(JNIEnv *env)
typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *);
typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *);
/*
* Support for finding JNI_On(Un)Load_<lib_name> if it exists.
* If cname == NULL then just find normal JNI_On(Un)Load entry point
*/
static void *findJniFunction(JNIEnv *env, void *handle,
const char *cname, jboolean isLoad) {
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
const char **syms;
int symsLen;
void *entryName = NULL;
char *jniFunctionName;
int i;
int len;
// Check for JNI_On(Un)Load<_libname> function
if (isLoad) {
syms = onLoadSymbols;
symsLen = sizeof(onLoadSymbols) / sizeof(char *);
} else {
syms = onUnloadSymbols;
symsLen = sizeof(onUnloadSymbols) / sizeof(char *);
}
for (i = 0; i < symsLen; i++) {
// cname + sym + '_' + '\0'
if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) >
FILENAME_MAX) {
goto done;
}
jniFunctionName = malloc(len);
if (jniFunctionName == NULL) {
JNU_ThrowOutOfMemoryError(env, NULL);
goto done;
}
buildJniFunctionName(syms[i], cname, jniFunctionName);
entryName = JVM_FindLibraryEntry(handle, jniFunctionName);
free(jniFunctionName);
if(entryName) {
break;
}
}
done:
return entryName;
}
/* /*
* Class: java_lang_ClassLoader_NativeLibrary * Class: java_lang_ClassLoader_NativeLibrary
* Method: load * Method: load
* Signature: (Ljava/lang/String;)J * Signature: (Ljava/lang/String;Z)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_load Java_java_lang_ClassLoader_00024NativeLibrary_load
(JNIEnv *env, jobject this, jstring name) (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
{ {
const char *cname; const char *cname;
jint jniVersion; jint jniVersion;
...@@ -327,18 +380,12 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load ...@@ -327,18 +380,12 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load
cname = JNU_GetStringPlatformChars(env, name, 0); cname = JNU_GetStringPlatformChars(env, name, 0);
if (cname == 0) if (cname == 0)
return; return;
handle = JVM_LoadLibrary(cname); handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);
if (handle) { if (handle) {
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
JNI_OnLoad_t JNI_OnLoad; JNI_OnLoad_t JNI_OnLoad;
unsigned int i; JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,
for (i = 0; i < sizeof(onLoadSymbols) / sizeof(char *); i++) { isBuiltin ? cname : NULL,
JNI_OnLoad = (JNI_OnLoad_t) JNI_TRUE);
JVM_FindLibraryEntry(handle, onLoadSymbols[i]);
if (JNI_OnLoad) {
break;
}
}
if (JNI_OnLoad) { if (JNI_OnLoad) {
JavaVM *jvm; JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm); (*env)->GetJavaVM(env, &jvm);
...@@ -355,7 +402,8 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load ...@@ -355,7 +402,8 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load
goto done; goto done;
} }
if (!JVM_IsSupportedJNIVersion(jniVersion)) { if (!JVM_IsSupportedJNIVersion(jniVersion) ||
(isBuiltin && jniVersion < JNI_VERSION_1_8)) {
char msg[256]; char msg[256];
jio_snprintf(msg, sizeof(msg), jio_snprintf(msg, sizeof(msg),
"unsupported JNI version 0x%08X required by %s", "unsupported JNI version 0x%08X required by %s",
...@@ -375,6 +423,7 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load ...@@ -375,6 +423,7 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load
goto done; goto done;
} }
(*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle)); (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));
(*env)->SetBooleanField(env, this, loadedID, JNI_TRUE);
done: done:
JNU_ReleaseStringPlatformChars(env, name, cname); JNU_ReleaseStringPlatformChars(env, name, cname);
...@@ -383,41 +432,40 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load ...@@ -383,41 +432,40 @@ Java_java_lang_ClassLoader_00024NativeLibrary_load
/* /*
* Class: java_lang_ClassLoader_NativeLibrary * Class: java_lang_ClassLoader_NativeLibrary
* Method: unload * Method: unload
* Signature: ()V * Signature: (Z)V
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_unload Java_java_lang_ClassLoader_00024NativeLibrary_unload
(JNIEnv *env, jobject this) (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
{ {
const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
void *handle; void *handle;
JNI_OnUnload_t JNI_OnUnload; JNI_OnUnload_t JNI_OnUnload;
unsigned int i; const char *cname;
if (!initIDs(env)) if (!initIDs(env))
return; return;
cname = JNU_GetStringPlatformChars(env, name, 0);
handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID)); if (cname == NULL) {
for (i = 0; i < sizeof(onUnloadSymbols) / sizeof(char *); i++) { return;
JNI_OnUnload = (JNI_OnUnload_t )
JVM_FindLibraryEntry(handle, onUnloadSymbols[i]);
if (JNI_OnUnload) {
break;
}
} }
handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID));
JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle,
isBuiltin ? cname : NULL,
JNI_FALSE);
if (JNI_OnUnload) { if (JNI_OnUnload) {
JavaVM *jvm; JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm); (*env)->GetJavaVM(env, &jvm);
(*JNI_OnUnload)(jvm, NULL); (*JNI_OnUnload)(jvm, NULL);
} }
JVM_UnloadLibrary(handle); JVM_UnloadLibrary(handle);
JNU_ReleaseStringPlatformChars(env, name, cname);
} }
/* /*
* Class: java_lang_ClassLoader_NativeLibrary * Class: java_lang_ClassLoader_NativeLibrary
* Method: find * Method: find
* Signature: (Ljava/lang/String;J)J * Signature: (Ljava/lang/String;)J
*/ */
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_find Java_java_lang_ClassLoader_00024NativeLibrary_find
...@@ -456,3 +504,63 @@ Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index) ...@@ -456,3 +504,63 @@ Java_java_lang_ClassLoader_getCaller(JNIEnv *env, jclass cls, jint index)
return NULL; return NULL;
} }
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: findBuiltinLib
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib
(JNIEnv *env, jclass cls, jstring name)
{
const char *cname;
char *libName;
int prefixLen = (int) strlen(JNI_LIB_PREFIX);
int suffixLen = (int) strlen(JNI_LIB_SUFFIX);
int len;
jstring lib;
void *ret;
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
if (name == NULL) {
JNU_ThrowInternalError(env, "NULL filename for native library");
return NULL;
}
// Can't call initIDs because it will recurse into NativeLibrary via
// FindClass to check context so set prochandle here as well.
procHandle = getProcessHandle();
cname = JNU_GetStringPlatformChars(env, name, 0);
if (cname == NULL) {
JNU_ThrowOutOfMemoryError(env, NULL);
return NULL;
}
// Copy name Skipping PREFIX
len = strlen(cname);
if (len <= (prefixLen+suffixLen)) {
JNU_ReleaseStringPlatformChars(env, name, cname);
return NULL;
}
libName = malloc(len + 1); //+1 for null if prefix+suffix == 0
if (libName == NULL) {
JNU_ReleaseStringPlatformChars(env, name, cname);
JNU_ThrowOutOfMemoryError(env, NULL);
return NULL;
}
if (len > prefixLen) {
strcpy(libName, cname+prefixLen);
}
JNU_ReleaseStringPlatformChars(env, name, cname);
// Strip SUFFIX
libName[strlen(libName)-suffixLen] = '\0';
// Check for JNI_OnLoad_libname function
ret = findJniFunction(env, procHandle, libName, JNI_TRUE);
if (ret != NULL) {
lib = JNU_NewStringPlatform(env, libName);
free(libName);
return lib;
}
free(libName);
return NULL;
}
/* /*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "jni.h" #include "jni.h"
#include "jni_util.h" #include "jni_util.h"
#include "dlfcn.h"
jstring nativeNewStringPlatform(JNIEnv *env, const char *str) { jstring nativeNewStringPlatform(JNIEnv *env, const char *str) {
return NULL; return NULL;
...@@ -33,3 +34,22 @@ jstring nativeNewStringPlatform(JNIEnv *env, const char *str) { ...@@ -33,3 +34,22 @@ jstring nativeNewStringPlatform(JNIEnv *env, const char *str) {
char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) { char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) {
return NULL; return NULL;
} }
void* getProcessHandle() {
static void *procHandle = NULL;
if (procHandle != NULL) {
return procHandle;
}
procHandle = (void*)dlopen(NULL, RTLD_LAZY);
return procHandle;
}
void buildJniFunctionName(const char *sym, const char *cname,
char *jniEntryName) {
strcpy(jniEntryName, sym);
if (cname != NULL) {
strcat(jniEntryName, "_");
strcat(jniEntryName, cname);
}
}
/* /*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -137,3 +137,35 @@ char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) ...@@ -137,3 +137,35 @@ char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
else else
return NULL; return NULL;
} }
void* getProcessHandle() {
return (void*)GetModuleHandle(NULL);
}
/*
* Windows symbols can be simple like JNI_OnLoad or __stdcall format
* like _JNI_OnLoad@8. We need to handle both.
*/
void buildJniFunctionName(const char *sym, const char *cname,
char *jniEntryName) {
if (cname != NULL) {
char *p = strrchr(sym, '@');
if (p != NULL && p != sym) {
// sym == _JNI_OnLoad@8
strncpy(jniEntryName, sym, (p - sym));
jniEntryName[(p-sym)] = '\0';
// jniEntryName == _JNI_OnLoad
strcat(jniEntryName, "_");
strcat(jniEntryName, cname);
strcat(jniEntryName, p);
//jniEntryName == _JNI_OnLoad_cname@8
} else {
strcpy(jniEntryName, sym);
strcat(jniEntryName, "_");
strcat(jniEntryName, cname);
}
} else {
strcpy(jniEntryName, sym);
}
return;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册