提交 0d8749d1 编写于 作者: C Chuansheng Lu 提交者: Jonathan Lu

[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
上级 7bb16499
......@@ -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
......@@ -285,6 +285,8 @@ SUNWprivate_1.1 {
# INSERT VTABLE SYMBOLS HERE
JVM_AttachToTenant;
local:
*;
};
......
......@@ -280,6 +280,8 @@ SUNWprivate_1.1 {
# INSERT VTABLE SYMBOLS HERE
JVM_AttachToTenant;
local:
*;
};
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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");
......
......@@ -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") \
......
......@@ -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) {
......
......@@ -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 ///////////////////////////////////////////////////////////////////////////////////////////
......
......@@ -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
*/
......
......@@ -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)
......
/*
* 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;
}
/*
* 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
......@@ -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
......
......@@ -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".
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册