8078644: CDS needs to support JVMTI CFLH
Support posting CLFH for shared classes. Tests are contributed by Misha Seledtsov. Reviewed-by: iklam, coleenp, acorn, dcubed, sspitsyn
This commit is contained in:
parent
38eb4a4f6f
commit
eb52950704
hotspot
src/share/vm
classfile
memory
oops
utilities
test
@ -25,12 +25,85 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classFileParser.hpp"
|
||||
#include "classfile/classFileStream.hpp"
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/klassFactory.hpp"
|
||||
#include "classfile/sharedClassUtil.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/jvmtiEnvBase.hpp"
|
||||
#include "prims/jvmtiRedefineClasses.hpp"
|
||||
#include "trace/traceMacros.hpp"
|
||||
|
||||
// called during initial loading of a shared class
|
||||
instanceKlassHandle KlassFactory::check_shared_class_file_load_hook(
|
||||
instanceKlassHandle ik,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS) {
|
||||
#if INCLUDE_CDS && INCLUDE_JVMTI
|
||||
assert(ik.not_null(), "sanity");
|
||||
assert(ik()->is_shared(), "expecting a shared class");
|
||||
|
||||
if (JvmtiExport::should_post_class_file_load_hook()) {
|
||||
assert(THREAD->is_Java_thread(), "must be JavaThread");
|
||||
|
||||
// Post the CFLH
|
||||
JvmtiCachedClassFileData* cached_class_file = NULL;
|
||||
JvmtiCachedClassFileData* archived_class_data = ik->get_archived_class_data();
|
||||
assert(archived_class_data != NULL, "shared class has no archived class data");
|
||||
unsigned char* ptr =
|
||||
VM_RedefineClasses::get_cached_class_file_bytes(archived_class_data);
|
||||
unsigned char* end_ptr =
|
||||
ptr + VM_RedefineClasses::get_cached_class_file_len(archived_class_data);
|
||||
unsigned char* old_ptr = ptr;
|
||||
JvmtiExport::post_class_file_load_hook(class_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
&ptr,
|
||||
&end_ptr,
|
||||
&cached_class_file);
|
||||
if (old_ptr != ptr) {
|
||||
// JVMTI agent has modified class file data.
|
||||
// Set new class file stream using JVMTI agent modified class file data.
|
||||
ClassLoaderData* loader_data =
|
||||
ClassLoaderData::class_loader_data(class_loader());
|
||||
int path_index = ik->shared_classpath_index();
|
||||
SharedClassPathEntry* ent =
|
||||
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
|
||||
ClassFileStream* stream = new ClassFileStream(ptr,
|
||||
end_ptr - ptr,
|
||||
ent->_name,
|
||||
ClassFileStream::verify);
|
||||
ClassFileParser parser(stream,
|
||||
class_name,
|
||||
loader_data,
|
||||
protection_domain,
|
||||
NULL,
|
||||
NULL,
|
||||
ClassFileParser::BROADCAST, // publicity level
|
||||
CHECK_NULL);
|
||||
instanceKlassHandle new_ik = parser.create_instance_klass(true /* changed_by_loadhook */,
|
||||
CHECK_NULL);
|
||||
if (cached_class_file != NULL) {
|
||||
new_ik->set_cached_class_file(cached_class_file);
|
||||
}
|
||||
|
||||
if (class_loader.is_null()) {
|
||||
ResourceMark rm;
|
||||
ClassLoader::add_package(class_name->as_C_string(), path_index, THREAD);
|
||||
}
|
||||
|
||||
return new_ik;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream,
|
||||
Symbol* name,
|
||||
ClassLoaderData* loader_data,
|
||||
@ -97,7 +170,6 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
|
||||
const InstanceKlass* host_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS) {
|
||||
|
||||
assert(stream != NULL, "invariant");
|
||||
assert(loader_data != NULL, "invariant");
|
||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
||||
@ -142,5 +214,27 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
|
||||
|
||||
TRACE_KLASS_CREATION(result, parser, THREAD);
|
||||
|
||||
#if INCLUDE_CDS && INCLUDE_JVMTI
|
||||
if (DumpSharedSpaces) {
|
||||
assert(cached_class_file == NULL, "Sanity");
|
||||
// Archive the class stream data into the optional data section
|
||||
JvmtiCachedClassFileData *p;
|
||||
int len;
|
||||
const unsigned char *bytes;
|
||||
// event based tracing might set cached_class_file
|
||||
if ((bytes = result->get_cached_class_file_bytes()) != NULL) {
|
||||
len = result->get_cached_class_file_len();
|
||||
} else {
|
||||
len = stream->length();
|
||||
bytes = stream->buffer();
|
||||
}
|
||||
p = (JvmtiCachedClassFileData*)MetaspaceShared::optional_data_space_alloc(
|
||||
offset_of(JvmtiCachedClassFileData, data) + len);
|
||||
p->length = len;
|
||||
memcpy(p->data, bytes, len);
|
||||
result->set_archived_class_data(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -75,6 +75,12 @@ class KlassFactory : AllStatic {
|
||||
const InstanceKlass* host_klass,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
TRAPS);
|
||||
public:
|
||||
static instanceKlassHandle check_shared_class_file_load_hook(
|
||||
instanceKlassHandle ik,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_KLASSFACTORY_HPP
|
||||
|
@ -1210,16 +1210,12 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) {
|
||||
|
||||
instanceKlassHandle SystemDictionary::load_shared_class(
|
||||
Symbol* class_name, Handle class_loader, TRAPS) {
|
||||
// Don't load shared class when JvmtiExport::should_post_class_file_load_hook()
|
||||
// is enabled since posting CFLH is not supported when loading shared class.
|
||||
if (!JvmtiExport::should_post_class_file_load_hook()) {
|
||||
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
||||
// Make sure we only return the boot class for the NULL classloader.
|
||||
if (ik.not_null() &&
|
||||
ik->is_shared_boot_class() && class_loader.is_null()) {
|
||||
Handle protection_domain;
|
||||
return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
||||
}
|
||||
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
||||
// Make sure we only return the boot class for the NULL classloader.
|
||||
if (ik.not_null() &&
|
||||
ik->is_shared_boot_class() && class_loader.is_null()) {
|
||||
Handle protection_domain;
|
||||
return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
||||
}
|
||||
return instanceKlassHandle();
|
||||
}
|
||||
@ -1303,11 +1299,6 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS) {
|
||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||
if (JvmtiExport::should_post_class_file_load_hook()) {
|
||||
// Don't load shared class when JvmtiExport::should_post_class_file_load_hook()
|
||||
// is enabled since posting CFLH is not supported when loading shared class.
|
||||
return nh;
|
||||
}
|
||||
|
||||
if (ik.not_null()) {
|
||||
Symbol* class_name = ik->name();
|
||||
@ -1358,6 +1349,14 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
||||
}
|
||||
}
|
||||
|
||||
instanceKlassHandle new_ik = KlassFactory::check_shared_class_file_load_hook(
|
||||
ik, class_name, class_loader, protection_domain, CHECK_(nh));
|
||||
if (new_ik.not_null()) {
|
||||
// The class is changed by CFLH. Return the new class. The shared class is
|
||||
// not used.
|
||||
return new_ik;
|
||||
}
|
||||
|
||||
// Adjust methods to recover missing data. They need addresses for
|
||||
// interpreter entry points and their default native method address
|
||||
// must be reset.
|
||||
|
@ -649,7 +649,7 @@ ReservedSpace FileMapInfo::reserve_shared_memory() {
|
||||
|
||||
// Memory map a region in the address space.
|
||||
static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode",
|
||||
"String1", "String2" };
|
||||
"String1", "String2", "OptionalData" };
|
||||
|
||||
char* FileMapInfo::map_region(int i) {
|
||||
assert(!MetaspaceShared::is_string_region(i), "sanity");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -252,10 +252,27 @@ public:
|
||||
bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
|
||||
void print_shared_spaces() NOT_CDS_RETURN;
|
||||
|
||||
// The ro+rw+md+mc spaces size
|
||||
static size_t core_spaces_size() {
|
||||
return align_size_up((SharedReadOnlySize + SharedReadWriteSize +
|
||||
SharedMiscDataSize + SharedMiscCodeSize),
|
||||
os::vm_allocation_granularity());
|
||||
}
|
||||
|
||||
// The estimated optional space size.
|
||||
//
|
||||
// Currently the optional space only has archived class bytes.
|
||||
// The core_spaces_size is the size of all class metadata, which is a good
|
||||
// estimate of the total class bytes to be archived. Only the portion
|
||||
// containing data is written out to the archive and mapped at runtime.
|
||||
// There is no memory waste due to unused portion in optional space.
|
||||
static size_t optional_space_size() {
|
||||
return core_spaces_size();
|
||||
}
|
||||
|
||||
// Total shared_spaces size includes the ro, rw, md, mc and od spaces
|
||||
static size_t shared_spaces_size() {
|
||||
return align_size_up(SharedReadOnlySize + SharedReadWriteSize +
|
||||
SharedMiscDataSize + SharedMiscCodeSize,
|
||||
os::vm_allocation_granularity());
|
||||
return core_spaces_size() + optional_space_size();
|
||||
}
|
||||
|
||||
// Stop CDS sharing and unmap CDS regions.
|
||||
|
@ -3172,36 +3172,28 @@ void Metaspace::global_initialize() {
|
||||
address cds_address = NULL;
|
||||
FileMapInfo* mapinfo = new FileMapInfo();
|
||||
|
||||
if (JvmtiExport::should_post_class_file_load_hook()) {
|
||||
// Currently CDS does not support JVMTI CFLH when loading shared class.
|
||||
// If JvmtiExport::should_post_class_file_load_hook is already enabled,
|
||||
// just disable UseSharedSpaces.
|
||||
FileMapInfo::fail_continue("Tool agent requires sharing to be disabled.");
|
||||
delete mapinfo;
|
||||
} else {
|
||||
// Open the shared archive file, read and validate the header. If
|
||||
// initialization fails, shared spaces [UseSharedSpaces] are
|
||||
// disabled and the file is closed.
|
||||
// Map in spaces now also
|
||||
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
|
||||
cds_total = FileMapInfo::shared_spaces_size();
|
||||
cds_address = (address)mapinfo->header()->region_addr(0);
|
||||
// Open the shared archive file, read and validate the header. If
|
||||
// initialization fails, shared spaces [UseSharedSpaces] are
|
||||
// disabled and the file is closed.
|
||||
// Map in spaces now also
|
||||
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
|
||||
cds_total = FileMapInfo::shared_spaces_size();
|
||||
cds_address = (address)mapinfo->header()->region_addr(0);
|
||||
#ifdef _LP64
|
||||
if (using_class_space()) {
|
||||
char* cds_end = (char*)(cds_address + cds_total);
|
||||
cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
|
||||
// If UseCompressedClassPointers is set then allocate the metaspace area
|
||||
// above the heap and above the CDS area (if it exists).
|
||||
allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
|
||||
// Map the shared string space after compressed pointers
|
||||
// because it relies on compressed class pointers setting to work
|
||||
mapinfo->map_string_regions();
|
||||
}
|
||||
#endif // _LP64
|
||||
} else {
|
||||
assert(!mapinfo->is_open() && !UseSharedSpaces,
|
||||
"archive file not closed or shared spaces not disabled.");
|
||||
if (using_class_space()) {
|
||||
char* cds_end = (char*)(cds_address + cds_total);
|
||||
cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
|
||||
// If UseCompressedClassPointers is set then allocate the metaspace area
|
||||
// above the heap and above the CDS area (if it exists).
|
||||
allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
|
||||
// Map the shared string space after compressed pointers
|
||||
// because it relies on compressed class pointers setting to work
|
||||
mapinfo->map_string_regions();
|
||||
}
|
||||
#endif // _LP64
|
||||
} else {
|
||||
assert(!mapinfo->is_open() && !UseSharedSpaces,
|
||||
"archive file not closed or shared spaces not disabled.");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
@ -65,6 +65,7 @@ address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL;
|
||||
size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0;
|
||||
SharedMiscRegion MetaspaceShared::_mc;
|
||||
SharedMiscRegion MetaspaceShared::_md;
|
||||
SharedMiscRegion MetaspaceShared::_od;
|
||||
|
||||
void SharedMiscRegion::initialize(ReservedSpace rs, size_t committed_byte_size, SharedSpaceType space_type) {
|
||||
_vs.initialize(rs, committed_byte_size);
|
||||
@ -93,16 +94,24 @@ void MetaspaceShared::initialize_shared_rs(ReservedSpace* rs) {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
_shared_rs = rs;
|
||||
|
||||
// Split up and initialize the misc code and data spaces
|
||||
size_t core_spaces_size = FileMapInfo::core_spaces_size();
|
||||
size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize;
|
||||
ReservedSpace shared_ro_rw = _shared_rs->first_part(metadata_size);
|
||||
ReservedSpace misc_section = _shared_rs->last_part(metadata_size);
|
||||
|
||||
// Now split into misc sections.
|
||||
// Split into the core and optional sections
|
||||
ReservedSpace core_data = _shared_rs->first_part(core_spaces_size);
|
||||
ReservedSpace optional_data = _shared_rs->last_part(core_spaces_size);
|
||||
|
||||
// The RO/RW and the misc sections
|
||||
ReservedSpace shared_ro_rw = core_data.first_part(metadata_size);
|
||||
ReservedSpace misc_section = core_data.last_part(metadata_size);
|
||||
|
||||
// Now split the misc code and misc data sections.
|
||||
ReservedSpace md_rs = misc_section.first_part(SharedMiscDataSize);
|
||||
ReservedSpace mc_rs = misc_section.last_part(SharedMiscDataSize);
|
||||
|
||||
_md.initialize(md_rs, SharedMiscDataSize, SharedMiscData);
|
||||
_mc.initialize(mc_rs, SharedMiscCodeSize, SharedMiscData);
|
||||
_mc.initialize(mc_rs, SharedMiscCodeSize, SharedMiscCode);
|
||||
_od.initialize(optional_data, metadata_size, SharedOptional);
|
||||
}
|
||||
|
||||
// Read/write a data stream for restoring/preserving metadata pointers and
|
||||
@ -521,6 +530,7 @@ private:
|
||||
GrowableArray<Klass*> *_class_promote_order;
|
||||
VirtualSpace _md_vs;
|
||||
VirtualSpace _mc_vs;
|
||||
VirtualSpace _od_vs;
|
||||
GrowableArray<MemRegion> *_string_regions;
|
||||
|
||||
public:
|
||||
@ -598,15 +608,19 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
remove_unshareable_in_classes();
|
||||
tty->print_cr("done. ");
|
||||
|
||||
// Set up the share data and shared code segments.
|
||||
// Set up the misc data, misc code and optional data segments.
|
||||
_md_vs = *MetaspaceShared::misc_data_region()->virtual_space();
|
||||
_mc_vs = *MetaspaceShared::misc_code_region()->virtual_space();
|
||||
_od_vs = *MetaspaceShared::optional_data_region()->virtual_space();
|
||||
char* md_low = _md_vs.low();
|
||||
char* md_top = MetaspaceShared::misc_data_region()->alloc_top();
|
||||
char* md_end = _md_vs.high();
|
||||
char* mc_low = _mc_vs.low();
|
||||
char* mc_top = MetaspaceShared::misc_code_region()->alloc_top();
|
||||
char* mc_end = _mc_vs.high();
|
||||
char* od_low = _od_vs.low();
|
||||
char* od_top = MetaspaceShared::optional_data_region()->alloc_top();
|
||||
char* od_end = _od_vs.high();
|
||||
|
||||
// Reserve space for the list of Klass*s whose vtables are used
|
||||
// for patching others as needed.
|
||||
@ -661,28 +675,32 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
const size_t rw_alloced = rw_space->capacity_bytes_slow(Metaspace::NonClassType);
|
||||
const size_t md_alloced = md_end-md_low;
|
||||
const size_t mc_alloced = mc_end-mc_low;
|
||||
const size_t od_alloced = od_end-od_low;
|
||||
const size_t total_alloced = ro_alloced + rw_alloced + md_alloced + mc_alloced
|
||||
+ ss_bytes;
|
||||
+ ss_bytes + od_alloced;
|
||||
|
||||
// Occupied size of each space.
|
||||
const size_t ro_bytes = ro_space->used_bytes_slow(Metaspace::NonClassType);
|
||||
const size_t rw_bytes = rw_space->used_bytes_slow(Metaspace::NonClassType);
|
||||
const size_t md_bytes = size_t(md_top - md_low);
|
||||
const size_t mc_bytes = size_t(mc_top - mc_low);
|
||||
const size_t od_bytes = size_t(od_top - od_low);
|
||||
|
||||
// Percent of total size
|
||||
const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes + ss_bytes;
|
||||
const size_t total_bytes = ro_bytes + rw_bytes + md_bytes + mc_bytes + ss_bytes + od_bytes;
|
||||
const double ro_t_perc = ro_bytes / double(total_bytes) * 100.0;
|
||||
const double rw_t_perc = rw_bytes / double(total_bytes) * 100.0;
|
||||
const double md_t_perc = md_bytes / double(total_bytes) * 100.0;
|
||||
const double mc_t_perc = mc_bytes / double(total_bytes) * 100.0;
|
||||
const double ss_t_perc = ss_bytes / double(total_bytes) * 100.0;
|
||||
const double od_t_perc = od_bytes / double(total_bytes) * 100.0;
|
||||
|
||||
// Percent of fullness of each space
|
||||
const double ro_u_perc = ro_bytes / double(ro_alloced) * 100.0;
|
||||
const double rw_u_perc = rw_bytes / double(rw_alloced) * 100.0;
|
||||
const double md_u_perc = md_bytes / double(md_alloced) * 100.0;
|
||||
const double mc_u_perc = mc_bytes / double(mc_alloced) * 100.0;
|
||||
const double od_u_perc = od_bytes / double(od_alloced) * 100.0;
|
||||
const double total_u_perc = total_bytes / double(total_alloced) * 100.0;
|
||||
|
||||
#define fmt_space "%s space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used] at " INTPTR_FORMAT
|
||||
@ -691,6 +709,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
tty->print_cr(fmt_space, "md", md_bytes, md_t_perc, md_alloced, md_u_perc, p2i(md_low));
|
||||
tty->print_cr(fmt_space, "mc", mc_bytes, mc_t_perc, mc_alloced, mc_u_perc, p2i(mc_low));
|
||||
tty->print_cr(fmt_space, "st", ss_bytes, ss_t_perc, ss_bytes, 100.0, p2i(ss_low));
|
||||
tty->print_cr(fmt_space, "od", od_bytes, od_t_perc, od_alloced, od_u_perc, p2i(od_low));
|
||||
tty->print_cr("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
|
||||
total_bytes, total_alloced, total_u_perc);
|
||||
|
||||
@ -734,6 +753,10 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
SharedMiscCodeSize,
|
||||
true, true);
|
||||
mapinfo->write_string_regions(_string_regions);
|
||||
mapinfo->write_region(MetaspaceShared::od, _od_vs.low(),
|
||||
pointer_delta(od_top, _od_vs.low(), sizeof(char)),
|
||||
pointer_delta(od_end, _od_vs.low(), sizeof(char)),
|
||||
true, false);
|
||||
}
|
||||
|
||||
mapinfo->close();
|
||||
@ -1049,8 +1072,6 @@ void MetaspaceShared::print_shared_spaces() {
|
||||
|
||||
|
||||
// Map shared spaces at requested addresses and return if succeeded.
|
||||
// Need to keep the bounds of the ro and rw space for the Metaspace::contains
|
||||
// call, or is_in_shared_space.
|
||||
bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
size_t image_alignment = mapinfo->alignment();
|
||||
|
||||
@ -1068,6 +1089,7 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
char* _rw_base = NULL;
|
||||
char* _md_base = NULL;
|
||||
char* _mc_base = NULL;
|
||||
char* _od_base = NULL;
|
||||
|
||||
// Map each shared region
|
||||
if ((_ro_base = mapinfo->map_region(ro)) != NULL &&
|
||||
@ -1078,6 +1100,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
mapinfo->verify_region_checksum(md) &&
|
||||
(_mc_base = mapinfo->map_region(mc)) != NULL &&
|
||||
mapinfo->verify_region_checksum(mc) &&
|
||||
(_od_base = mapinfo->map_region(od)) != NULL &&
|
||||
mapinfo->verify_region_checksum(od) &&
|
||||
(image_alignment == (size_t)max_alignment()) &&
|
||||
mapinfo->validate_classpath_entry_table()) {
|
||||
// Success (no need to do anything)
|
||||
@ -1089,6 +1113,7 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
if (_rw_base != NULL) mapinfo->unmap_region(rw);
|
||||
if (_md_base != NULL) mapinfo->unmap_region(md);
|
||||
if (_mc_base != NULL) mapinfo->unmap_region(mc);
|
||||
if (_od_base != NULL) mapinfo->unmap_region(od);
|
||||
#ifndef _WINDOWS
|
||||
// Release the entire mapped region
|
||||
shared_rs.release();
|
||||
|
@ -132,6 +132,7 @@ class MetaspaceShared : AllStatic {
|
||||
// Used only during dumping.
|
||||
static SharedMiscRegion _md;
|
||||
static SharedMiscRegion _mc;
|
||||
static SharedMiscRegion _od;
|
||||
public:
|
||||
enum {
|
||||
vtbl_list_size = DEFAULT_VTBL_LIST_SIZE,
|
||||
@ -148,7 +149,10 @@ class MetaspaceShared : AllStatic {
|
||||
max_strings = 2, // max number of string regions in string space
|
||||
num_non_strings = 4, // number of non-string regions
|
||||
first_string = num_non_strings, // index of first string region
|
||||
n_regions = max_strings + num_non_strings // total number of regions
|
||||
// The optional data region is the last region.
|
||||
// Currently it only contains class file data.
|
||||
od = max_strings + num_non_strings,
|
||||
n_regions = od + 1 // total number of regions
|
||||
};
|
||||
|
||||
// Accessor functions to save shared space created for metadata, which has
|
||||
@ -222,9 +226,10 @@ class MetaspaceShared : AllStatic {
|
||||
static int count_class(const char* classlist_file);
|
||||
static void estimate_regions_size() NOT_CDS_RETURN;
|
||||
|
||||
// Allocate a block of memory from the "mc" or "md" regions.
|
||||
// Allocate a block of memory from the "mc", "md", or "od" regions.
|
||||
static char* misc_code_space_alloc(size_t num_bytes) { return _mc.alloc(num_bytes); }
|
||||
static char* misc_data_space_alloc(size_t num_bytes) { return _md.alloc(num_bytes); }
|
||||
static char* optional_data_space_alloc(size_t num_bytes) { return _od.alloc(num_bytes); }
|
||||
|
||||
static address cds_i2i_entry_code_buffers(size_t total_size);
|
||||
|
||||
@ -243,5 +248,9 @@ class MetaspaceShared : AllStatic {
|
||||
assert(DumpSharedSpaces, "used during dumping only");
|
||||
return &_md;
|
||||
}
|
||||
static SharedMiscRegion* optional_data_region() {
|
||||
assert(DumpSharedSpaces, "used during dumping only");
|
||||
return &_od;
|
||||
}
|
||||
};
|
||||
#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "memory/heapInspection.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
@ -1972,11 +1973,6 @@ void InstanceKlass::remove_unshareable_info() {
|
||||
m->remove_unshareable_info();
|
||||
}
|
||||
|
||||
// cached_class_file might be pointing to a malloc'ed buffer allocated by
|
||||
// event-based tracing code at CDS dump time. It's not usable at runtime
|
||||
// so let's clear it.
|
||||
set_cached_class_file(NULL);
|
||||
|
||||
// do array classes also.
|
||||
array_klasses_do(remove_unshareable_in_class);
|
||||
}
|
||||
@ -2070,6 +2066,7 @@ void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
|
||||
}
|
||||
|
||||
void InstanceKlass::release_C_heap_structures() {
|
||||
assert(!this->is_shared(), "should not be called for a shared class");
|
||||
|
||||
// Can't release the constant pool here because the constant pool can be
|
||||
// deallocated separately from the InstanceKlass for default methods and
|
||||
@ -3653,6 +3650,15 @@ Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
JvmtiCachedClassFileData* InstanceKlass::get_cached_class_file() {
|
||||
if (MetaspaceShared::is_in_shared_space(_cached_class_file)) {
|
||||
// Ignore the archived class stream data
|
||||
return NULL;
|
||||
} else {
|
||||
return _cached_class_file;
|
||||
}
|
||||
}
|
||||
|
||||
jint InstanceKlass::get_cached_class_file_len() {
|
||||
return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
|
||||
}
|
||||
@ -3660,4 +3666,15 @@ jint InstanceKlass::get_cached_class_file_len() {
|
||||
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
|
||||
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
JvmtiCachedClassFileData* InstanceKlass::get_archived_class_data() {
|
||||
assert(this->is_shared(), "class should be shared");
|
||||
if (MetaspaceShared::is_in_shared_space(_cached_class_file)) {
|
||||
return _cached_class_file;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -783,7 +783,7 @@ public:
|
||||
void set_cached_class_file(JvmtiCachedClassFileData *data) {
|
||||
_cached_class_file = data;
|
||||
}
|
||||
JvmtiCachedClassFileData * get_cached_class_file() { return _cached_class_file; }
|
||||
JvmtiCachedClassFileData * get_cached_class_file();
|
||||
jint get_cached_class_file_len();
|
||||
unsigned char * get_cached_class_file_bytes();
|
||||
|
||||
@ -795,6 +795,13 @@ public:
|
||||
return _jvmti_cached_class_field_map;
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void set_archived_class_data(JvmtiCachedClassFileData* data) {
|
||||
_cached_class_file = data;
|
||||
}
|
||||
|
||||
JvmtiCachedClassFileData * get_archived_class_data();
|
||||
#endif // INCLUDE_CDS
|
||||
#else // INCLUDE_JVMTI
|
||||
|
||||
static void purge_previous_versions(InstanceKlass* ik) { return; };
|
||||
|
@ -282,6 +282,12 @@ void report_untested(const char* file, int line, const char* message) {
|
||||
}
|
||||
|
||||
void report_out_of_shared_space(SharedSpaceType shared_space) {
|
||||
if (shared_space == SharedOptional) {
|
||||
// The estimated shared_optional_space size is large enough
|
||||
// for all class bytes. It should not run out of space.
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
static const char* name[] = {
|
||||
"shared read only space",
|
||||
"shared read write space",
|
||||
|
@ -271,7 +271,8 @@ enum SharedSpaceType {
|
||||
SharedReadOnly,
|
||||
SharedReadWrite,
|
||||
SharedMiscData,
|
||||
SharedMiscCode
|
||||
SharedMiscCode,
|
||||
SharedOptional
|
||||
};
|
||||
|
||||
void report_out_of_shared_space(SharedSpaceType space_type);
|
||||
|
115
hotspot/test/runtime/SharedArchiveFile/CDSTestUtils.java
Normal file
115
hotspot/test/runtime/SharedArchiveFile/CDSTestUtils.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
|
||||
// This class contains common test utilities for CDS testing
|
||||
public class CDSTestUtils {
|
||||
|
||||
// check result of 'dump' operation
|
||||
public static void checkDump(OutputAnalyzer output, String... extraMatches)
|
||||
throws Exception {
|
||||
|
||||
output.shouldContain("Loading classes to share");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
for (String match : extraMatches) {
|
||||
output.shouldContain(match);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check the output for indication that mapping of the archive failed
|
||||
public static boolean isUnableToMap(OutputAnalyzer output) {
|
||||
String outStr = output.getOutput();
|
||||
if ((output.getExitValue() == 1) && (
|
||||
outStr.contains("Unable to reserve shared space at required address") ||
|
||||
outStr.contains("Unable to map ReadOnly shared space at required address") ||
|
||||
outStr.contains("Unable to map ReadWrite shared space at required address") ||
|
||||
outStr.contains("Unable to map MiscData shared space at required address") ||
|
||||
outStr.contains("Unable to map MiscCode shared space at required address") ||
|
||||
outStr.contains("Unable to map shared string space at required address") ||
|
||||
outStr.contains("Could not allocate metaspace at a compatible address") ||
|
||||
outStr.contains("Unable to allocate shared string space: range is not within java heap") ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check result of 'exec' operation, that is when JVM is run using the archive
|
||||
public static void checkExec(OutputAnalyzer output, String... extraMatches) throws Exception {
|
||||
if (isUnableToMap(output)) {
|
||||
System.out.println("Unable to map shared archive: test did not complete; assumed PASS");
|
||||
return;
|
||||
}
|
||||
output.shouldContain("sharing");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
for (String match : extraMatches) {
|
||||
output.shouldContain(match);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get the file object for the test artifact
|
||||
private static File getTestArtifactFile(String prefix, String name) {
|
||||
File dir = new File(System.getProperty("test.classes", "."));
|
||||
return new File(dir, prefix + name);
|
||||
}
|
||||
|
||||
|
||||
// create file containing the specified class list
|
||||
public static File makeClassList(String testCaseName, String classes[])
|
||||
throws Exception {
|
||||
|
||||
File classList = getTestArtifactFile(testCaseName, "test.classlist");
|
||||
FileOutputStream fos = new FileOutputStream(classList);
|
||||
PrintStream ps = new PrintStream(fos);
|
||||
|
||||
addToClassList(ps, classes);
|
||||
|
||||
ps.close();
|
||||
fos.close();
|
||||
|
||||
return classList;
|
||||
}
|
||||
|
||||
|
||||
private static void addToClassList(PrintStream ps, String classes[])
|
||||
throws IOException
|
||||
{
|
||||
if (classes != null) {
|
||||
for (String s : classes) {
|
||||
ps.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/Implementor.java
Normal file
37
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/Implementor.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public class Implementor implements Interface {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Implementor: entering main()");
|
||||
test();
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
// from interface
|
||||
(new Implementor()).printString();
|
||||
// from implementor
|
||||
System.out.println(TransformUtil.ChildCheckPattern +
|
||||
TransformUtil.BeforePattern);
|
||||
}
|
||||
}
|
31
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/Interface.java
Normal file
31
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/Interface.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public interface Interface {
|
||||
public static final String stringToBeTransformed =
|
||||
TransformUtil.ParentCheckPattern + TransformUtil.BeforePattern;
|
||||
|
||||
default void printString() {
|
||||
System.out.println(stringToBeTransformed);
|
||||
}
|
||||
}
|
40
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/SubClass.java
Normal file
40
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/SubClass.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public class SubClass extends SuperClazz {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("SubClass: entering main()");
|
||||
test();
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
// The line below will be used to check for successful class transformation
|
||||
System.out.println(TransformUtil.ChildCheckPattern +
|
||||
TransformUtil.BeforePattern);
|
||||
(new SubClass()).callParent();
|
||||
}
|
||||
|
||||
private void callParent() {
|
||||
super.testParent();
|
||||
}
|
||||
}
|
32
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/SuperClazz.java
Normal file
32
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/SuperClazz.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
public class SuperClazz {
|
||||
public static void testParent() {
|
||||
System.out.println("SuperClazz: entering testParent()");
|
||||
|
||||
// The line below will be used to check for successful class transformation
|
||||
System.out.println(TransformUtil.ParentCheckPattern + TransformUtil.BeforePattern);
|
||||
}
|
||||
}
|
45
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TestEntry.java
Normal file
45
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TestEntry.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
// Test Entry - a single entry in a test table
|
||||
// that defines a test case
|
||||
// See TransformRelatedClasses.java for more details
|
||||
public class TestEntry {
|
||||
int testCaseId;
|
||||
boolean transformParent;
|
||||
boolean transformChild;
|
||||
boolean isParentExpectedShared;
|
||||
boolean isChildExpectedShared;
|
||||
|
||||
public TestEntry(int testCaseId,
|
||||
boolean transformParent, boolean transformChild,
|
||||
boolean isParentExpectedShared, boolean isChildExpectedShared) {
|
||||
this.testCaseId = testCaseId;
|
||||
this.transformParent = transformParent;
|
||||
this.transformChild = transformChild;
|
||||
this.isParentExpectedShared = isParentExpectedShared;
|
||||
this.isChildExpectedShared = isChildExpectedShared;
|
||||
}
|
||||
}
|
||||
|
50
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java
Normal file
50
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with Interface/Implementor pair
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @requires vm.flavor != "minimal"
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* java.management
|
||||
* java.instrument
|
||||
* @build TransformUtil TransformerAgent Interface Implementor
|
||||
* @run main/othervm TransformRelatedClasses Interface Implementor
|
||||
*/
|
||||
|
||||
// Clarification on @requires declarations:
|
||||
// CDS is not supported w/o the use of Compressed OOPs
|
||||
// JVMTI's ClassFileLoadHook is not supported under minimal VM
|
||||
|
||||
// This test class uses TransformRelatedClasses to do its work.
|
||||
// The goal of this test is to exercise transformation of related interface
|
||||
// and its implementor in combination with CDS.
|
||||
// The transformation is done via ClassFileLoadHook mechanism.
|
||||
// Both superclass and subclass reside in the shared archive.
|
||||
// The test consists of 4 test cases where transformation is applied
|
||||
// to an interface and an implementor in a combinatorial manner.
|
||||
// Please see TransformRelatedClasses.java for details.
|
179
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformRelatedClasses.java
Normal file
179
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformRelatedClasses.java
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
// This is the main test class for testing transformation of related classes
|
||||
// in combination with CDS, to ensure these features work well together.
|
||||
// The relationships that can be tested using this test class are:
|
||||
// superclass/subclass, and interface/implementor relationships.
|
||||
//
|
||||
// The test uses combinatorial approach.
|
||||
// For details on test table and test cases see main() method in this class.
|
||||
//
|
||||
// This test consists of multiple classes for better flexibility and reuse,
|
||||
// and also relies on certain common utility code.
|
||||
// Here are the details on the structure of the test
|
||||
//
|
||||
// Structure of the test:
|
||||
// TransformRelatedClasses -- common main test driver
|
||||
// The TransformRelatedClasses is invoked from test driver classes:
|
||||
// TransformInterfaceAndImplementor, TransformSuperAndSubClasses
|
||||
// It is responsible for preparing test artifacts (test jar, agent jar
|
||||
// and the shared archive), running test cases and checking the results.
|
||||
// The following test classes below are launched in a sub-process with use
|
||||
// of shared archive:
|
||||
// SuperClazz, SubClass -- super/sub class pair under test
|
||||
// Interface, Implementor -- classes under test
|
||||
// This test will transform these classes, based on the test case data,
|
||||
// by changing a predefined unique string in each class.
|
||||
// For more details, see the test classes' code and comments.
|
||||
//
|
||||
// Other related classes:
|
||||
// TestEntry - a class representing a single test case, as test entry in the table
|
||||
// TransformTestCommon - common methods for transformation test cases
|
||||
//
|
||||
// Other utility/helper classes and files used in this test:
|
||||
// TransformerAgent - an agent that is used when JVM-under-test is executed
|
||||
// to transform specific strings inside specified classes
|
||||
// TransformerAgent.mf - accompanies transformer agent
|
||||
// CDSTestUtils - Test Utilities common to all CDS tests
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
|
||||
public class TransformRelatedClasses {
|
||||
static final String archiveName = "./TransformRelatedClasses.jsa";
|
||||
static String agentClasses[] = {
|
||||
"TransformerAgent",
|
||||
"TransformerAgent$SimpleTransformer",
|
||||
"TransformUtil"
|
||||
};
|
||||
|
||||
String parent;
|
||||
String child;
|
||||
String[] testClasses = new String[2];
|
||||
String[] testNames = new String[2];
|
||||
String testJar;
|
||||
String agentJar;
|
||||
|
||||
|
||||
private static void log(String msg) {
|
||||
System.out.println("TransformRelatedClasses: " + msg);
|
||||
}
|
||||
|
||||
|
||||
// This class is intended to test 2 parent-child relationships:
|
||||
// 1. Base Class (parent) and Derived Class (child)
|
||||
// 2. Interface (parent) and Implementor (child)
|
||||
// Parameters to main(): parent, child
|
||||
public static void main(String args[]) throws Exception {
|
||||
TransformRelatedClasses test = new TransformRelatedClasses(args[0], args[1]);
|
||||
test.prepare();
|
||||
|
||||
// Test Table
|
||||
// TestEntry: (testCaseId, transformParent, tranformChild,
|
||||
// isParentExpectedShared, isChildExpectedShared)
|
||||
ArrayList<TestEntry> testTable = new ArrayList<>();
|
||||
|
||||
// base case - no tranformation - all expected to be shared
|
||||
testTable.add(new TestEntry(0, false, false, true, true));
|
||||
|
||||
// transform parent only - both parent and child should not be shared
|
||||
testTable.add(new TestEntry(1, true, false, false, false));
|
||||
|
||||
// transform parent and child - both parent and child should not be shared
|
||||
testTable.add(new TestEntry(2, true, true, false, false));
|
||||
|
||||
// transform child only - parent should still be shared, but not child
|
||||
testTable.add(new TestEntry(3, false, true, true, false));
|
||||
|
||||
// run the tests
|
||||
for (TestEntry entry : testTable) {
|
||||
test.runTest(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public TransformRelatedClasses(String parent, String child) {
|
||||
log("Constructor: parent = " + parent + ", child = " + child);
|
||||
this.parent = parent;
|
||||
this.child = child;
|
||||
testClasses[0] = parent;
|
||||
testClasses[1] = child;
|
||||
testNames[0] = parent.replace('.', '/');
|
||||
testNames[1] = child.replace('.', '/');
|
||||
}
|
||||
|
||||
|
||||
// same test jar and archive can be used for all test cases
|
||||
private void prepare() throws Exception {
|
||||
// create agent jar
|
||||
// Agent is the same for all test cases
|
||||
String pathToManifest = "../../../../testlibrary/jvmti/TransformerAgent.mf";
|
||||
agentJar = ClassFileInstaller.writeJar("TransformerAgent.jar",
|
||||
ClassFileInstaller.Manifest.fromSourceFile(pathToManifest),
|
||||
agentClasses);
|
||||
|
||||
// create a test jar
|
||||
testJar =
|
||||
ClassFileInstaller.writeJar(parent + "-" + child + ".jar",
|
||||
testClasses);
|
||||
|
||||
// create an archive
|
||||
File classList = CDSTestUtils.makeClassList("transform-" + parent,
|
||||
testNames);
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
|
||||
"-Xbootclasspath/a:" + testJar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:ExtraSharedClassListFile=" +
|
||||
classList.getPath(),
|
||||
"-XX:SharedArchiveFile=" + archiveName,
|
||||
"-XX:+PrintSharedSpaces",
|
||||
"-Xshare:dump");
|
||||
OutputAnalyzer out = new OutputAnalyzer(pb.start());
|
||||
CDSTestUtils.checkDump(out);
|
||||
}
|
||||
|
||||
|
||||
private void runTest(TestEntry entry) throws Exception {
|
||||
log("runTest(): testCaseId = " + entry.testCaseId);
|
||||
|
||||
// execute with archive
|
||||
String agentParam = "-javaagent:" + agentJar + "=" +
|
||||
TransformTestCommon.getAgentParams(entry, parent, child);
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true,
|
||||
"-Xbootclasspath/a:" + testJar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=" + archiveName,
|
||||
"-Xlog:class+load=info",
|
||||
"-Xshare:on", "-showversion",
|
||||
agentParam, child);
|
||||
OutputAnalyzer out = new OutputAnalyzer(pb.start());
|
||||
|
||||
TransformTestCommon.checkResults(entry, out, parent, child);
|
||||
}
|
||||
}
|
51
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java
Normal file
51
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperAndSubClasses.java
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with SubClass and SuperClass
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @requires vm.flavor != "minimal"
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* java.management
|
||||
* java.instrument
|
||||
* @build TransformUtil TransformerAgent SubClass SuperClazz
|
||||
* @run main/othervm TransformRelatedClasses SuperClazz SubClass
|
||||
*/
|
||||
|
||||
// Clarification on @requires declarations:
|
||||
// CDS is not supported w/o the use of Compressed OOPs
|
||||
// JVMTI's ClassFileLoadHook is not supported under minimal VM
|
||||
|
||||
// This test class uses TransformRelatedClasses to do its work.
|
||||
// The goal of this test is to exercise transformation of related superclass
|
||||
// and subclass in combination with CDS.
|
||||
// The transformation is done via ClassFileLoadHook mechanism.
|
||||
// Both superclass and subclass reside in the shared archive.
|
||||
// The test consists of 4 test cases where transformation is applied
|
||||
// to a parent and child in combinatorial manner.
|
||||
// Please see TransformRelatedClasses.java for details.
|
52
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java
Normal file
52
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformSuperSubTwoPckgs.java
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Exercise initial transformation (ClassFileLoadHook)
|
||||
* with CDS with SubClass and SuperClass, each lives in own separate package
|
||||
* @library /test/lib /runtime/SharedArchiveFile /testlibrary/jvmti
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @requires vm.flavor != "minimal"
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* java.management
|
||||
* java.instrument
|
||||
* @build TransformUtil TransformerAgent SubClass SuperClazz
|
||||
* @compile myPkg2/SubClass.java myPkg1/SuperClazz.java
|
||||
* @run main/othervm TransformRelatedClasses myPkg1.SuperClazz myPkg2.SubClass
|
||||
*/
|
||||
|
||||
// Clarification on @requires declarations:
|
||||
// CDS is not supported w/o the use of Compressed OOPs
|
||||
// JVMTI's ClassFileLoadHook is not supported under minimal VM
|
||||
|
||||
// This test class uses TransformRelatedClasses to do its work.
|
||||
// The goal of this test is to exercise transformation of related superclass
|
||||
// and subclass in combination with CDS; each class lives in its own package.
|
||||
// The transformation is done via ClassFileLoadHook mechanism.
|
||||
// Both superclass and subclass reside in the shared archive.
|
||||
// The test consists of 4 test cases where transformation is applied
|
||||
// to a parent and child in combinatorial manner.
|
||||
// Please see TransformRelatedClasses.java for details.
|
114
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformTestCommon.java
Normal file
114
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/TransformTestCommon.java
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
|
||||
// This class contains methods common to all transformation test cases
|
||||
public class TransformTestCommon {
|
||||
|
||||
// get parameters to an agent depending on the test case
|
||||
// these parameters will instruct the agent which classes should be
|
||||
// transformed
|
||||
public static String getAgentParams(TestEntry entry,
|
||||
String parent, String child) {
|
||||
|
||||
if (entry.transformParent && entry.transformChild)
|
||||
return parent + "," + child;
|
||||
if (entry.transformParent)
|
||||
return parent;
|
||||
if (entry.transformChild)
|
||||
return child;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
private static void checkTransformationResults(TestEntry entry,
|
||||
OutputAnalyzer out)
|
||||
throws Exception {
|
||||
|
||||
if (entry.transformParent)
|
||||
out.shouldContain(TransformUtil.ParentCheckPattern +
|
||||
TransformUtil.AfterPattern);
|
||||
|
||||
if (entry.transformChild)
|
||||
out.shouldContain(TransformUtil.ChildCheckPattern +
|
||||
TransformUtil.AfterPattern);
|
||||
}
|
||||
|
||||
|
||||
private static void checkSharingByClass(TestEntry entry, OutputAnalyzer out,
|
||||
String parent, String child)
|
||||
throws Exception {
|
||||
|
||||
String parentSharedMatch = parent + " source: shared objects file";
|
||||
String childSharedMatch = child + " source: shared objects file";
|
||||
|
||||
if (entry.isParentExpectedShared)
|
||||
out.shouldContain(parentSharedMatch);
|
||||
else
|
||||
out.shouldNotContain(parentSharedMatch);
|
||||
|
||||
if (entry.isChildExpectedShared)
|
||||
out.shouldContain(childSharedMatch);
|
||||
else
|
||||
out.shouldNotContain(childSharedMatch);
|
||||
}
|
||||
|
||||
|
||||
// Both parent and child classes should be passed to ClassFileTransformer.transform()
|
||||
// exactly once.
|
||||
private static void checkTransformationCounts(TestEntry entry, OutputAnalyzer out,
|
||||
String parent, String child)
|
||||
throws Exception {
|
||||
|
||||
String patternBase = "TransformerAgent: SimpleTransformer called for: ";
|
||||
|
||||
out.shouldContain(patternBase + child + "@1");
|
||||
out.shouldContain(patternBase + parent + "@1");
|
||||
|
||||
out.shouldNotContain(patternBase + child + "@2");
|
||||
out.shouldNotContain(patternBase + parent + "@2");
|
||||
}
|
||||
|
||||
|
||||
public static void checkResults(TestEntry entry, OutputAnalyzer out,
|
||||
String parent, String child)
|
||||
throws Exception {
|
||||
|
||||
// If we were not able to map an archive,
|
||||
// then do not perform other checks, since
|
||||
// there was no sharing at all
|
||||
if (CDSTestUtils.isUnableToMap(out))
|
||||
return;
|
||||
|
||||
String childVmName = child.replace('.', '/');
|
||||
String parentVmName = parent.replace('.', '/');
|
||||
|
||||
CDSTestUtils.checkExec(out);
|
||||
checkTransformationCounts(entry, out, parentVmName, childVmName);
|
||||
checkTransformationResults(entry, out);
|
||||
checkSharingByClass(entry, out, parent, child);
|
||||
}
|
||||
}
|
33
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/myPkg1/SuperClazz.java
Normal file
33
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/myPkg1/SuperClazz.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package myPkg1;
|
||||
|
||||
public class SuperClazz {
|
||||
public static void testParent() {
|
||||
System.out.println("SuperClazz: entering testParent()");
|
||||
|
||||
// The line below will be used to check for successful class transformation
|
||||
System.out.println("parent-transform-check: this-should-be-transformed");
|
||||
}
|
||||
}
|
56
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/myPkg2/SubClass.java
Normal file
56
hotspot/test/runtime/SharedArchiveFile/serviceability/transformRelatedClasses/myPkg2/SubClass.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package myPkg2;
|
||||
|
||||
import myPkg1.SuperClazz;
|
||||
|
||||
public class SubClass extends SuperClazz {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("SubClass: entering main()");
|
||||
test();
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
// The line below will be used to check for successful class transformation
|
||||
System.out.println("child-transform-check: this-should-be-transformed");
|
||||
(new SubClass()).callParent();
|
||||
|
||||
// Get the system packages, which should contain myPkg1 and myPkag2
|
||||
Package[] pkgs = Package.getPackages();
|
||||
for (int i = 0; i < pkgs.length; i++) {
|
||||
if (pkgs[i].getName().equals("myPkg1")) {
|
||||
for (int j = 0; j < pkgs.length; j++) {
|
||||
if (pkgs[j].getName().equals("myPkg2")) {
|
||||
return; // found myPkg1 & myPkg1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Missing system package");
|
||||
}
|
||||
|
||||
private void callParent() {
|
||||
super.testParent();
|
||||
}
|
||||
}
|
75
hotspot/test/testlibrary/jvmti/TransformUtil.java
Normal file
75
hotspot/test/testlibrary/jvmti/TransformUtil.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
public class TransformUtil {
|
||||
public static final String BeforePattern = "this-should-be-transformed";
|
||||
public static final String AfterPattern = "this-has-been--transformed";
|
||||
public static final String ParentCheckPattern = "parent-transform-check: ";
|
||||
public static final String ChildCheckPattern = "child-transform-check: ";
|
||||
|
||||
/**
|
||||
* @return the number of occurrences of the <code>from</code> string that
|
||||
* have been replaced.
|
||||
*/
|
||||
public static int replace(byte buff[], String from, String to) {
|
||||
if (to.length() != from.length()) {
|
||||
throw new RuntimeException("bad strings");
|
||||
}
|
||||
byte f[] = asciibytes(from);
|
||||
byte t[] = asciibytes(to);
|
||||
byte f0 = f[0];
|
||||
|
||||
int numReplaced = 0;
|
||||
int max = buff.length - f.length;
|
||||
for (int i = 0; i < max; ) {
|
||||
if (buff[i] == f0 && replace(buff, f, t, i)) {
|
||||
i += f.length;
|
||||
numReplaced++;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return numReplaced;
|
||||
}
|
||||
|
||||
public static boolean replace(byte buff[], byte f[], byte t[], int i) {
|
||||
for (int x = 0; x < f.length; x++) {
|
||||
if (buff[x+i] != f[x]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < f.length; x++) {
|
||||
buff[x+i] = t[x];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static byte[] asciibytes(String s) {
|
||||
byte b[] = new byte[s.length()];
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
b[i] = (byte)s.charAt(i);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
100
hotspot/test/testlibrary/jvmti/TransformerAgent.java
Normal file
100
hotspot/test/testlibrary/jvmti/TransformerAgent.java
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.HashMap;
|
||||
|
||||
// This is a test utility class used to transform
|
||||
// specified classes via initial transformation (ClassFileLoadHook).
|
||||
// Names of classes to be transformed are supplied as arguments,
|
||||
// the phrase to be transformed is a hard-coded predefined
|
||||
// fairly unique phrase.
|
||||
|
||||
public class TransformerAgent {
|
||||
private static String[] classesToTransform;
|
||||
|
||||
|
||||
private static void log(String msg) {
|
||||
System.out.println("TransformerAgent: " + msg);
|
||||
}
|
||||
|
||||
|
||||
// arguments are comma-separated list of classes to transform
|
||||
public static void premain(String agentArguments, Instrumentation instrumentation) {
|
||||
log("premain() is called, arguments = " + agentArguments);
|
||||
classesToTransform = agentArguments.split(",");
|
||||
instrumentation.addTransformer(new SimpleTransformer(), /*canRetransform=*/true);
|
||||
}
|
||||
|
||||
|
||||
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
||||
log("agentmain() is called");
|
||||
premain(args, inst);
|
||||
}
|
||||
|
||||
|
||||
static class SimpleTransformer implements ClassFileTransformer {
|
||||
public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
|
||||
ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException {
|
||||
|
||||
log("SimpleTransformer called for: " + name + "@" + incrCounter(name));
|
||||
if (!shouldTransform(name))
|
||||
return null;
|
||||
|
||||
log("transforming: class name = " + name);
|
||||
int nrOfReplacements = TransformUtil.replace(buffer, TransformUtil.BeforePattern,
|
||||
TransformUtil.AfterPattern);
|
||||
log("replaced the string, nrOfReplacements = " + nrOfReplacements);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Check class name pattern, since test should only transform certain classes
|
||||
private static boolean shouldTransform(String name) {
|
||||
for (String match : classesToTransform) {
|
||||
if (name.matches(match)) {
|
||||
log("shouldTransform: match-found, match = " + match);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static HashMap<String, Integer> counterMap = new HashMap<>();
|
||||
|
||||
static Integer incrCounter(String className) {
|
||||
Integer i = counterMap.get(className);
|
||||
if (i == null) {
|
||||
i = new Integer(1);
|
||||
} else {
|
||||
i = new Integer(i.intValue() + 1);
|
||||
}
|
||||
counterMap.put(className, i);
|
||||
return i;
|
||||
}
|
||||
}
|
5
hotspot/test/testlibrary/jvmti/TransformerAgent.mf
Normal file
5
hotspot/test/testlibrary/jvmti/TransformerAgent.mf
Normal file
@ -0,0 +1,5 @@
|
||||
Manifest-Version: 1.0
|
||||
Premain-Class: TransformerAgent
|
||||
Agent-Class: TransformerAgent
|
||||
Can-Retransform-Classes: true
|
||||
Can-Redefine-Classes: false
|
Loading…
x
Reference in New Issue
Block a user