Path: blob/master/runtime/jcl/common/jniidcacheinit.c
6000 views
/*******************************************************************************1* Copyright (c) 2001, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/21#include "jclglob.h"22#include <string.h>23#include <stdlib.h>24#include "jcl.h"25#include "j2sever.h"26#include "j9lib.h"27#include "rommeth.h"28#include "j9protos.h"29#include "j9consts.h"30#include "jclglob.h"31#include "jniidcacheinit.h"32#include "j9.h"33#include "jclprots.h"34#if defined(J9ZOS390)35#include "atoe.h"36#include <_Ccsid.h>37#endif3839#include "ut_j9jcl.h"4041/**42* Initializes java/lang/String class ID in JniIDCache struct43*44* @param[in] env The JNI env45*46* @return TRUE or FALSE based on whether successfully initializing IDs or not47*/48BOOLEAN49initializeJavaLangStringIDCache(JNIEnv* env)50{51jstring jStringClass;52jobject globalStringRef;53BOOLEAN isGlobalRefRedundant=FALSE;54BOOLEAN isClassIDAlreadyCached=TRUE;55J9JavaVM *javaVM = ((J9VMThread *) env)->javaVM;5657/* Initializing java/lang/String class ID */58/* Check if java/lang/String class ID hasn't been cached yet */59omrthread_monitor_enter(javaVM->jclCacheMutex);6061if (JCL_CACHE_GET(env,CLS_java_lang_String) == NULL) {62isClassIDAlreadyCached=FALSE;63}6465omrthread_monitor_exit(javaVM->jclCacheMutex);6667if (!isClassIDAlreadyCached) {6869/* Load java/lang/String class */70jStringClass = (*env)->FindClass(env, "java/lang/String");71if ((*env)->ExceptionCheck(env)) {72return FALSE;73}7475globalStringRef = (*env)->NewGlobalRef(env, jStringClass);76if (globalStringRef == NULL) {77/* out of memory exception thrown */78javaVM->internalVMFunctions->throwNativeOOMError(env, 0, 0);79return FALSE;80}8182/* Allow the local reference jStringClass to be garbage collected immediately */83(*env)->DeleteLocalRef(env,jStringClass);848586omrthread_monitor_enter(javaVM->jclCacheMutex);8788if (JCL_CACHE_GET(env,CLS_java_lang_String) == NULL) {89/* Store java/lang/String class ID in JniIDCache struct */90JCL_CACHE_SET(env, CLS_java_lang_String, globalStringRef);91}92else {93isGlobalRefRedundant=TRUE;94}9596omrthread_monitor_exit(javaVM->jclCacheMutex);9798if (isGlobalRefRedundant == TRUE) {99(*env)->DeleteGlobalRef(env,globalStringRef);100}101}102return TRUE;103}104105106/**107* Initializes sun/reflect/ConstantPool (Java 8) or jdk/internal/reflect/ConstantPool (Java 11+) class ID108* and constantPoolOop field ID in JniIDCache struct109*110* @param[in] env The JNI env111*112* @return TRUE or FALSE based on whether successfully initializing IDs or not113*/114BOOLEAN115initializeSunReflectConstantPoolIDCache(JNIEnv* env)116{117J9JavaVM *javaVM = ((J9VMThread *) env)->javaVM;118BOOLEAN isClassIDAlreadyCached = TRUE;119BOOLEAN result = TRUE;120121omrthread_monitor_enter(javaVM->jclCacheMutex);122if (NULL == JCL_CACHE_GET(env, CLS_sun_reflect_ConstantPool)) {123isClassIDAlreadyCached = FALSE;124}125omrthread_monitor_exit(javaVM->jclCacheMutex);126127if (!isClassIDAlreadyCached) {128jclass sunReflectConstantPool = NULL;129130/* Load sun/reflect/ConstantPool (Java 8) or jdk/internal/reflect/ConstantPool (Java 11+) */131if (J2SE_VERSION(javaVM) >= J2SE_V11) {132sunReflectConstantPool = (*env)->FindClass(env, "jdk/internal/reflect/ConstantPool");133} else {134sunReflectConstantPool = (*env)->FindClass(env, "sun/reflect/ConstantPool");135}136if (NULL == sunReflectConstantPool) {137/* exception thrown */138result = FALSE;139} else {140jobject globalClassRef = (*env)->NewGlobalRef(env, sunReflectConstantPool);141/* Allow the local reference sunReflectConstantPool to be garbage collected immediately */142(*env)->DeleteLocalRef(env, sunReflectConstantPool);143if (NULL == globalClassRef) {144/* out of memory exception thrown */145javaVM->internalVMFunctions->throwNativeOOMError(env, 0, 0);146result = FALSE;147} else {148/* Initializing constantPoolOop field ID */149jfieldID fieldID = (*env)->GetFieldID(env, globalClassRef, "constantPoolOop", "Ljava/lang/Object;");150if (NULL == fieldID) {151result = FALSE;152} else {153BOOLEAN isGlobalRefRedundant = FALSE;154155omrthread_monitor_enter(javaVM->jclCacheMutex);156if (NULL == JCL_CACHE_GET(env,CLS_sun_reflect_ConstantPool)) {157/* Set FID_sun_reflect_ConstantPool_constantPoolOop first and CLS_sun_reflect_ConstantPool afterwards,158* read CLS_sun_reflect_ConstantPool first in java_lang_Access.c:Java_java_lang_Access_getConstantPool(),159* if NULL is returned, initializeSunReflectConstantPoolIDCache() is invoked to160* set FID_sun_reflect_ConstantPool_constantPoolOop, next read it and de-reference.161* Otherwise, a NULL FID_sun_reflect_ConstantPool_constantPoolOop could be returned and cause gpf later.162*/163JCL_CACHE_SET(env, FID_sun_reflect_ConstantPool_constantPoolOop, fieldID);164issueWriteBarrier();165JCL_CACHE_SET(env, CLS_sun_reflect_ConstantPool, globalClassRef);166} else {167isGlobalRefRedundant = TRUE;168}169omrthread_monitor_exit(javaVM->jclCacheMutex);170171if (isGlobalRefRedundant) {172(*env)->DeleteGlobalRef(env, globalClassRef);173}174}175}176}177}178return result;179}180181182