--- old/make/java/java/mapfile-vers 2013-03-05 17:15:16.140953825 -0500 +++ new/make/java/java/mapfile-vers 2013-03-05 17:15:14.892883207 -0500 @@ -133,6 +133,7 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find; Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_unload; + Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_registerNatives; Java_java_lang_Compiler_registerNatives; --- old/makefiles/mapfiles/libjava/mapfile-vers 2013-03-05 17:15:19.969170430 -0500 +++ new/makefiles/mapfiles/libjava/mapfile-vers 2013-03-05 17:15:18.745101171 -0500 @@ -133,6 +133,7 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find; Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_unload; + Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_getCaller; Java_java_lang_ClassLoader_registerNatives; Java_java_lang_Compiler_registerNatives; --- old/src/share/classes/java/lang/ClassLoader.java 2013-03-05 17:15:23.841389524 -0500 +++ new/src/share/classes/java/lang/ClassLoader.java 2013-03-05 17:15:22.597319134 -0500 @@ -1742,20 +1742,27 @@ // the loader this native library belongs. private Class fromClass; // the canonicalized name of the native library. + // or static library 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 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.fromClass = fromClass; + this.isBuiltin = isBuiltin; } protected void finalize() { synchronized (loadedLibraryNames) { - if (fromClass.getClassLoader() != null && handle != 0) { + if (fromClass.getClassLoader() != null && loaded) { /* remove the native library name */ int size = loadedLibraryNames.size(); for (int i = 0; i < size; i++) { @@ -1767,7 +1774,7 @@ /* unload the library. */ ClassLoader.nativeLibraryContext.push(this); try { - unload(); + unload(name, isBuiltin); } finally { ClassLoader.nativeLibraryContext.pop(); } @@ -1887,20 +1894,26 @@ } private static boolean loadLibrary0(Class fromClass, final File file) { - boolean exists = AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return file.exists() ? Boolean.TRUE : null; - }}) - != null; - if (!exists) { - return false; - } - String name; - try { - name = file.getCanonicalPath(); - } catch (IOException e) { - return false; + // Check to see if we're attempting to access a static library + // System.out.println("loadLibrary0: filename: " + file.getName()); + String name = NativeLibrary.findBuiltinLib(file.getName()); + // System.out.println("loadLibrary0: name: " + name); + boolean isBuiltin = (name != null); + if (!isBuiltin) { + boolean exists = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return file.exists() ? Boolean.TRUE : null; + }}) + != null; + if (!exists) { + return false; + } + try { + name = file.getCanonicalPath(); + } catch (IOException e) { + return false; + } } ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader(); @@ -1948,14 +1961,14 @@ } } } - NativeLibrary lib = new NativeLibrary(fromClass, name); + NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin); nativeLibraryContext.push(lib); try { - lib.load(name); + lib.load(name, isBuiltin); } finally { nativeLibraryContext.pop(); } - if (lib.handle != 0) { + if (lib.loaded) { loadedLibraryNames.addElement(name); libs.addElement(lib); return true; --- old/src/share/classes/java/lang/Runtime.java 2013-03-05 17:15:27.741610203 -0500 +++ new/src/share/classes/java/lang/Runtime.java 2013-03-05 17:15:26.509540491 -0500 @@ -749,10 +749,21 @@ public native void traceMethodCalls(boolean on); /** - * Loads the specified filename as a dynamic library. The filename - * argument must be a complete path name, + * Loads the native library specified by the filename argument. The filename + * argument must be an absolute path name. * (for example * Runtime.getRuntime().load("/home/avh/lib/libX11.so");). + * + * If the filename argument, when stripped of any platform-specific library + * prefix, path, and file extension, indicates a library whose name is 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. *

* First, if there is a security manager, its checkLink * method is called with the filename as its argument. @@ -769,7 +780,10 @@ * @exception SecurityException if a security manager exists and its * checkLink method doesn't allow * 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 filename is * null * @see java.lang.Runtime#getRuntime() @@ -793,12 +807,16 @@ } /** - * Loads the dynamic library with the specified library name. - * A file containing native code is loaded from the local file system - * from a place where library files are conventionally obtained. The - * details of this process are implementation-dependent. The - * mapping from a library name to a specific filename is done in a - * system-specific manner. + * Loads the native library specified by the libname + * argument. The libname argument must not contain any platform + * specific prefix, file extension or path. If a native library + * called libname is statically linked with the VM, then the + * JNI_OnLoad_libname 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. *

* First, if there is a security manager, its checkLink * method is called with the libname as its argument. @@ -823,7 +841,10 @@ * @exception SecurityException if a security manager exists and its * checkLink method doesn't allow * 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 libname is * null * @see java.lang.SecurityException --- old/src/share/classes/java/lang/System.java 2013-03-05 17:15:32.085856005 -0500 +++ new/src/share/classes/java/lang/System.java 2013-03-05 17:15:30.873787425 -0500 @@ -1037,9 +1037,20 @@ } /** - * Loads a code file with the specified filename from the local file - * system as a dynamic library. The filename - * argument must be a complete path name. + * Loads the native library specified by the filename argument. The filename + * argument must be an absolute path name. + * + * If the filename argument, when stripped of any platform-specific library + * prefix, path, and file extension, indicates a library whose name is 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. + * *

* The call System.load(name) is effectively equivalent * to the call: @@ -1051,7 +1062,10 @@ * @exception SecurityException if a security manager exists and its * checkLink method doesn't allow * 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 filename is * null * @see java.lang.Runtime#load(java.lang.String) @@ -1062,9 +1076,16 @@ } /** - * Loads the system library specified by the libname - * argument. The manner in which a library name is mapped to the - * actual system library is system dependent. + * Loads the native library specified by the libname + * argument. The libname argument must not contain any platform + * specific prefix, file extension or path. If a native library + * called libname is statically linked with the VM, then the + * JNI_OnLoad_libname 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. *

