mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-23 03:48:13 +00:00
Merge
This commit is contained in:
commit
6f19e14049
@ -34,7 +34,6 @@
|
||||
|
||||
define_pd_global(bool, ConvertSleepToYield, true);
|
||||
define_pd_global(bool, ShareVtableStubs, true);
|
||||
define_pd_global(bool, CountInterpCalls, true);
|
||||
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
|
||||
|
||||
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
|
||||
@ -61,8 +60,6 @@ define_pd_global(intx, StackRedPages, 1);
|
||||
|
||||
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
|
||||
|
||||
define_pd_global(intx, PreInflateSpin, 10);
|
||||
|
||||
define_pd_global(bool, RewriteBytecodes, true);
|
||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -869,7 +869,7 @@ void InterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
|
||||
// native method than the typical interpreter frame setup.
|
||||
address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// r1: Method*
|
||||
// rscratch1: sender sp
|
||||
@ -1307,7 +1307,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
//
|
||||
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// rscratch1: sender sp
|
||||
address entry_point = __ pc();
|
||||
|
||||
@ -47,8 +47,6 @@ define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
define_pd_global(intx, InlineFrequencyCount, 100);
|
||||
define_pd_global(intx, InlineSmallCode, 1500);
|
||||
|
||||
define_pd_global(intx, PreInflateSpin, 10);
|
||||
|
||||
// Flags for template interpreter.
|
||||
define_pd_global(bool, RewriteBytecodes, true);
|
||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||
|
||||
@ -668,7 +668,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
|
||||
address entry = __ pc();
|
||||
|
||||
const bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
const bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Allocate a new frame that represents the native callee (i2n frame).
|
||||
@ -1118,7 +1118,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// Generic interpreted method entry to (asm) interpreter.
|
||||
//
|
||||
address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
address entry = __ pc();
|
||||
// Generate the code to allocate the interpreter stack frame.
|
||||
Register Rsize_of_parameters = R4_ARG2, // Written by generate_fixed_frame.
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
define_pd_global(bool, DontYieldALot, true); // yield no more than 100 times per second
|
||||
define_pd_global(bool, ConvertSleepToYield, false); // do not convert sleep(0) to yield. Helps GUI
|
||||
define_pd_global(bool, ShareVtableStubs, false); // improves performance markedly for mtrt and compress
|
||||
define_pd_global(bool, CountInterpCalls, false); // not implemented in the interpreter
|
||||
define_pd_global(bool, NeedsDeoptSuspend, true); // register window machines need this
|
||||
|
||||
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
|
||||
@ -67,8 +66,6 @@ define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
|
||||
define_pd_global(intx, StackYellowPages, 2);
|
||||
define_pd_global(intx, StackRedPages, 1);
|
||||
|
||||
define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center
|
||||
|
||||
define_pd_global(bool, RewriteBytecodes, true);
|
||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -801,7 +801,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// the following temporary registers are used during frame creation
|
||||
const Register Gtmp1 = G3_scratch ;
|
||||
const Register Gtmp2 = G1_scratch;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// make sure registers are different!
|
||||
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
|
||||
@ -1225,7 +1225,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
address entry = __ pc();
|
||||
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// the following temporary registers are used during frame creation
|
||||
const Register Gtmp1 = G3_scratch ;
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
|
||||
define_pd_global(bool, ConvertSleepToYield, true);
|
||||
define_pd_global(bool, ShareVtableStubs, true);
|
||||
define_pd_global(bool, CountInterpCalls, true);
|
||||
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
|
||||
|
||||
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
|
||||
@ -66,8 +65,6 @@ define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(
|
||||
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
|
||||
#endif // AMD64
|
||||
|
||||
define_pd_global(intx, PreInflateSpin, 10);
|
||||
|
||||
define_pd_global(bool, RewriteBytecodes, true);
|
||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||
|
||||
|
||||
@ -1781,6 +1781,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
|
||||
} else
|
||||
if ((EmitSync & 128) == 0) { // avoid ST-before-CAS
|
||||
// register juggle because we need tmpReg for cmpxchgptr below
|
||||
movptr(scrReg, boxReg);
|
||||
movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2]
|
||||
|
||||
@ -1814,7 +1815,10 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
|
||||
}
|
||||
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
|
||||
movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3
|
||||
// If we weren't able to swing _owner from NULL to the BasicLock
|
||||
// then take the slow path.
|
||||
jccb (Assembler::notZero, DONE_LABEL);
|
||||
// update _owner from BasicLock to thread
|
||||
get_thread (scrReg); // beware: clobbers ICCs
|
||||
movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg);
|
||||
xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success
|
||||
@ -2083,6 +2087,9 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
xorptr(boxReg, boxReg); // box is really EAX
|
||||
if (os::is_MP()) { lock(); }
|
||||
cmpxchgptr(rsp, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
|
||||
// There's no successor so we tried to regrab the lock with the
|
||||
// placeholder value. If that didn't work, then another thread
|
||||
// grabbed the lock so we're done (and exit was a success).
|
||||
jccb (Assembler::notEqual, LSuccess);
|
||||
// Since we're low on registers we installed rsp as a placeholding in _owner.
|
||||
// Now install Self over rsp. This is safe as we're transitioning from
|
||||
@ -2190,6 +2197,9 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
|
||||
movptr(boxReg, (int32_t)NULL_WORD);
|
||||
if (os::is_MP()) { lock(); }
|
||||
cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
|
||||
// There's no successor so we tried to regrab the lock.
|
||||
// If that didn't work, then another thread grabbed the
|
||||
// lock so we're done (and exit was a success).
|
||||
jccb (Assembler::notEqual, LSuccess);
|
||||
// Intentional fall-through into slow-path
|
||||
|
||||
|
||||
@ -2456,7 +2456,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// allocate space for the code
|
||||
ResourceMark rm;
|
||||
// setup code generation tools
|
||||
CodeBuffer buffer("deopt_blob", 1024, 1024);
|
||||
// note: the buffer code size must account for StackShadowPages=50
|
||||
CodeBuffer buffer("deopt_blob", 1536, 1024);
|
||||
MacroAssembler* masm = new MacroAssembler(&buffer);
|
||||
int frame_size_in_words;
|
||||
OopMap* map = NULL;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -849,7 +849,7 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
|
||||
|
||||
address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// rbx,: Method*
|
||||
// rsi: sender sp
|
||||
@ -1265,7 +1265,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
//
|
||||
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// rbx,: Method*
|
||||
// rsi: sender sp
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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
|
||||
@ -809,7 +809,7 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
|
||||
// native method than the typical interpreter frame setup.
|
||||
address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// rbx: Method*
|
||||
// r13: sender sp
|
||||
@ -1256,7 +1256,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
//
|
||||
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// determine code generation flags
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
|
||||
|
||||
// ebx: Method*
|
||||
// r13: sender sp
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
|
||||
define_pd_global(bool, ConvertSleepToYield, true);
|
||||
define_pd_global(bool, ShareVtableStubs, true);
|
||||
define_pd_global(bool, CountInterpCalls, true);
|
||||
define_pd_global(bool, NeedsDeoptSuspend, false);
|
||||
|
||||
define_pd_global(bool, ImplicitNullChecks, true);
|
||||
@ -45,7 +44,6 @@ define_pd_global(intx, CodeEntryAlignment, 32);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
define_pd_global(intx, InlineFrequencyCount, 100);
|
||||
define_pd_global(intx, InlineSmallCode, 1000 );
|
||||
define_pd_global(intx, PreInflateSpin, 10);
|
||||
|
||||
define_pd_global(intx, StackYellowPages, 2);
|
||||
define_pd_global(intx, StackRedPages, 1);
|
||||
|
||||
@ -3740,15 +3740,6 @@ void os::win32::initialize_system_info() {
|
||||
"stack size not a multiple of page size");
|
||||
|
||||
initialize_performance_counter();
|
||||
|
||||
// Win95/Win98 scheduler bug work-around. The Win95/98 scheduler is
|
||||
// known to deadlock the system, if the VM issues to thread operations with
|
||||
// a too high frequency, e.g., such as changing the priorities.
|
||||
// The 6000 seems to work well - no deadlocks has been notices on the test
|
||||
// programs that we have seen experience this problem.
|
||||
if (!os::win32::is_nt()) {
|
||||
StarvationMonitorInterval = 6000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -75,6 +75,9 @@ ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
|
||||
{
|
||||
assert(h_m() != NULL, "no null method");
|
||||
|
||||
if (LogTouchedMethods) {
|
||||
h_m()->log_touched(Thread::current());
|
||||
}
|
||||
// These fields are always filled in in loaded methods.
|
||||
_flags = ciFlags(h_m()->access_flags());
|
||||
|
||||
|
||||
@ -2698,8 +2698,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
|
||||
// Inner class index
|
||||
u2 inner_class_info_index = cfs->get_u2_fast();
|
||||
check_property(
|
||||
inner_class_info_index == 0 ||
|
||||
valid_klass_reference_at(inner_class_info_index),
|
||||
valid_klass_reference_at(inner_class_info_index),
|
||||
"inner_class_info_index %u has bad constant type in class file %s",
|
||||
inner_class_info_index, CHECK_0);
|
||||
// Outer class index
|
||||
@ -5163,8 +5162,8 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu
|
||||
// The first non-signature thing better be a ')'
|
||||
if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) {
|
||||
length--;
|
||||
if (name->utf8_length() > 0 && name->byte_at(0) == '<') {
|
||||
// All internal methods must return void
|
||||
if (name == vmSymbols::object_initializer_name()) {
|
||||
// All "<init>" methods must return void
|
||||
if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) {
|
||||
return args_size;
|
||||
}
|
||||
|
||||
@ -58,14 +58,14 @@ Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS
|
||||
|
||||
if (DumpSharedSpaces) {
|
||||
// Allocate all symbols to CLD shared metaspace
|
||||
sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1);
|
||||
sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, PERM_REFCOUNT);
|
||||
} else if (c_heap) {
|
||||
// refcount starts as 1
|
||||
sym = new (len, THREAD) Symbol(name, len, 1);
|
||||
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
|
||||
} else {
|
||||
// Allocate to global arena
|
||||
sym = new (len, arena(), THREAD) Symbol(name, len, -1);
|
||||
sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
@ -2846,7 +2846,7 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
if (sig_stream.type() != T_VOID) {
|
||||
if (method_name == vmSymbols::object_initializer_name()) {
|
||||
// <init> method must have a void return type
|
||||
/* Unreachable? Class file parser verifies that methods with '<' have
|
||||
/* Unreachable? Class file parser verifies that <init> methods have
|
||||
* void return */
|
||||
verify_error(ErrorContext::bad_code(bci),
|
||||
"Return type must be void in <init> method");
|
||||
|
||||
@ -848,7 +848,7 @@ void EvacuateFollowersClosureGeneral::do_void() {
|
||||
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen,
|
||||
_scan_cur_or_nonheap,
|
||||
_scan_older);
|
||||
} while (!_gch->no_allocs_since_save_marks(true /* include_young */));
|
||||
} while (!_gch->no_allocs_since_save_marks());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ EvacuateFollowersClosure(GenCollectedHeap* gch,
|
||||
void DefNewGeneration::EvacuateFollowersClosure::do_void() {
|
||||
do {
|
||||
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
|
||||
} while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
|
||||
} while (!_gch->no_allocs_since_save_marks());
|
||||
}
|
||||
|
||||
DefNewGeneration::FastEvacuateFollowersClosure::
|
||||
@ -112,7 +112,7 @@ FastEvacuateFollowersClosure(GenCollectedHeap* gch,
|
||||
void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
|
||||
do {
|
||||
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
|
||||
} while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
|
||||
} while (!_gch->no_allocs_since_save_marks());
|
||||
guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ void DefNewGeneration::collect(bool full,
|
||||
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(false);
|
||||
|
||||
assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
|
||||
assert(gch->no_allocs_since_save_marks(),
|
||||
"save marks have not been newly set.");
|
||||
|
||||
// Not very pretty.
|
||||
@ -617,7 +617,7 @@ void DefNewGeneration::collect(bool full,
|
||||
&fsc_with_no_gc_barrier,
|
||||
&fsc_with_gc_barrier);
|
||||
|
||||
assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
|
||||
assert(gch->no_allocs_since_save_marks(),
|
||||
"save marks have not been newly set.");
|
||||
|
||||
{
|
||||
|
||||
@ -741,11 +741,9 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DEFN)
|
||||
|
||||
#undef GCH_SINCE_SAVE_MARKS_ITERATE_DEFN
|
||||
|
||||
bool GenCollectedHeap::no_allocs_since_save_marks(bool include_young) {
|
||||
if (include_young && !_young_gen->no_allocs_since_save_marks()) {
|
||||
return false;
|
||||
}
|
||||
return _old_gen->no_allocs_since_save_marks();
|
||||
bool GenCollectedHeap::no_allocs_since_save_marks() {
|
||||
return _young_gen->no_allocs_since_save_marks() &&
|
||||
_old_gen->no_allocs_since_save_marks();
|
||||
}
|
||||
|
||||
bool GenCollectedHeap::supports_inline_contig_alloc() const {
|
||||
|
||||
@ -436,7 +436,7 @@ public:
|
||||
|
||||
// Returns "true" iff no allocations have occurred since the last
|
||||
// call to "save_marks".
|
||||
bool no_allocs_since_save_marks(bool include_young);
|
||||
bool no_allocs_since_save_marks();
|
||||
|
||||
// Returns true if an incremental collection is likely to fail.
|
||||
// We optionally consult the young gen, if asked to do so;
|
||||
|
||||
@ -32,26 +32,32 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||
void markOopDesc::print_on(outputStream* st) const {
|
||||
if (is_marked()) {
|
||||
st->print(" marked(" INTPTR_FORMAT ")", value());
|
||||
} else if (has_monitor()) {
|
||||
// have to check has_monitor() before is_locked()
|
||||
st->print(" monitor(" INTPTR_FORMAT ")=", value());
|
||||
ObjectMonitor* mon = monitor();
|
||||
if (mon == NULL) {
|
||||
st->print("NULL (this should never be seen!)");
|
||||
} else {
|
||||
st->print("{count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT
|
||||
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
|
||||
mon->count(), mon->waiters(), mon->recursions(),
|
||||
p2i(mon->owner()));
|
||||
}
|
||||
} else if (is_locked()) {
|
||||
st->print(" locked(" INTPTR_FORMAT ")->", value());
|
||||
if (is_neutral()) {
|
||||
st->print("is_neutral");
|
||||
if (has_no_hash()) st->print(" no_hash");
|
||||
else st->print(" hash=" INTPTR_FORMAT, hash());
|
||||
if (has_no_hash()) {
|
||||
st->print(" no_hash");
|
||||
} else {
|
||||
st->print(" hash=" INTPTR_FORMAT, hash());
|
||||
}
|
||||
st->print(" age=%d", age());
|
||||
} else if (has_bias_pattern()) {
|
||||
st->print("is_biased");
|
||||
JavaThread* jt = biased_locker();
|
||||
st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
|
||||
} else if (has_monitor()) {
|
||||
ObjectMonitor* mon = monitor();
|
||||
if (mon == NULL)
|
||||
st->print("monitor=NULL");
|
||||
else {
|
||||
BasicLock * bl = (BasicLock *) mon->owner();
|
||||
st->print("monitor={count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
|
||||
mon->count(), mon->waiters(), mon->recursions(), p2i(bl));
|
||||
}
|
||||
} else {
|
||||
st->print("??");
|
||||
}
|
||||
|
||||
@ -422,6 +422,11 @@ MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
|
||||
if (!mh->init_method_counters(counters)) {
|
||||
MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
|
||||
}
|
||||
|
||||
if (LogTouchedMethods) {
|
||||
mh->log_touched(CHECK_NULL);
|
||||
}
|
||||
|
||||
return mh->method_counters();
|
||||
}
|
||||
|
||||
@ -2130,6 +2135,85 @@ void Method::collect_statistics(KlassSizeStats *sz) const {
|
||||
}
|
||||
#endif // INCLUDE_SERVICES
|
||||
|
||||
// LogTouchedMethods and PrintTouchedMethods
|
||||
|
||||
// TouchedMethodRecord -- we can't use a HashtableEntry<Method*> because
|
||||
// the Method may be garbage collected. Let's roll our own hash table.
|
||||
class TouchedMethodRecord : CHeapObj<mtTracing> {
|
||||
public:
|
||||
// It's OK to store Symbols here because they will NOT be GC'ed if
|
||||
// LogTouchedMethods is enabled.
|
||||
TouchedMethodRecord* _next;
|
||||
Symbol* _class_name;
|
||||
Symbol* _method_name;
|
||||
Symbol* _method_signature;
|
||||
};
|
||||
|
||||
static const int TOUCHED_METHOD_TABLE_SIZE = 20011;
|
||||
static TouchedMethodRecord** _touched_method_table = NULL;
|
||||
|
||||
void Method::log_touched(TRAPS) {
|
||||
|
||||
const int table_size = TOUCHED_METHOD_TABLE_SIZE;
|
||||
Symbol* my_class = klass_name();
|
||||
Symbol* my_name = name();
|
||||
Symbol* my_sig = signature();
|
||||
|
||||
unsigned int hash = my_class->identity_hash() +
|
||||
my_name->identity_hash() +
|
||||
my_sig->identity_hash();
|
||||
juint index = juint(hash) % table_size;
|
||||
|
||||
MutexLocker ml(TouchedMethodLog_lock, THREAD);
|
||||
if (_touched_method_table == NULL) {
|
||||
_touched_method_table = NEW_C_HEAP_ARRAY2(TouchedMethodRecord*, table_size,
|
||||
mtTracing, CURRENT_PC);
|
||||
memset(_touched_method_table, 0, sizeof(TouchedMethodRecord*)*table_size);
|
||||
}
|
||||
|
||||
TouchedMethodRecord* ptr = _touched_method_table[index];
|
||||
while (ptr) {
|
||||
if (ptr->_class_name == my_class &&
|
||||
ptr->_method_name == my_name &&
|
||||
ptr->_method_signature == my_sig) {
|
||||
return;
|
||||
}
|
||||
if (ptr->_next == NULL) break;
|
||||
ptr = ptr->_next;
|
||||
}
|
||||
TouchedMethodRecord* nptr = NEW_C_HEAP_OBJ(TouchedMethodRecord, mtTracing);
|
||||
my_class->set_permanent(); // prevent reclaimed by GC
|
||||
my_name->set_permanent();
|
||||
my_sig->set_permanent();
|
||||
nptr->_class_name = my_class;
|
||||
nptr->_method_name = my_name;
|
||||
nptr->_method_signature = my_sig;
|
||||
nptr->_next = NULL;
|
||||
|
||||
if (ptr == NULL) {
|
||||
// first
|
||||
_touched_method_table[index] = nptr;
|
||||
} else {
|
||||
ptr->_next = nptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Method::print_touched_methods(outputStream* out) {
|
||||
MutexLockerEx ml(Thread::current()->is_VM_thread() ? NULL : TouchedMethodLog_lock);
|
||||
out->print_cr("# Method::print_touched_methods version 1");
|
||||
if (_touched_method_table) {
|
||||
for (int i = 0; i < TOUCHED_METHOD_TABLE_SIZE; i++) {
|
||||
TouchedMethodRecord* ptr = _touched_method_table[i];
|
||||
while(ptr) {
|
||||
ptr->_class_name->print_symbol_on(out); out->print(".");
|
||||
ptr->_method_name->print_symbol_on(out); out->print(":");
|
||||
ptr->_method_signature->print_symbol_on(out); out->cr();
|
||||
ptr = ptr->_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verification
|
||||
|
||||
void Method::verify_on(outputStream* st) {
|
||||
|
||||
@ -625,6 +625,8 @@ class Method : public Metadata {
|
||||
#if INCLUDE_SERVICES
|
||||
void collect_statistics(KlassSizeStats *sz) const;
|
||||
#endif
|
||||
void log_touched(TRAPS);
|
||||
static void print_touched_methods(outputStream* out);
|
||||
|
||||
// interpreter support
|
||||
static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -96,12 +96,16 @@
|
||||
// TempNewSymbol (passed in as a parameter) so the reference count on its symbol
|
||||
// will be decremented when it goes out of scope.
|
||||
|
||||
|
||||
// This cannot be inherited from ResourceObj because it cannot have a vtable.
|
||||
// Since sometimes this is allocated from Metadata, pick a base allocation
|
||||
// type without virtual functions.
|
||||
class ClassLoaderData;
|
||||
|
||||
// Set _refcount to PERM_REFCOUNT to prevent the Symbol from being GC'ed.
|
||||
#ifndef PERM_REFCOUNT
|
||||
#define PERM_REFCOUNT -1
|
||||
#endif
|
||||
|
||||
// We separate the fields in SymbolBase from Symbol::_body so that
|
||||
// Symbol::size(int) can correctly calculate the space needed.
|
||||
class SymbolBase : public MetaspaceObj {
|
||||
@ -160,6 +164,13 @@ class Symbol : private SymbolBase {
|
||||
int refcount() const { return _refcount; }
|
||||
void increment_refcount();
|
||||
void decrement_refcount();
|
||||
// Set _refcount non zero to avoid being reclaimed by GC.
|
||||
void set_permanent() {
|
||||
assert(LogTouchedMethods, "Should not be called with LogTouchedMethods off");
|
||||
if (_refcount != PERM_REFCOUNT) {
|
||||
_refcount = PERM_REFCOUNT;
|
||||
}
|
||||
}
|
||||
|
||||
int byte_at(int index) const {
|
||||
assert(index >=0 && index < _length, "symbol index overflow");
|
||||
|
||||
@ -277,6 +277,8 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
|
||||
{ "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) },
|
||||
{ "ThreadSafetyMargin", JDK_Version::jdk(9), JDK_Version::jdk(10) },
|
||||
{ "LazyBootClassLoader", JDK_Version::jdk(9), JDK_Version::jdk(10) },
|
||||
{ "StarvationMonitorInterval", JDK_Version::jdk(9), JDK_Version::jdk(10) },
|
||||
{ "PreInflateSpin", JDK_Version::jdk(9), JDK_Version::jdk(10) },
|
||||
{ NULL, JDK_Version(0), JDK_Version(0) }
|
||||
};
|
||||
|
||||
|
||||
@ -1291,7 +1291,7 @@ public:
|
||||
experimental(intx, hashCode, 5, \
|
||||
"(Unstable) select hashCode generation algorithm") \
|
||||
\
|
||||
experimental(intx, WorkAroundNPTLTimedWaitHang, 1, \
|
||||
experimental(intx, WorkAroundNPTLTimedWaitHang, 0, \
|
||||
"(Unstable, Linux-specific) " \
|
||||
"avoid NPTL-FUTEX hang pthread_cond_timedwait") \
|
||||
\
|
||||
@ -2717,6 +2717,12 @@ public:
|
||||
develop(bool, EagerInitialization, false, \
|
||||
"Eagerly initialize classes if possible") \
|
||||
\
|
||||
diagnostic(bool, LogTouchedMethods, false, \
|
||||
"Log methods which have been ever touched in runtime") \
|
||||
\
|
||||
diagnostic(bool, PrintTouchedMethodsAtExit, false, \
|
||||
"Print all methods that have been ever touched in runtime") \
|
||||
\
|
||||
develop(bool, TraceMethodReplacement, false, \
|
||||
"Print when methods are replaced do to recompilation") \
|
||||
\
|
||||
@ -3282,9 +3288,6 @@ public:
|
||||
develop(intx, ProfilerNodeSize, 1024, \
|
||||
"Size in K to allocate for the Profile Nodes of each thread") \
|
||||
\
|
||||
product_pd(intx, PreInflateSpin, \
|
||||
"Number of times to spin wait before inflation") \
|
||||
\
|
||||
/* gc parameters */ \
|
||||
product(size_t, InitialHeapSize, 0, \
|
||||
"Initial heap size (in bytes); zero means use ergonomics") \
|
||||
@ -3725,9 +3728,6 @@ public:
|
||||
develop(intx, LongCompileThreshold, 50, \
|
||||
"Used with +TraceLongCompiles") \
|
||||
\
|
||||
product(intx, StarvationMonitorInterval, 200, \
|
||||
"Pause between each check (in milliseconds)") \
|
||||
\
|
||||
/* recompilation */ \
|
||||
product_pd(intx, CompileThreshold, \
|
||||
"number of interpreted method invocations before (re-)compiling") \
|
||||
@ -4080,9 +4080,6 @@ public:
|
||||
develop(bool, TraceDefaultMethods, false, \
|
||||
"Trace the default method processing steps") \
|
||||
\
|
||||
develop(bool, VerifyGenericSignatures, false, \
|
||||
"Abort VM on erroneous or inconsistent generic signatures") \
|
||||
\
|
||||
diagnostic(bool, WhiteBoxAPI, false, \
|
||||
"Enable internal testing APIs") \
|
||||
\
|
||||
|
||||
@ -330,6 +330,10 @@ void print_statistics() {
|
||||
SystemDictionary::print();
|
||||
}
|
||||
|
||||
if (LogTouchedMethods && PrintTouchedMethodsAtExit) {
|
||||
Method::print_touched_methods(tty);
|
||||
}
|
||||
|
||||
if (PrintBiasedLockingStatistics) {
|
||||
BiasedLocking::print_counters();
|
||||
}
|
||||
@ -382,6 +386,10 @@ void print_statistics() {
|
||||
if (PrintNMTStatistics) {
|
||||
MemTracker::final_report(tty);
|
||||
}
|
||||
|
||||
if (LogTouchedMethods && PrintTouchedMethodsAtExit) {
|
||||
Method::print_touched_methods(tty);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -63,6 +63,7 @@ Monitor* StringDedupQueue_lock = NULL;
|
||||
Mutex* StringDedupTable_lock = NULL;
|
||||
Monitor* CodeCache_lock = NULL;
|
||||
Mutex* MethodData_lock = NULL;
|
||||
Mutex* TouchedMethodLog_lock = NULL;
|
||||
Mutex* RetData_lock = NULL;
|
||||
Monitor* VMOperationQueue_lock = NULL;
|
||||
Monitor* VMOperationRequest_lock = NULL;
|
||||
@ -274,6 +275,7 @@ void mutex_init() {
|
||||
|
||||
def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes);
|
||||
def(MethodData_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always);
|
||||
def(TouchedMethodLog_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always);
|
||||
|
||||
def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always);
|
||||
def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never);
|
||||
|
||||
@ -55,6 +55,7 @@ extern Monitor* StringDedupQueue_lock; // a lock on the string dedupli
|
||||
extern Mutex* StringDedupTable_lock; // a lock on the string deduplication table
|
||||
extern Monitor* CodeCache_lock; // a lock on the CodeCache, rank is special, use MutexLockerEx
|
||||
extern Mutex* MethodData_lock; // a lock on installation of method data
|
||||
extern Mutex* TouchedMethodLog_lock; // a lock on allocation of LogExecutedMethods info
|
||||
extern Mutex* RetData_lock; // a lock on installation of RetData inside method data
|
||||
extern Mutex* DerivedPointerTableGC_lock; // a lock to protect the derived pointer table
|
||||
extern Monitor* VMOperationQueue_lock; // a lock on queue of vm_operations waiting to execute
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2015, 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
|
||||
@ -103,8 +103,10 @@
|
||||
// The knob* variables are effectively final. Once set they should
|
||||
// never be modified hence. Consider using __read_mostly with GCC.
|
||||
|
||||
int ObjectMonitor::Knob_ExitRelease = 0;
|
||||
int ObjectMonitor::Knob_Verbose = 0;
|
||||
int ObjectMonitor::Knob_VerifyInUse = 0;
|
||||
int ObjectMonitor::Knob_VerifyMatch = 0;
|
||||
int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool -
|
||||
static int Knob_LogSpins = 0; // enable jvmstat tally for spins
|
||||
static int Knob_HandOff = 0;
|
||||
@ -251,24 +253,6 @@ static volatile int InitDone = 0;
|
||||
// -----------------------------------------------------------------------------
|
||||
// Enter support
|
||||
|
||||
bool ObjectMonitor::try_enter(Thread* THREAD) {
|
||||
if (THREAD != _owner) {
|
||||
if (THREAD->is_lock_owned ((address)_owner)) {
|
||||
assert(_recursions == 0, "internal state error");
|
||||
_owner = THREAD;
|
||||
_recursions = 1;
|
||||
return true;
|
||||
}
|
||||
if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
_recursions++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void NOINLINE ObjectMonitor::enter(TRAPS) {
|
||||
// The following code is ordered to check the most common cases first
|
||||
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
|
||||
@ -2272,7 +2256,7 @@ void ObjectWaiter::wait_reenter_end(ObjectMonitor * const mon) {
|
||||
}
|
||||
|
||||
inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
|
||||
assert(node != NULL, "should not dequeue NULL node");
|
||||
assert(node != NULL, "should not add NULL node");
|
||||
assert(node->_prev == NULL, "node already in list");
|
||||
assert(node->_next == NULL, "node already in list");
|
||||
// put node at end of queue (circular doubly linked list)
|
||||
@ -2407,8 +2391,8 @@ static int kvGetInt(char * kvList, const char * Key, int Default) {
|
||||
char * v = kvGet(kvList, Key);
|
||||
int rslt = v ? ::strtol(v, NULL, 0) : Default;
|
||||
if (Knob_ReportSettings && v != NULL) {
|
||||
::printf (" SyncKnob: %s %d(%d)\n", Key, rslt, Default) ;
|
||||
::fflush(stdout);
|
||||
tty->print_cr("INFO: SyncKnob: %s %d(%d)", Key, rslt, Default) ;
|
||||
tty->flush();
|
||||
}
|
||||
return rslt;
|
||||
}
|
||||
@ -2442,8 +2426,10 @@ void ObjectMonitor::DeferredInitialize() {
|
||||
|
||||
#define SETKNOB(x) { Knob_##x = kvGetInt(knobs, #x, Knob_##x); }
|
||||
SETKNOB(ReportSettings);
|
||||
SETKNOB(ExitRelease);
|
||||
SETKNOB(Verbose);
|
||||
SETKNOB(VerifyInUse);
|
||||
SETKNOB(VerifyMatch);
|
||||
SETKNOB(FixedSpin);
|
||||
SETKNOB(SpinLimit);
|
||||
SETKNOB(SpinBase);
|
||||
@ -2477,7 +2463,9 @@ void ObjectMonitor::DeferredInitialize() {
|
||||
|
||||
if (os::is_MP()) {
|
||||
BackOffMask = (1 << Knob_SpinBackOff) - 1;
|
||||
if (Knob_ReportSettings) ::printf("BackOffMask=%X\n", BackOffMask);
|
||||
if (Knob_ReportSettings) {
|
||||
tty->print_cr("INFO: BackOffMask=0x%X", BackOffMask);
|
||||
}
|
||||
// CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
|
||||
} else {
|
||||
Knob_SpinLimit = 0;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2015, 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
|
||||
@ -196,8 +196,10 @@ class ObjectMonitor {
|
||||
static PerfCounter * _sync_Deflations;
|
||||
static PerfLongVariable * _sync_MonExtant;
|
||||
|
||||
static int Knob_ExitRelease;
|
||||
static int Knob_Verbose;
|
||||
static int Knob_VerifyInUse;
|
||||
static int Knob_VerifyMatch;
|
||||
static int Knob_SpinLimit;
|
||||
|
||||
void* operator new (size_t size) throw() {
|
||||
@ -317,7 +319,6 @@ class ObjectMonitor {
|
||||
void print();
|
||||
#endif
|
||||
|
||||
bool try_enter(TRAPS);
|
||||
void enter(TRAPS);
|
||||
void exit(bool not_suspended, TRAPS);
|
||||
void wait(jlong millis, bool interruptable, TRAPS);
|
||||
@ -354,14 +355,14 @@ class ObjectMonitor {
|
||||
#undef TEVENT
|
||||
#define TEVENT(nom) { if (SyncVerbose) FEVENT(nom); }
|
||||
|
||||
#define FEVENT(nom) \
|
||||
{ \
|
||||
static volatile int ctr = 0; \
|
||||
int v = ++ctr; \
|
||||
if ((v & (v - 1)) == 0) { \
|
||||
::printf(#nom " : %d\n", v); \
|
||||
::fflush(stdout); \
|
||||
} \
|
||||
#define FEVENT(nom) \
|
||||
{ \
|
||||
static volatile int ctr = 0; \
|
||||
int v = ++ctr; \
|
||||
if ((v & (v - 1)) == 0) { \
|
||||
tty->print_cr("INFO: " #nom " : %d", v); \
|
||||
tty->flush(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef TEVENT
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
#include "utilities/dtrace.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/preserveException.hpp"
|
||||
@ -927,8 +928,9 @@ static void InduceScavenge(Thread * Self, const char * Whence) {
|
||||
|
||||
if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) {
|
||||
if (ObjectMonitor::Knob_Verbose) {
|
||||
::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ;
|
||||
::fflush(stdout);
|
||||
tty->print_cr("INFO: Monitor scavenge - Induced STW @%s (%d)",
|
||||
Whence, ForceMonitorScavenge) ;
|
||||
tty->flush();
|
||||
}
|
||||
// Induce a 'null' safepoint to scavenge monitors
|
||||
// Must VM_Operation instance be heap allocated as the op will be enqueue and posted
|
||||
@ -937,8 +939,9 @@ static void InduceScavenge(Thread * Self, const char * Whence) {
|
||||
VMThread::execute(new VM_ForceAsyncSafepoint());
|
||||
|
||||
if (ObjectMonitor::Knob_Verbose) {
|
||||
::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ;
|
||||
::fflush(stdout);
|
||||
tty->print_cr("INFO: Monitor scavenge - STW posted @%s (%d)",
|
||||
Whence, ForceMonitorScavenge) ;
|
||||
tty->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1603,10 +1606,11 @@ void ObjectSynchronizer::deflate_idle_monitors() {
|
||||
// Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree.
|
||||
|
||||
if (ObjectMonitor::Knob_Verbose) {
|
||||
::printf("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",
|
||||
nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
|
||||
gMonitorPopulation, gMonitorFreeCount);
|
||||
::fflush(stdout);
|
||||
tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d "
|
||||
"ForceMonitorScavenge=%d : pop=%d free=%d",
|
||||
nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
|
||||
gMonitorPopulation, gMonitorFreeCount);
|
||||
tty->flush();
|
||||
}
|
||||
|
||||
ForceMonitorScavenge = 0; // Reset
|
||||
@ -1643,6 +1647,14 @@ class ReleaseJavaMonitorsClosure: public MonitorClosure {
|
||||
ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
|
||||
void do_monitor(ObjectMonitor* mid) {
|
||||
if (mid->owner() == THREAD) {
|
||||
if (ObjectMonitor::Knob_VerifyMatch != 0) {
|
||||
Handle obj((oop) mid->object());
|
||||
tty->print("INFO: unexpected locked object:");
|
||||
javaVFrame::print_locked_object_class_name(tty, obj, "locked");
|
||||
fatal(err_msg("exiting JavaThread=" INTPTR_FORMAT
|
||||
" unexpectedly owns ObjectMonitor=" INTPTR_FORMAT,
|
||||
THREAD, mid));
|
||||
}
|
||||
(void)mid->complete_exit(CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1802,14 +1802,25 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
||||
assert(!this->has_pending_exception(), "ensure_join should have cleared");
|
||||
|
||||
// 6282335 JNI DetachCurrentThread spec states that all Java monitors
|
||||
// held by this thread must be released. A detach operation must only
|
||||
// get here if there are no Java frames on the stack. Therefore, any
|
||||
// owned monitors at this point MUST be JNI-acquired monitors which are
|
||||
// pre-inflated and in the monitor cache.
|
||||
// held by this thread must be released. The spec does not distinguish
|
||||
// between JNI-acquired and regular Java monitors. We can only see
|
||||
// regular Java monitors here if monitor enter-exit matching is broken.
|
||||
//
|
||||
// ensure_join() ignores IllegalThreadStateExceptions, and so does this.
|
||||
if (exit_type == jni_detach && JNIDetachReleasesMonitors) {
|
||||
assert(!this->has_last_Java_frame(), "detaching with Java frames?");
|
||||
// Optionally release any monitors for regular JavaThread exits. This
|
||||
// is provided as a work around for any bugs in monitor enter-exit
|
||||
// matching. This can be expensive so it is not enabled by default.
|
||||
// ObjectMonitor::Knob_ExitRelease is a superset of the
|
||||
// JNIDetachReleasesMonitors option.
|
||||
//
|
||||
// ensure_join() ignores IllegalThreadStateExceptions, and so does
|
||||
// ObjectSynchronizer::release_monitors_owned_by_thread().
|
||||
if ((exit_type == jni_detach && JNIDetachReleasesMonitors) ||
|
||||
ObjectMonitor::Knob_ExitRelease) {
|
||||
// Sanity check even though JNI DetachCurrentThread() would have
|
||||
// returned JNI_ERR if there was a Java frame. JavaThread exit
|
||||
// should be done executing Java code by the time we get here.
|
||||
assert(!this->has_last_Java_frame(),
|
||||
"should not have a Java frame when detaching or exiting");
|
||||
ObjectSynchronizer::release_monitors_owned_by_thread(this);
|
||||
assert(!this->has_pending_exception(), "release_monitors should have cleared");
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
|
||||
void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
|
||||
if (obj.not_null()) {
|
||||
st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
|
||||
if (obj->klass() == SystemDictionary::Class_klass()) {
|
||||
@ -160,17 +160,29 @@ static void print_locked_object_class_name(outputStream* st, Handle obj, const c
|
||||
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
ResourceMark rm;
|
||||
|
||||
// If this is the first frame, and java.lang.Object.wait(...) then print out the receiver.
|
||||
// If this is the first frame and it is java.lang.Object.wait(...)
|
||||
// then print out the receiver. Locals are not always available,
|
||||
// e.g., compiled native frames have no scope so there are no locals.
|
||||
if (frame_count == 0) {
|
||||
if (method()->name() == vmSymbols::wait_name() &&
|
||||
method()->method_holder()->name() == vmSymbols::java_lang_Object()) {
|
||||
const char *wait_state = "waiting on"; // assume we are waiting
|
||||
// If earlier in the output we reported java.lang.Thread.State ==
|
||||
// "WAITING (on object monitor)" and now we report "waiting on", then
|
||||
// we are still waiting for notification or timeout. Otherwise if
|
||||
// we earlier reported java.lang.Thread.State == "BLOCKED (on object
|
||||
// monitor)", then we are actually waiting to re-lock the monitor.
|
||||
// At this level we can't distinguish the two cases to report
|
||||
// "waited on" rather than "waiting on" for the second case.
|
||||
StackValueCollection* locs = locals();
|
||||
if (!locs->is_empty()) {
|
||||
StackValue* sv = locs->at(0);
|
||||
if (sv->type() == T_OBJECT) {
|
||||
Handle o = locs->at(0)->get_obj();
|
||||
print_locked_object_class_name(st, o, "waiting on");
|
||||
print_locked_object_class_name(st, o, wait_state);
|
||||
}
|
||||
} else {
|
||||
st->print_cr("\t- %s <no object reference available>", wait_state);
|
||||
}
|
||||
} else if (thread()->current_park_blocker() != NULL) {
|
||||
oop obj = thread()->current_park_blocker();
|
||||
@ -179,8 +191,8 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print out all monitors that we have locked or are trying to lock
|
||||
// Print out all monitors that we have locked, or are trying to lock,
|
||||
// including re-locking after being notified or timing out in a wait().
|
||||
GrowableArray<MonitorInfo*>* mons = monitors();
|
||||
if (!mons->is_empty()) {
|
||||
bool found_first_monitor = false;
|
||||
@ -202,14 +214,14 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
if (monitor->owner() != NULL) {
|
||||
// the monitor is associated with an object, i.e., it is locked
|
||||
|
||||
// First, assume we have the monitor locked. If we haven't found an
|
||||
// owned monitor before and this is the first frame, then we need to
|
||||
// see if we have completed the lock or we are blocked trying to
|
||||
// acquire it - we can only be blocked if the monitor is inflated
|
||||
|
||||
markOop mark = NULL;
|
||||
const char *lock_state = "locked"; // assume we have the monitor locked
|
||||
if (!found_first_monitor && frame_count == 0) {
|
||||
// If this is the first frame and we haven't found an owned
|
||||
// monitor before, then we need to see if we have completed
|
||||
// the lock or if we are blocked trying to acquire it. Only
|
||||
// an inflated monitor that is first on the monitor list in
|
||||
// the first frame can block us on a monitor enter.
|
||||
mark = monitor->owner()->mark();
|
||||
if (mark->has_monitor() &&
|
||||
( // we have marked ourself as pending on this monitor
|
||||
@ -219,13 +231,35 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
)) {
|
||||
lock_state = "waiting to lock";
|
||||
} else {
|
||||
mark = NULL; // Disable printing below
|
||||
// We own the monitor which is not as interesting so
|
||||
// disable the extra printing below.
|
||||
mark = NULL;
|
||||
}
|
||||
} else if (frame_count != 0 && ObjectMonitor::Knob_Verbose) {
|
||||
// This is not the first frame so we either own this monitor
|
||||
// or we owned the monitor before and called wait(). Because
|
||||
// wait() could have been called on any monitor in a lower
|
||||
// numbered frame on the stack, we have to check all the
|
||||
// monitors on the list for this frame.
|
||||
// Note: Only enable this new output line in verbose mode
|
||||
// since existing tests are not ready for it.
|
||||
mark = monitor->owner()->mark();
|
||||
if (mark->has_monitor() &&
|
||||
( // we have marked ourself as pending on this monitor
|
||||
mark->monitor() == thread()->current_pending_monitor() ||
|
||||
// we are not the owner of this monitor
|
||||
!mark->monitor()->is_entered(thread())
|
||||
)) {
|
||||
lock_state = "waiting to re-lock in wait()";
|
||||
} else {
|
||||
// We own the monitor which is not as interesting so
|
||||
// disable the extra printing below.
|
||||
mark = NULL;
|
||||
}
|
||||
}
|
||||
print_locked_object_class_name(st, monitor->owner(), lock_state);
|
||||
if (Verbose && mark != NULL) {
|
||||
// match with format above, replacing "-" with " ".
|
||||
st->print("\t lockbits=");
|
||||
if (ObjectMonitor::Knob_Verbose && mark != NULL) {
|
||||
st->print("\t- lockbits=");
|
||||
mark->print_on(st);
|
||||
st->cr();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -135,7 +135,8 @@ class javaVFrame: public vframe {
|
||||
// Return an array of monitors locked by this frame in the youngest to oldest order
|
||||
GrowableArray<MonitorInfo*>* locked_monitors();
|
||||
|
||||
// printing used during stack dumps
|
||||
// printing used during stack dumps and diagnostics
|
||||
static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state);
|
||||
void print_lock_info_on(outputStream* st, int frame_count);
|
||||
void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); }
|
||||
|
||||
|
||||
@ -101,6 +101,7 @@
|
||||
template(WhiteBoxOperation) \
|
||||
template(ClassLoaderStatsOperation) \
|
||||
template(DumpHashtable) \
|
||||
template(DumpTouchedMethods) \
|
||||
template(MarkActiveNMethods) \
|
||||
template(PrintCompileQueue) \
|
||||
template(PrintCodeList) \
|
||||
|
||||
@ -74,6 +74,7 @@ void DCmdRegistrant::register_dcmds(){
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
|
||||
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
|
||||
|
||||
// Enhanced JMX Agent Support
|
||||
// These commands won't be exported via the DiagnosticCommandMBean until an
|
||||
@ -808,3 +809,35 @@ int ClassHierarchyDCmd::num_arguments() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class VM_DumpTouchedMethods : public VM_Operation {
|
||||
private:
|
||||
outputStream* _out;
|
||||
public:
|
||||
VM_DumpTouchedMethods(outputStream* out) {
|
||||
_out = out;
|
||||
}
|
||||
|
||||
virtual VMOp_Type type() const { return VMOp_DumpTouchedMethods; }
|
||||
|
||||
virtual void doit() {
|
||||
Method::print_touched_methods(_out);
|
||||
}
|
||||
};
|
||||
|
||||
TouchedMethodsDCmd::TouchedMethodsDCmd(outputStream* output, bool heap) :
|
||||
DCmdWithParser(output, heap)
|
||||
{}
|
||||
|
||||
void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) {
|
||||
if (!UnlockDiagnosticVMOptions) {
|
||||
output()->print_cr("VM.touched_methods command requires -XX:+UnlockDiagnosticVMOptions");
|
||||
return;
|
||||
}
|
||||
VM_DumpTouchedMethods dumper(output());
|
||||
VMThread::execute(&dumper);
|
||||
}
|
||||
|
||||
int TouchedMethodsDCmd::num_arguments() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include "services/diagnosticFramework.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#include "oops/method.hpp"
|
||||
|
||||
class HelpDCmd : public DCmdWithParser {
|
||||
protected:
|
||||
@ -341,6 +342,22 @@ public:
|
||||
virtual void execute(DCmdSource source, TRAPS);
|
||||
};
|
||||
|
||||
class TouchedMethodsDCmd : public DCmdWithParser {
|
||||
public:
|
||||
TouchedMethodsDCmd(outputStream* output, bool heap);
|
||||
static const char* name() {
|
||||
return "VM.print_touched_methods";
|
||||
}
|
||||
static const char* description() {
|
||||
return "Print all methods that have ever been touched during the lifetime of this JVM.";
|
||||
}
|
||||
static const char* impact() {
|
||||
return "Medium: Depends on Java content.";
|
||||
}
|
||||
static int num_arguments();
|
||||
virtual void execute(DCmdSource source, TRAPS);
|
||||
};
|
||||
|
||||
// See also: thread_dump in attachListener.cpp
|
||||
class ThreadDumpDCmd : public DCmdWithParser {
|
||||
protected:
|
||||
|
||||
101
hotspot/test/runtime/CommandLine/PrintTouchedMethods.java
Normal file
101
hotspot/test/runtime/CommandLine/PrintTouchedMethods.java
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* @bug 8025692
|
||||
* @modules java.base/sun.misc
|
||||
* java.management
|
||||
* @library /testlibrary
|
||||
* @compile TestLogTouchedMethods.java PrintTouchedMethods.java
|
||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+LogTouchedMethods PrintTouchedMethods
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class PrintTouchedMethods {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
String[] javaArgs1 = {"-XX:-UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
|
||||
|
||||
// UnlockDiagnostic turned off, should fail
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("Error: VM option 'LogTouchedMethods' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.");
|
||||
output.shouldContain("Error: Could not create the Java Virtual Machine.");
|
||||
|
||||
String[] javaArgs2 = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
|
||||
pb = ProcessTools.createJavaProcessBuilder(javaArgs2);
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
// check order:
|
||||
// 1 "# Method::print_touched_methods version 1" is the first in first line
|
||||
// 2 should contain TestLogMethods.methodA:()V
|
||||
// 3 should not contain TestLogMethods.methodB:()V
|
||||
// Repeat above for another run with -Xint
|
||||
List<String> lines = output.asLines();
|
||||
|
||||
if (lines.size() < 1) {
|
||||
throw new Exception("Empty output");
|
||||
}
|
||||
|
||||
String first = lines.get(0);
|
||||
if (!first.equals("# Method::print_touched_methods version 1")) {
|
||||
throw new Exception("First line mismatch");
|
||||
}
|
||||
|
||||
output.shouldContain("TestLogTouchedMethods.methodA:()V");
|
||||
output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
String[] javaArgs3 = {"-XX:+UnlockDiagnosticVMOptions", "-Xint", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
|
||||
pb = ProcessTools.createJavaProcessBuilder(javaArgs3);
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
lines = output.asLines();
|
||||
|
||||
if (lines.size() < 1) {
|
||||
throw new Exception("Empty output");
|
||||
}
|
||||
|
||||
first = lines.get(0);
|
||||
if (!first.equals("# Method::print_touched_methods version 1")) {
|
||||
throw new Exception("First line mismatch");
|
||||
}
|
||||
|
||||
output.shouldContain("TestLogTouchedMethods.methodA:()V");
|
||||
output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
// Test jcmd PrintTouchedMethods VM.print_touched_methods
|
||||
String pid = Integer.toString(ProcessTools.getProcessId());
|
||||
pb = new ProcessBuilder();
|
||||
pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.print_touched_methods"});
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
try {
|
||||
output.shouldContain("PrintTouchedMethods.main:([Ljava/lang/String;)V");
|
||||
} catch (RuntimeException e) {
|
||||
output.shouldContain("Unknown diagnostic command");
|
||||
}
|
||||
}
|
||||
}
|
||||
32
hotspot/test/runtime/CommandLine/TestLogTouchedMethods.java
Normal file
32
hotspot/test/runtime/CommandLine/TestLogTouchedMethods.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
/* used by PrintTouchedMethods.java */
|
||||
public class TestLogTouchedMethods {
|
||||
public static void main(String[] args) {
|
||||
new TestLogTouchedMethods().methodA();
|
||||
}
|
||||
|
||||
public void methodA() {} // called
|
||||
public void methodB() {} // this should not be called
|
||||
}
|
||||
@ -46,16 +46,8 @@ public class CreateCoredumpOnCrash {
|
||||
runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped");
|
||||
|
||||
if (Platform.isWindows()) {
|
||||
runTest("-XX:+CreateCoredumpOnCrash").shouldContain("Core dump will be written. Default location");
|
||||
|
||||
// The old CreateMinidumpOnCrash option should still work
|
||||
runTest("-XX:+CreateMinidumpOnCrash").shouldContain("Core dump will be written. Default location");
|
||||
runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped");
|
||||
|
||||
if (Platform.isDebugBuild()) {
|
||||
// Make sure we create dumps on Windows debug builds by default
|
||||
runTest("-Ddummyopt=false").shouldContain("Core dump will be written. Default location");
|
||||
}
|
||||
} else {
|
||||
runTest("-XX:+CreateCoredumpOnCrash").shouldNotContain("CreateCoredumpOnCrash turned off, no core file dumped");
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ public class TestOnError {
|
||||
// Execute the VM so that a
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:-TransmitErrorReport",
|
||||
"-XX:-CreateCoredumpOnCrash",
|
||||
"-XX:ErrorHandlerTest=12", // trigger potential SEGV
|
||||
"-XX:OnError=echo " + msg,
|
||||
TestOnError.class.getName());
|
||||
|
||||
54
hotspot/test/runtime/classFileParserBug/BadInitMethod.java
Normal file
54
hotspot/test/runtime/classFileParserBug/BadInitMethod.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* @bug 8130669
|
||||
* @summary VM prohibits <clinit> methods with return values
|
||||
* @compile ignoredClinit.jasm
|
||||
* @compile badInit.jasm
|
||||
* @run main/othervm -Xverify:all BadInitMethod
|
||||
*/
|
||||
|
||||
// Test that a non-void <clinit> method does not cause an exception to be
|
||||
// thrown. But that a non-void <init> method causes a ClassFormatError
|
||||
// exception.
|
||||
public class BadInitMethod {
|
||||
public static void main(String args[]) throws Throwable {
|
||||
|
||||
System.out.println("Regression test for bug 8130669");
|
||||
try {
|
||||
Class newClass = Class.forName("ignoredClinit");
|
||||
} catch (java.lang.Throwable e) {
|
||||
throw new RuntimeException("Unexpected exception: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
Class newClass = Class.forName("badInit");
|
||||
throw new RuntimeException("Expected ClassFormatError exception not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test BadInitMethod passed");
|
||||
}
|
||||
}
|
||||
}
|
||||
45
hotspot/test/runtime/classFileParserBug/EnclosingMethod.java
Normal file
45
hotspot/test/runtime/classFileParserBug/EnclosingMethod.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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
|
||||
* @bug 8130183
|
||||
* @summary For InnerClasses attribute, VM permits inner_class_info_index value of zero
|
||||
* @compile badEnclMthd.jcod
|
||||
* @run main/othervm -Xverify:all EnclosingMethod
|
||||
*/
|
||||
|
||||
// Test that an EnclosingMethod attribute with the value of 0 causes a ClassFormatError.
|
||||
public class EnclosingMethod {
|
||||
public static void main(String args[]) throws Throwable {
|
||||
|
||||
System.out.println("Regression test for bug 8130183");
|
||||
try {
|
||||
Class newClass = Class.forName("badEnclMthd");
|
||||
throw new RuntimeException("Expected ClassFormatError exception not thrown");
|
||||
} catch (java.lang.ClassFormatError e) {
|
||||
System.out.println("Test EnclosingMethod passed");
|
||||
}
|
||||
}
|
||||
}
|
||||
60
hotspot/test/runtime/classFileParserBug/badEnclMthd.jcod
Normal file
60
hotspot/test/runtime/classFileParserBug/badEnclMthd.jcod
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// Source: badEnclMthd
|
||||
class badEnclMthd {
|
||||
0xCAFEBABE;
|
||||
0; // minor version
|
||||
50; // major version
|
||||
[] { // Constant Pool
|
||||
; // first element is empty
|
||||
Utf8 "badEnclMthd"; // #1
|
||||
class #1; // #2
|
||||
Utf8 "java/lang/Object"; // #3
|
||||
class #3; // #4
|
||||
Utf8 "InnerClasses"; // #5
|
||||
Utf8 "badEnclMthd"; // #6
|
||||
class #6; // #7
|
||||
Utf8 "badEnclMthd"; // #8
|
||||
class #8; // #9
|
||||
} // Constant Pool
|
||||
0x0001; // access public
|
||||
#2;// this_cpx
|
||||
#4;// super_cpx
|
||||
[] { // interfaces
|
||||
} // interfaces
|
||||
[] { // fields
|
||||
} // fields
|
||||
[] { // methods
|
||||
} // methods
|
||||
[] { // attributes
|
||||
Attr(#5) { // InnerClasses
|
||||
[] { // InnerClasses
|
||||
#0 #2 #6 1; // Bad inner_class_info_index of 0 !!!
|
||||
#9 #0 #8 1;
|
||||
}
|
||||
} // end InnerClasses
|
||||
;
|
||||
} // attributes
|
||||
} // end class badEnclMthd
|
||||
47
hotspot/test/runtime/classFileParserBug/badInit.jasm
Normal file
47
hotspot/test/runtime/classFileParserBug/badInit.jasm
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
super public class badInit
|
||||
version 52:0
|
||||
{
|
||||
|
||||
|
||||
// This <init> method has a non-void signature. It should cause a
|
||||
// ClassFormatError exception.
|
||||
Method "<init>":"(I)I"
|
||||
stack 1 locals 2
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
iconst_4;
|
||||
ireturn;
|
||||
}
|
||||
|
||||
public static Method main:"([Ljava/lang/String;)V"
|
||||
stack 0 locals 1
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class badInit
|
||||
@ -19,28 +19,21 @@
|
||||
* 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
|
||||
* @bug 8076421
|
||||
* @summary Test of hprof option crashes Zero
|
||||
* @compile cpu002.java
|
||||
* @run main/othervm -Xrunhprof:cpu=times,file=cpu002.hprof.out cpu002
|
||||
*/
|
||||
// This class contains a <clinit> method with signature: ()I. The JVM should
|
||||
// not complain about this because methods named <clinit> that have arguments
|
||||
// and/or are not void should be ignored by the JVM.
|
||||
|
||||
import java.io.*;
|
||||
public class ignoredClinit version 51:0
|
||||
{
|
||||
|
||||
public class cpu002 {
|
||||
public static final int PASSED = 0;
|
||||
public static final int FAILED = 2;
|
||||
public static final int JCK_STATUS_BASE = 95;
|
||||
|
||||
public static void main (String argv[]) {
|
||||
System.exit(run(argv,System.out) + JCK_STATUS_BASE);
|
||||
public static Method "<clinit>":"()I"
|
||||
stack 1 locals 1
|
||||
{
|
||||
iconst_0;
|
||||
ireturn;
|
||||
}
|
||||
|
||||
public static int run(String argv[], PrintStream out) {
|
||||
return PASSED;
|
||||
}
|
||||
}
|
||||
} // end Class ignoredClinit
|
||||
@ -60,6 +60,7 @@ public class ReserveMemory {
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:-TransmitErrorReport",
|
||||
"-XX:-CreateCoredumpOnCrash",
|
||||
"-Xmx32m",
|
||||
"ReserveMemory",
|
||||
"test");
|
||||
|
||||
@ -34,6 +34,7 @@ import jdk.test.lib.apps.LingeredApp;
|
||||
* @test
|
||||
* @library /../../test/lib/share/classes
|
||||
* @library /testlibrary
|
||||
* @ignore 8129971
|
||||
* @build jdk.test.lib.*
|
||||
* @build jdk.test.lib.apps.*
|
||||
* @run main TestStackTrace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user