From 0d8749d1e52e9d34fbbc4e4fa6466d74e9b2d648 Mon Sep 17 00:00:00 2001 From: Chuansheng Lu Date: Thu, 20 Feb 2020 13:48:05 +0800 Subject: [PATCH] [MultiTenant] HotSpot interfaces for MultiTenant framework Summary: ported HotSpot interfaces to Dragonwell8 to support MultiTenant framework Test Plan: jdk/test/multi-tenant Reviewed-by: yuleil, sanhong Issue: https://github.com/alibaba/dragonwell8/issues/84 --- make/defs.make | 1 + make/linux/makefiles/mapfile-vers-debug | 2 + make/linux/makefiles/mapfile-vers-product | 2 + src/share/vm/classfile/javaClasses.cpp | 5 ++ src/share/vm/classfile/javaClasses.hpp | 3 + src/share/vm/classfile/systemDictionary.cpp | 11 ++++ src/share/vm/classfile/systemDictionary.hpp | 10 ++++ src/share/vm/classfile/vmSymbols.hpp | 15 +++++ src/share/vm/prims/jni.cpp | 4 ++ src/share/vm/prims/jvm.cpp | 47 +++++++++++++++- src/share/vm/prims/jvm.h | 6 ++ src/share/vm/prims/jvm_misc.hpp | 5 ++ src/share/vm/prims/tenantenv.cpp | 53 ++++++++++++++++++ src/share/vm/prims/tenantenv.h | 62 +++++++++++++++++++++ src/share/vm/runtime/globals_ext.hpp | 4 ++ src/share/vm/runtime/thread.cpp | 18 ++++++ src/share/vm/runtime/thread.hpp | 15 +++++ src/share/vm/services/management.cpp | 41 ++++++++------ 18 files changed, 286 insertions(+), 18 deletions(-) create mode 100644 src/share/vm/prims/tenantenv.cpp create mode 100644 src/share/vm/prims/tenantenv.h diff --git a/make/defs.make b/make/defs.make index 1e97a4cb8..a6f7ed871 100644 --- a/make/defs.make +++ b/make/defs.make @@ -370,6 +370,7 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jvmticmlr.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h +EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/tenantenv.h .PHONY: $(HS_ALT_MAKE)/defs.make diff --git a/make/linux/makefiles/mapfile-vers-debug b/make/linux/makefiles/mapfile-vers-debug index f920c07ad..12ba424d8 100644 --- a/make/linux/makefiles/mapfile-vers-debug +++ b/make/linux/makefiles/mapfile-vers-debug @@ -285,6 +285,8 @@ SUNWprivate_1.1 { # INSERT VTABLE SYMBOLS HERE + JVM_AttachToTenant; + local: *; }; diff --git a/make/linux/makefiles/mapfile-vers-product b/make/linux/makefiles/mapfile-vers-product index 08ff896ca..73eb0de98 100644 --- a/make/linux/makefiles/mapfile-vers-product +++ b/make/linux/makefiles/mapfile-vers-product @@ -280,6 +280,8 @@ SUNWprivate_1.1 { # INSERT VTABLE SYMBOLS HERE + JVM_AttachToTenant; + local: *; }; diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp index ae1a60f25..feb86a60a 100644 --- a/src/share/vm/classfile/javaClasses.cpp +++ b/src/share/vm/classfile/javaClasses.cpp @@ -930,6 +930,7 @@ int java_lang_Thread::_tid_offset = 0; int java_lang_Thread::_thread_status_offset = 0; int java_lang_Thread::_park_blocker_offset = 0; int java_lang_Thread::_park_event_offset = 0 ; +int java_lang_Thread::_inheritedTenantContainer_offset = 0 ; void java_lang_Thread::compute_offsets() { @@ -953,6 +954,7 @@ void java_lang_Thread::compute_offsets() { compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature()); compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(), vmSymbols::long_signature()); + compute_offset(_inheritedTenantContainer_offset, k, vmSymbols::inheritedTenantContainer_name(), vmSymbols::tenantcontainer_signature()); } @@ -1025,6 +1027,9 @@ oop java_lang_Thread::inherited_access_control_context(oop java_thread) { return java_thread->obj_field(_inheritedAccessControlContext_offset); } +oop java_lang_Thread::inherited_tenant_container(oop java_thread) { + return java_thread->obj_field(_inheritedTenantContainer_offset); +} jlong java_lang_Thread::stackSize(oop java_thread) { // The stackSize field is only present starting in 1.4 diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp index c041bb142..0516e37f2 100644 --- a/src/share/vm/classfile/javaClasses.hpp +++ b/src/share/vm/classfile/javaClasses.hpp @@ -332,6 +332,7 @@ class java_lang_Thread : AllStatic { static int _thread_status_offset; static int _park_blocker_offset; static int _park_event_offset ; + static int _inheritedTenantContainer_offset; static void compute_offsets(); @@ -363,6 +364,8 @@ class java_lang_Thread : AllStatic { static oop context_class_loader(oop java_thread); // Control context static oop inherited_access_control_context(oop java_thread); + // Tenant container + static oop inherited_tenant_container(oop java_thread); // Stack size hint static jlong stackSize(oop java_thread); // Thread ID diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp index 0fc7257d2..876b13fed 100644 --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -2002,6 +2002,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(ReferenceQueue_klass), scan, CHECK); + // Tenant support + WKID tenant_group_start = WK_KLASS_ENUM_NAME(com_alibaba_tenant_TenantGlobals_klass); + WKID tenant_group_end = WK_KLASS_ENUM_NAME(com_alibaba_tenant_TenantContainer_klass); + initialize_wk_klasses_until(tenant_group_start, scan, CHECK); + if (MultiTenant) { + initialize_wk_klasses_through(tenant_group_end, scan, CHECK); + } else { + // Skip the tenant related classes, if not enabled. + scan = WKID(tenant_group_end + 1); + } + // JSR 292 classes WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); WKID jsr292_group_end = WK_KLASS_ENUM_NAME(VolatileCallSite_klass); diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp index bd20461e7..99853a1ef 100644 --- a/src/share/vm/classfile/systemDictionary.hpp +++ b/src/share/vm/classfile/systemDictionary.hpp @@ -132,6 +132,14 @@ class SymbolPropertyTable; do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \ do_klass(ReferenceQueue_klass, java_lang_ref_ReferenceQueue, Pre ) \ \ + /* support for multi-tenant feature */ \ + do_klass(com_alibaba_tenant_TenantGlobals_klass, com_alibaba_tenant_TenantGlobals, Pre_Tenant ) \ + do_klass(com_alibaba_tenant_TenantConfiguration_klass,com_alibaba_tenant_TenantConfiguration, Pre_Tenant ) \ + do_klass(com_alibaba_tenant_TenantState_klass, com_alibaba_tenant_TenantState, Pre_Tenant ) \ + do_klass(com_alibaba_tenant_TenantException_klass, com_alibaba_tenant_TenantException, Pre_Tenant ) \ + do_klass(com_alibaba_tenant_TenantContainer_klass, com_alibaba_tenant_TenantContainer, Pre_Tenant ) \ + /* Note: TenantGlobals must be first, and TenantContainer last in group */ \ + \ do_klass(Thread_klass, java_lang_Thread, Pre ) \ do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \ do_klass(Properties_klass, java_util_Properties, Pre ) \ @@ -221,6 +229,7 @@ class SystemDictionary : AllStatic { enum InitOption { Pre, // preloaded; error if not present Pre_JSR292, // preloaded if EnableInvokeDynamic + Pre_Tenant, // preloaded if MultiTenant // Order is significant. Options before this point require resolve_or_fail. // Options after this point will use resolve_or_null instead. @@ -407,6 +416,7 @@ public: static Klass* check_klass_Pre( Klass* k) { return check_klass(k); } static Klass* check_klass_Pre_JSR292(Klass* k) { return EnableInvokeDynamic ? check_klass(k) : k; } + static Klass* check_klass_Pre_Tenant(Klass* k) { return MultiTenant ? check_klass(k) : k; } static Klass* check_klass_Opt( Klass* k) { return k; } static Klass* check_klass_Opt_Only_JDK15(Klass* k) { assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only"); diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp index 84ea4876b..619e6f0bc 100644 --- a/src/share/vm/classfile/vmSymbols.hpp +++ b/src/share/vm/classfile/vmSymbols.hpp @@ -53,6 +53,12 @@ template(java_lang_Object, "java/lang/Object") \ template(java_lang_Class, "java/lang/Class") \ template(java_lang_String, "java/lang/String") \ + template(com_alibaba_tenant_TenantGlobals, "com/alibaba/tenant/TenantGlobals") \ + template(com_alibaba_tenant_TenantConfiguration, "com/alibaba/tenant/TenantConfiguration") \ + template(com_alibaba_tenant_TenantState, "com/alibaba/tenant/TenantState") \ + template(com_alibaba_tenant_TenantException, "com/alibaba/tenant/TenantException") \ + template(com_alibaba_tenant_TenantContainer, "com/alibaba/tenant/TenantContainer") \ + template(com_alibaba_tenant_JGroup, "com/alibaba/tenant/JGroup") \ template(java_lang_Thread, "java/lang/Thread") \ template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ template(java_lang_Cloneable, "java/lang/Cloneable") \ @@ -314,8 +320,10 @@ template(group_name, "group") \ template(daemon_name, "daemon") \ template(eetop_name, "eetop") \ + template(inheritedTenantContainer_name, "inheritedTenantContainer") \ template(thread_status_name, "threadStatus") \ template(run_method_name, "run") \ + template(runThread_method_name, "runThread") \ template(exit_method_name, "exit") \ template(add_method_name, "add") \ template(remove_method_name, "remove") \ @@ -342,6 +350,7 @@ template(put_name, "put") \ template(type_name, "type") \ template(findNative_name, "findNative") \ + template(initializeTenantContainerClass_name, "initializeTenantContainerClass") \ template(deadChild_name, "deadChild") \ template(addClass_name, "addClass") \ template(throwIllegalAccessError_name, "throwIllegalAccessError") \ @@ -506,6 +515,7 @@ template(exception_void_signature, "(Ljava/lang/Exception;)V") \ template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \ template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \ + template(tenantcontainer_signature, "Lcom/alibaba/tenant/TenantContainer;") \ template(class_protectiondomain_signature, "(Ljava/lang/Class;Ljava/security/ProtectionDomain;)V") \ template(thread_signature, "Ljava/lang/Thread;") \ template(thread_array_signature, "[Ljava/lang/Thread;") \ @@ -514,6 +524,8 @@ template(class_array_signature, "[Ljava/lang/Class;") \ template(classloader_signature, "Ljava/lang/ClassLoader;") \ template(object_signature, "Ljava/lang/Object;") \ + template(state_name, "state") \ + template(com_alibaba_tenant_TenantState_signature, "Lcom/alibaba/tenant/TenantState;") \ template(object_array_signature, "[Ljava/lang/Object;") \ template(class_signature, "Ljava/lang/Class;") \ template(string_signature, "Ljava/lang/String;") \ @@ -878,6 +890,9 @@ do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \ do_name( updateByteBuffer_name, "updateByteBuffer") \ do_signature(updateByteBuffer_signature, "(IJII)I") \ + /* support for com.alibaba.tenant.TenantContainer */ \ + do_name( allocation_context_address, "allocationContext") \ + do_name( tenant_id_address, "tenantId") \ \ /* support for sun.misc.Unsafe */ \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp index d425ae158..b7d6d01f8 100644 --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -5607,6 +5607,10 @@ jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { ret = JNI_OK; return ret; + } else if (TENANT_ENV_VERSION_1_0 == version) { //get the tenant environment for java thread. + *(TenantEnv**)penv = ((JavaThread*) thread)->tenant_environment(); + ret = JNI_OK; + return ret; } else if (version == JVMPI_VERSION_1 || version == JVMPI_VERSION_1_1 || version == JVMPI_VERSION_1_2) { diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index 310ecc087..b23917a75 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -377,6 +377,18 @@ JVM_ENTRY(jobject, JVM_InitProperties(JNIEnv *env, jobject properties)) } } + //Convert the -XX:+MultiTenant command line flag + //to the com.alibaba.tenant.enableMultiTenant property in case that + //the java code can determine if the tenant feature is enabled but + //without loading tenant-related classes. + { + if(MultiTenant) { + PUTPROP(props, "com.alibaba.tenant.enableMultiTenant", "true"); + } else { + PUTPROP(props, "com.alibaba.tenant.enableMultiTenant", "false"); + } + } + // JVM monitoring and management support // Add the sun.management.compiler property for the compiler's name { @@ -3069,12 +3081,37 @@ static void thread_entry(JavaThread* thread, TRAPS) { HandleMark hm(THREAD); Handle obj(THREAD, thread->threadObj()); JavaValue result(T_VOID); - JavaCalls::call_virtual(&result, + + if(MultiTenant) { + oop tenantContainer = + java_lang_Thread::inherited_tenant_container(thread->threadObj()); + if(tenantContainer == NULL) { + JavaCalls::call_virtual(&result, + obj, + KlassHandle(THREAD, SystemDictionary::Thread_klass()), + vmSymbols::run_method_name(), + vmSymbols::void_method_signature(), + THREAD); + } else { + /*Call into TenantContainer.runThread instead of Thread.run. */ + Handle tenant_obj(THREAD, tenantContainer); + JavaCalls::call_virtual(&result, + tenant_obj, + KlassHandle(THREAD, SystemDictionary::com_alibaba_tenant_TenantContainer_klass()), + vmSymbols::runThread_method_name(), + vmSymbols::thread_void_signature(), + obj, + THREAD); + + } + } else { + JavaCalls::call_virtual(&result, obj, KlassHandle(THREAD, SystemDictionary::Thread_klass()), vmSymbols::run_method_name(), vmSymbols::void_method_signature(), THREAD); + } } @@ -3837,6 +3874,14 @@ JVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver, return result; JVM_END +/***************** Tenant support ************************************/ + +JVM_ENTRY(void, JVM_AttachToTenant(JNIEnv *env, jobject tenant)) + JVMWrapper("JVM_AttachToTenant"); + assert(MultiTenant, "pre-condition"); + assert (NULL != thread, "no current thread!"); + thread->set_tenantObj(tenant == NULL ? (oop)NULL : JNIHandles::resolve_non_null(tenant)); +JVM_END // Array /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/share/vm/prims/jvm.h b/src/share/vm/prims/jvm.h index 8261e488b..a1a3dd72f 100644 --- a/src/share/vm/prims/jvm.h +++ b/src/share/vm/prims/jvm.h @@ -357,6 +357,12 @@ JNIEXPORT jclass JNICALL JVM_LoadClass0(JNIEnv *env, jobject obj, jclass currClass, jstring currClassName); +/* + * com.alibaba.tenant.TenantContainer + */ +JNIEXPORT void JNICALL +JVM_AttachToTenant(JNIEnv *env, jobject tenant); + /* * java.lang.reflect.Array */ diff --git a/src/share/vm/prims/jvm_misc.hpp b/src/share/vm/prims/jvm_misc.hpp index 39b2d7199..e819dcee9 100644 --- a/src/share/vm/prims/jvm_misc.hpp +++ b/src/share/vm/prims/jvm_misc.hpp @@ -48,6 +48,11 @@ extern struct JNINativeInterface_* jni_functions_check(); extern struct JNINativeInterface_* jni_functions(); extern void copy_jni_function_table(const struct JNINativeInterface_* new_function_table); +/* + * Support for tenant function table. + */ +extern struct TenantNativeInterface_* tenant_functions(); + // Support for fast JNI accessors extern "C" { typedef jboolean (JNICALL *GetBooleanField_t) diff --git a/src/share/vm/prims/tenantenv.cpp b/src/share/vm/prims/tenantenv.cpp new file mode 100644 index 000000000..e6577b641 --- /dev/null +++ b/src/share/vm/prims/tenantenv.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "prims/tenantenv.h" +#include "runtime/globals.hpp" + +/** + * Be careful: any change to the following constant defintions, you MUST + * synch up them with ones defined in com.alibaba.tenant.TenantGlobals + */ + +#define TENANT_FLAG_MULTI_TENANT_ENABLED (0x1) // bit 0 to indicate if the tenant feature is enabled. + +static jint tenant_GetTenantFlags(TenantEnv *env, jclass cls); + +static struct TenantNativeInterface_ tenantNativeInterface = { + tenant_GetTenantFlags +}; + +struct TenantNativeInterface_* tenant_functions() +{ + return &tenantNativeInterface; +} + +static jint +tenant_GetTenantFlags(TenantEnv *env, jclass cls) +{ + jint result = 0x0; + + if (MultiTenant) { + result |= TENANT_FLAG_MULTI_TENANT_ENABLED; + } + + return result; +} diff --git a/src/share/vm/prims/tenantenv.h b/src/share/vm/prims/tenantenv.h new file mode 100644 index 000000000..d9936a200 --- /dev/null +++ b/src/share/vm/prims/tenantenv.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef SHARE_VM_PRIMS_TENANT_ENV_H +#define SHARE_VM_PRIMS_TENANT_ENV_H + +#include "jni.h" + +// 0x00200000 represents tenant module and the last 10 represents version 1.0 +#define TENANT_ENV_VERSION_1_0 0x00200010 + +/* + * Tenant Native Method Interface. + */ +struct TenantNativeInterface_; +struct TenantEnv_; + +#ifdef __cplusplus +typedef TenantEnv_ TenantEnv; +#else +typedef const struct TenantNativeInterface_* TenantEnv; +#endif + +/* + * We use inlined functions for C++ so that programmers can write: + * tenantEnv->GetTenantFlags(cls); + * in C++ rather than: + * (*tenantEnv)->GetTenantFlags(tenantEnv, cls); + * in C. + */ +struct TenantNativeInterface_ { + jint (JNICALL *GetTenantFlags)(TenantEnv *env, jclass cls); +}; + +struct TenantEnv_ { + const struct TenantNativeInterface_ *functions; +#ifdef __cplusplus + jint GetTenantFlags(jclass cls) { + return functions->GetTenantFlags(this, cls); + } +#endif +}; + +#endif // SHARE_VM_PRIMS_TENANT_ENV_H diff --git a/src/share/vm/runtime/globals_ext.hpp b/src/share/vm/runtime/globals_ext.hpp index ef2617201..6c654f2ad 100644 --- a/src/share/vm/runtime/globals_ext.hpp +++ b/src/share/vm/runtime/globals_ext.hpp @@ -93,6 +93,10 @@ product(uintx, ElasticHeapParallelWorkers, 0, \ "Number of parallel worker threads for memory " \ "commit/uncommit. 0 be same as ConcGCThreads") \ + \ + product(bool, MultiTenant, false, \ + "Enable the multi-tenant feature.") \ + //add new AJVM specific flags here diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index ecc507fa0..88b95acf6 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -1065,6 +1065,15 @@ static void call_initializeSystemClass(TRAPS) { vmSymbols::void_method_signature(), CHECK); } +static void call_initializeTenantContainerClass(TRAPS) { + Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::com_alibaba_tenant_TenantContainer(), true, CHECK); + instanceKlassHandle klass (THREAD, k); + + JavaValue result(T_VOID); + JavaCalls::call_static(&result, klass, vmSymbols::initializeTenantContainerClass_name(), + vmSymbols::void_method_signature(), CHECK); +} + char java_runtime_name[128] = ""; char java_runtime_version[128] = ""; @@ -1439,6 +1448,7 @@ void JavaThread::initialize() { _anchor.clear(); set_entry_point(NULL); set_jni_functions(jni_functions()); + set_tenant_functions(tenant_functions()); set_callee_target(NULL); set_vm_result(NULL); set_vm_result_2(NULL); @@ -1476,6 +1486,7 @@ void JavaThread::initialize() { _do_not_unlock_if_synchronized = false; _cached_monitor_info = NULL; _parker = Parker::Allocate(this) ; + _tenantObj = NULL; #ifndef PRODUCT _jmp_ring_index = 0; @@ -2805,6 +2816,7 @@ void JavaThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) // Traverse instance variables at the end since the GC may be moving things // around using this function f->do_oop((oop*) &_threadObj); + f->do_oop((oop*) &_tenantObj); f->do_oop((oop*) &_vm_result); f->do_oop((oop*) &_exception_oop); f->do_oop((oop*) &_pending_async_exception); @@ -3555,6 +3567,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); } + // Multi-tenant support + if (MultiTenant) { + //Initialize TennatContainer class after the system is booted. + call_initializeTenantContainerClass(CHECK_0); + } + // See : bugid 4211085. // Background : the static initializer of java.lang.Compiler tries to read // property"java.compiler" and read & write property "java.vm.info". diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp index 05e9528dc..9b2341cf6 100644 --- a/src/share/vm/runtime/thread.hpp +++ b/src/share/vm/runtime/thread.hpp @@ -29,6 +29,7 @@ #include "memory/threadLocalAllocBuffer.hpp" #include "oops/oop.hpp" #include "prims/jni.h" +#include "prims/tenantenv.h" #include "prims/jvmtiExport.hpp" #include "runtime/frame.hpp" #include "runtime/javaFrameAnchor.hpp" @@ -802,6 +803,7 @@ class JavaThread: public Thread { private: JavaThread* _next; // The next thread in the Threads list oop _threadObj; // The Java level thread object + oop _tenantObj; // The tenant object which this java thread attaches to #ifdef ASSERT private: @@ -831,6 +833,8 @@ class JavaThread: public Thread { JNIEnv _jni_environment; + TenantEnv _tenant_environment; // tenant environment + // Deopt support DeoptResourceMark* _deopt_mark; // Holds special ResourceMark for deoptimization @@ -1013,6 +1017,10 @@ class JavaThread: public Thread { return (struct JNINativeInterface_ *)_jni_environment.functions; } + void set_tenant_functions(struct TenantNativeInterface_* functionTable) { + _tenant_environment.functions = functionTable; + } + // This function is called at thread creation to allow // platform specific thread variables to be initialized. void cache_global_variables(); @@ -1041,6 +1049,10 @@ class JavaThread: public Thread { oop threadObj() const { return _threadObj; } void set_threadObj(oop p) { _threadObj = p; } + // Get/set the tenant which the thread is attached to + oop tenantObj() const { return _tenantObj; } + void set_tenantObj(oop tenantObj) { _tenantObj = tenantObj; } + ThreadPriority java_priority() const; // Read from threadObj() // Prepare thread and add to priority queue. If a priority is @@ -1407,6 +1419,9 @@ class JavaThread: public Thread { // Returns the jni environment for this thread JNIEnv* jni_environment() { return &_jni_environment; } + // Returns the tenant environment for this thread + TenantEnv* tenant_environment() { return &_tenant_environment; } + static JavaThread* thread_from_jni_environment(JNIEnv* env) { JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); // Only return NULL if thread is off the thread list; starting to diff --git a/src/share/vm/services/management.cpp b/src/share/vm/services/management.cpp index a8e6b0b27..76a4a2e5d 100644 --- a/src/share/vm/services/management.cpp +++ b/src/share/vm/services/management.cpp @@ -2214,33 +2214,40 @@ jlong Management::ticks_to_ms(jlong ticks) { JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids, jlongArray sizeArray)) // Check if threads is null - if (ids == NULL || sizeArray == NULL) { + if (sizeArray == NULL) { THROW(vmSymbols::java_lang_NullPointerException()); } ResourceMark rm(THREAD); - typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); - typeArrayHandle ids_ah(THREAD, ta); typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray)); typeArrayHandle sizeArray_h(THREAD, sa); - // validate the thread id array - validate_thread_id_array(ids_ah, CHECK); + if (ids == NULL){ + assert(sizeArray_h->length() > 0, "pre-condition"); + // fast path to retrieve current thread's data without locking + sizeArray_h->long_at_put(0, THREAD->cooked_allocated_bytes()); + } else { + typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids)); + typeArrayHandle ids_ah(THREAD, ta); - // sizeArray must be of the same length as the given array of thread IDs - int num_threads = ids_ah->length(); - if (num_threads != sizeArray_h->length()) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "The length of the given long array does not match the length of " - "the given array of thread IDs"); - } + // validate the thread id array + validate_thread_id_array(ids_ah, CHECK); - MutexLockerEx ml(Threads_lock); - for (int i = 0; i < num_threads; i++) { - JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); - if (java_thread != NULL) { - sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); + // sizeArray must be of the same length as the given array of thread IDs + int num_threads = ids_ah->length(); + if (num_threads != sizeArray_h->length()) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "The length of the given long array does not match the length of " + "the given array of thread IDs"); + } + + MutexLockerEx ml(Threads_lock); + for (int i = 0; i < num_threads; i++) { + JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i)); + if (java_thread != NULL) { + sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes()); + } } } JVM_END -- GitLab