mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8020309: Eliminate InstanceKlass::_cached_class_file_len
Use JvmtiCachedClassFileData. Reviewed-by: iklam, sspitsyn, dcubed
This commit is contained in:
parent
9a67229e2f
commit
3dfcb4125e
7 changed files with 60 additions and 46 deletions
|
@ -3647,8 +3647,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
// If RedefineClasses() was used before the retransformable
|
// If RedefineClasses() was used before the retransformable
|
||||||
// agent attached, then the cached class bytes may not be the
|
// agent attached, then the cached class bytes may not be the
|
||||||
// original class bytes.
|
// original class bytes.
|
||||||
unsigned char *cached_class_file_bytes = NULL;
|
JvmtiCachedClassFileData *cached_class_file = NULL;
|
||||||
jint cached_class_file_length;
|
|
||||||
Handle class_loader(THREAD, loader_data->class_loader());
|
Handle class_loader(THREAD, loader_data->class_loader());
|
||||||
bool has_default_methods = false;
|
bool has_default_methods = false;
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -3680,10 +3679,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
if (h_class_being_redefined != NULL) {
|
if (h_class_being_redefined != NULL) {
|
||||||
instanceKlassHandle ikh_class_being_redefined =
|
instanceKlassHandle ikh_class_being_redefined =
|
||||||
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
|
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
|
||||||
cached_class_file_bytes =
|
cached_class_file = ikh_class_being_redefined->get_cached_class_file();
|
||||||
ikh_class_being_redefined->get_cached_class_file_bytes();
|
|
||||||
cached_class_file_length =
|
|
||||||
ikh_class_being_redefined->get_cached_class_file_len();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3691,9 +3687,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
unsigned char* end_ptr = cfs->buffer() + cfs->length();
|
unsigned char* end_ptr = cfs->buffer() + cfs->length();
|
||||||
|
|
||||||
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
|
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
|
||||||
&ptr, &end_ptr,
|
&ptr, &end_ptr, &cached_class_file);
|
||||||
&cached_class_file_bytes,
|
|
||||||
&cached_class_file_length);
|
|
||||||
|
|
||||||
if (ptr != cfs->buffer()) {
|
if (ptr != cfs->buffer()) {
|
||||||
// JVMTI agent has modified class file data.
|
// JVMTI agent has modified class file data.
|
||||||
|
@ -4011,10 +4005,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached_class_file_bytes != NULL) {
|
if (cached_class_file != NULL) {
|
||||||
// JVMTI: we have an InstanceKlass now, tell it about the cached bytes
|
// JVMTI: we have an InstanceKlass now, tell it about the cached bytes
|
||||||
this_klass->set_cached_class_file(cached_class_file_bytes,
|
this_klass->set_cached_class_file(cached_class_file);
|
||||||
cached_class_file_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in field values obtained by parse_classfile_attributes
|
// Fill in field values obtained by parse_classfile_attributes
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "oops/symbol.hpp"
|
#include "oops/symbol.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
||||||
|
#include "prims/jvmtiRedefineClasses.hpp"
|
||||||
#include "prims/methodComparator.hpp"
|
#include "prims/methodComparator.hpp"
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
|
@ -291,7 +292,7 @@ InstanceKlass::InstanceKlass(int vtable_len,
|
||||||
set_initial_method_idnum(0);
|
set_initial_method_idnum(0);
|
||||||
_dependencies = NULL;
|
_dependencies = NULL;
|
||||||
set_jvmti_cached_class_field_map(NULL);
|
set_jvmti_cached_class_field_map(NULL);
|
||||||
set_cached_class_file(NULL, 0);
|
set_cached_class_file(NULL);
|
||||||
set_initial_method_idnum(0);
|
set_initial_method_idnum(0);
|
||||||
set_minor_version(0);
|
set_minor_version(0);
|
||||||
set_major_version(0);
|
set_major_version(0);
|
||||||
|
@ -2357,10 +2358,9 @@ void InstanceKlass::release_C_heap_structures() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// deallocate the cached class file
|
// deallocate the cached class file
|
||||||
if (_cached_class_file_bytes != NULL) {
|
if (_cached_class_file != NULL) {
|
||||||
os::free(_cached_class_file_bytes, mtClass);
|
os::free(_cached_class_file, mtClass);
|
||||||
_cached_class_file_bytes = NULL;
|
_cached_class_file = NULL;
|
||||||
_cached_class_file_len = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement symbol reference counts associated with the unloaded class.
|
// Decrement symbol reference counts associated with the unloaded class.
|
||||||
|
@ -3530,6 +3530,14 @@ Method* InstanceKlass::method_with_idnum(int idnum) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jint InstanceKlass::get_cached_class_file_len() {
|
||||||
|
return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
|
||||||
|
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Construct a PreviousVersionNode entry for the array hung off
|
// Construct a PreviousVersionNode entry for the array hung off
|
||||||
// the InstanceKlass.
|
// the InstanceKlass.
|
||||||
|
|
|
@ -133,6 +133,8 @@ class OopMapBlock VALUE_OBJ_CLASS_SPEC {
|
||||||
uint _count;
|
uint _count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct JvmtiCachedClassFileData;
|
||||||
|
|
||||||
class InstanceKlass: public Klass {
|
class InstanceKlass: public Klass {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class ClassFileParser;
|
friend class ClassFileParser;
|
||||||
|
@ -249,8 +251,8 @@ class InstanceKlass: public Klass {
|
||||||
// InstanceKlass. See PreviousVersionWalker below.
|
// InstanceKlass. See PreviousVersionWalker below.
|
||||||
GrowableArray<PreviousVersionNode *>* _previous_versions;
|
GrowableArray<PreviousVersionNode *>* _previous_versions;
|
||||||
// JVMTI fields can be moved to their own structure - see 6315920
|
// JVMTI fields can be moved to their own structure - see 6315920
|
||||||
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
|
// JVMTI: cached class file, before retransformable agent modified it in CFLH
|
||||||
jint _cached_class_file_len; // JVMTI: length of above
|
JvmtiCachedClassFileData* _cached_class_file;
|
||||||
|
|
||||||
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
|
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
|
||||||
|
|
||||||
|
@ -615,11 +617,12 @@ class InstanceKlass: public Klass {
|
||||||
static void purge_previous_versions(InstanceKlass* ik);
|
static void purge_previous_versions(InstanceKlass* ik);
|
||||||
|
|
||||||
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
|
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation
|
||||||
void set_cached_class_file(unsigned char *class_file_bytes,
|
void set_cached_class_file(JvmtiCachedClassFileData *data) {
|
||||||
jint class_file_len) { _cached_class_file_len = class_file_len;
|
_cached_class_file = data;
|
||||||
_cached_class_file_bytes = class_file_bytes; }
|
}
|
||||||
jint get_cached_class_file_len() { return _cached_class_file_len; }
|
JvmtiCachedClassFileData * get_cached_class_file() { return _cached_class_file; }
|
||||||
unsigned char * get_cached_class_file_bytes() { return _cached_class_file_bytes; }
|
jint get_cached_class_file_len();
|
||||||
|
unsigned char * get_cached_class_file_bytes();
|
||||||
|
|
||||||
// JVMTI: Support for caching of field indices, types, and offsets
|
// JVMTI: Support for caching of field indices, types, and offsets
|
||||||
void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {
|
void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "prims/jvmtiRawMonitor.hpp"
|
#include "prims/jvmtiRawMonitor.hpp"
|
||||||
#include "prims/jvmtiTagMap.hpp"
|
#include "prims/jvmtiTagMap.hpp"
|
||||||
#include "prims/jvmtiThreadState.inline.hpp"
|
#include "prims/jvmtiThreadState.inline.hpp"
|
||||||
|
#include "prims/jvmtiRedefineClasses.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/handles.hpp"
|
#include "runtime/handles.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
|
@ -516,8 +517,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||||
jint _curr_len;
|
jint _curr_len;
|
||||||
unsigned char * _curr_data;
|
unsigned char * _curr_data;
|
||||||
JvmtiEnv * _curr_env;
|
JvmtiEnv * _curr_env;
|
||||||
jint * _cached_length_ptr;
|
JvmtiCachedClassFileData ** _cached_class_file_ptr;
|
||||||
unsigned char ** _cached_data_ptr;
|
|
||||||
JvmtiThreadState * _state;
|
JvmtiThreadState * _state;
|
||||||
KlassHandle * _h_class_being_redefined;
|
KlassHandle * _h_class_being_redefined;
|
||||||
JvmtiClassLoadKind _load_kind;
|
JvmtiClassLoadKind _load_kind;
|
||||||
|
@ -526,8 +526,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||||
inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
|
inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
|
||||||
Handle h_protection_domain,
|
Handle h_protection_domain,
|
||||||
unsigned char **data_ptr, unsigned char **end_ptr,
|
unsigned char **data_ptr, unsigned char **end_ptr,
|
||||||
unsigned char **cached_data_ptr,
|
JvmtiCachedClassFileData **cache_ptr) {
|
||||||
jint *cached_length_ptr) {
|
|
||||||
_h_name = h_name;
|
_h_name = h_name;
|
||||||
_class_loader = class_loader;
|
_class_loader = class_loader;
|
||||||
_h_protection_domain = h_protection_domain;
|
_h_protection_domain = h_protection_domain;
|
||||||
|
@ -537,8 +536,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||||
_curr_len = *end_ptr - *data_ptr;
|
_curr_len = *end_ptr - *data_ptr;
|
||||||
_curr_data = *data_ptr;
|
_curr_data = *data_ptr;
|
||||||
_curr_env = NULL;
|
_curr_env = NULL;
|
||||||
_cached_length_ptr = cached_length_ptr;
|
_cached_class_file_ptr = cache_ptr;
|
||||||
_cached_data_ptr = cached_data_ptr;
|
|
||||||
|
|
||||||
_state = _thread->jvmti_thread_state();
|
_state = _thread->jvmti_thread_state();
|
||||||
if (_state != NULL) {
|
if (_state != NULL) {
|
||||||
|
@ -615,15 +613,20 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||||
}
|
}
|
||||||
if (new_data != NULL) {
|
if (new_data != NULL) {
|
||||||
// this agent has modified class data.
|
// this agent has modified class data.
|
||||||
if (caching_needed && *_cached_data_ptr == NULL) {
|
if (caching_needed && *_cached_class_file_ptr == NULL) {
|
||||||
// data has been changed by the new retransformable agent
|
// data has been changed by the new retransformable agent
|
||||||
// and it hasn't already been cached, cache it
|
// and it hasn't already been cached, cache it
|
||||||
*_cached_data_ptr = (unsigned char *)os::malloc(_curr_len, mtInternal);
|
JvmtiCachedClassFileData *p;
|
||||||
if (*_cached_data_ptr == NULL) {
|
p = (JvmtiCachedClassFileData *)os::malloc(
|
||||||
vm_exit_out_of_memory(_curr_len, OOM_MALLOC_ERROR, "unable to allocate cached copy of original class bytes");
|
offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal);
|
||||||
|
if (p == NULL) {
|
||||||
|
vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len,
|
||||||
|
OOM_MALLOC_ERROR,
|
||||||
|
"unable to allocate cached copy of original class bytes");
|
||||||
}
|
}
|
||||||
memcpy(*_cached_data_ptr, _curr_data, _curr_len);
|
p->length = _curr_len;
|
||||||
*_cached_length_ptr = _curr_len;
|
memcpy(p->data, _curr_data, _curr_len);
|
||||||
|
*_cached_class_file_ptr = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_curr_data != *_data_ptr) {
|
if (_curr_data != *_data_ptr) {
|
||||||
|
@ -662,13 +665,11 @@ void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
|
||||||
Handle h_protection_domain,
|
Handle h_protection_domain,
|
||||||
unsigned char **data_ptr,
|
unsigned char **data_ptr,
|
||||||
unsigned char **end_ptr,
|
unsigned char **end_ptr,
|
||||||
unsigned char **cached_data_ptr,
|
JvmtiCachedClassFileData **cache_ptr) {
|
||||||
jint *cached_length_ptr) {
|
|
||||||
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
||||||
h_protection_domain,
|
h_protection_domain,
|
||||||
data_ptr, end_ptr,
|
data_ptr, end_ptr,
|
||||||
cached_data_ptr,
|
cache_ptr);
|
||||||
cached_length_ptr);
|
|
||||||
poster.post();
|
poster.post();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,8 +323,7 @@ class JvmtiExport : public AllStatic {
|
||||||
static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
|
static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
|
||||||
Handle h_protection_domain,
|
Handle h_protection_domain,
|
||||||
unsigned char **data_ptr, unsigned char **end_ptr,
|
unsigned char **data_ptr, unsigned char **end_ptr,
|
||||||
unsigned char **cached_data_ptr,
|
JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN;
|
||||||
jint *cached_length_ptr) NOT_JVMTI_RETURN;
|
|
||||||
static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN;
|
static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN;
|
||||||
static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN;
|
static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN;
|
||||||
static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN;
|
static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN;
|
||||||
|
|
|
@ -3342,9 +3342,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||||
// should get cleared in the_class too.
|
// should get cleared in the_class too.
|
||||||
if (the_class->get_cached_class_file_bytes() == 0) {
|
if (the_class->get_cached_class_file_bytes() == 0) {
|
||||||
// the_class doesn't have a cache yet so copy it
|
// the_class doesn't have a cache yet so copy it
|
||||||
the_class->set_cached_class_file(
|
the_class->set_cached_class_file(scratch_class->get_cached_class_file());
|
||||||
scratch_class->get_cached_class_file_bytes(),
|
|
||||||
scratch_class->get_cached_class_file_len());
|
|
||||||
}
|
}
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
else {
|
else {
|
||||||
|
@ -3357,7 +3355,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
||||||
|
|
||||||
// NULL out in scratch class to not delete twice. The class to be redefined
|
// NULL out in scratch class to not delete twice. The class to be redefined
|
||||||
// always owns these bytes.
|
// always owns these bytes.
|
||||||
scratch_class->set_cached_class_file(NULL, 0);
|
scratch_class->set_cached_class_file(NULL);
|
||||||
|
|
||||||
// Replace inner_classes
|
// Replace inner_classes
|
||||||
Array<u2>* old_inner_classes = the_class->inner_classes();
|
Array<u2>* old_inner_classes = the_class->inner_classes();
|
||||||
|
|
|
@ -331,6 +331,11 @@
|
||||||
// coordinate a cleanup of these constants with Runtime.
|
// coordinate a cleanup of these constants with Runtime.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
struct JvmtiCachedClassFileData {
|
||||||
|
jint length;
|
||||||
|
unsigned char data[1];
|
||||||
|
};
|
||||||
|
|
||||||
class VM_RedefineClasses: public VM_Operation {
|
class VM_RedefineClasses: public VM_Operation {
|
||||||
private:
|
private:
|
||||||
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
||||||
|
@ -509,5 +514,12 @@ class VM_RedefineClasses: public VM_Operation {
|
||||||
// Modifiable test must be shared between IsModifiableClass query
|
// Modifiable test must be shared between IsModifiableClass query
|
||||||
// and redefine implementation
|
// and redefine implementation
|
||||||
static bool is_modifiable_class(oop klass_mirror);
|
static bool is_modifiable_class(oop klass_mirror);
|
||||||
|
|
||||||
|
static jint get_cached_class_file_len(JvmtiCachedClassFileData *cache) {
|
||||||
|
return cache == NULL ? 0 : cache->length;
|
||||||
|
}
|
||||||
|
static unsigned char * get_cached_class_file_bytes(JvmtiCachedClassFileData *cache) {
|
||||||
|
return cache == NULL ? NULL : cache->data;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP
|
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue