2015-12-08 20:04:03 +01:00
|
|
|
/*
|
2018-03-21 19:45:24 -04:00
|
|
|
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
2015-12-08 20:04:03 +01:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precompiled.hpp"
|
|
|
|
#include "classfile/classFileParser.hpp"
|
|
|
|
#include "classfile/classFileStream.hpp"
|
2016-09-18 21:10:48 -04:00
|
|
|
#include "classfile/classLoader.hpp"
|
2015-12-08 20:04:03 +01:00
|
|
|
#include "classfile/classLoaderData.hpp"
|
2016-09-18 21:10:48 -04:00
|
|
|
#include "classfile/classLoaderData.inline.hpp"
|
2015-12-08 20:04:03 +01:00
|
|
|
#include "classfile/klassFactory.hpp"
|
2018-04-26 13:40:58 -07:00
|
|
|
#include "memory/filemap.hpp"
|
2016-09-18 21:10:48 -04:00
|
|
|
#include "memory/metaspaceShared.hpp"
|
2015-12-08 20:04:03 +01:00
|
|
|
#include "memory/resourceArea.hpp"
|
|
|
|
#include "prims/jvmtiEnvBase.hpp"
|
2016-09-18 21:10:48 -04:00
|
|
|
#include "prims/jvmtiRedefineClasses.hpp"
|
2018-03-21 19:45:24 -04:00
|
|
|
#include "runtime/handles.inline.hpp"
|
2016-03-01 23:48:46 +01:00
|
|
|
#include "trace/traceMacros.hpp"
|
2015-12-08 20:04:03 +01:00
|
|
|
|
2016-09-18 21:10:48 -04:00
|
|
|
// called during initial loading of a shared class
|
2017-03-15 10:25:37 -04:00
|
|
|
InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
|
|
|
|
InstanceKlass* ik,
|
2016-09-18 21:10:48 -04:00
|
|
|
Symbol* class_name,
|
|
|
|
Handle class_loader,
|
|
|
|
Handle protection_domain, TRAPS) {
|
|
|
|
#if INCLUDE_CDS && INCLUDE_JVMTI
|
2017-03-15 10:25:37 -04:00
|
|
|
assert(ik != NULL, "sanity");
|
|
|
|
assert(ik->is_shared(), "expecting a shared class");
|
2016-09-18 21:10:48 -04:00
|
|
|
|
|
|
|
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();
|
2017-08-28 15:34:04 -07:00
|
|
|
const char* pathname;
|
|
|
|
if (path_index < 0) {
|
|
|
|
// shared classes loaded by user defined class loader
|
|
|
|
// do not have shared_classpath_index
|
|
|
|
ModuleEntry* mod_entry = ik->module();
|
|
|
|
if (mod_entry != NULL && (mod_entry->location() != NULL)) {
|
|
|
|
ResourceMark rm;
|
|
|
|
pathname = (const char*)(mod_entry->location()->as_C_string());
|
|
|
|
} else {
|
|
|
|
pathname = "";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SharedClassPathEntry* ent =
|
2018-04-10 11:43:40 -07:00
|
|
|
(SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
|
2017-08-28 15:34:04 -07:00
|
|
|
pathname = ent == NULL ? NULL : ent->name();
|
|
|
|
}
|
2016-09-18 21:10:48 -04:00
|
|
|
ClassFileStream* stream = new ClassFileStream(ptr,
|
|
|
|
end_ptr - ptr,
|
2017-08-28 15:34:04 -07:00
|
|
|
pathname,
|
2016-09-18 21:10:48 -04:00
|
|
|
ClassFileStream::verify);
|
|
|
|
ClassFileParser parser(stream,
|
|
|
|
class_name,
|
|
|
|
loader_data,
|
|
|
|
protection_domain,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
ClassFileParser::BROADCAST, // publicity level
|
|
|
|
CHECK_NULL);
|
2017-03-15 10:25:37 -04:00
|
|
|
InstanceKlass* new_ik = parser.create_instance_klass(true /* changed_by_loadhook */,
|
|
|
|
CHECK_NULL);
|
2016-09-18 21:10:48 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-22 11:06:18 -04:00
|
|
|
static ClassFileStream* check_class_file_load_hook(ClassFileStream* stream,
|
|
|
|
Symbol* name,
|
|
|
|
ClassLoaderData* loader_data,
|
|
|
|
Handle protection_domain,
|
|
|
|
JvmtiCachedClassFileData** cached_class_file,
|
|
|
|
TRAPS) {
|
2015-12-08 20:04:03 +01:00
|
|
|
|
|
|
|
assert(stream != NULL, "invariant");
|
|
|
|
|
|
|
|
if (JvmtiExport::should_post_class_file_load_hook()) {
|
|
|
|
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
|
|
|
const JavaThread* jt = (JavaThread*)THREAD;
|
|
|
|
|
|
|
|
Handle class_loader(THREAD, loader_data->class_loader());
|
|
|
|
|
|
|
|
// Get the cached class file bytes (if any) from the class that
|
|
|
|
// is being redefined or retransformed. We use jvmti_thread_state()
|
|
|
|
// instead of JvmtiThreadState::state_for(jt) so we don't allocate
|
|
|
|
// a JvmtiThreadState any earlier than necessary. This will help
|
|
|
|
// avoid the bug described by 7126851.
|
|
|
|
|
|
|
|
JvmtiThreadState* state = jt->jvmti_thread_state();
|
|
|
|
|
|
|
|
if (state != NULL) {
|
2017-03-15 10:25:37 -04:00
|
|
|
Klass* k = state->get_class_being_redefined();
|
2015-12-08 20:04:03 +01:00
|
|
|
|
2017-03-15 10:25:37 -04:00
|
|
|
if (k != NULL) {
|
|
|
|
InstanceKlass* class_being_redefined = InstanceKlass::cast(k);
|
|
|
|
*cached_class_file = class_being_redefined->get_cached_class_file();
|
2015-12-08 20:04:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char* ptr = const_cast<unsigned char*>(stream->buffer());
|
|
|
|
unsigned char* end_ptr = ptr + stream->length();
|
|
|
|
|
|
|
|
JvmtiExport::post_class_file_load_hook(name,
|
|
|
|
class_loader,
|
|
|
|
protection_domain,
|
|
|
|
&ptr,
|
|
|
|
&end_ptr,
|
|
|
|
cached_class_file);
|
|
|
|
|
|
|
|
if (ptr != stream->buffer()) {
|
|
|
|
// JVMTI agent has modified class file data.
|
|
|
|
// Set new class file stream using JVMTI agent modified class file data.
|
|
|
|
stream = new ClassFileStream(ptr,
|
|
|
|
end_ptr - ptr,
|
|
|
|
stream->source(),
|
|
|
|
stream->need_verify());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-15 10:25:37 -04:00
|
|
|
InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
|
|
|
|
Symbol* name,
|
|
|
|
ClassLoaderData* loader_data,
|
|
|
|
Handle protection_domain,
|
|
|
|
const InstanceKlass* host_klass,
|
|
|
|
GrowableArray<Handle>* cp_patches,
|
|
|
|
TRAPS) {
|
2015-12-08 20:04:03 +01:00
|
|
|
assert(stream != NULL, "invariant");
|
|
|
|
assert(loader_data != NULL, "invariant");
|
|
|
|
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
|
|
|
|
|
|
|
ResourceMark rm;
|
|
|
|
HandleMark hm;
|
|
|
|
|
|
|
|
JvmtiCachedClassFileData* cached_class_file = NULL;
|
|
|
|
|
8142968: Module System implementation
Initial integration of JEP 200, JEP 260, JEP 261, and JEP 282
Co-authored-by: Alex Buckley <alex.buckley@oracle.com>
Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com>
Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Mark Reinhold <mark.reinhold@oracle.com>
Co-authored-by: Harold Seigel <harold.seigel@oracle.com>
Co-authored-by: Lois Foltan <lois.foltan@oracle.com>
Co-authored-by: Calvin Cheung <calvin.cheung@oracle.com>
Co-authored-by: Christian Tornqvist <christian.tornqvist@oracle.com>
Co-authored-by: Erik Joelsson <erik.joelsson@oracle.com>
Co-authored-by: George Triantafillou <george.triantafillou@oracle.com>
Co-authored-by: Igor Ignatyev <igor.ignatyev@oracle.com>
Co-authored-by: Ioi Lam <ioi.lam@oracle.com>
Co-authored-by: James Laskey <james.laskey@oracle.com>
Co-authored-by: Jean-Francois Denise <jean-francois.denise@oracle.com>
Co-authored-by: Jiangli Zhou <jiangli.zhou@oracle.com>
Co-authored-by: Markus Gronlund <markus.gronlund@oracle.com>
Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com>
Co-authored-by: Staffan Larsen <staffan.larsen@oracle.com>
Co-authored-by: Sundararajan Athijegannathan <sundararajan.athijegannathan@oracle.com>
Reviewed-by: acorn, ccheung, coleenp, ctornqvi, dholmes, dsimms, gtriantafill, iklam, jiangli, mgronlun, mseledtsov, cjplummer, sspitsyn, stefank, twisti, hseigel, lfoltan, alanb, mchung, dfazunen
2016-03-17 19:04:01 +00:00
|
|
|
ClassFileStream* old_stream = stream;
|
|
|
|
|
2016-08-22 11:06:18 -04:00
|
|
|
// Skip this processing for VM anonymous classes
|
|
|
|
if (host_klass == NULL) {
|
|
|
|
stream = check_class_file_load_hook(stream,
|
|
|
|
name,
|
|
|
|
loader_data,
|
|
|
|
protection_domain,
|
|
|
|
&cached_class_file,
|
|
|
|
CHECK_NULL);
|
|
|
|
}
|
2015-12-08 20:04:03 +01:00
|
|
|
|
|
|
|
ClassFileParser parser(stream,
|
|
|
|
name,
|
|
|
|
loader_data,
|
|
|
|
protection_domain,
|
|
|
|
host_klass,
|
|
|
|
cp_patches,
|
|
|
|
ClassFileParser::BROADCAST, // publicity level
|
|
|
|
CHECK_NULL);
|
|
|
|
|
2017-03-15 10:25:37 -04:00
|
|
|
InstanceKlass* result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
|
8142968: Module System implementation
Initial integration of JEP 200, JEP 260, JEP 261, and JEP 282
Co-authored-by: Alex Buckley <alex.buckley@oracle.com>
Co-authored-by: Jonathan Gibbons <jonathan.gibbons@oracle.com>
Co-authored-by: Karen Kinnear <karen.kinnear@oracle.com>
Co-authored-by: Mandy Chung <mandy.chung@oracle.com>
Co-authored-by: Mark Reinhold <mark.reinhold@oracle.com>
Co-authored-by: Harold Seigel <harold.seigel@oracle.com>
Co-authored-by: Lois Foltan <lois.foltan@oracle.com>
Co-authored-by: Calvin Cheung <calvin.cheung@oracle.com>
Co-authored-by: Christian Tornqvist <christian.tornqvist@oracle.com>
Co-authored-by: Erik Joelsson <erik.joelsson@oracle.com>
Co-authored-by: George Triantafillou <george.triantafillou@oracle.com>
Co-authored-by: Igor Ignatyev <igor.ignatyev@oracle.com>
Co-authored-by: Ioi Lam <ioi.lam@oracle.com>
Co-authored-by: James Laskey <james.laskey@oracle.com>
Co-authored-by: Jean-Francois Denise <jean-francois.denise@oracle.com>
Co-authored-by: Jiangli Zhou <jiangli.zhou@oracle.com>
Co-authored-by: Markus Gronlund <markus.gronlund@oracle.com>
Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com>
Co-authored-by: Staffan Larsen <staffan.larsen@oracle.com>
Co-authored-by: Sundararajan Athijegannathan <sundararajan.athijegannathan@oracle.com>
Reviewed-by: acorn, ccheung, coleenp, ctornqvi, dholmes, dsimms, gtriantafill, iklam, jiangli, mgronlun, mseledtsov, cjplummer, sspitsyn, stefank, twisti, hseigel, lfoltan, alanb, mchung, dfazunen
2016-03-17 19:04:01 +00:00
|
|
|
assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant");
|
2015-12-08 20:04:03 +01:00
|
|
|
|
2017-03-15 10:25:37 -04:00
|
|
|
if (result == NULL) {
|
2015-12-08 20:04:03 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cached_class_file != NULL) {
|
|
|
|
// JVMTI: we have an InstanceKlass now, tell it about the cached bytes
|
|
|
|
result->set_cached_class_file(cached_class_file);
|
|
|
|
}
|
|
|
|
|
2017-10-19 19:23:48 -07:00
|
|
|
if (result->should_store_fingerprint()) {
|
|
|
|
result->store_fingerprint(stream->compute_fingerprint());
|
2016-12-11 19:07:04 -08:00
|
|
|
}
|
|
|
|
|
2016-03-01 23:48:46 +01:00
|
|
|
TRACE_KLASS_CREATION(result, parser, THREAD);
|
|
|
|
|
2017-08-28 15:34:04 -07:00
|
|
|
#if INCLUDE_CDS
|
2016-09-18 21:10:48 -04:00
|
|
|
if (DumpSharedSpaces) {
|
2018-04-10 11:43:40 -07:00
|
|
|
ClassLoader::record_result(result, stream, THREAD);
|
2017-08-28 15:34:04 -07:00
|
|
|
#if INCLUDE_JVMTI
|
2016-09-18 21:10:48 -04:00
|
|
|
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();
|
|
|
|
}
|
2017-08-02 18:06:38 -07:00
|
|
|
p = (JvmtiCachedClassFileData*)os::malloc(offset_of(JvmtiCachedClassFileData, data) + len, mtInternal);
|
2016-09-18 21:10:48 -04:00
|
|
|
p->length = len;
|
|
|
|
memcpy(p->data, bytes, len);
|
|
|
|
result->set_archived_class_data(p);
|
2017-08-28 15:34:04 -07:00
|
|
|
#endif // INCLUDE_JVMTI
|
2016-09-18 21:10:48 -04:00
|
|
|
}
|
2017-08-28 15:34:04 -07:00
|
|
|
#endif // INCLUDE_CDS
|
2016-09-18 21:10:48 -04:00
|
|
|
|
2015-12-08 20:04:03 +01:00
|
|
|
return result;
|
|
|
|
}
|