Path: blob/master/src/java.base/share/native/libjava/NativeLibraries.c
67743 views
/*1* Copyright (c) 2020, 2021, 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,116jboolean isBuiltin, jboolean isJNI, jboolean throwExceptionIfFail)117{118const char *cname;119jint jniVersion;120jthrowable cause;121void * handle;122jboolean loaded = JNI_FALSE;123124if (!initIDs(env))125return JNI_FALSE;126127cname = JNU_GetStringPlatformChars(env, name, 0);128if (cname == 0)129return JNI_FALSE;130handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname, throwExceptionIfFail);131if (isJNI) {132if (handle) {133JNI_OnLoad_t JNI_OnLoad;134JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,135isBuiltin ? cname : NULL,136JNI_TRUE);137if (JNI_OnLoad) {138JavaVM *jvm;139(*env)->GetJavaVM(env, &jvm);140jniVersion = (*JNI_OnLoad)(jvm, NULL);141} else {142jniVersion = 0x00010001;143}144145cause = (*env)->ExceptionOccurred(env);146if (cause) {147(*env)->ExceptionClear(env);148(*env)->Throw(env, cause);149if (!isBuiltin) {150JVM_UnloadLibrary(handle);151}152goto done;153}154155if (!JVM_IsSupportedJNIVersion(jniVersion) ||156(isBuiltin && jniVersion < JNI_VERSION_1_8)) {157char msg[256];158jio_snprintf(msg, sizeof(msg),159"unsupported JNI version 0x%08X required by %s",160jniVersion, cname);161JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);162if (!isBuiltin) {163JVM_UnloadLibrary(handle);164}165goto done;166}167(*env)->SetIntField(env, lib, jniVersionID, jniVersion);168} else {169cause = (*env)->ExceptionOccurred(env);170if (cause) {171(*env)->ExceptionClear(env);172(*env)->SetLongField(env, lib, handleID, (jlong)0);173(*env)->Throw(env, cause);174}175goto done;176}177}178(*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle));179loaded = JNI_TRUE;180181done:182JNU_ReleaseStringPlatformChars(env, name, cname);183return loaded;184}185186/*187* Class: jdk_internal_loader_NativeLibraries188* Method: unload189* Signature: (Ljava/lang/String;ZZJ)V190*/191JNIEXPORT void JNICALL192Java_jdk_internal_loader_NativeLibraries_unload193(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jboolean isJNI, jlong address)194{195const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;196void *handle;197JNI_OnUnload_t JNI_OnUnload;198const char *cname;199200if (!initIDs(env))201return;202cname = JNU_GetStringPlatformChars(env, name, 0);203if (cname == NULL) {204return;205}206handle = jlong_to_ptr(address);207if (isJNI) {208JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle,209isBuiltin ? cname : NULL,210JNI_FALSE);211if (JNI_OnUnload) {212JavaVM *jvm;213(*env)->GetJavaVM(env, &jvm);214(*JNI_OnUnload)(jvm, NULL);215}216}217if (!isBuiltin) {218JVM_UnloadLibrary(handle);219}220JNU_ReleaseStringPlatformChars(env, name, cname);221}222223224/*225* Class: jdk_internal_loader_NativeLibraries226* Method: findEntry0227* Signature: (Ljava/lang/String;)J228*/229JNIEXPORT jlong JNICALL230Java_jdk_internal_loader_NativeLibraries_findEntry0231(JNIEnv *env, jobject this, jobject lib, jstring name)232{233jlong handle;234const char *cname;235jlong res;236237if (!initIDs(env))238return jlong_zero;239240handle = (*env)->GetLongField(env, lib, handleID);241cname = (*env)->GetStringUTFChars(env, name, 0);242if (cname == 0)243return jlong_zero;244res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));245(*env)->ReleaseStringUTFChars(env, name, cname);246return res;247}248249/*250* Class: jdk_internal_loader_NativeLibraries251* Method: findBuiltinLib252* Signature: (Ljava/lang/String;)Ljava/lang/String;253*/254JNIEXPORT jstring JNICALL255Java_jdk_internal_loader_NativeLibraries_findBuiltinLib256(JNIEnv *env, jclass cls, jstring name)257{258const char *cname;259char *libName;260size_t prefixLen = strlen(JNI_LIB_PREFIX);261size_t suffixLen = strlen(JNI_LIB_SUFFIX);262size_t len;263jstring lib;264void *ret;265const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;266267if (name == NULL) {268JNU_ThrowInternalError(env, "NULL filename for native library");269return NULL;270}271procHandle = getProcessHandle();272cname = JNU_GetStringPlatformChars(env, name, 0);273if (cname == NULL) {274return NULL;275}276// Copy name Skipping PREFIX277len = strlen(cname);278if (len <= (prefixLen+suffixLen)) {279JNU_ReleaseStringPlatformChars(env, name, cname);280return NULL;281}282libName = malloc(len + 1); //+1 for null if prefix+suffix == 0283if (libName == NULL) {284JNU_ReleaseStringPlatformChars(env, name, cname);285JNU_ThrowOutOfMemoryError(env, NULL);286return NULL;287}288if (len > prefixLen) {289strcpy(libName, cname+prefixLen);290}291JNU_ReleaseStringPlatformChars(env, name, cname);292293// Strip SUFFIX294libName[strlen(libName)-suffixLen] = '\0';295296// Check for JNI_OnLoad_libname function297ret = findJniFunction(env, procHandle, libName, JNI_TRUE);298if (ret != NULL) {299lib = JNU_NewStringPlatform(env, libName);300free(libName);301return lib;302}303free(libName);304return NULL;305}306307308