Merge
This commit is contained in:
commit
3c7f50e9f2
hotspot/src/share/vm
@ -3647,8 +3647,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// If RedefineClasses() was used before the retransformable
|
||||
// agent attached, then the cached class bytes may not be the
|
||||
// original class bytes.
|
||||
unsigned char *cached_class_file_bytes = NULL;
|
||||
jint cached_class_file_length;
|
||||
JvmtiCachedClassFileData *cached_class_file = NULL;
|
||||
Handle class_loader(THREAD, loader_data->class_loader());
|
||||
bool has_default_methods = false;
|
||||
ResourceMark rm(THREAD);
|
||||
@ -3680,10 +3679,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
if (h_class_being_redefined != NULL) {
|
||||
instanceKlassHandle ikh_class_being_redefined =
|
||||
instanceKlassHandle(THREAD, (*h_class_being_redefined)());
|
||||
cached_class_file_bytes =
|
||||
ikh_class_being_redefined->get_cached_class_file_bytes();
|
||||
cached_class_file_length =
|
||||
ikh_class_being_redefined->get_cached_class_file_len();
|
||||
cached_class_file = ikh_class_being_redefined->get_cached_class_file();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3691,9 +3687,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
unsigned char* end_ptr = cfs->buffer() + cfs->length();
|
||||
|
||||
JvmtiExport::post_class_file_load_hook(name, class_loader(), protection_domain,
|
||||
&ptr, &end_ptr,
|
||||
&cached_class_file_bytes,
|
||||
&cached_class_file_length);
|
||||
&ptr, &end_ptr, &cached_class_file);
|
||||
|
||||
if (ptr != cfs->buffer()) {
|
||||
// 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
|
||||
this_klass->set_cached_class_file(cached_class_file_bytes,
|
||||
cached_class_file_length);
|
||||
this_klass->set_cached_class_file(cached_class_file);
|
||||
}
|
||||
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "oops/symbol.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
||||
#include "prims/jvmtiRedefineClasses.hpp"
|
||||
#include "prims/methodComparator.hpp"
|
||||
#include "runtime/fieldDescriptor.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
@ -291,7 +292,7 @@ InstanceKlass::InstanceKlass(int vtable_len,
|
||||
set_initial_method_idnum(0);
|
||||
_dependencies = 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_minor_version(0);
|
||||
set_major_version(0);
|
||||
@ -2357,10 +2358,9 @@ void InstanceKlass::release_C_heap_structures() {
|
||||
}
|
||||
|
||||
// deallocate the cached class file
|
||||
if (_cached_class_file_bytes != NULL) {
|
||||
os::free(_cached_class_file_bytes, mtClass);
|
||||
_cached_class_file_bytes = NULL;
|
||||
_cached_class_file_len = 0;
|
||||
if (_cached_class_file != NULL) {
|
||||
os::free(_cached_class_file, mtClass);
|
||||
_cached_class_file = NULL;
|
||||
}
|
||||
|
||||
// Decrement symbol reference counts associated with the unloaded class.
|
||||
@ -3530,6 +3530,14 @@ Method* InstanceKlass::method_with_idnum(int idnum) {
|
||||
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
|
||||
// the InstanceKlass.
|
||||
|
@ -133,6 +133,8 @@ class OopMapBlock VALUE_OBJ_CLASS_SPEC {
|
||||
uint _count;
|
||||
};
|
||||
|
||||
struct JvmtiCachedClassFileData;
|
||||
|
||||
class InstanceKlass: public Klass {
|
||||
friend class VMStructs;
|
||||
friend class ClassFileParser;
|
||||
@ -249,8 +251,8 @@ class InstanceKlass: public Klass {
|
||||
// InstanceKlass. See PreviousVersionWalker below.
|
||||
GrowableArray<PreviousVersionNode *>* _previous_versions;
|
||||
// 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
|
||||
jint _cached_class_file_len; // JVMTI: length of above
|
||||
// JVMTI: cached class file, before retransformable agent modified it in CFLH
|
||||
JvmtiCachedClassFileData* _cached_class_file;
|
||||
|
||||
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);
|
||||
|
||||
// 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,
|
||||
jint class_file_len) { _cached_class_file_len = class_file_len;
|
||||
_cached_class_file_bytes = class_file_bytes; }
|
||||
jint get_cached_class_file_len() { return _cached_class_file_len; }
|
||||
unsigned char * get_cached_class_file_bytes() { return _cached_class_file_bytes; }
|
||||
void set_cached_class_file(JvmtiCachedClassFileData *data) {
|
||||
_cached_class_file = data;
|
||||
}
|
||||
JvmtiCachedClassFileData * get_cached_class_file() { return _cached_class_file; }
|
||||
jint get_cached_class_file_len();
|
||||
unsigned char * get_cached_class_file_bytes();
|
||||
|
||||
// JVMTI: Support for caching of field indices, types, and offsets
|
||||
void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "prims/jvmtiRawMonitor.hpp"
|
||||
#include "prims/jvmtiTagMap.hpp"
|
||||
#include "prims/jvmtiThreadState.inline.hpp"
|
||||
#include "prims/jvmtiRedefineClasses.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/interfaceSupport.hpp"
|
||||
@ -516,8 +517,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
jint _curr_len;
|
||||
unsigned char * _curr_data;
|
||||
JvmtiEnv * _curr_env;
|
||||
jint * _cached_length_ptr;
|
||||
unsigned char ** _cached_data_ptr;
|
||||
JvmtiCachedClassFileData ** _cached_class_file_ptr;
|
||||
JvmtiThreadState * _state;
|
||||
KlassHandle * _h_class_being_redefined;
|
||||
JvmtiClassLoadKind _load_kind;
|
||||
@ -526,8 +526,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
|
||||
Handle h_protection_domain,
|
||||
unsigned char **data_ptr, unsigned char **end_ptr,
|
||||
unsigned char **cached_data_ptr,
|
||||
jint *cached_length_ptr) {
|
||||
JvmtiCachedClassFileData **cache_ptr) {
|
||||
_h_name = h_name;
|
||||
_class_loader = class_loader;
|
||||
_h_protection_domain = h_protection_domain;
|
||||
@ -537,8 +536,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
_curr_len = *end_ptr - *data_ptr;
|
||||
_curr_data = *data_ptr;
|
||||
_curr_env = NULL;
|
||||
_cached_length_ptr = cached_length_ptr;
|
||||
_cached_data_ptr = cached_data_ptr;
|
||||
_cached_class_file_ptr = cache_ptr;
|
||||
|
||||
_state = _thread->jvmti_thread_state();
|
||||
if (_state != NULL) {
|
||||
@ -615,15 +613,20 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
}
|
||||
if (new_data != NULL) {
|
||||
// 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
|
||||
// and it hasn't already been cached, cache it
|
||||
*_cached_data_ptr = (unsigned char *)os::malloc(_curr_len, mtInternal);
|
||||
if (*_cached_data_ptr == NULL) {
|
||||
vm_exit_out_of_memory(_curr_len, OOM_MALLOC_ERROR, "unable to allocate cached copy of original class bytes");
|
||||
JvmtiCachedClassFileData *p;
|
||||
p = (JvmtiCachedClassFileData *)os::malloc(
|
||||
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);
|
||||
*_cached_length_ptr = _curr_len;
|
||||
p->length = _curr_len;
|
||||
memcpy(p->data, _curr_data, _curr_len);
|
||||
*_cached_class_file_ptr = p;
|
||||
}
|
||||
|
||||
if (_curr_data != *_data_ptr) {
|
||||
@ -662,13 +665,11 @@ void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
|
||||
Handle h_protection_domain,
|
||||
unsigned char **data_ptr,
|
||||
unsigned char **end_ptr,
|
||||
unsigned char **cached_data_ptr,
|
||||
jint *cached_length_ptr) {
|
||||
JvmtiCachedClassFileData **cache_ptr) {
|
||||
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
||||
h_protection_domain,
|
||||
data_ptr, end_ptr,
|
||||
cached_data_ptr,
|
||||
cached_length_ptr);
|
||||
cache_ptr);
|
||||
poster.post();
|
||||
}
|
||||
|
||||
|
@ -323,8 +323,7 @@ class JvmtiExport : public AllStatic {
|
||||
static void post_class_file_load_hook(Symbol* h_name, Handle class_loader,
|
||||
Handle h_protection_domain,
|
||||
unsigned char **data_ptr, unsigned char **end_ptr,
|
||||
unsigned char **cached_data_ptr,
|
||||
jint *cached_length_ptr) NOT_JVMTI_RETURN;
|
||||
JvmtiCachedClassFileData **cache_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_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.
|
||||
if (the_class->get_cached_class_file_bytes() == 0) {
|
||||
// the_class doesn't have a cache yet so copy it
|
||||
the_class->set_cached_class_file(
|
||||
scratch_class->get_cached_class_file_bytes(),
|
||||
scratch_class->get_cached_class_file_len());
|
||||
the_class->set_cached_class_file(scratch_class->get_cached_class_file());
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
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
|
||||
// always owns these bytes.
|
||||
scratch_class->set_cached_class_file(NULL, 0);
|
||||
scratch_class->set_cached_class_file(NULL);
|
||||
|
||||
// Replace inner_classes
|
||||
Array<u2>* old_inner_classes = the_class->inner_classes();
|
||||
|
@ -331,6 +331,11 @@
|
||||
// coordinate a cleanup of these constants with Runtime.
|
||||
//
|
||||
|
||||
struct JvmtiCachedClassFileData {
|
||||
jint length;
|
||||
unsigned char data[1];
|
||||
};
|
||||
|
||||
class VM_RedefineClasses: public VM_Operation {
|
||||
private:
|
||||
// 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
|
||||
// and redefine implementation
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user