* The call System.loadLibrary(name) is effectively * equivalent to the call @@ -1076,7 +1097,10 @@ * @exception SecurityException if a security manager exists and its * checkLink method doesn't allow * 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 libname is * null * @see java.lang.Runtime#loadLibrary(java.lang.String) --- old/src/share/javavm/export/jni.h 2013-03-05 17:15:35.990076909 -0500 +++ new/src/share/javavm/export/jni.h 2013-03-05 17:15:34.774008103 -0500 @@ -1951,6 +1951,7 @@ #define JNI_VERSION_1_2 0x00010002 #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 +#define JNI_VERSION_1_8 0x00010008 #ifdef __cplusplus } /* extern "C" */ --- old/src/share/native/common/jni_util.h 2013-03-05 17:15:39.834294417 -0500 +++ new/src/share/native/common/jni_util.h 2013-03-05 17:15:38.598224480 -0500 @@ -339,6 +339,7 @@ void initializeEncoding(); +void* getProcessHandle(); #ifdef __cplusplus } /* extern "C" */ --- old/src/share/native/java/lang/ClassLoader.c 2013-03-05 17:15:43.634509436 -0500 +++ new/src/share/native/java/lang/ClassLoader.c 2013-03-05 17:15:42.410440178 -0500 @@ -32,6 +32,7 @@ #include "jvm.h" #include "java_lang_ClassLoader.h" #include "java_lang_ClassLoader_NativeLibrary.h" +#include /* defined in libverify.so/verify.dll (src file common/check_format.c) */ extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed); @@ -286,6 +287,8 @@ static jfieldID handleID; static jfieldID jniVersionID; +static jfieldID loadedID; +static void *procHandle; static jboolean initIDs(JNIEnv *env) { @@ -300,6 +303,10 @@ jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); if (jniVersionID == 0) return JNI_FALSE; + loadedID = (*env)->GetFieldID(env, this, "loaded", "Z"); + if (loadedID == 0) + return JNI_FALSE; + procHandle = getProcessHandle(); } return JNI_TRUE; } @@ -308,13 +315,63 @@ typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); /* + * Support for builtin library. JNI_On(Un)Load_ if it exists. + * If cname == NULL then just find normal JNI_On(Un)Load entry point + */ +static void *findBuiltinJniFunction(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 *jniEntryName; + 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; + } + jniEntryName = malloc(len); + if (jniEntryName == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + goto done; + } + strcpy(jniEntryName, syms[i]); + if (cname != NULL) { + strcat(jniEntryName, "_"); + strcat(jniEntryName, cname); + } + entryName = JVM_FindLibraryEntry(handle, jniEntryName); + free(jniEntryName); + if(entryName) { + break; + } + } + + done: + return entryName; +} + +/* * Class: java_lang_ClassLoader_NativeLibrary * Method: load - * Signature: (Ljava/lang/String;)J + * Signature: (Ljava/lang/String;Z)V */ JNIEXPORT void JNICALL Java_java_lang_ClassLoader_00024NativeLibrary_load - (JNIEnv *env, jobject this, jstring name) + (JNIEnv *env, jobject this, jstring name, jboolean isBuiltin) { const char *cname; jint jniVersion; @@ -327,18 +384,13 @@ cname = JNU_GetStringPlatformChars(env, name, 0); if (cname == 0) return; - handle = JVM_LoadLibrary(cname); + handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname); if (handle) { const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS; JNI_OnLoad_t JNI_OnLoad; - unsigned int i; - for (i = 0; i < sizeof(onLoadSymbols) / sizeof(char *); i++) { - JNI_OnLoad = (JNI_OnLoad_t) - JVM_FindLibraryEntry(handle, onLoadSymbols[i]); - if (JNI_OnLoad) { - break; - } - } + JNI_OnLoad = (JNI_OnLoad_t)findBuiltinJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_TRUE); if (JNI_OnLoad) { JavaVM *jvm; (*env)->GetJavaVM(env, &jvm); @@ -355,7 +407,8 @@ goto done; } - if (!JVM_IsSupportedJNIVersion(jniVersion)) { + if (!JVM_IsSupportedJNIVersion(jniVersion) || + (isBuiltin && jniVersion < JNI_VERSION_1_8)) { char msg[256]; jio_snprintf(msg, sizeof(msg), "unsupported JNI version 0x%08X required by %s", @@ -375,6 +428,7 @@ goto done; } (*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle)); + (*env)->SetBooleanField(env, this, loadedID, JNI_TRUE); done: JNU_ReleaseStringPlatformChars(env, name, cname); @@ -383,41 +437,40 @@ /* * Class: java_lang_ClassLoader_NativeLibrary * Method: unload - * Signature: ()V + * Signature: (Z)V */ JNIEXPORT void JNICALL Java_java_lang_ClassLoader_00024NativeLibrary_unload - (JNIEnv *env, jobject this) +(JNIEnv *env, jobject this, jstring name, jboolean isBuiltin) { const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; void *handle; JNI_OnUnload_t JNI_OnUnload; - unsigned int i; + const char *cname; if (!initIDs(env)) return; - - handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID)); - for (i = 0; i < sizeof(onUnloadSymbols) / sizeof(char *); i++) { - JNI_OnUnload = (JNI_OnUnload_t ) - JVM_FindLibraryEntry(handle, onUnloadSymbols[i]); - if (JNI_OnUnload) { - break; - } + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == NULL) { + return; } - + handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID)); + JNI_OnUnload = (JNI_OnUnload_t )findBuiltinJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_FALSE); if (JNI_OnUnload) { JavaVM *jvm; (*env)->GetJavaVM(env, &jvm); (*JNI_OnUnload)(jvm, NULL); } JVM_UnloadLibrary(handle); + JNU_ReleaseStringPlatformChars(env, name, cname); } /* * Class: java_lang_ClassLoader_NativeLibrary * Method: find - * Signature: (Ljava/lang/String;J)J + * Signature: (Ljava/lang/String;)J */ JNIEXPORT jlong JNICALL Java_java_lang_ClassLoader_00024NativeLibrary_find @@ -456,3 +509,61 @@ 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) { + 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_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 = findBuiltinJniFunction(env, procHandle, libName, JNI_TRUE); + if (ret != NULL) { + lib = JNU_NewStringPlatform(env, libName); + free(libName); + return lib; + } + free(libName); + return NULL; +} --- old/src/solaris/native/common/jni_util_md.c 2013-03-05 17:15:47.474726713 -0500 +++ new/src/solaris/native/common/jni_util_md.c 2013-03-05 17:15:46.238656780 -0500 @@ -25,6 +25,21 @@ #include "jni.h" #include "jni_util.h" +#include "dlfcn.h" + +void* getProcessHandle() { + static procHandle = NULL; + if (procHandle != NULL) { + return procHandle; + } + // char * err1 = (char *)dlerror(); + procHandle = (void*)dlopen(NULL, RTLD_LAZY); + // if (procHandle == NULL) { + // char * err = (char *)dlerror(); + // fprintf(stderr, "dlopen: %s\n", err); + // } + return procHandle; +} jstring nativeNewStringPlatform(JNIEnv *env, const char *str) { return NULL; --- old/src/windows/native/common/jni_util_md.c 2013-03-05 17:15:51.830973197 -0500 +++ new/src/windows/native/common/jni_util_md.c 2013-03-05 17:15:50.070873609 -0500 @@ -137,3 +137,7 @@ else return NULL; } + +void* getProcessHandle() { + return (void*)GetModuleHandle(NULL); +}