JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
JVMWrapper("JVM_Sleep");
if (millis < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
}
JavaThreadSleepState jtss(thread);
#ifndef USDT2
HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis);
#else /* USDT2 */
HOTSPOT_THREAD_SLEEP_BEGIN(
millis);
#endif /* USDT2 */
EventThreadSleep event;
if (millis == 0) {
if (ConvertSleepToYield) {
os::yield();
} else {
ThreadState old_state = thread->osthread()->get_state();
thread->osthread()->set_state(SLEEPING);
os::sleep(thread, MinSleepInterval, false);
thread->osthread()->set_state(old_state);
}
} else {
ThreadState old_state = thread->osthread()->get_state();
thread->osthread()->set_state(SLEEPING);
if (os::sleep(thread, millis, true) == OS_INTRPT) {
if (!HAS_PENDING_EXCEPTION) {
if (event.should_commit()) {
post_thread_sleep_event(&event, millis);
}
#ifndef USDT2
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1);
#else /* USDT2 */
HOTSPOT_THREAD_SLEEP_END(
1);
#endif /* USDT2 */
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
}
}
thread->osthread()->set_state(old_state);
}
if (event.should_commit()) {
post_thread_sleep_event(&event, millis);
}
#ifndef USDT2
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0);
#else /* USDT2 */
HOTSPOT_THREAD_SLEEP_END(
0);
#endif /* USDT2 */
JVM_END
JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
JVMWrapper("JVM_CurrentThread");
oop jthread = thread->threadObj();
assert (thread != NULL, "no current thread!");
return JNIHandles::make_local(env, jthread);
JVM_END
JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_CountStackFrames");
oop java_thread = JNIHandles::resolve_non_null(jthread);
bool throw_illegal_thread_state = false;
int count = 0;
{
MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
if (thr == NULL) {
} else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) {
throw_illegal_thread_state = true;
} else {
for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) {
if (!vfst.method()->is_native()) count++;
}
}
}
if (throw_illegal_thread_state) {
THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(),
"this thread is not suspended");
}
return count;
JVM_END
JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_Interrupt");
oop java_thread = JNIHandles::resolve_non_null(jthread);
MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
if (thr != NULL) {
Thread::interrupt(thr);
}
JVM_END
JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted))
JVMWrapper("JVM_IsInterrupted");
oop java_thread = JNIHandles::resolve_non_null(jthread);
MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
if (thr == NULL) {
return JNI_FALSE;
} else {
return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0);
}
JVM_END
JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))
JVMWrapper("JVM_HoldsLock");
assert(THREAD->is_Java_thread(), "sanity check");
if (obj == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
}
Handle h_obj(THREAD, JNIHandles::resolve(obj));
return ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, h_obj);
JVM_END
JVM_ENTRY(void, JVM_DumpAllStacks(JNIEnv* env, jclass))
JVMWrapper("JVM_DumpAllStacks");
VM_PrintThreads op;
VMThread::execute(&op);
if (JvmtiExport::should_post_data_dump()) {
JvmtiExport::post_data_dump();
}
JVM_END
JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name))
JVMWrapper("JVM_SetNativeThreadName");
ResourceMark rm(THREAD);
oop java_thread = JNIHandles::resolve_non_null(jthread);
JavaThread* thr = java_lang_Thread::thread(java_thread);
if (Thread::current() == thr && !thr->has_attached_via_jni()) {
const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
os::set_native_thread_name(thread_name);
}
JVM_END
static bool is_trusted_frame(JavaThread* jthread, vframeStream* vfst) {
assert(jthread->is_Java_thread(), "must be a Java thread");
if (jthread->privileged_stack_top() == NULL) return false;
if (jthread->privileged_stack_top()->frame_id() == vfst->frame_id()) {
oop loader = jthread->privileged_stack_top()->class_loader();
if (loader == NULL) return true;
bool trusted = java_lang_ClassLoader::is_trusted_loader(loader);
if (trusted) return true;
}
return false;
}
JVM_ENTRY(jclass, JVM_CurrentLoadedClass(JNIEnv *env))
JVMWrapper("JVM_CurrentLoadedClass");
ResourceMark rm(THREAD);
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
bool trusted = is_trusted_frame(thread, &vfst);
if (trusted) return NULL;
Method* m = vfst.method();
if (!m->is_native()) {
InstanceKlass* holder = m->method_holder();
oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
return (jclass) JNIHandles::make_local(env, holder->java_mirror());
}
}
}
return NULL;
JVM_END
JVM_ENTRY(jobject, JVM_CurrentClassLoader(JNIEnv *env))
JVMWrapper("JVM_CurrentClassLoader");
ResourceMark rm(THREAD);
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
bool trusted = is_trusted_frame(thread, &vfst);
if (trusted) return NULL;
Method* m = vfst.method();
if (!m->is_native()) {
InstanceKlass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
return JNIHandles::make_local(env, loader);
}
}
}
return NULL;
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
JVMWrapper("JVM_GetClassContext");
ResourceMark rm(THREAD);
JvmtiVMObjectAllocEventCollector oam;
vframeStream vfst(thread);
if (SystemDictionary::reflect_CallerSensitive_klass() != NULL) {
Method* m = vfst.method();
if (!(m->method_holder() == SystemDictionary::SecurityManager_klass() &&
m->name() == vmSymbols::getClassContext_name() &&
m->signature() == vmSymbols::void_class_array_signature())) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext");
}
}
GrowableArray<KlassHandle>* klass_array = new GrowableArray<KlassHandle>();
for (; !vfst.at_end(); vfst.security_next()) {
Method* m = vfst.method();
if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) {
Klass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
klass_array->append(holder);
}
}
objArrayOop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), klass_array->length(), CHECK_NULL);
for (int i = 0; i < klass_array->length(); i++) {
result->obj_at_put(i, klass_array->at(i)->java_mirror());
}
return (jobjectArray) JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jint, JVM_ClassDepth(JNIEnv *env, jstring name))
JVMWrapper("JVM_ClassDepth");
ResourceMark rm(THREAD);
Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
Handle class_name_str = java_lang_String::internalize_classname(h_name, CHECK_0);
const char* str = java_lang_String::as_utf8_string(class_name_str());
TempNewSymbol class_name_sym = SymbolTable::probe(str, (int)strlen(str));
if (class_name_sym == NULL) {
return -1;
}
int depth = 0;
for(vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
if (!vfst.method()->is_native()) {
InstanceKlass* holder = vfst.method()->method_holder();
assert(holder->is_klass(), "just checking");
if (holder->name() == class_name_sym) {
return depth;
}
depth++;
}
}
return -1;
JVM_END
JVM_ENTRY(jint, JVM_ClassLoaderDepth(JNIEnv *env))
JVMWrapper("JVM_ClassLoaderDepth");
ResourceMark rm(THREAD);
int depth = 0;
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
bool trusted = is_trusted_frame(thread, &vfst);
if (trusted) return -1;
Method* m = vfst.method();
if (!m->is_native()) {
InstanceKlass* holder = m->method_holder();
assert(holder->is_klass(), "just checking");
oop loader = holder->class_loader();
if (loader != NULL && !java_lang_ClassLoader::is_trusted_loader(loader)) {
return depth;
}
depth++;
}
}
return -1;
JVM_END
JVM_ENTRY(jstring, JVM_GetSystemPackage(JNIEnv *env, jstring name))
JVMWrapper("JVM_GetSystemPackage");
ResourceMark rm(THREAD);
JvmtiVMObjectAllocEventCollector oam;
char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
oop result = ClassLoader::get_system_package(str, CHECK_NULL);
return (jstring) JNIHandles::make_local(result);
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env))
JVMWrapper("JVM_GetSystemPackages");
JvmtiVMObjectAllocEventCollector oam;
objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(result);
JVM_END
bool force_verify_field_access(Klass* current_class, Klass* field_class, AccessFlags access, bool classloader_only) {
if (current_class == NULL) {
return true;
}
if ((current_class == field_class) || access.is_public()) {
return true;
}
if (access.is_protected()) {
if (current_class->is_subclass_of(field_class)) {
return true;
}
}
return (!access.is_private() && InstanceKlass::cast(current_class)->is_same_class_package(field_class));
}
JVM_ENTRY(jobject, JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass))
JVMWrapper("JVM_AllocateNewObject");
JvmtiVMObjectAllocEventCollector oam;
oop curr_mirror = JNIHandles::resolve_non_null(currClass);
oop init_mirror = JNIHandles::resolve_non_null(initClass);
if (java_lang_Class::is_primitive(curr_mirror) || java_lang_Class::is_primitive(init_mirror)) {
ResourceMark rm(THREAD);
THROW_0(vmSymbols::java_lang_InvalidClassException());
}
if (java_lang_Class::as_Klass(curr_mirror)->oop_is_array() ||
java_lang_Class::as_Klass(init_mirror)->oop_is_array()) {
ResourceMark rm(THREAD);
THROW_0(vmSymbols::java_lang_InvalidClassException());
}
instanceKlassHandle curr_klass (THREAD, java_lang_Class::as_Klass(curr_mirror));
instanceKlassHandle init_klass (THREAD, java_lang_Class::as_Klass(init_mirror));
assert(curr_klass->is_subclass_of(init_klass()), "just checking");
curr_klass->check_valid_for_instantiation(false, CHECK_NULL);
curr_klass->initialize(CHECK_NULL);
methodHandle m (THREAD,
init_klass->find_method(vmSymbols::object_initializer_name(),
vmSymbols::void_method_signature()));
if (m.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
Method::name_and_sig_as_C_string(init_klass(),
vmSymbols::object_initializer_name(),
vmSymbols::void_method_signature()));
}
if (curr_klass == init_klass && !m->is_public()) {
THROW_0(vmSymbols::java_lang_IllegalAccessException());
}
if (!force_verify_field_access(curr_klass(), init_klass(), m->access_flags(), false)) {
THROW_0(vmSymbols::java_lang_IllegalAccessException());
}
Handle obj = curr_klass->allocate_instance_handle(CHECK_NULL);
JavaCalls::call_default_constructor(thread, m, obj, CHECK_NULL);
return JNIHandles::make_local(obj());
JVM_END
JVM_ENTRY(jobject, JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length))
JVMWrapper("JVM_AllocateNewArray");
JvmtiVMObjectAllocEventCollector oam;
oop mirror = JNIHandles::resolve_non_null(currClass);
if (java_lang_Class::is_primitive(mirror)) {
THROW_0(vmSymbols::java_lang_InvalidClassException());
}
Klass* k = java_lang_Class::as_Klass(mirror);
oop result;
if (k->oop_is_typeArray()) {
result = TypeArrayKlass::cast(k)->allocate(length, CHECK_NULL);
} else if (k->oop_is_objArray()) {
ObjArrayKlass* oak = ObjArrayKlass::cast(k);
oak->initialize(CHECK_NULL); // make sure class is initialized (matches Classic VM behavior)
result = oak->allocate(length, CHECK_NULL);
} else {
THROW_0(vmSymbols::java_lang_InvalidClassException());
}
return JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) {
vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
oop loader = vfst.method()->method_holder()->class_loader();
if (loader != NULL && !SystemDictionary::is_ext_class_loader(loader)) {
return JNIHandles::make_local(env, loader);
}
}
return NULL;
JVM_END
JVM_ENTRY(jclass, JVM_LoadClass0(JNIEnv *env, jobject receiver,
jclass currClass, jstring currClassName))
JVMWrapper("JVM_LoadClass0");
ResourceMark rm(THREAD);
Handle classname (THREAD, JNIHandles::resolve_non_null(currClassName));
Handle string = java_lang_String::internalize_classname(classname, CHECK_NULL);
const char* str = java_lang_String::as_utf8_string(string());
if (str == NULL || (int)strlen(str) > Symbol::max_length()) {
THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), str);
}
TempNewSymbol name = SymbolTable::new_symbol(str, CHECK_NULL);
Handle curr_klass (THREAD, JNIHandles::resolve(currClass));
oop loader = NULL;
oop protection_domain = NULL;
if (curr_klass.is_null()) {
for (vframeStream vfst(thread);
!vfst.at_end() && loader == NULL;
vfst.next()) {
if (!vfst.method()->is_native()) {
InstanceKlass* holder = vfst.method()->method_holder();
loader = holder->class_loader();
protection_domain = holder->protection_domain();
}
}
} else {
Klass* curr_klass_oop = java_lang_Class::as_Klass(curr_klass());
loader = InstanceKlass::cast(curr_klass_oop)->class_loader();
protection_domain = InstanceKlass::cast(curr_klass_oop)->protection_domain();
}
Handle h_loader(THREAD, loader);
Handle h_prot (THREAD, protection_domain);
jclass result = find_class_from_class_loader(env, name, true, h_loader, h_prot,
false, thread);
if (TraceClassResolution && result != NULL) {
trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
}
return result;
JVM_END
static inline arrayOop check_array(JNIEnv *env, jobject arr, bool type_array_only, TRAPS) {
if (arr == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
oop a = JNIHandles::resolve_non_null(arr);
if (!a->is_array() || (type_array_only && !a->is_typeArray())) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Argument is not an array");
}
return arrayOop(a);
}
JVM_ENTRY(jint, JVM_GetArrayLength(JNIEnv *env, jobject arr))
JVMWrapper("JVM_GetArrayLength");
arrayOop a = check_array(env, arr, false, CHECK_0);
return a->length();
JVM_END
JVM_ENTRY(jobject, JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index))
JVMWrapper("JVM_Array_Get");
JvmtiVMObjectAllocEventCollector oam;
arrayOop a = check_array(env, arr, false, CHECK_NULL);
jvalue value;
BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL);
oop box = Reflection::box(&value, type, CHECK_NULL);
return JNIHandles::make_local(env, box);
JVM_END
JVM_ENTRY(jvalue, JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode))
JVMWrapper("JVM_GetPrimitiveArrayElement");
jvalue value;
value.i = 0; // to initialize value before getting used in CHECK
arrayOop a = check_array(env, arr, true, CHECK_(value));
assert(a->is_typeArray(), "just checking");
BasicType type = Reflection::array_get(&value, a, index, CHECK_(value));
BasicType wide_type = (BasicType) wCode;
if (type != wide_type) {
Reflection::widen(&value, type, wide_type, CHECK_(value));
}
return value;
JVM_END
JVM_ENTRY(void, JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val))
JVMWrapper("JVM_SetArrayElement");
arrayOop a = check_array(env, arr, false, CHECK);
oop box = JNIHandles::resolve(val);
jvalue value;
value.i = 0; // to initialize value before getting used in CHECK
BasicType value_type;
if (a->is_objArray()) {
value_type = Reflection::unbox_for_regular_object(box, &value);
} else {
value_type = Reflection::unbox_for_primitive(box, &value, CHECK);
}
Reflection::array_set(&value, a, index, value_type, CHECK);
JVM_END
JVM_ENTRY(void, JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode))
JVMWrapper("JVM_SetPrimitiveArrayElement");
arrayOop a = check_array(env, arr, true, CHECK);
assert(a->is_typeArray(), "just checking");
BasicType value_type = (BasicType) vCode;
Reflection::array_set(&v, a, index, value_type, CHECK);
JVM_END
JVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length))
JVMWrapper("JVM_NewArray");
JvmtiVMObjectAllocEventCollector oam;
oop element_mirror = JNIHandles::resolve(eltClass);
oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL);
return JNIHandles::make_local(env, result);
JVM_END
JVM_ENTRY(jobject, JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim))
JVMWrapper("JVM_NewMultiArray");
JvmtiVMObjectAllocEventCollector oam;
arrayOop dim_array = check_array(env, dim, true, CHECK_NULL);
oop element_mirror = JNIHandles::resolve(eltClass);
assert(dim_array->is_typeArray(), "just checking");
oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL);
return JNIHandles::make_local(env, result);
JVM_END
JVM_LEAF(jint, JVM_InitializeSocketLibrary())
JVMWrapper("JVM_InitializeSocketLibrary");
return 0;
JVM_END
JVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol))
JVMWrapper("JVM_Socket");
return os::socket(domain, type, protocol);
JVM_END
JVM_LEAF(jint, JVM_SocketClose(jint fd))
JVMWrapper2("JVM_SocketClose (0x%x)", fd);
return os::socket_close(fd);
JVM_END
JVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto))
JVMWrapper2("JVM_SocketShutdown (0x%x)", fd);
return os::socket_shutdown(fd, howto);
JVM_END
JVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags))
JVMWrapper2("JVM_Recv (0x%x)", fd);
return os::recv(fd, buf, (size_t)nBytes, (uint)flags);
JVM_END
JVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags))
JVMWrapper2("JVM_Send (0x%x)", fd);
return os::send(fd, buf, (size_t)nBytes, (uint)flags);
JVM_END
JVM_LEAF(jint, JVM_Timeout(int fd, long timeout))
JVMWrapper2("JVM_Timeout (0x%x)", fd);
return os::timeout(fd, timeout);
JVM_END
JVM_LEAF(jint, JVM_Listen(jint fd, jint count))
JVMWrapper2("JVM_Listen (0x%x)", fd);
return os::listen(fd, count);
JVM_END
JVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len))
JVMWrapper2("JVM_Connect (0x%x)", fd);
return os::connect(fd, him, (socklen_t)len);
JVM_END
JVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len))
JVMWrapper2("JVM_Bind (0x%x)", fd);
return os::bind(fd, him, (socklen_t)len);
JVM_END
JVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len))
JVMWrapper2("JVM_Accept (0x%x)", fd);
socklen_t socklen = (socklen_t)(*len);
jint result = os::accept(fd, him, &socklen);
return result;
JVM_END
JVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen))
JVMWrapper2("JVM_RecvFrom (0x%x)", fd);
socklen_t socklen = (socklen_t)(*fromlen);
jint result = os::recvfrom(fd, buf, (size_t)nBytes, (uint)flags, from, &socklen);
return result;
JVM_END
JVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len))
JVMWrapper2("JVM_GetSockName (0x%x)", fd);
socklen_t socklen = (socklen_t)(*len);
jint result = os::get_sock_name(fd, him, &socklen);
return result;
JVM_END
JVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen))
JVMWrapper2("JVM_SendTo (0x%x)", fd);
return os::sendto(fd, buf, (size_t)len, (uint)flags, to, (socklen_t)tolen);
JVM_END
JVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes))
JVMWrapper2("JVM_SocketAvailable (0x%x)", fd);
return os::socket_available(fd, pbytes);
JVM_END
JVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen))
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
socklen_t socklen = (socklen_t)(*optlen);
jint result = os::get_sock_opt(fd, level, optname, optval, &socklen);
return result;
JVM_END
JVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen))
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
return os::set_sock_opt(fd, level, optname, optval, (socklen_t)optlen);
JVM_END
JVM_LEAF(int, JVM_GetHostName(char* name, int namelen))
JVMWrapper("JVM_GetHostName");
return os::get_host_name(name, namelen);
JVM_END
JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
JVMWrapper2("JVM_LoadLibrary (%s)", name);
char ebuf[1024];
void *load_result;
{
ThreadToNativeFromVM ttnfvm(thread);
load_result = os::dll_load(name, ebuf, sizeof ebuf);
}
if (load_result == NULL) {
char msg[1024];
jio_snprintf(msg, sizeof msg, "%s: %s", name, ebuf);
Handle h_exception =
Exceptions::new_exception(thread,
vmSymbols::java_lang_UnsatisfiedLinkError(),
msg, Exceptions::unsafe_to_utf8);
THROW_HANDLE_0(h_exception);
}
return load_result;
JVM_END
JVM_LEAF(void, JVM_UnloadLibrary(void* handle))
JVMWrapper("JVM_UnloadLibrary");
os::dll_unload(handle);
JVM_END
JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name))
JVMWrapper2("JVM_FindLibraryEntry (%s)", name);
return os::dll_lookup(handle, name);
JVM_END
JVM_LEAF(jboolean, JVM_IsNaN(jdouble a))
JVMWrapper("JVM_IsNaN");
return g_isnan(a);
JVM_END
JVM_LEAF(jboolean, JVM_IsSupportedJNIVersion(jint version))
JVMWrapper2("JVM_IsSupportedJNIVersion (%d)", version);
return Threads::is_supported_jni_version_including_1_1(version);
JVM_END
JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str))
JVMWrapper("JVM_InternString");
JvmtiVMObjectAllocEventCollector oam;
if (str == NULL) return NULL;
oop string = JNIHandles::resolve_non_null(str);
oop result = StringTable::intern(string, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result);
JVM_END
JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void) {
VM_Exit::block_if_vm_exited();
JVMWrapper("JVM_RawMonitorCreate");
return new Mutex(Mutex::native, "JVM_RawMonitorCreate");
}
JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon) {
VM_Exit::block_if_vm_exited();
JVMWrapper("JVM_RawMonitorDestroy");
delete ((Mutex*) mon);
}
JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon) {
VM_Exit::block_if_vm_exited();
JVMWrapper("JVM_RawMonitorEnter");
((Mutex*) mon)->jvm_raw_lock();
return 0;
}
JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) {
VM_Exit::block_if_vm_exited();
JVMWrapper("JVM_RawMonitorExit");
((Mutex*) mon)->jvm_raw_unlock();
}
typedef jfloat (JNICALL *IntBitsToFloatFn )(JNIEnv* env, jclass cb, jint value);
typedef jdouble (JNICALL *LongBitsToDoubleFn)(JNIEnv* env, jclass cb, jlong value);
typedef jint (JNICALL *FloatToIntBitsFn )(JNIEnv* env, jclass cb, jfloat value);
typedef jlong (JNICALL *DoubleToLongBitsFn)(JNIEnv* env, jclass cb, jdouble value);
static IntBitsToFloatFn int_bits_to_float_fn = NULL;
static LongBitsToDoubleFn long_bits_to_double_fn = NULL;
static FloatToIntBitsFn float_to_int_bits_fn = NULL;
static DoubleToLongBitsFn double_to_long_bits_fn = NULL;
void initialize_converter_functions() {
if (JDK_Version::is_gte_jdk14x_version()) {
return;
}
assert(
int_bits_to_float_fn == NULL &&
long_bits_to_double_fn == NULL &&
float_to_int_bits_fn == NULL &&
double_to_long_bits_fn == NULL ,
"initialization done twice"
);
int_bits_to_float_fn = CAST_TO_FN_PTR(IntBitsToFloatFn , NativeLookup::base_library_lookup("java/lang/Float" , "intBitsToFloat" , "(I)F"));
long_bits_to_double_fn = CAST_TO_FN_PTR(LongBitsToDoubleFn, NativeLookup::base_library_lookup("java/lang/Double", "longBitsToDouble", "(J)D"));
float_to_int_bits_fn = CAST_TO_FN_PTR(FloatToIntBitsFn , NativeLookup::base_library_lookup("java/lang/Float" , "floatToIntBits" , "(F)I"));
double_to_long_bits_fn = CAST_TO_FN_PTR(DoubleToLongBitsFn, NativeLookup::base_library_lookup("java/lang/Double", "doubleToLongBits", "(D)J"));
assert(
int_bits_to_float_fn != NULL &&
long_bits_to_double_fn != NULL &&
float_to_int_bits_fn != NULL &&
double_to_long_bits_fn != NULL ,
"initialization failed"
);
}
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init,
Handle loader, Handle protection_domain,
jboolean throwError, TRAPS) {
Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL);
KlassHandle klass_handle(THREAD, klass);
if (init && klass_handle->oop_is_instance()) {
klass_handle->initialize(CHECK_NULL);
}
return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
}
#ifndef PRODUCT
extern "C" {
JNIEXPORT jboolean JNICALL JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get);
JNIEXPORT jboolean JNICALL JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get);
JNIEXPORT void JNICALL JVM_VMBreakPoint(JNIEnv *env, jobject obj);
}
JVM_LEAF(jboolean, JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get))
JVMWrapper("JVM_AccessBoolVMFlag");
return is_get ? CommandLineFlags::boolAt((char*) name, (bool*) value) : CommandLineFlags::boolAtPut((char*) name, (bool*) value, Flag::INTERNAL);
JVM_END
JVM_LEAF(jboolean, JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get))
JVMWrapper("JVM_AccessVMIntFlag");
intx v;
jboolean result = is_get ? CommandLineFlags::intxAt((char*) name, &v) : CommandLineFlags::intxAtPut((char*) name, &v, Flag::INTERNAL);
return result;
JVM_END
JVM_ENTRY(void, JVM_VMBreakPoint(JNIEnv *env, jobject obj))
JVMWrapper("JVM_VMBreakPoint");
oop the_obj = JNIHandles::resolve(obj);
BREAKPOINT;
JVM_END
#endif
JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0))
JVMWrapper("JVM_InvokeMethod");
Handle method_handle;
if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) {
method_handle = Handle(THREAD, JNIHandles::resolve(method));
Handle receiver(THREAD, JNIHandles::resolve(obj));
objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
jobject res = JNIHandles::make_local(env, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
oop ret_type = java_lang_reflect_Method::return_type(method_handle());
assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!");
if (java_lang_Class::is_primitive(ret_type)) {
JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);
}
}
return res;
} else {
THROW_0(vmSymbols::java_lang_StackOverflowError());
}
JVM_END
JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0))
JVMWrapper("JVM_NewInstanceFromConstructor");
oop constructor_mirror = JNIHandles::resolve(c);
objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
jobject res = JNIHandles::make_local(env, result);
if (JvmtiExport::should_post_vm_object_alloc()) {
JvmtiExport::post_vm_object_alloc(JavaThread::current(), result);
}
return res;
JVM_END
JVM_LEAF(jboolean, JVM_SupportsCX8())
JVMWrapper("JVM_SupportsCX8");
return VM_Version::supports_cx8();
JVM_END
JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal))
JVMWrapper("JVM_CX8Field");
jlong res;
oop o = JNIHandles::resolve(obj);
intptr_t fldOffs = jfieldIDWorkaround::from_instance_jfieldID(o->klass(), fid);
volatile jlong* addr = (volatile jlong*)((address)o + fldOffs);
assert(VM_Version::supports_cx8(), "cx8 not supported");
res = Atomic::cmpxchg(newVal, addr, oldVal);
return res == oldVal;
JVM_END
JVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env))
JVMWrapper("JVM_DTraceGetVersion");
return (jint)JVM_TRACING_DTRACE_VERSION;
JVM_END
JVM_ENTRY(jlong,JVM_DTraceActivate(
JNIEnv* env, jint version, jstring module_name, jint providers_count,
JVM_DTraceProvider* providers))
JVMWrapper("JVM_DTraceActivate");
return DTraceJSDT::activate(
version, module_name, providers_count, providers, THREAD);
JVM_END
JVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method))
JVMWrapper("JVM_DTraceIsProbeEnabled");
return DTraceJSDT::is_probe_enabled(method);
JVM_END
JVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle))
JVMWrapper("JVM_DTraceDispose");
DTraceJSDT::dispose(handle);
JVM_END
JVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env))
JVMWrapper("JVM_DTraceIsSupported");
return DTraceJSDT::is_supported();
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy))
ResourceMark rm(THREAD);
ThreadsListEnumerator tle(THREAD, false, false);
JvmtiVMObjectAllocEventCollector oam;
int num_threads = tle.num_threads();
objArrayOop r = oopFactory::new_objArray(SystemDictionary::Thread_klass(), num_threads, CHECK_NULL);
objArrayHandle threads_ah(THREAD, r);
for (int i = 0; i < num_threads; i++) {
Handle h = tle.get_threadObj(i);
threads_ah->obj_at_put(i, h());
}
return (jobjectArray) JNIHandles::make_local(env, threads_ah());
JVM_END
JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads))
JVMWrapper("JVM_DumpThreads");
JvmtiVMObjectAllocEventCollector oam;
if (threads == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), 0);
}
objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(threads));
objArrayHandle ah(THREAD, a);
int num_threads = ah->length();
if (num_threads == 0) {
THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);
}
Klass* k = ObjArrayKlass::cast(ah->klass())->element_klass();
if (k != SystemDictionary::Thread_klass()) {
THROW_(vmSymbols::java_lang_IllegalArgumentException(), 0);
}
ResourceMark rm(THREAD);
GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
for (int i = 0; i < num_threads; i++) {
oop thread_obj = ah->obj_at(i);
instanceHandle h(THREAD, (instanceOop) thread_obj);
thread_handle_array->append(h);
}
Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, stacktraces());
JVM_END
JVM_ENTRY_NO_ENV(void*, JVM_GetManagement(jint version))
return Management::get_jmm_interface(version);
JVM_END
JVM_ENTRY(jobject, JVM_InitAgentProperties(JNIEnv *env, jobject properties))
JVMWrapper("JVM_InitAgentProperties");
ResourceMark rm;
Handle props(THREAD, JNIHandles::resolve_non_null(properties));
PUTPROP(props, "sun.java.command", Arguments::java_command());
PUTPROP(props, "sun.jvm.flags", Arguments::jvm_flags());
PUTPROP(props, "sun.jvm.args", Arguments::jvm_args());
return properties;
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass))
{
JVMWrapper("JVM_GetEnclosingMethodInfo");
JvmtiVMObjectAllocEventCollector oam;
if (ofClass == NULL) {
return NULL;
}
Handle mirror(THREAD, JNIHandles::resolve_non_null(ofClass));
if (java_lang_Class::is_primitive(mirror())) {
return NULL;
}
Klass* k = java_lang_Class::as_Klass(mirror());
if (!k->oop_is_instance()) {
return NULL;
}
instanceKlassHandle ik_h(THREAD, k);
int encl_method_class_idx = ik_h->enclosing_method_class_index();
if (encl_method_class_idx == 0) {
return NULL;
}
objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL);
objArrayHandle dest(THREAD, dest_o);
Klass* enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL);
dest->obj_at_put(0, enc_k->java_mirror());
int encl_method_method_idx = ik_h->enclosing_method_method_index();
if (encl_method_method_idx != 0) {
Symbol* sym = ik_h->constants()->symbol_at(
extract_low_short_from_int(
ik_h->constants()->name_and_type_at(encl_method_method_idx)));
Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
dest->obj_at_put(1, str());
sym = ik_h->constants()->symbol_at(
extract_high_short_from_int(
ik_h->constants()->name_and_type_at(encl_method_method_idx)));
str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
dest->obj_at_put(2, str());
}
return (jobjectArray) JNIHandles::make_local(dest());
}
JVM_END
JVM_ENTRY(jintArray, JVM_GetThreadStateValues(JNIEnv* env,
jint javaThreadState))
{
typeArrayHandle values_h;
switch (javaThreadState) {
case JAVA_THREAD_STATE_NEW : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::NEW);
break;
}
case JAVA_THREAD_STATE_RUNNABLE : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::RUNNABLE);
break;
}
case JAVA_THREAD_STATE_BLOCKED : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER);
break;
}
case JAVA_THREAD_STATE_WAITING : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::IN_OBJECT_WAIT);
values_h->int_at_put(1, java_lang_Thread::PARKED);
break;
}
case JAVA_THREAD_STATE_TIMED_WAITING : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 3, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::SLEEPING);
values_h->int_at_put(1, java_lang_Thread::IN_OBJECT_WAIT_TIMED);
values_h->int_at_put(2, java_lang_Thread::PARKED_TIMED);
break;
}
case JAVA_THREAD_STATE_TERMINATED : {
typeArrayOop r = oopFactory::new_typeArray(T_INT, 1, CHECK_NULL);
values_h = typeArrayHandle(THREAD, r);
values_h->int_at_put(0, java_lang_Thread::TERMINATED);
break;
}
default:
return NULL;
}
return (jintArray) JNIHandles::make_local(env, values_h());
}
JVM_END
JVM_ENTRY(jobjectArray, JVM_GetThreadStateNames(JNIEnv* env,
jint javaThreadState,
jintArray values))
{
ResourceMark rm;
if (values == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), 0);
}
typeArrayOop v = typeArrayOop(JNIHandles::resolve_non_null(values));
typeArrayHandle values_h(THREAD, v);
objArrayHandle names_h;
switch (javaThreadState) {
case JAVA_THREAD_STATE_NEW : {
assert(values_h->length() == 1 &&
values_h->int_at(0) == java_lang_Thread::NEW,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1, /* only 1 substate */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name = java_lang_String::create_from_str("NEW", CHECK_NULL);
names_h->obj_at_put(0, name());
break;
}
case JAVA_THREAD_STATE_RUNNABLE : {
assert(values_h->length() == 1 &&
values_h->int_at(0) == java_lang_Thread::RUNNABLE,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1, /* only 1 substate */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name = java_lang_String::create_from_str("RUNNABLE", CHECK_NULL);
names_h->obj_at_put(0, name());
break;
}
case JAVA_THREAD_STATE_BLOCKED : {
assert(values_h->length() == 1 &&
values_h->int_at(0) == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1, /* only 1 substate */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name = java_lang_String::create_from_str("BLOCKED", CHECK_NULL);
names_h->obj_at_put(0, name());
break;
}
case JAVA_THREAD_STATE_WAITING : {
assert(values_h->length() == 2 &&
values_h->int_at(0) == java_lang_Thread::IN_OBJECT_WAIT &&
values_h->int_at(1) == java_lang_Thread::PARKED,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
2, /* number of substates */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name0 = java_lang_String::create_from_str("WAITING.OBJECT_WAIT",
CHECK_NULL);
Handle name1 = java_lang_String::create_from_str("WAITING.PARKED",
CHECK_NULL);
names_h->obj_at_put(0, name0());
names_h->obj_at_put(1, name1());
break;
}
case JAVA_THREAD_STATE_TIMED_WAITING : {
assert(values_h->length() == 3 &&
values_h->int_at(0) == java_lang_Thread::SLEEPING &&
values_h->int_at(1) == java_lang_Thread::IN_OBJECT_WAIT_TIMED &&
values_h->int_at(2) == java_lang_Thread::PARKED_TIMED,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
3, /* number of substates */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name0 = java_lang_String::create_from_str("TIMED_WAITING.SLEEPING",
CHECK_NULL);
Handle name1 = java_lang_String::create_from_str("TIMED_WAITING.OBJECT_WAIT",
CHECK_NULL);
Handle name2 = java_lang_String::create_from_str("TIMED_WAITING.PARKED",
CHECK_NULL);
names_h->obj_at_put(0, name0());
names_h->obj_at_put(1, name1());
names_h->obj_at_put(2, name2());
break;
}
case JAVA_THREAD_STATE_TERMINATED : {
assert(values_h->length() == 1 &&
values_h->int_at(0) == java_lang_Thread::TERMINATED,
"Invalid threadStatus value");
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
1, /* only 1 substate */
CHECK_NULL);
names_h = objArrayHandle(THREAD, r);
Handle name = java_lang_String::create_from_str("TERMINATED", CHECK_NULL);
names_h->obj_at_put(0, name());
break;
}
default:
return NULL;
}
return (jobjectArray) JNIHandles::make_local(env, names_h());
}
JVM_END
JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size))
{
memset(info, 0, info_size);
info->jvm_version = Abstract_VM_Version::jvm_version();
info->update_version = 0; /* 0 in HotSpot Express VM */
info->special_update_version = 0; /* 0 in HotSpot Express VM */
info->is_attachable = AttachListener::is_attach_supported();
}
JVM_END
C:\hotspot-69087d08d473\src\share\vm/prims/jvm.h
#ifndef SHARE_VM_PRIMS_JVM_H
#define SHARE_VM_PRIMS_JVM_H
#include "prims/jni.h"
#ifdef TARGET_OS_FAMILY_linux
# include "jvm_linux.h"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "jvm_solaris.h"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "jvm_windows.h"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "jvm_aix.h"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "jvm_bsd.h"
#endif
#ifndef _JAVASOFT_JVM_H_
#define _JAVASOFT_JVM_H_
#ifdef __cplusplus
extern "C" {
#endif
#define JVM_INTERFACE_VERSION 4
JNIEXPORT jobjectArray JNICALL
JVM_GetMethodParameters(JNIEnv *env, jobject method);
JNIEXPORT jint JNICALL
JVM_GetInterfaceVersion(void);
PART 1: Functions for Native Libraries
JNIEXPORT jint JNICALL
JVM_IHashCode(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL
JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms);
JNIEXPORT void JNICALL
JVM_MonitorNotify(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL
JVM_MonitorNotifyAll(JNIEnv *env, jobject obj);
JNIEXPORT jobject JNICALL
JVM_Clone(JNIEnv *env, jobject obj);
JNIEXPORT jstring JNICALL
JVM_InternString(JNIEnv *env, jstring str);
JNIEXPORT jlong JNICALL
JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
JNIEXPORT jlong JNICALL
JVM_NanoTime(JNIEnv *env, jclass ignored);
JNIEXPORT void JNICALL
JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
jobject dst, jint dst_pos, jint length);
JNIEXPORT jobject JNICALL
JVM_InitProperties(JNIEnv *env, jobject p);
JNIEXPORT void JNICALL
JVM_OnExit(void (*func)(void));
JNIEXPORT void JNICALL
JVM_CopySwapMemory(JNIEnv *env, jobject srcObj, jlong srcOffset,
jobject dstObj, jlong dstOffset, jlong size,
jlong elemSize);
JNIEXPORT void JNICALL
JVM_Exit(jint code);
JNIEXPORT void JNICALL
JVM_BeforeHalt();
JNIEXPORT void JNICALL
JVM_Halt(jint code);
JNIEXPORT void JNICALL
JVM_GC(void);
JNIEXPORT jlong JNICALL
JVM_MaxObjectInspectionAge(void);
JNIEXPORT void JNICALL
JVM_TraceInstructions(jboolean on);
JNIEXPORT void JNICALL
JVM_TraceMethodCalls(jboolean on);
JNIEXPORT jlong JNICALL
JVM_TotalMemory(void);
JNIEXPORT jlong JNICALL
JVM_FreeMemory(void);
JNIEXPORT jlong JNICALL
JVM_MaxMemory(void);
JNIEXPORT jint JNICALL
JVM_ActiveProcessorCount(void);
JNIEXPORT jboolean JNICALL
JVM_IsUseContainerSupport(void);
JNIEXPORT void * JNICALL
JVM_LoadLibrary(const char *name);
JNIEXPORT void JNICALL
JVM_UnloadLibrary(void * handle);
JNIEXPORT void * JNICALL
JVM_FindLibraryEntry(void *handle, const char *name);
JNIEXPORT jboolean JNICALL
JVM_IsSupportedJNIVersion(jint version);
JNIEXPORT jboolean JNICALL
JVM_IsNaN(jdouble d);
JNIEXPORT void JNICALL
JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
JNIEXPORT jint JNICALL
JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable);
JNIEXPORT jobject JNICALL
JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index);
JNIEXPORT void JNICALL
JVM_InitializeCompiler (JNIEnv *env, jclass compCls);
JNIEXPORT jboolean JNICALL
JVM_IsSilentCompiler(JNIEnv *env, jclass compCls);
JNIEXPORT jboolean JNICALL
JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls);
JNIEXPORT jboolean JNICALL
JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname);
JNIEXPORT jobject JNICALL
JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg);
JNIEXPORT void JNICALL
JVM_EnableCompiler(JNIEnv *env, jclass compCls);
JNIEXPORT void JNICALL
JVM_DisableCompiler(JNIEnv *env, jclass compCls);
JNIEXPORT void JNICALL
JVM_StartThread(JNIEnv *env, jobject thread);
JNIEXPORT void JNICALL
JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
JNIEXPORT jboolean JNICALL
JVM_IsThreadAlive(JNIEnv *env, jobject thread);
JNIEXPORT void JNICALL
JVM_SuspendThread(JNIEnv *env, jobject thread);
JNIEXPORT void JNICALL
JVM_ResumeThread(JNIEnv *env, jobject thread);
JNIEXPORT void JNICALL
JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
JNIEXPORT void JNICALL
JVM_Yield(JNIEnv *env, jclass threadClass);
JNIEXPORT void JNICALL
JVM_Sleep(JNIEnv *env, jclass threadClass, jlong millis);
JNIEXPORT jobject JNICALL
JVM_CurrentThread(JNIEnv *env, jclass threadClass);
JNIEXPORT jint JNICALL
JVM_CountStackFrames(JNIEnv *env, jobject thread);
JNIEXPORT void JNICALL
JVM_Interrupt(JNIEnv *env, jobject thread);
JNIEXPORT jboolean JNICALL
JVM_IsInterrupted(JNIEnv *env, jobject thread, jboolean clearInterrupted);
JNIEXPORT jboolean JNICALL
JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj);
JNIEXPORT void JNICALL
JVM_DumpAllStacks(JNIEnv *env, jclass unused);
JNIEXPORT jobjectArray JNICALL
JVM_GetAllThreads(JNIEnv *env, jclass dummy);
JNIEXPORT void JNICALL
JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name);
JNIEXPORT jobjectArray JNICALL
JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
JNIEXPORT jclass JNICALL
JVM_CurrentLoadedClass(JNIEnv *env);
JNIEXPORT jobject JNICALL
JVM_CurrentClassLoader(JNIEnv *env);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassContext(JNIEnv *env);
JNIEXPORT jint JNICALL
JVM_ClassDepth(JNIEnv *env, jstring name);
JNIEXPORT jint JNICALL
JVM_ClassLoaderDepth(JNIEnv *env);
JNIEXPORT jstring JNICALL
JVM_GetSystemPackage(JNIEnv *env, jstring name);
JNIEXPORT jobjectArray JNICALL
JVM_GetSystemPackages(JNIEnv *env);
JNIEXPORT jobject JNICALL
JVM_AllocateNewObject(JNIEnv *env, jobject obj, jclass currClass,
jclass initClass);
JNIEXPORT jobject JNICALL
JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass,
jint length);
JNIEXPORT jobject JNICALL
JVM_LatestUserDefinedLoader(JNIEnv *env);
JNIEXPORT jclass JNICALL
JVM_LoadClass0(JNIEnv *env, jobject obj, jclass currClass,
jstring currClassName);
JNIEXPORT jint JNICALL
JVM_GetArrayLength(JNIEnv *env, jobject arr);
JNIEXPORT jobject JNICALL
JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index);
JNIEXPORT jvalue JNICALL
JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode);
JNIEXPORT void JNICALL
JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val);
JNIEXPORT void JNICALL
JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
unsigned char vCode);
JNIEXPORT jobject JNICALL
JVM_NewArray(JNIEnv *env, jclass eltClass, jint length);
JNIEXPORT jobject JNICALL
JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
#define JVM_CALLER_DEPTH -1
JNIEXPORT jclass JNICALL
JVM_GetCallerClass(JNIEnv *env, int n);
JNIEXPORT jclass JNICALL
JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
JNIEXPORT void JNICALL
JVM_ResolveClass(JNIEnv *env, jclass cls);
JNIEXPORT jclass JNICALL
JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
jobject loader, jboolean throwError);
JNIEXPORT jclass JNICALL
JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
JNIEXPORT jclass JNICALL
JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init,
jobject loader, jclass caller);
JNIEXPORT jclass JNICALL
JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
jclass from);
JNIEXPORT jclass JNICALL
JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name);
JNIEXPORT jclass JNICALL
JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
jsize len, jobject pd);
JNIEXPORT jclass JNICALL
JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len, jobject pd,
const char *source);
JNIEXPORT jclass JNICALL
JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
jobject loader, const jbyte *buf,
jsize len, jobject pd, const char *source,
jboolean verify);
JNIEXPORT jstring JNICALL
JVM_GetClassName(JNIEnv *env, jclass cls);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassInterfaces(JNIEnv *env, jclass cls);
JNIEXPORT jobject JNICALL
JVM_GetClassLoader(JNIEnv *env, jclass cls);
JNIEXPORT jboolean JNICALL
JVM_IsInterface(JNIEnv *env, jclass cls);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassSigners(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL
JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers);
JNIEXPORT jobject JNICALL
JVM_GetProtectionDomain(JNIEnv *env, jclass cls);
JNIEXPORT jboolean JNICALL
JVM_IsArrayClass(JNIEnv *env, jclass cls);
JNIEXPORT jboolean JNICALL
JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
JNIEXPORT jclass JNICALL
JVM_GetComponentType(JNIEnv *env, jclass cls);
JNIEXPORT jint JNICALL
JVM_GetClassModifiers(JNIEnv *env, jclass cls);
JNIEXPORT jobjectArray JNICALL
JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass);
JNIEXPORT jclass JNICALL
JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass);
JNIEXPORT jstring JNICALL
JVM_GetClassSignature(JNIEnv *env, jclass cls);
JNIEXPORT jbyteArray JNICALL
JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
JNIEXPORT jbyteArray JNICALL
JVM_GetFieldAnnotations(JNIEnv *env, jobject field);
JNIEXPORT jbyteArray JNICALL
JVM_GetMethodAnnotations(JNIEnv *env, jobject method);
JNIEXPORT jbyteArray JNICALL
JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method);
JNIEXPORT jbyteArray JNICALL
JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method);
JNIEXPORT jbyteArray JNICALL
JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
JNIEXPORT jbyteArray JNICALL
JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field);
JNIEXPORT jbyteArray JNICALL
JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
This returns the access flags for the class as specified in the
class file rather than searching the InnerClasses attribute (if
present) to find the source-level access flags. Only the values of
the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
valid. */
JNIEXPORT jint JNICALL
JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
JNIEXPORT jobject JNICALL
JVM_GetClassConstantPool(JNIEnv *env, jclass cls);
JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
(JNIEnv *env, jobject obj, jobject unused);
JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
(JNIEnv *env, jobject obj, jobject unused, jint index);
JNIEXPORT jobject JNICALL
JVM_DoPrivileged(JNIEnv *env, jclass cls,
jobject action, jobject context, jboolean wrapException);
JNIEXPORT jobject JNICALL
JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls);
JNIEXPORT jobject JNICALL
JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls);
JNIEXPORT void * JNICALL
JVM_RegisterSignal(jint sig, void *handler);
JNIEXPORT jboolean JNICALL
JVM_RaiseSignal(jint sig);
JNIEXPORT jint JNICALL
JVM_FindSignal(const char *name);
JNIEXPORT jboolean JNICALL
JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls);
JNIEXPORT jobject JNICALL
JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
JNIEXPORT jboolean JNICALL
JVM_SupportsCX8(void);
JNIEXPORT jboolean JNICALL
JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fldID, jlong oldVal, jlong newVal);
#define JVM_TRACING_DTRACE_VERSION 1
typedef struct {
jmethodID method;
jstring function;
jstring name;
void* reserved[4]; // for future use
} JVM_DTraceProbe;
typedef struct {
jint nameStability;
jint dataStability;
jint dependencyClass;
} JVM_DTraceInterfaceAttributes;
typedef struct {
jstring name;
JVM_DTraceProbe* probes;
jint probe_count;
JVM_DTraceInterfaceAttributes providerAttributes;
JVM_DTraceInterfaceAttributes moduleAttributes;
JVM_DTraceInterfaceAttributes functionAttributes;
JVM_DTraceInterfaceAttributes nameAttributes;
JVM_DTraceInterfaceAttributes argsAttributes;
void* reserved[4]; // for future use
} JVM_DTraceProvider;
JNIEXPORT jint JNICALL
JVM_DTraceGetVersion(JNIEnv* env);
JNIEXPORT jlong JNICALL
JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name,
jint providers_count, JVM_DTraceProvider* providers);
JNIEXPORT jboolean JNICALL
JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method);
JNIEXPORT void JNICALL
JVM_DTraceDispose(JNIEnv* env, jlong handle);
JNIEXPORT jboolean JNICALL
JVM_DTraceIsSupported(JNIEnv* env);
PART 2: Support for the Verifier and Class File Format Checker
JNIEXPORT const char * JNICALL
JVM_GetClassNameUTF(JNIEnv *env, jclass cb);
JNIEXPORT void JNICALL
JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types);
JNIEXPORT jint JNICALL
JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb);
JNIEXPORT jint JNICALL
JVM_GetClassFieldsCount(JNIEnv *env, jclass cb);
JNIEXPORT jint JNICALL
JVM_GetClassMethodsCount(JNIEnv *env, jclass cb);
JNIEXPORT void JNICALL
JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
unsigned short *exceptions);
JNIEXPORT jint JNICALL
JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index);
JNIEXPORT void JNICALL
JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
unsigned char *code);
JNIEXPORT jint JNICALL
JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index);
typedef struct {
jint start_pc;
jint end_pc;
jint handler_pc;
jint catchType;
} JVM_ExceptionTableEntryType;
JNIEXPORT void JNICALL
JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
jint entry_index,
JVM_ExceptionTableEntryType *entry);
JNIEXPORT jint JNICALL
JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index);
JNIEXPORT jint JNICALL
JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index);
JNIEXPORT jint JNICALL
JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index);
JNIEXPORT jint JNICALL
JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index);
JNIEXPORT jint JNICALL
JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index);
JNIEXPORT jint JNICALL
JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index);
JNIEXPORT jboolean JNICALL
JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
JNIEXPORT jboolean JNICALL
JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index);
JNIEXPORT const char * JNICALL
JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT const char * JNICALL
JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index);
JNIEXPORT jint JNICALL
JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
JNIEXPORT jint JNICALL
JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
JNIEXPORT void JNICALL
JVM_ReleaseUTF(const char *utf);
JNIEXPORT jboolean JNICALL
JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
#define JVM_ACC_PUBLIC 0x0001 /* visible to everyone */
#define JVM_ACC_PRIVATE 0x0002 /* visible only to the defining class */
#define JVM_ACC_PROTECTED 0x0004 /* visible to subclasses */
#define JVM_ACC_STATIC 0x0008 /* instance variable is static */
#define JVM_ACC_FINAL 0x0010 /* no further subclassing, overriding */
#define JVM_ACC_SYNCHRONIZED 0x0020 /* wrap method call in monitor lock */
#define JVM_ACC_SUPER 0x0020 /* funky handling of invokespecial */
#define JVM_ACC_VOLATILE 0x0040 /* can not cache in registers */
#define JVM_ACC_BRIDGE 0x0040 /* bridge method generated by compiler */
#define JVM_ACC_TRANSIENT 0x0080 /* not persistent */
#define JVM_ACC_VARARGS 0x0080 /* method declared with variable number of args */
#define JVM_ACC_NATIVE 0x0100 /* implemented in C */
#define JVM_ACC_INTERFACE 0x0200 /* class is an interface */
#define JVM_ACC_ABSTRACT 0x0400 /* no definition provided */
#define JVM_ACC_STRICT 0x0800 /* strict floating point */
#define JVM_ACC_SYNTHETIC 0x1000 /* compiler-generated class, method or field */
#define JVM_ACC_ANNOTATION 0x2000 /* annotation type */
#define JVM_ACC_ENUM 0x4000 /* field is declared as element of enum */
#define JVM_ACC_PUBLIC_BIT 0
#define JVM_ACC_PRIVATE_BIT 1
#define JVM_ACC_PROTECTED_BIT 2
#define JVM_ACC_STATIC_BIT 3
#define JVM_ACC_FINAL_BIT 4
#define JVM_ACC_SYNCHRONIZED_BIT 5
#define JVM_ACC_SUPER_BIT 5
#define JVM_ACC_VOLATILE_BIT 6
#define JVM_ACC_BRIDGE_BIT 6
#define JVM_ACC_TRANSIENT_BIT 7
#define JVM_ACC_VARARGS_BIT 7
#define JVM_ACC_NATIVE_BIT 8
#define JVM_ACC_INTERFACE_BIT 9
#define JVM_ACC_ABSTRACT_BIT 10
#define JVM_ACC_STRICT_BIT 11
#define JVM_ACC_SYNTHETIC_BIT 12
#define JVM_ACC_ANNOTATION_BIT 13
#define JVM_ACC_ENUM_BIT 14
enum {
JVM_CONSTANT_Utf8 = 1,
JVM_CONSTANT_Unicode, /* unused */
JVM_CONSTANT_Integer,
JVM_CONSTANT_Float,
JVM_CONSTANT_Long,
JVM_CONSTANT_Double,
JVM_CONSTANT_Class,
JVM_CONSTANT_String,
JVM_CONSTANT_Fieldref,
JVM_CONSTANT_Methodref,
JVM_CONSTANT_InterfaceMethodref,
JVM_CONSTANT_NameAndType,
JVM_CONSTANT_MethodHandle = 15, // JSR 292
JVM_CONSTANT_MethodType = 16, // JSR 292
JVM_CONSTANT_InvokeDynamic = 18, // JSR 292
JVM_CONSTANT_ExternalMax = 18 // Last tag found in classfiles
};
enum {
JVM_REF_getField = 1,
JVM_REF_getStatic = 2,
JVM_REF_putField = 3,
JVM_REF_putStatic = 4,
JVM_REF_invokeVirtual = 5,
JVM_REF_invokeStatic = 6,
JVM_REF_invokeSpecial = 7,
JVM_REF_newInvokeSpecial = 8,
JVM_REF_invokeInterface = 9
};
#define JVM_T_BOOLEAN 4
#define JVM_T_CHAR 5
#define JVM_T_FLOAT 6
#define JVM_T_DOUBLE 7
#define JVM_T_BYTE 8
#define JVM_T_SHORT 9
#define JVM_T_INT 10
#define JVM_T_LONG 11
#define JVM_SIGNATURE_ARRAY '['
#define JVM_SIGNATURE_BYTE 'B'
#define JVM_SIGNATURE_CHAR 'C'
#define JVM_SIGNATURE_CLASS 'L'
#define JVM_SIGNATURE_ENDCLASS ';'
#define JVM_SIGNATURE_ENUM 'E'
#define JVM_SIGNATURE_FLOAT 'F'
#define JVM_SIGNATURE_DOUBLE 'D'
#define JVM_SIGNATURE_FUNC '('
#define JVM_SIGNATURE_ENDFUNC ')'
#define JVM_SIGNATURE_INT 'I'
#define JVM_SIGNATURE_LONG 'J'
#define JVM_SIGNATURE_SHORT 'S'
#define JVM_SIGNATURE_VOID 'V'
#define JVM_SIGNATURE_BOOLEAN 'Z'
typedef jboolean (*verifier_fn_t)(JNIEnv *env,
jclass cb,
char * msg_buf,
jint buf_len);
typedef struct {
unsigned long code; /* byte code */
unsigned long excs; /* exceptions */
unsigned long etab; /* catch table */
unsigned long lnum; /* line number */
unsigned long lvar; /* local vars */
} method_size_info;
typedef struct {
unsigned int constants; /* constant pool */
unsigned int fields;
unsigned int methods;
unsigned int interfaces;
unsigned int fields2; /* number of static 2-word fields */
unsigned int innerclasses; /* # of records in InnerClasses attr */
method_size_info clinit; /* memory used in clinit */
method_size_info main; /* used everywhere else */
} class_size_info;
typedef jstring (*to_java_string_fn_t)(JNIEnv *env, char *str);
typedef char *(*to_c_string_fn_t)(JNIEnv *env, jstring s, jboolean *b);
typedef jint (*check_format_fn_t)(char *class_name,
unsigned char *data,
unsigned int data_size,
class_size_info *class_size,
char *message_buffer,
jint buffer_length,
jboolean measure_only,
jboolean check_relaxed);
#define JVM_RECOGNIZED_CLASS_MODIFIERS (JVM_ACC_PUBLIC | \
JVM_ACC_FINAL | \
JVM_ACC_SUPER | \
JVM_ACC_INTERFACE | \
JVM_ACC_ABSTRACT | \
JVM_ACC_ANNOTATION | \
JVM_ACC_ENUM | \
JVM_ACC_SYNTHETIC)
#define JVM_RECOGNIZED_FIELD_MODIFIERS (JVM_ACC_PUBLIC | \
JVM_ACC_PRIVATE | \
JVM_ACC_PROTECTED | \
JVM_ACC_STATIC | \
JVM_ACC_FINAL | \
JVM_ACC_VOLATILE | \
JVM_ACC_TRANSIENT | \
JVM_ACC_ENUM | \
JVM_ACC_SYNTHETIC)
#define JVM_RECOGNIZED_METHOD_MODIFIERS (JVM_ACC_PUBLIC | \
JVM_ACC_PRIVATE | \
JVM_ACC_PROTECTED | \
JVM_ACC_STATIC | \
JVM_ACC_FINAL | \
JVM_ACC_SYNCHRONIZED | \
JVM_ACC_BRIDGE | \
JVM_ACC_VARARGS | \
JVM_ACC_NATIVE | \
JVM_ACC_ABSTRACT | \
JVM_ACC_STRICT | \
JVM_ACC_SYNTHETIC)
typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
PART 3: I/O and Network Support
#define JVM_IO_ERR (-1)
#define JVM_IO_INTR (-2)
JNIEXPORT jint JNICALL
JVM_GetLastErrorString(char *buf, int len);
JNIEXPORT char * JNICALL
JVM_NativePath(char *);
#define JVM_EEXIST -100
JNIEXPORT jint JNICALL
JVM_Open(const char *fname, jint flags, jint mode);
JNIEXPORT jint JNICALL
JVM_Close(jint fd);
JNIEXPORT jint JNICALL
JVM_Read(jint fd, char *buf, jint nbytes);
JNIEXPORT jint JNICALL
JVM_Write(jint fd, char *buf, jint nbytes);
JNIEXPORT jint JNICALL
JVM_Available(jint fd, jlong *pbytes);
JNIEXPORT jlong JNICALL
JVM_Lseek(jint fd, jlong offset, jint whence);
JNIEXPORT jint JNICALL
JVM_SetLength(jint fd, jlong length);
JNIEXPORT jint JNICALL
JVM_Sync(jint fd);
JNIEXPORT jint JNICALL
JVM_InitializeSocketLibrary(void);
struct sockaddr;
JNIEXPORT jint JNICALL
JVM_Socket(jint domain, jint type, jint protocol);
JNIEXPORT jint JNICALL
JVM_SocketClose(jint fd);
JNIEXPORT jint JNICALL
JVM_SocketShutdown(jint fd, jint howto);
JNIEXPORT jint JNICALL
JVM_Recv(jint fd, char *buf, jint nBytes, jint flags);
JNIEXPORT jint JNICALL
JVM_Send(jint fd, char *buf, jint nBytes, jint flags);
JNIEXPORT jint JNICALL
JVM_Timeout(int fd, long timeout);
JNIEXPORT jint JNICALL
JVM_Listen(jint fd, jint count);
JNIEXPORT jint JNICALL
JVM_Connect(jint fd, struct sockaddr *him, jint len);
JNIEXPORT jint JNICALL
JVM_Bind(jint fd, struct sockaddr *him, jint len);
JNIEXPORT jint JNICALL
JVM_Accept(jint fd, struct sockaddr *him, jint *len);
JNIEXPORT jint JNICALL
JVM_RecvFrom(jint fd, char *buf, int nBytes,
int flags, struct sockaddr *from, int *fromlen);
JNIEXPORT jint JNICALL
JVM_SendTo(jint fd, char *buf, int len,
int flags, struct sockaddr *to, int tolen);
JNIEXPORT jint JNICALL
JVM_SocketAvailable(jint fd, jint *result);
JNIEXPORT jint JNICALL
JVM_GetSockName(jint fd, struct sockaddr *him, int *len);
JNIEXPORT jint JNICALL
JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen);
JNIEXPORT jint JNICALL
JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen);
JNIEXPORT int JNICALL
JVM_GetHostName(char* name, int namelen);
JNIEXPORT int
jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
JNIEXPORT int
jio_snprintf(char *str, size_t count, const char *fmt, ...);
JNIEXPORT int
jio_fprintf(FILE *, const char *fmt, ...);
JNIEXPORT int
jio_vfprintf(FILE *, const char *fmt, va_list args);
JNIEXPORT void * JNICALL
JVM_RawMonitorCreate(void);
JNIEXPORT void JNICALL
JVM_RawMonitorDestroy(void *mon);
JNIEXPORT jint JNICALL
JVM_RawMonitorEnter(void *mon);
JNIEXPORT void JNICALL
JVM_RawMonitorExit(void *mon);
JNIEXPORT jobject JNICALL
JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
JNIEXPORT jobject JNICALL
JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
JNIEXPORT void* JNICALL
JVM_GetManagement(jint version);
JNIEXPORT jobject JNICALL
JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
JNIEXPORT jstring JNICALL
JVM_GetTemporaryDirectory(JNIEnv *env);
JNIEXPORT jobjectArray JNICALL
JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
enum {
JAVA_THREAD_STATE_NEW = 0,
JAVA_THREAD_STATE_RUNNABLE = 1,
JAVA_THREAD_STATE_BLOCKED = 2,
JAVA_THREAD_STATE_WAITING = 3,
JAVA_THREAD_STATE_TIMED_WAITING = 4,
JAVA_THREAD_STATE_TERMINATED = 5,
JAVA_THREAD_STATE_COUNT = 6
};
JNIEXPORT jintArray JNICALL
JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState);
JNIEXPORT jobjectArray JNICALL
JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values);
JNIEXPORT jboolean JNICALL
JVM_KnownToNotExist(JNIEnv *env, jobject loader, const char *classname);
JNIEXPORT jobjectArray JNICALL
JVM_GetResourceLookupCacheURLs(JNIEnv *env, jobject loader);
JNIEXPORT jintArray JNICALL
JVM_GetResourceLookupCache(JNIEnv *env, jobject loader, const char *resource_name);
typedef struct {
unsigned int jvm_version; /* Consists of major.minor.0.build */
unsigned int update_version : 8; /* 0 in HotSpot Express VM */
unsigned int special_update_version : 8; /* 0 in HotSpot Express VM */
unsigned int reserved1 : 16;
unsigned int reserved2;
unsigned int is_attachable : 1;
unsigned int : 31;
unsigned int : 32;
unsigned int : 32;
} jvm_version_info;
#define JVM_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
#define JVM_VERSION_MINOR(version) ((version & 0x00FFFF00) >> 8)
#define JVM_VERSION_MICRO(version) 0
#define JVM_VERSION_BUILD(version) ((version & 0x000000FF))
JNIEXPORT void JNICALL
JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size);
typedef struct {
unsigned int jdk_version; /* Consists of major, minor, micro (n.n.n) */
unsigned int update_version : 16; /* Update release version (uu) */
unsigned int special_update_version : 8; /* Special update release version (c)*/
unsigned int reserved1 : 8;
unsigned int reserved2;
unsigned int thread_park_blocker : 1;
unsigned int post_vm_init_hook_enabled : 1;
unsigned int pending_list_uses_discovered_field : 1;
unsigned int : 29;
unsigned int : 32;
unsigned int : 32;
} jdk_version_info;
#define JDK_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
#define JDK_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
#define JDK_VERSION_MICRO(version) ((version & 0x0000FF00) >> 8)
#define JDK_VERSION_BUILD(version) ((version & 0x000000FF))
typedef void (*jdk_version_info_fn_t)(jdk_version_info* info, size_t info_size);
typedef struct JDK1_1InitArgs {
jint version;
char **properties;
jint checkSource;
jint nativeStackSize;
jint javaStackSize;
jint minHeapSize;
jint maxHeapSize;
jint verifyMode;
char *classpath;
jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
void (JNICALL *exit)(jint code);
void (JNICALL *abort)(void);
jint enableClassGC;
jint enableVerboseGC;
jint disableAsyncGC;
jint verbose;
jboolean debugging;
jint debugPort;
} JDK1_1InitArgs;
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* !_JAVASOFT_JVM_H_ */
#endif // SHARE_VM_PRIMS_JVM_H
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiAgentThread.hpp
#ifndef SHARE_VM_PRIMS_JVMTIAGENTTHREAD_HPP
#define SHARE_VM_PRIMS_JVMTIAGENTTHREAD_HPP
#include "jvmtifiles/jvmtiEnv.hpp"
class JvmtiAgentThread : public JavaThread {
jvmtiStartFunction _start_fn;
JvmtiEnv* _env;
const void *_start_arg;
public:
JvmtiAgentThread(JvmtiEnv* env, jvmtiStartFunction start_fn, const void *start_arg);
bool is_jvmti_agent_thread() const { return true; }
static void start_function_wrapper(JavaThread *thread, TRAPS);
void call_start_function();
};
#endif // SHARE_VM_PRIMS_JVMTIAGENTTHREAD_HPP
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiClassFileReconstituter.cpp
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "oops/fieldStreams.hpp"
#include "prims/jvmtiClassFileReconstituter.hpp"
#include "runtime/signature.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "bytes_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "bytes_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "bytes_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "bytes_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "bytes_ppc.hpp"
#endif
void JvmtiClassFileReconstituter::write_field_infos() {
HandleMark hm(thread());
Array<AnnotationArray*>* fields_anno = ikh()->fields_annotations();
Array<AnnotationArray*>* fields_type_anno = ikh()->fields_type_annotations();
int java_fields = ikh()->java_fields_count();
write_u2(java_fields);
for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) {
AccessFlags access_flags = fs.access_flags();
int name_index = fs.name_index();
int signature_index = fs.signature_index();
int initial_value_index = fs.initval_index();
guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field");
int generic_signature_index = fs.generic_signature_index();
AnnotationArray* anno = fields_anno == NULL ? NULL : fields_anno->at(fs.index());
AnnotationArray* type_anno = fields_type_anno == NULL ? NULL : fields_type_anno->at(fs.index());
write_u2(access_flags.as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS);
write_u2(name_index);
write_u2(signature_index);
int attr_count = 0;
if (initial_value_index != 0) {
++attr_count;
}
if (access_flags.is_synthetic()) {
}
if (generic_signature_index != 0) {
++attr_count;
}
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
if (type_anno != NULL) {
++attr_count; // has RuntimeVisibleTypeAnnotations attribute
}
write_u2(attr_count);
if (initial_value_index != 0) {
write_attribute_name_index("ConstantValue");
write_u4(2); //length always 2
write_u2(initial_value_index);
}
if (access_flags.is_synthetic()) {
}
if (generic_signature_index != 0) {
write_signature_attribute(generic_signature_index);
}
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
if (type_anno != NULL) {
write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
}
}
}
void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
ConstMethod* const_method = method->constMethod();
u2 line_num_cnt = 0;
int stackmap_len = 0;
int local_variable_table_length = 0;
int local_variable_type_table_length = 0;
int attr_count = 0;
int attr_size = 0;
if (const_method->has_linenumber_table()) {
line_num_cnt = line_number_table_entries(method);
if (line_num_cnt != 0) {
++attr_count;
attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2);
}
}
if (method->has_stackmap_table()) {
stackmap_len = method->stackmap_data()->length();
if (stackmap_len != 0) {
++attr_count;
attr_size += 2 + 4 + stackmap_len;
}
}
if (method->has_localvariable_table()) {
local_variable_table_length = method->localvariable_table_length();
if (local_variable_table_length != 0) {
++attr_count;
attr_size += 2 + 4 + 2 + local_variable_table_length * (2 + 2 + 2 + 2 + 2);
LocalVariableTableElement *elem = method->localvariable_table_start();
for (int idx = 0; idx < local_variable_table_length; idx++) {
if (elem[idx].signature_cp_index != 0) {
local_variable_type_table_length++;
}
}
if (local_variable_type_table_length != 0) {
++attr_count;
attr_size += 2 + 4 + 2 + local_variable_type_table_length * (2 + 2 + 2 + 2 + 2);
}
}
}
ExceptionTable exception_table(method());
int exception_table_length = exception_table.length();
int code_size = const_method->code_size();
int size =
2+2+4 + // max_stack, max_locals, code_length
code_size + // code
2 + // exception_table_length
(2+2+2+2) * exception_table_length + // exception_table
2 + // attributes_count
attr_size; // attributes
write_attribute_name_index("Code");
write_u4(size);
write_u2(method->verifier_max_stack());
write_u2(method->max_locals());
write_u4(code_size);
copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
write_u2(exception_table_length);
for (int index = 0; index < exception_table_length; index++) {
write_u2(exception_table.start_pc(index));
write_u2(exception_table.end_pc(index));
write_u2(exception_table.handler_pc(index));
write_u2(exception_table.catch_type_index(index));
}
write_u2(attr_count);
if (line_num_cnt != 0) {
write_line_number_table_attribute(method, line_num_cnt);
}
if (stackmap_len != 0) {
write_stackmap_table_attribute(method, stackmap_len);
}
if (local_variable_table_length != 0) {
write_local_variable_table_attribute(method, local_variable_table_length);
}
if (local_variable_type_table_length != 0) {
write_local_variable_type_table_attribute(method, local_variable_type_table_length);
}
}
void JvmtiClassFileReconstituter::write_exceptions_attribute(ConstMethod* const_method) {
CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start();
int checked_exceptions_length = const_method->checked_exceptions_length();
int size =
2 + // number_of_exceptions
2 * checked_exceptions_length; // exception_index_table
write_attribute_name_index("Exceptions");
write_u4(size);
write_u2(checked_exceptions_length);
for (int index = 0; index < checked_exceptions_length; index++) {
write_u2(checked_exceptions[index].class_cp_index);
}
}
void JvmtiClassFileReconstituter::write_source_file_attribute() {
assert(ikh()->source_file_name() != NULL, "caller must check");
write_attribute_name_index("SourceFile");
write_u4(2); // always length 2
write_u2(symbol_to_cpool_index(ikh()->source_file_name()));
}
void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() {
assert(ikh()->source_debug_extension() != NULL, "caller must check");
write_attribute_name_index("SourceDebugExtension");
int len = (int)strlen(ikh()->source_debug_extension());
write_u4(len);
u1* ext = (u1*)ikh()->source_debug_extension();
for (int i=0; i<len; i++) {
write_u1(ext[i]);
}
}
void JvmtiClassFileReconstituter::write_signature_attribute(u2 generic_signature_index) {
write_attribute_name_index("Signature");
write_u4(2); // always length 2
write_u2(generic_signature_index);
}
u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
InnerClassesIterator iter(ikh());
return iter.length();
}
void JvmtiClassFileReconstituter::write_annotations_attribute(const char* attr_name,
AnnotationArray* annos) {
u4 length = annos->length();
write_attribute_name_index(attr_name);
write_u4(length);
memcpy(writeable_address(length), annos->adr_at(0), length);
}
void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() {
Array<u2>* operands = cpool()->operands();
write_attribute_name_index("BootstrapMethods");
int num_bootstrap_methods = ConstantPool::operand_array_length(operands);
int length = sizeof(u2); // num_bootstrap_methods
for (int n = 0; n < num_bootstrap_methods; n++) {
u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n);
length += sizeof(u2); // bootstrap_method_ref
length += sizeof(u2); // num_bootstrap_arguments
length += sizeof(u2) * num_bootstrap_arguments; // bootstrap_arguments[num_bootstrap_arguments]
}
write_u4(length);
write_u2(num_bootstrap_methods);
for (int n = 0; n < num_bootstrap_methods; n++) {
u2 bootstrap_method_ref = cpool()->operand_bootstrap_method_ref_index_at(n);
u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n);
write_u2(bootstrap_method_ref);
write_u2(num_bootstrap_arguments);
for (int arg = 0; arg < num_bootstrap_arguments; arg++) {
u2 bootstrap_argument = cpool()->operand_argument_index_at(n, arg);
write_u2(bootstrap_argument);
}
}
}
void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
InnerClassesIterator iter(ikh());
guarantee(iter.length() != 0 && iter.length() == length,
"caller must check");
u2 entry_count = length / InstanceKlass::inner_class_next_offset;
u4 size = 2 + entry_count * (2+2+2+2);
write_attribute_name_index("InnerClasses");
write_u4(size);
write_u2(entry_count);
for (; !iter.done(); iter.next()) {
write_u2(iter.inner_class_info_index());
write_u2(iter.outer_class_info_index());
write_u2(iter.inner_name_index());
write_u2(iter.inner_access_flags());
}
}
void JvmtiClassFileReconstituter::write_synthetic_attribute() {
write_attribute_name_index("Synthetic");
write_u4(0); //length always zero
}
u2 JvmtiClassFileReconstituter::line_number_table_entries(methodHandle method) {
u2 num_entries = 0;
CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
while (stream.read_pair()) {
num_entries++;
}
return num_entries;
}
void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method,
u2 num_entries) {
write_attribute_name_index("LineNumberTable");
write_u4(2 + num_entries * (2 + 2));
write_u2(num_entries);
CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
while (stream.read_pair()) {
write_u2(stream.bci());
write_u2(stream.line());
}
}
void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHandle method, u2 num_entries) {
write_attribute_name_index("LocalVariableTable");
write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
write_u2(num_entries);
assert(method->localvariable_table_length() == num_entries, "just checking");
LocalVariableTableElement *elem = method->localvariable_table_start();
for (int j=0; j<method->localvariable_table_length(); j++) {
write_u2(elem->start_bci);
write_u2(elem->length);
write_u2(elem->name_cp_index);
write_u2(elem->descriptor_cp_index);
write_u2(elem->slot);
elem++;
}
}
void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(methodHandle method, u2 num_entries) {
write_attribute_name_index("LocalVariableTypeTable");
write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
write_u2(num_entries);
LocalVariableTableElement *elem = method->localvariable_table_start();
for (int j=0; j<method->localvariable_table_length(); j++) {
if (elem->signature_cp_index > 0) {
write_u2(elem->start_bci);
write_u2(elem->length);
write_u2(elem->name_cp_index);
write_u2(elem->signature_cp_index);
write_u2(elem->slot);
num_entries--;
}
elem++;
}
assert(num_entries == 0, "just checking");
}
void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method,
int stackmap_len) {
write_attribute_name_index("StackMapTable");
write_u4(stackmap_len);
memcpy(
writeable_address(stackmap_len),
(void*)(method->stackmap_data()->adr_at(0)),
stackmap_len);
}
void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
AccessFlags access_flags = method->access_flags();
ConstMethod* const_method = method->constMethod();
u2 generic_signature_index = const_method->generic_signature_index();
AnnotationArray* anno = method->annotations();
AnnotationArray* param_anno = method->parameter_annotations();
AnnotationArray* default_anno = method->annotation_default();
AnnotationArray* type_anno = method->type_annotations();
if (method->is_overpass()) {
return;
}
write_u2(access_flags.get_flags() & JVM_RECOGNIZED_METHOD_MODIFIERS);
write_u2(const_method->name_index());
write_u2(const_method->signature_index());
int attr_count = 0;
if (const_method->code_size() != 0) {
++attr_count; // has Code attribute
}
if (const_method->has_checked_exceptions()) {
++attr_count; // has Exceptions attribute
}
if (default_anno != NULL) {
++attr_count; // has AnnotationDefault attribute
}
if (access_flags.is_synthetic()) { // FIXME
}
if (generic_signature_index != 0) {
++attr_count;
}
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
if (param_anno != NULL) {
++attr_count; // has RuntimeVisibleParameterAnnotations attribute
}
if (type_anno != NULL) {
++attr_count; // has RuntimeVisibleTypeAnnotations attribute
}
write_u2(attr_count);
if (const_method->code_size() > 0) {
write_code_attribute(method);
}
if (const_method->has_checked_exceptions()) {
write_exceptions_attribute(const_method);
}
if (default_anno != NULL) {
write_annotations_attribute("AnnotationDefault", default_anno);
}
if (access_flags.is_synthetic()) {
}
if (generic_signature_index != 0) {
write_signature_attribute(generic_signature_index);
}
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
if (param_anno != NULL) {
write_annotations_attribute("RuntimeVisibleParameterAnnotations", param_anno);
}
if (type_anno != NULL) {
write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
}
}
void JvmtiClassFileReconstituter::write_class_attributes() {
u2 inner_classes_length = inner_classes_attribute_length();
Symbol* generic_signature = ikh()->generic_signature();
AnnotationArray* anno = ikh()->class_annotations();
AnnotationArray* type_anno = ikh()->class_type_annotations();
int attr_count = 0;
if (generic_signature != NULL) {
++attr_count;
}
if (ikh()->source_file_name() != NULL) {
++attr_count;
}
if (ikh()->source_debug_extension() != NULL) {
++attr_count;
}
if (inner_classes_length > 0) {
++attr_count;
}
if (anno != NULL) {
++attr_count; // has RuntimeVisibleAnnotations attribute
}
if (type_anno != NULL) {
++attr_count; // has RuntimeVisibleTypeAnnotations attribute
}
if (cpool()->operands() != NULL) {
++attr_count;
}
write_u2(attr_count);
if (generic_signature != NULL) {
write_signature_attribute(symbol_to_cpool_index(generic_signature));
}
if (ikh()->source_file_name() != NULL) {
write_source_file_attribute();
}
if (ikh()->source_debug_extension() != NULL) {
write_source_debug_extension_attribute();
}
if (inner_classes_length > 0) {
write_inner_classes_attribute(inner_classes_length);
}
if (anno != NULL) {
write_annotations_attribute("RuntimeVisibleAnnotations", anno);
}
if (type_anno != NULL) {
write_annotations_attribute("RuntimeVisibleTypeAnnotations", type_anno);
}
if (cpool()->operands() != NULL) {
write_bootstrapmethod_attribute();
}
}
void JvmtiClassFileReconstituter::write_method_infos() {
HandleMark hm(thread());
Array<Method*>* methods = ikh()->methods();
int num_methods = methods->length();
int num_overpass = 0;
for (int index = 0; index < num_methods; index++) {
Method* method = methods->at(index);
if (method->is_overpass()) {
num_overpass++;
}
}
write_u2(num_methods - num_overpass);
if (JvmtiExport::can_maintain_original_method_order()) {
int index;
int original_index;
intArray method_order(num_methods, 0);
for (index = 0; index < num_methods; index++) {
original_index = ikh()->method_ordering()->at(index);
assert(original_index >= 0 && original_index < num_methods,
"invalid original method index");
method_order.at_put(original_index, index);
}
for (original_index = 0; original_index < num_methods; original_index++) {
index = method_order.at(original_index);
methodHandle method(thread(), methods->at(index));
write_method_info(method);
}
} else {
for (int index = 0; index < num_methods; index++) {
methodHandle method(thread(), methods->at(index));
write_method_info(method);
}
}
}
void JvmtiClassFileReconstituter::write_class_file_format() {
ReallocMark();
write_u4(0xCAFEBABE);
write_u2(ikh()->minor_version());
u2 major = ikh()->major_version();
write_u2(major);
write_u2(cpool()->length());
copy_cpool_bytes(writeable_address(cpool_size()));
write_u2(ikh()->access_flags().get_flags() & JVM_RECOGNIZED_CLASS_MODIFIERS);
write_u2(class_symbol_to_cpool_index(ikh()->name()));
Klass* super_class = ikh()->super();
write_u2(super_class == NULL? 0 : // zero for java.lang.Object
class_symbol_to_cpool_index(super_class->name()));
Array<Klass*>* interfaces = ikh()->local_interfaces();
int num_interfaces = interfaces->length();
write_u2(num_interfaces);
for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(thread());
instanceKlassHandle iikh(thread(), interfaces->at(index));
write_u2(class_symbol_to_cpool_index(iikh->name()));
}
write_field_infos();
write_method_infos();
write_class_attributes();
}
address JvmtiClassFileReconstituter::writeable_address(size_t size) {
size_t used_size = _buffer_ptr - _buffer;
if (size + used_size >= _buffer_size) {
size_t new_buffer_size = (size + _buffer_size*2 + 1) / initial_buffer_size
_buffer = REALLOC_RESOURCE_ARRAY(u1, _buffer, _buffer_size, new_buffer_size);
_buffer_size = new_buffer_size;
_buffer_ptr = _buffer + used_size;
}
u1* ret_ptr = _buffer_ptr;
_buffer_ptr += size;
return ret_ptr;
}
void JvmtiClassFileReconstituter::write_attribute_name_index(const char* name) {
TempNewSymbol sym = SymbolTable::probe(name, (int)strlen(name));
assert(sym != NULL, "attribute name symbol not found");
u2 attr_name_index = symbol_to_cpool_index(sym);
assert(attr_name_index != 0, "attribute name symbol not in constant pool");
write_u2(attr_name_index);
}
void JvmtiClassFileReconstituter::write_u1(u1 x) {
}
void JvmtiClassFileReconstituter::write_u2(u2 x) {
Bytes::put_Java_u2(writeable_address(2), x);
}
void JvmtiClassFileReconstituter::write_u4(u4 x) {
Bytes::put_Java_u4(writeable_address(4), x);
}
void JvmtiClassFileReconstituter::write_u8(u8 x) {
Bytes::put_Java_u8(writeable_address(8), x);
}
void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
unsigned char* bytecodes) {
BytecodeStream bs(mh);
unsigned char* p = bytecodes;
Bytecodes::Code code;
bool is_rewritten = mh->method_holder()->is_rewritten();
while ((code = bs.next()) >= 0) {
assert(Bytecodes::is_java_code(code), "sanity check");
assert(code != Bytecodes::_breakpoint, "sanity check");
address bcp = bs.bcp();
int len = bs.instruction_size();
assert(len > 0, "length must be > 0");
if (len > 1) {
memcpy(p+1, bcp+1, len-1);
}
if (is_rewritten && len > 1) {
bool is_wide = false;
switch (code) {
case Bytecodes::_getstatic : // fall through
case Bytecodes::_putstatic : // fall through
case Bytecodes::_getfield : // fall through
case Bytecodes::_putfield : // fall through
case Bytecodes::_invokevirtual : // fall through
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokeinterface : {
assert(len == 3 ||
(code == Bytecodes::_invokeinterface && len == 5) ||
(code == Bytecodes::_invokedynamic && len == 5),
"sanity check");
int cpci = Bytes::get_native_u2(bcp+1);
bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic);
ConstantPoolCacheEntry* entry;
if (is_invokedynamic) {
cpci = Bytes::get_native_u4(bcp+1);
entry = mh->constants()->invokedynamic_cp_cache_entry_at(cpci);
} else {
entry = mh->constants()->cache()->entry_at(cpci);
}
int i = entry->constant_pool_index();
assert(i < mh->constants()->length(), "sanity check");
Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
if (is_invokedynamic) *(p+3) = *(p+4) = 0;
break;
}
case Bytecodes::_ldc_w:
is_wide = true; // fall through
case Bytecodes::_ldc: {
if (bs.raw_code() == Bytecodes::_fast_aldc || bs.raw_code() == Bytecodes::_fast_aldc_w) {
int cpci = is_wide ? Bytes::get_native_u2(bcp+1) : (u1)(*(bcp+1));
int i = mh->constants()->object_to_cp_index(cpci);
assert(i < mh->constants()->length(), "sanity check");
if (is_wide) {
Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
} else {
}
}
break;
}
}
}
p += len;
}
}
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiClassFileReconstituter.hpp
#ifndef SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
#define SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
#include "jvmtifiles/jvmtiEnv.hpp"
class JvmtiConstantPoolReconstituter : public StackObj {
private:
int _cpool_size;
SymbolHashMap* _symmap;
SymbolHashMap* _classmap;
constantPoolHandle _cpool;
instanceKlassHandle _ikh;
jvmtiError _err;
protected:
instanceKlassHandle ikh() { return _ikh; };
constantPoolHandle cpool() { return _cpool; };
u2 symbol_to_cpool_index(Symbol* sym) {
return _symmap->symbol_to_value(sym);
}
u2 class_symbol_to_cpool_index(Symbol* sym) {
return _classmap->symbol_to_value(sym);
}
public:
JvmtiConstantPoolReconstituter(instanceKlassHandle ikh){
set_error(JVMTI_ERROR_NONE);
_ikh = ikh;
_cpool = constantPoolHandle(Thread::current(), ikh->constants());
_symmap = new SymbolHashMap();
_classmap = new SymbolHashMap();
_cpool_size = _cpool->hash_entries_to(_symmap, _classmap);
if (_cpool_size == 0) {
set_error(JVMTI_ERROR_OUT_OF_MEMORY);
} else if (_cpool_size < 0) {
set_error(JVMTI_ERROR_INTERNAL);
}
}
~JvmtiConstantPoolReconstituter() {
if (_symmap != NULL) {
delete _symmap;
_symmap = NULL;
}
if (_classmap != NULL) {
delete _classmap;
_classmap = NULL;
}
}
void set_error(jvmtiError err) { _err = err; }
jvmtiError get_error() { return _err; }
int cpool_size() { return _cpool_size; }
void copy_cpool_bytes(unsigned char *cpool_bytes) {
if (cpool_bytes == NULL) {
assert(cpool_bytes != NULL, "cpool_bytes pointer must not be NULL");
return;
}
cpool()->copy_cpool_bytes(cpool_size(), _symmap, cpool_bytes);
}
};
class JvmtiClassFileReconstituter : public JvmtiConstantPoolReconstituter {
private:
size_t _buffer_size;
u1* _buffer;
u1* _buffer_ptr;
Thread* _thread;
enum {
initial_buffer_size = 1024
};
inline Thread* thread() { return _thread; }
void write_class_file_format();
void write_field_infos();
void write_method_infos();
void write_method_info(methodHandle method);
void write_code_attribute(methodHandle method);
void write_exceptions_attribute(ConstMethod* const_method);
void write_synthetic_attribute();
void write_class_attributes();
void write_source_file_attribute();
void write_source_debug_extension_attribute();
u2 line_number_table_entries(methodHandle method);
void write_line_number_table_attribute(methodHandle method, u2 num_entries);
void write_local_variable_table_attribute(methodHandle method, u2 num_entries);
void write_local_variable_type_table_attribute(methodHandle method, u2 num_entries);
void write_stackmap_table_attribute(methodHandle method, int stackmap_table_len);
u2 inner_classes_attribute_length();
void write_inner_classes_attribute(int length);
void write_signature_attribute(u2 generic_signaure_index);
void write_attribute_name_index(const char* name);
void write_annotations_attribute(const char* attr_name, AnnotationArray* annos);
void write_bootstrapmethod_attribute();
address writeable_address(size_t size);
void write_u1(u1 x);
void write_u2(u2 x);
void write_u4(u4 x);
void write_u8(u8 x);
public:
JvmtiClassFileReconstituter(instanceKlassHandle ikh) :
JvmtiConstantPoolReconstituter(ikh) {
_buffer_size = initial_buffer_size;
_buffer = _buffer_ptr = NEW_RESOURCE_ARRAY(u1, _buffer_size);
_thread = Thread::current();
write_class_file_format();
};
size_t class_file_size() { return _buffer_ptr - _buffer; }
u1* class_file_bytes() { return _buffer; }
static void copy_bytecodes(methodHandle method, unsigned char* bytecodes);
};
#endif // SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiCodeBlobEvents.cpp
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/scopeDesc.hpp"
#include "code/vtableStubs.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiCodeBlobEvents.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/vmThread.hpp"
class CodeBlobCollector : StackObj {
private:
GrowableArray<JvmtiCodeBlobDesc*>* _code_blobs; // collected blobs
int _pos; // iterator position
static GrowableArray<JvmtiCodeBlobDesc*>* _global_code_blobs;
static void do_blob(CodeBlob* cb);
static void do_vtable_stub(VtableStub* vs);
public:
CodeBlobCollector() {
_code_blobs = NULL;
_pos = -1;
}
~CodeBlobCollector() {
if (_code_blobs != NULL) {
for (int i=0; i<_code_blobs->length(); i++) {
FreeHeap(_code_blobs->at(i));
}
delete _code_blobs;
}
}
void collect();
JvmtiCodeBlobDesc* first() {
assert(_code_blobs != NULL, "not collected");
if (_code_blobs->length() == 0) {
return NULL;
}
_pos = 0;
return _code_blobs->at(0);
}
JvmtiCodeBlobDesc* next() {
assert(_pos >= 0, "iteration not started");
if (_pos+1 >= _code_blobs->length()) {
return NULL;
}
return _code_blobs->at(++_pos);
}
};
GrowableArray<JvmtiCodeBlobDesc*>* CodeBlobCollector::_global_code_blobs;
void CodeBlobCollector::do_blob(CodeBlob* cb) {
if (cb->is_nmethod()) {
return;
}
if (cb->is_buffer_blob() && strcmp(cb->name(), "vtable chunks") == 0) {
return;
}
address addr = cb->code_begin();
for (int i=0; i<_global_code_blobs->length(); i++) {
JvmtiCodeBlobDesc* scb = _global_code_blobs->at(i);
if (addr == scb->code_begin()) {
return;
}
}
JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(cb->name(), cb->code_begin(), cb->code_end());
_global_code_blobs->append(scb);
}
void CodeBlobCollector::do_vtable_stub(VtableStub* vs) {
JvmtiCodeBlobDesc* scb = new JvmtiCodeBlobDesc(vs->is_vtable_stub() ? "vtable stub" : "itable stub",
vs->code_begin(), vs->code_end());
_global_code_blobs->append(scb);
}
void CodeBlobCollector::collect() {
assert_locked_or_safepoint(CodeCache_lock);
assert(_global_code_blobs == NULL, "checking");
_global_code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiCodeBlobDesc*>(50,true);
int index = 0;
StubCodeDesc* desc;
while ((desc = StubCodeDesc::desc_for_index(++index)) != NULL) {
_global_code_blobs->append(new JvmtiCodeBlobDesc(desc->name(), desc->begin(), desc->end()));
}
VtableStubs::vtable_stub_do(do_vtable_stub);
CodeCache::blobs_do(do_blob);
_code_blobs = _global_code_blobs;
_global_code_blobs = NULL;
}
jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
CodeBlobCollector collector;
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
collector.collect();
}
JvmtiCodeBlobDesc* blob = collector.first();
while (blob != NULL) {
JvmtiExport::post_dynamic_code_generated(env, blob->name(), blob->code_begin(), blob->code_end());
blob = collector.next();
}
return JVMTI_ERROR_NONE;
}
jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
HandleMark hm;
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
nmethod* current = CodeCache::first_nmethod();
while (current != NULL) {
if (current->is_alive()) {
nmethodLocker nml(current);
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
current->get_and_cache_jmethod_id();
JvmtiExport::post_compiled_method_load(current);
}
current = CodeCache::next_nmethod(current);
}
return JVMTI_ERROR_NONE;
}
void JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nmethod *nm,
jvmtiAddrLocationMap** map_ptr,
jint *map_length_ptr)
{
ResourceMark rm;
jvmtiAddrLocationMap* map = NULL;
jint map_length = 0;
methodHandle mh(nm->method());
if (!mh->is_native()) {
PcDesc *pcd;
int pcds_in_method;
pcds_in_method = (nm->scopes_pcs_end() - nm->scopes_pcs_begin());
map = NEW_C_HEAP_ARRAY(jvmtiAddrLocationMap, pcds_in_method, mtInternal);
address scopes_data = nm->scopes_data_begin();
for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
ScopeDesc *sd = &sc0;
while( !sd->is_top() ) { sd = sd->sender(); }
int bci = sd->bci();
if (bci != InvocationEntryBci) {
assert(map_length < pcds_in_method, "checking");
map[map_length].start_address = (const void*)pcd->real_pc(nm);
map[map_length].location = bci;
++map_length;
}
}
}
}
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiCodeBlobEvents.hpp
#ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP
#define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP
#include "jvmtifiles/jvmti.h"
class JvmtiEnv;
class JvmtiCodeBlobEvents : public AllStatic {
public:
static jvmtiError generate_dynamic_code_events(JvmtiEnv* env);
static jvmtiError generate_compiled_method_load_events(JvmtiEnv* env);
static void build_jvmti_addr_location_map(nmethod *nm, jvmtiAddrLocationMap** map,
jint *map_length);
};
#endif // SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiEnter.hpp
#ifndef SHARE_VM_PRIMS_JVMTIENTER_HPP
#define SHARE_VM_PRIMS_JVMTIENTER_HPP
#include "classfile/systemDictionary.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jvmtiImpl.hpp"
#include "runtime/interfaceSupport.hpp"
#endif // SHARE_VM_PRIMS_JVMTIENTER_HPP
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiEnv.cpp
#include "precompiled.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/interpreter.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "prims/jniCheck.hpp"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiAgentThread.hpp"
#include "prims/jvmtiClassFileReconstituter.hpp"
#include "prims/jvmtiCodeBlobEvents.hpp"
#include "prims/jvmtiExtensions.hpp"
#include "prims/jvmtiGetLoadedClasses.hpp"
#include "prims/jvmtiImpl.hpp"
#include "prims/jvmtiManageCapabilities.hpp"
#include "prims/jvmtiRawMonitor.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/jvmtiTagMap.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "prims/jvmtiUtil.hpp"
#include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jfieldIDWorkaround.hpp"
#include "runtime/osThread.hpp"
#include "runtime/reflectionUtils.hpp"
#include "runtime/signature.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vmThread.hpp"
#include "services/threadService.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/preserveException.hpp"
#define FIXLATER 0 // REMOVE this when completed.
#define TraceJVMTICalls false
JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) {
}
JvmtiEnv::~JvmtiEnv() {
}
JvmtiEnv*
JvmtiEnv::create_a_jvmti(jint version) {
return new JvmtiEnv(version);
}
class VM_JNIFunctionTableCopier : public VM_Operation {
private:
const struct JNINativeInterface_ *_function_table;
public:
VM_JNIFunctionTableCopier(const struct JNINativeInterface_ *func_tbl) {
_function_table = func_tbl;
};
VMOp_Type type() const { return VMOp_JNIFunctionTableCopier; }
void doit() {
copy_jni_function_table(_function_table);
};
};
jvmtiError
JvmtiEnv::Allocate(jlong size, unsigned char** mem_ptr) {
return allocate(size, mem_ptr);
} /* end Allocate */
jvmtiError
JvmtiEnv::Deallocate(unsigned char* mem) {
return deallocate(mem);
} /* end Deallocate */
jvmtiError
JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) {
JvmtiThreadState* state = java_thread->jvmti_thread_state();
if (state == NULL) {
if (data == NULL) {
return JVMTI_ERROR_NONE;
}
state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
}
state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data);
return JVMTI_ERROR_NONE;
} /* end SetThreadLocalStorage */
jvmtiError
JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) {
JavaThread* current_thread = JavaThread::current();
if (thread == NULL) {
JvmtiThreadState* state = current_thread->jvmti_thread_state();
state->env_thread_state(this)->get_agent_thread_local_storage_data();
} else {
ThreadInVMfromNative __tiv(current_thread);
VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread)
debug_only(VMNativeEntryWrapper __vew;)
oop thread_oop = JNIHandles::resolve_external_guard(thread);
if (thread_oop == NULL) {
return JVMTI_ERROR_INVALID_THREAD;
}
if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
return JVMTI_ERROR_INVALID_THREAD;
}
JavaThread* java_thread = java_lang_Thread::thread(thread_oop);
if (java_thread == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
JvmtiThreadState* state = java_thread->jvmti_thread_state();
state->env_thread_state(this)->get_agent_thread_local_storage_data();
}
return JVMTI_ERROR_NONE;
} /* end GetThreadLocalStorage */
jvmtiError
JvmtiEnv::GetLoadedClasses(jint* class_count_ptr, jclass** classes_ptr) {
return JvmtiGetLoadedClasses::getLoadedClasses(this, class_count_ptr, classes_ptr);
} /* end GetLoadedClasses */
jvmtiError
JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr) {
return JvmtiGetLoadedClasses::getClassLoaderClasses(this, initiating_loader,
class_count_ptr, classes_ptr);
} /* end GetClassLoaderClasses */
jvmtiError
JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) {
JNI_TRUE : JNI_FALSE;
return JVMTI_ERROR_NONE;
} /* end IsModifiableClass */
jvmtiError
JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
int index;
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
jvmtiClassDefinition* class_definitions =
NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);
NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY);
for (index = 0; index < class_count; index++) {
HandleMark hm(current_thread);
jclass jcls = classes[index];
oop k_mirror = JNIHandles::resolve_external_guard(jcls);
if (k_mirror == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (!k_mirror->is_a(SystemDictionary::Class_klass())) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_UNMODIFIABLE_CLASS;
}
Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
KlassHandle klass(current_thread, k_oop);
jint status = klass->jvmti_class_status();
if (status & (JVMTI_CLASS_STATUS_ERROR)) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (status & (JVMTI_CLASS_STATUS_ARRAY)) {
return JVMTI_ERROR_UNMODIFIABLE_CLASS;
}
instanceKlassHandle ikh(current_thread, k_oop);
if (ikh->get_cached_class_file_bytes() == NULL) {
constantPoolHandle constants(current_thread, ikh->constants());
MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
JvmtiClassFileReconstituter reconstituter(ikh);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
return reconstituter.get_error();
}
class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size();
class_definitions[index].class_bytes = (unsigned char*)
reconstituter.class_file_bytes();
} else {
class_definitions[index].class_byte_count = ikh->get_cached_class_file_len();
class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes();
}
class_definitions[index].klass = jcls;
}
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
VMThread::execute(&op);
return (op.check_error());
} /* end RetransformClasses */
jvmtiError
JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) {
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine);
VMThread::execute(&op);
return (op.check_error());
} /* end RedefineClasses */
jvmtiError
JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) {
oop mirror = JNIHandles::resolve_external_guard(object);
NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT);
if (mirror->klass() == SystemDictionary::Class_klass() &&
!java_lang_Class::is_primitive(mirror)) {
Klass* k = java_lang_Class::as_Klass(mirror);
assert(k != NULL, "class for non-primitive mirror must exist");
} else {
}
return JVMTI_ERROR_NONE;
} /* end GetObjectSize */
jvmtiError
JvmtiEnv::SetNativeMethodPrefix(const char* prefix) {
return prefix == NULL?
SetNativeMethodPrefixes(0, NULL) :
SetNativeMethodPrefixes(1, (char**)&prefix);
} /* end SetNativeMethodPrefix */
jvmtiError
JvmtiEnv::SetNativeMethodPrefixes(jint prefix_count, char** prefixes) {
if (Threads::number_of_threads() == 0) {
return set_native_method_prefixes(prefix_count, prefixes);
} else {
MutexLocker mu(JvmtiThreadState_lock);
return set_native_method_prefixes(prefix_count, prefixes);
}
} /* end SetNativeMethodPrefixes */
jvmtiError
JvmtiEnv::SetEventCallbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks) {
JvmtiEventController::set_event_callbacks(this, callbacks, size_of_callbacks);
return JVMTI_ERROR_NONE;
} /* end SetEventCallbacks */
jvmtiError
JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) {
JavaThread* java_thread = NULL;
if (event_thread != NULL) {
oop thread_oop = JNIHandles::resolve_external_guard(event_thread);
if (thread_oop == NULL) {
return JVMTI_ERROR_INVALID_THREAD;
}
if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
return JVMTI_ERROR_INVALID_THREAD;
}
java_thread = java_lang_Thread::thread(thread_oop);
if (java_thread == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
}
if (!JvmtiEventController::is_valid_event_type(event_type)) {
return JVMTI_ERROR_INVALID_EVENT_TYPE;
}
if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
bool enabled = (mode == JVMTI_ENABLE);
if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) {
return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
}
if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
record_class_file_load_hook_enabled();
}
JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled);
return JVMTI_ERROR_NONE;
} /* end SetEventNotificationMode */
jvmtiError
JvmtiEnv::GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
JvmtiManageCapabilities::get_potential_capabilities(get_capabilities(),
get_prohibited_capabilities(),
capabilities_ptr);
return JVMTI_ERROR_NONE;
} /* end GetPotentialCapabilities */
jvmtiError
JvmtiEnv::AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
return JvmtiManageCapabilities::add_capabilities(get_capabilities(),
get_prohibited_capabilities(),
capabilities_ptr,
get_capabilities());
} /* end AddCapabilities */
jvmtiError
JvmtiEnv::RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
JvmtiManageCapabilities::relinquish_capabilities(get_capabilities(), capabilities_ptr, get_capabilities());
return JVMTI_ERROR_NONE;
} /* end RelinquishCapabilities */
jvmtiError
JvmtiEnv::GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
JvmtiManageCapabilities::copy_capabilities(get_capabilities(), capabilities_ptr);
return JVMTI_ERROR_NONE;
} /* end GetCapabilities */
jvmtiError
JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {
jvmtiPhase phase = get_phase();
if (phase == JVMTI_PHASE_ONLOAD) {
Arguments::append_sysclasspath(segment);
return JVMTI_ERROR_NONE;
} else if (use_version_1_0_semantics()) {
return JVMTI_ERROR_WRONG_PHASE;
} else if (phase == JVMTI_PHASE_LIVE) {
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
if (zip_entry == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
Thread* thread = Thread::current();
HandleMark hm;
Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock());
ObjectLocker ol(loader_lock, thread);
if (TraceClassLoading) {
tty->print_cr("[Opened %s]", zip_entry->name());
}
ClassLoaderExt::append_boot_classpath(zip_entry);
return JVMTI_ERROR_NONE;
} else {
return JVMTI_ERROR_WRONG_PHASE;
}
} /* end AddToBootstrapClassLoaderSearch */
jvmtiError
JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) {
jvmtiPhase phase = get_phase();
if (phase == JVMTI_PHASE_ONLOAD) {
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
if (strcmp("java.class.path", p->key()) == 0) {
p->append_value(segment);
break;
}
}
return JVMTI_ERROR_NONE;
} else if (phase == JVMTI_PHASE_LIVE) {
HandleMark hm;
ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment);
if (zip_entry == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
delete zip_entry; // no longer needed
Thread* THREAD = Thread::current();
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
ObjectLocker ol(loader, THREAD);
Handle path = java_lang_String::create_from_platform_dependent_str(segment, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return JVMTI_ERROR_INTERNAL;
}
instanceKlassHandle loader_ik(THREAD, loader->klass());
{
JavaValue res(T_VOID);
JavaCalls::call_special(&res,
loader,
loader_ik,
vmSymbols::appendToClassPathForInstrumentation_name(),
vmSymbols::appendToClassPathForInstrumentation_signature(),
path,
THREAD);
if (HAS_PENDING_EXCEPTION) {
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
CLEAR_PENDING_EXCEPTION;
if (ex_name == vmSymbols::java_lang_NoSuchMethodError()) {
return JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED;
} else {
return JVMTI_ERROR_INTERNAL;
}
}
}
return JVMTI_ERROR_NONE;
} else {
return JVMTI_ERROR_WRONG_PHASE;
}
} /* end AddToSystemClassLoaderSearch */
jvmtiError
JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetPhase */
jvmtiError
JvmtiEnv::DisposeEnvironment() {
dispose();
return JVMTI_ERROR_NONE;
} /* end DisposeEnvironment */
jvmtiError
JvmtiEnv::SetEnvironmentLocalStorage(const void* data) {
set_env_local_storage(data);
return JVMTI_ERROR_NONE;
} /* end SetEnvironmentLocalStorage */
jvmtiError
JvmtiEnv::GetEnvironmentLocalStorage(void** data_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetEnvironmentLocalStorage */
jvmtiError
JvmtiEnv::GetVersionNumber(jint* version_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetVersionNumber */
jvmtiError
JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) {
if (error < JVMTI_ERROR_NONE || error > JVMTI_ERROR_MAX) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
const char *name = JvmtiUtil::error_name(error);
if (name == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
size_t len = strlen(name) + 1;
jvmtiError err = allocate(len, (unsigned char**)name_ptr);
if (err == JVMTI_ERROR_NONE) {
memcpy(*name_ptr, name, len);
}
return err;
} /* end GetErrorName */
jvmtiError
JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) {
switch (flag) {
case JVMTI_VERBOSE_OTHER:
break;
case JVMTI_VERBOSE_CLASS:
TraceClassLoading = value != 0;
TraceClassUnloading = value != 0;
break;
case JVMTI_VERBOSE_GC:
PrintGC = value != 0;
break;
case JVMTI_VERBOSE_JNI:
PrintJNIResolving = value != 0;
break;
default:
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
};
return JVMTI_ERROR_NONE;
} /* end SetVerboseFlag */
jvmtiError
JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetJLocationFormat */
jvmtiError
JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) {
jint state;
oop thread_oop;
JavaThread* thr;
if (thread == NULL) {
thread_oop = JavaThread::current()->threadObj();
} else {
thread_oop = JNIHandles::resolve_external_guard(thread);
}
if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
return JVMTI_ERROR_INVALID_THREAD;
}
state = (jint)java_lang_Thread::get_thread_status(thread_oop);
thr = java_lang_Thread::thread(thread_oop);
if (thr != NULL) {
JavaThreadState jts = thr->thread_state();
if (thr->is_being_ext_suspended()) {
state |= JVMTI_THREAD_STATE_SUSPENDED;
}
if (jts == _thread_in_native) {
state |= JVMTI_THREAD_STATE_IN_NATIVE;
}
OSThread* osThread = thr->osthread();
if (osThread != NULL && osThread->interrupted()) {
state |= JVMTI_THREAD_STATE_INTERRUPTED;
}
}
return JVMTI_ERROR_NONE;
} /* end GetThreadState */
jvmtiError
JvmtiEnv::GetCurrentThread(jthread* thread_ptr) {
JavaThread* current_thread = JavaThread::current();
return JVMTI_ERROR_NONE;
} /* end GetCurrentThread */
jvmtiError
JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) {
int nthreads = 0;
Handle *thread_objs = NULL;
ResourceMark rm;
HandleMark hm;
ThreadsListEnumerator tle(Thread::current(), true);
nthreads = tle.num_threads();
if (nthreads == 0) {
return JVMTI_ERROR_NONE;
}
thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads);
NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY);
for (int i = 0; i < nthreads; i++) {
thread_objs[i] = Handle(tle.get_threadObj(i));
}
jthread *jthreads = new_jthreadArray(nthreads, thread_objs);
NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY);
return JVMTI_ERROR_NONE;
} /* end GetAllThreads */
jvmtiError
JvmtiEnv::SuspendThread(JavaThread* java_thread) {
if (java_thread->is_hidden_from_external_view()) {
return (JVMTI_ERROR_NONE);
}
{
MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
if (java_thread->is_external_suspend()) {
return (JVMTI_ERROR_THREAD_SUSPENDED);
}
if (java_thread->is_exiting()) { // thread is in the process of exiting
return (JVMTI_ERROR_THREAD_NOT_ALIVE);
}
java_thread->set_external_suspend();
}
if (!JvmtiSuspendControl::suspend(java_thread)) {
return (JVMTI_ERROR_THREAD_NOT_ALIVE);
}
return JVMTI_ERROR_NONE;
} /* end SuspendThread */
jvmtiError
JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) {
int needSafepoint = 0; // > 0 if we need a safepoint
for (int i = 0; i < request_count; i++) {
JavaThread *java_thread = get_JavaThread(request_list[i]);
if (java_thread == NULL) {
results[i] = JVMTI_ERROR_INVALID_THREAD;
continue;
}
if (java_thread->threadObj() == NULL) {
results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
continue;
}
if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) {
results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
continue;
}
if (java_thread->is_hidden_from_external_view()) {
results[i] = JVMTI_ERROR_NONE; // indicate successful suspend
continue;
}
{
MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag);
if (java_thread->is_external_suspend()) {
results[i] = JVMTI_ERROR_THREAD_SUSPENDED;
continue;
}
if (java_thread->is_exiting()) { // thread is in the process of exiting
results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
continue;
}
java_thread->set_external_suspend();
}
if (java_thread->thread_state() == _thread_in_native) {
if (!JvmtiSuspendControl::suspend(java_thread)) {
needSafepoint++;
results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
continue;
}
} else {
needSafepoint++;
}
results[i] = JVMTI_ERROR_NONE; // indicate successful suspend
}
if (needSafepoint > 0) {
VM_ForceSafepoint vfs;
VMThread::execute(&vfs);
}
return JVMTI_ERROR_NONE;
} /* end SuspendThreadList */
jvmtiError
JvmtiEnv::ResumeThread(JavaThread* java_thread) {
if (java_thread->is_hidden_from_external_view()) {
return JVMTI_ERROR_NONE;
}
if (!java_thread->is_being_ext_suspended()) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
if (!JvmtiSuspendControl::resume(java_thread)) {
return JVMTI_ERROR_INTERNAL;
}
return JVMTI_ERROR_NONE;
} /* end ResumeThread */
jvmtiError
JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) {
for (int i = 0; i < request_count; i++) {
JavaThread *java_thread = get_JavaThread(request_list[i]);
if (java_thread == NULL) {
results[i] = JVMTI_ERROR_INVALID_THREAD;
continue;
}
if (java_thread->is_hidden_from_external_view()) {
results[i] = JVMTI_ERROR_NONE; // indicate successful resume
continue;
}
if (!java_thread->is_being_ext_suspended()) {
results[i] = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
continue;
}
if (!JvmtiSuspendControl::resume(java_thread)) {
results[i] = JVMTI_ERROR_INTERNAL;
continue;
}
results[i] = JVMTI_ERROR_NONE; // indicate successful suspend
}
return JVMTI_ERROR_NONE;
} /* end ResumeThreadList */
jvmtiError
JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) {
oop e = JNIHandles::resolve_external_guard(exception);
NULL_CHECK(e, JVMTI_ERROR_NULL_POINTER);
JavaThread::send_async_exception(java_thread->threadObj(), e);
return JVMTI_ERROR_NONE;
} /* end StopThread */
jvmtiError
JvmtiEnv::InterruptThread(jthread thread) {
oop thread_oop = JNIHandles::resolve_external_guard(thread);
if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass()))
return JVMTI_ERROR_INVALID_THREAD;
JavaThread* current_thread = JavaThread::current();
MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock);
JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread));
NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE);
Thread::interrupt(java_thread);
return JVMTI_ERROR_NONE;
} /* end InterruptThread */
jvmtiError
JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
ResourceMark rm;
HandleMark hm;
JavaThread* current_thread = JavaThread::current();
oop thread_oop;
if (thread == NULL) {
thread_oop = current_thread->threadObj();
} else {
thread_oop = JNIHandles::resolve_external_guard(thread);
}
if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass()))
return JVMTI_ERROR_INVALID_THREAD;
Handle thread_obj(current_thread, thread_oop);
Handle name;
ThreadPriority priority;
Handle thread_group;
Handle context_class_loader;
bool is_daemon;
name = Handle(current_thread, java_lang_Thread::name(thread_obj()));
priority = java_lang_Thread::priority(thread_obj());
thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj()));
is_daemon = java_lang_Thread::is_daemon(thread_obj());
oop loader = java_lang_Thread::context_class_loader(thread_obj());
context_class_loader = Handle(current_thread, loader);
{ const char *n;
if (name() != NULL) {
n = java_lang_String::as_utf8_string(name());
} else {
n = UNICODE::as_utf8(NULL, 0);
}
info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1);
if (info_ptr->name == NULL)
return JVMTI_ERROR_OUT_OF_MEMORY;
strcpy(info_ptr->name, n);
}
info_ptr->is_daemon = is_daemon;
info_ptr->priority = priority;
info_ptr->context_class_loader = (context_class_loader.is_null()) ? NULL :
jni_reference(context_class_loader);
info_ptr->thread_group = jni_reference(thread_group);
return JVMTI_ERROR_NONE;
} /* end GetThreadInfo */
jvmtiError
JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
if (java_thread == calling_thread) {
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
} else {
VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list);
VMThread::execute(&op);
err = op.result();
}
jint owned_monitor_count = owned_monitors_list->length();
if (err == JVMTI_ERROR_NONE) {
if ((err = allocate(owned_monitor_count * sizeof(jobject *),
(unsigned char**)owned_monitors_ptr)) == JVMTI_ERROR_NONE) {
for (int i = 0; i < owned_monitor_count; i++) {
(*owned_monitors_ptr)[i] =
((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor;
}
}
}
for (int i = 0; i < owned_monitor_count; i++) {
deallocate((unsigned char*)owned_monitors_list->at(i));
}
delete owned_monitors_list;
return err;
} /* end GetOwnedMonitorInfo */
jvmtiError
JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
if (java_thread == calling_thread) {
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
} else {
VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list);
VMThread::execute(&op);
err = op.result();
}
jint owned_monitor_count = owned_monitors_list->length();
if (err == JVMTI_ERROR_NONE) {
if ((err = allocate(owned_monitor_count * sizeof(jvmtiMonitorStackDepthInfo),
(unsigned char**)monitor_info_ptr)) == JVMTI_ERROR_NONE) {
for (int i = 0; i < owned_monitor_count; i++) {
(*monitor_info_ptr)[i].monitor =
((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor;
(*monitor_info_ptr)[i].stack_depth =
((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->stack_depth;
}
}
}
for (int i = 0; i < owned_monitor_count; i++) {
deallocate((unsigned char*)owned_monitors_list->at(i));
}
delete owned_monitors_list;
return err;
} /* end GetOwnedMonitorStackDepthInfo */
jvmtiError
JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();
if (java_thread == calling_thread) {
err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr);
} else {
VM_GetCurrentContendedMonitor op(this, calling_thread, java_thread, monitor_ptr);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end GetCurrentContendedMonitor */
jvmtiError
JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) {
oop thread_oop = JNIHandles::resolve_external_guard(thread);
if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
return JVMTI_ERROR_INVALID_THREAD;
}
if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
return JVMTI_ERROR_INVALID_PRIORITY;
}
JavaThread* current_thread = JavaThread::current();
Handle thread_hndl(current_thread, thread_oop);
{
MutexLocker mu(Threads_lock); // grab Threads_lock
JvmtiAgentThread *new_thread = new JvmtiAgentThread(this, proc, arg);
if (new_thread == NULL || new_thread->osthread() == NULL) {
if (new_thread) delete new_thread;
return JVMTI_ERROR_OUT_OF_MEMORY;
}
java_lang_Thread::set_thread(thread_hndl(), new_thread);
java_lang_Thread::set_priority(thread_hndl(), (ThreadPriority)priority);
java_lang_Thread::set_daemon(thread_hndl());
new_thread->set_threadObj(thread_hndl());
Threads::add(new_thread);
Thread::start(new_thread);
} // unlock Threads_lock
return JVMTI_ERROR_NONE;
} /* end RunAgentThread */
jvmtiError
JvmtiEnv::GetTopThreadGroups(jint* group_count_ptr, jthreadGroup** groups_ptr) {
JavaThread* current_thread = JavaThread::current();
NULL_CHECK(*groups_ptr, JVMTI_ERROR_OUT_OF_MEMORY);
{
HandleMark hm(current_thread);
Handle system_thread_group(current_thread, Universe::system_thread_group());
}
return JVMTI_ERROR_NONE;
} /* end GetTopThreadGroups */
jvmtiError
JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) {
ResourceMark rm;
HandleMark hm;
JavaThread* current_thread = JavaThread::current();
Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group));
NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP);
typeArrayHandle name;
Handle parent_group;
bool is_daemon;
ThreadPriority max_priority;
name = typeArrayHandle(current_thread,
java_lang_ThreadGroup::name(group_obj()));
parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj()));
is_daemon = java_lang_ThreadGroup::is_daemon(group_obj());
max_priority = java_lang_ThreadGroup::maxPriority(group_obj());
info_ptr->is_daemon = is_daemon;
info_ptr->max_priority = max_priority;
info_ptr->parent = jni_reference(parent_group);
if (name() != NULL) {
const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1);
NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY);
strcpy(info_ptr->name, n);
} else {
info_ptr->name = NULL;
}
return JVMTI_ERROR_NONE;
} /* end GetThreadGroupInfo */
jvmtiError
JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr) {
JavaThread* current_thread = JavaThread::current();
oop group_obj = (oop) JNIHandles::resolve_external_guard(group);
NULL_CHECK(group_obj, JVMTI_ERROR_INVALID_THREAD_GROUP);
Handle *thread_objs = NULL;
Handle *group_objs = NULL;
int nthreads = 0;
int ngroups = 0;
int hidden_threads = 0;
ResourceMark rm;
HandleMark hm;
Handle group_hdl(current_thread, group_obj);
{
ObjectLocker ol(group_hdl, current_thread);
nthreads = java_lang_ThreadGroup::nthreads(group_hdl());
ngroups = java_lang_ThreadGroup::ngroups(group_hdl());
if (nthreads > 0) {
objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl());
assert(nthreads <= threads->length(), "too many threads");
thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads);
for (int i = 0, j = 0; i < nthreads; i++) {
oop thread_obj = threads->obj_at(i);
assert(thread_obj != NULL, "thread_obj is NULL");
JavaThread *javathread = java_lang_Thread::thread(thread_obj);
if (javathread != NULL && javathread->is_hidden_from_external_view()) {
hidden_threads++;
continue;
}
thread_objs[j++] = Handle(current_thread, thread_obj);
}
nthreads -= hidden_threads;
}
if (ngroups > 0) {
objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl());
assert(ngroups <= groups->length(), "too many threads");
group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups);
for (int i = 0; i < ngroups; i++) {
oop group_obj = groups->obj_at(i);
assert(group_obj != NULL, "group_obj != NULL");
group_objs[i] = Handle(current_thread, group_obj);
}
}
} // ThreadGroup unlocked here
if ((nthreads > 0) && (*threads_ptr == NULL)) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
if ((ngroups > 0) && (*groups_ptr == NULL)) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
return JVMTI_ERROR_NONE;
} /* end GetThreadGroupChildren */
jvmtiError
JvmtiEnv::GetStackTrace(JavaThread* java_thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
if (java_thread == JavaThread::current()) {
err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr);
} else {
VM_GetStackTrace op(this, java_thread, start_depth, max_frame_count, frame_buffer, count_ptr);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end GetStackTrace */
jvmtiError
JvmtiEnv::GetAllStackTraces(jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();
VM_GetAllStackTraces op(this, calling_thread, max_frame_count);
VMThread::execute(&op);
err = op.result();
return err;
} /* end GetAllStackTraces */
jvmtiError
JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
VM_GetThreadListStackTraces op(this, thread_count, thread_list, max_frame_count);
VMThread::execute(&op);
err = op.result();
if (err == JVMTI_ERROR_NONE) {
}
return err;
} /* end GetThreadListStackTraces */
jvmtiError
JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
err = get_frame_count(state, count_ptr);
} else {
VM_GetFrameCount op(this, state, count_ptr);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end GetFrameCount */
jvmtiError
JvmtiEnv::PopFrame(JavaThread* java_thread) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
uint32_t debug_bits = 0;
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
if (java_thread->popframe_condition() != JavaThread::popframe_inactive) {
return JVMTI_ERROR_INTERNAL;
}
{
OSThread* osThread = java_thread->osthread();
if (osThread->get_state() == MONITOR_WAIT) {
return JVMTI_ERROR_OPAQUE_FRAME;
}
}
{
ResourceMark rm(current_thread);
int frame_count = 0;
bool is_interpreted[2];
intptr_t *frame_sp[2];
for (vframeStream vfs(java_thread, true); !vfs.at_end(); vfs.next()) {
methodHandle mh(current_thread, vfs.method());
if (mh->is_native()) return(JVMTI_ERROR_OPAQUE_FRAME);
is_interpreted[frame_count] = vfs.is_interpreted_frame();
frame_sp[frame_count] = vfs.frame_id();
if (++frame_count > 1) break;
}
if (frame_count < 2) {
if(vframeFor(java_thread, 1) == NULL) {
return JVMTI_ERROR_NO_MORE_FRAMES;
} else {
return JVMTI_ERROR_OPAQUE_FRAME;
}
}
for (int i = 0; i < 2; i++) {
if (!is_interpreted[i]) {
Deoptimization::deoptimize_frame(java_thread, frame_sp[i]);
}
}
state->update_for_pop_top_frame();
java_thread->set_popframe_condition(JavaThread::popframe_pending_bit);
state->set_pending_step_for_popframe();
}
return JVMTI_ERROR_NONE;
} /* end PopFrame */
jvmtiError
JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
err = get_frame_location(java_thread, depth, method_ptr, location_ptr);
} else {
VM_GetFrameLocation op(this, java_thread, depth, method_ptr, location_ptr);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end GetFrameLocation */
jvmtiError
JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) {
ResourceMark rm;
uint32_t debug_bits = 0;
JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
if (TraceJVMTICalls) {
JvmtiSuspendControl::print();
}
vframe *vf = vframeFor(java_thread, depth);
if (vf == NULL) {
return JVMTI_ERROR_NO_MORE_FRAMES;
}
if (!vf->is_java_frame() || ((javaVFrame*) vf)->method()->is_native()) {
return JVMTI_ERROR_OPAQUE_FRAME;
}
assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL");
int frame_number = state->count_frames() - depth;
state->env_thread_state(this)->set_frame_pop(frame_number);
return JVMTI_ERROR_NONE;
} /* end NotifyFramePop */
jvmtiError
JvmtiEnv::ForceEarlyReturnObject(JavaThread* java_thread, jobject value) {
jvalue val;
val.l = value;
return force_early_return(java_thread, val, atos);
} /* end ForceEarlyReturnObject */
jvmtiError
JvmtiEnv::ForceEarlyReturnInt(JavaThread* java_thread, jint value) {
jvalue val;
val.i = value;
return force_early_return(java_thread, val, itos);
} /* end ForceEarlyReturnInt */
jvmtiError
JvmtiEnv::ForceEarlyReturnLong(JavaThread* java_thread, jlong value) {
jvalue val;
val.j = value;
return force_early_return(java_thread, val, ltos);
} /* end ForceEarlyReturnLong */
jvmtiError
JvmtiEnv::ForceEarlyReturnFloat(JavaThread* java_thread, jfloat value) {
jvalue val;
val.f = value;
return force_early_return(java_thread, val, ftos);
} /* end ForceEarlyReturnFloat */
jvmtiError
JvmtiEnv::ForceEarlyReturnDouble(JavaThread* java_thread, jdouble value) {
jvalue val;
val.d = value;
return force_early_return(java_thread, val, dtos);
} /* end ForceEarlyReturnDouble */
jvmtiError
JvmtiEnv::ForceEarlyReturnVoid(JavaThread* java_thread) {
jvalue val;
val.j = 0L;
return force_early_return(java_thread, val, vtos);
} /* end ForceEarlyReturnVoid */
jvmtiError
JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) {
Klass* k_oop = NULL;
if (klass != NULL) {
oop k_mirror = JNIHandles::resolve_external_guard(klass);
if (k_mirror == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
k_oop = java_lang_Class::as_Klass(k_mirror);
if (k_oop == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
}
if (initial_object != NULL) {
oop init_obj = JNIHandles::resolve_external_guard(initial_object);
if (init_obj == NULL) {
return JVMTI_ERROR_INVALID_OBJECT;
}
}
Thread *thread = Thread::current();
HandleMark hm(thread);
KlassHandle kh (thread, k_oop);
TraceTime t("FollowReferences", TraceJVMTIObjectTagging);
JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, kh, initial_object, callbacks, user_data);
return JVMTI_ERROR_NONE;
} /* end FollowReferences */
jvmtiError
JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) {
Klass* k_oop = NULL;
if (klass != NULL) {
oop k_mirror = JNIHandles::resolve_external_guard(klass);
if (k_mirror == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
k_oop = java_lang_Class::as_Klass(k_mirror);
if (k_oop == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
}
Thread *thread = Thread::current();
HandleMark hm(thread);
KlassHandle kh (thread, k_oop);
TraceTime t("IterateThroughHeap", TraceJVMTIObjectTagging);
JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, kh, callbacks, user_data);
return JVMTI_ERROR_NONE;
} /* end IterateThroughHeap */
jvmtiError
JvmtiEnv::GetTag(jobject object, jlong* tag_ptr) {
oop o = JNIHandles::resolve_external_guard(object);
NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT);
return JVMTI_ERROR_NONE;
} /* end GetTag */
jvmtiError
JvmtiEnv::SetTag(jobject object, jlong tag) {
oop o = JNIHandles::resolve_external_guard(object);
NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT);
JvmtiTagMap::tag_map_for(this)->set_tag(object, tag);
return JVMTI_ERROR_NONE;
} /* end SetTag */
jvmtiError
JvmtiEnv::GetObjectsWithTags(jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) {
TraceTime t("GetObjectsWithTags", TraceJVMTIObjectTagging);
return JvmtiTagMap::tag_map_for(this)->get_objects_with_tags((jlong*)tags, tag_count, count_ptr, object_result_ptr, tag_result_ptr);
} /* end GetObjectsWithTags */
jvmtiError
JvmtiEnv::ForceGarbageCollection() {
Universe::heap()->collect(GCCause::_jvmti_force_gc);
return JVMTI_ERROR_NONE;
} /* end ForceGarbageCollection */
jvmtiError
JvmtiEnv::IterateOverObjectsReachableFromObject(jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data) {
oop o = JNIHandles::resolve_external_guard(object);
NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT);
JvmtiTagMap::tag_map_for(this)->iterate_over_objects_reachable_from_object(object, object_reference_callback, user_data);
return JVMTI_ERROR_NONE;
} /* end IterateOverObjectsReachableFromObject */
jvmtiError
JvmtiEnv::IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data) {
TraceTime t("IterateOverReachableObjects", TraceJVMTIObjectTagging);
JvmtiTagMap::tag_map_for(this)->iterate_over_reachable_objects(heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
return JVMTI_ERROR_NONE;
} /* end IterateOverReachableObjects */
jvmtiError
JvmtiEnv::IterateOverHeap(jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) {
TraceTime t("IterateOverHeap", TraceJVMTIObjectTagging);
Thread *thread = Thread::current();
HandleMark hm(thread);
JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, KlassHandle(), heap_object_callback, user_data);
return JVMTI_ERROR_NONE;
} /* end IterateOverHeap */
jvmtiError
JvmtiEnv::IterateOverInstancesOfClass(oop k_mirror, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) {
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
if (k_oop == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
Thread *thread = Thread::current();
HandleMark hm(thread);
KlassHandle klass (thread, k_oop);
TraceTime t("IterateOverInstancesOfClass", TraceJVMTIObjectTagging);
JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, klass, heap_object_callback, user_data);
return JVMTI_ERROR_NONE;
} /* end IterateOverInstancesOfClass */
jvmtiError
JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject* value_ptr) {
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
VM_GetOrSetLocal op(java_thread, current_thread, depth, slot);
VMThread::execute(&op);
jvmtiError err = op.result();
if (err != JVMTI_ERROR_NONE) {
return err;
} else {
return JVMTI_ERROR_NONE;
}
} /* end GetLocalObject */
jvmtiError
JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
VM_GetReceiver op(java_thread, current_thread, depth);
VMThread::execute(&op);
jvmtiError err = op.result();
if (err != JVMTI_ERROR_NONE) {
return err;
} else {
return JVMTI_ERROR_NONE;
}
} /* end GetLocalInstance */
jvmtiError
JvmtiEnv::GetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint* value_ptr) {
ResourceMark rm;
VM_GetOrSetLocal op(java_thread, depth, slot, T_INT);
VMThread::execute(&op);
return op.result();
} /* end GetLocalInt */
jvmtiError
JvmtiEnv::GetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong* value_ptr) {
ResourceMark rm;
VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG);
VMThread::execute(&op);
return op.result();
} /* end GetLocalLong */
jvmtiError
JvmtiEnv::GetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat* value_ptr) {
ResourceMark rm;
VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT);
VMThread::execute(&op);
return op.result();
} /* end GetLocalFloat */
jvmtiError
JvmtiEnv::GetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble* value_ptr) {
ResourceMark rm;
VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE);
VMThread::execute(&op);
return op.result();
} /* end GetLocalDouble */
jvmtiError
JvmtiEnv::SetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject value) {
ResourceMark rm;
jvalue val;
val.l = value;
VM_GetOrSetLocal op(java_thread, depth, slot, T_OBJECT, val);
VMThread::execute(&op);
return op.result();
} /* end SetLocalObject */
jvmtiError
JvmtiEnv::SetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint value) {
ResourceMark rm;
jvalue val;
val.i = value;
VM_GetOrSetLocal op(java_thread, depth, slot, T_INT, val);
VMThread::execute(&op);
return op.result();
} /* end SetLocalInt */
jvmtiError
JvmtiEnv::SetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong value) {
ResourceMark rm;
jvalue val;
val.j = value;
VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG, val);
VMThread::execute(&op);
return op.result();
} /* end SetLocalLong */
jvmtiError
JvmtiEnv::SetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat value) {
ResourceMark rm;
jvalue val;
val.f = value;
VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT, val);
VMThread::execute(&op);
return op.result();
} /* end SetLocalFloat */
jvmtiError
JvmtiEnv::SetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble value) {
ResourceMark rm;
jvalue val;
val.d = value;
VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE, val);
VMThread::execute(&op);
return op.result();
} /* end SetLocalDouble */
jvmtiError
JvmtiEnv::SetBreakpoint(Method* method_oop, jlocation location) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
if (location < 0) { // simple invalid location check first
return JVMTI_ERROR_INVALID_LOCATION;
}
if (location >= (jlocation) method_oop->code_size()) {
return JVMTI_ERROR_INVALID_LOCATION;
}
ResourceMark rm;
JvmtiBreakpoint bp(method_oop, location);
JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
if (jvmti_breakpoints.set(bp) == JVMTI_ERROR_DUPLICATE)
return JVMTI_ERROR_DUPLICATE;
if (TraceJVMTICalls) {
jvmti_breakpoints.print();
}
return JVMTI_ERROR_NONE;
} /* end SetBreakpoint */
jvmtiError
JvmtiEnv::ClearBreakpoint(Method* method_oop, jlocation location) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
if (location < 0) { // simple invalid location check first
return JVMTI_ERROR_INVALID_LOCATION;
}
if (location >= (jlocation) method_oop->code_size()) {
return JVMTI_ERROR_INVALID_LOCATION;
}
JvmtiBreakpoint bp(method_oop, location);
JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
if (jvmti_breakpoints.clear(bp) == JVMTI_ERROR_NOT_FOUND)
return JVMTI_ERROR_NOT_FOUND;
if (TraceJVMTICalls) {
jvmti_breakpoints.print();
}
return JVMTI_ERROR_NONE;
} /* end ClearBreakpoint */
jvmtiError
JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) {
if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_access_watched(true);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true);
return JVMTI_ERROR_NONE;
} /* end SetFieldAccessWatch */
jvmtiError
JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) {
if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_access_watched(false);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false);
return JVMTI_ERROR_NONE;
} /* end ClearFieldAccessWatch */
jvmtiError
JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) {
if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE;
fdesc_ptr->set_is_field_modification_watched(true);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true);
return JVMTI_ERROR_NONE;
} /* end SetFieldModificationWatch */
jvmtiError
JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) {
if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND;
fdesc_ptr->set_is_field_modification_watched(false);
JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false);
return JVMTI_ERROR_NONE;
} /* end ClearFieldModificationWatch */
jvmtiError
JvmtiEnv::GetClassSignature(oop k_mirror, char** signature_ptr, char** generic_ptr) {
ResourceMark rm;
bool isPrimitive = java_lang_Class::is_primitive(k_mirror);
Klass* k = NULL;
if (!isPrimitive) {
k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
}
if (signature_ptr != NULL) {
char* result = NULL;
if (isPrimitive) {
char tchar = type2char(java_lang_Class::primitive_type(k_mirror));
result = (char*) jvmtiMalloc(2);
result[0] = tchar;
result[1] = '\0';
} else {
const char* class_sig = k->signature_name();
result = (char *) jvmtiMalloc(strlen(class_sig)+1);
strcpy(result, class_sig);
}
}
if (generic_ptr != NULL) {
if (!isPrimitive && k->oop_is_instance()) {
Symbol* soo = InstanceKlass::cast(k)->generic_signature();
if (soo != NULL) {
const char *gen_sig = soo->as_C_string();
if (gen_sig != NULL) {
char* gen_result;
jvmtiError err = allocate(strlen(gen_sig) + 1,
(unsigned char **)&gen_result);
if (err != JVMTI_ERROR_NONE) {
return err;
}
strcpy(gen_result, gen_sig);
}
}
}
}
return JVMTI_ERROR_NONE;
} /* end GetClassSignature */
jvmtiError
JvmtiEnv::GetClassStatus(oop k_mirror, jint* status_ptr) {
jint result = 0;
if (java_lang_Class::is_primitive(k_mirror)) {
result |= JVMTI_CLASS_STATUS_PRIMITIVE;
} else {
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
result = k->jvmti_class_status();
}
return JVMTI_ERROR_NONE;
} /* end GetClassStatus */
jvmtiError
JvmtiEnv::GetSourceFileName(oop k_mirror, char** source_name_ptr) {
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
Klass* k_klass = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS);
if (!k_klass->oop_is_instance()) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
Symbol* sfnOop = InstanceKlass::cast(k_klass)->source_file_name();
NULL_CHECK(sfnOop, JVMTI_ERROR_ABSENT_INFORMATION);
{
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
const char* sfncp = (const char*) sfnOop->as_C_string();
strcpy(*source_name_ptr, sfncp);
}
return JVMTI_ERROR_NONE;
} /* end GetSourceFileName */
jvmtiError
JvmtiEnv::GetClassModifiers(oop k_mirror, jint* modifiers_ptr) {
JavaThread* current_thread = JavaThread::current();
jint result = 0;
if (!java_lang_Class::is_primitive(k_mirror)) {
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
result = k->compute_modifier_flags(current_thread);
JavaThread* THREAD = current_thread; // pass to macros
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return JVMTI_ERROR_INTERNAL;
};
if(k->is_super()) {
result |= JVM_ACC_SUPER;
}
} else {
result = (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC);
}
return JVMTI_ERROR_NONE;
} /* end GetClassModifiers */
jvmtiError
JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** methods_ptr) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) {
return JVMTI_ERROR_CLASS_NOT_PREPARED;
}
if (!k->oop_is_instance()) {
return JVMTI_ERROR_NONE;
}
instanceKlassHandle instanceK_h(current_thread, k);
int result_length = instanceK_h->methods()->length();
jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID));
int index;
if (JvmtiExport::can_maintain_original_method_order()) {
for (index = 0; index < result_length; index++) {
Method* m = instanceK_h->methods()->at(index);
int original_index = instanceK_h->method_ordering()->at(index);
assert(original_index >= 0 && original_index < result_length, "invalid original method index");
jmethodID id = m->jmethod_id();
result_list[original_index] = id;
}
} else {
for (index = 0; index < result_length; index++) {
Method* m = instanceK_h->methods()->at(index);
jmethodID id = m->jmethod_id();
result_list[index] = id;
}
}
return JVMTI_ERROR_NONE;
} /* end GetClassMethods */
jvmtiError
JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ptr) {
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) {
return JVMTI_ERROR_CLASS_NOT_PREPARED;
}
if (!k->oop_is_instance()) {
return JVMTI_ERROR_NONE;
}
instanceKlassHandle instanceK_h(current_thread, k);
int result_count = 0;
FilteredFieldStream flds(instanceK_h, true, true);
result_count = flds.field_count();
jfieldID* result_list = (jfieldID*) jvmtiMalloc(result_count * sizeof(jfieldID));
int id_index = (result_count - 1);
for (FilteredFieldStream src_st(instanceK_h, true, true); !src_st.eos(); src_st.next()) {
result_list[id_index--] = jfieldIDWorkaround::to_jfieldID(
instanceK_h, src_st.offset(),
src_st.access_flags().is_static());
}
assert(id_index == -1, "just checking");
return JVMTI_ERROR_NONE;
} /* end GetClassFields */
jvmtiError
JvmtiEnv::GetImplementedInterfaces(oop k_mirror, jint* interface_count_ptr, jclass** interfaces_ptr) {
{
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) ))
return JVMTI_ERROR_CLASS_NOT_PREPARED;
if (!k->oop_is_instance()) {
return JVMTI_ERROR_NONE;
}
Array<Klass*>* interface_list = InstanceKlass::cast(k)->local_interfaces();
const int result_length = (interface_list == NULL ? 0 : interface_list->length());
jclass* result_list = (jclass*) jvmtiMalloc(result_length * sizeof(jclass));
for (int i_index = 0; i_index < result_length; i_index += 1) {
Klass* klass_at = interface_list->at(i_index);
assert(klass_at->is_klass(), "interfaces must be Klass*s");
assert(klass_at->is_interface(), "interfaces must be interfaces");
oop mirror_at = klass_at->java_mirror();
Handle handle_at = Handle(current_thread, mirror_at);
result_list[i_index] = (jclass) jni_reference(handle_at);
}
}
return JVMTI_ERROR_NONE;
} /* end GetImplementedInterfaces */
jvmtiError
JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* major_version_ptr) {
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
Thread *thread = Thread::current();
HandleMark hm(thread);
KlassHandle klass(thread, k_oop);
jint status = klass->jvmti_class_status();
if (status & (JVMTI_CLASS_STATUS_ERROR)) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (status & (JVMTI_CLASS_STATUS_ARRAY)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
instanceKlassHandle ik(thread, k_oop);
return JVMTI_ERROR_NONE;
} /* end GetClassVersionNumbers */
jvmtiError
JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* constant_pool_byte_count_ptr, unsigned char** constant_pool_bytes_ptr) {
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
Thread *thread = Thread::current();
HandleMark hm(thread);
ResourceMark rm(thread);
KlassHandle klass(thread, k_oop);
jint status = klass->jvmti_class_status();
if (status & (JVMTI_CLASS_STATUS_ERROR)) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (status & (JVMTI_CLASS_STATUS_ARRAY)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
instanceKlassHandle ikh(thread, k_oop);
constantPoolHandle constants(thread, ikh->constants());
MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
JvmtiConstantPoolReconstituter reconstituter(ikh);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
return reconstituter.get_error();
}
unsigned char *cpool_bytes;
int cpool_size = reconstituter.cpool_size();
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
return reconstituter.get_error();
}
jvmtiError res = allocate(cpool_size, &cpool_bytes);
if (res != JVMTI_ERROR_NONE) {
return res;
}
reconstituter.copy_cpool_bytes(cpool_bytes);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
return reconstituter.get_error();
}
return JVMTI_ERROR_NONE;
} /* end GetConstantPool */
jvmtiError
JvmtiEnv::IsInterface(oop k_mirror, jboolean* is_interface_ptr) {
{
bool result = false;
if (!java_lang_Class::is_primitive(k_mirror)) {
Klass* k = java_lang_Class::as_Klass(k_mirror);
if (k != NULL && k->is_interface()) {
result = true;
}
}
}
return JVMTI_ERROR_NONE;
} /* end IsInterface */
jvmtiError
JvmtiEnv::IsArrayClass(oop k_mirror, jboolean* is_array_class_ptr) {
{
bool result = false;
if (!java_lang_Class::is_primitive(k_mirror)) {
Klass* k = java_lang_Class::as_Klass(k_mirror);
if (k != NULL && k->oop_is_array()) {
result = true;
}
}
}
return JVMTI_ERROR_NONE;
} /* end IsArrayClass */
jvmtiError
JvmtiEnv::GetClassLoader(oop k_mirror, jobject* classloader_ptr) {
{
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_NONE;
}
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
oop result_oop = k->class_loader();
if (result_oop == NULL) {
return JVMTI_ERROR_NONE;
}
Handle result_handle = Handle(current_thread, result_oop);
jclass result_jnihandle = (jclass) jni_reference(result_handle);
}
return JVMTI_ERROR_NONE;
} /* end GetClassLoader */
jvmtiError
JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_ptr) {
{
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
Klass* k = java_lang_Class::as_Klass(k_mirror);
NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
if (!k->oop_is_instance()) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
char* sde = InstanceKlass::cast(k)->source_debug_extension();
NULL_CHECK(sde, JVMTI_ERROR_ABSENT_INFORMATION);
{
strcpy(*source_debug_extension_ptr, sde);
}
}
return JVMTI_ERROR_NONE;
} /* end GetSourceDebugExtension */
jvmtiError
JvmtiEnv::GetObjectHashCode(jobject object, jint* hash_code_ptr) {
oop mirror = JNIHandles::resolve_external_guard(object);
NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT);
NULL_CHECK(hash_code_ptr, JVMTI_ERROR_NULL_POINTER);
{
jint result = (jint) mirror->identity_hash();
}
return JVMTI_ERROR_NONE;
} /* end GetObjectHashCode */
jvmtiError
JvmtiEnv::GetObjectMonitorUsage(jobject object, jvmtiMonitorUsage* info_ptr) {
JavaThread* calling_thread = JavaThread::current();
jvmtiError err = get_object_monitor_usage(calling_thread, object, info_ptr);
if (err == JVMTI_ERROR_THREAD_NOT_SUSPENDED) {
VM_GetObjectMonitorUsage op(this, calling_thread, object, info_ptr);
VMThread::execute(&op);
err = op.result();
}
return err;
} /* end GetObjectMonitorUsage */
jvmtiError
JvmtiEnv::GetFieldName(fieldDescriptor* fdesc_ptr, char** name_ptr, char** signature_ptr, char** generic_ptr) {
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
if (name_ptr == NULL) {
} else {
const char* fieldName = fdesc_ptr->name()->as_C_string();
if (*name_ptr == NULL)
return JVMTI_ERROR_OUT_OF_MEMORY;
strcpy(*name_ptr, fieldName);
}
if (signature_ptr== NULL) {
} else {
const char* fieldSignature = fdesc_ptr->signature()->as_C_string();
if (*signature_ptr == NULL)
return JVMTI_ERROR_OUT_OF_MEMORY;
strcpy(*signature_ptr, fieldSignature);
}
if (generic_ptr != NULL) {
Symbol* soop = fdesc_ptr->generic_signature();
if (soop != NULL) {
const char* gen_sig = soop->as_C_string();
if (gen_sig != NULL) {
jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr);
if (err != JVMTI_ERROR_NONE) {
return err;
}
strcpy(*generic_ptr, gen_sig);
}
}
}
return JVMTI_ERROR_NONE;
} /* end GetFieldName */
jvmtiError
JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetFieldDeclaringClass */
jvmtiError
JvmtiEnv::GetFieldModifiers(fieldDescriptor* fdesc_ptr, jint* modifiers_ptr) {
AccessFlags resultFlags = fdesc_ptr->access_flags();
jint result = resultFlags.as_int();
return JVMTI_ERROR_NONE;
} /* end GetFieldModifiers */
jvmtiError
JvmtiEnv::IsFieldSynthetic(fieldDescriptor* fdesc_ptr, jboolean* is_synthetic_ptr) {
return JVMTI_ERROR_NONE;
} /* end IsFieldSynthetic */
jvmtiError
JvmtiEnv::GetMethodName(Method* method_oop, char** name_ptr, char** signature_ptr, char** generic_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread); // get the utf8 name and signature
if (name_ptr == NULL) {
} else {
const char* utf8_name = (const char *) method_oop->name()->as_utf8();
strcpy(*name_ptr, utf8_name);
}
if (signature_ptr == NULL) {
} else {
const char* utf8_signature = (const char *) method_oop->signature()->as_utf8();
strcpy(*signature_ptr, utf8_signature);
}
if (generic_ptr != NULL) {
Symbol* soop = method_oop->generic_signature();
if (soop != NULL) {
const char* gen_sig = soop->as_C_string();
if (gen_sig != NULL) {
jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr);
if (err != JVMTI_ERROR_NONE) {
return err;
}
strcpy(*generic_ptr, gen_sig);
}
}
}
return JVMTI_ERROR_NONE;
} /* end GetMethodName */
jvmtiError
JvmtiEnv::GetMethodDeclaringClass(Method* method_oop, jclass* declaring_class_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*declaring_class_ptr) = get_jni_class_non_null(method_oop->method_holder());
return JVMTI_ERROR_NONE;
} /* end GetMethodDeclaringClass */
jvmtiError
JvmtiEnv::GetMethodModifiers(Method* method_oop, jint* modifiers_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*modifiers_ptr) = method_oop->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;
return JVMTI_ERROR_NONE;
} /* end GetMethodModifiers */
jvmtiError
JvmtiEnv::GetMaxLocals(Method* method_oop, jint* max_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*max_ptr) = method_oop->max_locals();
return JVMTI_ERROR_NONE;
} /* end GetMaxLocals */
jvmtiError
JvmtiEnv::GetArgumentsSize(Method* method_oop, jint* size_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*size_ptr) = method_oop->size_of_parameters();
return JVMTI_ERROR_NONE;
} /* end GetArgumentsSize */
jvmtiError
JvmtiEnv::GetLineNumberTable(Method* method_oop, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
if (!method_oop->has_linenumber_table()) {
return (JVMTI_ERROR_ABSENT_INFORMATION);
}
jint num_entries = 0;
CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table());
while (stream.read_pair()) {
num_entries++;
}
jvmtiLineNumberEntry *jvmti_table =
(jvmtiLineNumberEntry *)jvmtiMalloc(num_entries * (sizeof(jvmtiLineNumberEntry)));
if (num_entries > 0) {
int index = 0;
CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table());
while (stream.read_pair()) {
jvmti_table[index].start_location = (jlocation) stream.bci();
jvmti_table[index].line_number = (jint) stream.line();
index++;
}
assert(index == num_entries, "sanity check");
}
(*entry_count_ptr) = num_entries;
(*table_ptr) = jvmti_table;
return JVMTI_ERROR_NONE;
} /* end GetLineNumberTable */
jvmtiError
JvmtiEnv::GetMethodLocation(Method* method_oop, jlocation* start_location_ptr, jlocation* end_location_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*end_location_ptr) = (jlocation) (method_oop->code_size() - 1);
if (method_oop->code_size() == 0) {
(*start_location_ptr) = (jlocation)(-1);
} else {
(*start_location_ptr) = (jlocation)(0);
}
return JVMTI_ERROR_NONE;
} /* end GetMethodLocation */
jvmtiError
JvmtiEnv::GetLocalVariableTable(Method* method_oop, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
JavaThread* current_thread = JavaThread::current();
InstanceKlass* ik = method_oop->method_holder();
if (!ik->access_flags().has_localvariable_table()) {
return (JVMTI_ERROR_ABSENT_INFORMATION);
}
ConstantPool* constants = method_oop->constants();
NULL_CHECK(constants, JVMTI_ERROR_ABSENT_INFORMATION);
jint num_entries = method_oop->localvariable_table_length();
jvmtiLocalVariableEntry *jvmti_table = (jvmtiLocalVariableEntry *)
jvmtiMalloc(num_entries * (sizeof(jvmtiLocalVariableEntry)));
if (num_entries > 0) {
LocalVariableTableElement* table = method_oop->localvariable_table_start();
for (int i = 0; i < num_entries; i++) {
jlocation start_location = (jlocation) table[i].start_bci;
jint length = (jint) table[i].length;
int name_index = (int) table[i].name_cp_index;
int signature_index = (int) table[i].descriptor_cp_index;
int generic_signature_index = (int) table[i].signature_cp_index;
jint slot = (jint) table[i].slot;
char *name_buf = NULL;
char *sig_buf = NULL;
char *gen_sig_buf = NULL;
{
ResourceMark rm(current_thread);
const char *utf8_name = (const char *) constants->symbol_at(name_index)->as_utf8();
name_buf = (char *) jvmtiMalloc(strlen(utf8_name)+1);
strcpy(name_buf, utf8_name);
const char *utf8_signature = (const char *) constants->symbol_at(signature_index)->as_utf8();
sig_buf = (char *) jvmtiMalloc(strlen(utf8_signature)+1);
strcpy(sig_buf, utf8_signature);
if (generic_signature_index > 0) {
const char *utf8_gen_sign = (const char *)
constants->symbol_at(generic_signature_index)->as_utf8();
gen_sig_buf = (char *) jvmtiMalloc(strlen(utf8_gen_sign)+1);
strcpy(gen_sig_buf, utf8_gen_sign);
}
}
jvmti_table[i].start_location = start_location;
jvmti_table[i].length = length;
jvmti_table[i].name = name_buf;
jvmti_table[i].signature = sig_buf;
jvmti_table[i].generic_signature = gen_sig_buf;
jvmti_table[i].slot = slot;
}
}
(*entry_count_ptr) = num_entries;
(*table_ptr) = jvmti_table;
return JVMTI_ERROR_NONE;
} /* end GetLocalVariableTable */
jvmtiError
JvmtiEnv::GetBytecodes(Method* method_oop, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
HandleMark hm;
methodHandle method(method_oop);
jint size = (jint)method->code_size();
jvmtiError err = allocate(size, bytecodes_ptr);
if (err != JVMTI_ERROR_NONE) {
return err;
}
(*bytecode_count_ptr) = size;
JvmtiClassFileReconstituter::copy_bytecodes(method, *bytecodes_ptr);
return JVMTI_ERROR_NONE;
} /* end GetBytecodes */
jvmtiError
JvmtiEnv::IsMethodNative(Method* method_oop, jboolean* is_native_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*is_native_ptr) = method_oop->is_native();
return JVMTI_ERROR_NONE;
} /* end IsMethodNative */
jvmtiError
JvmtiEnv::IsMethodSynthetic(Method* method_oop, jboolean* is_synthetic_ptr) {
NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID);
(*is_synthetic_ptr) = method_oop->is_synthetic();
return JVMTI_ERROR_NONE;
} /* end IsMethodSynthetic */
jvmtiError
JvmtiEnv::IsMethodObsolete(Method* method_oop, jboolean* is_obsolete_ptr) {
if (use_version_1_0_semantics() &&
get_capabilities()->can_redefine_classes == 0) {
return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
}
if (method_oop == NULL || method_oop->is_obsolete()) {
} else {
}
return JVMTI_ERROR_NONE;
} /* end IsMethodObsolete */
jvmtiError
JvmtiEnv::CreateRawMonitor(const char* name, jrawMonitorID* monitor_ptr) {
JvmtiRawMonitor* rmonitor = new JvmtiRawMonitor(name);
NULL_CHECK(rmonitor, JVMTI_ERROR_OUT_OF_MEMORY);
return JVMTI_ERROR_NONE;
} /* end CreateRawMonitor */
jvmtiError
JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) {
if (Threads::number_of_threads() == 0) {
JvmtiPendingMonitors::destroy(rmonitor);
} else {
Thread* thread = Thread::current();
if (rmonitor->is_entered(thread)) {
int r;
intptr_t recursion = rmonitor->recursions();
for (intptr_t i = 0; i <= recursion; i++) {
r = rmonitor->raw_exit(thread);
assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked");
if (r != ObjectMonitor::OM_OK) { // robustness
return JVMTI_ERROR_INTERNAL;
}
}
}
if (rmonitor->owner() != NULL) {
return JVMTI_ERROR_NOT_MONITOR_OWNER;
}
}
delete rmonitor;
return JVMTI_ERROR_NONE;
} /* end DestroyRawMonitor */
jvmtiError
JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) {
if (Threads::number_of_threads() == 0) {
JvmtiPendingMonitors::enter(rmonitor);
} else {
int r = 0;
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* current_thread = (JavaThread*)thread;
#ifdef PROPER_TRANSITIONS
ThreadInVMfromUnknown __tiv;
{
ThreadBlockInVM __tbivm(current_thread);
r = rmonitor->raw_enter(current_thread);
}
#else
JavaThreadState state = current_thread->thread_state();
assert(state == _thread_in_native, "Must be _thread_in_native");
assert(!current_thread->has_last_Java_frame() ||
current_thread->frame_anchor()->walkable(), "Must be walkable");
current_thread->set_thread_state(_thread_blocked);
r = rmonitor->raw_enter(current_thread);
current_thread->set_thread_state(state);
#endif /* PROPER_TRANSITIONS */
assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
} else {
if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) {
r = rmonitor->raw_enter(thread);
} else {
ShouldNotReachHere();
}
}
if (r != ObjectMonitor::OM_OK) { // robustness
return JVMTI_ERROR_INTERNAL;
}
}
return JVMTI_ERROR_NONE;
} /* end RawMonitorEnter */
jvmtiError
JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) {
jvmtiError err = JVMTI_ERROR_NONE;
if (Threads::number_of_threads() == 0) {
if (!JvmtiPendingMonitors::exit(rmonitor)) {
err = JVMTI_ERROR_NOT_MONITOR_OWNER;
}
} else {
int r = 0;
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* current_thread = (JavaThread*)thread;
#ifdef PROPER_TRANSITIONS
ThreadInVMfromUnknown __tiv;
#endif /* PROPER_TRANSITIONS */
r = rmonitor->raw_exit(current_thread);
} else {
if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) {
r = rmonitor->raw_exit(thread);
} else {
ShouldNotReachHere();
}
}
if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) {
err = JVMTI_ERROR_NOT_MONITOR_OWNER;
} else {
assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked");
if (r != ObjectMonitor::OM_OK) { // robustness
err = JVMTI_ERROR_INTERNAL;
}
}
}
return err;
} /* end RawMonitorExit */
jvmtiError
JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) {
int r = 0;
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* current_thread = (JavaThread*)thread;
#ifdef PROPER_TRANSITIONS
ThreadInVMfromUnknown __tiv;
{
ThreadBlockInVM __tbivm(current_thread);
r = rmonitor->raw_wait(millis, true, current_thread);
}
#else
JavaThreadState state = current_thread->thread_state();
assert(state == _thread_in_native, "Must be _thread_in_native");
assert(!current_thread->has_last_Java_frame() ||
current_thread->frame_anchor()->walkable(), "Must be walkable");
current_thread->set_thread_state(_thread_blocked);
r = rmonitor->raw_wait(millis, true, current_thread);
current_thread->set_thread_state(state);
#endif /* PROPER_TRANSITIONS */
} else {
if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) {
r = rmonitor->raw_wait(millis, true, thread);
} else {
ShouldNotReachHere();
}
}
switch (r) {
case ObjectMonitor::OM_INTERRUPTED:
return JVMTI_ERROR_INTERRUPT;
case ObjectMonitor::OM_ILLEGAL_MONITOR_STATE:
return JVMTI_ERROR_NOT_MONITOR_OWNER;
}
assert(r == ObjectMonitor::OM_OK, "raw_wait should have worked");
if (r != ObjectMonitor::OM_OK) { // robustness
return JVMTI_ERROR_INTERNAL;
}
return JVMTI_ERROR_NONE;
} /* end RawMonitorWait */
jvmtiError
JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) {
int r = 0;
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* current_thread = (JavaThread*)thread;
ThreadInVMfromUnknown __tiv;
r = rmonitor->raw_notify(current_thread);
} else {
if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) {
r = rmonitor->raw_notify(thread);
} else {
ShouldNotReachHere();
}
}
if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) {
return JVMTI_ERROR_NOT_MONITOR_OWNER;
}
assert(r == ObjectMonitor::OM_OK, "raw_notify should have worked");
if (r != ObjectMonitor::OM_OK) { // robustness
return JVMTI_ERROR_INTERNAL;
}
return JVMTI_ERROR_NONE;
} /* end RawMonitorNotify */
jvmtiError
JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) {
int r = 0;
Thread* thread = Thread::current();
if (thread->is_Java_thread()) {
JavaThread* current_thread = (JavaThread*)thread;
ThreadInVMfromUnknown __tiv;
r = rmonitor->raw_notifyAll(current_thread);
} else {
if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) {
r = rmonitor->raw_notifyAll(thread);
} else {
ShouldNotReachHere();
}
}
if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) {
return JVMTI_ERROR_NOT_MONITOR_OWNER;
}
assert(r == ObjectMonitor::OM_OK, "raw_notifyAll should have worked");
if (r != ObjectMonitor::OM_OK) { // robustness
return JVMTI_ERROR_INTERNAL;
}
return JVMTI_ERROR_NONE;
} /* end RawMonitorNotifyAll */
jvmtiError
JvmtiEnv::SetJNIFunctionTable(const jniNativeInterface* function_table) {
VM_JNIFunctionTableCopier copier(function_table);
VMThread::execute(&copier);
return JVMTI_ERROR_NONE;
} /* end SetJNIFunctionTable */
jvmtiError
JvmtiEnv::GetJNIFunctionTable(jniNativeInterface** function_table) {
if (*function_table == NULL)
return JVMTI_ERROR_OUT_OF_MEMORY;
memcpy(*function_table,(JavaThread::current())->get_jni_functions(),sizeof(jniNativeInterface));
return JVMTI_ERROR_NONE;
} /* end GetJNIFunctionTable */
jvmtiError
JvmtiEnv::GenerateEvents(jvmtiEvent event_type) {
if (event_type != JVMTI_EVENT_COMPILED_METHOD_LOAD &&
event_type != JVMTI_EVENT_DYNAMIC_CODE_GENERATED) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) {
if (get_capabilities()->can_generate_compiled_method_load_events == 0) {
return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
}
return JvmtiCodeBlobEvents::generate_compiled_method_load_events(this);
} else {
return JvmtiCodeBlobEvents::generate_dynamic_code_events(this);
}
} /* end GenerateEvents */
jvmtiError
JvmtiEnv::GetExtensionFunctions(jint* extension_count_ptr, jvmtiExtensionFunctionInfo** extensions) {
return JvmtiExtensions::get_functions(this, extension_count_ptr, extensions);
} /* end GetExtensionFunctions */
jvmtiError
JvmtiEnv::GetExtensionEvents(jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions) {
return JvmtiExtensions::get_events(this, extension_count_ptr, extensions);
} /* end GetExtensionEvents */
jvmtiError
JvmtiEnv::SetExtensionEventCallback(jint extension_event_index, jvmtiExtensionEvent callback) {
return JvmtiExtensions::set_event_callback(this, extension_event_index, callback);
} /* end SetExtensionEventCallback */
jvmtiError
JvmtiEnv::GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
os::current_thread_cpu_time_info(info_ptr);
return JVMTI_ERROR_NONE;
} /* end GetCurrentThreadCpuTimerInfo */
jvmtiError
JvmtiEnv::GetCurrentThreadCpuTime(jlong* nanos_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetCurrentThreadCpuTime */
jvmtiError
JvmtiEnv::GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
os::thread_cpu_time_info(info_ptr);
return JVMTI_ERROR_NONE;
} /* end GetThreadCpuTimerInfo */
jvmtiError
JvmtiEnv::GetThreadCpuTime(JavaThread* java_thread, jlong* nanos_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetThreadCpuTime */
jvmtiError
JvmtiEnv::GetTimerInfo(jvmtiTimerInfo* info_ptr) {
os::javaTimeNanos_info(info_ptr);
return JVMTI_ERROR_NONE;
} /* end GetTimerInfo */
jvmtiError
JvmtiEnv::GetTime(jlong* nanos_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetTime */
jvmtiError
JvmtiEnv::GetAvailableProcessors(jint* processor_count_ptr) {
return JVMTI_ERROR_NONE;
} /* end GetAvailableProcessors */
jvmtiError
JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr);
if (err != JVMTI_ERROR_NONE) {
return err;
}
int i = 0 ;
for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) {
const char *key = p->key();
char **tmp_value = *property_ptr+i;
err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value);
if (err == JVMTI_ERROR_NONE) {
strcpy(*tmp_value, key);
} else {
for (int j = 0; j < i; j++) {
Deallocate((unsigned char*)*property_ptr+j);
}
Deallocate((unsigned char*)property_ptr);
break;
}
}
return err;
} /* end GetSystemProperties */
jvmtiError
JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
const char *value;
value = Arguments::PropertyList_get_value(Arguments::system_properties(), property);
if (value == NULL) {
err = JVMTI_ERROR_NOT_AVAILABLE;
} else {
err = allocate((strlen(value)+1) * sizeof(char), (unsigned char **)value_ptr);
if (err == JVMTI_ERROR_NONE) {
strcpy(*value_ptr, value);
}
}
return err;
} /* end GetSystemProperty */
jvmtiError
JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) {
jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE;
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
if (strcmp(property, p->key()) == 0) {
if (p->set_value((char *)value_ptr)) {
err = JVMTI_ERROR_NONE;
}
}
}
return err;
} /* end SetSystemProperty */
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiEnvBase.cpp
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.hpp"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/jvmtiEventController.inline.hpp"
#include "prims/jvmtiExtensions.hpp"
#include "prims/jvmtiImpl.hpp"
#include "prims/jvmtiManageCapabilities.hpp"
#include "prims/jvmtiTagMap.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/jfieldIDWorkaround.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/objectMonitor.inline.hpp"
#include "runtime/signature.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vframe.hpp"
#include "runtime/vframe_hp.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
JvmtiEnvBase* JvmtiEnvBase::_head_environment = NULL;
bool JvmtiEnvBase::_globally_initialized = false;
volatile bool JvmtiEnvBase::_needs_clean_up = false;
jvmtiPhase JvmtiEnvBase::_phase = JVMTI_PHASE_PRIMORDIAL;
volatile int JvmtiEnvBase::_dying_thread_env_iteration_count = 0;
extern jvmtiInterface_1_ jvmti_Interface;
extern jvmtiInterface_1_ jvmtiTrace_Interface;
void
JvmtiEnvBase::globally_initialize() {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
assert(_globally_initialized == false, "bad call");
JvmtiManageCapabilities::initialize();
JvmtiExtensions::register_extensions();
#ifdef JVMTI_TRACE
JvmtiTrace::initialize();
#endif
_globally_initialized = true;
}
void
JvmtiEnvBase::initialize() {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
{
JvmtiEnvIterator it;
JvmtiEnvBase *previous_env = NULL;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
previous_env = env;
}
if (previous_env == NULL) {
_head_environment = this;
} else {
previous_env->set_next_environment(this);
}
}
if (_globally_initialized == false) {
globally_initialize();
}
}
bool
JvmtiEnvBase::is_valid() {
jint value = 0;
switch (sizeof(_magic)) {
case 2:
value = Bytes::get_native_u2((address)&_magic);
break;
case 4:
value = Bytes::get_native_u4((address)&_magic);
break;
case 8:
value = Bytes::get_native_u8((address)&_magic);
break;
default:
guarantee(false, "_magic field is an unexpected size");
}
return value == JVMTI_MAGIC;
}
bool
JvmtiEnvBase::use_version_1_0_semantics() {
int major, minor, micro;
JvmtiExport::decode_version_values(_version, &major, &minor, µ);
return major == 1 && minor == 0; // micro version doesn't matter here
}
bool
JvmtiEnvBase::use_version_1_1_semantics() {
int major, minor, micro;
JvmtiExport::decode_version_values(_version, &major, &minor, µ);
return major == 1 && minor == 1; // micro version doesn't matter here
}
bool
JvmtiEnvBase::use_version_1_2_semantics() {
int major, minor, micro;
JvmtiExport::decode_version_values(_version, &major, &minor, µ);
return major == 1 && minor == 2; // micro version doesn't matter here
}
JvmtiEnvBase::JvmtiEnvBase(jint version) : _env_event_enable() {
_version = version;
_env_local_storage = NULL;
_tag_map = NULL;
_native_method_prefix_count = 0;
_native_method_prefixes = NULL;
_next = NULL;
_class_file_load_hook_ever_enabled = false;
_is_retransformable = true;
memset(&_event_callbacks,0,sizeof(jvmtiEventCallbacks));
memset(&_current_capabilities, 0, sizeof(_current_capabilities));
memset(&_prohibited_capabilities, 0, sizeof(_prohibited_capabilities));
_magic = JVMTI_MAGIC;
JvmtiEventController::env_initialize((JvmtiEnv*)this);
#ifdef JVMTI_TRACE
_jvmti_external.functions = TraceJVMTI != NULL ? &jvmtiTrace_Interface : &jvmti_Interface;
#else
_jvmti_external.functions = &jvmti_Interface;
#endif
}
void
JvmtiEnvBase::dispose() {
#ifdef JVMTI_TRACE
JvmtiTrace::shutdown();
#endif
JvmtiEventController::env_dispose(this);
}
void
JvmtiEnvBase::env_dispose() {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
_magic = DISPOSED_MAGIC;
jvmtiCapabilities *caps = get_capabilities();
JvmtiManageCapabilities::relinquish_capabilities(caps, caps, caps);
set_native_method_prefixes(0, NULL);
JvmtiTagMap* tag_map_to_deallocate = _tag_map;
set_tag_map(NULL);
if (tag_map_to_deallocate != NULL) {
delete tag_map_to_deallocate;
}
_needs_clean_up = true;
}
JvmtiEnvBase::~JvmtiEnvBase() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
JvmtiTagMap* tag_map_to_deallocate = _tag_map;
set_tag_map(NULL);
if (tag_map_to_deallocate != NULL) {
delete tag_map_to_deallocate;
}
_magic = BAD_MAGIC;
}
void
JvmtiEnvBase::periodic_clean_up() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
JvmtiThreadState::periodic_clean_up();
JvmtiEnvIterator it;
JvmtiEnvBase* previous_env = NULL;
JvmtiEnvBase* env = it.first();
while (env != NULL) {
if (env->is_valid()) {
previous_env = env;
env = it.next(env);
} else {
JvmtiEnvBase* defunct_env = env;
env = it.next(env);
if (previous_env == NULL) {
_head_environment = env;
} else {
previous_env->set_next_environment(env);
}
delete defunct_env;
}
}
}
void
JvmtiEnvBase::check_for_periodic_clean_up() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
class ThreadInsideIterationClosure: public ThreadClosure {
private:
bool _inside;
public:
ThreadInsideIterationClosure() : _inside(false) {};
void do_thread(Thread* thread) {
_inside |= thread->is_inside_jvmti_env_iteration();
}
bool is_inside_jvmti_env_iteration() {
return _inside;
}
};
if (_needs_clean_up) {
ThreadInsideIterationClosure tiic;
Threads::threads_do(&tiic);
if (!tiic.is_inside_jvmti_env_iteration() &&
!is_inside_dying_thread_env_iteration()) {
_needs_clean_up = false;
JvmtiEnvBase::periodic_clean_up();
}
}
}
void
JvmtiEnvBase::record_first_time_class_file_load_hook_enabled() {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(),
"sanity check");
if (!_class_file_load_hook_ever_enabled) {
_class_file_load_hook_ever_enabled = true;
if (get_capabilities()->can_retransform_classes) {
_is_retransformable = true;
} else {
_is_retransformable = false;
get_prohibited_capabilities()->can_retransform_classes = 1;
}
}
}
void
JvmtiEnvBase::record_class_file_load_hook_enabled() {
if (!_class_file_load_hook_ever_enabled) {
if (Threads::number_of_threads() == 0) {
record_first_time_class_file_load_hook_enabled();
} else {
MutexLocker mu(JvmtiThreadState_lock);
record_first_time_class_file_load_hook_enabled();
}
}
}
jvmtiError
JvmtiEnvBase::set_native_method_prefixes(jint prefix_count, char** prefixes) {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(),
"sanity check");
int old_prefix_count = get_native_method_prefix_count();
char **old_prefixes = get_native_method_prefixes();
if (prefix_count == 0 || !is_valid()) {
_native_method_prefix_count = 0;
_native_method_prefixes = NULL;
} else {
char** new_prefixes = (char**)os::malloc((prefix_count) * sizeof(char*), mtInternal);
if (new_prefixes == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
for (int i = 0; i < prefix_count; i++) {
char* prefix = prefixes[i];
if (prefix == NULL) {
for (int j = 0; j < (i-1); j++) {
os::free(new_prefixes[j]);
}
os::free(new_prefixes);
return JVMTI_ERROR_NULL_POINTER;
}
prefix = os::strdup(prefixes[i]);
if (prefix == NULL) {
for (int j = 0; j < (i-1); j++) {
os::free(new_prefixes[j]);
}
os::free(new_prefixes);
return JVMTI_ERROR_OUT_OF_MEMORY;
}
new_prefixes[i] = prefix;
}
_native_method_prefix_count = prefix_count;
_native_method_prefixes = new_prefixes;
}
if (old_prefix_count != 0) {
for (int i = 0; i < old_prefix_count; i++) {
os::free(old_prefixes[i]);
}
os::free(old_prefixes);
}
return JVMTI_ERROR_NONE;
}
char**
JvmtiEnvBase::get_all_native_method_prefixes(int* count_ptr) {
assert(Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint() ||
JvmtiThreadState_lock->is_locked(),
"sanity check");
int total_count = 0;
GrowableArray<char*>* prefix_array =new GrowableArray<char*>(5);
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
int prefix_count = env->get_native_method_prefix_count();
char** prefixes = env->get_native_method_prefixes();
for (int j = 0; j < prefix_count; j++) {
char* prefix = prefixes[j];
char* prefix_copy = NEW_RESOURCE_ARRAY(char, strlen(prefix)+1);
strcpy(prefix_copy, prefix);
prefix_array->at_put_grow(total_count++, prefix_copy);
}
}
char** all_prefixes = NEW_RESOURCE_ARRAY(char*, total_count);
char** p = all_prefixes;
for (int i = 0; i < total_count; ++i) {
}
return all_prefixes;
}
void
JvmtiEnvBase::set_event_callbacks(const jvmtiEventCallbacks* callbacks,
jint size_of_callbacks) {
assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
size_t byte_cnt = sizeof(jvmtiEventCallbacks);
memset(&_event_callbacks, 0, byte_cnt);
if (callbacks != NULL && is_valid()) {
if (size_of_callbacks < (jint)byte_cnt) {
byte_cnt = size_of_callbacks;
}
memcpy(&_event_callbacks, callbacks, byte_cnt);
}
}
bool
JvmtiEnvBase::is_thread_fully_suspended(JavaThread* thr, bool wait_for_suspend, uint32_t *bits) {
if (thr != JavaThread::current()) {
if (wait_for_suspend) {
if (!thr->wait_for_ext_suspend_completion(SuspendRetryCount,
SuspendRetryDelay, bits)) {
return false;
}
}
else if (!thr->is_ext_suspend_completed_with_lock(bits)) {
return false;
}
}
return true;
}
unsigned char *
JvmtiEnvBase::jvmtiMalloc(jlong size) {
unsigned char* mem = NULL;
jvmtiError result = allocate(size, &mem);
assert(result == JVMTI_ERROR_NONE, "Allocate failed");
return mem;
}
jobject *
JvmtiEnvBase::new_jobjectArray(int length, Handle *handles) {
if (length == 0) {
return NULL;
}
jobject *objArray = (jobject *) jvmtiMalloc(sizeof(jobject) * length);
NULL_CHECK(objArray, NULL);
for (int i=0; i<length; i++) {
objArray[i] = jni_reference(handles[i]);
}
return objArray;
}
jthread *
JvmtiEnvBase::new_jthreadArray(int length, Handle *handles) {
return (jthread *) new_jobjectArray(length,handles);
}
jthreadGroup *
JvmtiEnvBase::new_jthreadGroupArray(int length, Handle *handles) {
return (jthreadGroup *) new_jobjectArray(length,handles);
}
JavaThread *
JvmtiEnvBase::get_JavaThread(jthread jni_thread) {
oop t = JNIHandles::resolve_external_guard(jni_thread);
if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) {
return NULL;
}
return java_lang_Thread::thread(t);
}
vframe*
JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) {
if (!java_thread->has_last_Java_frame()) {
return NULL;
}
RegisterMap reg_map(java_thread);
vframe *vf = java_thread->last_java_vframe(®_map);
int d = 0;
while ((vf != NULL) && (d < depth)) {
vf = vf->java_sender();
d++;
}
return vf;
}
jclass
JvmtiEnvBase::get_jni_class_non_null(Klass* k) {
assert(k != NULL, "k != NULL");
return (jclass)jni_reference(k->java_mirror());
}
bool
JvmtiEnvBase::get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd) {
if (!jfieldIDWorkaround::is_valid_jfieldID(k, field)) {
return false;
}
bool found = false;
if (jfieldIDWorkaround::is_static_jfieldID(field)) {
JNIid* id = jfieldIDWorkaround::from_static_jfieldID(field);
found = id->find_local_field(fd);
} else {
int offset = jfieldIDWorkaround::from_instance_jfieldID(k, field);
found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, fd);
}
return found;
}
jint
JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) {
jint ret = 0;
if (!java_thread->has_last_Java_frame()) {
return ret; // no Java frames so no monitors
}
ResourceMark rm;
HandleMark hm;
RegisterMap reg_map(java_thread);
for(javaVFrame *jvf=java_thread->last_java_vframe(®_map); jvf != NULL;
jvf = jvf->java_sender()) {
GrowableArray<MonitorInfo*>* mons = jvf->monitors();
if (!mons->is_empty()) {
for (int i = 0; i < mons->length(); i++) {
MonitorInfo *mi = mons->at(i);
if (mi->owner_is_scalar_replaced()) continue;
if (mi->owner() != NULL && mi->owner() == hobj()) {
ret++;
}
}
}
}
return ret;
}
jvmtiError
JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert((SafepointSynchronize::is_at_safepoint() ||
is_thread_fully_suspended(java_thread, false, &debug_bits)),
"at safepoint or target thread is suspended");
oop obj = NULL;
ObjectMonitor *mon = java_thread->current_waiting_monitor();
if (mon == NULL) {
mon = java_thread->current_pending_monitor();
if (mon != NULL) {
obj = (oop)mon->object();
}
} else {
obj = (oop)mon->object();
assert(obj != NULL, "Object.wait() should have an object");
}
if (obj == NULL) {
} else {
HandleMark hm;
Handle hobj(obj);
}
return JVMTI_ERROR_NONE;
}
jvmtiError
JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread,
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
jvmtiError err = JVMTI_ERROR_NONE;
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert((SafepointSynchronize::is_at_safepoint() ||
is_thread_fully_suspended(java_thread, false, &debug_bits)),
"at safepoint or target thread is suspended");
if (java_thread->has_last_Java_frame()) {
ResourceMark rm;
HandleMark hm;
RegisterMap reg_map(java_thread);
int depth = 0;
for (javaVFrame *jvf = java_thread->last_java_vframe(®_map); jvf != NULL;
jvf = jvf->java_sender()) {
if (depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1);
if (err != JVMTI_ERROR_NONE) {
return err;
}
}
}
}
JvmtiMonitorClosure jmc(java_thread, calling_thread, owned_monitors_list, this);
ObjectSynchronizer::monitors_iterate(&jmc);
err = jmc.error();
return err;
}
jvmtiError
JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread,
javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, int stack_depth) {
jvmtiError err = JVMTI_ERROR_NONE;
ResourceMark rm;
GrowableArray<MonitorInfo*>* mons = jvf->monitors();
if (mons->is_empty()) {
return err; // this javaVFrame holds no monitors
}
HandleMark hm;
oop wait_obj = NULL;
{
ObjectMonitor *mon = java_thread->current_waiting_monitor();
if (mon != NULL) {
wait_obj = (oop)mon->object();
}
}
oop pending_obj = NULL;
{
ObjectMonitor *mon = java_thread->current_pending_monitor();
if (mon != NULL) {
pending_obj = (oop)mon->object();
}
}
for (int i = 0; i < mons->length(); i++) {
MonitorInfo *mi = mons->at(i);
if (mi->owner_is_scalar_replaced()) continue;
oop obj = mi->owner();
if (obj == NULL) {
continue;
}
if (wait_obj == obj) {
continue;
}
if (pending_obj == obj) {
continue;
}
if (owned_monitors_list->length() > 0) {
bool found = false;
for (int j = 0; j < owned_monitors_list->length(); j++) {
jobject jobj = ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(j))->monitor;
oop check = JNIHandles::resolve(jobj);
if (check == obj) {
found = true; // we found the object
break;
}
}
if (found) {
continue;
}
}
jvmtiMonitorStackDepthInfo *jmsdi;
err = allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi);
if (err != JVMTI_ERROR_NONE) {
return err;
}
Handle hobj(obj);
jmsdi->monitor = jni_reference(calling_thread, hobj);
jmsdi->stack_depth = stack_depth;
owned_monitors_list->append(jmsdi);
}
return err;
}
jvmtiError
JvmtiEnvBase::get_stack_trace(JavaThread *java_thread,
jint start_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert((SafepointSynchronize::is_at_safepoint() ||
is_thread_fully_suspended(java_thread, false, &debug_bits)),
"at safepoint or target thread is suspended");
int count = 0;
if (java_thread->has_last_Java_frame()) {
RegisterMap reg_map(java_thread);
Thread* current_thread = Thread::current();
ResourceMark rm(current_thread);
javaVFrame *jvf = java_thread->last_java_vframe(®_map);
HandleMark hm(current_thread);
if (start_depth != 0) {
if (start_depth > 0) {
for (int j = 0; j < start_depth && jvf != NULL; j++) {
jvf = jvf->java_sender();
}
if (jvf == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
} else { // start_depth < 0
javaVFrame *jvf_cursor = jvf;
javaVFrame *jvf_prev = NULL;
javaVFrame *jvf_prev_prev;
int j = 0;
while (jvf_cursor != NULL) {
jvf_prev_prev = jvf_prev;
jvf_prev = jvf_cursor;
for (j = 0; j > start_depth && jvf_cursor != NULL; j--) {
jvf_cursor = jvf_cursor->java_sender();
}
}
if (j == start_depth) {
jvf = jvf_prev;
} else {
if (jvf_prev_prev == NULL) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
jvf = jvf_prev_prev;
for (; j < 0; j++) {
jvf = jvf->java_sender();
}
}
}
}
for (; count < max_count && jvf != NULL; count++) {
frame_buffer[count].method = jvf->method()->jmethod_id();
frame_buffer[count].location = (jvf->method()->is_native() ? -1 : jvf->bci());
jvf = jvf->java_sender();
}
} else {
if (start_depth != 0) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
}
return JVMTI_ERROR_NONE;
}
jvmtiError
JvmtiEnvBase::get_frame_count(JvmtiThreadState *state, jint *count_ptr) {
assert((state != NULL),
"JavaThread should create JvmtiThreadState before calling this method");
return JVMTI_ERROR_NONE;
}
jvmtiError
JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth,
jmethodID* method_ptr, jlocation* location_ptr) {
#ifdef ASSERT
uint32_t debug_bits = 0;
#endif
assert((SafepointSynchronize::is_at_safepoint() ||
is_thread_fully_suspended(java_thread, false, &debug_bits)),
"at safepoint or target thread is suspended");
Thread* current_thread = Thread::current();
ResourceMark rm(current_thread);
vframe *vf = vframeFor(java_thread, depth);
if (vf == NULL) {
return JVMTI_ERROR_NO_MORE_FRAMES;
}
#ifdef PRODUCT
if (!vf->is_java_frame()) {
return JVMTI_ERROR_INTERNAL;
}
#endif
HandleMark hm(current_thread);
javaVFrame *jvf = javaVFrame::cast(vf);
Method* method = jvf->method();
if (method->is_native()) {
} else {
}
return JVMTI_ERROR_NONE;
}
jvmtiError
JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) {
HandleMark hm;
Handle hobj;
bool at_safepoint = SafepointSynchronize::is_at_safepoint();
{
oop mirror = JNIHandles::resolve_external_guard(object);
NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT);
NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER);
hobj = Handle(mirror);
}
JavaThread *owning_thread = NULL;
ObjectMonitor *mon = NULL;
jvmtiMonitorUsage ret = {
NULL, 0, 0, NULL, 0, NULL
};
uint32_t debug_bits = 0;
{
if (SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke_at_safepoint(hobj);
} else {
BiasedLocking::revoke_and_rebias(hobj, false, calling_thread);
}
address owner = NULL;
{
markOop mark = hobj()->mark();
if (!mark->has_monitor()) {
if (mark->has_locker()) {
owner = (address)mark->locker(); // save the address of the Lock word
}
} else {
mon = mark->monitor();
owner = (address)mon->owner();
}
}
if (owner != NULL) {
owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint);
if (owning_thread != NULL) {
if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
HandleMark hm;
Handle th(owning_thread->threadObj());
ret.owner = (jthread)jni_reference(calling_thread, th);
}
}
if (owning_thread != NULL) { // monitor is owned
if ((address)owning_thread == owner) {
assert(mon != NULL,
"must have heavyweight monitor with JavaThread * owner");
ret.entry_count = mon->recursions() + 1;
} else {
ResourceMark rm;
ret.entry_count = count_locked_objects(owning_thread, hobj);
}
}
}
int nWant = 0, nWait = 0;
if (mon != NULL) {
nWant = mon->contentions(); // # of threads contending for monitor
nWait = mon->waiters(); // # of threads in Object.wait()
ret.waiter_count = nWant + nWait;
ret.notify_waiter_count = nWait;
} else {
ret.waiter_count = 0;
ret.notify_waiter_count = 0;
}
jvmtiError err;
err = allocate(ret.waiter_count * sizeof(jthread *), (unsigned char**)&ret.waiters);
if (err != JVMTI_ERROR_NONE) {
return err;
}
err = allocate(ret.notify_waiter_count * sizeof(jthread *),
(unsigned char**)&ret.notify_waiters);
if (err != JVMTI_ERROR_NONE) {
deallocate((unsigned char*)ret.waiters);
return err;
}
if (mon != NULL) {
memset(ret.waiters, 0, ret.waiter_count * sizeof(jthread *));
memset(ret.notify_waiters, 0, ret.notify_waiter_count * sizeof(jthread *));
if (ret.waiter_count > 0) {
HandleMark hm;
if (nWant > 0) {
ResourceMark rm;
GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads(
nWant, (address)mon, !at_safepoint);
if (wantList->length() < nWant) {
nWant = wantList->length();
}
for (int i = 0; i < nWant; i++) {
JavaThread *pending_thread = wantList->at(i);
if (owning_thread == NULL && !at_safepoint &&
!JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) {
if (ret.owner != NULL) {
destroy_jni_reference(calling_thread, ret.owner);
}
for (int j = 0; j < i; j++) {
destroy_jni_reference(calling_thread, ret.waiters[j]);
}
deallocate((unsigned char*)ret.waiters);
deallocate((unsigned char*)ret.notify_waiters);
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
Handle th(pending_thread->threadObj());
ret.waiters[i] = (jthread)jni_reference(calling_thread, th);
}
}
if (nWait > 0) {
int offset = nWant; // add after any contending threads
ObjectWaiter *waiter = mon->first_waiter();
for (int i = 0, j = 0; i < nWait; i++) {
if (waiter == NULL) {
nWait = j;
break;
}
Thread *t = mon->thread_of_waiter(waiter);
if (t != NULL && t->is_Java_thread()) {
JavaThread *wjava_thread = (JavaThread *)t;
Handle th(wjava_thread->threadObj());
ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th);
ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th);
}
waiter = mon->next_waiter(waiter);
}
}
}
ret.waiter_count = nWant + nWait;
ret.notify_waiter_count = nWait;
} else {
}
return JVMTI_ERROR_NONE;
}
ResourceTracker::ResourceTracker(JvmtiEnv* env) {
_env = env;
_allocations = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<unsigned char*>(20, true);
_failed = false;
}
ResourceTracker::~ResourceTracker() {
if (_failed) {
for (int i=0; i<_allocations->length(); i++) {
_env->deallocate(_allocations->at(i));
}
}
delete _allocations;
}
jvmtiError ResourceTracker::allocate(jlong size, unsigned char** mem_ptr) {
unsigned char *ptr;
jvmtiError err = _env->allocate(size, &ptr);
if (err == JVMTI_ERROR_NONE) {
_allocations->append(ptr);
} else {
_failed = true;
}
return err;
}
unsigned char* ResourceTracker::allocate(jlong size) {
unsigned char* ptr;
allocate(size, &ptr);
return ptr;
}
char* ResourceTracker::strdup(const char* str) {
char *dup_str = (char*)allocate(strlen(str)+1);
if (dup_str != NULL) {
strcpy(dup_str, str);
}
return dup_str;
}
struct StackInfoNode {
struct StackInfoNode *next;
jvmtiStackInfo info;
};
void
VM_GetMultipleStackTraces::fill_frames(jthread jt, JavaThread *thr, oop thread_oop) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
jint state = 0;
struct StackInfoNode *node = NEW_RESOURCE_OBJ(struct StackInfoNode);
jvmtiStackInfo *infop = &(node->info);
node->next = head();
set_head(node);
infop->frame_count = 0;
infop->thread = jt;
if (thread_oop != NULL) {
state = (jint)java_lang_Thread::get_thread_status(thread_oop);
}
if (thr != NULL) { // add more state bits if there is a JavaThead to query
if (thr->is_ext_suspended() || thr->is_external_suspend()) {
state |= JVMTI_THREAD_STATE_SUSPENDED;
}
JavaThreadState jts = thr->thread_state();
if (jts == _thread_in_native) {
state |= JVMTI_THREAD_STATE_IN_NATIVE;
}
OSThread* osThread = thr->osthread();
if (osThread != NULL && osThread->interrupted()) {
state |= JVMTI_THREAD_STATE_INTERRUPTED;
}
}
infop->state = state;
if (thr != NULL || (state & JVMTI_THREAD_STATE_ALIVE) != 0) {
infop->frame_buffer = NEW_RESOURCE_ARRAY(jvmtiFrameInfo, max_frame_count());
env()->get_stack_trace(thr, 0, max_frame_count(),
infop->frame_buffer, &(infop->frame_count));
} else {
infop->frame_buffer = NULL;
infop->frame_count = 0;
}
_frame_count_total += infop->frame_count;
}
void
VM_GetMultipleStackTraces::allocate_and_fill_stacks(jint thread_count) {
jlong alloc_size = thread_count * sizeof(jvmtiStackInfo)
+ _frame_count_total * sizeof(jvmtiFrameInfo);
env()->allocate(alloc_size, (unsigned char **)&_stack_info);
jvmtiStackInfo *si = _stack_info + thread_count; // bottom of stack info
jvmtiFrameInfo *fi = (jvmtiFrameInfo *)si; // is the top of frame info
for (struct StackInfoNode *sin = head(); sin != NULL; sin = sin->next) {
jint frame_count = sin->info.frame_count;
size_t frames_size = frame_count * sizeof(jvmtiFrameInfo);
--si;
memcpy(si, &(sin->info), sizeof(jvmtiStackInfo));
if (frames_size == 0) {
si->frame_buffer = NULL;
} else {
memcpy(fi, sin->info.frame_buffer, frames_size);
si->frame_buffer = fi; // point to the new allocated copy of the frames
fi += frame_count;
}
}
assert(si == _stack_info, "the last copied stack info must be the first record");
assert((unsigned char *)fi == ((unsigned char *)_stack_info) + alloc_size,
"the last copied frame info must be the last record");
}
void
VM_GetThreadListStackTraces::doit() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
ResourceMark rm;
for (int i = 0; i < _thread_count; ++i) {
jthread jt = _thread_list[i];
oop thread_oop = JNIHandles::resolve_external_guard(jt);
if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
set_result(JVMTI_ERROR_INVALID_THREAD);
return;
}
fill_frames(jt, java_lang_Thread::thread(thread_oop), thread_oop);
}
allocate_and_fill_stacks(_thread_count);
}
void
VM_GetAllStackTraces::doit() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
ResourceMark rm;
_final_thread_count = 0;
for (JavaThread *jt = Threads::first(); jt != NULL; jt = jt->next()) {
oop thread_oop = jt->threadObj();
if (thread_oop != NULL &&
!jt->is_exiting() &&
java_lang_Thread::is_alive(thread_oop) &&
!jt->is_hidden_from_external_view()) {
++_final_thread_count;
fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop),
jt, thread_oop);
}
}
allocate_and_fill_stacks(_final_thread_count);
}
jvmtiError
JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_thread,
jvalue value, TosState tos, Handle* ret_ob_h) {
ResourceMark rm(current_thread);
vframe *vf = vframeFor(java_thread, 0);
NULL_CHECK(vf, JVMTI_ERROR_NO_MORE_FRAMES);
javaVFrame *jvf = (javaVFrame*) vf;
if (!vf->is_java_frame() || jvf->method()->is_native()) {
return JVMTI_ERROR_OPAQUE_FRAME;
}
if (vf->is_compiled_frame()) {
if (!vf->fr().can_be_deoptimized()) {
return JVMTI_ERROR_OPAQUE_FRAME;
}
Deoptimization::deoptimize_frame(java_thread, jvf->fr().id());
}
Symbol* signature = jvf->method()->signature();
ResultTypeFinder rtf(signature);
TosState fr_tos = as_TosState(rtf.type());
if (fr_tos != tos) {
if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) {
return JVMTI_ERROR_TYPE_MISMATCH;
}
}
jobject jobj = value.l;
if (tos == atos && jobj != NULL) { // NULL reference is allowed
Handle ob_h = Handle(current_thread, JNIHandles::resolve_external_guard(jobj));
NULL_CHECK(ob_h, JVMTI_ERROR_INVALID_OBJECT);
KlassHandle ob_kh = KlassHandle(current_thread, ob_h()->klass());
NULL_CHECK(ob_kh, JVMTI_ERROR_INVALID_OBJECT);
char* ty_sign = 1 + strchr(signature->as_C_string(), ')');
if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_kh(), current_thread)) {
return JVMTI_ERROR_TYPE_MISMATCH;
}
}
return JVMTI_ERROR_NONE;
} /* end check_top_frame */
jvmtiError
JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState tos) {
JavaThread* current_thread = JavaThread::current();
HandleMark hm(current_thread);
uint32_t debug_bits = 0;
JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
if (state == NULL) {
return JVMTI_ERROR_THREAD_NOT_ALIVE;
}
if (!is_thread_fully_suspended(java_thread,
true /* wait for suspend completion */,
&debug_bits)) {
return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
}
if (state->is_earlyret_pending()) {
return JVMTI_ERROR_INTERNAL;
}
{
OSThread* osThread = java_thread->osthread();
if (osThread->get_state() == MONITOR_WAIT) {
return JVMTI_ERROR_OPAQUE_FRAME;
}
}
Handle ret_ob_h = Handle();
jvmtiError err = check_top_frame(current_thread, java_thread, value, tos, &ret_ob_h);
if (err != JVMTI_ERROR_NONE) {
return err;
}
assert(tos != atos || value.l == NULL || ret_ob_h() != NULL,
"return object oop must not be NULL if jobject is not NULL");
state->set_earlyret_pending();
state->set_earlyret_oop(ret_ob_h());
state->set_earlyret_value(value, tos);
state->set_pending_step_for_earlyret();
return JVMTI_ERROR_NONE;
} /* end force_early_return */
void
JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) {
if ( _error != JVMTI_ERROR_NONE) {
return;
}
if (mon->owner() == _java_thread ) {
oop obj = (oop)mon->object();
bool found = false;
for (int j = 0; j < _owned_monitors_list->length(); j++) {
jobject jobj = ((jvmtiMonitorStackDepthInfo*)_owned_monitors_list->at(j))->monitor;
oop check = JNIHandles::resolve(jobj);
if (check == obj) {
found = true;
break;
}
}
if (found == false) {
jvmtiError err;
jvmtiMonitorStackDepthInfo *jmsdi;
err = _env->allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi);
if (err != JVMTI_ERROR_NONE) {
_error = err;
return;
}
Handle hobj(obj);
jmsdi->monitor = _env->jni_reference(_calling_thread, hobj);
jmsdi->stack_depth = -1;
_owned_monitors_list->append(jmsdi);
}
}
}
C:\hotspot-69087d08d473\src\share\vm/prims/jvmtiEnvBase.hpp
#ifndef SHARE_VM_PRIMS_JVMTIENVBASE_HPP
#define SHARE_VM_PRIMS_JVMTIENVBASE_HPP
#include "classfile/classLoader.hpp"
#include "prims/jvmtiEnvThreadState.hpp"
#include "prims/jvmtiEventController.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/frame.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/thread.hpp"
#include "runtime/vm_operations.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
class JvmtiEnv;
class JvmtiThreadState;
class JvmtiRawMonitor; // for jvmtiEnv.hpp
class JvmtiEventControllerPrivate;
class JvmtiTagMap;
class JvmtiEnvBase : public CHeapObj<mtInternal> {
private:
#if INCLUDE_JVMTI
static JvmtiEnvBase* _head_environment; // head of environment list
#endif // INCLUDE_JVMTI
static bool _globally_initialized;
static jvmtiPhase _phase;
static volatile int _dying_thread_env_iteration_count;
public:
enum {
JDK15_JVMTI_VERSION = JVMTI_VERSION_1_0 + 33, /* version: 1.0.33 */
JDK16_JVMTI_VERSION = JVMTI_VERSION_1_1 + 102, /* version: 1.1.102 */
JDK17_JVMTI_VERSION = JVMTI_VERSION_1_2 + 2 /* version: 1.2.2 */
};
static jvmtiPhase get_phase() { return _phase; }
static void set_phase(jvmtiPhase phase) { _phase = phase; }
static bool is_vm_live() { return _phase == JVMTI_PHASE_LIVE; }
static void entering_dying_thread_env_iteration() { ++_dying_thread_env_iteration_count; }
static void leaving_dying_thread_env_iteration() { --_dying_thread_env_iteration_count; }
static bool is_inside_dying_thread_env_iteration(){ return _dying_thread_env_iteration_count > 0; }
private:
enum {
JVMTI_MAGIC = 0x71EE,
DISPOSED_MAGIC = 0xDEFC,
BAD_MAGIC = 0xDEAD
};
jvmtiEnv _jvmti_external;
jint _magic;
jint _version; // version value passed to JNI GetEnv()
JvmtiEnvBase* _next;
bool _is_retransformable;
const void *_env_local_storage; // per env agent allocated data.
jvmtiEventCallbacks _event_callbacks;
jvmtiExtEventCallbacks _ext_event_callbacks;
JvmtiTagMap* volatile _tag_map;
JvmtiEnvEventEnable _env_event_enable;
jvmtiCapabilities _current_capabilities;
jvmtiCapabilities _prohibited_capabilities;
volatile bool _class_file_load_hook_ever_enabled;
static volatile bool _needs_clean_up;
char** _native_method_prefixes;
int _native_method_prefix_count;
protected:
JvmtiEnvBase(jint version);
~JvmtiEnvBase();
void dispose();
void env_dispose();
void set_env_local_storage(const void* data) { _env_local_storage = data; }
const void* get_env_local_storage() { return _env_local_storage; }
void record_class_file_load_hook_enabled();
void record_first_time_class_file_load_hook_enabled();
char** get_native_method_prefixes() { return _native_method_prefixes; }
int get_native_method_prefix_count() { return _native_method_prefix_count; }
jvmtiError set_native_method_prefixes(jint prefix_count, char** prefixes);
private:
friend class JvmtiEventControllerPrivate;
void initialize();
void set_event_callbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks);
static void globally_initialize();
static void periodic_clean_up();
friend class JvmtiEnvIterator;
JvmtiEnv* next_environment() { return (JvmtiEnv*)_next; }
void set_next_environment(JvmtiEnvBase* env) { _next = env; }
static JvmtiEnv* head_environment() {
JVMTI_ONLY(return (JvmtiEnv*)_head_environment);
NOT_JVMTI(return NULL);
}
public:
bool is_valid();
bool use_version_1_0_semantics(); // agent asked for version 1.0
bool use_version_1_1_semantics(); // agent asked for version 1.1
bool use_version_1_2_semantics(); // agent asked for version 1.2
bool is_retransformable() { return _is_retransformable; }
static ByteSize jvmti_external_offset() {
return byte_offset_of(JvmtiEnvBase, _jvmti_external);
};
static JvmtiEnv* JvmtiEnv_from_jvmti_env(jvmtiEnv *env) {
return (JvmtiEnv*)((intptr_t)env - in_bytes(jvmti_external_offset()));
};
jvmtiCapabilities *get_capabilities() { return &_current_capabilities; }
jvmtiCapabilities *get_prohibited_capabilities() { return &_prohibited_capabilities; }
static char** get_all_native_method_prefixes(int* count_ptr);
static bool environments_might_exist() {
return head_environment() != NULL;
}
static void check_for_periodic_clean_up();
JvmtiEnvEventEnable *env_event_enable() {
return &_env_event_enable;
}
jvmtiError allocate(jlong size, unsigned char** mem_ptr) {
if (size < 0) {
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
}
if (size == 0) {
} else {
if (*mem_ptr == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
}
return JVMTI_ERROR_NONE;
}
jvmtiError deallocate(unsigned char* mem) {
if (mem != NULL) {
os::free(mem, mtInternal);
}
return JVMTI_ERROR_NONE;
}
unsigned char* jvmtiMalloc(jlong size); // don't use this - call allocate
jobject jni_reference(Handle hndl) {
return JNIHandles::make_local(hndl());
}
jobject jni_reference(JavaThread *thread, Handle hndl) {
return JNIHandles::make_local(thread, hndl());
}
void destroy_jni_reference(jobject jobj) {
JNIHandles::destroy_local(jobj);
}
void destroy_jni_reference(JavaThread *thread, jobject jobj) {
destroy_jni_reference(jobj);
}
jvmtiEnv* jvmti_external() { return &_jvmti_external; };
bool has_callback(jvmtiEvent event_type) {
assert(event_type >= JVMTI_MIN_EVENT_TYPE_VAL &&
event_type <= JVMTI_MAX_EVENT_TYPE_VAL, "checking");
return ((void**)&_event_callbacks)[event_type-JVMTI_MIN_EVENT_TYPE_VAL] != NULL;
}
jvmtiEventCallbacks* callbacks() {
return &_event_callbacks;
}
jvmtiExtEventCallbacks* ext_callbacks() {
return &_ext_event_callbacks;
}
void set_tag_map(JvmtiTagMap* tag_map) {
_tag_map = tag_map;
}
JvmtiTagMap* tag_map() {
return _tag_map;
}
JvmtiTagMap* tag_map_acquire() {
return (JvmtiTagMap*)OrderAccess::load_ptr_acquire(&_tag_map);
}
void release_set_tag_map(JvmtiTagMap* tag_map) {
OrderAccess::release_store_ptr(&_tag_map, tag_map);
}
bool is_enabled(jvmtiEvent event_type) {
return _env_event_enable.is_enabled(event_type);
}
protected:
jobject * new_jobjectArray(int length, Handle *handles);
jthread * new_jthreadArray(int length, Handle *handles);
jthreadGroup * new_jthreadGroupArray(int length, Handle *handles);
JavaThread * get_JavaThread(jthread jni_thread);
jclass get_jni_class_non_null(Klass* k);
jint count_locked_objects(JavaThread *java_thread, Handle hobj);
jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread,
JavaThread* java_thread,
javaVFrame *jvf,
GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list,
jint depth);
vframe* vframeFor(JavaThread* java_thread, jint depth);
public:
static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd);
static bool is_thread_fully_suspended(JavaThread *thread,
bool wait_for_suspend,
uint32_t *bits);
jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr);
jvmtiError get_frame_location(JavaThread* java_thread, jint depth,
jmethodID* method_ptr, jlocation* location_ptr);
jvmtiError get_object_monitor_usage(JavaThread *calling_thread,
jobject object, jvmtiMonitorUsage* info_ptr);
jvmtiError get_stack_trace(JavaThread *java_thread,
jint stack_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr);
jvmtiError get_current_contended_monitor(JavaThread *calling_thread,
JavaThread *java_thread,
jobject *monitor_ptr);
jvmtiError get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread,
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list);
jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread,
jvalue value, TosState tos, Handle* ret_ob_h);
jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos);
};
class JvmtiEnvIterator : public StackObj {
private:
bool _entry_was_marked;
public:
JvmtiEnvIterator() {
if (Threads::number_of_threads() == 0) {
_entry_was_marked = false; // we are single-threaded, no need
} else {
Thread::current()->entering_jvmti_env_iteration();
_entry_was_marked = true;
}
}
~JvmtiEnvIterator() {
if (_entry_was_marked) {
Thread::current()->leaving_jvmti_env_iteration();
}
}
JvmtiEnv* first() { return JvmtiEnvBase::head_environment(); }
JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); }
};
class VM_GetOwnedMonitorInfo : public VM_Operation {
private:
JvmtiEnv *_env;
JavaThread* _calling_thread;
JavaThread *_java_thread;
jvmtiError _result;
GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;
public:
VM_GetOwnedMonitorInfo(JvmtiEnv* env, JavaThread* calling_thread,
JavaThread* java_thread,
GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list) {
_env = env;
_calling_thread = calling_thread;
_java_thread = java_thread;
_owned_monitors_list = owned_monitor_list;
_result = JVMTI_ERROR_NONE;
}
VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; }
void doit() {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
if (Threads::includes(_java_thread) && !_java_thread->is_exiting()
&& _java_thread->threadObj() != NULL) {
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread,
_owned_monitors_list);
}
}
jvmtiError result() { return _result; }
};
class VM_GetObjectMonitorUsage : public VM_Operation {
private:
JvmtiEnv *_env;
jobject _object;
JavaThread* _calling_thread;
jvmtiMonitorUsage* _info_ptr;
jvmtiError _result;
public:
VM_GetObjectMonitorUsage(JvmtiEnv *env, JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) {
_env = env;
_object = object;
_calling_thread = calling_thread;
_info_ptr = info_ptr;
}
VMOp_Type type() const { return VMOp_GetObjectMonitorUsage; }
jvmtiError result() { return _result; }
void doit() {
_result = ((JvmtiEnvBase*) _env)->get_object_monitor_usage(_calling_thread, _object, _info_ptr);
}
};
class VM_GetCurrentContendedMonitor : public VM_Operation {
private:
JvmtiEnv *_env;
JavaThread *_calling_thread;
JavaThread *_java_thread;
jobject *_owned_monitor_ptr;
jvmtiError _result;
public:
VM_GetCurrentContendedMonitor(JvmtiEnv *env, JavaThread *calling_thread, JavaThread *java_thread, jobject *mon_ptr) {
_env = env;
_calling_thread = calling_thread;
_java_thread = java_thread;
_owned_monitor_ptr = mon_ptr;
}
VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; }
jvmtiError result() { return _result; }
void doit() {
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
if (Threads::includes(_java_thread) && !_java_thread->is_exiting() &&
_java_thread->threadObj() != NULL) {
_result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr);
}
}
};
sssssss66
最新推荐文章于 2024-08-26 10:49:37 发布