--- a/hotspot/src/share/vm/memory/filemap.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/memory/filemap.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -32,8 +32,8 @@
// header: dump of archive instance plus versioning info, datestamp, etc.
// [magic # = 0xF00BABA2]
// ... padding to align on page-boundary
-// read-write space from CompactingPermGenGen
-// read-only space from CompactingPermGenGen
+// read-write space
+// read-only space
// misc data (block offset table, string table, symbols, dictionary, etc.)
// tag(666)
--- a/hotspot/src/share/vm/oops/constMethod.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/constMethod.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -27,68 +27,61 @@
#include "oops/oop.hpp"
-// An ConstMethod* represents portions of a Java method which
-// do not vary.
+// An ConstMethod represents portions of a Java method which are not written to after
+// the classfile is parsed(*see below). This part of the method can be shared across
+// processes in a read-only section with Class Data Sharing (CDS). It's important
+// that this class doesn't have virtual functions because the vptr cannot be shared
+// with CDS.
+// (*)RewriteByteCodes and RewriteFrequentPairs is an exception but turned off in CDS
//
-// Memory layout (each line represents a word). Note that most
-// applications load thousands of methods, so keeping the size of this
+// Note that most applications load thousands of methods, so keeping the size of this
// structure small has a big impact on footprint.
+
+// The actual bytecodes are inlined after the end of the ConstMethod struct.
+//
+// The line number table is compressed and inlined following the byte codes. It is
+// found as the first byte following the byte codes. Note that accessing the line
+// number and local variable tables is not performance critical at all.
+//
+// The checked exceptions table and the local variable table are inlined after the
+// line number table, and indexed from the end of the method. We do not compress the
+// checked exceptions table since the average length is less than 2, and it is used
+// by reflection so access should be fast. We do not bother to compress the local
+// variable table either since it is mostly absent.
+//
//
-// |------------------------------------------------------|
-// | header |
-// | klass |
-// |------------------------------------------------------|
-// | fingerprint 1 |
-// | fingerprint 2 |
-// | constants (oop) |
-// | stackmap_data (oop) |
-// | constMethod_size |
-// | interp_kind | flags | code_size |
-// | name index | signature index |
-// | method_idnum | max_stack |
-// | max_locals | size_of_parameters |
-// |------------------------------------------------------|
-// | |
-// | byte codes |
-// | |
-// |------------------------------------------------------|
-// | compressed linenumber table |
-// | (see class CompressedLineNumberReadStream) |
-// | (note that length is unknown until decompressed) |
-// | (access flags bit tells whether table is present) |
-// | (indexed from start of ConstMethod*) |
-// | (elements not necessarily sorted!) |
-// |------------------------------------------------------|
-// | localvariable table elements + length (length last) |
-// | (length is u2, elements are 6-tuples of u2) |
-// | (see class LocalVariableTableElement) |
-// | (access flags bit tells whether table is present) |
-// | (indexed from end of ConstMethod*) |
-// |------------------------------------------------------|
-// | exception table + length (length last) |
-// | (length is u2, elements are 4-tuples of u2) |
-// | (see class ExceptionTableElement) |
-// | (access flags bit tells whether table is present) |
-// | (indexed from end of ConstMethod*) |
-// |------------------------------------------------------|
-// | checked exceptions elements + length (length last) |
-// | (length is u2, elements are u2) |
-// | (see class CheckedExceptionElement) |
-// | (access flags bit tells whether table is present) |
-// | (indexed from end of ConstMethod*) |
-// |------------------------------------------------------|
-// | method parameters elements + length (length last) |
-// | (length is u2, elements are u2, u4 structures) |
-// | (see class MethodParametersElement) |
-// | (access flags bit tells whether table is present) |
-// | (indexed from end of ConstMethod*) |
-// |------------------------------------------------------|
-// | generic signature index (u2) |
-// | (indexed from start of constMethodOop) |
-// |------------------------------------------------------|
-// | annotations arrays - method, parameter, type, default|
-// | pointer to Array<u1> if annotation is present |
-// |------------------------------------------------------|
+// ConstMethod embedded field layout (after declared fields):
+// [EMBEDDED byte codes]
+// [EMBEDDED compressed linenumber table]
+// (see class CompressedLineNumberReadStream)
+// (note that length is unknown until decompressed)
+// (access flags bit tells whether table is present)
+// (indexed from start of ConstMethod)
+// (elements not necessarily sorted!)
+// [EMBEDDED localvariable table elements + length (length last)]
+// (length is u2, elements are 6-tuples of u2)
+// (see class LocalVariableTableElement)
+// (access flags bit tells whether table is present)
+// (indexed from end of ConstMethod*)
+// [EMBEDDED exception table + length (length last)]
+// (length is u2, elements are 4-tuples of u2)
+// (see class ExceptionTableElement)
+// (access flags bit tells whether table is present)
+// (indexed from end of ConstMethod*)
+// [EMBEDDED checked exceptions elements + length (length last)]
+// (length is u2, elements are u2)
+// (see class CheckedExceptionElement)
+// (access flags bit tells whether table is present)
+// (indexed from end of ConstMethod*)
+// [EMBEDDED method parameters elements + length (length last)]
+// (length is u2, elements are u2, u4 structures)
+// (see class MethodParametersElement)
+// (access flags bit tells whether table is present)
+// (indexed from end of ConstMethod*)
+// [EMBEDDED generic signature index (u2)]
+// (indexed from end of constMethodOop)
+// [EMBEDDED annotations arrays - method, parameter, type, default]
+// pointer to Array<u1> if annotation is present
//
// IMPORTANT: If anything gets added here, there need to be changes to
// ensure that ServicabilityAgent doesn't get broken as a result!
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -180,12 +180,12 @@
return (i < 0) ? _no_index_sentinel : i;
}
-Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
+Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which, TRAPS) {
// A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
// tag is not updated atomicly.
- CPSlot entry = this_oop->slot_at(which);
+ CPSlot entry = this_cp->slot_at(which);
if (entry.is_resolved()) {
assert(entry.get_klass()->is_klass(), "must be");
// Already resolved - return entry.
@@ -204,15 +204,15 @@
Symbol* name = NULL;
Handle loader;
- { MonitorLockerEx ml(this_oop->lock());
+ { MonitorLockerEx ml(this_cp->lock());
- if (this_oop->tag_at(which).is_unresolved_klass()) {
- if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
+ if (this_cp->tag_at(which).is_unresolved_klass()) {
+ if (this_cp->tag_at(which).is_unresolved_klass_in_error()) {
in_error = true;
} else {
do_resolve = true;
- name = this_oop->unresolved_klass_at(which);
- loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
+ name = this_cp->unresolved_klass_at(which);
+ loader = Handle(THREAD, this_cp->pool_holder()->class_loader());
}
}
} // unlocking constantPool
@@ -221,26 +221,26 @@
// The original attempt to resolve this constant pool entry failed so find the
// original error and throw it again (JVMS 5.4.3).
if (in_error) {
- Symbol* error = SystemDictionary::find_resolution_error(this_oop, which);
+ Symbol* error = SystemDictionary::find_resolution_error(this_cp, which);
guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
ResourceMark rm;
// exception text will be the class name
- const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
+ const char* className = this_cp->unresolved_klass_at(which)->as_C_string();
THROW_MSG_0(error, className);
}
if (do_resolve) {
- // this_oop must be unlocked during resolve_or_fail
- oop protection_domain = this_oop->pool_holder()->protection_domain();
+ // this_cp must be unlocked during resolve_or_fail
+ oop protection_domain = this_cp->pool_holder()->protection_domain();
Handle h_prot (THREAD, protection_domain);
- Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
+ Klass* kk = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
KlassHandle k;
if (!HAS_PENDING_EXCEPTION) {
- k = KlassHandle(THREAD, k_oop);
+ k = KlassHandle(THREAD, kk);
// preserve the resolved klass.
- mirror_handle = Handle(THREAD, k_oop->java_mirror());
+ mirror_handle = Handle(THREAD, kk->java_mirror());
// Do access check for klasses
- verify_constant_pool_resolve(this_oop, k, THREAD);
+ verify_constant_pool_resolve(this_cp, k, THREAD);
}
// Failed to resolve class. We must record the errors so that subsequent attempts
@@ -251,12 +251,12 @@
bool throw_orig_error = false;
{
- MonitorLockerEx ml(this_oop->lock());
+ MonitorLockerEx ml(this_cp->lock());
// some other thread has beaten us and has resolved the class.
- if (this_oop->tag_at(which).is_klass()) {
+ if (this_cp->tag_at(which).is_klass()) {
CLEAR_PENDING_EXCEPTION;
- entry = this_oop->resolved_klass_at(which);
+ entry = this_cp->resolved_klass_at(which);
return entry.get_klass();
}
@@ -267,12 +267,12 @@
// and OutOfMemoryError, etc, or if the thread was hit by stop()
// Needs clarification to section 5.4.3 of the VM spec (see 6308271)
}
- else if (!this_oop->tag_at(which).is_unresolved_klass_in_error()) {
- SystemDictionary::add_resolution_error(this_oop, which, error);
- this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
+ else if (!this_cp->tag_at(which).is_unresolved_klass_in_error()) {
+ SystemDictionary::add_resolution_error(this_cp, which, error);
+ this_cp->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
} else {
// some other thread has put the class in error state.
- error = SystemDictionary::find_resolution_error(this_oop, which);
+ error = SystemDictionary::find_resolution_error(this_cp, which);
assert(error != NULL, "checking");
throw_orig_error = true;
}
@@ -281,7 +281,7 @@
if (throw_orig_error) {
CLEAR_PENDING_EXCEPTION;
ResourceMark rm;
- const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
+ const char* className = this_cp->unresolved_klass_at(which)->as_C_string();
THROW_MSG_0(error, className);
}
@@ -305,32 +305,32 @@
}
}
}
- if (k() != this_oop->pool_holder()) {
+ if (k() != this_cp->pool_holder()) {
// only print something if the classes are different
if (source_file != NULL) {
tty->print("RESOLVE %s %s %s:%d\n",
- this_oop->pool_holder()->external_name(),
+ this_cp->pool_holder()->external_name(),
InstanceKlass::cast(k())->external_name(), source_file, line_number);
} else {
tty->print("RESOLVE %s %s\n",
- this_oop->pool_holder()->external_name(),
+ this_cp->pool_holder()->external_name(),
InstanceKlass::cast(k())->external_name());
}
}
return k();
} else {
- MonitorLockerEx ml(this_oop->lock());
+ MonitorLockerEx ml(this_cp->lock());
// Only updated constant pool - if it is resolved.
- do_resolve = this_oop->tag_at(which).is_unresolved_klass();
+ do_resolve = this_cp->tag_at(which).is_unresolved_klass();
if (do_resolve) {
- ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
+ ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
- this_oop->klass_at_put(which, k());
+ this_cp->klass_at_put(which, k());
}
}
}
- entry = this_oop->resolved_klass_at(which);
+ entry = this_cp->resolved_klass_at(which);
assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point");
return entry.get_klass();
}
@@ -340,8 +340,8 @@
// by compiler and exception handling. Also used to avoid classloads for
// instanceof operations. Returns NULL if the class has not been loaded or
// if the verification of constant pool failed
-Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_oop, int which) {
- CPSlot entry = this_oop->slot_at(which);
+Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_cp, int which) {
+ CPSlot entry = this_cp->slot_at(which);
if (entry.is_resolved()) {
assert(entry.get_klass()->is_klass(), "must be");
return entry.get_klass();
@@ -349,8 +349,8 @@
assert(entry.is_unresolved(), "must be either symbol or klass");
Thread *thread = Thread::current();
Symbol* name = entry.get_symbol();
- oop loader = this_oop->pool_holder()->class_loader();
- oop protection_domain = this_oop->pool_holder()->protection_domain();
+ oop loader = this_cp->pool_holder()->class_loader();
+ oop protection_domain = this_cp->pool_holder()->protection_domain();
Handle h_prot (thread, protection_domain);
Handle h_loader (thread, loader);
Klass* k = SystemDictionary::find(name, h_loader, h_prot, thread);
@@ -360,7 +360,7 @@
EXCEPTION_MARK;
KlassHandle klass(THREAD, k);
// return NULL if verification fails
- verify_constant_pool_resolve(this_oop, klass, THREAD);
+ verify_constant_pool_resolve(this_cp, klass, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
return NULL;
@@ -373,8 +373,8 @@
}
-Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_oop, int which) {
- return klass_at_if_loaded(this_oop, this_oop->klass_ref_index_at(which));
+Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_cp, int which) {
+ return klass_at_if_loaded(this_cp, this_cp->klass_ref_index_at(which));
}
@@ -486,11 +486,11 @@
}
-void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
+void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle k, TRAPS) {
if (k->oop_is_instance() || k->oop_is_objArray()) {
- instanceKlassHandle holder (THREAD, this_oop->pool_holder());
- Klass* elem_oop = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass();
- KlassHandle element (THREAD, elem_oop);
+ instanceKlassHandle holder (THREAD, this_cp->pool_holder());
+ Klass* elem = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass();
+ KlassHandle element (THREAD, elem);
// The element type could be a typeArray - we only need the access check if it is
// an reference to another class
@@ -559,10 +559,10 @@
}
-void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS) {
- for (int index = 1; index < this_oop->length(); index++) { // Index 0 is unused
- if (this_oop->tag_at(index).is_string()) {
- this_oop->string_at(index, CHECK);
+void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS) {
+ for (int index = 1; index < this_cp->length(); index++) { // Index 0 is unused
+ if (this_cp->tag_at(index).is_string()) {
+ this_cp->string_at(index, CHECK);
}
}
}
@@ -585,11 +585,11 @@
// If resolution for MethodHandle or MethodType fails, save the exception
// in the resolution error table, so that the same exception is thrown again.
-void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which,
+void ConstantPool::save_and_throw_exception(constantPoolHandle this_cp, int which,
int tag, TRAPS) {
ResourceMark rm;
Symbol* error = PENDING_EXCEPTION->klass()->name();
- MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag.
+ MonitorLockerEx ml(this_cp->lock()); // lock cpool to change tag.
int error_tag = (tag == JVM_CONSTANT_MethodHandle) ?
JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError;
@@ -601,12 +601,12 @@
// and OutOfMemoryError, etc, or if the thread was hit by stop()
// Needs clarification to section 5.4.3 of the VM spec (see 6308271)
- } else if (this_oop->tag_at(which).value() != error_tag) {
- SystemDictionary::add_resolution_error(this_oop, which, error);
- this_oop->tag_at_put(which, error_tag);
+ } else if (this_cp->tag_at(which).value() != error_tag) {
+ SystemDictionary::add_resolution_error(this_cp, which, error);
+ this_cp->tag_at_put(which, error_tag);
} else {
// some other thread has put the class in error state.
- error = SystemDictionary::find_resolution_error(this_oop, which);
+ error = SystemDictionary::find_resolution_error(this_cp, which);
assert(error != NULL, "checking");
CLEAR_PENDING_EXCEPTION;
THROW_MSG(error, "");
@@ -617,7 +617,7 @@
// Called to resolve constants in the constant pool and return an oop.
// Some constant pool entries cache their resolved oop. This is also
// called to create oops from constants to use in arguments for invokedynamic
-oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
+oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS) {
oop result_oop = NULL;
Handle throw_exception;
@@ -625,23 +625,23 @@
// It is possible that this constant is one which is cached in the objects.
// We'll do a linear search. This should be OK because this usage is rare.
assert(index > 0, "valid index");
- cache_index = this_oop->cp_to_object_index(index);
+ cache_index = this_cp->cp_to_object_index(index);
}
assert(cache_index == _no_index_sentinel || cache_index >= 0, "");
assert(index == _no_index_sentinel || index >= 0, "");
if (cache_index >= 0) {
- result_oop = this_oop->resolved_references()->obj_at(cache_index);
+ result_oop = this_cp->resolved_references()->obj_at(cache_index);
if (result_oop != NULL) {
return result_oop;
// That was easy...
}
- index = this_oop->object_to_cp_index(cache_index);
+ index = this_cp->object_to_cp_index(cache_index);
}
jvalue prim_value; // temp used only in a few cases below
- int tag_value = this_oop->tag_at(index).value();
+ int tag_value = this_cp->tag_at(index).value();
switch (tag_value) {
@@ -650,7 +650,7 @@
case JVM_CONSTANT_Class:
{
assert(cache_index == _no_index_sentinel, "should not have been set");
- Klass* resolved = klass_at_impl(this_oop, index, CHECK_NULL);
+ Klass* resolved = klass_at_impl(this_cp, index, CHECK_NULL);
// ldc wants the java mirror.
result_oop = resolved->java_mirror();
break;
@@ -658,17 +658,17 @@
case JVM_CONSTANT_String:
assert(cache_index != _no_index_sentinel, "should have been set");
- if (this_oop->is_pseudo_string_at(index)) {
- result_oop = this_oop->pseudo_string_at(index, cache_index);
+ if (this_cp->is_pseudo_string_at(index)) {
+ result_oop = this_cp->pseudo_string_at(index, cache_index);
break;
}
- result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
+ result_oop = string_at_impl(this_cp, index, cache_index, CHECK_NULL);
break;
case JVM_CONSTANT_MethodHandleInError:
case JVM_CONSTANT_MethodTypeInError:
{
- Symbol* error = SystemDictionary::find_resolution_error(this_oop, index);
+ Symbol* error = SystemDictionary::find_resolution_error(this_cp, index);
guarantee(error != (Symbol*)NULL, "tag mismatch with resolution error table");
ResourceMark rm;
THROW_MSG_0(error, "");
@@ -677,72 +677,72 @@
case JVM_CONSTANT_MethodHandle:
{
- int ref_kind = this_oop->method_handle_ref_kind_at(index);
- int callee_index = this_oop->method_handle_klass_index_at(index);
- Symbol* name = this_oop->method_handle_name_ref_at(index);
- Symbol* signature = this_oop->method_handle_signature_ref_at(index);
+ int ref_kind = this_cp->method_handle_ref_kind_at(index);
+ int callee_index = this_cp->method_handle_klass_index_at(index);
+ Symbol* name = this_cp->method_handle_name_ref_at(index);
+ Symbol* signature = this_cp->method_handle_signature_ref_at(index);
if (PrintMiscellaneous)
tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
- ref_kind, index, this_oop->method_handle_index_at(index),
+ ref_kind, index, this_cp->method_handle_index_at(index),
callee_index, name->as_C_string(), signature->as_C_string());
KlassHandle callee;
- { Klass* k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
+ { Klass* k = klass_at_impl(this_cp, callee_index, CHECK_NULL);
callee = KlassHandle(THREAD, k);
}
- KlassHandle klass(THREAD, this_oop->pool_holder());
+ KlassHandle klass(THREAD, this_cp->pool_holder());
Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
callee, name, signature,
THREAD);
result_oop = value();
if (HAS_PENDING_EXCEPTION) {
- save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
+ save_and_throw_exception(this_cp, index, tag_value, CHECK_NULL);
}
break;
}
case JVM_CONSTANT_MethodType:
{
- Symbol* signature = this_oop->method_type_signature_at(index);
+ Symbol* signature = this_cp->method_type_signature_at(index);
if (PrintMiscellaneous)
tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
- index, this_oop->method_type_index_at(index),
+ index, this_cp->method_type_index_at(index),
signature->as_C_string());
- KlassHandle klass(THREAD, this_oop->pool_holder());
+ KlassHandle klass(THREAD, this_cp->pool_holder());
Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD);
result_oop = value();
if (HAS_PENDING_EXCEPTION) {
- save_and_throw_exception(this_oop, index, tag_value, CHECK_NULL);
+ save_and_throw_exception(this_cp, index, tag_value, CHECK_NULL);
}
break;
}
case JVM_CONSTANT_Integer:
assert(cache_index == _no_index_sentinel, "should not have been set");
- prim_value.i = this_oop->int_at(index);
+ prim_value.i = this_cp->int_at(index);
result_oop = java_lang_boxing_object::create(T_INT, &prim_value, CHECK_NULL);
break;
case JVM_CONSTANT_Float:
assert(cache_index == _no_index_sentinel, "should not have been set");
- prim_value.f = this_oop->float_at(index);
+ prim_value.f = this_cp->float_at(index);
result_oop = java_lang_boxing_object::create(T_FLOAT, &prim_value, CHECK_NULL);
break;
case JVM_CONSTANT_Long:
assert(cache_index == _no_index_sentinel, "should not have been set");
- prim_value.j = this_oop->long_at(index);
+ prim_value.j = this_cp->long_at(index);
result_oop = java_lang_boxing_object::create(T_LONG, &prim_value, CHECK_NULL);
break;
case JVM_CONSTANT_Double:
assert(cache_index == _no_index_sentinel, "should not have been set");
- prim_value.d = this_oop->double_at(index);
+ prim_value.d = this_cp->double_at(index);
result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL);
break;
default:
DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
- this_oop(), index, cache_index, tag_value) );
+ this_cp(), index, cache_index, tag_value) );
assert(false, "unexpected constant tag");
break;
}
@@ -750,15 +750,15 @@
if (cache_index >= 0) {
// Cache the oop here also.
Handle result_handle(THREAD, result_oop);
- MonitorLockerEx ml(this_oop->lock()); // don't know if we really need this
- oop result = this_oop->resolved_references()->obj_at(cache_index);
+ MonitorLockerEx ml(this_cp->lock()); // don't know if we really need this
+ oop result = this_cp->resolved_references()->obj_at(cache_index);
// Benign race condition: resolved_references may already be filled in while we were trying to lock.
// The important thing here is that all threads pick up the same result.
// It doesn't matter which racing thread wins, as long as only one
// result is used by all threads, and all future queries.
// That result may be either a resolved constant or a failure exception.
if (result == NULL) {
- this_oop->resolved_references()->obj_at_put(cache_index, result_handle());
+ this_cp->resolved_references()->obj_at_put(cache_index, result_handle());
return result_handle();
} else {
// Return the winning thread's result. This can be different than
@@ -778,8 +778,8 @@
}
-oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_oop, int index, TRAPS) {
- assert(this_oop->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
+oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS) {
+ assert(this_cp->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
Handle bsm;
int argc;
@@ -787,14 +787,14 @@
// JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type], plus optional arguments
// The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
// It is accompanied by the optional arguments.
- int bsm_index = this_oop->invoke_dynamic_bootstrap_method_ref_index_at(index);
- oop bsm_oop = this_oop->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
+ int bsm_index = this_cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
+ oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) {
THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle");
}
// Extract the optional static arguments.
- argc = this_oop->invoke_dynamic_argument_count_at(index);
+ argc = this_cp->invoke_dynamic_argument_count_at(index);
if (argc == 0) return bsm_oop;
bsm = Handle(THREAD, bsm_oop);
@@ -808,21 +808,21 @@
info->obj_at_put(0, bsm());
for (int i = 0; i < argc; i++) {
- int arg_index = this_oop->invoke_dynamic_argument_index_at(index, i);
- oop arg_oop = this_oop->resolve_possibly_cached_constant_at(arg_index, CHECK_NULL);
+ int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
+ oop arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK_NULL);
info->obj_at_put(1+i, arg_oop);
}
return info();
}
-oop ConstantPool::string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS) {
+oop ConstantPool::string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS) {
// If the string has already been interned, this entry will be non-null
- oop str = this_oop->resolved_references()->obj_at(obj_index);
+ oop str = this_cp->resolved_references()->obj_at(obj_index);
if (str != NULL) return str;
- Symbol* sym = this_oop->unresolved_string_at(which);
+ Symbol* sym = this_cp->unresolved_string_at(which);
str = StringTable::intern(sym, CHECK_(NULL));
- this_oop->string_at_put(which, obj_index, str);
+ this_cp->string_at_put(which, obj_index, str);
assert(java_lang_String::is_instance(str), "must be string");
return str;
}
--- a/hotspot/src/share/vm/oops/constantPool.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -48,7 +48,7 @@
# include "bytes_ppc.hpp"
#endif
-// A constantPool is an array containing class constants as described in the
+// A ConstantPool is an array containing class constants as described in the
// class file.
//
// Most of the constant pool entries are written during class parsing, which
@@ -81,9 +81,10 @@
};
class KlassSizeStats;
+
class ConstantPool : public Metadata {
friend class VMStructs;
- friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast
+ friend class BytecodeInterpreter; // Directly extracts a klass in the pool for fast instanceof/checkcast
friend class Universe; // For null constructor
private:
Array<u1>* _tags; // the tag array describing the constant pool's contents
@@ -747,13 +748,13 @@
friend class SystemDictionary;
// Used by compiler to prevent classloading.
- static Method* method_at_if_loaded (constantPoolHandle this_oop, int which);
- static bool has_appendix_at_if_loaded (constantPoolHandle this_oop, int which);
- static oop appendix_at_if_loaded (constantPoolHandle this_oop, int which);
- static bool has_method_type_at_if_loaded (constantPoolHandle this_oop, int which);
- static oop method_type_at_if_loaded (constantPoolHandle this_oop, int which);
- static Klass* klass_at_if_loaded (constantPoolHandle this_oop, int which);
- static Klass* klass_ref_at_if_loaded (constantPoolHandle this_oop, int which);
+ static Method* method_at_if_loaded (constantPoolHandle this_cp, int which);
+ static bool has_appendix_at_if_loaded (constantPoolHandle this_cp, int which);
+ static oop appendix_at_if_loaded (constantPoolHandle this_cp, int which);
+ static bool has_method_type_at_if_loaded (constantPoolHandle this_cp, int which);
+ static oop method_type_at_if_loaded (constantPoolHandle this_cp, int which);
+ static Klass* klass_at_if_loaded (constantPoolHandle this_cp, int which);
+ static Klass* klass_ref_at_if_loaded (constantPoolHandle this_cp, int which);
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
// future by other Java code. These take constant pool indices rather than
@@ -811,19 +812,19 @@
}
// Performs the LinkResolver checks
- static void verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle klass, TRAPS);
+ static void verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle klass, TRAPS);
// Implementation of methods that needs an exposed 'this' pointer, in order to
// handle GC while executing the method
- static Klass* klass_at_impl(constantPoolHandle this_oop, int which, TRAPS);
- static oop string_at_impl(constantPoolHandle this_oop, int which, int obj_index, TRAPS);
+ static Klass* klass_at_impl(constantPoolHandle this_cp, int which, TRAPS);
+ static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS);
// Resolve string constants (to prevent allocation during compilation)
- static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
+ static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS);
- static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
- static void save_and_throw_exception(constantPoolHandle this_oop, int which, int tag_value, TRAPS);
- static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_oop, int index, TRAPS);
+ static oop resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS);
+ static void save_and_throw_exception(constantPoolHandle this_cp, int which, int tag_value, TRAPS);
+ static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS);
public:
// Merging ConstantPool* support:
--- a/hotspot/src/share/vm/oops/cpCache.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, 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
@@ -328,7 +328,7 @@
// the f1 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;',
// not '(Ljava/lang/String;)Ljava/util/List;'.
// The fact that String and List are involved is encoded in the MethodType in refs[f2].
- // This allows us to create fewer method oops, while keeping type safety.
+ // This allows us to create fewer Methods, while keeping type safety.
//
objArrayHandle resolved_references = cpool->resolved_references();
--- a/hotspot/src/share/vm/oops/cpCache.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, 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
@@ -102,8 +102,9 @@
// _f1 = Method* for non-virtual calls, unused by virtual calls.
// for interface calls, which are essentially virtual but need a klass,
// contains Klass* for the corresponding interface.
-// for invokedynamic, f1 contains a site-specific CallSite object (as an appendix)
-// for invokehandle, f1 contains a site-specific MethodType object (as an appendix)
+// for invokedynamic and invokehandle, f1 contains the adapter method which
+// manages the actual call. The appendix is stored in the ConstantPool
+// resolved_references array.
// (upcoming metadata changes will move the appendix to a separate array)
// _f2 = vtable/itable index (or final Method*) for virtual calls only,
// unused by non-virtual. The is_vfinal flag indicates this is a
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -432,8 +432,8 @@
if (!InstanceKlass::cast(super)->is_initialized()) return;
// call body to expose the this pointer
- instanceKlassHandle this_oop(thread, this);
- eager_initialize_impl(this_oop);
+ instanceKlassHandle this_k(thread, this);
+ eager_initialize_impl(this_k);
}
}
@@ -470,16 +470,16 @@
assert(!is_not_initialized(), "class must be initialized now");
}
-void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
+void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_k) {
EXCEPTION_MARK;
- oop init_lock = this_oop->init_lock();
+ oop init_lock = this_k->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
// abort if someone beat us to the initialization
- if (!this_oop->is_not_initialized()) return; // note: not equivalent to is_initialized()
-
- ClassState old_state = this_oop->init_state();
- link_class_impl(this_oop, true, THREAD);
+ if (!this_k->is_not_initialized()) return; // note: not equivalent to is_initialized()
+
+ ClassState old_state = this_k->init_state();
+ link_class_impl(this_k, true, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
// Abort if linking the class throws an exception.
@@ -487,16 +487,16 @@
// Use a test to avoid redundantly resetting the state if there's
// no change. Set_init_state() asserts that state changes make
// progress, whereas here we might just be spinning in place.
- if( old_state != this_oop->_init_state )
- this_oop->set_init_state (old_state);
+ if( old_state != this_k->_init_state )
+ this_k->set_init_state (old_state);
} else {
// linking successfull, mark class as initialized
- this_oop->set_init_state (fully_initialized);
- this_oop->fence_and_clear_init_lock();
+ this_k->set_init_state (fully_initialized);
+ this_k->fence_and_clear_init_lock();
// trace
if (TraceClassInitialization) {
ResourceMark rm(THREAD);
- tty->print_cr("[Initialized %s without side effects]", this_oop->external_name());
+ tty->print_cr("[Initialized %s without side effects]", this_k->external_name());
}
}
}
@@ -508,8 +508,8 @@
void InstanceKlass::initialize(TRAPS) {
if (this->should_be_initialized()) {
HandleMark hm(THREAD);
- instanceKlassHandle this_oop(THREAD, this);
- initialize_impl(this_oop, CHECK);
+ instanceKlassHandle this_k(THREAD, this);
+ initialize_impl(this_k, CHECK);
// Note: at this point the class may be initialized
// OR it may be in the state of being initialized
// in case of recursive initialization!
@@ -520,11 +520,11 @@
bool InstanceKlass::verify_code(
- instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
+ instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
// 1) Verify the bytecodes
Verifier::Mode mode =
throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
- return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), CHECK_false);
+ return Verifier::verify(this_k, mode, this_k->should_verify_class(), CHECK_false);
}
@@ -540,8 +540,8 @@
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
HandleMark hm(THREAD);
- instanceKlassHandle this_oop(THREAD, this);
- link_class_impl(this_oop, true, CHECK);
+ instanceKlassHandle this_k(THREAD, this);
+ link_class_impl(this_k, true, CHECK);
}
}
@@ -551,22 +551,22 @@
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
HandleMark hm(THREAD);
- instanceKlassHandle this_oop(THREAD, this);
- link_class_impl(this_oop, false, CHECK_false);
+ instanceKlassHandle this_k(THREAD, this);
+ link_class_impl(this_k, false, CHECK_false);
}
return is_linked();
}
bool InstanceKlass::link_class_impl(
- instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
+ instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
// check for error state
- if (this_oop->is_in_error_state()) {
+ if (this_k->is_in_error_state()) {
ResourceMark rm(THREAD);
THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
- this_oop->external_name(), false);
+ this_k->external_name(), false);
}
// return if already verified
- if (this_oop->is_linked()) {
+ if (this_k->is_linked()) {
return true;
}
@@ -576,7 +576,7 @@
JavaThread* jt = (JavaThread*)THREAD;
// link super class before linking this class
- instanceKlassHandle super(THREAD, this_oop->super());
+ instanceKlassHandle super(THREAD, this_k->super());
if (super.not_null()) {
if (super->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
@@ -584,7 +584,7 @@
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
- this_oop->external_name(),
+ this_k->external_name(),
super->external_name()
);
return false;
@@ -594,7 +594,7 @@
}
// link all interfaces implemented by this class before linking this class
- Array<Klass*>* interfaces = this_oop->local_interfaces();
+ Array<Klass*>* interfaces = this_k->local_interfaces();
int num_interfaces = interfaces->length();
for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(THREAD);
@@ -603,7 +603,7 @@
}
// in case the class is linked in the process of linking its superclasses
- if (this_oop->is_linked()) {
+ if (this_k->is_linked()) {
return true;
}
@@ -618,14 +618,14 @@
// verification & rewriting
{
- oop init_lock = this_oop->init_lock();
+ oop init_lock = this_k->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
// rewritten will have been set if loader constraint error found
// on an earlier link attempt
// don't verify or rewrite if already rewritten
- if (!this_oop->is_linked()) {
- if (!this_oop->is_rewritten()) {
+ if (!this_k->is_linked()) {
+ if (!this_k->is_rewritten()) {
{
// Timer includes any side effects of class verification (resolution,
// etc), but not recursive entry into verify_code().
@@ -635,7 +635,7 @@
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_VERIFY);
- bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
+ bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
if (!verify_ok) {
return false;
}
@@ -644,39 +644,39 @@
// Just in case a side-effect of verify linked this class already
// (which can sometimes happen since the verifier loads classes
// using custom class loaders, which are free to initialize things)
- if (this_oop->is_linked()) {
+ if (this_k->is_linked()) {
return true;
}
// also sets rewritten
- this_oop->rewrite_class(CHECK_false);
+ this_k->rewrite_class(CHECK_false);
}
// relocate jsrs and link methods after they are all rewritten
- this_oop->link_methods(CHECK_false);
+ this_k->link_methods(CHECK_false);
// Initialize the vtable and interface table after
// methods have been rewritten since rewrite may
// fabricate new Method*s.
// also does loader constraint checking
- if (!this_oop()->is_shared()) {
+ if (!this_k()->is_shared()) {
ResourceMark rm(THREAD);
- this_oop->vtable()->initialize_vtable(true, CHECK_false);
- this_oop->itable()->initialize_itable(true, CHECK_false);
+ this_k->vtable()->initialize_vtable(true, CHECK_false);
+ this_k->itable()->initialize_itable(true, CHECK_false);
}
#ifdef ASSERT
else {
ResourceMark rm(THREAD);
- this_oop->vtable()->verify(tty, true);
+ this_k->vtable()->verify(tty, true);
// In case itable verification is ever added.
- // this_oop->itable()->verify(tty, true);
+ // this_k->itable()->verify(tty, true);
}
#endif
- this_oop->set_init_state(linked);
+ this_k->set_init_state(linked);
if (JvmtiExport::should_post_class_prepare()) {
Thread *thread = THREAD;
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
- JvmtiExport::post_class_prepare((JavaThread *) thread, this_oop());
+ JvmtiExport::post_class_prepare((JavaThread *) thread, this_k());
}
}
}
@@ -689,13 +689,13 @@
// verification but before the first method of the class is executed.
void InstanceKlass::rewrite_class(TRAPS) {
assert(is_loaded(), "must be loaded");
- instanceKlassHandle this_oop(THREAD, this);
- if (this_oop->is_rewritten()) {
- assert(this_oop()->is_shared(), "rewriting an unshared class?");
+ instanceKlassHandle this_k(THREAD, this);
+ if (this_k->is_rewritten()) {
+ assert(this_k()->is_shared(), "rewriting an unshared class?");
return;
}
- Rewriter::rewrite(this_oop, CHECK);
- this_oop->set_rewritten();
+ Rewriter::rewrite(this_k, CHECK);
+ this_k->set_rewritten();
}
// Now relocate and link method entry points after class is rewritten.
@@ -729,19 +729,19 @@
}
-void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
+void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) {
// Make sure klass is linked (verified) before initialization
// A class could already be verified, since it has been reflected upon.
- this_oop->link_class(CHECK);
-
- DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);
+ this_k->link_class(CHECK);
+
+ DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_k()), -1);
bool wait = false;
// refer to the JVM book page 47 for description of steps
// Step 1
{
- oop init_lock = this_oop->init_lock();
+ oop init_lock = this_k->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
Thread *self = THREAD; // it's passed the current thread
@@ -750,29 +750,29 @@
// If we were to use wait() instead of waitInterruptibly() then
// we might end up throwing IE from link/symbol resolution sites
// that aren't expected to throw. This would wreak havoc. See 6320309.
- while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
+ while(this_k->is_being_initialized() && !this_k->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
// Step 3
- if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
- DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);
+ if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) {
+ DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_k()), -1,wait);
return;
}
// Step 4
- if (this_oop->is_initialized()) {
- DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
+ if (this_k->is_initialized()) {
+ DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_k()), -1,wait);
return;
}
// Step 5
- if (this_oop->is_in_error_state()) {
- DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);
+ if (this_k->is_in_error_state()) {
+ DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_k()), -1,wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
- const char* className = this_oop->external_name();
+ const char* className = this_k->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
@@ -785,13 +785,13 @@
}
// Step 6
- this_oop->set_init_state(being_initialized);
- this_oop->set_init_thread(self);
+ this_k->set_init_state(being_initialized);
+ this_k->set_init_thread(self);
}
// Step 7
- Klass* super_klass = this_oop->super();
- if (super_klass != NULL && !this_oop->is_interface() && super_klass->should_be_initialized()) {
+ Klass* super_klass = this_k->super();
+ if (super_klass != NULL && !this_k->is_interface() && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
if (HAS_PENDING_EXCEPTION) {
@@ -799,18 +799,18 @@
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
- this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
+ this_k->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below
}
- DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);
+ DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_k()), -1,wait);
THROW_OOP(e());
}
}
- if (this_oop->has_default_methods()) {
+ if (this_k->has_default_methods()) {
// Step 7.5: initialize any interfaces which have default methods
- for (int i = 0; i < this_oop->local_interfaces()->length(); ++i) {
- Klass* iface = this_oop->local_interfaces()->at(i);
+ for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
+ Klass* iface = this_k->local_interfaces()->at(i);
InstanceKlass* ik = InstanceKlass::cast(iface);
if (ik->has_default_methods() && ik->should_be_initialized()) {
ik->initialize(THREAD);
@@ -821,7 +821,7 @@
{
EXCEPTION_MARK;
// Locks object, set state, and notify all waiting threads
- this_oop->set_initialization_state_and_notify(
+ this_k->set_initialization_state_and_notify(
initialization_error, THREAD);
// ignore any exception thrown, superclass initialization error is
@@ -829,7 +829,7 @@
CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(
- super__failed, InstanceKlass::cast(this_oop()), -1, wait);
+ super__failed, InstanceKlass::cast(this_k()), -1, wait);
THROW_OOP(e());
}
}
@@ -840,7 +840,7 @@
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD;
- DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);
+ DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_k()), -1,wait);
// Timer includes any side effects of class initialization (resolution,
// etc), but not recursive entry into call_class_initializer().
PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
@@ -849,14 +849,14 @@
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_CLINIT);
- this_oop->call_class_initializer(THREAD);
+ this_k->call_class_initializer(THREAD);
}
// Step 9
if (!HAS_PENDING_EXCEPTION) {
- this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
+ this_k->set_initialization_state_and_notify(fully_initialized, CHECK);
{ ResourceMark rm(THREAD);
- debug_only(this_oop->vtable()->verify(tty, true);)
+ debug_only(this_k->vtable()->verify(tty, true);)
}
}
else {
@@ -868,13 +868,13 @@
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
- this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
+ this_k->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
// JVMTI has already reported the pending exception
// JVMTI internal flag reset is needed in order to report ExceptionInInitializerError
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
- DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);
+ DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_k()), -1,wait);
if (e->is_a(SystemDictionary::Error_klass())) {
THROW_OOP(e());
} else {
@@ -884,7 +884,7 @@
&args);
}
}
- DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);
+ DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_k()), -1,wait);
}
@@ -894,11 +894,11 @@
set_initialization_state_and_notify_impl(kh, state, CHECK);
}
-void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
- oop init_lock = this_oop->init_lock();
+void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) {
+ oop init_lock = this_k->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
- this_oop->set_init_state(state);
- this_oop->fence_and_clear_init_lock();
+ this_k->set_init_state(state);
+ this_k->fence_and_clear_init_lock();
ol.notify_all(CHECK);
}
@@ -952,12 +952,11 @@
void InstanceKlass::process_interfaces(Thread *thread) {
// link this class into the implementors list of every interface it implements
- Klass* this_as_klass_oop = this;
for (int i = local_interfaces()->length() - 1; i >= 0; i--) {
assert(local_interfaces()->at(i)->is_klass(), "must be a klass");
InstanceKlass* interf = InstanceKlass::cast(local_interfaces()->at(i));
assert(interf->is_interface(), "expected interface");
- interf->add_implementor(this_as_klass_oop);
+ interf->add_implementor(this);
}
}
@@ -1083,12 +1082,12 @@
}
Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) {
- instanceKlassHandle this_oop(THREAD, this);
- return array_klass_impl(this_oop, or_null, n, THREAD);
+ instanceKlassHandle this_k(THREAD, this);
+ return array_klass_impl(this_k, or_null, n, THREAD);
}
-Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_oop, bool or_null, int n, TRAPS) {
- if (this_oop->array_klasses() == NULL) {
+Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_k, bool or_null, int n, TRAPS) {
+ if (this_k->array_klasses() == NULL) {
if (or_null) return NULL;
ResourceMark rm;
@@ -1099,14 +1098,14 @@
MutexLocker ma(MultiArray_lock, THREAD);
// Check if update has already taken place
- if (this_oop->array_klasses() == NULL) {
- Klass* k = ObjArrayKlass::allocate_objArray_klass(this_oop->class_loader_data(), 1, this_oop, CHECK_NULL);
- this_oop->set_array_klasses(k);
+ if (this_k->array_klasses() == NULL) {
+ Klass* k = ObjArrayKlass::allocate_objArray_klass(this_k->class_loader_data(), 1, this_k, CHECK_NULL);
+ this_k->set_array_klasses(k);
}
}
}
// _this will always be set at this point
- ObjArrayKlass* oak = (ObjArrayKlass*)this_oop->array_klasses();
+ ObjArrayKlass* oak = (ObjArrayKlass*)this_k->array_klasses();
if (or_null) {
return oak->array_klass_or_null(n);
}
@@ -1133,20 +1132,20 @@
return NULL;
}
-void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) {
+void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_k, TRAPS) {
if (ReplayCompiles &&
(ReplaySuppressInitializers == 1 ||
- ReplaySuppressInitializers >= 2 && this_oop->class_loader() != NULL)) {
+ ReplaySuppressInitializers >= 2 && this_k->class_loader() != NULL)) {
// Hide the existence of the initializer for the purpose of replaying the compile
return;
}
- methodHandle h_method(THREAD, this_oop->class_initializer());
- assert(!this_oop->is_initialized(), "we cannot initialize twice");
+ methodHandle h_method(THREAD, this_k->class_initializer());
+ assert(!this_k->is_initialized(), "we cannot initialize twice");
if (TraceClassInitialization) {
tty->print("%d Initializing ", call_class_initializer_impl_counter++);
- this_oop->name()->print_value();
- tty->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", (address)this_oop());
+ this_k->name()->print_value();
+ tty->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", (address)this_k());
}
if (h_method() != NULL) {
JavaCallArguments args; // No arguments
@@ -1296,8 +1295,8 @@
}
-void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
- for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) {
+void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS) {
+ for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor& fd = fs.field_descriptor();
f(&fd, CHECK);
@@ -1515,14 +1514,14 @@
}
/* jni_id_for_impl for jfieldIds only */
-JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_oop, int offset) {
+JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_k, int offset) {
MutexLocker ml(JfieldIdCreation_lock);
// Retry lookup after we got the lock
- JNIid* probe = this_oop->jni_ids() == NULL ? NULL : this_oop->jni_ids()->find(offset);
+ JNIid* probe = this_k->jni_ids() == NULL ? NULL : this_k->jni_ids()->find(offset);
if (probe == NULL) {
// Slow case, allocate new static field identifier
- probe = new JNIid(this_oop(), offset, this_oop->jni_ids());
- this_oop->set_jni_ids(probe);
+ probe = new JNIid(this_k(), offset, this_k->jni_ids());
+ this_k->set_jni_ids(probe);
}
return probe;
}
@@ -3161,8 +3160,8 @@
}
// Verify first subklass
- if (subklass_oop() != NULL) {
- guarantee(subklass_oop()->is_klass(), "should be klass");
+ if (subklass() != NULL) {
+ guarantee(subklass()->is_klass(), "should be klass");
}
// Verify siblings
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -43,35 +43,7 @@
// An InstanceKlass is the VM level representation of a Java class.
// It contains all information needed for at class at execution runtime.
-// InstanceKlass layout:
-// [C++ vtbl pointer ] Klass
-// [subtype cache ] Klass
-// [instance size ] Klass
-// [java mirror ] Klass
-// [super ] Klass
-// [access_flags ] Klass
-// [name ] Klass
-// [first subklass ] Klass
-// [next sibling ] Klass
-// [array klasses ]
-// [methods ]
-// [local interfaces ]
-// [transitive interfaces ]
-// [fields ]
-// [constants ]
-// [class loader ]
-// [source file name ]
-// [inner classes ]
-// [static field size ]
-// [nonstatic field size ]
-// [static oop fields size ]
-// [nonstatic oop maps size ]
-// [has finalize method ]
-// [deoptimization mark bit ]
-// [initialization state ]
-// [initializing thread ]
-// [Java vtable length ]
-// [oop map cache (stack maps) ]
+// InstanceKlass embedded field layout (after declared fields):
// [EMBEDDED Java vtable ] size in words = vtable_len
// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
// The embedded nonstatic oop-map blocks are short pairs (offset, length)
@@ -1031,16 +1003,16 @@
// Static methods that are used to implement member methods where an exposed this pointer
// is needed due to possible GCs
- static bool link_class_impl (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
- static bool verify_code (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
- static void initialize_impl (instanceKlassHandle this_oop, TRAPS);
- static void eager_initialize_impl (instanceKlassHandle this_oop);
- static void set_initialization_state_and_notify_impl (instanceKlassHandle this_oop, ClassState state, TRAPS);
- static void call_class_initializer_impl (instanceKlassHandle this_oop, TRAPS);
- static Klass* array_klass_impl (instanceKlassHandle this_oop, bool or_null, int n, TRAPS);
- static void do_local_static_fields_impl (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS);
+ static bool link_class_impl (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
+ static bool verify_code (instanceKlassHandle this_k, bool throw_verifyerror, TRAPS);
+ static void initialize_impl (instanceKlassHandle this_k, TRAPS);
+ static void eager_initialize_impl (instanceKlassHandle this_k);
+ static void set_initialization_state_and_notify_impl (instanceKlassHandle this_k, ClassState state, TRAPS);
+ static void call_class_initializer_impl (instanceKlassHandle this_k, TRAPS);
+ static Klass* array_klass_impl (instanceKlassHandle this_k, bool or_null, int n, TRAPS);
+ static void do_local_static_fields_impl (instanceKlassHandle this_k, void f(fieldDescriptor* fd, TRAPS), TRAPS);
/* jni_id_for_impl for jfieldID only */
- static JNIid* jni_id_for_impl (instanceKlassHandle this_oop, int offset);
+ static JNIid* jni_id_for_impl (instanceKlassHandle this_k, int offset);
// Returns the array class for the n'th dimension
Klass* array_klass_impl(bool or_null, int n, TRAPS);
--- a/hotspot/src/share/vm/oops/klass.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -334,19 +334,11 @@
}
-Klass* Klass::subklass() const {
- return _subklass == NULL ? NULL : _subklass;
-}
-
InstanceKlass* Klass::superklass() const {
assert(super() == NULL || super()->oop_is_instance(), "must be instance klass");
return _super == NULL ? NULL : InstanceKlass::cast(_super);
}
-Klass* Klass::next_sibling() const {
- return _next_sibling == NULL ? NULL : _next_sibling;
-}
-
void Klass::set_subklass(Klass* s) {
assert(s != this, "sanity check");
_subklass = s;
@@ -365,7 +357,7 @@
assert((!super->is_interface() // interfaces cannot be supers
&& (super->superklass() == NULL || !is_interface())),
"an interface can only be a subklass of Object");
- Klass* prev_first_subklass = super->subklass_oop();
+ Klass* prev_first_subklass = super->subklass();
if (prev_first_subklass != NULL) {
// set our sibling to be the superklass' previous first subklass
set_next_sibling(prev_first_subklass);
@@ -405,7 +397,7 @@
assert(current->is_loader_alive(is_alive), "just checking, this should be live");
// Find and set the first alive subklass
- Klass* sub = current->subklass_oop();
+ Klass* sub = current->subklass();
while (sub != NULL && !sub->is_loader_alive(is_alive)) {
#ifndef PRODUCT
if (TraceClassUnloading && WizardMode) {
@@ -413,7 +405,7 @@
tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name());
}
#endif
- sub = sub->next_sibling_oop();
+ sub = sub->next_sibling();
}
current->set_subklass(sub);
if (sub != NULL) {
@@ -421,13 +413,13 @@
}
// Find and set the first alive sibling
- Klass* sibling = current->next_sibling_oop();
+ Klass* sibling = current->next_sibling();
while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
if (TraceClassUnloading && WizardMode) {
ResourceMark rm;
tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name());
}
- sibling = sibling->next_sibling_oop();
+ sibling = sibling->next_sibling();
}
current->set_next_sibling(sibling);
if (sibling != NULL) {
--- a/hotspot/src/share/vm/oops/klass.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -56,34 +56,6 @@
// actual type. (See oop.inline.hpp for some of the forwarding code.)
// ALL FUNCTIONS IMPLEMENTING THIS DISPATCH ARE PREFIXED WITH "oop_"!
-// Klass layout:
-// [C++ vtbl ptr ] (contained in Metadata)
-// [layout_helper ]
-// [super_check_offset ] for fast subtype checks
-// [name ]
-// [secondary_super_cache] for fast subtype checks
-// [secondary_supers ] array of 2ndary supertypes
-// [primary_supers 0]
-// [primary_supers 1]
-// [primary_supers 2]
-// ...
-// [primary_supers 7]
-// [java_mirror ]
-// [super ]
-// [subklass ] first subclass
-// [next_sibling ] link to chain additional subklasses
-// [next_link ]
-// [class_loader_data]
-// [modifier_flags]
-// [access_flags ]
-// [last_biased_lock_bulk_revocation_time] (64 bits)
-// [prototype_header]
-// [biased_lock_revocation_count]
-// [_modified_oops]
-// [_accumulated_modified_oops]
-// [trace_id]
-
-
// Forward declarations.
template <class T> class Array;
template <class T> class GrowableArray;
@@ -257,9 +229,9 @@
// Use InstanceKlass::contains_field_offset to classify field offsets.
// sub/superklass links
+ Klass* subklass() const { return _subklass; }
+ Klass* next_sibling() const { return _next_sibling; }
InstanceKlass* superklass() const;
- Klass* subklass() const;
- Klass* next_sibling() const;
void append_to_sibling_list(); // add newly created receiver to superklass' subklass list
void set_next_link(Klass* k) { _next_link = k; }
@@ -281,8 +253,6 @@
bool has_accumulated_modified_oops() { return _accumulated_modified_oops == 1; }
protected: // internal accessors
- Klass* subklass_oop() const { return _subklass; }
- Klass* next_sibling_oop() const { return _next_sibling; }
void set_subklass(Klass* s);
void set_next_sibling(Klass* s);
--- a/hotspot/src/share/vm/oops/method.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -577,12 +577,12 @@
}
-objArrayHandle Method::resolved_checked_exceptions_impl(Method* this_oop, TRAPS) {
- int length = this_oop->checked_exceptions_length();
+objArrayHandle Method::resolved_checked_exceptions_impl(Method* method, TRAPS) {
+ int length = method->checked_exceptions_length();
if (length == 0) { // common case
return objArrayHandle(THREAD, Universe::the_empty_class_klass_array());
} else {
- methodHandle h_this(THREAD, this_oop);
+ methodHandle h_this(THREAD, method);
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle()));
objArrayHandle mirrors (THREAD, m_oop);
for (int i = 0; i < length; i++) {
--- a/hotspot/src/share/vm/oops/method.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/oops/method.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -40,50 +40,15 @@
// A Method represents a Java method.
//
-// Memory layout (each line represents a word). Note that most applications load thousands of methods,
-// so keeping the size of this structure small has a big impact on footprint.
-//
-// The actual bytecodes are inlined after the end of the Method struct.
-//
-// There are bits in the access_flags telling whether inlined tables are present.
-// Note that accessing the line number and local variable tables is not performance critical at all.
-// Accessing the checked exceptions table is used by reflection, so we put that last to make access
-// to it fast.
-//
-// The line number table is compressed and inlined following the byte codes. It is found as the first
-// byte following the byte codes. The checked exceptions table and the local variable table are inlined
-// after the line number table, and indexed from the end of the method. We do not compress the checked
-// exceptions table since the average length is less than 2, and do not bother to compress the local
-// variable table either since it is mostly absent.
-//
-// Note that native_function and signature_handler has to be at fixed offsets (required by the interpreter)
+// Note that most applications load thousands of methods, so keeping the size of this
+// class small has a big impact on footprint.
//
-// |------------------------------------------------------|
-// | header |
-// | klass |
-// |------------------------------------------------------|
-// | ConstMethod* (metadata) |
-// |------------------------------------------------------|
-// | MethodData* (metadata) |
-// | MethodCounters |
-// |------------------------------------------------------|
-// | access_flags |
-// | vtable_index |
-// |------------------------------------------------------|
-// | result_index (C++ interpreter only) |
-// |------------------------------------------------------|
-// | method_size | intrinsic_id | flags |
-// |------------------------------------------------------|
-// | code (pointer) |
-// | i2i (pointer) |
-// | adapter (pointer) |
-// | from_compiled_entry (pointer) |
-// | from_interpreted_entry (pointer) |
-// |------------------------------------------------------|
-// | native_function (present only if native) |
-// | signature_handler (present only if native) |
-// |------------------------------------------------------|
-
+// Note that native_function and signature_handler have to be at fixed offsets
+// (required by the interpreter)
+//
+// Method embedded field layout (after declared fields):
+// [EMBEDDED native_function (present only if native) ]
+// [EMBEDDED signature_handler (present only if native) ]
class CheckedExceptionElement;
class LocalVariableTableElement;
@@ -661,7 +626,7 @@
// Static methods that are used to implement member methods where an exposed this pointer
// is needed due to possible GCs
- static objArrayHandle resolved_checked_exceptions_impl(Method* this_oop, TRAPS);
+ static objArrayHandle resolved_checked_exceptions_impl(Method* method, TRAPS);
// Returns the byte code index from the byte code pointer
int bci_from(address bcp) const;
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -1020,19 +1020,12 @@
}
if (owning_thread != NULL) { // monitor is owned
- if ((address)owning_thread == owner) {
- // the owner field is the JavaThread *
- assert(mon != NULL,
- "must have heavyweight monitor with JavaThread * owner");
- ret.entry_count = mon->recursions() + 1;
- } else {
- // The owner field is the Lock word on the JavaThread's stack
- // so the recursions field is not valid. We have to count the
- // number of recursive monitor entries the hard way. We pass
- // a handle to survive any GCs along the way.
- ResourceMark rm;
- ret.entry_count = count_locked_objects(owning_thread, hobj);
- }
+ // The recursions field of a monitor does not reflect recursions
+ // as lightweight locks before inflating the monitor are not included.
+ // We have to count the number of recursive monitor entries the hard way.
+ // We pass a handle to survive any GCs along the way.
+ ResourceMark rm;
+ ret.entry_count = count_locked_objects(owning_thread, hobj);
}
// implied else: entry_count == 0
}
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -1903,24 +1903,22 @@
// check if do gclog rotation
// +UseGCLogFileRotation is a must,
// no gc log rotation when log file not supplied or
-// NumberOfGCLogFiles is 0, or GCLogFileSize is 0
+// NumberOfGCLogFiles is 0
void check_gclog_consistency() {
if (UseGCLogFileRotation) {
- if ((Arguments::gc_log_filename() == NULL) ||
- (NumberOfGCLogFiles == 0) ||
- (GCLogFileSize == 0)) {
+ if ((Arguments::gc_log_filename() == NULL) || (NumberOfGCLogFiles == 0)) {
jio_fprintf(defaultStream::output_stream(),
- "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files> -XX:GCLogFileSize=<num_of_size>[k|K|m|M|g|G]\n"
- "where num_of_file > 0 and num_of_size > 0\n"
+ "To enable GC log rotation, use -Xloggc:<filename> -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<num_of_files>\n"
+ "where num_of_file > 0\n"
"GC log rotation is turned off\n");
UseGCLogFileRotation = false;
}
}
- if (UseGCLogFileRotation && GCLogFileSize < 8*K) {
- FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
- jio_fprintf(defaultStream::output_stream(),
- "GCLogFileSize changed to minimum 8K\n");
+ if (UseGCLogFileRotation && (GCLogFileSize != 0) && (GCLogFileSize < 8*K)) {
+ FLAG_SET_CMDLINE(uintx, GCLogFileSize, 8*K);
+ jio_fprintf(defaultStream::output_stream(),
+ "GCLogFileSize changed to minimum 8K\n");
}
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -2423,9 +2423,9 @@
"Number of gclog files in rotation " \
"(default: 0, no rotation)") \
\
- product(uintx, GCLogFileSize, 0, \
- "GC log file size (default: 0 bytes, no rotation). " \
- "It requires UseGCLogFileRotation") \
+ product(uintx, GCLogFileSize, 8*K, \
+ "GC log file size, requires UseGCLogFileRotation. " \
+ "Set to 0 to only trigger rotation via jcmd") \
\
/* JVMTI heap profiling */ \
\
--- a/hotspot/src/share/vm/runtime/safepoint.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -535,7 +535,7 @@
// rotate log files?
if (UseGCLogFileRotation) {
- gclog_or_tty->rotate_log();
+ gclog_or_tty->rotate_log(false);
}
if (MemTracker::is_on()) {
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -96,6 +96,7 @@
template(JFRCheckpoint) \
template(Exit) \
template(LinuxDllLoad) \
+ template(RotateGCLog) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@@ -399,4 +400,15 @@
void doit();
};
+
+class VM_RotateGCLog: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_RotateGCLog(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_RotateGCLog; }
+ void doit() { gclog_or_tty->rotate_log(true, _out); }
+};
+
#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -55,6 +55,7 @@
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
#endif // INCLUDE_SERVICES
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
@@ -659,3 +660,13 @@
os::print_dll_info(output());
output()->cr();
}
+
+void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) {
+ if (UseGCLogFileRotation) {
+ VM_RotateGCLog rotateop(output());
+ VMThread::execute(&rotateop);
+ } else {
+ output()->print_cr("Target VM does not support GC log file rotation.");
+ }
+}
+
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -383,4 +383,21 @@
virtual void execute(DCmdSource source, TRAPS);
};
+class RotateGCLogDCmd : public DCmd {
+public:
+ RotateGCLogDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() { return "GC.rotate_log"; }
+ static const char* description() {
+ return "Force the GC log file to be rotated.";
+ }
+ static const char* impact() { return "Low"; }
+ virtual void execute(DCmdSource source, TRAPS);
+ static int num_arguments() { return 0; }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "control", NULL};
+ return p;
+ }
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/src/share/vm/utilities/debug.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, 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
@@ -243,7 +243,6 @@
// out of shared space reporting
enum SharedSpaceType {
- SharedPermGen,
SharedReadOnly,
SharedReadWrite,
SharedMiscData
--- a/hotspot/src/share/vm/utilities/ostream.cpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp Sun Mar 30 03:29:48 2014 -0700
@@ -662,13 +662,13 @@
// write to gc log file at safepoint. If in future, changes made for mutator threads or
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized.
-void gcLogFileStream::rotate_log() {
+void gcLogFileStream::rotate_log(bool force, outputStream* out) {
char time_msg[FILENAMEBUFLEN];
char time_str[EXTRACHARLEN];
char current_file_name[FILENAMEBUFLEN];
char renamed_file_name[FILENAMEBUFLEN];
- if (_bytes_written < (jlong)GCLogFileSize) {
+ if (!should_rotate(force)) {
return;
}
@@ -685,6 +685,11 @@
jio_snprintf(time_msg, sizeof(time_msg), "File %s rotated at %s\n",
_file_name, os::local_time_string((char *)time_str, sizeof(time_str)));
write(time_msg, strlen(time_msg));
+
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
dump_loggc_header();
return;
}
@@ -706,12 +711,18 @@
_file_name, _cur_file_num);
jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num);
- jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the"
- " maximum size. Saved as %s\n",
- os::local_time_string((char *)time_str, sizeof(time_str)),
- renamed_file_name);
+
+ const char* msg = force ? "GC log rotation request has been received."
+ : "GC log file has reached the maximum size.";
+ jio_snprintf(time_msg, sizeof(time_msg), "%s %s Saved as %s\n",
+ os::local_time_string((char *)time_str, sizeof(time_str)),
+ msg, renamed_file_name);
write(time_msg, strlen(time_msg));
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
fclose(_file);
_file = NULL;
@@ -752,6 +763,11 @@
os::local_time_string((char *)time_str, sizeof(time_str)),
current_file_name);
write(time_msg, strlen(time_msg));
+
+ if (out != NULL) {
+ out->print(time_msg);
+ }
+
dump_loggc_header();
// remove the existing file
if (access(current_file_name, F_OK) == 0) {
--- a/hotspot/src/share/vm/utilities/ostream.hpp Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.hpp Sun Mar 30 03:29:48 2014 -0700
@@ -115,7 +115,7 @@
// flushing
virtual void flush() {}
virtual void write(const char* str, size_t len) = 0;
- virtual void rotate_log() {} // GC log rotation
+ virtual void rotate_log(bool force, outputStream* out = NULL) {} // GC log rotation
virtual ~outputStream() {} // close properly on deletion
void dec_cr() { dec(); cr(); }
@@ -240,8 +240,14 @@
gcLogFileStream(const char* file_name);
~gcLogFileStream();
virtual void write(const char* c, size_t len);
- virtual void rotate_log();
+ virtual void rotate_log(bool force, outputStream* out = NULL);
void dump_loggc_header();
+
+ /* If "force" sets true, force log file rotation from outside JVM */
+ bool should_rotate(bool force) {
+ return force ||
+ ((GCLogFileSize != 0) && ((uintx)_bytes_written >= GCLogFileSize));
+ }
};
#ifndef PRODUCT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/TestGCLogRotationViaJcmd.java Sun Mar 30 03:29:48 2014 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 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 TestGCLogRotationViaJcmd.java
+ * @bug 7090324
+ * @summary test for gc log rotation via jcmd
+ * @library /testlibrary
+ * @run main/othervm -Xloggc:test.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 TestGCLogRotationViaJcmd
+ *
+ */
+import com.oracle.java.testlibrary.*;
+import java.io.File;
+import java.io.FilenameFilter;
+
+public class TestGCLogRotationViaJcmd {
+
+ static final File currentDirectory = new File(".");
+ static final String LOG_FILE_NAME = "test.log";
+ static final int NUM_LOGS = 3;
+
+ static FilenameFilter logFilter = new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith(LOG_FILE_NAME);
+ }
+ };
+
+ public static void main(String[] args) throws Exception {
+ // Grab the pid from the current java process
+ String pid = Integer.toString(ProcessTools.getProcessId());
+
+ // Create a JDKToolLauncher
+ JDKToolLauncher jcmd = JDKToolLauncher.create("jcmd")
+ .addToolArg(pid)
+ .addToolArg("GC.rotate_log");
+
+ for (int times = 1; times < NUM_LOGS; times++) {
+ // Run jcmd <pid> GC.rotate_log
+ ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand());
+
+ // Make sure we didn't crash
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ }
+
+ // GC log check
+ File[] logs = currentDirectory.listFiles(logFilter);
+ if (logs.length != NUM_LOGS) {
+ throw new Error("There are only " + logs.length
+ + " logs instead " + NUM_LOGS);
+ }
+
+ }
+
+}
+
--- a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java Sun Mar 30 03:29:48 2014 -0700
@@ -26,10 +26,7 @@
* @key nmt jcmd
* @summary Verify that jcmd correctly reports that NMT is not enabled
* @library /testlibrary
- * First run without enabling NMT
- * @run main/othervm JcmdWithNMTDisabled
- * Then run with explicitly disabling NMT, should not be any difference
- * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled
+ * @run main JcmdWithNMTDisabled 1
*/
import com.oracle.java.testlibrary.*;
@@ -39,6 +36,27 @@
static String pid;
public static void main(String args[]) throws Exception {
+
+ // This test explicitly needs to be run with the exact command lines below, not passing on
+ // arguments from the parent VM is a conscious choice to avoid NMT being turned on.
+ if (args.length > 0) {
+ ProcessBuilder pb;
+ OutputAnalyzer output;
+ String testjdkPath = System.getProperty("test.jdk");
+
+ // First run without enabling NMT
+ pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "JcmdWithNMTDisabled");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ // Then run with explicitly disabling NMT, should not be any difference
+ pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "-XX:NativeMemoryTracking=off", "JcmdWithNMTDisabled");
+ output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+
+ return;
+ }
+
// Grab my own PID
pid = Integer.toString(ProcessTools.getProcessId());
--- a/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java Fri Mar 28 09:15:41 2014 -0700
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsWriteError.java Sun Mar 30 03:29:48 2014 -0700
@@ -22,7 +22,6 @@
*/
/*
- * @ignore 8032222
* @test CdsWriteError
* @summary Test how VM handles situation when it is impossible to write the
* CDS archive. VM is expected to exit gracefully and display the
@@ -46,6 +45,12 @@
return;
}
+ // This test has been unstable for Mac OSx (see JDK-8032222)
+ if (Platform.isOSX()) {
+ System.out.println("This test is skipped on Mac");
+ return;
+ }
+
String folderName = "tmp";
String fileName = folderName + File.separator + "empty.jsa";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/8036666/GetObjectLockCount.java Sun Mar 30 03:29:48 2014 -0700
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2014 SAP AG. 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.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.jdi.AbsentInformationException;
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.LocalVariable;
+import com.sun.jdi.Location;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.Connector.Argument;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.VMStartException;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.ClassPrepareEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.EventQueue;
+import com.sun.jdi.event.EventSet;
+import com.sun.jdi.event.VMDeathEvent;
+import com.sun.jdi.event.VMDisconnectEvent;
+import com.sun.jdi.event.VMStartEvent;
+import com.sun.jdi.request.BreakpointRequest;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.EventRequestManager;
+
+
+/*
+ * @test GetObjectLockCount.java
+ * @bug 8036666
+ * @key regression
+ * @summary verify jvm returns correct lock recursion count
+ * @run compile -g RecursiveObjectLock.java
+ * @run main/othervm GetObjectLockCount
+ * @author axel.siebenborn@sap.com
+ */
+
+public class GetObjectLockCount {
+
+ public static final String CLASS_NAME = "RecursiveObjectLock";
+ public static final String METHOD_NAME = "breakpoint1";
+ public static final String ARGUMENTS = "";
+
+
+ /**
+ * Find a com.sun.jdi.CommandLineLaunch connector
+ */
+ static LaunchingConnector findLaunchingConnector() {
+ List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
+ Iterator <Connector> iter = connectors.iterator();
+ while (iter.hasNext()) {
+ Connector connector = iter.next();
+ if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) {
+ return (LaunchingConnector)connector;
+ }
+ }
+ throw new Error("No launching connector");
+ }
+
+ static VirtualMachine launchTarget(String mainArgs) {
+ LaunchingConnector connector = findLaunchingConnector();
+ Map<String, Argument> arguments = connectorArguments(connector, mainArgs);
+ try {
+ return (VirtualMachine) connector.launch(arguments);
+ } catch (IOException exc) {
+ throw new Error("Unable to launch target VM: " + exc);
+ } catch (IllegalConnectorArgumentsException exc) {
+ throw new Error("Internal error: " + exc);
+ } catch (VMStartException exc) {
+ throw new Error("Target VM failed to initialize: " +
+ exc.getMessage());
+ }
+ }
+ /**
+ * Return the launching connector's arguments.
+ */
+ static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
+ Map<String,Connector.Argument> arguments = connector.defaultArguments();
+
+ Connector.Argument mainArg = (Connector.Argument)arguments.get("main");
+ if (mainArg == null) {
+ throw new Error("Bad launching connector");
+ }
+ mainArg.setValue(mainArgs);
+
+ Connector.Argument optionsArg = (Connector.Argument)arguments.get("options");
+ if (optionsArg == null) {
+ throw new Error("Bad launching connector");
+ }
+ optionsArg.setValue(ARGUMENTS);
+ return arguments;
+ }
+
+ private static void addClassWatch(VirtualMachine vm) {
+ EventRequestManager erm = vm.eventRequestManager();
+ ClassPrepareRequest classPrepareRequest = erm
+ .createClassPrepareRequest();
+ classPrepareRequest.addClassFilter(CLASS_NAME);
+ classPrepareRequest.setEnabled(true);
+ }
+
+ private static void addBreakpoint(VirtualMachine vm, ReferenceType refType) {
+ Location breakpointLocation = null;
+ List<Location> locs;
+ try {
+ locs = refType.allLineLocations();
+ for (Location loc: locs) {
+ if (loc.method().name().equals(METHOD_NAME)) {
+ breakpointLocation = loc;
+ break;
+ }
+ }
+ } catch (AbsentInformationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (breakpointLocation != null) {
+ EventRequestManager evtReqMgr = vm.eventRequestManager();
+ BreakpointRequest bReq = evtReqMgr.createBreakpointRequest(breakpointLocation);
+ bReq.setSuspendPolicy(BreakpointRequest.SUSPEND_ALL);
+ bReq.enable();
+ }
+ }
+
+ /**
+ * @param args
+ * @throws InterruptedException
+ */
+ public static void main(String[] args) throws InterruptedException {
+
+ VirtualMachine vm = launchTarget(CLASS_NAME);
+
+ // process events
+ EventQueue eventQueue = vm.eventQueue();
+ // resume the vm
+ boolean launched = false;
+
+ while (!launched) {
+ EventSet eventSet = eventQueue.remove();
+ for (Event event : eventSet) {
+ if (event instanceof VMStartEvent) {
+ System.out.println("Vm launched");
+ // set watch field on already loaded classes
+ List<ReferenceType> referenceTypes = vm.classesByName(CLASS_NAME);
+ for (ReferenceType refType : referenceTypes) {
+ System.out.println("Found Class");
+ addBreakpoint(vm, refType);
+ }
+
+ // watch for loaded classes
+ addClassWatch(vm);
+ vm.resume();
+ launched = true;
+ }
+ }
+ }
+
+ Process process = vm.process();
+
+ // Copy target's output and error to our output and error.
+ Thread outThread = new StreamRedirectThread("out reader", process.getInputStream());
+ Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream());
+
+ int recursionCount = -1;
+
+ errThread.start();
+ outThread.start();
+ boolean connected = true;
+ while (connected) {
+ EventSet eventSet = eventQueue.remove();
+ for (Event event : eventSet) {
+ if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) {
+ // exit
+ connected = false;
+ }
+ else if (event instanceof ClassPrepareEvent) {
+ // watch field on loaded class
+ System.out.println("ClassPrepareEvent");
+ ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event;
+ ReferenceType refType = classPrepEvent.referenceType();
+ addBreakpoint(vm, refType);
+ } else if (event instanceof BreakpointEvent) {
+ recursionCount = getLockRecursions(vm);
+ System.out.println("resume...");
+ }
+ }
+ eventSet.resume();
+ }
+ // Shutdown begins when event thread terminates
+ try {
+ errThread.join(); // Make sure output is forwarded
+ outThread.join();
+ } catch (InterruptedException e) {
+ // we don't interrupt
+ e.printStackTrace();
+ }
+ if (recursionCount != 3) {
+ throw new AssertionError("recursions: expected 3, but was " + recursionCount);
+ }
+ }
+
+ public static int getLockRecursions(VirtualMachine vm) {
+ List <ThreadReference> threads = vm.allThreads();
+ for (ThreadReference thread : threads) {
+ if (thread.name().equals("main")) {
+
+ System.out.println("Found main thread.");
+ try{
+ StackFrame frame = thread.frame(3);
+ return frame.thisObject().entryCount();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ System.out.println("Main thread not found!");
+ }
+ return -1;
+ }
+}
+
+class StreamRedirectThread extends Thread {
+
+ private final BufferedReader in;
+
+ private static final int BUFFER_SIZE = 2048;
+
+ /**
+ * Set up for copy.
+ * @param name Name of the thread
+ * @param in Stream to copy from
+ */
+ StreamRedirectThread(String name, InputStream in) {
+ super(name);
+ this.in = new BufferedReader(new InputStreamReader(in));
+ }
+
+ /**
+ * Copy.
+ */
+ public void run() {
+ try {
+ String line;
+ while ((line = in.readLine ()) != null) {
+ System.out.println("testvm: " + line);
+ }
+ System.out.flush();
+ } catch(IOException exc) {
+ System.err.println("Child I/O Transfer - " + exc);
+ exc.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/8036666/RecursiveObjectLock.java Sun Mar 30 03:29:48 2014 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 SAP AG. 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 RecursiveObjectLock {
+
+ public void testMethod() {
+ synchronized (this) {
+ nestedLock1();
+ }
+ }
+
+ public void nestedLock1() {
+ synchronized (this) {
+ nestedLock2();
+ }
+ }
+
+ public void nestedLock2() {
+ synchronized (this) {
+ callWait();
+ }
+ }
+
+ public void callWait(){
+ try {
+ this.wait(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ breakpoint1();
+ }
+
+ public static void breakpoint1() {
+ // purpose: hold a breakpoint
+ }
+
+ public static void main(String[] args) {
+ RecursiveObjectLock ro = new RecursiveObjectLock();
+ ro.testMethod();
+ System.out.println("ready");
+ }
+
+}