Path: blob/master/src/java.base/share/native/libjava/NativeLibraries.c
41149 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>26#include <assert.h>2728#include "jni.h"29#include "jni_util.h"30#include "jlong.h"31#include "jvm.h"32#include "jdk_internal_loader_NativeLibraries.h"33#include <string.h>3435typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *);36typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *);3738static jfieldID handleID;39static jfieldID jniVersionID;40static void *procHandle;414243static jboolean initIDs(JNIEnv *env)44{45if (handleID == 0) {46jclass this =47(*env)->FindClass(env, "jdk/internal/loader/NativeLibraries$NativeLibraryImpl");48if (this == 0)49return JNI_FALSE;50handleID = (*env)->GetFieldID(env, this, "handle", "J");51if (handleID == 0)52return JNI_FALSE;53jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I");54if (jniVersionID == 0)55return JNI_FALSE;56procHandle = getProcessHandle();57}58return JNI_TRUE;59}606162/*63* Support for finding JNI_On(Un)Load_<lib_name> if it exists.64* If cname == NULL then just find normal JNI_On(Un)Load entry point65*/66static void *findJniFunction(JNIEnv *env, void *handle,67const char *cname, jboolean isLoad) {68const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;69const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;70const char **syms;71int symsLen;72void *entryName = NULL;73char *jniFunctionName;74int i;75size_t len;7677// Check for JNI_On(Un)Load<_libname> function78if (isLoad) {79syms = onLoadSymbols;80symsLen = sizeof(onLoadSymbols) / sizeof(char *);81} else {82syms = onUnloadSymbols;83symsLen = sizeof(onUnloadSymbols) / sizeof(char *);84}85for (i = 0; i < symsLen; i++) {86// cname + sym + '_' + '\0'87if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) >88FILENAME_MAX) {89goto done;90}91jniFunctionName = malloc(len);92if (jniFunctionName == NULL) {93JNU_ThrowOutOfMemoryError(env, NULL);94goto done;95}96buildJniFunctionName(syms[i], cname, jniFunctionName);97entryName = JVM_FindLibraryEntry(handle, jniFunctionName);98free(jniFunctionName);99if(entryName) {100break;101}102}103104done:105return entryName;106}107108/*109* Class: jdk_internal_loader_NativeLibraries110* Method: load111* Signature: (Ljava/lang/String;ZZ)Z112*/113JNIEXPORT jboolean JNICALL114Java_jdk_internal_loader_NativeLibraries_load115(JNIEnv *env, jobject this, jobject lib, jstring name, jboolean isBuiltin, jboolean isJNI)116{117const char *cname;118jint jniVersion;119jthrowable cause;120void * handle;121jboolean loaded = JNI_FALSE;122123if (!initIDs(env))124return JNI_FALSE;125126cname = JNU_GetStringPlatformChars(env, name, 0);127if (cname == 0)128return JNI_FALSE;129handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);130if (isJNI) {131if (handle) {132JNI_OnLoad_t JNI_OnLoad;133JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,134isBuiltin ? cname : NULL,135JNI_TRUE);136if (JNI_OnLoad) {137JavaVM *jvm;138(*env)->GetJavaVM(env, &jvm);139jniVersion = (*JNI_OnLoad)(jvm, NULL);140} else {141jniVersion = 0x00010001;142}143144cause = (*env)->ExceptionOccurred(env);145if (cause) {146(*env)->ExceptionClear(env);147(*env)->Throw(env, cause);148if (!isBuiltin) {149JVM_UnloadLibrary(handle);150}151goto done;152}153154if (!JVM_IsSupportedJNIVersion(jniVersion) ||155(isBuiltin && jniVersion < JNI_VERSION_1_8)) {156char msg[256];157jio_snprintf(msg, sizeof(msg),158"unsupported JNI version 0x%08X required by %s",159jniVersion, cname);160JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);161if (!isBuiltin) {162JVM_UnloadLibrary(handle);163}164goto done;165}166(*env)->SetIntField(env, lib, jniVersionID, jniVersion);167} else {168cause = (*env)->ExceptionOccurred(env);169if (cause) {170(*env)->ExceptionClear(env);171(*env)->SetLongField(env, lib, handleID, (jlong)0);172(*env)->Throw(env, cause);173}174goto done;175}176}177(*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle));178loaded = JNI_TRUE;179180done:181JNU_ReleaseStringPlatformChars(env, name, cname);182return loaded;183}184185/*186* Class: jdk_internal_loader_NativeLibraries187* Method: unload188* Signature: (Ljava/lang/String;ZZJ)V189*/190JNIEXPORT void JNICALL191Java_jdk_internal_loader_NativeLibraries_unload192(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jboolean isJNI, jlong address)193{194const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;195void *handle;196JNI_OnUnload_t JNI_OnUnload;197const char *cname;198199if (!initIDs(env))200return;201cname = JNU_GetStringPlatformChars(env, name, 0);202if (cname == NULL) {203return;204}205handle = jlong_to_ptr(address);206if (isJNI) {207JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle,208isBuiltin ? cname : NULL,209JNI_FALSE);210if (JNI_OnUnload) {211JavaVM *jvm;212(*env)->GetJavaVM(env, &jvm);213(*JNI_OnUnload)(jvm, NULL);214}215}216if (!isBuiltin) {217JVM_UnloadLibrary(handle);218}219JNU_ReleaseStringPlatformChars(env, name, cname);220}221222223/*224* Class: jdk_internal_loader_NativeLibraries225* Method: findEntry0226* Signature: (Ljava/lang/String;)J227*/228JNIEXPORT jlong JNICALL229Java_jdk_internal_loader_NativeLibraries_findEntry0230(JNIEnv *env, jobject this, jobject lib, jstring name)231{232jlong handle;233const char *cname;234jlong res;235236if (!initIDs(env))237return jlong_zero;238239handle = (*env)->GetLongField(env, lib, handleID);240cname = (*env)->GetStringUTFChars(env, name, 0);241if (cname == 0)242return jlong_zero;243res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));244(*env)->ReleaseStringUTFChars(env, name, cname);245return res;246}247248/*249* Class: jdk_internal_loader_NativeLibraries250* Method: findBuiltinLib251* Signature: (Ljava/lang/String;)Ljava/lang/String;252*/253JNIEXPORT jstring JNICALL254Java_jdk_internal_loader_NativeLibraries_findBuiltinLib255(JNIEnv *env, jclass cls, jstring name)256{257const char *cname;258char *libName;259size_t prefixLen = strlen(JNI_LIB_PREFIX);260size_t suffixLen = strlen(JNI_LIB_SUFFIX);261size_t len;262jstring lib;263void *ret;264const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;265266if (name == NULL) {267JNU_ThrowInternalError(env, "NULL filename for native library");268return NULL;269}270procHandle = getProcessHandle();271cname = JNU_GetStringPlatformChars(env, name, 0);272if (cname == NULL) {273return NULL;274}275// Copy name Skipping PREFIX276len = strlen(cname);277if (len <= (prefixLen+suffixLen)) {278JNU_ReleaseStringPlatformChars(env, name, cname);279return NULL;280}281libName = malloc(len + 1); //+1 for null if prefix+suffix == 0282if (libName == NULL) {283JNU_ReleaseStringPlatformChars(env, name, cname);284JNU_ThrowOutOfMemoryError(env, NULL);285return NULL;286}287if (len > prefixLen) {288strcpy(libName, cname+prefixLen);289}290JNU_ReleaseStringPlatformChars(env, name, cname);291292// Strip SUFFIX293libName[strlen(libName)-suffixLen] = '\0';294295// Check for JNI_OnLoad_libname function296ret = findJniFunction(env, procHandle, libName, JNI_TRUE);297if (ret != NULL) {298lib = JNU_NewStringPlatform(env, libName);299free(libName);300return lib;301}302free(libName);303return NULL;304}305306307