From 9544f5225c9f16f4d9eb08d32d1f6bce12e5b139 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 17 Sep 2015 18:41:05 -0700 Subject: [PATCH 001/167] 8134297: NPE in GSSNameElement nameType check Reviewed-by: xuelei --- .../classes/sun/security/jgss/wrapper/GSSNameElement.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index d09ca8d6a16..3463fd69dfa 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -159,7 +159,9 @@ public class GSSNameElement implements GSSNameSpi { int atPos = krbName.lastIndexOf('@'); if (atPos != -1) { String atRealm = krbName.substring(atPos); - if (nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL) + // getNativeNameType() can modify NT_GSS_KRB5_PRINCIPAL to null + if ((nameType == null + || nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL)) && new String(nameBytes).endsWith(atRealm)) { // Created from Kerberos name with realm, no need to check } else { From 200784d505dd98444c48c9ccb7f2e4df36dcbb6a Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Oct 2015 18:13:34 -0400 Subject: [PATCH 002/167] 8132051: Better byte behavior Co-authored-by: Roland Westerlin Co-authored-by: Vladimir Kozlov Co-authored-by: John Rose Reviewed-by: bdelsart, roland, kvn, jrose, ahgross --- .../cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 5 +- .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 59 +++++++++++++++-- .../src/cpu/sparc/vm/interp_masm_sparc.hpp | 2 + .../src/cpu/sparc/vm/templateTable_sparc.cpp | 65 +++++++++++++++++-- .../src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 5 +- hotspot/src/cpu/x86/vm/interp_masm_x86.cpp | 51 +++++++++++++++ hotspot/src/cpu/x86/vm/interp_masm_x86.hpp | 3 + hotspot/src/cpu/x86/vm/templateTable_x86.cpp | 60 +++++++++++++++-- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 35 +++++++++- hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 3 +- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 61 ++++++++++++++++- hotspot/src/share/vm/c1/c1_Instruction.hpp | 7 +- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 23 +++++++ hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 1 + .../share/vm/classfile/classFileParser.cpp | 6 +- .../src/share/vm/classfile/defaultMethods.cpp | 4 +- .../vm/interpreter/bytecodeInterpreter.cpp | 25 +++++-- .../src/share/vm/interpreter/bytecodes.cpp | 3 +- .../src/share/vm/interpreter/bytecodes.hpp | 1 + .../vm/interpreter/interpreterRuntime.cpp | 3 +- .../vm/interpreter/templateInterpreter.cpp | 12 ++-- .../vm/interpreter/templateInterpreter.hpp | 2 +- .../templateInterpreterGenerator.cpp | 17 ++++- .../share/vm/interpreter/templateTable.cpp | 1 + hotspot/src/share/vm/oops/constMethod.cpp | 1 + hotspot/src/share/vm/oops/constMethod.hpp | 5 ++ hotspot/src/share/vm/oops/cpCache.hpp | 25 +++---- hotspot/src/share/vm/oops/klass.hpp | 15 +++++ hotspot/src/share/vm/oops/method.cpp | 4 +- hotspot/src/share/vm/oops/oop.inline.hpp | 4 +- hotspot/src/share/vm/opto/memnode.cpp | 2 +- hotspot/src/share/vm/opto/parse1.cpp | 34 ++++++++++ hotspot/src/share/vm/opto/parse2.cpp | 6 +- hotspot/src/share/vm/opto/type.cpp | 10 +-- hotspot/src/share/vm/prims/jni.cpp | 2 + hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 2 +- hotspot/src/share/vm/prims/jvmtiExport.cpp | 2 +- hotspot/src/share/vm/prims/unsafe.cpp | 13 +++- hotspot/src/share/vm/runtime/reflection.cpp | 2 +- .../share/vm/utilities/globalDefinitions.hpp | 21 +++--- 40 files changed, 514 insertions(+), 88 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 6185a1d59cd..de568fd7693 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -344,7 +344,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -389,7 +389,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 4e0b6d504f6..580b1336bf3 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -208,6 +208,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case atos: ld_ptr(oop_addr, Otos_l); st_ptr(G0, oop_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: ld(val_addr, Otos_l1); break; @@ -452,9 +453,10 @@ void InterpreterMacroAssembler::push(TosState state) { interp_verify_oop(Otos_i, state, __FILE__, __LINE__); switch (state) { case atos: push_ptr(); break; - case btos: push_i(); break; - case ctos: - case stos: push_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: push_i(); break; case ltos: push_l(); break; case ftos: push_f(); break; @@ -468,9 +470,10 @@ void InterpreterMacroAssembler::push(TosState state) { void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; - case btos: pop_i(); break; - case ctos: - case stos: pop_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: pop_i(); break; case ltos: pop_l(); break; case ftos: pop_f(); break; @@ -1103,6 +1106,49 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, interp_verify_oop(Otos_i, state, __FILE__, __LINE__); } +void InterpreterMacroAssembler::narrow(Register result) { + + ld_ptr(Address(Lmethod, Method::const_offset()), G3_scratch); + ldub(G3_scratch, in_bytes(ConstMethod::result_type_offset()), G3_scratch); + + Label notBool, notByte, notChar, done; + + // common case first + cmp(G3_scratch, T_INT); + br(Assembler::equal, true, pn, done); + delayed()->nop(); + + cmp(G3_scratch, T_BOOLEAN); + br(Assembler::notEqual, true, pn, notBool); + delayed()->cmp(G3_scratch, T_BYTE); + and3(result, 1, result); + ba(done); + delayed()->nop(); + + bind(notBool); + // cmp(G3_scratch, T_BYTE); + br(Assembler::notEqual, true, pn, notByte); + delayed()->cmp(G3_scratch, T_CHAR); + sll(result, 24, result); + sra(result, 24, result); + ba(done); + delayed()->nop(); + + bind(notByte); + // cmp(G3_scratch, T_CHAR); + sll(result, 16, result); + br(Assembler::notEqual, true, pn, done); + delayed()->sra(result, 16, result); + // sll(result, 16, result); + srl(result, 16, result); + + // bind(notChar); + // must be short, instructions already executed in delay slot + // sll(result, 16, result); + // sra(result, 16, result); + + bind(done); +} // remove activation // @@ -1151,6 +1197,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 #endif case btos: // fall through + case ztos: // fall through case ctos: case stos: // fall through case atos: // fall through diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 4fa3b09b3a9..1baceb1233c 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -103,6 +103,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void dispatch_via (TosState state, address* table); + void narrow(Register result); + // Removes the current activation (incl. unlocking of monitors). // Additionally this code is used for earlyReturn in which case we // want to skip throwing an exception and installing an exception. diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 1315f7c8d60..2976383f767 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -165,6 +165,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -922,8 +923,20 @@ void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(O2); // index // Otos_i: val + // O2: index // O3: array __ index_check(O3, O2, 0, G3_scratch, O2); + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(O3, G4_scratch); + __ ld(G4_scratch, in_bytes(Klass::layout_helper_offset()), G4_scratch); + __ set(Klass::layout_helper_boolean_diffbit(), G3_scratch); + __ andcc(G3_scratch, G4_scratch, G0); + Label L_skip; + __ br(Assembler::zero, false, Assembler::pn, L_skip); + __ delayed()->nop(); + __ and3(Otos_i, 1, Otos_i); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } @@ -2008,6 +2021,12 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(Otos_i); + } __ remove_activation(state, /* throw_monitor_exception */ true); // The caller's SP was adjusted upon method entry to accomodate @@ -2218,7 +2237,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr Label checkVolatile; // compute field type - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj; + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj; __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags); // Make sure we don't need to mask Rflags after the above shift ConstantPoolCacheEntry::verify_tos_state_shift(); @@ -2273,7 +2292,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed() ->cmp(Rflags, ctos); + __ delayed() ->cmp(Rflags, ztos); // btos __ ldsb(Rclass, Roffset, Otos_i); @@ -2286,6 +2305,22 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ bind(notByte); + // cmp(Rflags, ztos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed() ->cmp(Rflags, ctos); + + // ztos + __ ldsb(Rclass, Roffset, Otos_i); + __ push(itos); + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + + __ bind(notBool); + // cmp(Rflags, ctos); __ br(Assembler::notEqual, false, Assembler::pt, notChar); __ delayed() ->cmp(Rflags, stos); @@ -2449,6 +2484,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // save tos values before call_VM() clobbers them case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break; @@ -2466,6 +2502,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break; @@ -2581,7 +2618,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr ConstantPoolCacheEntry::verify_tos_state_shift(); // compute field type - Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat; + Label notInt, notShort, notChar, notObj, notByte, notBool, notLong, notFloat; if (is_static) { // putstatic with object type most likely, check that first @@ -2649,7 +2686,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed()->cmp(Rflags, ltos); + __ delayed()->cmp(Rflags, ztos); // btos { @@ -2664,6 +2701,25 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + + // cmp(Rflags, btos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed()->cmp(Rflags, ltos); + + // ztos + { + __ pop_i(); + if (!is_static) pop_and_check_object(Rclass); + __ and3(Otos_i, 1, Otos_i); + __ stb(Otos_i, Rclass, Roffset); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, G3_scratch, G4_scratch, true, byte_no); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + } + + __ bind(notBool); // cmp(Rflags, ltos); __ br(Assembler::notEqual, false, Assembler::pt, notLong); __ delayed()->cmp(Rflags, ctos); @@ -2787,6 +2843,7 @@ void TemplateTable::fast_storefield(TosState state) { pop_and_check_object(Rclass); switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ and3(Otos_i, 1, Otos_i); // fall through to bputfield case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break; case Bytecodes::_fast_cputfield: /* fall through */ case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break; diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index b545d0b6989..20c19325463 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -284,7 +284,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -332,7 +332,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { // Seems to be a precise post_barrier(LIR_OprFact::address(array_addr), value.result()); } else { - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); } } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp index 8dc3084c442..f8578f9f420 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp @@ -349,6 +349,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { verify_oop(rax, state); break; case ltos: movptr(rax, val_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -370,6 +371,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case ltos: movl(rdx, val_addr1); // fall through case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -616,6 +618,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -633,6 +636,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -668,6 +672,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: pop_i(rax); break; @@ -716,6 +721,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: push_i(rax); break; @@ -849,6 +855,51 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { dispatch_base(state, table); } +void InterpreterMacroAssembler::narrow(Register result) { + + // Get method->_constMethod->_result_type + movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + movptr(rcx, Address(rcx, Method::const_offset())); + load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset())); + + Label done, notBool, notByte, notChar; + + // common case first + cmpl(rcx, T_INT); + jcc(Assembler::equal, done); + + // mask integer result to narrower return type. + cmpl(rcx, T_BOOLEAN); + jcc(Assembler::notEqual, notBool); + andl(result, 0x1); + jmp(done); + + bind(notBool); + cmpl(rcx, T_BYTE); + jcc(Assembler::notEqual, notByte); + LP64_ONLY(movsbl(result, result);) + NOT_LP64(shll(result, 24);) // truncate upper 24 bits + NOT_LP64(sarl(result, 24);) // and sign-extend byte + jmp(done); + + bind(notByte); + cmpl(rcx, T_CHAR); + jcc(Assembler::notEqual, notChar); + LP64_ONLY(movzwl(result, result);) + NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits + jmp(done); + + bind(notChar); + // cmpl(rcx, T_SHORT); // all that's left + // jcc(Assembler::notEqual, done); + LP64_ONLY(movswl(result, result);) + NOT_LP64(shll(result, 16);) // truncate upper 16 bits + NOT_LP64(sarl(result, 16);) // and sign-extend short + + // Nothing to do for T_INT + bind(done); +} + // remove activation // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 470ac6e6399..9ed5c2c9ad3 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -192,6 +192,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void prepare_to_jump_from_interpreted(); void jump_from_interpreted(Register method, Register temp); + // narrow int return value + void narrow(Register result); + // Returning from interpreted functions // // Removes the current activation (incl. unlocking of monitors) diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 42520c7e418..9f99613b1e6 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -243,6 +243,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -1082,6 +1083,16 @@ void TemplateTable::bastore() { // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(rcx, rdx); + __ movl(rcx, Address(rcx, Klass::layout_helper_offset())); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ testl(rcx, diffbit); + Label L_skip; + __ jccb(Assembler::zero, L_skip); + __ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -2540,13 +2551,12 @@ void TemplateTable::fast_binaryswitch() { void TemplateTable::_return(TosState state) { transition(state, state); - Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); - assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { assert(state == vtos, "only valid state"); + Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); __ movptr(robj, aaddress(0)); __ load_klass(rdi, robj); __ movl(rdi, Address(rdi, Klass::access_flags_offset())); @@ -2559,7 +2569,14 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(rax); + } __ remove_activation(state, rbcp); + __ jmp(rbcp); } @@ -2754,7 +2771,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize)); - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); // Make sure we don't need to mask edx after the above shift @@ -2773,6 +2790,20 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jmp(Done); __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos (same code as btos) + __ load_signed_byte(rax, field); + __ push(ztos); + // Rewrite bytecode to be faster + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); // atos @@ -3006,7 +3037,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);) - Label notByte, notInt, notShort, notChar, + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); @@ -3027,6 +3058,22 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos + { + __ pop(ztos); + if (!is_static) pop_and_check_object(obj); + __ andl(rax, 0x1); + __ movb(field, rax); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); @@ -3214,6 +3261,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(rax); break; @@ -3238,6 +3286,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(rax); break; @@ -3297,6 +3346,9 @@ void TemplateTable::fast_storefield(TosState state) { case Bytecodes::_fast_iputfield: __ movl(field, rax); break; + case Bytecodes::_fast_zputfield: + __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(field, rax); break; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 4dc68335b6a..48143d50e72 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -82,6 +82,29 @@ int CppInterpreter::normal_entry(Method* method, intptr_t UNUSED, TRAPS) { return 0; } +intptr_t narrow(BasicType type, intptr_t result) { + // mask integer result to narrower return type. + switch (type) { + case T_BOOLEAN: + return result&1; + case T_BYTE: + return (intptr_t)(jbyte)result; + case T_CHAR: + return (intptr_t)(uintptr_t)(jchar)result; + case T_SHORT: + return (intptr_t)(jshort)result; + case T_OBJECT: // nothing to do fall through + case T_LONG: + case T_INT: + case T_FLOAT: + case T_DOUBLE: + case T_VOID: + return result; + default : ShouldNotReachHere(); + } +} + + void CppInterpreter::main_loop(int recurse, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -195,8 +218,14 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { stack->set_sp(stack->sp() + method->max_locals()); // Push our result - for (int i = 0; i < result_slots; i++) - stack->push(result[-i]); + for (int i = 0; i < result_slots; i++) { + // Adjust result to smaller + intptr_t res = result[-i]; + if (result_slots == 1) { + res = narrow(result_type_of(method), res); + } + stack->push(res); + } } int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { @@ -532,6 +561,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0); break; @@ -570,6 +600,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0); break; diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index c4a084a4518..2b01e3ae04c 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -305,7 +305,8 @@ void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), - x->elt_type(), value, x->state_before())); + x->elt_type(), value, x->state_before(), + x->check_boolean())); return; } } diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 172e26eb4d9..7eacc2c952d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -976,7 +976,19 @@ void GraphBuilder::store_indexed(BasicType type) { (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { length = append(new ArrayLength(array, state_before)); } - StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); + ciType* array_type = array->declared_type(); + bool check_boolean = false; + if (array_type != NULL) { + if (array_type->is_loaded() && + array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) { + assert(type == T_BYTE, "boolean store uses bastore"); + Value mask = append(new Constant(new IntConstant(1))); + value = append(new LogicOp(Bytecodes::_iand, value, mask)); + } + } else if (type == T_BYTE) { + check_boolean = true; + } + StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean); append(result); _memory->store_value(value); @@ -1443,6 +1455,36 @@ void GraphBuilder::method_return(Value x) { need_mem_bar = true; } + BasicType bt = method()->return_type()->basic_type(); + switch (bt) { + case T_BYTE: + { + Value shift = append(new Constant(new IntConstant(24))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_SHORT: + { + Value shift = append(new Constant(new IntConstant(16))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_CHAR: + { + Value mask = append(new Constant(new IntConstant(0xFFFF))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + case T_BOOLEAN: + { + Value mask = append(new Constant(new IntConstant(1))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + } + // Check to see whether we are inlining. If so, Return // instructions become Gotos to the continuation point. if (continuation() != NULL) { @@ -1611,6 +1653,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); break; } @@ -1672,6 +1718,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching); if (!needs_patching) store = _memory->store(store); if (store != NULL) { @@ -4134,7 +4184,12 @@ void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_ #ifndef _LP64 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); #endif - Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); + Value val = args->at(3); + if (t == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } + Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, val, is_volatile)); compilation()->set_has_unsafe_access(true); kill_all(); } @@ -4208,7 +4263,7 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { Value index = args->at(1); if (is_store) { Value value = args->at(2); - Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before)); + Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before, false)); store->set_flag(Instruction::NeedsRangeCheckFlag, false); _memory->store_value(value); } else { diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 8f6bf233f3d..38fcc56ae75 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -974,11 +974,13 @@ LEAF(StoreIndexed, AccessIndexed) ciMethod* _profiled_method; int _profiled_bci; + bool _check_boolean; + public: // creation - StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before) + StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before, bool check_boolean) : AccessIndexed(array, index, length, elt_type, state_before) - , _value(value), _profiled_method(NULL), _profiled_bci(0) + , _value(value), _profiled_method(NULL), _profiled_bci(0), _check_boolean(check_boolean) { set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object())); set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object())); @@ -990,6 +992,7 @@ LEAF(StoreIndexed, AccessIndexed) Value value() const { return _value; } bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } + bool check_boolean() const { return _check_boolean; } // Helpers for MethodData* profiling void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } void set_profiled_method(ciMethod* method) { _profiled_method = method; } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 3c8454e5260..956bb657ed6 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3680,3 +3680,26 @@ void LIRGenerator::do_MemBar(MemBar* x) { } } } + +LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) { + if (x->check_boolean()) { + LIR_Opr value_fixed = rlock_byte(T_BYTE); + if (TwoOperandLIRForm) { + __ move(value, value_fixed); + __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed); + } else { + __ logical_and(value, LIR_OprFact::intConst(1), value_fixed); + } + LIR_Opr klass = new_register(T_METADATA); + __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info); + null_check_info = NULL; + LIR_Opr layout = new_register(T_INT); + __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout); + __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE); + value = value_fixed; + } + return value; +} diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index bf36d7dc10e..6885ff6186c 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -448,6 +448,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void profile_arguments(ProfileCall* x); void profile_parameters(Base* x); void profile_parameters_at_call(ProfileCall* x); + LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info); public: Compilation* compilation() const { return _compilation; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index cedf1b48509..5a735d525e5 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2713,11 +2713,9 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, m->set_constants(_cp); m->set_name_index(name_index); m->set_signature_index(signature_index); -#ifdef CC_INTERP - // hmm is there a gc issue here?? + ResultTypeFinder rtf(cp->symbol_at(signature_index)); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); if (args_size >= 0) { m->set_size_of_parameters(args_size); diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index 65d546e249c..1b8cf3084ed 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -860,10 +860,8 @@ static Method* new_method( m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); m->set_signature_index(cp->utf8(sig)); -#ifdef CC_INTERP ResultTypeFinder rtf(sig); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->set_size_of_parameters(params); m->set_max_stack(max_stack); m->set_max_locals(params); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index dbe5355b1df..2b42fab10b9 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1767,8 +1767,19 @@ run: ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } - CASE(_bastore): - ARRAY_STOREFROM32(T_BYTE, jbyte, "%d", STACK_INT, 0); + CASE(_bastore): { + ARRAY_INTRO(-3); + int item = STACK_INT(-1); + // if it is a T_BOOLEAN array, mask the stored value to 0/1 + if (arrObj->klass() == Universe::boolArrayKlassObj()) { + item &= 1; + } else { + assert(arrObj->klass() == Universe::byteArrayKlassObj(), + "should be byte array otherwise"); + } + ((typeArrayOop)arrObj)->byte_at_put(index, item); + UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); + } CASE(_castore): ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0); CASE(_sastore): @@ -1999,7 +2010,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field_acquire(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field_acquire(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field_acquire(field_offset), -1); @@ -2020,7 +2031,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field(field_offset), -1); @@ -2109,6 +2120,9 @@ run: obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->release_byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->release_long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { @@ -2129,6 +2143,9 @@ run: obj->obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index 78ef212d9bf..863c85fae63 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -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 @@ -496,6 +496,7 @@ void Bytecodes::initialize() { def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield ); diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 4f52e7b4a1a..86e88d4b516 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -257,6 +257,7 @@ class Bytecodes: AllStatic { _fast_aputfield , _fast_bputfield , + _fast_zputfield , _fast_cputfield , _fast_dputfield , _fast_fputfield , diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 27fed0c33f2..cd1d88926aa 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1077,7 +1077,8 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, char sig_type = '\0'; switch(cp_entry->flag_state()) { - case btos: sig_type = 'Z'; break; + case btos: sig_type = 'B'; break; + case ztos: sig_type = 'Z'; break; case ctos: sig_type = 'C'; break; case stos: sig_type = 'S'; break; case itos: sig_type = 'I'; break; diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index a059bd5871f..8b368a12d79 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -89,8 +89,9 @@ void TemplateInterpreter::initialize() { // Implementation of EntryPoint EntryPoint::EntryPoint() { - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _entry[btos] = NULL; + _entry[ztos] = NULL; _entry[ctos] = NULL; _entry[stos] = NULL; _entry[atos] = NULL; @@ -102,9 +103,10 @@ EntryPoint::EntryPoint() { } -EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { - assert(number_of_states == 9, "check the code below"); +EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { + assert(number_of_states == 10, "check the code below"); _entry[btos] = bentry; + _entry[ztos] = zentry; _entry[ctos] = centry; _entry[stos] = sentry; _entry[atos] = aentry; @@ -155,6 +157,7 @@ EntryPoint DispatchTable::entry(int i) const { return EntryPoint( _table[btos][i], + _table[ztos][i], _table[ctos][i], _table[stos][i], _table[atos][i], @@ -169,8 +172,9 @@ EntryPoint DispatchTable::entry(int i) const { void DispatchTable::set_entry(int i, EntryPoint& entry) { assert(0 <= i && i < length, "index out of bounds"); - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _table[btos][i] = entry.entry(btos); + _table[ztos][i] = entry.entry(ztos); _table[ctos][i] = entry.entry(ctos); _table[stos][i] = entry.entry(stos); _table[atos][i] = entry.entry(atos); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp index 1955cae20cb..f9d008d5c92 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp @@ -47,7 +47,7 @@ class EntryPoint VALUE_OBJ_CLASS_SPEC { public: // Construction EntryPoint(); - EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); + EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); // Attributes address entry(TosState state) const; // return target address for a given tosca state diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index a10981c48af..a2c427f4aa8 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -74,6 +74,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_trace_code = EntryPoint( generate_trace_code(btos), + generate_trace_code(ztos), generate_trace_code(ctos), generate_trace_code(stos), generate_trace_code(atos), @@ -94,6 +95,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), generate_return_entry_for(atos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(ltos, i, index_size), @@ -105,13 +107,16 @@ void TemplateInterpreterGenerator::generate_all() { } { CodeletMark cm(_masm, "invoke return entry points"); - const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + // These states are in order specified in TosState, except btos/ztos/ctos/stos are + // really the same as itos since there is no top of stack optimization for these types + const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl}; const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { TosState state = states[i]; + assert(state != ilgl, "states array is wrong above"); Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); @@ -122,6 +127,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_earlyret_entry = EntryPoint( generate_earlyret_entry_for(btos), + generate_earlyret_entry_for(ztos), generate_earlyret_entry_for(ctos), generate_earlyret_entry_for(stos), generate_earlyret_entry_for(atos), @@ -140,6 +146,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), generate_deopt_entry_for(atos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(ltos, i), @@ -167,6 +174,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_continuation_entry = EntryPoint( generate_continuation_for(btos), + generate_continuation_for(ztos), generate_continuation_for(ctos), generate_continuation_for(stos), generate_continuation_for(atos), @@ -182,6 +190,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_safept_entry = EntryPoint( generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), @@ -301,7 +310,7 @@ void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { void TemplateInterpreterGenerator::set_unimplemented(int i) { address e = _unimplemented_bytecode; - EntryPoint entry(e, e, e, e, e, e, e, e, e); + EntryPoint entry(e, e, e, e, e, e, e, e, e, e); Interpreter::_normal_table.set_entry(i, entry); Interpreter::_wentry_point[i] = _unimplemented_bytecode; } @@ -316,6 +325,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { assert(_unimplemented_bytecode != NULL, "should have been generated before"); assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); address bep = _illegal_bytecode_sequence; + address zep = _illegal_bytecode_sequence; address cep = _illegal_bytecode_sequence; address sep = _illegal_bytecode_sequence; address aep = _illegal_bytecode_sequence; @@ -337,7 +347,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { set_wide_entry_point(t, wep); } // set entry points - EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); + EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep); Interpreter::_normal_table.set_entry(code, entry); Interpreter::_wentry_point[code] = wep; CodeCacheExtensions::completed_template_interpreter_entries(_masm, code); @@ -355,6 +365,7 @@ void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& assert(t->is_valid(), "template must exist"); switch (t->tos_in()) { case btos: + case ztos: case ctos: case stos: ShouldNotReachHere(); // btos/ctos/stos should use itos. diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp index ebca67320bd..4672a1ee4eb 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.cpp +++ b/hotspot/src/share/vm/interpreter/templateTable.cpp @@ -488,6 +488,7 @@ void TemplateTable::initialize() { def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos ); def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); + def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos ); def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos ); diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 5ffc8e03e81..8de67525a27 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -66,6 +66,7 @@ ConstMethod::ConstMethod(int byte_code_size, set_max_locals(0); set_method_idnum(0); set_size_of_parameters(0); + set_result_type(T_VOID); } // Accessor that copies to metadata. diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 01df3b1a3d8..7f63d9e2b38 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -210,6 +210,7 @@ private: int _constMethod_size; u2 _flags; + u1 _result_type; // BasicType of result // Size of Java bytecodes allocated immediately after Method*. u2 _code_size; @@ -494,6 +495,8 @@ public: static ByteSize size_of_parameters_offset() { return byte_offset_of(ConstMethod, _size_of_parameters); } + static ByteSize result_type_offset() + { return byte_offset_of(ConstMethod, _result_type); } // Unique id for the method static const u2 MAX_IDNUM; @@ -516,6 +519,8 @@ public: int size_of_parameters() const { return _size_of_parameters; } void set_size_of_parameters(int size) { _size_of_parameters = size; } + void set_result_type(BasicType rt) { assert(rt < 16, "result type too large"); + _result_type = (u1)rt; } // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; } diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index 33828d52f6a..840177a10cd 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -77,18 +77,19 @@ class PSPromotionManager; // f2 flag true if f2 contains an oop (e.g., virtual final method) // fv flag true if invokeinterface used for method in class Object // -// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the +// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 16 with the // following mapping to the TosState states: // // btos: 0 -// ctos: 1 -// stos: 2 -// itos: 3 -// ltos: 4 -// ftos: 5 -// dtos: 6 -// atos: 7 -// vtos: 8 +// ztos: 1 +// ctos: 2 +// stos: 3 +// itos: 4 +// ltos: 5 +// ftos: 6 +// dtos: 7 +// atos: 8 +// vtos: 9 // // Entry specific: field entries: // _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index @@ -352,14 +353,8 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } - bool is_byte() const { return flag_state() == btos; } - bool is_char() const { return flag_state() == ctos; } - bool is_short() const { return flag_state() == stos; } - bool is_int() const { return flag_state() == itos; } bool is_long() const { return flag_state() == ltos; } - bool is_float() const { return flag_state() == ftos; } bool is_double() const { return flag_state() == dtos; } - bool is_object() const { return flag_state() == atos; } TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index cff1d74d6ef..14675aa81ee 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -342,6 +342,21 @@ protected: assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity"); return (BasicType) btvalue; } + + // Want a pattern to quickly diff against layout header in register + // find something less clever! + static int layout_helper_boolean_diffbit() { + jint zlh = array_layout_helper(T_BOOLEAN); + jint blh = array_layout_helper(T_BYTE); + assert(zlh != blh, "array layout helpers must differ"); + int diffbit = 1; + while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) { + diffbit <<= 1; + assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE"); + } + return diffbit; + } + static int layout_helper_log2_element_size(jint lh) { assert(lh < (jint)_lh_neutral_value, "must be array"); int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index b3f2b868b64..d6fe27a1c93 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1220,10 +1220,8 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, m->set_signature_index(_imcp_invoke_signature); assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(m->signature() == signature, ""); -#ifdef CC_INTERP ResultTypeFinder rtf(signature); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->compute_size_of_parameters(THREAD); m->init_intrinsic_id(); assert(m->is_method_handle_intrinsic(), ""); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 5f896346986..c3072a1b21c 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -443,7 +443,7 @@ jchar oopDesc::char_field(int offset) const { return (jchar) * void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } -void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; } +void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (((jint) contents) & 1); } jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); } void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; } @@ -483,7 +483,7 @@ jchar oopDesc::char_field_acquire(int offset) const { return O void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } -void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); } +void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), (contents & 1)); } jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); } void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); } diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index d6b3c9394ad..5580c7901d4 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -2389,7 +2389,7 @@ StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const ctl != NULL, "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: + case T_BOOLEAN: val = gvn.transform(new AndINode(val, gvn.intcon(0x1))); // Fall through to T_BYTE case case T_BYTE: return new StoreBNode(ctl, mem, adr, adr_type, val, mo); case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 833f0a66add..22b3e27292e 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -730,6 +730,26 @@ void Parse::do_all_blocks() { #endif } +static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) { + switch (bt) { + case T_BYTE: + v = gvn->transform(new LShiftINode(v, gvn->intcon(24))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(24))); + break; + case T_SHORT: + v = gvn->transform(new LShiftINode(v, gvn->intcon(16))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(16))); + break; + case T_CHAR: + v = gvn->transform(new AndINode(v, gvn->intcon(0xFFFF))); + break; + case T_BOOLEAN: + v = gvn->transform(new AndINode(v, gvn->intcon(0x1))); + break; + } + return v; +} + //-------------------------------build_exits---------------------------------- // Build normal and exceptional exit merge points. void Parse::build_exits() { @@ -754,6 +774,16 @@ void Parse::build_exits() { // Add a return value to the exit state. (Do not push it yet.) if (tf()->range()->cnt() > TypeFunc::Parms) { const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + if (ret_bt == T_BOOLEAN || + ret_bt == T_CHAR || + ret_bt == T_BYTE || + ret_bt == T_SHORT) { + ret_type = TypeInt::INT; + } + } + // Don't "bind" an unloaded return klass to the ret_phi. If the klass // becomes loaded during the subsequent parsing, the loaded and unloaded // types will not join when we transform and push in do_exits(). @@ -1014,6 +1044,10 @@ void Parse::do_exits() { } return; } + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn); + } _exits.push_node(ret_type->basic_type(), ret_phi); } diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 6c0c2bec44f..c8553ce798b 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -64,11 +64,15 @@ void Parse::array_load(BasicType elem_type) { //--------------------------------array_store---------------------------------- void Parse::array_store(BasicType elem_type) { - Node* adr = array_addressing(elem_type, 1); + const Type* elem = Type::TOP; + Node* adr = array_addressing(elem_type, 1, &elem); if (stopped()) return; // guaranteed null or range check Node* val = pop(); dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); + if (elem == TypeInt::BOOL) { + elem_type = T_BOOLEAN; + } store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 42b290bd29e..babc67b2433 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1820,14 +1820,16 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig) break; case T_OBJECT: case T_ARRAY: - case T_BOOLEAN: - case T_CHAR: case T_FLOAT: - case T_BYTE: - case T_SHORT: case T_INT: field_array[pos++] = get_const_type(type); break; + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + field_array[pos++] = TypeInt::INT; + break; default: ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 80dc866f136..2f9b49359c5 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -2188,6 +2188,7 @@ JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID field_value.unionType = value; \ o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ o->Fieldname##_field_put(offset, value); \ ReturnProbe; \ JNI_END @@ -2387,6 +2388,7 @@ JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID field_value.unionType = value; \ JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ ReturnProbe;\ JNI_END diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 96ee3a19adb..dd241a014d7 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1354,7 +1354,7 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa ResultTypeFinder rtf(signature); TosState fr_tos = as_TosState(rtf.type()); if (fr_tos != tos) { - if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) { + if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) { return JVMTI_ERROR_TYPE_MISMATCH; } } diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 20de3f979cb..324d297e649 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1702,7 +1702,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { - if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') { + if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. // determine which it really is, and convert fieldDescriptor fd; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index f951f694f1d..72226385d3e 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -133,13 +133,22 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { ///// Data in the Java heap. +#define truncate_jboolean(x) ((x) & 1) +#define truncate_jbyte(x) (x) +#define truncate_jshort(x) (x) +#define truncate_jchar(x) (x) +#define truncate_jint(x) (x) +#define truncate_jlong(x) (x) +#define truncate_jfloat(x) (x) +#define truncate_jdouble(x) (x) + #define GET_FIELD(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset) #define SET_FIELD(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - *(type_name*)index_oop_from_field_offset_long(p, offset) = x + *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x) #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ @@ -150,7 +159,7 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); + OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x)); // Get/SetObject must be special-cased, since it works with handles. diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 1832711848b..625d55830de 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -1025,7 +1025,7 @@ static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) { static void narrow(jvalue* value, BasicType narrow_type, TRAPS) { switch (narrow_type) { case T_BOOLEAN: - value->z = (jboolean)value->i; + value->z = (jboolean) (value->i & 1); return; case T_BYTE: value->b = (jbyte)value->i; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3c04e2a0f54..fde654f1cf5 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -846,14 +846,15 @@ class JavaValue { enum TosState { // describes the tos cache contents btos = 0, // byte, bool tos cached - ctos = 1, // char tos cached - stos = 2, // short tos cached - itos = 3, // int tos cached - ltos = 4, // long tos cached - ftos = 5, // float tos cached - dtos = 6, // double tos cached - atos = 7, // object cached - vtos = 8, // tos not cached + ztos = 1, // byte, bool tos cached + ctos = 2, // char tos cached + stos = 3, // short tos cached + itos = 4, // int tos cached + ltos = 5, // long tos cached + ftos = 6, // float tos cached + dtos = 7, // double tos cached + atos = 8, // object cached + vtos = 9, // tos not cached number_of_states, ilgl // illegal state: should not occur }; @@ -862,7 +863,7 @@ enum TosState { // describes the tos cache contents inline TosState as_TosState(BasicType type) { switch (type) { case T_BYTE : return btos; - case T_BOOLEAN: return btos; // FIXME: Add ztos + case T_BOOLEAN: return ztos; case T_CHAR : return ctos; case T_SHORT : return stos; case T_INT : return itos; @@ -878,8 +879,8 @@ inline TosState as_TosState(BasicType type) { inline BasicType as_BasicType(TosState state) { switch (state) { - //case ztos: return T_BOOLEAN;//FIXME case btos : return T_BYTE; + case ztos : return T_BOOLEAN; case ctos : return T_CHAR; case stos : return T_SHORT; case itos : return T_INT; From 0edc09be0ce2f4c2dd3a96298e09d4735ab6e890 Mon Sep 17 00:00:00 2001 From: Vadim Pakhnushev Date: Tue, 20 Oct 2015 12:08:44 +0300 Subject: [PATCH 003/167] 8139008: Better state table management Reviewed-by: prr, srl, mschoene --- .../share/native/libfontmanager/layout/StateTableProcessor2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp index 9aa097a6f52..ab74b239d76 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp @@ -60,6 +60,7 @@ StateTableProcessor2::StateTableProcessor2(const LEReferenceToentryTableOffset); classTable = LEReferenceTo(stHeader, success, classTableOffset); + if (LE_FAILURE(success)) return; format = SWAPW(classTable->format); stateArray = LEReferenceToArrayOf(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY); From fc6a5d3bd2bb830fda0949944c1ba734d0deed1f Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Mon, 21 Dec 2015 10:43:40 -0800 Subject: [PATCH 004/167] 8143945: Better GCM validation Reviewed-by: xuelei, mullan --- .../com/sun/crypto/provider/GaloisCounterMode.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 9f8f54a1823..87fa4a383f3 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -512,11 +512,17 @@ final class GaloisCounterMode extends FeedbackCipher { byte[] sOut = new byte[s.length]; GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock); gctrForSToTag.doFinal(s, 0, s.length, sOut, 0); + + // check entire authentication tag for time-consistency + int mismatch = 0; for (int i = 0; i < tagLenBytes; i++) { - if (tag[i] != sOut[i]) { - throw new AEADBadTagException("Tag mismatch!"); - } + mismatch |= tag[i] ^ sOut[i]; } + + if (mismatch != 0) { + throw new AEADBadTagException("Tag mismatch!"); + } + return len; } From e171854b1c74dfa2ea9ab5ff9982ff8050247b58 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Wed, 23 Dec 2015 02:31:34 +0000 Subject: [PATCH 005/167] 8138593: Make DSA more fair Changed nounce K generation to FIPS 186-4 B2.1 Reviewed-by: mullan --- .../classes/sun/security/provider/DSA.java | 252 ++---------------- .../TestInitSignWithMyOwnRandom.java | 6 +- .../sun/security/provider/DSA/TestDSA2.java | 4 +- 3 files changed, 30 insertions(+), 232 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java index 6f8c27a38c0..a25949742bb 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java @@ -106,6 +106,18 @@ abstract class DSA extends SignatureSpi { this.p1363Format = p1363Format; } + private static void checkKey(DSAParams params, int digestLen, String mdAlgo) + throws InvalidKeyException { + // FIPS186-3 states in sec4.2 that a hash function which provides + // a lower security strength than the (L, N) pair ordinarily should + // not be used. + int valueN = params.getQ().bitLength(); + if (valueN > digestLen) { + throw new InvalidKeyException("The security strength of " + + mdAlgo + " digest algorithm is not sufficient for this key size"); + } + } + /** * Initialize the DSA object with a DSA private key. * @@ -130,6 +142,12 @@ abstract class DSA extends SignatureSpi { throw new InvalidKeyException("DSA private key lacks parameters"); } + // check key size against hash output size for signing + // skip this check for verification to minimize impact on existing apps + if (md.getAlgorithm() != "NullDigest20") { + checkKey(params, md.getDigestLength()*8, md.getAlgorithm()); + } + this.params = params; this.presetX = priv.getX(); this.presetY = null; @@ -160,7 +178,6 @@ abstract class DSA extends SignatureSpi { if (params == null) { throw new InvalidKeyException("DSA public key lacks parameters"); } - this.params = params; this.presetY = pub.getY(); this.presetX = null; @@ -406,20 +423,13 @@ abstract class DSA extends SignatureSpi { return t5.mod(q); } - // NOTE: This following impl is defined in FIPS 186-3 AppendixB.2.2. - // Original DSS algos such as SHA1withDSA and RawDSA uses a different - // algorithm defined in FIPS 186-1 Sec3.2, and thus need to override this. + // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1. protected BigInteger generateK(BigInteger q) { SecureRandom random = getSigningRandom(); - byte[] kValue = new byte[q.bitLength()/8]; + byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8]; - while (true) { - random.nextBytes(kValue); - BigInteger k = new BigInteger(1, kValue).mod(q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - return k; - } - } + random.nextBytes(kValue); + return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE); } // Use the application-specified SecureRandom Object if provided. @@ -504,222 +514,10 @@ abstract class DSA extends SignatureSpi { } } - static class LegacyDSA extends DSA { - /* The random seed used to generate k */ - private int[] kSeed; - /* The random seed used to generate k (specified by application) */ - private byte[] kSeedAsByteArray; - /* - * The random seed used to generate k - * (prevent the same Kseed from being used twice in a row - */ - private int[] kSeedLast; - - public LegacyDSA(MessageDigest md) throws NoSuchAlgorithmException { - this(md, false); - } - - private LegacyDSA(MessageDigest md, boolean p1363Format) - throws NoSuchAlgorithmException { - super(md, p1363Format); - } - - @Deprecated - protected void engineSetParameter(String key, Object param) { - if (key.equals("KSEED")) { - if (param instanceof byte[]) { - kSeed = byteArray2IntArray((byte[])param); - kSeedAsByteArray = (byte[])param; - } else { - debug("unrecognized param: " + key); - throw new InvalidParameterException("kSeed not a byte array"); - } - } else { - throw new InvalidParameterException("Unsupported parameter"); - } - } - - @Deprecated - protected Object engineGetParameter(String key) { - if (key.equals("KSEED")) { - return kSeedAsByteArray; - } else { - return null; - } - } - - /* - * Please read bug report 4044247 for an alternative, faster, - * NON-FIPS approved method to generate K - */ - @Override - protected BigInteger generateK(BigInteger q) { - BigInteger k = null; - - // The application specified a kSeed for us to use. - // Note: we dis-allow usage of the same Kseed twice in a row - if (kSeed != null && !Arrays.equals(kSeed, kSeedLast)) { - k = generateKUsingKSeed(kSeed, q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - kSeedLast = kSeed.clone(); - return k; - } - } - - // The application did not specify a Kseed for us to use. - // We'll generate a new Kseed by getting random bytes from - // a SecureRandom object. - SecureRandom random = getSigningRandom(); - - while (true) { - int[] seed = new int[5]; - - for (int i = 0; i < 5; i++) seed[i] = random.nextInt(); - - k = generateKUsingKSeed(seed, q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - kSeedLast = seed; - return k; - } - } - } - - /** - * Compute k for the DSA signature as defined in the original DSS, - * i.e. FIPS186. - * - * @param seed the seed for generating k. This seed should be - * secure. This is what is referred to as the KSEED in the DSA - * specification. - * - * @param g the g parameter from the DSA key pair. - */ - private BigInteger generateKUsingKSeed(int[] seed, BigInteger q) { - - // check out t in the spec. - int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476, - 0xC3D2E1F0, 0x67452301 }; - // - int[] tmp = SHA_7(seed, t); - byte[] tmpBytes = new byte[tmp.length * 4]; - for (int i = 0; i < tmp.length; i++) { - int k = tmp[i]; - for (int j = 0; j < 4; j++) { - tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8))); - } - } - BigInteger k = new BigInteger(1, tmpBytes).mod(q); - return k; - } - - // Constants for each round - private static final int round1_kt = 0x5a827999; - private static final int round2_kt = 0x6ed9eba1; - private static final int round3_kt = 0x8f1bbcdc; - private static final int round4_kt = 0xca62c1d6; - - /** - * Computes set 1 thru 7 of SHA-1 on m1. */ - static int[] SHA_7(int[] m1, int[] h) { - - int[] W = new int[80]; - System.arraycopy(m1,0,W,0,m1.length); - int temp = 0; - - for (int t = 16; t <= 79; t++){ - temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; - W[t] = ((temp << 1) | (temp >>>(32 - 1))); - } - - int a = h[0],b = h[1],c = h[2], d = h[3], e = h[4]; - for (int i = 0; i < 20; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - ((b&c)|((~b)&d))+ e + W[i] + round1_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 2 - for (int i = 20; i < 40; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - (b ^ c ^ d) + e + W[i] + round2_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 3 - for (int i = 40; i < 60; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - ((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 4 - for (int i = 60; i < 80; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - (b ^ c ^ d) + e + W[i] + round4_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - int[] md = new int[5]; - md[0] = h[0] + a; - md[1] = h[1] + b; - md[2] = h[2] + c; - md[3] = h[3] + d; - md[4] = h[4] + e; - return md; - } - - /* - * Utility routine for converting a byte array into an int array - */ - private int[] byteArray2IntArray(byte[] byteArray) { - - int j = 0; - byte[] newBA; - int mod = byteArray.length % 4; - - // guarantee that the incoming byteArray is a multiple of 4 - // (pad with 0's) - switch (mod) { - case 3: newBA = new byte[byteArray.length + 1]; break; - case 2: newBA = new byte[byteArray.length + 2]; break; - case 1: newBA = new byte[byteArray.length + 3]; break; - default: newBA = new byte[byteArray.length + 0]; break; - } - System.arraycopy(byteArray, 0, newBA, 0, byteArray.length); - - // copy each set of 4 bytes in the byte array into an integer - int[] newSeed = new int[newBA.length / 4]; - for (int i = 0; i < newBA.length; i += 4) { - newSeed[j] = newBA[i + 3] & 0xFF; - newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00; - newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000; - newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000; - j++; - } - - return newSeed; - } - } - /** * Standard SHA1withDSA implementation. */ - public static final class SHA1withDSA extends LegacyDSA { + public static final class SHA1withDSA extends DSA { public SHA1withDSA() throws NoSuchAlgorithmException { super(MessageDigest.getInstance("SHA-1")); } @@ -728,7 +526,7 @@ abstract class DSA extends SignatureSpi { /** * SHA1withDSA implementation that uses the IEEE P1363 format. */ - public static final class SHA1withDSAinP1363Format extends LegacyDSA { + public static final class SHA1withDSAinP1363Format extends DSA { public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException { super(MessageDigest.getInstance("SHA-1"), true); } @@ -741,7 +539,7 @@ abstract class DSA extends SignatureSpi { * not, a SignatureException is thrown when sign()/verify() is called * per JCA spec. */ - static class Raw extends LegacyDSA { + static class Raw extends DSA { // Internal special-purpose MessageDigest impl for RawDSA // Only override whatever methods used // NOTE: no clone support diff --git a/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java b/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java index 2a2121e249d..0d2d7fd35a4 100644 --- a/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java +++ b/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -55,9 +55,9 @@ class TestRandomSource extends SecureRandom { int count = 0; - public int nextInt() { + @Override + public void nextBytes(byte[] rs) { count++; - return 0; } public boolean isUsed() { diff --git a/jdk/test/sun/security/provider/DSA/TestDSA2.java b/jdk/test/sun/security/provider/DSA/TestDSA2.java index 00691535ac1..320acce4880 100644 --- a/jdk/test/sun/security/provider/DSA/TestDSA2.java +++ b/jdk/test/sun/security/provider/DSA/TestDSA2.java @@ -60,8 +60,8 @@ public class TestDSA2 { boolean[] expectedToPass = { true, true, true, true, true, true, true, true }; test(1024, expectedToPass); - boolean[] expectedToPass2 = { true, true, true, true, - true, true, true, true }; + boolean[] expectedToPass2 = { true, false, true, true, + true, false, true, true }; test(2048, expectedToPass2); } From 46cb32012acde827d2924895083a4cfada9864db Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 7 Jan 2016 13:59:49 -0500 Subject: [PATCH 006/167] 8146518: Zero interpreter broken with better byte behaviours Replaced Method::_result_type_index with Method::_result_type for better byte behaviours should be used for Zero also. Reviewed-by: roland, kvn, bdelsart, kevinw --- hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp | 7 ++++--- hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp | 6 +----- hotspot/src/share/vm/oops/method.cpp | 9 --------- hotspot/src/share/vm/oops/method.hpp | 12 ------------ 4 files changed, 5 insertions(+), 29 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 48143d50e72..43b45fad16a 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -94,6 +94,7 @@ intptr_t narrow(BasicType type, intptr_t result) { case T_SHORT: return (intptr_t)(jshort)result; case T_OBJECT: // nothing to do fall through + case T_ARRAY: case T_LONG: case T_INT: case T_FLOAT: @@ -184,7 +185,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[result_type_of(method)]; + result_slots = type2size[method->result_type()]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -222,7 +223,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { // Adjust result to smaller intptr_t res = result[-i]; if (result_slots == 1) { - res = narrow(result_type_of(method), res); + res = narrow(method->result_type(), res); } stack->push(res); } @@ -436,7 +437,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // Push our result if (!HAS_PENDING_EXCEPTION) { - BasicType type = result_type_of(method); + BasicType type = method->result_type(); stack->set_sp(stack->sp() - type2size[type]); switch (type) { diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp index 3a6bd52f2cb..9c0a2a01091 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -49,8 +49,4 @@ static intptr_t* calculate_unwind_sp(ZeroStack* stack, oop method_handle); static void throw_exception(JavaThread* thread, Symbol* name,char *msg=NULL); - private: - // Fast result type determination - static BasicType result_type_of(Method* method); - #endif // CPU_ZERO_VM_CPPINTERPRETER_ZERO_HPP diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index d6fe27a1c93..3491bda1c69 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -84,9 +84,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) { NoSafepointVerifier no_safepoint; set_constMethod(xconst); set_access_flags(access_flags); -#ifdef CC_INTERP - set_result_index(T_VOID); -#endif set_intrinsic_id(vmIntrinsics::_none); set_jfr_towrite(false); set_force_inline(false); @@ -445,12 +442,6 @@ void Method::compute_size_of_parameters(Thread *thread) { set_size_of_parameters(asc.size() + (is_static() ? 0 : 1)); } -#ifdef CC_INTERP -void Method::set_result_index(BasicType type) { - _result_index = Interpreter::BasicType_as_index(type); -} -#endif - BasicType Method::result_type() const { ResultTypeFinder rtf(signature()); return rtf.type(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index a1acd932cea..264a07db004 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -69,9 +69,6 @@ class Method : public Metadata { AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) // note: can have vtables with >2**16 elements (because of inheritance) -#ifdef CC_INTERP - int _result_index; // C++ interpreter needs for converting results to/from stack -#endif u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) // Flags @@ -171,11 +168,6 @@ class Method : public Metadata { return constMethod()->type_annotations(); } -#ifdef CC_INTERP - void set_result_index(BasicType type); - int result_index() { return _result_index; } -#endif - // Helper routine: get klass name + "." + method name + signature as // C string, for the purpose of providing more useful NoSuchMethodErrors // and fatal error handling. The string is allocated in resource @@ -552,7 +544,6 @@ class Method : public Metadata { void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments) Symbol* klass_name() const; // returns the name of the method holder BasicType result_type() const; // type of the method result - int result_type_index() const; // type index of the method result bool is_returning_oop() const { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); } bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); } @@ -653,9 +644,6 @@ class Method : public Metadata { // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } static ByteSize access_flags_offset() { return byte_offset_of(Method, _access_flags ); } -#ifdef CC_INTERP - static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); } -#endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } static ByteSize method_data_offset() { From 29aeb056925592e0c463a46149d12df9b7884cbc Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 13 Jan 2016 11:23:25 -0800 Subject: [PATCH 007/167] 8146498: Better device table adjustments Reviewed-by: vadim, mschoene --- .../share/native/libfontmanager/layout/DeviceTables.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp index df4df194fcf..7ea3032fe97 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp @@ -45,9 +45,12 @@ const le_uint16 DeviceTable::fieldBits[] = { 2, 4, 8}; le_int16 DeviceTable::getAdjustment(const LEReferenceTo&base, le_uint16 ppem, LEErrorCode &success) const { + le_int16 result = 0; + if (LE_FAILURE(success)) { + return result; + } le_uint16 start = SWAPW(startSize); le_uint16 format = SWAPW(deltaFormat) - 1; - le_int16 result = 0; if (ppem >= start && ppem <= SWAPW(endSize) && format < FORMAT_COUNT) { le_uint16 sizeIndex = ppem - start; From 11920c3315e20a6948bea7bb7ccad45601271fca Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 13 Jan 2016 11:24:11 -0800 Subject: [PATCH 008/167] 8146494: Better ligature substitution Reviewed-by: vadim, mschoene --- .../layout/LigatureSubstProc.cpp | 20 +++++++++++++++++++ .../layout/LigatureSubstProc2.cpp | 20 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp index 5a94563fa5b..76131fd2193 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp @@ -71,6 +71,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp { LEErrorCode success = LE_NO_ERROR; const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); + if (LE_FAILURE(success)) { + currGlyph++; + return 0; + } ByteOffset newState = SWAPW(entry->newStateOffset); le_uint16 flags = SWAPW(entry->flags); @@ -91,6 +95,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp if (actionOffset != 0) { LEReferenceTo ap(stHeader, success, actionOffset); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } LigatureActionEntry action; le_int32 offset, i = 0, j = 0; le_int32 stack[nComponents]; @@ -101,6 +109,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp if (j++ > 0) { ap.addObject(success); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } } action = SWAPL(*ap.getAlias()); @@ -124,9 +136,17 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp return newState; // get out! bad font } i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success)); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } if (action & (lafLast | lafStore)) { LEReferenceTo ligatureOffset(stHeader, success, i); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias()); glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp index 77e907322ed..1a4709e1d81 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp @@ -95,6 +95,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp if (actionOffset != 0) { LEReferenceTo ap(stHeader, success, ligActionOffset); // byte offset + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } ap.addObject(ligActionIndex, success); LEReferenceToArrayOf ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY); LigatureActionEntry action; @@ -104,8 +108,8 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp LEReferenceToArrayOf componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY); if(LE_FAILURE(success)) { - currGlyph+= dir; - return nextStateIndex; // get out! bad font + currGlyph+= dir; + return nextStateIndex; // get out! bad font } do { @@ -114,6 +118,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp if (j++ > 0) { ap.addObject(success); } + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } action = SWAPL(*ap.getAlias()); @@ -129,9 +137,17 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp return nextStateIndex; // get out! bad font } i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success)); + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } if (action & (lafLast | lafStore)) { TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success)); + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); if(mm==nComponents) { LE_DEBUG_BAD_FONT("exceeded nComponents"); From 0aa59442eb94dc59551dbebca4ee4504cd0d7d37 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 20 Jan 2016 20:51:45 +0000 Subject: [PATCH 009/167] 8129952: Ensure thread consistency Reviewed-by: alanb, ahgross, skoivu --- .../classes/java/io/ObjectInputStream.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index dbf10bd757d..60fc7947435 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1915,6 +1915,8 @@ public class ObjectInputStream if (obj == null || handles.lookupException(passHandle) != null) { defaultReadFields(null, slotDesc); // skip field values } else if (slotDesc.hasReadObjectMethod()) { + ThreadDeath t = null; + boolean reset = false; SerialCallbackContext oldContext = curContext; if (oldContext != null) oldContext.check(); @@ -1933,10 +1935,19 @@ public class ObjectInputStream */ handles.markException(passHandle, ex); } finally { - curContext.setUsed(); - if (oldContext!= null) - oldContext.check(); - curContext = oldContext; + do { + try { + curContext.setUsed(); + if (oldContext!= null) + oldContext.check(); + curContext = oldContext; + reset = true; + } catch (ThreadDeath x) { + t = x; // defer until reset is true + } + } while (!reset); + if (t != null) + throw t; } /* From 83e0997bbda9529859c37fc302f665ad5ac047c9 Mon Sep 17 00:00:00 2001 From: Shanliang Jiang Date: Fri, 22 Jan 2016 13:27:09 +0100 Subject: [PATCH 010/167] 8144430: Improve JMX connections Reviewed-by: dfuchs, jbachorik, skoivu, ahgross --- .../classes/java/io/ObjectInputStream.java | 40 ++++++-- .../misc/JavaObjectInputStreamAccess.java | 41 ++++++++ .../misc/ObjectStreamClassValidator.java | 42 ++++++++ .../jdk/internal/misc/SharedSecrets.java | 16 +++- .../remote/rmi/RMIConnectorServer.java | 18 +++- .../remote/rmi/RMIJRMPServerImpl.java | 88 ++++++++++++++++- .../jmxremote/ConnectorBootstrap.java | 6 ++ .../rmi/server/DeserializationChecker.java | 93 ++++++++++++++++++ .../sun/rmi/server/MarshalInputStream.java | 42 +++++++- .../sun/rmi/server/UnicastServerRef.java | 95 +++++++++++++++++-- 10 files changed, 455 insertions(+), 26 deletions(-) create mode 100644 jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java create mode 100644 jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index 60fc7947435..cd040d3d7e5 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -40,6 +40,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; +import jdk.internal.misc.JavaObjectInputStreamAccess; +import jdk.internal.misc.ObjectStreamClassValidator; +import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.Unsafe; import sun.reflect.misc.ReflectUtil; @@ -1509,23 +1512,28 @@ public class ObjectInputStream throws IOException { byte tc = bin.peekByte(); + ObjectStreamClass descriptor; switch (tc) { case TC_NULL: - return (ObjectStreamClass) readNull(); - + descriptor = (ObjectStreamClass) readNull(); + break; case TC_REFERENCE: - return (ObjectStreamClass) readHandle(unshared); - + descriptor = (ObjectStreamClass) readHandle(unshared); + break; case TC_PROXYCLASSDESC: - return readProxyDesc(unshared); - + descriptor = readProxyDesc(unshared); + break; case TC_CLASSDESC: - return readNonProxyDesc(unshared); - + descriptor = readNonProxyDesc(unshared); + break; default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } + if (descriptor != null) { + validateDescriptor(descriptor); + } + return descriptor; } private boolean isCustomSubclass() { @@ -3658,4 +3666,20 @@ public class ObjectInputStream } } + private void validateDescriptor(ObjectStreamClass descriptor) { + ObjectStreamClassValidator validating = validator; + if (validating != null) { + validating.validateDescriptor(descriptor); + } + } + + // controlled access to ObjectStreamClassValidator + private volatile ObjectStreamClassValidator validator; + + private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) { + ois.validator = validator; + } + static { + SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator); + } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java new file mode 100644 index 00000000000..c344f8adc7c --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.misc; + +import java.io.ObjectInputStream; + +/** + * The interface to specify methods for accessing {@code ObjectInputStream} + * @author sjiang + */ +public interface JavaObjectInputStreamAccess { + /** + * Sets a descriptor validating. + * @param ois stream to have the descriptors validated + * @param validator validator used to validate a descriptor. + */ + public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator); +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java b/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java new file mode 100644 index 00000000000..2b543a30721 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.misc; + +import java.io.ObjectStreamClass; + +/** + * A callback used by {@code ObjectInputStream} to do descriptor validation. + * + * @author sjiang + */ +public interface ObjectStreamClassValidator { + /** + * This method will be called by ObjectInputStream to + * check a descriptor just before creating an object described by this descriptor. + * The object will not be created if this method throws a {@code RuntimeException}. + * @param descriptor descriptor to be checked. + */ + public void validateDescriptor(ObjectStreamClass descriptor); +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index 3246bde5be1..24dc4ce43a7 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,9 @@ import java.lang.module.ModuleDescriptor; import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; +import java.io.ObjectInputStream; import java.security.ProtectionDomain; import java.security.AccessController; -import jdk.internal.misc.Unsafe; /** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without @@ -63,6 +63,7 @@ public class SharedSecrets { private static JavaAWTAccess javaAWTAccess; private static JavaAWTFontAccess javaAWTFontAccess; private static JavaBeansAccess javaBeansAccess; + private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -262,4 +263,15 @@ public class SharedSecrets { public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) { javaUtilResourceBundleAccess = access; } + + public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() { + if (javaObjectInputStreamAccess == null) { + unsafe.ensureClassInitialized(ObjectInputStream.class); + } + return javaObjectInputStreamAccess; + } + + public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) { + javaObjectInputStreamAccess = access; + } } diff --git a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java index fe90422c193..a71bef5b403 100644 --- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ import java.util.Set; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; +import javax.management.remote.JMXAuthenticator; import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXConnector; @@ -99,6 +100,21 @@ public class RMIConnectorServer extends JMXConnectorServer { public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.server.socket.factory"; + /** + * Name of the attribute that specifies a list of class names acceptable + * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()} + * remote method call. + *

+ * This list of classes should correspond to the transitive closure of the + * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator} + * associated with the {@linkplain RMIServer} implementation. + *

+ * If the attribute is not set, or is null, then any class is + * deemed acceptable. + */ + public static final String CREDENTIAL_TYPES = + "jmx.remote.rmi.server.credential.types"; + /** *

Makes an RMIConnectorServer. * This is equivalent to calling {@link #RMIConnectorServer( diff --git a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java index 0e45c966c9c..838c092ca48 100644 --- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java +++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,13 @@ import javax.security.auth.Subject; import com.sun.jmx.remote.internal.RMIExporter; import com.sun.jmx.remote.util.EnvHelp; +import java.io.ObjectStreamClass; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import sun.reflect.misc.ReflectUtil; +import sun.rmi.server.DeserializationChecker; import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef2; @@ -52,6 +59,9 @@ import sun.rmi.server.UnicastServerRef2; * @since 1.5 */ public class RMIJRMPServerImpl extends RMIServerImpl { + + private final ExportedWrapper exportedWrapper; + /** *

Creates a new {@link RMIServer} object that will be exported * on the given port using the given socket factories.

@@ -89,10 +99,31 @@ public class RMIJRMPServerImpl extends RMIServerImpl { this.csf = csf; this.ssf = ssf; this.env = (env == null) ? Collections.emptyMap() : env; + + String[] credentialsTypes + = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES); + List types = null; + if (credentialsTypes != null) { + types = new ArrayList<>(); + for (String type : credentialsTypes) { + if (type == null) { + throw new IllegalArgumentException("A credential type is null."); + } + ReflectUtil.checkPackageAccess(type); + types.add(type); + } + } + exportedWrapper = types != null ? + new ExportedWrapper(this, types) : + null; } protected void export() throws IOException { - export(this); + if (exportedWrapper != null) { + export(exportedWrapper); + } else { + export(this); + } } private void export(Remote obj) throws RemoteException { @@ -142,7 +173,11 @@ public class RMIJRMPServerImpl extends RMIServerImpl { * RMIJRMPServerImpl has not been exported yet. */ public Remote toStub() throws IOException { - return RemoteObject.toStub(this); + if (exportedWrapper != null) { + return RemoteObject.toStub(exportedWrapper); + } else { + return RemoteObject.toStub(this); + } } /** @@ -189,11 +224,56 @@ public class RMIJRMPServerImpl extends RMIServerImpl { * server failed. */ protected void closeServer() throws IOException { - unexport(this, true); + if (exportedWrapper != null) { + unexport(exportedWrapper, true); + } else { + unexport(this, true); + } } private final int port; private final RMIClientSocketFactory csf; private final RMIServerSocketFactory ssf; private final Map env; + + private static class ExportedWrapper implements RMIServer, DeserializationChecker { + private final RMIServer impl; + private final List allowedTypes; + + private ExportedWrapper(RMIServer impl, List credentialsTypes) { + this.impl = impl; + allowedTypes = credentialsTypes; + } + + @Override + public String getVersion() throws RemoteException { + return impl.getVersion(); + } + + @Override + public RMIConnection newClient(Object credentials) throws IOException { + return impl.newClient(credentials); + } + + @Override + public void check(Method method, ObjectStreamClass descriptor, + int paramIndex, int callID) { + String type = descriptor.getName(); + if (!allowedTypes.contains(type)) { + throw new ClassCastException("Unsupported type: " + type); + } + } + + @Override + public void checkProxyClass(Method method, String[] ifaces, + int paramIndex, int callID) { + if (ifaces != null && ifaces.length > 0) { + for (String iface : ifaces) { + if (!allowedTypes.contains(iface)) { + throw new ClassCastException("Unsupported type: " + iface); + } + } + } + } + } } diff --git a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index 5ef0f7f1708..477b7786421 100644 --- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java @@ -510,6 +510,9 @@ public final class ConnectorBootstrap { // This RMI server should not keep the VM alive Map env = new HashMap<>(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter()); + env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{ + String[].class.getName(), String.class.getName() + }); // The local connector server need only be available via the // loopback connection. @@ -740,6 +743,9 @@ public final class ConnectorBootstrap { PermanentExporter exporter = new PermanentExporter(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter); + env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{ + String[].class.getName(), String.class.getName() + }); boolean useSocketFactory = bindAddress != null && !useSsl; diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java new file mode 100644 index 00000000000..8182b10bfbe --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.rmi.server; + +import java.io.ObjectStreamClass; +import java.lang.reflect.Method; + +/** + * Implementing this interface to have a deserialization control when RMI + * dispatches a remote request. If an exported object implements this interface, + * RMI dispatching mechanism will call the method {@code check} every time + * deserialising a remote object for invoking a method of the exported object. + * + * @author sjiang + */ +public interface DeserializationChecker { + /** + * Will be called to check a descriptor. + * This method may be called 2 times, the first time is when a descriptor is read + * from the stream, the second is just before creating an object described + * by this descriptor. + * + * @param method the method invoked from a remote request. + * @param descriptor The descriptor of the class of any object deserialised + * while deserialising the parameter. The first descriptor will be that of + * the top level object (the concrete class of the parameter itself); + * Subsequent calls with the same {@code method}, {@code paramIndex} and + * {@code callID} will correspond to objects contained in the parameter. + * @param paramIndex an index indicates the position of a parameter in the + * method. This index will be reused for deserialising all + * objects contained in the parameter object. For example, the parameter + * being deserialised is a {@code List}, all deserialisation calls for its + * elements will have same index. + * @param callID a unique ID identifying one + * time method invocation, the same ID is used for deserialization call of + * all parameters within the method. + */ + public void check(Method method, + ObjectStreamClass descriptor, + int paramIndex, + int callID); + + /** + * Will be called to validate a Proxy interfaces from a remote user before loading it. + * @param method the method invoked from a remote request. + * @param ifaces a string table of all interfaces implemented by the proxy to be checked. + * @param paramIndex an index indicates the position of a parameter in the + * method. This index will be reused for deserialising all + * objects contained in the parameter object. For example, the parameter + * being deserialised is a {@code List}, all deserialisation calls for its + * elements will have same index. + * @param callID a unique ID identifying one + * time method invocation, the same ID is used for deserialization call of + * all parameters within the method. + */ + public void checkProxyClass(Method method, + String[] ifaces, + int paramIndex, + int callID); + + /** + * Inform of the completion of parameter deserialisation for a method invocation. + * This is useful if the last parameter is a complex object, like a {@code List} + * which elements are complex object too. + * + * The default implementation does nothing. + * @param callID the ID identifying a method invocation. + */ + public default void end(int callID) {} +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java index 3453e61f517..59c0be3360e 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,13 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; -import java.net.URL; import java.util.*; import java.security.AccessControlException; import java.security.Permission; - import java.rmi.server.RMIClassLoader; import java.security.PrivilegedAction; +import jdk.internal.misc.ObjectStreamClassValidator; +import jdk.internal.misc.SharedSecrets; /** * MarshalInputStream is an extension of ObjectInputStream. When resolving @@ -54,6 +54,11 @@ import java.security.PrivilegedAction; * @author Peter Jones */ public class MarshalInputStream extends ObjectInputStream { + interface StreamChecker extends ObjectStreamClassValidator { + void checkProxyInterfaceNames(String[] ifaces); + } + + private volatile StreamChecker streamChecker = null; /** * Value of "java.rmi.server.useCodebaseOnly" property, @@ -123,7 +128,7 @@ public class MarshalInputStream extends ObjectInputStream { throws IOException, StreamCorruptedException { super(in); - } + } /** * Returns a callback previously registered via the setDoneCallback @@ -240,6 +245,11 @@ public class MarshalInputStream extends ObjectInputStream { protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { + StreamChecker checker = streamChecker; + if (checker != null) { + checker.checkProxyInterfaceNames(interfaces); + } + /* * Always read annotation written by MarshalOutputStream. */ @@ -319,4 +329,28 @@ public class MarshalInputStream extends ObjectInputStream { void useCodebaseOnly() { useCodebaseOnly = true; } + + synchronized void setStreamChecker(StreamChecker checker) { + streamChecker = checker; + SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker); + } + @Override + protected ObjectStreamClass readClassDescriptor() throws IOException, + ClassNotFoundException { + ObjectStreamClass descriptor = super.readClassDescriptor(); + + validateDesc(descriptor); + + return descriptor; + } + + private void validateDesc(ObjectStreamClass descriptor) { + StreamChecker checker; + synchronized (this) { + checker = streamChecker; + } + if (checker != null) { + checker.validateDescriptor(descriptor); + } + } } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java index b608f237cf5..3c57aa4b2d2 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package sun.rmi.server; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.io.PrintStream; +import java.io.ObjectStreamClass; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.rmi.MarshalException; @@ -52,6 +52,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.atomic.AtomicInteger; import sun.rmi.runtime.Log; import sun.rmi.transport.LiveRef; import sun.rmi.transport.Target; @@ -116,6 +117,8 @@ public class UnicastServerRef extends UnicastRef private static final Map,?> withoutSkeletons = Collections.synchronizedMap(new WeakHashMap,Void>()); + private final AtomicInteger methodCallIDCount = new AtomicInteger(0); + /** * Create a new (empty) Unicast server remote reference. */ @@ -297,14 +300,11 @@ public class UnicastServerRef extends UnicastRef logCall(obj, method); // unmarshal parameters - Class[] types = method.getParameterTypes(); - Object[] params = new Object[types.length]; + Object[] params = null; try { unmarshalCustomCallData(in); - for (int i = 0; i < types.length; i++) { - params[i] = unmarshalValue(types[i], in); - } + params = unmarshalParameters(obj, method, marshalStream); } catch (java.io.IOException e) { throw new UnmarshalException( "error unmarshalling arguments", e); @@ -565,4 +565,85 @@ public class UnicastServerRef extends UnicastRef return map; } } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Perform any necessary checks. + */ + private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in) + throws IOException, ClassNotFoundException { + return (obj instanceof DeserializationChecker) ? + unmarshalParametersChecked((DeserializationChecker)obj, method, in) : + unmarshalParametersUnchecked(method, in); + } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Do not perform any additional checks. + */ + private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in) + throws IOException, ClassNotFoundException { + Class[] types = method.getParameterTypes(); + Object[] params = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + params[i] = unmarshalValue(types[i], in); + } + return params; + } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Do perform all additional checks. + */ + private Object[] unmarshalParametersChecked( + DeserializationChecker checker, + Method method, MarshalInputStream in) + throws IOException, ClassNotFoundException { + int callID = methodCallIDCount.getAndIncrement(); + MyChecker myChecker = new MyChecker(checker, method, callID); + in.setStreamChecker(myChecker); + try { + Class[] types = method.getParameterTypes(); + Object[] values = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + myChecker.setIndex(i); + values[i] = unmarshalValue(types[i], in); + } + myChecker.end(callID); + return values; + } finally { + in.setStreamChecker(null); + } + } + + private static class MyChecker implements MarshalInputStream.StreamChecker { + private final DeserializationChecker descriptorCheck; + private final Method method; + private final int callID; + private int parameterIndex; + + MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) { + this.descriptorCheck = descriptorCheck; + this.method = method; + this.callID = callID; + } + + @Override + public void validateDescriptor(ObjectStreamClass descriptor) { + descriptorCheck.check(method, descriptor, parameterIndex, callID); + } + + @Override + public void checkProxyInterfaceNames(String[] ifaces) { + descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID); + } + + void setIndex(int parameterIndex) { + this.parameterIndex = parameterIndex; + } + + void end(int callId) { + descriptorCheck.end(callId); + } + } } From 9105842337913b9b8e5922b1195efe050459b194 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 8 Feb 2016 12:54:57 +0000 Subject: [PATCH 011/167] 8148475: Missing SA Bytecode updates Reviewed-by: coleenp --- .../jvm/hotspot/interpreter/Bytecodes.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java index 3f09ee30c19..8f51fb8cb8b 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,29 +253,30 @@ public class Bytecodes { public static final int _fast_sgetfield = 210; public static final int _fast_aputfield = 211; public static final int _fast_bputfield = 212; - public static final int _fast_cputfield = 213; - public static final int _fast_dputfield = 214; - public static final int _fast_fputfield = 215; - public static final int _fast_iputfield = 216; - public static final int _fast_lputfield = 217; - public static final int _fast_sputfield = 218; - public static final int _fast_aload_0 = 219; - public static final int _fast_iaccess_0 = 220; - public static final int _fast_aaccess_0 = 221; - public static final int _fast_faccess_0 = 222; - public static final int _fast_iload = 223; - public static final int _fast_iload2 = 224; - public static final int _fast_icaload = 225; - public static final int _fast_invokevfinal = 226; - public static final int _fast_linearswitch = 227; - public static final int _fast_binaryswitch = 228; - public static final int _fast_aldc = 229; - public static final int _fast_aldc_w = 230; - public static final int _return_register_finalizer = 231; - public static final int _invokehandle = 232; - public static final int _shouldnotreachhere = 233; // For debugging + public static final int _fast_zputfield = 213; + public static final int _fast_cputfield = 214; + public static final int _fast_dputfield = 215; + public static final int _fast_fputfield = 216; + public static final int _fast_iputfield = 217; + public static final int _fast_lputfield = 218; + public static final int _fast_sputfield = 219; + public static final int _fast_aload_0 = 220; + public static final int _fast_iaccess_0 = 221; + public static final int _fast_aaccess_0 = 222; + public static final int _fast_faccess_0 = 223; + public static final int _fast_iload = 224; + public static final int _fast_iload2 = 225; + public static final int _fast_icaload = 226; + public static final int _fast_invokevfinal = 227; + public static final int _fast_linearswitch = 228; + public static final int _fast_binaryswitch = 229; + public static final int _fast_aldc = 230; + public static final int _fast_aldc_w = 231; + public static final int _return_register_finalizer = 232; + public static final int _invokehandle = 233; + public static final int _shouldnotreachhere = 234; // For debugging - public static final int number_of_codes = 234; + public static final int number_of_codes = 235; // Flag bits derived from format strings, can_trap, can_rewrite, etc.: // semantic flags: @@ -776,6 +777,7 @@ public class Bytecodes { def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield ); From ea91682fe1e6b041f366466b5f3445ad8e141dc6 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 9 Feb 2016 15:54:16 -0500 Subject: [PATCH 012/167] 8149170: Better byte behavior should normalize JNI arguments Arguments coming from native should be converted to 0=false, 1-255=true Reviewed-by: kvn, kevinw, jrose, bdelsart, gtriantafill --- hotspot/make/test/JtregNative.gmk | 3 +- hotspot/src/share/vm/prims/jni.cpp | 26 +++++++- .../runtime/BoolReturn/BoolConstructor.java | 35 +++++++++++ .../BoolReturn/NativeSmallIntCallsTest.java | 60 +++++++++++++++++++ .../BoolReturn/libNativeSmallIntCalls.c | 57 ++++++++++++++++++ 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 hotspot/test/runtime/BoolReturn/BoolConstructor.java create mode 100644 hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java create mode 100644 hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 95c6bf242b7..62478ce6923 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \ $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ + $(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ $(HOTSPOT_TOPDIR)/test/compiler/native \ diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 2f9b49359c5..8c1a020ac0f 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -919,7 +919,14 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { protected: va_list _ap; - inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = va_arg(_ap, jint); + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg @@ -960,9 +967,17 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { while ( 1 ) { switch ( fingerprint & parameter_feature_mask ) { case bool_parm: + get_bool(); + break; case char_parm: + get_char(); + break; case short_parm: + get_short(); + break; case byte_parm: + get_byte(); + break; case int_parm: get_int(); break; @@ -996,7 +1011,14 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher { protected: const jvalue *_ap; - inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); } + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = (_ap++)->z; + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int((jint)(_ap++)->c); } inline void get_short() { _arguments->push_int((jint)(_ap++)->s); } inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); } diff --git a/hotspot/test/runtime/BoolReturn/BoolConstructor.java b/hotspot/test/runtime/BoolReturn/BoolConstructor.java new file mode 100644 index 00000000000..c870a4e6366 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/BoolConstructor.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; + +public class BoolConstructor { + + boolean field; + BoolConstructor(boolean b, boolean expected) { + field = b; + // System.out.println("b is " + b + " field is " + field); + Asserts.assertTrue(field == b, "BoolConstructor argument not converted correctly"); + Asserts.assertTrue(field == expected, "BoolConstructor argument not stored correctly"); + } +} diff --git a/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java new file mode 100644 index 00000000000..d911435382a --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8149170 + * @summary Test native functions return booleans as 0/1 but differently than java functions + * @library /testlibrary + * @compile BoolConstructor.java + * @run main/native NativeSmallIntCallsTest + */ + +// This test shows that returns from native calls for boolean truncate to JNI_TRUE if value != 0 +// and JNI_FALSE if value returned is 0. + +import jdk.test.lib.Asserts; + +public class NativeSmallIntCallsTest { + static native boolean nativeCastToBoolCallTrue(); + static native boolean nativeCastToBoolCallFalse(); + static native boolean nativeCallBoolConstructor(int visible, boolean expected); + static { + System.loadLibrary("NativeSmallIntCalls"); + } + + public static void main(java.lang.String[] unused) throws Exception { + // Call through jni + // JNI makes all results != 0 true for compatibility + boolean nativeTrueVal = nativeCastToBoolCallTrue(); + Asserts.assertTrue(nativeTrueVal, "trueval is false!"); + + boolean nativeFalseVal = nativeCastToBoolCallFalse(); + Asserts.assertTrue(nativeFalseVal, "falseval is false in native!"); + + // Call a constructor or method that passes jboolean values into Java from native + nativeCallBoolConstructor(1, true); + nativeCallBoolConstructor(0x10, true); + nativeCallBoolConstructor(0x100, false); + nativeCallBoolConstructor(0x1000, false); + } +} diff --git a/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c new file mode 100644 index 00000000000..acf09ac41f8 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT void JNICALL +Java_NativeSmallIntCallsTest_nativeCallBoolConstructor(JNIEnv* env, jobject obj, int visible, int expected) { + jclass cls; + jmethodID ctor; + + cls = (*env)->FindClass(env, "BoolConstructor"); + if(NULL == cls) { + return; + } + + ctor = (*env)->GetMethodID(env, cls, "", "(ZZ)V"); + if(NULL == ctor) { + return; + } + + // printf("visible 0x%x expected %d\n", visible, expected); + + (*env)->NewObject(env, cls, ctor, (jboolean) visible, expected); +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallTrue(JNIEnv* env, jobject obj) { + + return 55; +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallFalse(JNIEnv* env, jobject obj) { + + return 44; +} + From f1b44959119f484f6744b9a53984656560ea74c8 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sat, 20 Feb 2016 14:11:18 -0800 Subject: [PATCH 013/167] 8149367: PolicyQualifierInfo/index_Ctor JCk test fails with IOE: Invalid encoding for PolicyQualifierInfo Fix incorrect code Reviewed-by: jrose, coleenp, kevinw --- .../src/share/vm/runtime/deoptimization.cpp | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 9c038d74c48..d380bf6d518 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -896,13 +896,25 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_at_put(index, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_at_put(index, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_at_put(index, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_at_put(index, (jboolean)*((jint*)&val)); @@ -1017,13 +1029,25 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_field_put(offset, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_field_put(offset, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_field_put(offset, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_field_put(offset, (jboolean)*((jint*)&val)); From c606f158a9cf51e4ddc4703f0c0b79a0584c912c Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Sun, 21 Feb 2016 08:33:59 -0500 Subject: [PATCH 014/167] 8150012: Better byte behavior for reflection Reviewed-by: kvn, jrose, kevinw, ahgross --- hotspot/src/share/vm/oops/typeArrayOop.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index 8ab2f4d1f74..adf99a30fe4 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -96,7 +96,7 @@ class typeArrayOopDesc : public arrayOopDesc { void byte_at_put(int which, jbyte contents) { *byte_at_addr(which) = contents; } jboolean bool_at(int which) const { return *bool_at_addr(which); } - void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = contents; } + void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = (((jint)contents) & 1); } jchar char_at(int which) const { return *char_at_addr(which); } void char_at_put(int which, jchar contents) { *char_at_addr(which) = contents; } From 43e034bc512d81cb6c31ab4d9afc711034ccde71 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 25 Feb 2016 21:45:26 +0000 Subject: [PATCH 015/167] 8150654: Zero cleanup of CppInterpreter::result_type_of() Reviewed-by: coleenp --- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 43b45fad16a..e05e6d65bc0 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -804,26 +804,6 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { return (InterpreterFrame *) fp; } -BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t = T_ILLEGAL; // silence compiler warnings - switch (method->result_index()) { - case 0 : t = T_BOOLEAN; break; - case 1 : t = T_CHAR; break; - case 2 : t = T_BYTE; break; - case 3 : t = T_SHORT; break; - case 4 : t = T_INT; break; - case 5 : t = T_LONG; break; - case 6 : t = T_VOID; break; - case 7 : t = T_FLOAT; break; - case 8 : t = T_DOUBLE; break; - case 9 : t = T_OBJECT; break; - default: ShouldNotReachHere(); - } - assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), - "out of step with AbstractInterpreter::BasicType_as_index"); - return t; -} - address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { ShouldNotCallThis(); return NULL; From 49b2db4ae7ff6499003679f87df594ba5947ffad Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 18 Mar 2016 18:07:55 -0700 Subject: [PATCH 016/167] 8152335: Improve MethodHandle consistency Co-authored-by: Michael Haupt Reviewed-by: acorn, ahgross, jrose --- .../share/classes/java/lang/ClassLoader.java | 3 + .../classes/java/lang/invoke/MemberName.java | 29 ++++++-- .../java/lang/invoke/MethodHandleNatives.java | 2 +- .../classes/sun/invoke/util/VerifyAccess.java | 68 +++++++++++++++---- 4 files changed, 82 insertions(+), 20 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 1fcd03b760f..61123302a3c 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -817,6 +817,9 @@ public abstract class ClassLoader { if (!checkName(name)) throw new NoClassDefFoundError("IllegalName: " + name); + // Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias + // relies on the fact that spoofing is impossible if a class has a name + // of the form "java.*" if ((name != null) && name.startsWith("java.") && this != getBuiltinPlatformClassLoader()) { throw new SecurityException diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index d141efcac6e..de4e3c15537 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -827,7 +827,7 @@ import java.util.Objects; assert(isResolved() == isResolved); } - void checkForTypeAlias() { + void checkForTypeAlias(Class refc) { if (isInvocable()) { MethodType type; if (this.type instanceof MethodType) @@ -835,16 +835,16 @@ import java.util.Objects; else this.type = type = getMethodType(); if (type.erase() == type) return; - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad method type alias: "+type+" not visible from "+refc); } else { Class type; if (this.type instanceof Class) type = (Class) this.type; else this.type = type = getFieldType(); - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad field type alias: "+type+" not visible from "+refc); } } @@ -1016,10 +1016,25 @@ import java.util.Objects; MemberName m = ref.clone(); // JVM will side-effect the ref assert(refKind == m.getReferenceKind()); try { + // There are 4 entities in play here: + // * LC: lookupClass + // * REFC: symbolic reference class (MN.clazz before resolution); + // * DEFC: resolved method holder (MN.clazz after resolution); + // * PTYPES: parameter types (MN.type) + // + // What we care about when resolving a MemberName is consistency between DEFC and PTYPES. + // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM + // finishes the resolution, so do TA checks right after MHN.resolve() is over. + // + // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation, + // so it is safe to call a MH from any context. + // + // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't + // participate in method selection. m = MethodHandleNatives.resolve(m, lookupClass); - m.checkForTypeAlias(); + m.checkForTypeAlias(m.getDeclaringClass()); m.resolution = null; - } catch (LinkageError ex) { + } catch (ClassNotFoundException | LinkageError ex) { // JVM reports that the "bytecode behavior" would get an error assert(!m.isResolved()); m.resolution = ex; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 7a5d3f1f0b2..67c197dd709 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -49,7 +49,7 @@ class MethodHandleNatives { static native void init(MemberName self, Object ref); static native void expand(MemberName self); - static native MemberName resolve(MemberName self, Class caller) throws LinkageError; + static native MemberName resolve(MemberName self, Class caller) throws LinkageError, ClassNotFoundException; static native int getMembers(Class defc, String matchName, String matchSig, int matchFlags, Class caller, int skip, MemberName[] results); diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java index 456909fde1c..37cbede912a 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java @@ -231,22 +231,66 @@ public class VerifyAccess { * @param refc the class attempting to make the reference */ public static boolean isTypeVisible(Class type, Class refc) { - if (type == refc) return true; // easy check + if (type == refc) { + return true; // easy check + } while (type.isArray()) type = type.getComponentType(); - if (type.isPrimitive() || type == Object.class) return true; - ClassLoader parent = type.getClassLoader(); - if (parent == null) return true; - ClassLoader child = refc.getClassLoader(); - if (child == null) return false; - if (parent == child || loadersAreRelated(parent, child, true)) + if (type.isPrimitive() || type == Object.class) { return true; - // Do it the hard way: Look up the type name from the refc loader. - try { - Class res = child.loadClass(type.getName()); - return (type == res); - } catch (ClassNotFoundException ex) { + } + ClassLoader typeLoader = type.getClassLoader(); + ClassLoader refcLoader = refc.getClassLoader(); + if (typeLoader == refcLoader) { + return true; + } + if (refcLoader == null && typeLoader != null) { return false; } + if (typeLoader == null && type.getName().startsWith("java.")) { + // Note: The API for actually loading classes, ClassLoader.defineClass, + // guarantees that classes with names beginning "java." cannot be aliased, + // because class loaders cannot load them directly. + return true; + } + + // Do it the hard way: Look up the type name from the refc loader. + // + // Force the refc loader to report and commit to a particular binding for this type name (type.getName()). + // + // In principle, this query might force the loader to load some unrelated class, + // which would cause this query to fail (and the original caller to give up). + // This would be wasted effort, but it is expected to be very rare, occurring + // only when an attacker is attempting to create a type alias. + // In the normal case, one class loader will simply delegate to the other, + // and the same type will be visible through both, with no extra loading. + // + // It is important to go through Class.forName instead of ClassLoader.loadClass + // because Class.forName goes through the JVM system dictionary, which records + // the class lookup once for all. This means that even if a not-well-behaved class loader + // would "change its mind" about the meaning of the name, the Class.forName request + // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary + // will record the first successful result. Unsuccessful results are not stored. + // + // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary + // class loader about the binding of the proposed name (type.getName()). + // The looked up type ("res") is compared for equality against the proposed + // type ("type") and then is discarded. Thus, the worst that can happen to + // the "child" class loader is that it is bothered to load and report a class + // that differs from "type"; this happens once due to JVM system dictionary + // memoization. And the caller never gets to look at the alternate type binding + // ("res"), whether it exists or not. + final String name = type.getName(); + Class res = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<>() { + public Class run() { + try { + return Class.forName(name, false, refcLoader); + } catch (ClassNotFoundException | LinkageError e) { + return null; // Assume the class is not found + } + } + }); + return (type == res); } /** From 8543426a278f7d168c1985827a5bb49597080ab5 Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Wed, 30 Mar 2016 15:26:10 +0530 Subject: [PATCH 017/167] 8033936: java.awt.List events are not sent properly to handleEvent or ItemListener Reviewed-by: serb, psadhukhan --- .../windows/native/libawt/windows/awt_List.h | 1 + .../awt/List/ItemEventTest/ItemEventTest.java | 143 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h index 73effc3a56e..3450089b509 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h @@ -56,6 +56,7 @@ public: } INLINE void Deselect(int pos) { if (isMultiSelect) { + SendListMessage(LB_SETCARETINDEX, pos, FALSE); SendListMessage(LB_SETSEL, FALSE, pos); } else { diff --git a/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java b/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java new file mode 100644 index 00000000000..c239b01360c --- /dev/null +++ b/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033936 + * @summary Verify that correct ItemEvent is received while selection & + * deselection of multi select List items. + */ + +import java.awt.AWTException; +import java.awt.Event; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class ItemEventTest extends Frame +{ + List list; + final String expectedSelectionOrder; + StringBuilder actualSelectionOrder; + Robot robot; + + public ItemEventTest() + { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + expectedSelectionOrder = "01230123"; + + list = new List(4, true); + list.add("0"); + list.add("1"); + list.add("2"); + list.add("3"); + + add(list); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + } + + @Override + public boolean handleEvent(Event e) { + if (e.target instanceof List) { + if (e.id == Event.LIST_DESELECT || e.id == Event.LIST_SELECT) { + actualSelectionOrder.append(e.arg); + } + } + return true; + } + + void testHandleEvent() { + // When no ItemListener is added to List, parent's handleEvent is + // called with ItemEvent. + performTest(); + } + + void testItemListener() { + list.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent ie) { + actualSelectionOrder.append(ie.getItem()); + } + }); + performTest(); + } + + void performTest() { + actualSelectionOrder = new StringBuilder(); + Point loc = list.getLocationOnScreen(); + Rectangle rect = list.getBounds(); + int dY = rect.height / list.getItemCount(); + loc = new Point(loc.x + 10, loc.y + 5); + + String osName = System.getProperty("os.name"); + boolean isMac = osName.contains("Mac") || osName.contains("mac"); + if(isMac) { + robot.keyPress(KeyEvent.VK_META); + } + + // First loop to select & Second loop to deselect the list items. + for (int j = 0; j < 2; ++j) { + for (int i = 0; i < list.getItemCount(); ++i) { + robot.mouseMove(loc.x, loc.y + i * dY); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(100); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.waitForIdle(); + } + } + + if(isMac) { + robot.keyRelease(KeyEvent.VK_META); + } + + if (!expectedSelectionOrder.equals(actualSelectionOrder.toString())) { + dispose(); + throw new RuntimeException("ItemEvent for selection & deselection" + + " of multi select List's item is not correct" + + " Expected : " + expectedSelectionOrder + + " Actual : " + actualSelectionOrder); + } + } + + public static void main(String args[]) { + ItemEventTest test = new ItemEventTest(); + test.testHandleEvent(); + test.testItemListener(); + test.dispose(); + } +} From 61f991148093946b63a335a44cb08153f3b5ecc5 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 30 Mar 2016 16:00:43 +0530 Subject: [PATCH 018/167] 8061258: [macosx] PrinterJob's native Print Dialog does not reflect specified Copies or Page Ranges Reviewed-by: prr, jdv --- .../native/libawt_lwawt/awt/CPrinterJob.m | 50 +++--- .../awt/print/PrinterJob/DlgAttrsBug.java | 152 ++++++++++++++++++ 2 files changed, 179 insertions(+), 23 deletions(-) create mode 100644 jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m index 165e7029497..b1428528730 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m @@ -368,6 +368,8 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj static JNF_MEMBER_CACHE(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z"); static JNF_MEMBER_CACHE(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I"); + static JNF_MEMBER_CACHE(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I"); + static JNF_MEMBER_CACHE(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); @@ -379,31 +381,33 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj jboolean collated = JNFCallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object) [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate]; - jint jNumPages = JNFCallIntMethod(env, srcPageable, jm_getNumberOfPages); // AWT_THREADING Safe (!appKit) - if (jNumPages != java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES) - { - jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); - if (selectID ==0) { - [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; - } else if (selectID == 2) { - // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether - // NSPrintAllPages is YES or NO - [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; - [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; - } else { - [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; - } - - jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage); - jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage); - // setting fromPage and toPage will not be shown in the dialog if printing All pages - [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; - [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; - } - else - { + jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); + jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage); + jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage); + if (selectID ==0) { [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; + } else if (selectID == 2) { + // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether + // NSPrintAllPages is YES or NO + [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; + [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; + } else { + jint minPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMinPage); + jint maxPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMaxPage); + + // for PD_SELECTION or PD_NOSELECTION, check from/to page + // to determine which radio button to select + if (fromPage > minPage || toPage < maxPage) { + [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; + } else { + [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; + } } + + // setting fromPage and toPage will not be shown in the dialog if printing All pages + [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; + [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; + jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat); if (page != NULL) { javaPageFormatToNSPrintInfo(env, NULL, page, dst); diff --git a/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java b/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java new file mode 100644 index 00000000000..dc31ffda1fd --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8061258 + * @summary PrinterJob's native Print Dialog does not reflect + * specified Copies or Page Ranges + * @run main/manual DlgAttrsBug + */ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + + +public class DlgAttrsBug implements Printable { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(DlgAttrsBug::printTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("Print Dialog does not " + + "reflect Copies or Page Ranges"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void printTest() { + PrinterJob job = PrinterJob.getPrinterJob(); + if (job.getPrintService() == null) { + System.out.println("No printers. Test cannot continue"); + return; + } + job.setPrintable(new DlgAttrsBug()); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(new Copies(5)); + aset.add(new PageRanges(3,4)); + aset.add(DialogTypeSelection.NATIVE); + job.printDialog(aset); + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " Visual inspection of print dialog is required.\n" + + " A print dialog will be shown.\n " + + " Please verify Copies 5 is selected.\n" + + " Also verify, Page Range is selected with " + + " from page 3 and to Page 4.\n" + + " If ok, press PASS else press FAIL"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + } + + public int print(Graphics g, PageFormat pf, int pi) + throws PrinterException { + System.out.println("pi = " + pi); + if (pi >= 5) { + return NO_SUCH_PAGE; + } + g.drawString("Page : " + (pi+1), 200, 200); + return PAGE_EXISTS; + } + +} From dfbe023cec5a5159f8787993ebe2adb4342c3607 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 30 Mar 2016 17:17:00 +0530 Subject: [PATCH 019/167] 8042713: [macosx] Print dialog does not update attribute set with page range Reviewed-by: prr, jdv --- .../classes/sun/lwawt/macosx/CPrinterJob.java | 40 +++++++- .../native/libawt_lwawt/awt/CPrinterJob.m | 14 ++- .../PrinterJob/PrintAttributeUpdateTest.java | 91 +++++++++++++++++++ 3 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 491b257765f..aa00647de21 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -36,6 +36,7 @@ import java.security.PrivilegedAction; import javax.print.*; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaPrintableArea; import javax.print.attribute.standard.MediaSize; @@ -194,10 +195,37 @@ public final class CPrinterJob extends RasterPrinterJob { // setPageRange will set firstPage and lastPage as called in getFirstPage // and getLastPage setPageRange(range[0][0] - 1, range[0][1] - 1); + } else { + // if rangeSelect is SunPageSelection.ALL + // then setPageRange appropriately + setPageRange(-1, -1); } } } + private void setPageRangeAttribute(int from, int to, boolean isRangeSet) { + if (attributes != null) { + // since native Print use zero-based page indices, + // we need to store in 1-based format in attributes set + // but setPageRange again uses zero-based indices so it should be + // 1 less than pageRanges attribute + if (isRangeSet) { + attributes.add(new PageRanges(from+1, to+1)); + attributes.add(SunPageSelection.RANGE); + setPageRange(from, to); + } else { + attributes.add(SunPageSelection.ALL); + } + } + } + + private void setCopiesAttribute(int copies) { + if (attributes != null) { + attributes.add(new Copies(copies)); + super.setCopies(copies); + } + } + volatile boolean onEventThread; @Override @@ -691,9 +719,15 @@ public final class CPrinterJob extends RasterPrinterJob { if (pageFormat != null) { Printable printable = pageable.getPrintable(pageIndex); if (printable != null) { - BufferedImage bimg = new BufferedImage((int)Math.round(pageFormat.getWidth()), (int)Math.round(pageFormat.getHeight()), BufferedImage.TYPE_INT_ARGB_PRE); - PeekGraphics peekGraphics = createPeekGraphics(bimg.createGraphics(), printerJob); - Rectangle2D pageFormatArea = getPageFormatArea(pageFormat); + BufferedImage bimg = + new BufferedImage( + (int)Math.round(pageFormat.getWidth()), + (int)Math.round(pageFormat.getHeight()), + BufferedImage.TYPE_INT_ARGB_PRE); + PeekGraphics peekGraphics = + createPeekGraphics(bimg.createGraphics(), printerJob); + Rectangle2D pageFormatArea = + getPageFormatArea(pageFormat); initPrinterGraphics(peekGraphics, pageFormatArea); // Do the assignment here! diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m index b1428528730..03a32ddd8e7 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m @@ -312,9 +312,9 @@ static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobjec static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable) { static JNF_MEMBER_CACHE(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V"); - static JNF_MEMBER_CACHE(jm_setCopies, sjc_CPrinterJob, "setCopies", "(I)V"); + static JNF_MEMBER_CACHE(jm_setCopiesAttribute, sjc_CPrinterJob, "setCopiesAttribute", "(I)V"); static JNF_MEMBER_CACHE(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V"); - static JNF_MEMBER_CACHE(jm_setPageRange, sjc_CPrinterJob, "setPageRange", "(II)V"); + static JNF_MEMBER_CACHE(jm_setPageRangeAttribute, sjc_CPrinterJob, "setPageRangeAttribute", "(IIZ)V"); // get the selected printer's name, and set the appropriate PrintService on the Java side NSString *name = [[src printer] name]; @@ -327,7 +327,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies]; if ([nsCopies respondsToSelector:@selector(integerValue)]) { - JNFCallVoidMethod(env, dstPrinterJob, jm_setCopies, [nsCopies integerValue]); // AWT_THREADING Safe (known object) + JNFCallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object) } NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate]; @@ -340,6 +340,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d if ([nsPrintAllPages respondsToSelector:@selector(boolValue)]) { jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES; + jboolean isRangeSet = false; if (![nsPrintAllPages boolValue]) { NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage]; @@ -353,9 +354,12 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d { jLastPage = [nsLastPage integerValue] - 1; } - } + isRangeSet = true; + } + JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute, + jFirstPage, jLastPage, isRangeSet); + // AWT_THREADING Safe (known object) - JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRange, jFirstPage, jLastPage); // AWT_THREADING Safe (known object) } } diff --git a/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java b/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java new file mode 100644 index 00000000000..f068964c4e1 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + @test + @bug 8042713 + @summary Print Dialog does not update attribute set with page range + @run main/manual PrintAttributeUpdateTest + */ +import java.awt.Component; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Printable; +import java.awt.print.PrinterJob; +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.print.attribute.standard.PageRanges; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +public class PrintAttributeUpdateTest implements Pageable, Printable { + + public static void main(String args[]) throws Exception { + String[] instructions + = { + "Select Pages Range From instead of All in print dialog. ", + "Then select Print" + }; + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog((Component) null, + instructions, "Instructions", + JOptionPane.INFORMATION_MESSAGE); + }); + HashPrintRequestAttributeSet as = new HashPrintRequestAttributeSet(); + PrinterJob j = PrinterJob.getPrinterJob(); + j.setPageable(new PrintAttributeUpdateTest()); + as.add(DialogTypeSelection.NATIVE); + j.printDialog(as); + if (as.containsKey(PageRanges.class) == false) { + throw new RuntimeException("Print Dialog did not update " + + " attribute set with page range"); + } + Attribute attrs[] = as.toArray(); + for (int i = 0; i < attrs.length; i++) { + System.out.println("attr " + attrs[i]); + } + j.print(as); + } + + public int getNumberOfPages() { + return UNKNOWN_NUMBER_OF_PAGES; + } + + public PageFormat getPageFormat(int pageIndex) { + PageFormat pf = new PageFormat(); + return pf; + } + + public Printable getPrintable(int pageIndex) { + return this; + } + + public int print(Graphics g, PageFormat pgFmt, int pi) { + g.drawString("Page : " + (pi + 1), 200, 200); + + return PAGE_EXISTS; + } + +} From e7e8e6904f7222cf9fe4d74119e0bf6a1d62c3ac Mon Sep 17 00:00:00 2001 From: Ajit Ghaisas Date: Thu, 31 Mar 2016 15:30:05 +0530 Subject: [PATCH 020/167] 6353518: Creation of a WritableRaster with a custom DataBuffer causes erroneous Exception Reviewed-by: serb, prr, flar --- .../classes/sun/java2d/IntegerNIORaster.java | 12 +- .../share/classes/java/awt/image/Raster.java | 178 ++++++--- .../sun/awt/image/ByteBandedRaster.java | 35 +- .../sun/awt/image/ByteComponentRaster.java | 37 +- .../sun/awt/image/ByteInterleavedRaster.java | 35 +- .../sun/awt/image/BytePackedRaster.java | 35 +- .../sun/awt/image/IntegerComponentRaster.java | 36 +- .../awt/image/IntegerInterleavedRaster.java | 34 +- .../sun/awt/image/ShortBandedRaster.java | 34 +- .../sun/awt/image/ShortComponentRaster.java | 34 +- .../sun/awt/image/ShortInterleavedRaster.java | 31 +- .../java/awt/image/RasterCreationTest.java | 352 ++++++++++++++++++ 12 files changed, 621 insertions(+), 232 deletions(-) create mode 100644 jdk/test/java/awt/image/RasterCreationTest.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java b/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java index 59101b74006..e2dfcf20d73 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class IntegerNIORaster extends SunWritableRaster { ") cannot be <= 0"); } // This is cribbed from java.awt.image.Raster. - DataBuffer db = new DataBufferNIOInt(w * h); + DataBufferNIOInt db = new DataBufferNIOInt(w * h); if (location == null) { location = new Point(0, 0); } @@ -48,13 +48,11 @@ public class IntegerNIORaster extends SunWritableRaster { return new IntegerNIORaster(sppsm, db, location); } - public IntegerNIORaster(SampleModel sampleModel, DataBuffer dataBuffer, Point origin) { + public IntegerNIORaster(SampleModel sampleModel, DataBufferNIOInt dataBuffer, Point origin) { // This is all cribbed from sun.awt.image.IntegerInterleavedRaster & sun.awt.image.IntegerComponentRaster super(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, sampleModel.getWidth(), sampleModel.getHeight()), origin, null); - if (!(dataBuffer instanceof DataBufferNIOInt)) { - throw new RasterFormatException("IntegerNIORasters must have DataBufferNIOInt DataBuffers"); - } - this.data = ((DataBufferNIOInt)dataBuffer).getBuffer(); + + this.data = dataBuffer.getBuffer(); } public WritableRaster createCompatibleWritableRaster() { diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java b/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java index f5a36d10a47..c7aca57eed8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -629,7 +629,8 @@ public class Raster { int scanlineStride, int pixelStride, int bandOffsets[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -645,15 +646,26 @@ public class Raster { bandOffsets); switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(csm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteInterleavedRaster(csm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(csm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortInterleavedRaster(csm, + (DataBufferUShort) dataBuffer, location); + } + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(csm, dataBuffer, location); } /** @@ -691,7 +703,8 @@ public class Raster { int scanlineStride, int bankIndices[], int bandOffsets[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -713,18 +726,29 @@ public class Raster { switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteBandedRaster(bsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteBandedRaster(bsm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortBandedRaster(bsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortBandedRaster(bsm, + (DataBufferUShort) dataBuffer, location); + } + break; case DataBuffer.TYPE_INT: - return new SunWritableRaster(bsm, dataBuffer, location); + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(bsm, dataBuffer, location); } /** @@ -761,7 +785,8 @@ public class Raster { int w, int h, int scanlineStride, int bandMasks[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -776,18 +801,33 @@ public class Raster { switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteInterleavedRaster(sppsm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sppsm, + (DataBufferUShort) dataBuffer, location); + } + break; case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sppsm, + (DataBufferInt) dataBuffer, location); + } + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(sppsm, dataBuffer, location); } /** @@ -821,7 +861,8 @@ public class Raster { public static WritableRaster createPackedRaster(DataBuffer dataBuffer, int w, int h, int bitsPerPixel, - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -846,9 +887,10 @@ public class Raster { MultiPixelPackedSampleModel mppsm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel); - if (dataType == DataBuffer.TYPE_BYTE && - (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) { - return new BytePackedRaster(mppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte && + (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) + { + return new BytePackedRaster(mppsm, (DataBufferByte) dataBuffer, location); } else { return new SunWritableRaster(mppsm, dataBuffer, location); } @@ -878,7 +920,8 @@ public class Raster { */ public static Raster createRaster(SampleModel sm, DataBuffer db, - Point location) { + Point location) + { if ((sm == null) || (db == null)) { throw new NullPointerException("SampleModel and DataBuffer cannot be null"); } @@ -890,32 +933,53 @@ public class Raster { if (sm instanceof PixelInterleavedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; } } else if (sm instanceof SinglePixelPackedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; - case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_INT: + if (db instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sm, + (DataBufferInt) db, location); + } + break; } } else if (sm instanceof MultiPixelPackedSampleModel && dataType == DataBuffer.TYPE_BYTE && - sm.getSampleSize(0) < 8) { - return new BytePackedRaster(sm, db, location); + db instanceof DataBufferByte && + sm.getSampleSize(0) < 8) + { + return new BytePackedRaster(sm, (DataBufferByte) db, location); } // we couldn't do anything special - do the generic thing - - return new Raster(sm,db,location); + return new Raster(sm, db, location); } /** @@ -964,7 +1028,8 @@ public class Raster { */ public static WritableRaster createWritableRaster(SampleModel sm, DataBuffer db, - Point location) { + Point location) + { if ((sm == null) || (db == null)) { throw new NullPointerException("SampleModel and DataBuffer cannot be null"); } @@ -976,32 +1041,53 @@ public class Raster { if (sm instanceof PixelInterleavedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; } } else if (sm instanceof SinglePixelPackedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; - case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_INT: + if (db instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sm, + (DataBufferInt) db, location); + } + break; } } else if (sm instanceof MultiPixelPackedSampleModel && dataType == DataBuffer.TYPE_BYTE && - sm.getSampleSize(0) < 8) { - return new BytePackedRaster(sm, db, location); + db instanceof DataBufferByte && + sm.getSampleSize(0) < 8) + { + return new BytePackedRaster(sm, (DataBufferByte) db, location); } // we couldn't do anything special - do the generic thing - - return new SunWritableRaster(sm,db,location); + return new SunWritableRaster(sm, db, location); } /** diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java index 699c1ea2f43..1123a9f69fd 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -74,10 +73,9 @@ public class ByteBandedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specifies the origin. */ - public ByteBandedRaster(SampleModel sampleModel, - Point origin) { + public ByteBandedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -93,12 +91,13 @@ public class ByteBandedRaster extends SunWritableRaster { * initialized and must be a DataBufferShort compatible with SampleModel. * SampleModel must be of type BandedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x , origin.y, sampleModel.getWidth(), @@ -119,39 +118,33 @@ public class ByteBandedRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, + DataBufferByte dataBuffer, Rectangle aRegion, Point origin, - ByteBandedRaster parent) { - + ByteBandedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteBandedRaster must have" + - "byte DataBuffers"); - } - DataBufferByte dbb = (DataBufferByte)dataBuffer; - if (sampleModel instanceof BandedSampleModel) { BandedSampleModel bsm = (BandedSampleModel)sampleModel; this.scanlineStride = bsm.getScanlineStride(); int bankIndices[] = bsm.getBankIndices(); int bandOffsets[] = bsm.getBandOffsets(); - int dOffsets[] = dbb.getOffsets(); + int dOffsets[] = dataBuffer.getOffsets(); dataOffsets = new int[bankIndices.length]; data = new byte[bankIndices.length][]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; for (int i = 0; i < bankIndices.length; i++) { - data[i] = stealData(dbb, bankIndices[i]); + data[i] = stealData(dataBuffer, bankIndices[i]); dataOffsets[i] = dOffsets[bankIndices[i]] + xOffset + yOffset*scanlineStride + bandOffsets[i]; } @@ -672,7 +665,7 @@ public class ByteBandedRaster extends SunWritableRaster { int deltaY = y0 - y; return new ByteBandedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java index 673e51d8518..f284e3b1fc4 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -94,7 +93,7 @@ public class ByteComponentRaster extends SunWritableRaster { */ public ByteComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -111,12 +110,13 @@ public class ByteComponentRaster extends SunWritableRaster { * SampleModel must be of type SinglePixelPackedSampleModel * or ComponentSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -141,33 +141,28 @@ public class ByteComponentRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ByteComponentRaster parent) { + DataBufferByte dataBuffer, + Rectangle aRegion, + Point origin, + ByteComponentRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteComponentRasters must have " + - "byte DataBuffers"); - } - - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); - if (dbb.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for ByteComponentRasters"+ " must only have 1 bank."); } - int dbOffset = dbb.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel ism = (ComponentSampleModel)sampleModel; @@ -823,7 +818,7 @@ public class ByteComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new ByteComponentRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java index 52f01b30b63..b406fb65211 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -87,7 +86,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { */ public ByteInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -104,12 +103,13 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * SampleModel must be of type SinglePixelPackedSampleModel * or InterleavedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -178,27 +178,22 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ByteInterleavedRaster parent) { + DataBufferByte dataBuffer, + Rectangle aRegion, + Point origin, + ByteInterleavedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteInterleavedRasters must have " + - "byte DataBuffers"); - } - - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); + this.data = stealData(dataBuffer, 0); int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -221,7 +216,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbb.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride; } else { throw new RasterFormatException("ByteInterleavedRasters must " + @@ -1259,7 +1254,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { int deltaY = y0 - y; return new ByteInterleavedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java index f9696c17eb8..ac00075c16a 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.MultiPixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -89,10 +88,9 @@ public class BytePackedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public BytePackedRaster(SampleModel sampleModel, - Point origin) { + public BytePackedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -108,12 +106,13 @@ public class BytePackedRaster extends SunWritableRaster { * initialized and must be a DataBufferByte compatible with SampleModel. * SampleModel must be of type MultiPixelPackedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public BytePackedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -137,7 +136,7 @@ public class BytePackedRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. @@ -146,26 +145,22 @@ public class BytePackedRaster extends SunWritableRaster { * to requirements of this Raster type. */ public BytePackedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, + DataBufferByte dataBuffer, Rectangle aRegion, Point origin, - BytePackedRaster parent){ + BytePackedRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("BytePackedRasters must have" + - "byte DataBuffers"); - } - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); - if (dbb.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for BytePackedRasters"+ " must only have 1 bank."); } - int dbOffset = dbb.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = @@ -1322,7 +1317,7 @@ public class BytePackedRaster extends SunWritableRaster { int deltaY = y0 - y; return new BytePackedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java index cd84986b77f..44ab7253083 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.Rectangle; import java.awt.Point; @@ -107,10 +106,9 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public IntegerComponentRaster(SampleModel sampleModel, - Point origin) { + public IntegerComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferInt) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -130,8 +128,9 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public IntegerComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferInt dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -161,24 +160,21 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public IntegerComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - IntegerComponentRaster parent){ + DataBufferInt dataBuffer, + Rectangle aRegion, + Point origin, + IntegerComponentRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin,parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferInt)) { - throw new RasterFormatException("IntegerComponentRasters must have" + - "integer DataBuffers"); - } - DataBufferInt dbi = (DataBufferInt)dataBuffer; - if (dbi.getNumBanks() != 1) { + + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for IntegerComponentRasters"+ " must only have 1 bank."); } - this.data = stealData(dbi, 0); + this.data = stealData(dataBuffer, 0); if (sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = @@ -197,7 +193,7 @@ public class IntegerComponentRaster extends SunWritableRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbi.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); this.bandOffset = this.dataOffsets[0]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -569,7 +565,7 @@ public class IntegerComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new IntegerComponentRaster(sm, - dataBuffer, + (DataBufferInt) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java index a852080a701..48ec3eed7ad 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.Rectangle; import java.awt.Point; @@ -67,10 +66,9 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public IntegerInterleavedRaster(SampleModel sampleModel, - Point origin) { + public IntegerInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferInt) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -90,8 +88,9 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param origin The Point that specifies the origin. */ public IntegerInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferInt dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -121,19 +120,16 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param parent The parent (if any) of this raster. */ public IntegerInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - IntegerInterleavedRaster parent){ + DataBufferInt dataBuffer, + Rectangle aRegion, + Point origin, + IntegerInterleavedRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin,parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferInt)) { - throw new RasterFormatException("IntegerInterleavedRasters must have" + - "integer DataBuffers"); - } - DataBufferInt dbi = (DataBufferInt)dataBuffer; - this.data = stealData(dbi, 0); + + this.data = stealData(dataBuffer, 0); if (sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = @@ -141,7 +137,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbi.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); this.bandOffset = this.dataOffsets[0]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -481,7 +477,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { int deltaY = y0 - y; return new IntegerInterleavedRaster(sm, - dataBuffer, + (DataBufferInt) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java index fd5c610504d..6222c61b5e9 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -72,10 +71,9 @@ public class ShortBandedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public ShortBandedRaster(SampleModel sampleModel, - Point origin) { + public ShortBandedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -95,8 +93,9 @@ public class ShortBandedRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public ShortBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -123,32 +122,27 @@ public class ShortBandedRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public ShortBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortBandedRaster parent) { - + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortBandedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortBandedRaster must have " + - "ushort DataBuffers"); - } - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; if (sampleModel instanceof BandedSampleModel) { BandedSampleModel bsm = (BandedSampleModel)sampleModel; this.scanlineStride = bsm.getScanlineStride(); int bankIndices[] = bsm.getBankIndices(); int bandOffsets[] = bsm.getBandOffsets(); - int dOffsets[] = dbus.getOffsets(); + int dOffsets[] = dataBuffer.getOffsets(); dataOffsets = new int[bankIndices.length]; data = new short[bankIndices.length][]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; for (int i = 0; i < bankIndices.length; i++) { - data[i] = stealData(dbus, bankIndices[i]); + data[i] = stealData(dataBuffer, bankIndices[i]); dataOffsets[i] = dOffsets[bankIndices[i]] + xOffset + yOffset*scanlineStride + bandOffsets[i]; } @@ -670,7 +664,7 @@ public class ShortBandedRaster extends SunWritableRaster { int deltaY = y0 - y; return new ShortBandedRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java index 76ab7d75ce4..79016e9df5a 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -94,7 +93,7 @@ public class ShortComponentRaster extends SunWritableRaster { */ public ShortComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -115,8 +114,9 @@ public class ShortComponentRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public ShortComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -146,28 +146,22 @@ public class ShortComponentRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public ShortComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortComponentRaster parent) { - + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortComponentRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if(!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortComponentRasters must have "+ - "short DataBuffers"); - } - - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; - this.data = stealData(dbus, 0); - if (dbus.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for ShortComponentRasters"+ " must only have 1 bank."); } - int dbOffset = dbus.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; @@ -758,7 +752,7 @@ public class ShortComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new ShortComponentRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java index 05310891fe5..7a1644b6275 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -71,7 +70,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { */ public ShortInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -92,8 +91,9 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param origin The Point that specifies the origin. */ public ShortInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -123,22 +123,17 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param parent The parent (if any) of this raster. */ public ShortInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortInterleavedRaster parent) { + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortInterleavedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if(!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortInterleavedRasters must "+ - "have ushort DataBuffers"); - } - - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; - this.data = stealData(dbus, 0); + this.data = stealData(dataBuffer, 0); // REMIND: need case for interleaved ComponentSampleModel if ((sampleModel instanceof PixelInterleavedSampleModel) || @@ -160,7 +155,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbus.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; dataOffsets[0] += xOffset+yOffset*scanlineStride; @@ -730,7 +725,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { int deltaY = y0 - y; return new ShortInterleavedRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/test/java/awt/image/RasterCreationTest.java b/jdk/test/java/awt/image/RasterCreationTest.java new file mode 100644 index 00000000000..885fb8da76d --- /dev/null +++ b/jdk/test/java/awt/image/RasterCreationTest.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Point; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferDouble; +import java.awt.image.DataBufferFloat; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.DataBufferUShort; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.PixelInterleavedSampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + +/* + * @test + * @bug 6353518 + * @summary Test possible combinations of Raster creation + * Test fails if any of Raster.createXXX() method throws exception. + */ +public class RasterCreationTest { + + public static void main(String[] args) { + + final int width = 10; + final int height = 5; + final int imageSize = width * height; + Point location = new Point(0, 0); + int[] bandOffsets = {0}; + int[] bitMask = {0x00ff0000, 0x0000ff00, 0xff, 0x0}; + + SampleModel[] inputSampleModels = { + new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, + 1, 1, 1, 1, bandOffsets), + new PixelInterleavedSampleModel(DataBuffer.TYPE_USHORT, + 1, 1, 1, 1, bandOffsets), + new PixelInterleavedSampleModel(DataBuffer.TYPE_INT, + 1, 1, 1, 1, bandOffsets), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, bitMask), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT, + width, height, bitMask), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, + width, height, bitMask), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, 4), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_USHORT, + width, height, 2), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_INT, + width, height, 2) + }; + + // --------------------------------------------------------------------- + // Test ability to create Raster & WritableRaster with DataBuffer + // classes + // --------------------------------------------------------------------- + DataBuffer[] inputDataBuffer = { + new DataBufferByte(imageSize), + new DataBufferUShort(imageSize), + new DataBufferInt(imageSize, 1), + new DataBufferShort(imageSize), + new DataBufferFloat(imageSize), + new DataBufferDouble(imageSize) + }; + + for (SampleModel sm : inputSampleModels) { + for (DataBuffer db : inputDataBuffer) { + // Test Raster creation + Raster.createRaster(sm, db, location); + + // Test writableRaster creation + Raster.createWritableRaster(sm, db, location); + Raster.createWritableRaster(sm, location); + } + } + + // --------------------------------------------------------------------- + // Test ability to create Raster & WritableRaster with custom DataBuffer + // classes + // --------------------------------------------------------------------- + DataBuffer[] myDataBuffer = { + new MyDataBufferByte(imageSize), + new MyDataBufferUShort(imageSize), + new MyDataBufferInt(imageSize), + new MyDataBufferShort(imageSize), + new MyDataBufferDouble(imageSize), + new MyDataBufferFloat(imageSize) + }; + + for (SampleModel sm : inputSampleModels) { + for (DataBuffer db : myDataBuffer) { + // Test Raster creation + Raster.createRaster(sm, db, location); + + // Test writableRaster creation + Raster.createWritableRaster(sm, db, location); + Raster.createWritableRaster(sm, location); + } + } + + // --------------------------------------------------------------------- + // Test ability to create InterleavedRaster + // --------------------------------------------------------------------- + int[] interleavedInputDataTypes = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT + }; + + int numBands = 1; + + for (int i : interleavedInputDataTypes) { + Raster.createInterleavedRaster(i, width, height, 1, location); + Raster.createInterleavedRaster(i, width, height, width * numBands, + numBands, bandOffsets, location); + } + + for (int i = 0; i < interleavedInputDataTypes.length ; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + Raster.createInterleavedRaster(d1, width, height, width * numBands, + numBands, bandOffsets, location); + Raster.createInterleavedRaster(d2, width, height, width * numBands, + numBands, bandOffsets, location); + } + + // --------------------------------------------------------------------- + // Test ability to create BandedRaster + // --------------------------------------------------------------------- + int[] bankIndices = new int[numBands]; + bankIndices[0] = 0; + + int[] bandedInputDataTypes = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT + }; + + for (int i : bandedInputDataTypes) { + Raster.createBandedRaster(i, width, height, 1, location); + Raster.createBandedRaster(i, width, height, width, + bankIndices, bandOffsets, location); + } + + for (int i = 0; i < bandedInputDataTypes.length; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + Raster.createBandedRaster(d1, width, height, width, + bankIndices, bandOffsets, location); + Raster.createBandedRaster(d2, width, height, width, + bankIndices, bandOffsets, location); + } + + // --------------------------------------------------------------------- + // Test ability to create PackedRaster + // --------------------------------------------------------------------- + int[] bandMasks = new int[numBands]; + bandMasks[0] = 0; + + int packedInputDataTypes[] = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT + }; + + for (int i : packedInputDataTypes) { + Raster.createPackedRaster(i, width, height, bandMasks, location); + + for (int bits = 1; bits < 5; bits *= 2) { + Raster.createPackedRaster(i, width, height, 1, bits, location); + } + } + + for (int i = 0; i < packedInputDataTypes.length; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + for (int bits = 1; bits < 5; bits *= 2) { + Raster.createPackedRaster(d1, width, height, bits, location); + Raster.createPackedRaster(d2, width, height, bits, location); + } + + Raster.createPackedRaster(d1, width, height, 1,bandMasks, location); + Raster.createPackedRaster(d2, width, height, 1,bandMasks, location); + } + } +} + +// --------------------------------------------------------------------- +// Custom DataBuffer classes for testing purpose +// --------------------------------------------------------------------- +final class MyDataBufferByte extends DataBuffer { + + byte[] data; + byte[][] bankdata; + + public MyDataBufferByte(int size) { + super(TYPE_BYTE, size); + data = new byte[size]; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (byte) val; + } +} + +final class MyDataBufferDouble extends DataBuffer { + + double[] data; + double[][] bankdata; + + public MyDataBufferDouble(int size) { + super(TYPE_DOUBLE, size); + data = new double[size]; + bankdata = new double[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return (int) bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (double) val; + } +} + +final class MyDataBufferFloat extends DataBuffer { + + float[] data; + float[][] bankdata; + + public MyDataBufferFloat(int size) { + super(TYPE_FLOAT, size); + data = new float[size]; + bankdata = new float[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return (int) bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (float) val; + } +} + +final class MyDataBufferShort extends DataBuffer { + + short[] data; + short[][] bankdata; + + public MyDataBufferShort(int size) { + super(TYPE_SHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (short) val; + } +} + +final class MyDataBufferUShort extends DataBuffer { + + short[] data; + short[][] bankdata; + + public MyDataBufferUShort(int size) { + super(TYPE_USHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (short) val; + } +} + +final class MyDataBufferInt extends DataBuffer { + + int[] data; + int[][] bankdata; + + public MyDataBufferInt(int size) { + super(TYPE_INT, size); + data = new int[size]; + bankdata = new int[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (int) val; + } +} From a7b8a6a5ccf2839052fb14cd777f9ecf071066e6 Mon Sep 17 00:00:00 2001 From: Dmitry Markov Date: Fri, 1 Apr 2016 11:22:22 +0300 Subject: [PATCH 021/167] 8073400: Some Monospaced logical fonts have a different width Reviewed-by: okutsu, prr --- .../fontconfig/windows.fontconfig.properties | 2 +- .../MonospacedGlyphWidthTest.java | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java diff --git a/jdk/make/data/fontconfig/windows.fontconfig.properties b/jdk/make/data/fontconfig/windows.fontconfig.properties index 9d3fa4a8315..3a2e2b31b18 100644 --- a/jdk/make/data/fontconfig/windows.fontconfig.properties +++ b/jdk/make/data/fontconfig/windows.fontconfig.properties @@ -243,7 +243,7 @@ sequence.fallback=lucida,symbols,\ # Exclusion Ranges -exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff +exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-f8ff exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac diff --git a/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java b/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java new file mode 100644 index 00000000000..82dd8ab57f1 --- /dev/null +++ b/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8073400 + * @summary Some Monospaced logical fonts have a different width + * @author Dmitry Markov + * @run main MonospacedGlyphWidthTest + */ +import java.awt.*; +import java.awt.font.FontRenderContext; + +public class MonospacedGlyphWidthTest { + private static final int START_INDEX = 0x2018; + private static final int END_INDEX = 0x201F; + + public static void main(String[] args) { + Font font = new Font(Font.MONOSPACED, Font.PLAIN, 12); + double width = getCharWidth(font, 'a'); + + for (int i = START_INDEX; i <= END_INDEX; i++) { + if (width != getCharWidth(font, (char)i)) { + throw new RuntimeException("Test Failed: characters have different width!"); + } + } + System.out.println("Test Passed!"); + } + + private static double getCharWidth(Font font, char c) { + FontRenderContext fontRenderContext = new FontRenderContext(null, false, false); + return font.getStringBounds(new char[] {c}, 0, 1, fontRenderContext).getWidth(); + } +} + From fbd868d77c3a0ee11613071e976366f6395e192e Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Fri, 1 Apr 2016 13:52:04 +0300 Subject: [PATCH 022/167] 8149028: [TEST] add test for TIFFDirectory Reviewed-by: ssadetsky, yan --- .../plugins/tiff/TIFFDirectoryTest.java | 266 +++++++++++++++++ .../tiff/TIFFDirectoryWriteReadTest.java | 255 ++++++++++++++++ .../plugins/tiff/TIFFImageReadParamTest.java | 275 ++++++++++++++++++ 3 files changed, 796 insertions(+) create mode 100644 jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java create mode 100644 jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java create mode 100644 jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java new file mode 100644 index 00000000000..39c2474512c --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8149028 + * @author a.stepanov + * @summary some simple checks for TIFFDirectory + * @run main TIFFDirectoryTest + */ + +import java.util.List; +import java.util.ArrayList; +import javax.imageio.metadata.*; +import javax.imageio.plugins.tiff.*; + + +public class TIFFDirectoryTest { + + private static void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void run() { + + int type = TIFFTag.TIFF_LONG, dt = 1 << type; + int n0 = 1000, n1 = 1001, n2 = 1002, n3 = 1003; + + TIFFTag tag1 = new TIFFTag(Integer.toString(n1), n1, dt); + TIFFTag tag2 = new TIFFTag(Integer.toString(n2), n2, dt); + TIFFTag tag3 = new TIFFTag(Integer.toString(n3), n3, dt); + TIFFTag parent = new TIFFTag(Integer.toString(n0), n0, dt); + + // tag sets array must not be null + boolean ok = false; + try { new TIFFDirectory(null, parent); } + catch (NullPointerException e) { ok = true; } + check(ok, "can construct TIFFDirectory with null tagsets array"); + + // but can be empty + TIFFTagSet emptySets[] = {}; + TIFFDirectory d = new TIFFDirectory(emptySets, parent); + check(d.getTagSets().length == 0, "invalid number of tag sets"); + check(d.getParentTag().getName().equals(Integer.toString(n0)) && + (d.getParentTag().getNumber() == n0), "invalid parent tag"); + + + // add tags + List tags = new ArrayList<>(); + tags.add(tag1); + tags.add(tag2); + TIFFTagSet ts1 = new TIFFTagSet(tags); + + tags.clear(); + tags.add(tag3); + TIFFTagSet ts2 = new TIFFTagSet(tags); + + TIFFTagSet sets[] = {ts1, ts2}; + d = new TIFFDirectory(sets, parent); + + check(d.getTagSets().length == sets.length, "invalid number of tag sets"); + + // check getTag() + for (int i = n1; i <= n3; i++) { + TIFFTag t = d.getTag(i); + check(t.getNumber() == i, "invalid tag number"); + check(t.getName().equals(Integer.toString(i)), "invalid tag name"); + check(t.getDataTypes() == dt, "invalid tag data types"); + } + + TIFFDirectory d2; + try { d2 = d.clone(); } + catch (CloneNotSupportedException e) { throw new RuntimeException(e); } + + // check removeTagSet() + d.removeTagSet(ts2); + check(d.getTagSets().length == 1, "invalid number of tag sets"); + check(d.getTagSets()[0].getTag(n1).getName().equals(Integer.toString(n1)), + "invalid tag name"); + check(d.getTagSets()[0].getTag(n2).getName().equals(Integer.toString(n2)), + "invalid tag name"); + + d.removeTagSet(ts1); + check(d.getTagSets().length == 0, "invalid number of tag sets"); + + // check cloned data + check(d2.getTagSets().length == sets.length, + "invalid number of tag sets"); + TIFFTagSet sets2[] = d2.getTagSets(); + check(sets2.length == sets.length, "invalid number of tag sets"); + check( + (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) && + (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) && + (sets2[0].getTag(Integer.toString(n0)) == null) && + (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) && + (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data"); + + check( + (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) && + (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) && + (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt), + "invalid data type"); + + // must not be able to call removeTagSet with null argument + ok = false; + try { d.removeTagSet(null); } + catch (NullPointerException e) { ok = true; } + check(ok, "must not be able to use null as an argument for remove"); + + // check parent tag + check( d.getParentTag().getName().equals(Integer.toString(n0)) && + d2.getParentTag().getName().equals(Integer.toString(n0)), + "invalid parent tag name"); + + check(( d.getParentTag().getNumber() == n0) && + (d2.getParentTag().getNumber() == n0), + "invalid parent tag number"); + + check(( d.getParentTag().getDataTypes() == dt) && + (d2.getParentTag().getDataTypes() == dt), + "invalid parent data type"); + + d.addTagSet(ts1); + d.addTagSet(ts2); + + // add the same tag set twice and check that nothing changed + d.addTagSet(ts2); + + check(d.getTagSets().length == 2, "invalid number of tag sets"); + + // check field operations + check(d.getNumTIFFFields() == 0, "invalid TIFFFields number"); + check(d.getTIFFField(Integer.MAX_VALUE) == null, + "must return null TIFFField"); + + long offset = 4L; + long a[] = {Long.MIN_VALUE, 0, Long.MAX_VALUE}; + int v = 100500; + TIFFField + f1 = new TIFFField(tag1, type, offset, d), + f2 = new TIFFField(tag2, v), + f3 = new TIFFField(tag3, type, a.length, a); + + d.addTIFFField(f1); + d.addTIFFField(f2); + d.addTIFFField(f3); + + check(d.containsTIFFField(n1) && + d.containsTIFFField(n2) && + d.containsTIFFField(n3) && + !d.containsTIFFField(n0), "invalid containsTIFFField() results"); + + check(d.getTIFFField(n0) == null, "can get unadded field"); + + check(d.getNumTIFFFields() == 3, "invalid TIFFFields number"); + + check(d.getTIFFField(n1).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n1).getAsLong(0) == offset, "invalid offset"); + + check(d.getTIFFField(n2).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value"); + + check(d.getTIFFField(n3).getCount() == a.length, + "invalid TIFFField count"); + for (int i = 0; i < a.length; ++i) { + check(d.getTIFFField(n3).getAsLong(i) == a[i], + "invalid TIFFField value"); + } + + TIFFField nested = d.getTIFFField(n1).getDirectory().getTIFFField(n1); + check(nested.getTag().getNumber() == n1, "invalid tag number"); + check(nested.getCount() == 1, "invalid field count"); + check(nested.getAsLong(0) == offset, "invalid offset"); + + // check that the field is overwritten correctly + int v2 = 1 << 16; + d.addTIFFField(new TIFFField(tag3, v2)); + check(d.getTIFFField(n3).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n3).getAsInt(0)== v2, "invalid TIFFField value"); + check(d.getNumTIFFFields() == 3, "invalid TIFFFields number"); + + // check removeTIFFField() + d.removeTIFFField(n3); + check(d.getNumTIFFFields() == 2, "invalid TIFFFields number"); + check(d.getTIFFField(n3) == null, "can get removed field"); + + d.removeTIFFFields(); + check((d.getTIFFField(n1) == null) && (d.getTIFFField(n2) == null), + "can get removed field"); + check((d.getNumTIFFFields() == 0) && (d.getTIFFFields().length == 0), + "invalid TIFFFields number"); + + // check that array returned by getTIFFFields() is sorted + // by tag number (as it stated in the docs) + d.addTIFFField(f3); + d.addTIFFField(f1); + d.addTIFFField(f2); + + TIFFField fa[] = d.getTIFFFields(); + check(fa.length == 3, "invalid number of fields"); + check((fa[0].getTagNumber() == n1) && + (fa[1].getTagNumber() == n2) && + (fa[2].getTagNumber() == n3), + "array of the fields must be sorted by tag number"); + + d.removeTIFFFields(); + d.addTIFFField(f2); + + // test getAsMetaData / createFromMetadata + try { + d2 = TIFFDirectory.createFromMetadata(d.getAsMetadata()); + } catch (IIOInvalidTreeException e) { + throw new RuntimeException(e); + } + + // check new data + check(d2.getTagSets().length == sets.length, + "invalid number of tag sets"); + sets2 = d2.getTagSets(); + check(sets2.length == sets.length, "invalid number of tag sets"); + check( + (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) && + (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) && + (sets2[0].getTag(Integer.toString(n0)) == null) && + (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) && + (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data"); + + check( + (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) && + (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) && + (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt), + "invalid data type"); + + check(!d2.containsTIFFField(n1) && + d2.containsTIFFField(n2) && + !d2.containsTIFFField(n3), "invalid containsTIFFField() results"); + check(d2.getTIFFField(n2).getCount() == 1, "invalid TIFFField count"); + check(d2.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value"); + + check((d2.getParentTag().getNumber() == n0) && + d2.getParentTag().getName().equals(Integer.toString(n0)), + "invalid parent tag"); + } + + public static void main(String[] args) { (new TIFFDirectoryTest()).run(); } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java new file mode 100644 index 00000000000..eb668255ea6 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8149028 + * @author a.stepanov + * @summary a simple write-read test for TIFFDirectory + * @run main TIFFDirectoryWriteReadTest + */ + +import java.awt.*; +import java.awt.color.*; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.*; +import javax.imageio.plugins.tiff.*; + + +public class TIFFDirectoryWriteReadTest { + + private final static String FILENAME = "test.tiff"; + private final static int SZ = 100; + private final static Color C = Color.RED; + + private static final String COPYRIGHT[] = {"Copyright 123ABC.."}; + private static final String DESCRIPTION[] = {"Test Image", "Description"}; + private static final String SOFTWARE[] = {"test", "software", "123"}; + + private static final long RES_X[][] = {{2, 1}}, RES_Y[][] = {{1, 1}}; + + private static final byte[] ICC_PROFILE = + ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData(); + + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data[], + int num) { + + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, data.length, data)); + } + + private void checkASCIIField(TIFFDirectory d, + String what, + String data[], + int num) { + + String notFound = what + " field was not found"; + check(d.containsTIFFField(num), notFound); + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == data.length, "invalid " + what + " data count"); + for (int i = 0; i < data.length; i++) { + check(f.getValueAsString(i).equals(data[i]), + "invalid " + what + " data"); + } + } + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img = new BufferedImage( + SZ, SZ, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(C); + g.fillRect(0, 0, SZ, SZ); + g.dispose(); + + IIOMetadata metadata = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img), writer.getDefaultWriteParam()); + + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + addASCIIField(dir, "Copyright", + COPYRIGHT, BaselineTIFFTagSet.TAG_COPYRIGHT); + + addASCIIField(dir, "ImageDescription", + DESCRIPTION, BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION); + + addASCIIField(dir, "Software", + SOFTWARE, BaselineTIFFTagSet.TAG_SOFTWARE); + + dir.addTIFFField(new TIFFField( + new TIFFTag("XResolution", BaselineTIFFTagSet.TAG_X_RESOLUTION, + 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_X)); + dir.addTIFFField(new TIFFField( + new TIFFTag("YResolution", BaselineTIFFTagSet.TAG_Y_RESOLUTION, + 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_Y)); + + dir.addTIFFField(new TIFFField( + new TIFFTag("ICC Profile", BaselineTIFFTagSet.TAG_ICC_PROFILE, + 1 << TIFFTag.TIFF_UNDEFINED), + TIFFTag.TIFF_UNDEFINED, ICC_PROFILE.length, ICC_PROFILE)); + + IIOMetadata data = dir.getAsMetadata(); + writer.write(new IIOImage(img, null, data)); + + ios.flush(); + writer.dispose(); + } + s.close(); + } + + + + private void readAndCheckImage() throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s); + + int ni = reader.getNumImages(true); + check(ni == 1, "invalid number of images"); + + // check image + BufferedImage img = reader.read(0); + check(img.getWidth() == SZ && img.getHeight() == SZ, + "invalid image size"); + + Color c = new Color(img.getRGB(SZ / 2, SZ / 2)); + check(C.equals(c), "invalid image color"); + + IIOMetadata metadata = reader.readAll(0, null).getMetadata(); + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + reader.dispose(); + s.close(); + + // ===== perform tag checks ===== + + checkASCIIField(dir, "copyright", COPYRIGHT, + BaselineTIFFTagSet.TAG_COPYRIGHT); + + checkASCIIField(dir, "description", DESCRIPTION, + BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION); + + checkASCIIField(dir, "software", SOFTWARE, + BaselineTIFFTagSet.TAG_SOFTWARE); + + TIFFField f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); + check(f.getCount() == 1, "invalid width field count"); + int w = f.getAsInt(0); + check(w == SZ, "invalid width"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); + check(f.getCount() == 1, "invalid height field count"); + int h = f.getAsInt(0); + check(h == SZ, "invalid height"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); + // RGB: 3 x 8 bits for R, G and B components + int bps[] = f.getAsInts(); + check((f.getCount() == 3) && (bps.length == 3), "invalid BPS count"); + for (int b: bps) { check(b == 8, "invalid bits per sample"); } + + // RGB: PhotometricInterpretation = 2 + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); + check(f.getCount() == 1, "invalid count"); + check(f.getAsInt(0) == 2, "invalid photometric interpretation for RGB"); + + String rat = " resolution must be rational"; + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION); + check(f.getType() == TIFFTag.TIFF_RATIONAL, "x" + rat); + check(f.getCount() == 1 && + f.getAsInt(0) == (int) (RES_X[0][0] / RES_X[0][1]), + "invalid x resolution"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION); + check(f.getType() == TIFFTag.TIFF_RATIONAL, "y" + rat); + check(f.getCount() == 1 && + f.getAsInt(0) == (int) (RES_Y[0][0] / RES_Y[0][1]), + "invalid y resolution"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE); + check(f.getType() == TIFFTag.TIFF_UNDEFINED, + "invalid ICC profile field type"); + int cnt = f.getCount(); + byte icc[] = f.getAsBytes(); + check((cnt == ICC_PROFILE.length) && (cnt == icc.length), + "invalid ICC profile"); + for (int i = 0; i < cnt; i++) { + check(icc[i] == ICC_PROFILE[i], "invalid ICC profile"); + } + } + + public void run() { + + try { + writeImage(); + readAndCheckImage(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + public static void main(String[] args) { + (new TIFFDirectoryWriteReadTest()).run(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java new file mode 100644 index 00000000000..34fd5ed8983 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8149028 + * @author a.stepanov + * @summary check TIFFDirectory manipulation + * by means of TIFFImageReadParam + * @run main TIFFImageReadParamTest + */ + + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.plugins.tiff.*; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class TIFFImageReadParamTest { + + private final static String FILENAME = "test.tiff"; + private final static int SZ = 100; + private final static Color C = Color.RED; + + private final static String GEO_DATA = "test params"; + private final static int GEO_N = GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS; + + private final static String EXIF_DATA = "2000:01:01 00:00:01"; + private final static int EXIF_N = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL; + + private final static String GPS_DATA = + ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS; + private final static int GPS_N = ExifGPSTagSet.TAG_GPS_STATUS; + + private final static short FAX_DATA = + FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED; + private final static int FAX_N = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA; + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data, + int num) { + + String a[] = {data}; + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, 1, a)); + } + + private void checkASCIIValue(TIFFDirectory d, + String what, + String data, + int num) { + + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == 1, "invalid " + what + " data count"); + check(f.getValueAsString(0).equals(data), + "invalid " + what + " data"); + } + + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img = + new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(C); + g.fillRect(0, 0, SZ, SZ); + g.dispose(); + + IIOMetadata metadata = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img), writer.getDefaultWriteParam()); + + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + // add some extension tags + addASCIIField(dir, "GeoAsciiParamsTag", GEO_DATA, GEO_N); + addASCIIField(dir, "DateTimeOriginal", EXIF_DATA, EXIF_N); + addASCIIField(dir, "GPSStatus", GPS_DATA, GPS_N); + + dir.addTIFFField(new TIFFField(new TIFFTag( + "CleanFaxData", FAX_N, 1 << TIFFTag.TIFF_SHORT), FAX_DATA)); + + IIOMetadata data = dir.getAsMetadata(); + + writer.write(new IIOImage(img, null, data)); + + ios.flush(); + writer.dispose(); + } + } + + private void checkImage(BufferedImage img) { + + check(img.getWidth() == SZ, "invalid image width"); + check(img.getHeight() == SZ, "invalid image height"); + Color c = new Color(img.getRGB(SZ / 2, SZ / 2)); + check(c.equals(C), "invalid image color"); + } + + private TIFFDirectory getDir(TIFFTagSet[] add, + TIFFTagSet[] remove) throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s, false, true); + + int ni = reader.getNumImages(true); + check(ni == 1, "invalid number of images: " + ni); + + TIFFImageReadParam param = new TIFFImageReadParam(); + for (TIFFTagSet ts: add) { param.addAllowedTagSet(ts); } + for (TIFFTagSet ts: remove) { param.removeAllowedTagSet(ts); } + + IIOImage img = reader.readAll(0, param); + + // just in case, check image + checkImage((BufferedImage) img.getRenderedImage()); + + IIOMetadata metadata = img.getMetadata(); + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + reader.dispose(); + s.close(); + + return dir; + } + + private void simpleChecks() { + + TIFFImageReadParam param = new TIFFImageReadParam(); + + java.util.List allowed = param.getAllowedTagSets(); + + // see docs + check(allowed.contains(BaselineTIFFTagSet.getInstance()), + "must contain BaselineTIFFTagSet"); + check(allowed.contains(FaxTIFFTagSet.getInstance()), + "must contain FaxTIFFTagSet"); + check(allowed.contains(ExifParentTIFFTagSet.getInstance()), + "must contain ExifParentTIFFTagSet"); + check(allowed.contains(GeoTIFFTagSet.getInstance()), + "must contain GeoTIFFTagSet"); + + TIFFTagSet gps = ExifGPSTagSet.getInstance(); + param.addAllowedTagSet(gps); + check(param.getAllowedTagSets().contains(gps), + "must contain ExifGPSTagSet"); + + param.removeAllowedTagSet(gps); + check(!param.getAllowedTagSets().contains(gps), + "must not contain ExifGPSTagSet"); + + // check that repeating remove goes properly + param.removeAllowedTagSet(gps); + + boolean ok = false; + try { param.addAllowedTagSet(null); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "must not be able to add null tag set"); + + ok = false; + try { param.removeAllowedTagSet(null); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "must not be able to remove null tag set"); + } + + private void run() { + + simpleChecks(); + + try { + + writeImage(); + + TIFFTagSet + empty[] = {}, + geo[] = { GeoTIFFTagSet.getInstance() }, + exif[] = { ExifTIFFTagSet.getInstance() }, + gps[] = { ExifGPSTagSet.getInstance() }, + fax[] = { FaxTIFFTagSet.getInstance() }; + + // default param state + TIFFDirectory dir = getDir(empty, empty); + // Geo and Fax are default allowed tag sets + check(dir.containsTIFFField(GEO_N), "must contain Geo field"); + checkASCIIValue(dir, "Geo", GEO_DATA, GEO_N); + check(dir.containsTIFFField(FAX_N), "must contain Fax field"); + check( + (dir.getTIFFField(FAX_N).getCount() == 1) && + (dir.getTIFFField(FAX_N).getAsInt(0) == FAX_DATA), + "invalid Fax field value"); + + // corresponding tag sets are non-default + check(!dir.containsTIFFField(EXIF_N), "must not contain Geo field"); + check(!dir.containsTIFFField(GPS_N), "must not contain GPS field"); + + // remove Fax + dir = getDir(empty, fax); + check(!dir.containsTIFFField(FAX_N), "must not contain Fax field"); + + // add EXIF, remove Geo + dir = getDir(exif, geo); + check(dir.containsTIFFField(EXIF_N), "must contain EXIF field"); + checkASCIIValue(dir, "EXIF", EXIF_DATA, EXIF_N); + check(!dir.containsTIFFField(GEO_N), "must not contain Geo field"); + + // add GPS + dir = getDir(gps, empty); + check(dir.containsTIFFField(GPS_N), "must contain GPS field"); + checkASCIIValue(dir, "GPS", GPS_DATA, GPS_N); + + } catch (Exception e) { throw new RuntimeException(e); } + } + + public static void main(String[] args) { + (new TIFFImageReadParamTest()).run(); + } +} From 8bc85384cdc789835040d270d37d503c3d2c0ef8 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 1 Apr 2016 09:52:13 -0700 Subject: [PATCH 023/167] 8153272: [pit] Tag @run requires "main" in java/awt/FontClass/CreateFont/CreateFontArrayTest.java Reviewed-by: yan --- .../java/awt/FontClass/CreateFont/CreateFontArrayTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java b/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java index d68b2e4409f..4dbff501d39 100644 --- a/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java +++ b/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java @@ -23,9 +23,9 @@ /* * @test - * @bug 8055463 + * @bug 8055463 8153272 * @summary Test createFont APIs - * @run CreateFontArrayTest + * @run main CreateFontArrayTest */ import java.awt.Font; From dc61e8176dc402e22fa51004003fa3625bcfe21d Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Mon, 4 Apr 2016 11:26:14 +0530 Subject: [PATCH 024/167] 6897701: In Nimbus Disabled Menus and Menu Items don't look disabled Reviewed-by: ssadetsky, alexsch --- .../javax/swing/plaf/synth/SynthStyle.java | 2 +- .../LookAndFeel/6897701/JMenuItemsTest.java | 130 ++++++++++++++++++ 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java index bf41d10dff1..56744c2a03b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -775,7 +775,7 @@ public abstract class SynthStyle { if (disabledColor == null || disabledColor instanceof UIResource) { return getColorForState(context, type); } - } else if (c instanceof JLabel && + } else if ((c instanceof JLabel || c instanceof JMenuItem) && (type == ColorType.FOREGROUND || type == ColorType.TEXT_FOREGROUND)) { return getColorForState(context, type); diff --git a/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java b/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java new file mode 100644 index 00000000000..c8e2492de2f --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 6897701 + * @summary Verify JMenu and JMenuItem Disabled state for Nimbus LAF + * @run main JMenuItemsTest + */ +import java.awt.Color; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class JMenuItemsTest { + + private static JFrame mainFrame; + private static JMenu disabledMenu; + private static JMenuItem disabledMenuItem; + + public JMenuItemsTest() { + createUI(); + } + + private void createUI() { + + mainFrame = new JFrame("Test"); + + disabledMenu = new JMenu("Disabled Menu"); + disabledMenu.setForeground(Color.BLUE); + disabledMenu.setEnabled(false); + + disabledMenuItem = new JMenuItem("Disabled MenuItem"); + disabledMenuItem.setForeground(Color.BLUE); + disabledMenuItem.setEnabled(false); + + JMenuBar menuBar = new JMenuBar(); + menuBar = new JMenuBar(); + menuBar.add(disabledMenu); + menuBar.add(disabledMenuItem); + + mainFrame.add(menuBar); + mainFrame.pack(); + mainFrame.setVisible(true); + } + + private void dispose() { + mainFrame.dispose(); + } + + private void testDisabledStateOfJMenu() { + + // Test disabled JMenu state + Rectangle rect = disabledMenu.getBounds(); + BufferedImage image = new BufferedImage(rect.width, rect.height, + BufferedImage.TYPE_INT_ARGB); + disabledMenu.paint(image.getGraphics()); + int y = image.getHeight() / 2; + for (int x = 0; x < image.getWidth(); x++) { + Color c = new Color(image.getRGB(x, y)); + if (c.equals(Color.BLUE)) { + dispose(); + throw new RuntimeException("JMenu Disabled" + + " State not Valid."); + } + } + + } + + private void testDisabledStateOfJMenuItem() { + + // Test disabled JMenuItem state + Rectangle rect = disabledMenuItem.getBounds(); + BufferedImage image = new BufferedImage(rect.width, rect.height, + BufferedImage.TYPE_INT_ARGB); + disabledMenuItem.paint(image.getGraphics()); + int y = image.getHeight() / 2; + for (int x = 0; x < image.getWidth(); x++) { + Color c = new Color(image.getRGB(x, y)); + if (c.equals(Color.BLUE)) { + dispose(); + throw new RuntimeException("JMenuItem Disabled" + + " State not Valid."); + } + } + + } + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + SwingUtilities.invokeAndWait(() -> { + + try { + JMenuItemsTest obj = new JMenuItemsTest(); + obj.testDisabledStateOfJMenu(); + obj.testDisabledStateOfJMenuItem(); + obj.dispose(); + + } catch (Exception ex) { + throw ex; + } + + }); + } +} From ed6f748110fbd5822e8d9174e723dae0cdaaee5b Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 4 Apr 2016 16:54:59 +0530 Subject: [PATCH 025/167] 6357905: java.awt.JobAttributes.getFromPage() and getToPage() always returns "1" Reviewed-by: prr, jdv --- .../share/classes/sun/print/PrintJob2D.java | 24 +++- .../java/awt/PrintJob/JobAttrUpdateTest.java | 126 ++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 0d3df28921c..a67fb9be7ce 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -483,8 +483,30 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { pageFormat.setOrientation(PageFormat.LANDSCAPE); } else { pageFormat.setOrientation(PageFormat.PORTRAIT); - } + } + PageRanges pageRangesAttr + = (PageRanges) attributes.get(PageRanges.class); + if (pageRangesAttr != null) { + // Get the PageRanges from print dialog. + int[][] range = pageRangesAttr.getMembers(); + + int prevFromPage = this.jobAttributes.getFromPage(); + int prevToPage = this.jobAttributes.getToPage(); + + int currFromPage = range[0][0]; + int currToPage = range[range.length - 1][1]; + + // if from < to update fromPage first followed by toPage + // else update toPage first followed by fromPage + if (currFromPage < prevToPage) { + this.jobAttributes.setFromPage(currFromPage); + this.jobAttributes.setToPage(currToPage); + } else { + this.jobAttributes.setToPage(currToPage); + this.jobAttributes.setFromPage(currFromPage); + } + } printerJob.setPrintable(this, pageFormat); } diff --git a/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java b/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java new file mode 100644 index 00000000000..186b9a6d8ba --- /dev/null +++ b/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* + * @test + * @bug 6357905 + * @summary JobAttributes.getFromPage() and getToPage() always returns 1 + * @run main/manual JobAttrUpdateTest + */ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.JobAttributes; +import java.awt.PrintJob; +import java.awt.Toolkit; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class JobAttrUpdateTest { + + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(JobAttrUpdateTest::printTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("" + + "JobAttributes.getFromPage(),getToPage() not updated correctly"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void printTest() { + JobAttributes ja = new JobAttributes(); + + Toolkit tk = Toolkit.getDefaultToolkit(); + // ja.setToPage(4); + // ja.setFromPage(3); + // show dialog + PrintJob pjob = tk.getPrintJob(new JFrame(), "test", ja, null); + if (pjob == null) { + return; + } + + + if (ja.getDefaultSelection() == JobAttributes.DefaultSelectionType.RANGE) { + int fromPage = ja.getFromPage(); + int toPage = ja.getToPage(); + if (fromPage != 2 || toPage != 3) { + fail(); + } else { + pass(); + } + } + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A print dialog will be shown.\n " + + " Please select Pages within Page-range.\n" + + " and enter From 2 and To 3. Then Select OK."; + + final JDialog dialog = new JDialog(); + dialog.setTitle("JobAttribute Updation Test"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + } +} From 01b34486fa0e4e8724e6e5f089850c16758fe23b Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 4 Apr 2016 14:22:07 -0700 Subject: [PATCH 026/167] 8147544: Remove sun.misc.ManagedLocalsThread from java.desktop Reviewed-by: serb, chegar --- .../classes/com/apple/laf/AquaFileSystemModel.java | 3 +-- .../macosx/classes/sun/font/CFontManager.java | 1 - .../macosx/classes/sun/lwawt/LWToolkit.java | 10 +++++----- .../sun/lwawt/macosx/CDragSourceContextPeer.java | 3 +-- .../classes/sun/lwawt/macosx/CFileDialog.java | 3 +-- .../sun/lwawt/macosx/CPrinterDialogPeer.java | 3 +-- .../classes/sun/lwawt/macosx/CPrinterJob.java | 4 ++-- .../com/sun/imageio/stream/StreamCloser.java | 5 ++--- .../java/swing/plaf/windows/WindowsLookAndFeel.java | 3 +-- .../com/sun/media/sound/JSSecurityManager.java | 11 ++++------- .../com/sun/media/sound/SoftAudioPusher.java | 4 +--- .../com/sun/media/sound/SoftJitterCorrector.java | 4 +--- .../com/sun/media/sound/SoftSynthesizer.java | 4 +--- .../share/classes/java/awt/EventDispatchThread.java | 13 ++++++++++--- .../image/renderable/RenderableImageProducer.java | 4 +--- .../share/classes/javax/swing/JTable.java | 3 +-- .../share/classes/javax/swing/TimerQueue.java | 5 ++--- .../javax/swing/plaf/basic/BasicDirectoryModel.java | 3 +-- .../classes/javax/swing/text/JTextComponent.java | 4 ++-- .../share/classes/javax/swing/text/LayoutQueue.java | 3 +-- .../share/classes/sun/applet/AppletClassLoader.java | 12 +++++++++--- .../share/classes/sun/applet/AppletPanel.java | 8 +++----- .../share/classes/sun/applet/AppletViewer.java | 11 ++++++----- .../share/classes/sun/awt/AWTAutoShutdown.java | 5 ++--- .../share/classes/sun/awt/AppContext.java | 5 ++--- .../classes/sun/awt/im/InputMethodManager.java | 4 ++-- .../share/classes/sun/awt/image/ImageFetcher.java | 12 +++++++++--- .../share/classes/sun/font/CreatedFontTracker.java | 5 ++--- .../share/classes/sun/font/SunFontManager.java | 5 ++--- .../share/classes/sun/java2d/Disposer.java | 3 +-- .../classes/sun/java2d/loops/GraphicsPrimitive.java | 6 +++--- .../classes/sun/java2d/opengl/OGLRenderQueue.java | 4 ++-- .../share/classes/sun/print/PrintJob2D.java | 4 ++-- .../share/classes/sun/print/ServiceNotifier.java | 12 +++++++----- .../unix/classes/sun/awt/X11/GtkFileDialogPeer.java | 3 +-- .../unix/classes/sun/awt/X11/InfoWindow.java | 3 +-- .../unix/classes/sun/awt/X11/XTaskbarPeer.java | 7 ++----- .../unix/classes/sun/awt/X11/XToolkit.java | 9 +++++---- .../unix/classes/sun/awt/X11GraphicsDevice.java | 5 ++--- .../sun/print/PrintServiceLookupProvider.java | 5 ++--- .../sun/awt/shell/Win32ShellFolderManager2.java | 11 ++++++----- .../classes/sun/awt/windows/WFileDialogPeer.java | 3 +-- .../classes/sun/awt/windows/WPageDialogPeer.java | 4 +--- .../classes/sun/awt/windows/WPrintDialogPeer.java | 3 +-- .../windows/classes/sun/awt/windows/WToolkit.java | 8 ++++---- .../sun/java2d/d3d/D3DScreenUpdateManager.java | 11 ++++++----- .../sun/print/PrintServiceLookupProvider.java | 5 ++--- 47 files changed, 125 insertions(+), 141 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java index 05eddcea4d8..f6f1df47ff7 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java @@ -35,7 +35,6 @@ import javax.swing.event.ListDataEvent; import javax.swing.filechooser.FileSystemView; import javax.swing.table.AbstractTableModel; -import sun.misc.ManagedLocalsThread; /** * NavServices-like implementation of a file Table * @@ -393,7 +392,7 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi this.currentDirectory = currentDirectory; this.fid = fid; String name = "Aqua L&F File Loading Thread"; - this.loadThread = new ManagedLocalsThread(this, name); + this.loadThread = new Thread(null, this, name, 0, false); this.loadThread.start(); } diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java index 9e883938e46..0c505b28576 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -42,7 +42,6 @@ import sun.awt.FontConfiguration; import sun.awt.HeadlessToolkit; import sun.awt.util.ThreadGroupUtils; import sun.lwawt.macosx.*; -import sun.misc.ManagedLocalsThread; public final class CFontManager extends SunFontManager { private static Hashtable genericFonts = new Hashtable(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java index b74719f149b..b7262a5a402 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java @@ -35,7 +35,6 @@ import java.security.*; import java.util.*; import sun.awt.*; -import sun.misc.ManagedLocalsThread; import sun.print.*; import sun.awt.util.ThreadGroupUtils; @@ -77,13 +76,14 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { shutdown(); waitForRunState(STATE_CLEANUP); }; - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "AWT-Shutdown", 0, false); shutdown.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdown); String name = "AWT-LW"; - Thread toolkitThread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread toolkitThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); toolkitThread.setDaemon(true); toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); toolkitThread.start(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java index 10aef016b0c..0c8d4afc08f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java @@ -44,7 +44,6 @@ import sun.awt.dnd.*; import sun.lwawt.LWComponentPeer; import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; -import sun.misc.ManagedLocalsThread; public final class CDragSourceContextPeer extends SunDragSourceContextPeer { @@ -181,7 +180,7 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { } } }; - new ManagedLocalsThread(dragRunnable).start(); + new Thread(null, dragRunnable, "Drag", 0, false).start(); } catch (Exception e) { final long nativeDragSource = getNativeContext(); setNativeContext(0); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java index 459afae179d..34651baba70 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java @@ -37,7 +37,6 @@ import java.io.*; import sun.awt.CausedFocusEvent.Cause; import sun.awt.AWTAccessor; import sun.java2d.pipe.Region; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetBooleanAction; class CFileDialog implements FileDialogPeer { @@ -120,7 +119,7 @@ class CFileDialog implements FileDialogPeer { if (visible) { // Java2 Dialog class requires peer to run code in a separate thread // and handles keeping the call modal - new ManagedLocalsThread(new Task()).start(); + new Thread(null, new Task(), "FileDialog", 0, false).start(); } // We hide ourself before "show" returns - setVisible(false) // doesn't apply diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java index 1837feb0ccd..cb1ee148707 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java @@ -29,7 +29,6 @@ import java.awt.*; import java.awt.dnd.*; import sun.lwawt.*; -import sun.misc.ManagedLocalsThread; public class CPrinterDialogPeer extends LWWindowPeer { static { @@ -59,7 +58,7 @@ public class CPrinterDialogPeer extends LWWindowPeer { printerDialog.setRetVal(printerDialog.showDialog()); printerDialog.setVisible(false); }; - new ManagedLocalsThread(task).start(); + new Thread(null, task, "PrintDialog", 0, false).start(); } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index aa00647de21..a22f0c3d15e 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -44,7 +44,6 @@ import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.PageRanges; import sun.java2d.*; -import sun.misc.ManagedLocalsThread; import sun.print.*; public final class CPrinterJob extends RasterPrinterJob { @@ -775,7 +774,8 @@ public final class CPrinterJob extends RasterPrinterJob { // upcall from native private static void detachPrintLoop(final long target, final long arg) { - new ManagedLocalsThread(() -> _safePrintLoop(target, arg)).start(); + new Thread(null, () -> _safePrintLoop(target, arg), + "PrintLoop", 0, false).start(); } private static native void _safePrintLoop(long target, long arg); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java index 32fa02fe175..f71a481a700 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java @@ -26,7 +26,6 @@ package com.sun.imageio.stream; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import java.io.IOException; import java.security.AccessController; @@ -92,8 +91,8 @@ public class StreamCloser { * Make its parent the top-level thread group. */ ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup(); - streamCloser = new ManagedLocalsThread(tg, - streamCloserRunnable); + streamCloser = new Thread(tg, streamCloserRunnable, + "StreamCloser", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index 5b57582bee9..d27205f3eaf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -64,7 +64,6 @@ import sun.awt.SunToolkit; import sun.awt.OSInfo; import sun.awt.shell.ShellFolder; import sun.font.FontUtilities; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; @@ -2053,7 +2052,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel if (audioRunnable != null) { // Runnable appears to block until completed playing, hence // start up another thread to handle playing. - new ManagedLocalsThread(audioRunnable).start(); + new Thread(null, audioRunnable, "Audio", 0, false).start(); } } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java index 738704facf4..d59118889c2 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedInputStream; import java.io.InputStream; import java.io.File; @@ -145,12 +143,11 @@ final class JSSecurityManager { static Thread createThread(final Runnable runnable, final String threadName, final boolean isDaemon, final int priority, - final boolean doStart) { - Thread thread = new ManagedLocalsThread(runnable); + final boolean doStart) + { + String name = (threadName != null) ? threadName : "JSSM Thread"; + Thread thread = new Thread(null, runnable, threadName, 0, false); - if (threadName != null) { - thread.setName(threadName); - } thread.setDaemon(isDaemon); if (priority >= 0) { thread.setPriority(priority); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java index 87f4852714c..3a5e6d9dc1b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java @@ -24,8 +24,6 @@ */ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.IOException; import javax.sound.sampled.AudioInputStream; @@ -55,7 +53,7 @@ public final class SoftAudioPusher implements Runnable { if (active) return; active = true; - audiothread = new ManagedLocalsThread(this); + audiothread = new Thread(null, this, "AudioPusher", 0, false); audiothread.setDaemon(true); audiothread.setPriority(Thread.MAX_PRIORITY); audiothread.start(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java index f845a369e0b..61cdf7cdf25 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java @@ -24,8 +24,6 @@ */ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import java.io.EOFException; @@ -216,7 +214,7 @@ public final class SoftJitterCorrector extends AudioInputStream { } }; - thread = new ManagedLocalsThread(runnable); + thread = new Thread(null, runnable, "JitterCorrector", 0, false); thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java index ef2182d6c9e..41b0cffa3df 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -141,7 +139,7 @@ public final class SoftSynthesizer implements AudioSynthesizer, pusher = null; jitter_stream = null; sourceDataLine = null; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "Synthesizer",0,false).start(); } return len; } diff --git a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java index 67b4ad852df..d4bead31360 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java +++ b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java @@ -31,7 +31,6 @@ import java.awt.event.WindowEvent; import java.util.ArrayList; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; import sun.awt.dnd.SunDragSourceContextPeer; @@ -55,7 +54,7 @@ import sun.awt.dnd.SunDragSourceContextPeer; * * @since 1.1 */ -class EventDispatchThread extends ManagedLocalsThread { +class EventDispatchThread extends Thread { private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread"); @@ -66,8 +65,16 @@ class EventDispatchThread extends ManagedLocalsThread { private ArrayList eventFilters = new ArrayList(); + /** + * Must always call 5 args super-class constructor passing false + * to indicate not to inherit locals. + */ + private EventDispatchThread() { + throw new UnsupportedOperationException("Must erase locals"); + } + EventDispatchThread(ThreadGroup group, String name, EventQueue queue) { - super(group, name); + super(group, null, name, 0, false); setEventQueue(queue); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java index 77d0b281b43..3eccc740aab 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java @@ -35,8 +35,6 @@ package java.awt.image.renderable; -import sun.misc.ManagedLocalsThread; - import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.ImageConsumer; @@ -137,7 +135,7 @@ public class RenderableImageProducer implements ImageProducer, Runnable { addConsumer(ic); // Need to build a runnable object for the Thread. String name = "RenderableImageProducer Thread"; - Thread thread = new ManagedLocalsThread(this, name); + Thread thread = new Thread(null, this, name, 0, false); thread.start(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java index a0111c36c0d..9ca12ea6ee1 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java @@ -56,7 +56,6 @@ import java.util.List; import javax.print.attribute.*; import javax.print.PrintService; -import sun.misc.ManagedLocalsThread; import sun.reflect.misc.ReflectUtil; import sun.swing.SwingUtilities2; @@ -6375,7 +6374,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable }; // start printing on another thread - Thread th = new ManagedLocalsThread(runnable); + Thread th = new Thread(null, runnable, "JTablePrint", 0, false); th.start(); printingStatus.showModal(true); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java b/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java index 5f05a3b6beb..9160b956e95 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java @@ -36,7 +36,6 @@ import java.util.concurrent.*; import java.util.concurrent.locks.*; import java.util.concurrent.atomic.AtomicLong; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * Internal class to manage all Timers using one thread. @@ -101,8 +100,8 @@ class TimerQueue implements Runnable final ThreadGroup threadGroup = AppContext.getAppContext().getThreadGroup(); AccessController.doPrivileged((PrivilegedAction) () -> { String name = "TimerQueue"; - Thread timerThread = new ManagedLocalsThread(threadGroup, - this, name); + Thread timerThread = + new Thread(threadGroup, this, name, 0, false); timerThread.setDaemon(true); timerThread.setPriority(Thread.NORM_PRIORITY); timerThread.start(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index d263907f742..a95c82d20fe 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -26,7 +26,6 @@ package javax.swing.plaf.basic; import sun.awt.shell.ShellFolder; -import sun.misc.ManagedLocalsThread; import javax.swing.*; import javax.swing.event.ListDataEvent; @@ -271,7 +270,7 @@ public class BasicDirectoryModel extends AbstractListModel implements Pr this.currentDirectory = currentDirectory; this.fid = fid; String name = "Basic L&F File Loading Thread"; - this.loadThread = new ManagedLocalsThread(this, name); + this.loadThread = new Thread(null, this, name, 0, false); this.loadThread.start(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java index 571745be89d..3d31a0d1936 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java @@ -70,7 +70,6 @@ import javax.print.attribute.*; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; import sun.swing.PrintingStatus; import sun.swing.SwingUtilities2; import sun.swing.text.TextComponentPrintable; @@ -2353,7 +2352,8 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A runnablePrinting.run(); } else { if (isEventDispatchThread) { - new ManagedLocalsThread(runnablePrinting).start(); + new Thread(null, runnablePrinting, + "JTextComponentPrint", 0, false ).start(); printingStatus.showModal(true); } else { printingStatus.showModal(false); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java b/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java index 7109005c721..6801a84da5b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java @@ -26,7 +26,6 @@ package javax.swing.text; import java.util.Vector; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * A queue of text layout tasks. @@ -92,7 +91,7 @@ public class LayoutQueue { } } while (work != null); }; - worker = new ManagedLocalsThread(workerRunnable, "text-layout"); + worker = new Thread(null, workerRunnable, "text-layout", 0, false); worker.setPriority(Thread.MIN_PRIORITY); worker.start(); } diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java index a778ca6c769..38a4e93415e 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java @@ -52,7 +52,6 @@ import java.security.Permission; import java.security.PermissionCollection; import sun.awt.AppContext; import sun.awt.SunToolkit; -import sun.misc.ManagedLocalsThread; import sun.net.www.ParseUtil; import sun.security.util.SecurityConstants; @@ -858,13 +857,20 @@ public void grab() { * this operation to complete before continuing, wait for the notifyAll() * operation on the syncObject to occur. */ -class AppContextCreator extends ManagedLocalsThread { +class AppContextCreator extends Thread { Object syncObject = new Object(); AppContext appContext = null; volatile boolean created = false; + /** + * Must call the 5-args super-class constructor to erase locals. + */ + private AppContextCreator() { + throw new UnsupportedOperationException("Must erase locals"); + } + AppContextCreator(ThreadGroup group) { - super(group, "AppContextCreator"); + super(group, null, "AppContextCreator", 0, false); } public void run() { diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java index 7ef9e111171..404131827fe 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java @@ -44,7 +44,6 @@ import sun.awt.AppContext; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; import sun.awt.util.PerformanceLogger; -import sun.misc.ManagedLocalsThread; import sun.security.util.SecurityConstants; /** @@ -166,7 +165,7 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ThreadGroup appletGroup = loader.getThreadGroup(); - handler = new ManagedLocalsThread(appletGroup, this, "thread " + nm); + handler = new Thread(appletGroup, this, "thread " + nm, 0, false); // set the context class loader for this thread AccessController.doPrivileged(new PrivilegedAction() { @Override @@ -396,9 +395,8 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // until the loader thread terminates. // (one way or another). if (loaderThread == null) { - // REMIND: do we want a name? - //System.out.println("------------------- loading applet"); - setLoaderThread(new ManagedLocalsThread(this)); + setLoaderThread(new Thread(null, this, + "AppletLoader", 0, false)); loaderThread.start(); // we get to go to sleep while this runs loaderThread.join(); diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java index b310b277f93..d613fc94341 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java @@ -38,7 +38,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import sun.awt.SunToolkit; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * A frame to show the applet tag in. @@ -854,7 +853,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable { // final AppletPanel p = panel; - new ManagedLocalsThread(new Runnable() + new Thread(null, new Runnable() { @Override public void run() @@ -867,7 +866,8 @@ public class AppletViewer extends Frame implements AppletContext, Printable { appletSystemExit(); } } - }).start(); + }, + "AppletCloser", 0, false).start(); } /** @@ -890,7 +890,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable { // spawn a new thread to avoid blocking the event queue // when calling appletShutdown. // - new ManagedLocalsThread(new Runnable() + new Thread(null, new Runnable() { @Override public void run() @@ -901,7 +901,8 @@ public class AppletViewer extends Frame implements AppletContext, Printable { } appletSystemExit(); } - }).start(); + }, + "AppletQuit", 0, false).start(); } /** diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java index 1ecef9162ca..8dd14c78444 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Set; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; /** @@ -337,8 +336,8 @@ public final class AWTAutoShutdown implements Runnable { private void activateBlockerThread() { AccessController.doPrivileged((PrivilegedAction) () -> { String name = "AWT-Shutdown"; - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); thread.setContextClassLoader(null); thread.setDaemon(false); blockerThread = thread; diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java index b4bc32996b2..e966905d2e0 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -46,7 +46,6 @@ import java.lang.ref.SoftReference; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -598,8 +597,8 @@ public final class AppContext { } public Thread run() { - Thread t = new ManagedLocalsThread(appContext.getThreadGroup(), - runnable, "AppContext Disposer"); + Thread t = new Thread(appContext.getThreadGroup(), + runnable, "AppContext Disposer", 0, false); t.setContextClassLoader(appContext.getContextClassLoader()); t.setPriority(Thread.NORM_PRIORITY + 1); t.setDaemon(true); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java index 14221d8a909..f61825d8ddf 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java @@ -55,7 +55,6 @@ import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import sun.awt.InputMethodSupport; import sun.awt.SunToolkit; -import sun.misc.ManagedLocalsThread; /** * {@code InputMethodManager} is an abstract class that manages the input @@ -166,7 +165,8 @@ public abstract class InputMethodManager { // to choose from. Otherwise, just keep the instance. if (imm.hasMultipleInputMethods()) { imm.initialize(); - Thread immThread = new ManagedLocalsThread(imm, threadName); + Thread immThread = + new Thread(null, imm, threadName, 0, false); immThread.setDaemon(true); immThread.setPriority(Thread.NORM_PRIORITY + 1); immThread.start(); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java index 4ad7eea1682..2aca4285977 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java @@ -27,7 +27,6 @@ package sun.awt.image; import java.util.Vector; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * An ImageFetcher is a thread used to fetch ImageFetchable objects. @@ -42,7 +41,7 @@ import sun.misc.ManagedLocalsThread; * @author Jim Graham * @author Fred Ecks */ -class ImageFetcher extends ManagedLocalsThread { +class ImageFetcher extends Thread { static final int HIGH_PRIORITY = 8; static final int LOW_PRIORITY = 3; static final int ANIM_PRIORITY = 2; @@ -51,11 +50,18 @@ class ImageFetcher extends ManagedLocalsThread { // ImageFetchable to be added to the // queue before an ImageFetcher dies + /** + * We must only call the 5 args super() constructor passing + * in "false" to indicate to not inherit locals. + */ + private ImageFetcher() { + throw new UnsupportedOperationException("Must erase locals"); + } /** * Constructor for ImageFetcher -- only called by add() below. */ private ImageFetcher(ThreadGroup threadGroup, int index) { - super(threadGroup, "Image Fetcher " + index); + super(threadGroup, null, "Image Fetcher " + index, 0, false); setDaemon(true); } diff --git a/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java b/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java index 0ce75a7b235..2e239528c71 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java +++ b/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java @@ -36,7 +36,6 @@ import java.util.concurrent.TimeUnit; import sun.awt.AppContext; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; public class CreatedFontTracker { @@ -122,8 +121,8 @@ public class CreatedFontTracker { * Make its parent the top-level thread group. */ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - t = new ManagedLocalsThread(rootTG, - TempFileDeletionHook::runHooks); + t = new Thread(rootTG, TempFileDeletionHook::runHooks, + "TempFontFileDeleter", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java index 67bb3fd383a..19200c8282b 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -55,7 +55,6 @@ import sun.awt.FontConfiguration; import sun.awt.SunToolkit; import sun.awt.util.ThreadGroupUtils; import sun.java2d.FontSupport; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; /** @@ -2513,8 +2512,8 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { }; AccessController.doPrivileged((PrivilegedAction) () -> { ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - fileCloser = new ManagedLocalsThread(rootTG, - fileCloserRunnable); + fileCloser = new Thread(rootTG, fileCloserRunnable, + "FileCloser", 0, false); fileCloser.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(fileCloser); return null; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java b/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java index 01336443bb1..e63da023936 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java @@ -26,7 +26,6 @@ package sun.java2d; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; @@ -85,7 +84,7 @@ public class Disposer implements Runnable { AccessController.doPrivileged((PrivilegedAction) () -> { String name = "Java2D Disposer"; ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread t = new ManagedLocalsThread(rootTG, disposerInstance, name); + Thread t = new Thread(rootTG, disposerInstance, name, 0, false); t.setContextClassLoader(null); t.setDaemon(true); t.setPriority(Thread.MAX_PRIORITY); diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java b/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java index 38bbaeb5178..a71978a10ac 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java @@ -48,7 +48,6 @@ import java.io.FileNotFoundException; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetPropertyAction; /** @@ -420,8 +419,9 @@ public abstract class GraphicsPrimitive { public static void setShutdownHook() { AccessController.doPrivileged((PrivilegedAction) () -> { TraceReporter t = new TraceReporter(); - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), t); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), t, + "TraceReporter", 0, false); thread.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(thread); return null; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java index 27abcbd86f8..5a843792f37 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java @@ -28,7 +28,6 @@ package sun.java2d.opengl; import sun.awt.util.ThreadGroupUtils; import sun.java2d.pipe.RenderBuffer; import sun.java2d.pipe.RenderQueue; -import sun.misc.ManagedLocalsThread; import static sun.java2d.pipe.BufferedOpCodes.*; import java.security.AccessController; @@ -161,7 +160,8 @@ public class OGLRenderQueue extends RenderQueue { public QueueFlusher() { String name = "Java2D Queue Flusher"; - thread = new ManagedLocalsThread(ThreadGroupUtils.getRootThreadGroup(), this, name); + thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), + this, name, 0, false); thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); diff --git a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java index a67fb9be7ce..b62c4eb1298 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -71,7 +71,6 @@ import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.PageRanges; -import sun.misc.ManagedLocalsThread; import sun.print.SunPageSelection; import sun.print.SunMinMaxPage; @@ -1009,7 +1008,8 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { } private void startPrinterJobThread() { - printerJobThread = new ManagedLocalsThread(this, "printerJobThread"); + printerJobThread = + new Thread(null, this, "printerJobThread", 0, false); printerJobThread.start(); } diff --git a/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java b/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java index 573684a6048..8df17defd05 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.util.Vector; import javax.print.PrintService; @@ -42,15 +40,19 @@ import javax.print.event.PrintServiceAttributeListener; * to obtain the state of the attributes and notifies the listeners of * any changes. */ -class ServiceNotifier extends ManagedLocalsThread { +class ServiceNotifier extends Thread { private PrintService service; private Vector listeners; private boolean stop = false; private PrintServiceAttributeSet lastSet; + /* + * If adding any other constructors, always call the 5-args + * super-class constructor passing "false" for inherit-locals. + */ ServiceNotifier(PrintService service) { - super(service.getName() + " notifier"); + super(null, null, service.getName() + " notifier", 0, false); this.service = service; listeners = new Vector<>(); try { @@ -70,7 +72,7 @@ class ServiceNotifier extends ManagedLocalsThread { } } - void removeListener(PrintServiceAttributeListener listener) { + void removeListener(PrintServiceAttributeListener listener) { synchronized (this) { if (listener == null || listeners == null) { return; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java index d6ef132fede..fb7688f9b8e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java @@ -29,7 +29,6 @@ import java.awt.peer.FileDialogPeer; import java.io.File; import java.io.FilenameFilter; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; /** * FileDialogPeer for the GtkFileChooser. @@ -120,7 +119,7 @@ final class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { standaloneWindow = 0; fd.setVisible(false); }; - new ManagedLocalsThread(task).start(); + new Thread(null, task, "ShowDialog", 0, false).start(); } else { quit(); fd.setVisible(false); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java index a7870a95b6a..62658c7e92e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java @@ -29,7 +29,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.peer.TrayIconPeer; import sun.awt.*; -import sun.misc.ManagedLocalsThread; import java.awt.image.*; import java.text.BreakIterator; @@ -452,7 +451,7 @@ public abstract class InfoWindow extends Window { final Thread thread; Displayer() { - this.thread = new ManagedLocalsThread(this); + this.thread = new Thread(null, this, "Displayer", 0, false); this.thread.setDaemon(true); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java index bfb964c9b7c..fa23ae0b66e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java @@ -29,7 +29,6 @@ import java.awt.PopupMenu; import java.awt.Taskbar.Feature; import java.awt.peer.TaskbarPeer; import java.awt.event.ActionEvent; -import sun.misc.ManagedLocalsThread; import java.security.AccessController; import sun.security.action.GetPropertyAction; @@ -48,10 +47,8 @@ final class XTaskbarPeer implements TaskbarPeer { new GetPropertyAction("java.desktop.appName", "")); nativeLibraryLoaded = init(dname); if (nativeLibraryLoaded) { - ManagedLocalsThread t - = new ManagedLocalsThread(() -> { - runloop(); - }); + Thread t = new Thread(null, () -> { runloop(); }, + "TaskBar", 0, false); t.setDaemon(true); t.start(); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index f1904e07626..aa460f9f636 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -284,8 +284,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } }; String name = "XToolkt-Shutdown-Thread"; - Thread shutdownThread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), r, name); + Thread shutdownThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); shutdownThread.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdownThread); return null; @@ -332,8 +332,9 @@ public final class XToolkit extends UNIXToolkit implements Runnable { toolkitThread = AccessController.doPrivileged((PrivilegedAction) () -> { String name = "AWT-XAWT"; - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, + 0, false); thread.setContextClassLoader(null); thread.setPriority(Thread.NORM_PRIORITY + 1); thread.setDaemon(true); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 9f35f172014..14ff9a5d45b 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -44,7 +44,6 @@ import sun.java2d.loops.SurfaceType; import sun.awt.util.ThreadGroupUtils; import sun.java2d.SunGraphicsEnvironment; -import sun.misc.ManagedLocalsThread; /** * This is an implementation of a GraphicsDevice object for a single @@ -442,8 +441,8 @@ public final class X11GraphicsDevice extends GraphicsDevice } }; String name = "Display-Change-Shutdown-Thread-" + screen; - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), r, name); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); t.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(t); return null; diff --git a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java index 7cf6bf0aced..4da098d504e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStream; @@ -213,7 +211,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup public PrintServiceLookupProvider() { // start the printer listener thread if (pollServices) { - Thread thr = new ManagedLocalsThread(new PrinterChangeListener()); + Thread thr = new Thread(null, new PrinterChangeListener(), + "PrinterListener", 0, false); thr.setDaemon(true); thr.start(); IPPPrintService.debug_println(debugPrefix+"polling turned on"); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index b01d04443df..1e20c3582f7 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -41,7 +41,6 @@ import java.util.stream.Stream; import static sun.awt.shell.Win32ShellFolder2.*; import sun.awt.OSInfo; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; // NOTE: This class supersedes Win32ShellFolderManager, which was removed // from distribution after version 1.4.2. @@ -524,8 +523,9 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { return null; }); AccessController.doPrivileged((PrivilegedAction) () -> { - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownHook); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownHook, + "ShellFolder", 0, false); Runtime.getRuntime().addShutdownHook(t); return null; }); @@ -548,8 +548,9 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), comRun, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), comRun, name, + 0, false); thread.setDaemon(true); return thread; }); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java index e75f3b9f486..383254b815a 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -36,7 +36,6 @@ import java.util.MissingResourceException; import java.util.Vector; import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @@ -98,7 +97,7 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @Override public void show() { - new ManagedLocalsThread(this::_show).start(); + new Thread(null, this::_show, "FileDialog", 0, false).start(); } @Override diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java index 10d99948b10..5e7303b1af1 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java @@ -25,8 +25,6 @@ package sun.awt.windows; -import sun.misc.ManagedLocalsThread; - final class WPageDialogPeer extends WPrintDialogPeer { WPageDialogPeer(WPageDialog target) { @@ -53,6 +51,6 @@ final class WPageDialogPeer extends WPrintDialogPeer { } ((WPrintDialog)target).setVisible(false); }; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "PageDialog", 0, false).start(); } } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java index 99c727493d1..a80e7dd6d13 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java @@ -32,7 +32,6 @@ import java.awt.dnd.DropTarget; import java.util.Vector; import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; class WPrintDialogPeer extends WWindowPeer implements DialogPeer { @@ -78,7 +77,7 @@ class WPrintDialogPeer extends WWindowPeer implements DialogPeer { } ((WPrintDialog)target).setVisible(false); }; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "PrintDialog", 0, false).start(); } synchronized void setHWnd(long hwnd) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index 8fb6f386474..097f68dac31 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -52,7 +52,6 @@ import sun.awt.datatransfer.DataTransferer; import sun.java2d.d3d.D3DRenderQueue; import sun.java2d.opengl.OGLRenderQueue; -import sun.misc.ManagedLocalsThread; import sun.print.PrintJob2D; import java.awt.dnd.DragSource; @@ -256,7 +255,7 @@ public final class WToolkit extends SunToolkit implements Runnable { (PrivilegedAction) ThreadGroupUtils::getRootThreadGroup); if (!startToolkitThread(this, rootTG)) { String name = "AWT-Windows"; - Thread toolkitThread = new ManagedLocalsThread(rootTG, this, name); + Thread toolkitThread = new Thread(rootTG, this, name, 0, false); toolkitThread.setDaemon(true); toolkitThread.start(); } @@ -283,8 +282,9 @@ public final class WToolkit extends SunToolkit implements Runnable { private void registerShutdownHook() { AccessController.doPrivileged((PrivilegedAction) () -> { - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this::shutdown); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this::shutdown, + "ToolkitShutdown", 0, false); shutdown.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdown); return null; diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index 4b112b9fcc7..62be1e84f1b 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -49,7 +49,6 @@ import sun.java2d.SurfaceData; import sun.java2d.windows.GDIWindowSurfaceData; import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData; import sun.java2d.windows.WindowsFlags; -import sun.misc.ManagedLocalsThread; /** * This class handles rendering to the screen with the D3D pipeline. @@ -99,8 +98,9 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager done = true; wakeUpUpdateThread(); }; - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "ScreenUpdater", 0, false); shutdown.setContextClassLoader(null); try { Runtime.getRuntime().addShutdownHook(shutdown); @@ -348,8 +348,9 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager if (screenUpdater == null) { screenUpdater = AccessController.doPrivileged((PrivilegedAction) () -> { String name = "D3D Screen Updater"; - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, + 0, false); // REMIND: should it be higher? t.setPriority(Thread.NORM_PRIORITY + 2); t.setDaemon(true); diff --git a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java index e9139b46525..347336bcb7a 100644 --- a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java +++ b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -99,7 +97,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { return; } // start the printer listener thread - Thread thr = new ManagedLocalsThread(new PrinterChangeListener()); + Thread thr = new Thread(null, new PrinterChangeListener(), + "PrinterListener", 0, false); thr.setDaemon(true); thr.start(); } /* else condition ought to never happen! */ From c4be81827a38475c8b6766c5417b296db694f2f0 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 5 Apr 2016 10:39:46 +0300 Subject: [PATCH 027/167] 8146301: Enter key does not work in a deserialized JFileChooser Reviewed-by: alexsch, prr --- .../classes/javax/swing/JFileChooser.java | 37 +++++---- .../DeserializedJFileChooserTest.java | 75 +++++++++++++++++++ 2 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java index 01edf5d0486..b37dd05050a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,12 @@ package javax.swing; import javax.swing.event.*; import javax.swing.filechooser.*; +import javax.swing.filechooser.FileFilter; import javax.swing.plaf.FileChooserUI; import javax.accessibility.*; -import java.io.File; -import java.io.ObjectOutputStream; -import java.io.IOException; +import java.io.*; import java.util.Vector; import java.awt.AWTEvent; @@ -51,8 +50,6 @@ import java.beans.JavaBean; import java.beans.BeanProperty; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; import java.lang.ref.WeakReference; /** @@ -390,19 +387,7 @@ public class JFileChooser extends JComponent implements Accessible { } private void installHierarchyListener() { - addHierarchyListener(new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) - == HierarchyEvent.PARENT_CHANGED) { - JFileChooser fc = JFileChooser.this; - JRootPane rootPane = SwingUtilities.getRootPane(fc); - if (rootPane != null) { - rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc)); - } - } - } - }); + addHierarchyListener(new FCHierarchyListener()); } private void installShowFilesListener() { @@ -2055,4 +2040,18 @@ public class JFileChooser extends JComponent implements Accessible { } // inner class AccessibleJFileChooser + private class FCHierarchyListener implements HierarchyListener, + Serializable { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) + == HierarchyEvent.PARENT_CHANGED) { + JFileChooser fc = JFileChooser.this; + JRootPane rootPane = SwingUtilities.getRootPane(fc); + if (rootPane != null) { + rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc)); + } + } + } + } } diff --git a/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java b/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java new file mode 100644 index 00000000000..122b819255c --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8146301 + * @summary Enter key does not work in a deserialized JFileChooser. + * @run main DeserializedJFileChooserTest + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class DeserializedJFileChooserTest { + + private static int state = -1; + private static JFileChooser deserialized; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeLater( () -> { + try { + JFileChooser jfc = new JFileChooser(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(jfc); + oos.close(); + ByteArrayInputStream bis = + new ByteArrayInputStream(bos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bis); + deserialized = (JFileChooser) ois.readObject(); + state = deserialized.showOpenDialog(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.delay(1000); + if (state != JFileChooser.APPROVE_OPTION) { + deserialized.cancelSelection(); + throw new RuntimeException("Failed"); + } + } +} From f0d7d7a5a853972e8c98cdec7697d3ebf643f64c Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 5 Apr 2016 10:47:08 +0300 Subject: [PATCH 028/167] 8149631: rgb(...) CSS color values are not parsed properly Reviewed-by: alexsch --- .../classes/javax/swing/text/html/CSS.java | 14 ++++- .../CSS/ColorValue/RGBColorValueTest.java | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java index 85cf2a8d16f..06a8ebf6534 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1522,8 +1522,16 @@ public class CSS implements Serializable { current++; } last = current; - while (current < length && !Character.isWhitespace - (value.charAt(current))) { + int inParentheses = 0; + char ch; + while (current < length && ( + !Character.isWhitespace(ch = value.charAt(current)) + || inParentheses > 0)) { + if (ch == '(') { + inParentheses++; + } else if (ch == ')') { + inParentheses--; + } current++; } if (last != current) { diff --git a/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java b/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java new file mode 100644 index 00000000000..fce9408717d --- /dev/null +++ b/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 8149631 + * @summary rgb(...) CSS color values are not parsed properly + * @run main RGBColorValueTest + */ + +import javax.swing.text.AttributeSet; +import javax.swing.text.html.StyleSheet; + +import static javax.swing.text.html.CSS.Attribute.*; + +public class RGBColorValueTest { + + public static void main(String[] args) { + StyleSheet styleSheet = new StyleSheet(); + AttributeSet attributeSet = styleSheet. + getDeclaration("border-color: rgb(1, 2, 3) rgb(1, 2, 4);"); + if (!attributeSet.getAttribute(BORDER_TOP_COLOR).toString() + .equals("rgb(1, 2, 3)") || + !attributeSet.getAttribute(BORDER_BOTTOM_COLOR).toString() + .equals("rgb(1, 2, 3)") || + !attributeSet.getAttribute(BORDER_RIGHT_COLOR).toString() + .equals("rgb(1, 2, 4)") || + !attributeSet.getAttribute(BORDER_LEFT_COLOR).toString() + .equals("rgb(1, 2, 4)") ) { + throw new RuntimeException("Failed"); + } + } +} From a120ac732a1010a98ff004858bfb88ce68a8771f Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Tue, 5 Apr 2016 10:59:01 +0300 Subject: [PATCH 029/167] 8151333: Some AWT functions may access an array outside of its bounds Reviewed-by: alexsch, prr --- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 7d2b8b0dbd0..8b64034a295 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1877,31 +1877,34 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode AWT_LOCK(); - config = awt_XRRGetScreenInfo(awt_display, - RootWindow(awt_display, screen)); - if (config != NULL) { - Rotation rotation; - short curRate; - SizeID curSizeIndex; - XRRScreenSize *sizes; - int nsizes; + if (screen < ScreenCount(awt_display)) { - curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); - sizes = awt_XRRConfigSizes(config, &nsizes); - curRate = awt_XRRConfigCurrentRate(config); + config = awt_XRRGetScreenInfo(awt_display, + RootWindow(awt_display, screen)); + if (config != NULL) { + Rotation rotation; + short curRate; + SizeID curSizeIndex; + XRRScreenSize *sizes; + int nsizes; - if ((sizes != NULL) && - (curSizeIndex < nsizes)) - { - XRRScreenSize curSize = sizes[curSizeIndex]; - displayMode = X11GD_CreateDisplayMode(env, - curSize.width, - curSize.height, - BIT_DEPTH_MULTI, - curRate); + curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); + sizes = awt_XRRConfigSizes(config, &nsizes); + curRate = awt_XRRConfigCurrentRate(config); + + if ((sizes != NULL) && + (curSizeIndex < nsizes)) + { + XRRScreenSize curSize = sizes[curSizeIndex]; + displayMode = X11GD_CreateDisplayMode(env, + curSize.width, + curSize.height, + BIT_DEPTH_MULTI, + curRate); + } + + awt_XRRFreeScreenConfigInfo(config); } - - awt_XRRFreeScreenConfigInfo(config); } AWT_FLUSH_UNLOCK(); From 3b618308c3252fc5dc9bd028325e9e210532bd86 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 5 Apr 2016 14:52:31 +0530 Subject: [PATCH 030/167] 8153363: Redundant check for number of components in PackedColorModel.equals() method Reviewed-by: prr, flar --- .../share/classes/java/awt/image/PackedColorModel.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java index c5e8ec8d3ab..0db6ff17441 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java @@ -404,9 +404,6 @@ public abstract class PackedColorModel extends ColorModel { PackedColorModel cm = (PackedColorModel) obj; int numC = cm.getNumComponents(); - if (numC != numComponents) { - return false; - } for(int i=0; i < numC; i++) { if (maskArray[i] != cm.getMask(i)) { return false; From e4020fda7d28add7b9c7aacce47648754be4f81d Mon Sep 17 00:00:00 2001 From: Avik Niyogi Date: Tue, 5 Apr 2016 15:37:13 +0530 Subject: [PATCH 031/167] 8137169: [macosx] Incorrect minimal heigh of JTabbedPane with more tabs Reviewed-by: rchamyal, alexsch --- .../laf/AquaTabbedPaneCopyFromBasicUI.java | 33 +--- .../8137169/ScrollableTabbedPaneTest.java | 182 ++++++++++++++++++ 2 files changed, 184 insertions(+), 31 deletions(-) create mode 100644 jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java index 92df95b6db2..d85ed9e8f67 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java @@ -2183,50 +2183,21 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing } protected int preferredTabAreaHeight(final int tabPlacement, final int width) { - final FontMetrics metrics = getFontMetrics(); final int tabCount = tabPane.getTabCount(); int total = 0; if (tabCount > 0) { - int rows = 1; - int x = 0; - final int maxTabHeight = calculateMaxTabHeight(tabPlacement); - - for (int i = 0; i < tabCount; i++) { - final int tabWidth = calculateTabWidth(tabPlacement, i, metrics); - - if (x != 0 && x + tabWidth > width) { - rows++; - x = 0; - } - x += tabWidth; - } - total = calculateTabAreaHeight(tabPlacement, rows, maxTabHeight); + total = calculateTabAreaHeight(tabPlacement, 1, maxTabHeight); } return total; } protected int preferredTabAreaWidth(final int tabPlacement, final int height) { - final FontMetrics metrics = getFontMetrics(); final int tabCount = tabPane.getTabCount(); int total = 0; if (tabCount > 0) { - int columns = 1; - int y = 0; - final int fontHeight = metrics.getHeight(); - maxTabWidth = calculateMaxTabWidth(tabPlacement); - - for (int i = 0; i < tabCount; i++) { - final int tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); - - if (y != 0 && y + tabHeight > height) { - columns++; - y = 0; - } - y += tabHeight; - } - total = calculateTabAreaWidth(tabPlacement, columns, maxTabWidth); + total = calculateTabAreaWidth(tabPlacement, 1, maxTabWidth); } return total; } diff --git a/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java b/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java new file mode 100644 index 00000000000..834da2ef522 --- /dev/null +++ b/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8137169 + * @summary verifies TabbedScrollPane minimum height for all Look and Feels + * @library ../../regtesthelpers + * @build Util + * @run main ScrollableTabbedPaneTest + */ + +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class ScrollableTabbedPaneTest { + + private static JFrame frame; + private static JTabbedPane pane; + private static Robot robot; + private static volatile String errorString = ""; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.delay(1000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName(), + lookAndFeelItem.getName()); + } + if (!"".equals(errorString)) { + throw new RuntimeException("Error Log:\n" + errorString); + } + } + + private static void executeCase(String lookAndFeelString, String shortLAF) + throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createUI(shortLAF); + stepsToExecute(shortLAF); + + createLeftUI(shortLAF); + stepsToExecute(shortLAF); + + createRightUI(shortLAF); + stepsToExecute(shortLAF); + } + } + + private static void stepsToExecute(String shortLAF) throws Exception { + robot.delay(100); + runTestCase(shortLAF); + robot.delay(1000); + cleanUp(); + robot.delay(1000); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static void createUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + private static void createLeftUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.setTabPlacement(SwingConstants.LEFT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + + private static void createRightUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.setTabPlacement(SwingConstants.RIGHT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + + private static void runTestCase(String shortLAF) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + int i = 0; + int value= 0; + do { + String title = "Tab" + (i + 1); + pane.addTab(title, new JPanel()); + int tempValue = pane.getMinimumSize().height; + if(value==0) { + value = tempValue; + } + if(value != tempValue) { + String error = "[" + shortLAF + + "]: [Error]: TabbedScrollPane fails"; + errorString += error; + } + + ++i; + } while (i < 10); + } + }); + } +} + From fe992bb6cdfe3970e5a438f750f0b32cf6061865 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 5 Apr 2016 17:30:23 +0300 Subject: [PATCH 032/167] 8152501: closed/javax/sound/sampled/FileWriter/WaveBigEndian.java failing Reviewed-by: amenkov --- .../sun/media/sound/AudioFloatConverter.java | 109 ++++++++------ .../Bits16ToFromFloatArray.java | 101 +++++++++++++ .../Bits24ToFromFloatArray.java | 126 ++++++++++++++++ .../Bits32ToFromFloatArray.java | 130 ++++++++++++++++ .../Bits64ToFromFloatArray.java | 142 ++++++++++++++++++ .../Bits8ToFromFloatArray.java | 78 ++++++++++ 6 files changed, 640 insertions(+), 46 deletions(-) create mode 100644 jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java create mode 100644 jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java create mode 100644 jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java create mode 100644 jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java create mode 100644 jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java index 910e2dc8352..77930d05657 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; import java.nio.ByteBuffer; @@ -319,8 +320,10 @@ public abstract class AudioFloatConverter { float[] out_buff, int out_offset, int out_len) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < out_len; i++) - out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f); + for (int i = 0; i < out_len; i++) { + byte x = in_buff[ix++]; + out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f; + } return out_buff; } @@ -328,8 +331,10 @@ public abstract class AudioFloatConverter { byte[] out_buff, int out_offset) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < in_len; i++) - out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f); + for (int i = 0; i < in_len; i++) { + final float x = in_buff[ix++]; + out_buff[ox++] = (byte) (x > 0 ? x * 127 : x * 128); + } return out_buff; } } @@ -340,9 +345,10 @@ public abstract class AudioFloatConverter { float[] out_buff, int out_offset, int out_len) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < out_len; i++) - out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127) - * (1.0f / 127.0f); + for (int i = 0; i < out_len; i++) { + byte x = (byte) (in_buff[ix++] - 128); + out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f; + } return out_buff; } @@ -350,8 +356,10 @@ public abstract class AudioFloatConverter { byte[] out_buff, int out_offset) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < in_len; i++) - out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f); + for (int i = 0; i < in_len; i++) { + float x = in_buff[ix++]; + out_buff[ox++] = (byte) (128 + (x > 0 ? x * 127 : x * 128)); + } return out_buff; } } @@ -369,10 +377,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int len = out_offset + out_len; for (int ox = out_offset; ox < len; ox++) { - out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | - (in_buff[ix++] << 8))) * (1.0f / 32767.0f); + short x = (short) (in_buff[ix++] & 0xFF | (in_buff[ix++] << 8)); + out_buff[ox] = x > 0 ? x / 32767.0f : x / 32768.0f; } - return out_buff; } @@ -381,7 +388,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; int len = in_offset + in_len; for (int ix = in_offset; ix < len; ix++) { - int x = (int) (in_buff[ix] * 32767.0); + float f = in_buff[ix]; + short x = (short) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); } @@ -396,8 +404,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < out_len; i++) { - out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | - (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f); + short x = (short) ((in_buff[ix++] << 8) | (in_buff[ix++] & 0xFF)); + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -407,7 +415,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + short x = (short) (f > 0 ? f * 32767.0f : f * 32768.0f); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; } @@ -423,7 +432,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < out_len; i++) { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8); - out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + x -= 32768; + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -433,7 +443,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = 32767 + (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); } @@ -449,7 +460,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < out_len; i++) { int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + x -= 32768; + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -459,7 +471,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = 32767 + (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; } @@ -484,7 +497,7 @@ public abstract class AudioFloatConverter { | ((in_buff[ix++] & 0xFF) << 16); if (x > 0x7FFFFF) x -= 0x1000000; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -494,7 +507,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); if (x < 0) x += 0x1000000; out_buff[ox++] = (byte) x; @@ -516,7 +530,7 @@ public abstract class AudioFloatConverter { | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); if (x > 0x7FFFFF) x -= 0x1000000; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -526,7 +540,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); if (x < 0) x += 0x1000000; out_buff[ox++] = (byte) (x >>> 16); @@ -546,8 +561,8 @@ public abstract class AudioFloatConverter { for (int i = 0; i < out_len; i++) { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16); - x -= 0x7FFFFF; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + x -= 0x800000; + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -557,8 +572,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); - x += 0x7FFFFF; + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); + x += 0x800000; out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) (x >>> 16); @@ -576,8 +592,8 @@ public abstract class AudioFloatConverter { for (int i = 0; i < out_len; i++) { int x = ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - x -= 0x7FFFFF; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + x -= 0x800000; + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -587,8 +603,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); - x += 0x7FFFFF; + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); + x += 8388608; out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; @@ -673,7 +690,7 @@ public abstract class AudioFloatConverter { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 24); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -685,7 +702,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) (x >>> 16); @@ -706,7 +723,7 @@ public abstract class AudioFloatConverter { int x = ((in_buff[ix++] & 0xFF) << 24) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -718,7 +735,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; out_buff[ox++] = (byte) (x >>> 24); out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); @@ -737,7 +754,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, signed, little-endian private static class AudioFloatConversion32xSL extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xSL(int xbytes) { this.xbytes = xbytes; @@ -778,7 +795,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, signed, big-endian private static class AudioFloatConversion32xSB extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xSB(int xbytes) { this.xbytes = xbytes; @@ -820,7 +837,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, unsigned, little-endian private static class AudioFloatConversion32xUL extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xUL(int xbytes) { this.xbytes = xbytes; @@ -835,7 +852,7 @@ public abstract class AudioFloatConverter { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 24); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -847,7 +864,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; for (int j = 0; j < xbytes; j++) { out_buff[ox++] = 0; } @@ -863,7 +880,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, unsigned, big-endian private static class AudioFloatConversion32xUB extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xUB(int xbytes) { this.xbytes = xbytes; @@ -878,7 +895,7 @@ public abstract class AudioFloatConverter { ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); ix += xbytes; - x -= 2147483647; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / 2147483647.0f); } return out_buff; @@ -889,8 +906,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * 2147483647.0); - x += 2147483647; + int x = (int) (in_buff[ix++] * 2147483647.0f); + x += 0x80000000; out_buff[ox++] = (byte) (x >>> 24); out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java new file mode 100644 index 00000000000..54e404dcf6f --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.*; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits16ToFromFloatArray { + + private static final int SIZE = 16; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static short MID_U = (short) (Short.MAX_VALUE + 1); + private static short MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) (Short.MIN_VALUE >> 8), (byte) (Short.MIN_VALUE & 0xff), 0, + 0, (byte) (Short.MAX_VALUE >> 8), (byte) (Short.MAX_VALUE & 0xff) + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, (byte) (MID_U >> 8), (byte) (MID_U & 0xff), + (byte) (MAX_U >> 8), (byte) (MAX_U >> 8) + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) (Short.MIN_VALUE & 0xff), (byte) (Short.MIN_VALUE >> 8), 0, + 0, (byte) (Short.MAX_VALUE & 0xff), (byte) (Short.MAX_VALUE >> 8) + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, (byte) (MID_U & 0xff), (byte) (MID_U >> 8), + (byte) (MAX_U >> 8), (byte) (MAX_U >> 8) + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println("enc = " + enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java new file mode 100644 index 00000000000..1bd215435d2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits24ToFromFloatArray { + + private static final int SIZE = 24; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static int MIN_S = -8_388_608; + private static int MAX_S = 8_388_607; + + private static int MID_U = 0xFFFFFF / 2 + 1; + private static int MAX_U = 0xFFFFFF; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((MIN_S >> 16) & 0xff), + (byte) ((MIN_S >> 8) & 0xff), + (byte) ((MIN_S >> 0) & 0xff), + 0, 0, 0, + (byte) ((MAX_S >> 16) & 0xff), + (byte) ((MAX_S >> 8) & 0xff), + (byte) ((MAX_S >> 0) & 0xff), + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) ((MIN_S >> 0) & 0xff), + (byte) ((MIN_S >> 8) & 0xff), + (byte) ((MIN_S >> 16) & 0xff), + 0, 0, 0, + (byte) ((MAX_S >> 0) & 0xff), + (byte) ((MAX_S >> 8) & 0xff), + (byte) ((MAX_S >> 16) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println(enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java new file mode 100644 index 00000000000..7a550a54df3 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits32ToFromFloatArray { + + private static final int SIZE = 32; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static int MID_U = (int) (Integer.MAX_VALUE + 1); + private static int MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((Integer.MIN_VALUE >> 24) & 0xff), + (byte) ((Integer.MIN_VALUE >> 16) & 0xff), + (byte) ((Integer.MIN_VALUE >> 8) & 0xff), + (byte) ((Integer.MIN_VALUE >> 0) & 0xff), + 0, 0, 0, 0, + (byte) ((Integer.MAX_VALUE >> 24) & 0xff), + (byte) ((Integer.MAX_VALUE >> 16) & 0xff), + (byte) ((Integer.MAX_VALUE >> 8) & 0xff), + (byte) ((Integer.MAX_VALUE >> 0) & 0xff), + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, 0, + (byte) ((MID_U >> 24) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MAX_U >> 24) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) ((Integer.MIN_VALUE >> 0) & 0xff), + (byte) ((Integer.MIN_VALUE >> 8) & 0xff), + (byte) ((Integer.MIN_VALUE >> 16) & 0xff), + (byte) ((Integer.MIN_VALUE >> 24) & 0xff), + 0, 0, 0, 0, + (byte) ((Integer.MAX_VALUE >> 0) & 0xff), + (byte) ((Integer.MAX_VALUE >> 8) & 0xff), + (byte) ((Integer.MAX_VALUE >> 16) & 0xff), + (byte) ((Integer.MAX_VALUE >> 24) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, 0, + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 24) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 24) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java new file mode 100644 index 00000000000..558835bcb52 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits64ToFromFloatArray { + + private static final int SIZE = 64; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static long MID_U = (long) (Long.MAX_VALUE + 1); + private static long MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((Long.MIN_VALUE >> 56) & 0xff), + (byte) ((Long.MIN_VALUE >> 48) & 0xff), + (byte) ((Long.MIN_VALUE >> 40) & 0xff), + (byte) ((Long.MIN_VALUE >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + 0, 0, 0, 0, + 0, 0, 0, 0, + (byte) ((Long.MAX_VALUE >> 56) & 0xff), + (byte) ((Long.MAX_VALUE >> 48) & 0xff), + (byte) ((Long.MAX_VALUE >> 40) & 0xff), + (byte) ((Long.MAX_VALUE >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, 0, + 0, 0, 0, 0, + (byte) ((MID_U >> 56) & 0xff), + (byte) ((MID_U >> 48) & 0xff), + (byte) ((MID_U >> 40) & 0xff), + (byte) ((MID_U >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MAX_U >> 56) & 0xff), + (byte) ((MAX_U >> 48) & 0xff), + (byte) ((MAX_U >> 40) & 0xff), + (byte) ((MAX_U >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((Long.MIN_VALUE >> 32) & 0xff), + (byte) ((Long.MIN_VALUE >> 40) & 0xff), + (byte) ((Long.MIN_VALUE >> 48) & 0xff), + (byte) ((Long.MIN_VALUE >> 56) & 0xff), + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((Long.MAX_VALUE >> 32) & 0xff), + (byte) ((Long.MAX_VALUE >> 40) & 0xff), + (byte) ((Long.MAX_VALUE >> 48) & 0xff), + (byte) ((Long.MAX_VALUE >> 56) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MID_U >> 32) & 0xff), + (byte) ((MID_U >> 40) & 0xff), + (byte) ((MID_U >> 48) & 0xff), + (byte) ((MID_U >> 56) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MAX_U >> 32) & 0xff), + (byte) ((MAX_U >> 40) & 0xff), + (byte) ((MAX_U >> 48) & 0xff), + (byte) ((MAX_U >> 56) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println(enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java new file mode 100644 index 00000000000..1d4ab606745 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.*; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits8ToFromFloatArray { + + private static final int SIZE = 8; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static final byte[] SIGNED = {Byte.MIN_VALUE, 0, Byte.MAX_VALUE}; + + private static final byte[] UNSIGNED = { + 0, (byte) (Byte.MAX_VALUE + 1), (byte) -1 + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED); + test(PCM_SIGNED, SIGNED); + } + + private static void test(final Encoding enc, final byte[] expected) { + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + true); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} From d5b317c8db1338497269ff3bd17b78bc231507f2 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 5 Apr 2016 17:44:19 +0300 Subject: [PATCH 033/167] 7076354: JavaSoundAudioClip stop() Method sequencer.addMetaEventListener(this); wrong? Reviewed-by: amenkov --- .../share/classes/com/sun/media/sound/JavaSoundAudioClip.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index 1ac0a54a3d8..ca9ac9c9122 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -232,7 +232,7 @@ public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, L } else if (sequencer != null) { try { sequencerloop = false; - sequencer.addMetaEventListener(this); + sequencer.removeMetaEventListener(this); sequencer.stop(); } catch (Exception e3) { if (Printer.err) e3.printStackTrace(); From 0cd8d72e1d8bfc69b004d1cc17c220e414619134 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 5 Apr 2016 18:11:12 +0300 Subject: [PATCH 034/167] 8144166: [macosx] Test java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java fails Reviewed-by: alexsch --- .../laf/AquaInternalFrameDockIconUI.java | 74 +++++----- .../CompEventOnHiddenComponent.java | 2 +- .../DockIconRepaint/DockIconRepaint.java | 127 ++++++++++++++++++ 3 files changed, 159 insertions(+), 44 deletions(-) create mode 100644 jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java index a24faef499a..af2aaf05ed6 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,28 +40,28 @@ import sun.swing.SwingUtilities2; * From MacDockIconUI * * A JRSUI L&F implementation of JInternalFrame.JDesktopIcon - * @author - * @version */ -public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseListener, MouseMotionListener, ComponentListener { - private static final String CACHED_FRAME_ICON_KEY = "apple.laf.internal.frameIcon"; +public final class AquaInternalFrameDockIconUI extends DesktopIconUI + implements MouseListener, MouseMotionListener { - protected JInternalFrame.JDesktopIcon fDesktopIcon; - protected JInternalFrame fFrame; - protected ScaledImageLabel fIconPane; - protected DockLabel fDockLabel; - protected boolean fTrackingIcon = false; + private JInternalFrame.JDesktopIcon fDesktopIcon; + private JInternalFrame fFrame; + private ScaledImageLabel fIconPane; + private DockLabel fDockLabel; + private boolean fTrackingIcon; public static ComponentUI createUI(final JComponent c) { return new AquaInternalFrameDockIconUI(); } + @Override public void installUI(final JComponent c) { fDesktopIcon = (JInternalFrame.JDesktopIcon)c; installComponents(); installListeners(); } + @Override public void uninstallUI(final JComponent c) { uninstallComponents(); uninstallListeners(); @@ -69,55 +69,54 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL fFrame = null; } - protected void installComponents() { + private void installComponents() { fFrame = fDesktopIcon.getInternalFrame(); fIconPane = new ScaledImageLabel(); fDesktopIcon.setLayout(new BorderLayout()); fDesktopIcon.add(fIconPane, BorderLayout.CENTER); } - protected void uninstallComponents() { + private void uninstallComponents() { fDesktopIcon.setLayout(null); fDesktopIcon.remove(fIconPane); } - protected void installListeners() { + private void installListeners() { fDesktopIcon.addMouseListener(this); fDesktopIcon.addMouseMotionListener(this); - fFrame.addComponentListener(this); } - protected void uninstallListeners() { - fFrame.removeComponentListener(this); + private void uninstallListeners() { fDesktopIcon.removeMouseMotionListener(this); fDesktopIcon.removeMouseListener(this); } + @Override public Dimension getMinimumSize(final JComponent c) { return new Dimension(32, 32); } + @Override public Dimension getMaximumSize(final JComponent c) { return new Dimension(128, 128); } + @Override public Dimension getPreferredSize(final JComponent c) { return new Dimension(64, 64); //$ Dock preferred size } - public Insets getInsets(final JComponent c) { - return new Insets(0, 0, 0, 0); - } - void updateIcon() { fIconPane.updateIcon(); } + @Override public void mousePressed(final MouseEvent e) { fTrackingIcon = fIconPane.mouseInIcon(e); if (fTrackingIcon) fIconPane.repaint(); } + @Override public void mouseReleased(final MouseEvent e) {// only when it's actually in the image if (fFrame.isIconifiable() && fFrame.isIcon()) { if (fTrackingIcon) { @@ -137,6 +136,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL if (fDockLabel != null && !fIconPane.getBounds().contains(e.getX(), e.getY())) fDockLabel.hide(); } + @Override public void mouseEntered(final MouseEvent e) { if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) return; String title = fFrame.getTitle(); @@ -145,41 +145,27 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL fDockLabel.show(fDesktopIcon); } + @Override public void mouseExited(final MouseEvent e) { if (fDockLabel != null && (e.getModifiers() & InputEvent.BUTTON1_MASK) == 0) fDockLabel.hide(); } + @Override public void mouseClicked(final MouseEvent e) { } + @Override public void mouseDragged(final MouseEvent e) { } + @Override public void mouseMoved(final MouseEvent e) { } - public void componentHidden(final ComponentEvent e) { } - - public void componentMoved(final ComponentEvent e) { } - - public void componentResized(final ComponentEvent e) { - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null); - } - - public void componentShown(final ComponentEvent e) { - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null); - } - @SuppressWarnings("serial") // Superclass is not serializable across versions - class ScaledImageLabel extends JLabel { + private final class ScaledImageLabel extends JLabel { ScaledImageLabel() { super(null, null, CENTER); } void updateIcon() { - final Object priorIcon = fFrame.getClientProperty(CACHED_FRAME_ICON_KEY); - if (priorIcon instanceof ImageIcon) { - setIcon((ImageIcon)priorIcon); - return; - } - int width = fFrame.getWidth(); int height = fFrame.getHeight(); @@ -196,11 +182,10 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL final float scale = (float)fDesktopIcon.getWidth() / (float)Math.max(width, height) * 0.89f; // Sending in -1 for width xor height causes it to maintain aspect ratio - final ImageIcon icon = new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH)); - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, icon); - setIcon(icon); + setIcon(new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH))); } + @Override public void paint(final Graphics g) { if (getIcon() == null) updateIcon(); @@ -222,13 +207,14 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL return getBounds().contains(e.getX(), e.getY()); } + @Override public Dimension getPreferredSize() { return new Dimension(64, 64); //$ Dock preferred size } } @SuppressWarnings("serial") // Superclass is not serializable across versions - class DockLabel extends JLabel { + private static final class DockLabel extends JLabel { static final int NUB_HEIGHT = 7; static final int ROUND_ADDITIONAL_HEIGHT = 8; static final int ROUND_ADDITIONAL_WIDTH = 12; @@ -243,6 +229,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL setSize(SwingUtilities.computeStringWidth(metrics, getText()) + ROUND_ADDITIONAL_WIDTH * 2, metrics.getAscent() + NUB_HEIGHT + ROUND_ADDITIONAL_HEIGHT); } + @Override public void paint(final Graphics g) { final int width = getWidth(); final int height = getHeight(); @@ -303,6 +290,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL } } + @Override @Deprecated public void hide() { final Container parent = getParent(); diff --git a/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java b/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java index 43a6d326702..cd74e128b7c 100644 --- a/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java +++ b/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java @@ -25,7 +25,7 @@ /* @test - @bug 6383903 + @bug 6383903 8144166 @summary REGRESSION: componentMoved is now getting called for some hidden components @author andrei.dmitriev: area=awt.component @run main CompEventOnHiddenComponent diff --git a/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java b/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java new file mode 100644 index 00000000000..6af5c95e473 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.beans.PropertyVetoException; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; + +/** + * @test + * @bug 8144166 + * @requires (os.family == "mac") + */ +public final class DockIconRepaint { + + private static volatile Color color; + + private static JFrame frame; + + private static JInternalFrame jif; + + private static Robot robot; + + private static Point iconLoc; + + private static Rectangle iconBounds; + + public static void main(final String[] args) throws Exception { + robot = new Robot(); + EventQueue.invokeAndWait(DockIconRepaint::createUI); + try { + robot.waitForIdle(); + color = Color.BLUE; + test(); + color = Color.RED; + test(); + color = Color.GREEN; + test(); + } finally { + frame.dispose(); + } + } + + private static void test() throws Exception { + // maximize the frame to force repaint + EventQueue.invokeAndWait(() -> { + try { + jif.setIcon(false); + jif.setMaximum(true); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + }); + robot.waitForIdle(); + Thread.sleep(1000); + // minimize the frame to dock, the icon should be up2date + EventQueue.invokeAndWait(() -> { + try { + jif.setIcon(true); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + iconLoc = jif.getDesktopIcon().getLocationOnScreen(); + iconBounds = jif.getDesktopIcon().getBounds(); + }); + robot.waitForIdle(); + Thread.sleep(1000); + + final Color c = robot.getPixelColor(iconLoc.x + iconBounds.width / 2, + iconLoc.y + iconBounds.height / 2); + if (c.getRGB() != color.getRGB()) { + System.err.println("Exp: " + Integer.toHexString(color.getRGB())); + System.err.println("Actual: " + Integer.toHexString(c.getRGB())); + throw new RuntimeException("Wrong color."); + } + } + + private static void createUI() { + frame = new JFrame(); + frame.setUndecorated(true); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + final JDesktopPane pane = new JDesktopPane(); + final JPanel panel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + g.setColor(color); + g.fillRect(0, 0, getWidth(), getHeight()); + } + }; + jif = new JInternalFrame(); + jif.add(panel); + jif.setVisible(true); + jif.setSize(300, 300); + pane.add(jif); + frame.add(pane); + frame.setVisible(true); + } +} From c06119d8ae9d68279b795152e5c73c8bb3936537 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 5 Apr 2016 18:23:10 +0300 Subject: [PATCH 035/167] 8151773: [macosx] TrayIcon.imageAutoSize property is ignored Reviewed-by: alexsch --- .../native/libawt_lwawt/awt/CTrayIcon.m | 23 +++++++++++-------- .../MultiResolutionTrayIconTest.java | 3 +-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m index 73d4c2f7896..36d13667f55 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,18 +39,21 @@ * If the image of the specified size won't fit into the status bar, * then scale it down proprtionally. Otherwise, leave it as is. */ -static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) { +static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) { NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height); // There is a black line at the bottom of the status bar // that we don't want to cover with image pixels. - CGFloat desiredHeight = [[NSStatusBar systemStatusBar] thickness] - 1.0; - CGFloat scaleFactor = MIN(1.0, desiredHeight/imageSize.height); - - imageRect.size.width *= scaleFactor; - imageRect.size.height *= scaleFactor; + CGFloat desiredSize = [[NSStatusBar systemStatusBar] thickness] - 1.0; + if (autosize) { + imageRect.size.width = desiredSize; + imageRect.size.height = desiredSize; + } else { + CGFloat scaleFactor = MIN(1.0, desiredSize/imageSize.height); + imageRect.size.width *= scaleFactor; + imageRect.size.height *= scaleFactor; + } imageRect = NSIntegralRect(imageRect); - return imageRect.size; } @@ -101,9 +104,9 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) { return peer; } -- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize{ +- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize { NSSize imageSize = [imagePtr size]; - NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize); + NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize, autosize); if (imageSize.width != scaledSize.width || imageSize.height != scaledSize.height) { [imagePtr setSize: scaledSize]; diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java index 87a6de00917..bb0a7525ec7 100644 --- a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java @@ -24,8 +24,7 @@ /* @test - @bug 8150176 - @ignore 8150176 + @bug 8150176 8151773 @summary Check if correct resolution variant is used for tray icon. @author a.stepanov @run applet/manual=yesno MultiResolutionTrayIconTest.html From 54ba9a6358cc922df30a1113f33aabfc2b32ddb3 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Tue, 5 Apr 2016 21:13:44 +0400 Subject: [PATCH 036/167] 6949414: JMenu.buildMenuElementArray() endless loop 6424606: behavior of returned from MenuSelectionManager.defaultManager() object is inconsistent with spec Reviewed-by: serb, ssadetsky --- .../share/classes/javax/swing/JMenu.java | 11 ++-- .../swing/plaf/basic/BasicPopupMenuUI.java | 8 ++- .../6949414/JPopupMenuEndlessLoopTest.java | 59 +++++++++++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java b/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java index c9a279a5ed0..643f2c85ecb 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java @@ -1296,7 +1296,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @return the array of menu items */ private MenuElement[] buildMenuElementArray(JMenu leaf) { - Vector elements = new Vector(); + Vector elements = new Vector<>(); Component current = leaf.getPopupMenu(); JPopupMenu pop; JMenu menu; @@ -1314,11 +1314,14 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement } else if (current instanceof JMenuBar) { bar = (JMenuBar) current; elements.insertElementAt(bar, 0); - MenuElement me[] = new MenuElement[elements.size()]; - elements.copyInto(me); - return me; + break; + } else { + break; } } + MenuElement me[] = new MenuElement[elements.size()]; + elements.copyInto(me); + return me; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index 4a4d0baf32b..1b6c56c2fc0 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -797,9 +797,11 @@ public class BasicPopupMenuUI extends PopupMenuUI { if (invoker instanceof JPopupMenu) { invoker = ((JPopupMenu)invoker).getInvoker(); } - grabbedWindow = invoker instanceof Window? - (Window)invoker : - SwingUtilities.getWindowAncestor(invoker); + grabbedWindow = (invoker == null) + ? null + : ((invoker instanceof Window) + ? (Window) invoker + : SwingUtilities.getWindowAncestor(invoker)); if(grabbedWindow != null) { if(tk instanceof sun.awt.SunToolkit) { ((sun.awt.SunToolkit)tk).grab(grabbedWindow); diff --git a/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java b/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java new file mode 100644 index 00000000000..0a0df91379f --- /dev/null +++ b/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 6949414 6424606 + * @summary JMenu.buildMenuElementArray() endless loop + * @run main/timeout=5 JPopupMenuEndlessLoopTest + */ +public class JPopupMenuEndlessLoopTest { + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + + JPopupMenu popup = new JPopupMenu("Popup Menu"); + JMenu menu = new JMenu("Menu"); + menu.add(new JMenuItem("Menu Item")); + popup.add(menu); + menu.doClick(); + MenuElement[] elems = MenuSelectionManager + .defaultManager().getSelectedPath(); + + if (elems == null || elems.length == 0) { + throw new RuntimeException("Empty Selection"); + } + + if (elems[0] != popup || elems[1] != menu) { + throw new RuntimeException("Necessary menus are not selected!"); + } + }); + } +} From 2479abaae737d824ddf0d3ec0fb0f21f37308cd9 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 5 Apr 2016 11:52:52 -0700 Subject: [PATCH 037/167] 8146324: Add sun.font.FontUtilities.isComplexCharCode or related method Reviewed-by: serb, ssadetsky --- .../share/classes/java/awt/Font.java | 43 ++++++++++ .../share/classes/sun/font/FontUtilities.java | 19 +++++ .../awt/FontClass/TextRequiresLayoutTest.java | 85 +++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java diff --git a/jdk/src/java.desktop/share/classes/java/awt/Font.java b/jdk/src/java.desktop/share/classes/java/awt/Font.java index 8edd2227bad..29ce9f1a084 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Font.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java @@ -765,6 +765,49 @@ public class Font implements java.io.Serializable this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); } + /** + * Returns true if any part of the specified text is from a + * complex script for which the implementation will need to invoke + * layout processing in order to render correctly when using + * {@link Graphics#drawString(String,int,int) drawString(String,int,int)} + * and other text rendering methods. Measurement of the text + * may similarly need the same extra processing. + * The {@code start} and {@code end} indices are provided so that + * the application can request only a subset of the text be considered. + * The last char index examined is at {@code "end-1"}, + * i.e a request to examine the entire array would be + *
+     * {@code Font.textRequiresLayout(chars, 0, chars.length);}
+     * 
+ * An application may find this information helpful in + * performance sensitive code. + *

+ * Note that even if this method returns {@code false}, layout processing + * may still be invoked when used with any {@code Font} + * for which {@link #hasLayoutAttributes()} returns {@code true}, + * so that method will need to be consulted for the specific font, + * in order to obtain an answer which accounts for such font attributes. + * + * @param chars the text. + * @param start the index of the first char to examine. + * @param end the ending index, exclusive. + * @return {@code true} if the specified text will need special layout. + * @throws NullPointerException if {@code chars} is null. + * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or + * {@code end} is greater than the length of the {@code chars} array. + * @since 9 + */ + public static boolean textRequiresLayout(char[] chars, + int start, int end) { + if (chars == null) { + throw new NullPointerException("null char array"); + } + if (start < 0 || end > chars.length) { + throw new ArrayIndexOutOfBoundsException("start < 0 or end > len"); + } + return FontUtilities.isComplexScript(chars, start, end); + } + /** * Returns a {@code Font} appropriate to the attributes. * If {@code attributes} contains a {@code FONT} attribute diff --git a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java index 3aec0a72d89..bfbd4559448 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -182,6 +182,25 @@ public final class FontUtilities { return FontAccess.getFontAccess().getFont2D(font); } + /** + * Return true if there any characters which would trigger layout. + * This method considers supplementary characters to be simple, + * since we do not presently invoke layout on any code points in + * outside the BMP. + */ + public static boolean isComplexScript(char [] chs, int start, int limit) { + + for (int i = start; i < limit; i++) { + if (chs[i] < MIN_LAYOUT_CHARCODE) { + continue; + } + else if (isComplexCharCode(chs[i])) { + return true; + } + } + return false; + } + /** * If there is anything in the text which triggers a case * where char->glyph does not map 1:1 in straightforward diff --git a/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java new file mode 100644 index 00000000000..99b2595c41b --- /dev/null +++ b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8146324 + * @summary Test Font.textRequiresLayout + */ + +import java.awt.Font; + +public class TextRequiresLayoutTest { + + public static void main(String args[]) { + + String simpleStr = "Hello World"; + String complexStr = "\u0641\u0642\u0643"; + char[] simpleChars = simpleStr.toCharArray(); + char[] complexChars = complexStr.toCharArray(); + + if (Font.textRequiresLayout(simpleChars, 0, simpleChars.length)) { + throw new RuntimeException("Simple text should not need layout"); + } + + if (!Font.textRequiresLayout(complexChars, 0, complexChars.length)) { + throw new RuntimeException("Complex text should need layout"); + } + + if (Font.textRequiresLayout(complexChars, 0, 0)) { + throw new RuntimeException("Empty text should not need layout"); + } + + boolean except = false; + try { + Font.textRequiresLayout(null, 0, 0); + } catch (NullPointerException npe) { + except = true; + } + if (!except) { + throw new RuntimeException("No expected IllegalArgumentException"); + } + + except = false; + try { + Font.textRequiresLayout(complexChars, -1, 0); + } catch (ArrayIndexOutOfBoundsException aioobe) { + except = true; + } + if (!except) { + throw new + RuntimeException("No expected ArrayIndexOutOfBoundsException"); + } + + except = false; + try { + Font.textRequiresLayout(complexChars, 0, complexChars.length+1); + } catch (ArrayIndexOutOfBoundsException aioobe) { + except = true; + } + if (!except) { + throw new + RuntimeException("No expected ArrayIndexOutOfBoundsException"); + } + } +} From d69d30499a70736971a2e653b86e21a2bcb4f383 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Wed, 6 Apr 2016 12:25:21 +0530 Subject: [PATCH 038/167] 8044289: In ImageIO.write() and ImageIO.read() null stream is not handled properly Reviewed-by: prr, serb, psadhukhan --- .../share/classes/javax/imageio/ImageIO.java | 46 ++-- .../imageio/stream/NullStreamCheckTest.java | 202 ++++++++++++++++++ 2 files changed, 230 insertions(+), 18 deletions(-) create mode 100644 jdk/test/javax/imageio/stream/NullStreamCheckTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java index ae480b9c002..7af7b77be77 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java @@ -1294,7 +1294,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(File input) throws IOException { if (input == null) { @@ -1344,7 +1345,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(InputStream input) throws IOException { if (input == null) { @@ -1352,6 +1354,9 @@ public final class ImageIO { } ImageInputStream stream = createImageInputStream(input); + if (stream == null) { + throw new IIOException("Can't create an ImageInputStream!"); + } BufferedImage bi = read(stream); if (bi == null) { stream.close(); @@ -1384,7 +1389,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(URL input) throws IOException { if (input == null) { @@ -1398,6 +1404,14 @@ public final class ImageIO { throw new IIOException("Can't get input stream from URL!", e); } ImageInputStream stream = createImageInputStream(istream); + if (stream == null) { + /* close the istream when stream is null so that if user has + * given filepath as URL he can delete it, otherwise stream will + * be open to that file and he will not be able to delete it. + */ + istream.close(); + throw new IIOException("Can't create an ImageInputStream!"); + } BufferedImage bi; try { bi = read(stream); @@ -1510,7 +1524,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing. + * @exception IOException if an error occurs during writing or when not + * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, String formatName, @@ -1518,7 +1533,6 @@ public final class ImageIO { if (output == null) { throw new IllegalArgumentException("output == null!"); } - ImageOutputStream stream = null; ImageWriter writer = getWriter(im, formatName); if (writer == null) { @@ -1528,13 +1542,11 @@ public final class ImageIO { return false; } - try { - output.delete(); - stream = createImageOutputStream(output); - } catch (IOException e) { - throw new IIOException("Can't create output stream!", e); + output.delete(); + ImageOutputStream stream = createImageOutputStream(output); + if (stream == null) { + throw new IIOException("Can't create an ImageOutputStream!"); } - try { return doWrite(im, writer, stream); } finally { @@ -1562,7 +1574,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing. + * @exception IOException if an error occurs during writing or when not + * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, String formatName, @@ -1570,13 +1583,10 @@ public final class ImageIO { if (output == null) { throw new IllegalArgumentException("output == null!"); } - ImageOutputStream stream = null; - try { - stream = createImageOutputStream(output); - } catch (IOException e) { - throw new IIOException("Can't create output stream!", e); + ImageOutputStream stream = createImageOutputStream(output); + if (stream == null) { + throw new IIOException("Can't create an ImageOutputStream!"); } - try { return doWrite(im, getWriter(im, formatName), stream); } finally { diff --git a/jdk/test/javax/imageio/stream/NullStreamCheckTest.java b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java new file mode 100644 index 00000000000..f763b9de1e6 --- /dev/null +++ b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8044289 + * @summary Test verifies that when some of the read() and write() methods + * are not able to get stream from createImageInputStream() and + * createImageOutputStream() are we doing null check for stream + * and throwing IOException as per specification. + * @run main NullStreamCheckTest + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageInputStreamSpi; +import javax.imageio.spi.ImageOutputStreamSpi; + +public class NullStreamCheckTest { + + // get ImageIORegistry default instance. + private static final IIORegistry localRegistry = IIORegistry. + getDefaultInstance(); + // stream variables needed for input and output. + static LocalOutputStream outputStream = new LocalOutputStream(); + static LocalInputStream inputStream = new LocalInputStream(); + + static final int width = 50, height = 50; + + // input and output BufferedImage needed while read and write. + static BufferedImage inputImage = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + // creates test file needed for read and write in local directory. + private static File createTestFile(String name) throws IOException { + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String filePath = dir+sep; + File directory = new File(filePath); + File tmpTestFile = File.createTempFile(name, ".png", directory); + directory.delete(); + return tmpTestFile; + } + + /* if we catch expected IOException message return + * false otherwise return true. + */ + private static boolean verifyOutputExceptionMessage(IOException ex) { + String message = ex.getMessage(); + return (!message.equals("Can't create an ImageOutputStream!")); + } + + /* if we catch expected IOException message return + * false otherwise return true. + */ + private static boolean verifyInputExceptionMessage(IOException ex) { + String message = ex.getMessage(); + return (!message.equals("Can't create an ImageInputStream!")); + } + + private static void verifyFileWrite() throws IOException { + File outputTestFile = createTestFile("outputTestFile"); + try { + ImageIO.write(inputImage, "png", outputTestFile); + } catch (IOException ex) { + if (verifyOutputExceptionMessage(ex)) + throw ex; + } finally { + outputTestFile.delete(); + } + } + + private static void verifyStreamWrite() throws IOException { + try { + ImageIO.write(inputImage, "png", outputStream); + } catch (IOException ex) { + if (verifyOutputExceptionMessage(ex)) + throw ex; + } finally { + try { + outputStream.close(); + } catch (IOException ex) { + throw ex; + } + } + } + + private static void verifyFileRead() throws IOException { + File inputTestFile = createTestFile("inputTestFile"); + try { + ImageIO.read(inputTestFile); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } finally { + inputTestFile.delete(); + } + } + + private static void verifyStreamRead() throws IOException { + try { + ImageIO.read(inputStream); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } finally { + try { + inputStream.close(); + } catch (IOException ex) { + throw ex; + } + } + } + + private static void verifyUrlRead() throws IOException { + URL url; + File inputTestUrlFile = createTestFile("inputTestFile"); + try { + try { + url = inputTestUrlFile.toURI().toURL(); + } catch (MalformedURLException ex) { + throw ex; + } + + try { + ImageIO.read(url); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } + } finally { + inputTestUrlFile.delete(); + } + } + + public static void main(String[] args) throws IOException, + MalformedURLException { + + /* deregister ImageOutputStreamSpi so that we creatImageOutputStream + * returns null while writing. + */ + localRegistry.deregisterAll(ImageOutputStreamSpi.class); + /* verify possible ImageIO.write() scenario's for null stream output + * from createImageOutputStream() API in ImageIO class. + */ + verifyFileWrite(); + verifyStreamWrite(); + + /* deregister ImageInputStreamSpi so that we creatImageInputStream + * returns null while reading. + */ + localRegistry.deregisterAll(ImageInputStreamSpi.class); + /* verify possible ImageIO.read() scenario's for null stream output + * from createImageInputStream API in ImageIO class. + */ + verifyFileRead(); + verifyStreamRead(); + verifyUrlRead(); + } + + static class LocalOutputStream extends OutputStream { + + @Override + public void write(int i) throws IOException { + } + } + + static class LocalInputStream extends InputStream { + + @Override + public int read() throws IOException { + return 0; + } + } +} From d3b1596a8b9abbae5b7f52d75c69e683785ea9d0 Mon Sep 17 00:00:00 2001 From: Alexander Kulyakhtin Date: Wed, 6 Apr 2016 13:47:18 +0300 Subject: [PATCH 039/167] 8153584: New jtreg test to verify PathSearchingVirutalMachine.bootClassPath() behaviour Adding a new jtreg test Reviewed-by: dsamersoff --- .../sun/jdi/SunBootClassPathEmptyTest.java | 97 +++++++++++++++++++ jdk/test/com/sun/jdi/TestClass.java | 30 ++++++ 2 files changed, 127 insertions(+) create mode 100644 jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java create mode 100644 jdk/test/com/sun/jdi/TestClass.java diff --git a/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java new file mode 100644 index 00000000000..e062996ee6a --- /dev/null +++ b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.jdi.connect.*; +import com.sun.jdi.*; +import java.util.Map; +import java.util.List; +import jdk.test.lib.Asserts; + +/* + * @test + * @summary Verifies that PathSearchingVirtualMachine.bootClassPath() + * returns an empty list in case no bootclass path specified + * regardless of sun.boot.class.path option, which is now obsolete + * @library /test/lib/share/classes + * @compile TestClass.java + * @compile SunBootClassPathEmptyTest.java + * @run main/othervm SunBootClassPathEmptyTest + */ +public class SunBootClassPathEmptyTest { + + /** + * Helper class to facilitate the debuggee VM launching + */ + private static class VmConnector { + + LaunchingConnector lc; + VirtualMachine vm; + + VmConnector() { + for (LaunchingConnector c : Bootstrap.virtualMachineManager().launchingConnectors()) { + System.out.println("name: " + c.name()); + if (c.name().equals("com.sun.jdi.CommandLineLaunch")) { + lc = c; + break; + } + } + if (lc == null) { + throw new RuntimeException("Connector not found"); + } + } + + PathSearchingVirtualMachine launchVm(String cmdLine, String options) throws Exception { + Map vmArgs = lc.defaultArguments(); + vmArgs.get("main").setValue(cmdLine); + if (options != null) { + vmArgs.get("options").setValue(options); + } + System.out.println("Debugger is launching vm ..."); + vm = lc.launch(vmArgs); + if (!(vm instanceof PathSearchingVirtualMachine)) { + throw new RuntimeException("VM is not a PathSearchingVirtualMachine"); + } + return (PathSearchingVirtualMachine) vm; + } + + } + + private static VmConnector connector = new VmConnector(); + + public static void main(String[] args) throws Exception { + testWithObsoleteClassPathOption(null); + testWithObsoleteClassPathOption("someclasspath"); + } + + private static void testWithObsoleteClassPathOption(String obsoleteClassPath) throws Exception { + PathSearchingVirtualMachine vm = connector.launchVm("TestClass", makeClassPathOptions(obsoleteClassPath)); + List bootClassPath = vm.bootClassPath(); + Asserts.assertNotNull(bootClassPath, "Expected bootClassPath to be empty but was null"); + Asserts.assertEquals(0, bootClassPath.size(), "Expected bootClassPath.size() 0 but was: " + bootClassPath.size()); + } + + private static String makeClassPathOptions(String obsoleteClassPath) { + return obsoleteClassPath == null ? null : "-Dsun.boot.class.path=" + obsoleteClassPath; + } + +} diff --git a/jdk/test/com/sun/jdi/TestClass.java b/jdk/test/com/sun/jdi/TestClass.java new file mode 100644 index 00000000000..dab6b66648c --- /dev/null +++ b/jdk/test/com/sun/jdi/TestClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +public class TestClass { + + public static void main(String[] args) { + System.out.println("This is a test"); + } + +} From 8442a9192c70da2968024041eb747bda4d9d6893 Mon Sep 17 00:00:00 2001 From: Yuri Nesterenko Date: Wed, 6 Apr 2016 14:44:32 +0300 Subject: [PATCH 040/167] 8152693: Changed behavior of java/awt/xembed/server/TestXEmbedServerJava.java test Reviewed-by: ssadetsky, serb --- .../xembed/server/TestXEmbedServerJava.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java b/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java index 75898f4cbfe..8e0c3d6774e 100644 --- a/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java +++ b/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java @@ -76,7 +76,23 @@ public class TestXEmbedServerJava extends TestXEmbedServer { public Process startClient(Rectangle[] bounds, long window) { try { String java_home = System.getProperty("java.home"); - return Runtime.getRuntime().exec(java_home + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED JavaClient " + window); + boolean hasModules = true; + try { + Class.class.getMethod("getModule"); + }catch(Exception hasModulesEx) { + hasModules = false; + } + if (hasModules) { + System.out.println(java_home + + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+ + "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window); + return Runtime.getRuntime().exec(java_home + + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+ + "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window); + }else{ + System.out.println(java_home + "/bin/java JavaClient " + window); + return Runtime.getRuntime().exec(java_home + "/bin/java JavaClient " + window); + } } catch (IOException ex1) { ex1.printStackTrace(); } From 5621da5d8abe18945cb9f05f94d7e84834a6b5fc Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Wed, 6 Apr 2016 18:59:21 -0500 Subject: [PATCH 041/167] 8153149: Uninitialised memory in WinAccessBridge.cpp:1128 Remove extraneous initializer Reviewed-by: prr, serb --- .../windows/native/libwindowsaccessbridge/WinAccessBridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp b/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp index 45b47071fcd..3fa8fc6f67c 100644 --- a/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp +++ b/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1125,7 +1125,7 @@ WinAccessBridge::getAccessibleContextWithFocus(HWND window, long *vmID, JOBJECT6 PrintDebugString("WinAccessBridge::getAccessibleContextWithFocus(%p, %X, )", window, vmID); // find vmID, etc. from HWND; ask that VM for the AC w/Focus - HWND pkgVMID = (HWND)ABLongToHandle( pkg->rVMID ) ; + HWND pkgVMID; if (getAccessibleContextFromHWND(window, (long *)&(pkgVMID), &(pkg->rAccessibleContext)) == TRUE) { HWND destABWindow = javaVMs->findAccessBridgeWindow((long)pkgVMID); // ineffecient [[[FIXME]]] if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) { From da560b474474a5e760f193ae028785703951a6fe Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Wed, 6 Apr 2016 19:53:20 -0500 Subject: [PATCH 042/167] 8153153: Format string argument mismatch in jaccesswalker.cpp:545 Use proper format specifier Reviewed-by: prr, serb --- .../windows/native/jaccesswalker/jaccesswalker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp b/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp index b8602f52f0d..7943374892c 100644 --- a/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp +++ b/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -543,7 +543,7 @@ void Jaccesswalker::addComponentNodes(long vmID, AccessibleContext context, } else { char s[LINE_BUFSIZE]; sprintf( s, - "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %X", + "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %p", vmID, context ); TVITEM tvi; From 7aaf0feaf6c43ca6937ebe7f2be2971f2510b646 Mon Sep 17 00:00:00 2001 From: Nishit Jain Date: Fri, 8 Apr 2016 12:00:19 +0900 Subject: [PATCH 043/167] 7015696: The new currency symbols 20B9 (INDIAN RUPEE), 20BA (TURKISH LIRA), 20BD (RUBLE SIGN) not displayed 8031992: Add Kannada support to the JDK Reviewed-by: okutsu, peytoia --- jdk/make/data/fontconfig/windows.fontconfig.properties | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/make/data/fontconfig/windows.fontconfig.properties b/jdk/make/data/fontconfig/windows.fontconfig.properties index 3a2e2b31b18..fcfcb8f5190 100644 --- a/jdk/make/data/fontconfig/windows.fontconfig.properties +++ b/jdk/make/data/fontconfig/windows.fontconfig.properties @@ -37,6 +37,7 @@ allfonts.chinese-gb18030-extb=SimSun-ExtB allfonts.chinese-hkscs=MingLiU_HKSCS allfonts.chinese-ms950-extb=MingLiU-ExtB allfonts.devanagari=Mangal +allfonts.kannada=Tunga allfonts.dingbats=Wingdings allfonts.lucida=Lucida Sans Regular allfonts.symbol=Symbol @@ -239,11 +240,11 @@ sequence.allfonts.x-windows-874=alphabetic,thai,dingbats,symbol sequence.fallback=lucida,symbols,\ chinese-ms950,chinese-hkscs,chinese-ms936,chinese-gb18030,\ - japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian + japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian,kannada # Exclusion Ranges -exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-f8ff +exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-f8ff exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac @@ -295,6 +296,7 @@ filename.GulimChe=gulim.TTC filename.Lucida_Sans_Regular=LucidaSansRegular.ttf filename.Mangal=MANGAL.TTF +filename.Tunga=TUNGA.TTF filename.Symbol=SYMBOL.TTF filename.Wingdings=WINGDING.TTF From 540242ecef1ef17644dc2dae0d3210b69bd29892 Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Fri, 8 Apr 2016 12:56:28 +0300 Subject: [PATCH 044/167] 8152183: [TEST] add test for TIFFField Reviewed-by: prr, yan --- .../tiff/MultiPageImageTIFFFieldTest.java | 378 +++++++++++++ .../tiff/TIFFDirectoryWriteReadTest.java | 3 +- .../imageio/plugins/tiff/TIFFFieldTest.java | 502 ++++++++++++++++++ 3 files changed, 882 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java create mode 100644 jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java diff --git a/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java b/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java new file mode 100644 index 00000000000..4a5757824fd --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @ignore 8148454 + * @bug 8152183 8148454 + * @author a.stepanov + * @summary check that TIFFields are derived properly for multi-page tiff + * @run main MultiPageImageTIFFFieldTest + */ + +import java.awt.*; +import java.awt.color.*; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.*; +import javax.imageio.plugins.tiff.*; + + +public class MultiPageImageTIFFFieldTest { + + private final static String FILENAME = "test.tiff"; + private final static int W1 = 20, H1 = 40, W2 = 100, H2 = 15; + private final static Color C1 = Color.BLACK, C2 = Color.RED; + + private final static int N_WIDTH = BaselineTIFFTagSet.TAG_IMAGE_WIDTH; + private final static int N_HEIGHT = BaselineTIFFTagSet.TAG_IMAGE_LENGTH; + + private static final String DESCRIPTION_1[] = {"Description-1", "abc ABC"}; + private static final String DESCRIPTION_2[] = {"Description-2", "1-2-3"}; + private final static int N_DESCRIPTION = + BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION; + + private final static String EXIF_DATA_1[] = {"2001:01:01 00:00:01"}; + private final static String EXIF_DATA_2[] = {"2002:02:02 00:00:02"}; + private final static int N_EXIF = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL; + + private final static String GPS_DATA[] = { + ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS}; + private final static int N_GPS = ExifGPSTagSet.TAG_GPS_STATUS; + + private final static short FAX_DATA = + FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED; + private final static int N_FAX = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA; + + private static final byte[] ICC_PROFILE_2 = + ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData(); + private static final int N_ICC = BaselineTIFFTagSet.TAG_ICC_PROFILE; + + private static final int N_BPS = BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE; + + private static final int + COMPRESSION_1 = BaselineTIFFTagSet.COMPRESSION_DEFLATE, + COMPRESSION_2 = BaselineTIFFTagSet.COMPRESSION_LZW; + private static final int N_COMPRESSION = BaselineTIFFTagSet.TAG_COMPRESSION; + + private static final int + GRAY_1 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO, + GRAY_2 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO, + RGB = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; + + private static final int N_PHOTO = + BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION; + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data[], + int num) { + + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, data.length, data)); + } + + private void checkASCIIField(TIFFDirectory d, + String what, + String data[], + int num) { + + String notFound = what + " field was not found"; + check(d.containsTIFFField(num), notFound); + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == data.length, "invalid " + what + " data count"); + for (int i = 0; i < data.length; i++) { + check(f.getValueAsString(i).equals(data[i]), + "invalid " + what + " data"); + } + } + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img1 = + new BufferedImage(W1, H1, BufferedImage.TYPE_BYTE_GRAY); + Graphics g = img1.getGraphics(); + g.setColor(C1); + g.fillRect(0, 0, W1, H1); + g.dispose(); + + BufferedImage img2 = + new BufferedImage(W2, H2, BufferedImage.TYPE_INT_RGB); + g = img2.getGraphics(); + g.setColor(C2); + g.fillRect(0, 0, W2, H2); + g.dispose(); + + ImageWriteParam param1 = writer.getDefaultWriteParam(); + param1.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param1.setCompressionType("Deflate"); + param1.setCompressionQuality(0.5f); + + ImageWriteParam param2 = writer.getDefaultWriteParam(); + param2.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param2.setCompressionType("LZW"); + param2.setCompressionQuality(0.5f); + + IIOMetadata + md1 = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img1), param1), + md2 = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img2), param2); + + TIFFDirectory + dir1 = TIFFDirectory.createFromMetadata(md1), + dir2 = TIFFDirectory.createFromMetadata(md2); + + addASCIIField(dir1, "ImageDescription", DESCRIPTION_1, N_DESCRIPTION); + addASCIIField(dir2, "ImageDescription", DESCRIPTION_2, N_DESCRIPTION); + + addASCIIField(dir1, "GPSStatus", GPS_DATA, N_GPS); + addASCIIField(dir2, "GPSStatus", GPS_DATA, N_GPS); + + addASCIIField(dir1, "DateTimeOriginal", EXIF_DATA_1, N_EXIF); + addASCIIField(dir2, "DateTimeOriginal", EXIF_DATA_2, N_EXIF); + + TIFFTag faxTag = new TIFFTag( + "CleanFaxData", N_FAX, 1 << TIFFTag.TIFF_SHORT); + dir1.addTIFFField(new TIFFField(faxTag, FAX_DATA)); + dir2.addTIFFField(new TIFFField(faxTag, FAX_DATA)); + + dir2.addTIFFField(new TIFFField( + new TIFFTag("ICC Profile", N_ICC, 1 << TIFFTag.TIFF_UNDEFINED), + TIFFTag.TIFF_UNDEFINED, ICC_PROFILE_2.length, ICC_PROFILE_2)); + + writer.prepareWriteSequence(null); + writer.writeToSequence( + new IIOImage(img1, null, dir1.getAsMetadata()), param1); + writer.writeToSequence( + new IIOImage(img2, null, dir2.getAsMetadata()), param2); + writer.endWriteSequence(); + + ios.flush(); + writer.dispose(); + } + s.close(); + } + + private void checkBufferedImages(BufferedImage im1, BufferedImage im2) { + + check(im1.getWidth() == W1, "invalid width for image 1"); + check(im1.getHeight() == H1, "invalid height for image 1"); + check(im2.getWidth() == W2, "invalid width for image 2"); + check(im2.getHeight() == H2, "invalid height for image 2"); + + Color + c1 = new Color(im1.getRGB(W1 / 2, H1 / 2)), + c2 = new Color(im2.getRGB(W2 / 2, H2 / 2)); + + check(c1.equals(C1), "invalid image 1 color"); + check(c2.equals(C2), "invalid image 2 color"); + } + + private void readAndCheckImage() throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s, false, true); + + int ni = reader.getNumImages(true); + check(ni == 2, "invalid number of images"); + + // check TIFFImageReadParam for multipage image + TIFFImageReadParam + param1 = new TIFFImageReadParam(), param2 = new TIFFImageReadParam(); + + param1.addAllowedTagSet(ExifTIFFTagSet.getInstance()); + param1.addAllowedTagSet(ExifGPSTagSet.getInstance()); + + param2.addAllowedTagSet(ExifTIFFTagSet.getInstance()); + param2.addAllowedTagSet(GeoTIFFTagSet.getInstance()); + + // FaxTIFFTagSet is allowed by default + param2.removeAllowedTagSet(FaxTIFFTagSet.getInstance()); + + + // read images and metadata + IIOImage i1 = reader.readAll(0, param1), i2 = reader.readAll(1, param2); + BufferedImage + bi1 = (BufferedImage) i1.getRenderedImage(), + bi2 = (BufferedImage) i2.getRenderedImage(); + + // check rendered images, just in case + checkBufferedImages(bi1, bi2); + + TIFFDirectory + dir1 = TIFFDirectory.createFromMetadata(i1.getMetadata()), + dir2 = TIFFDirectory.createFromMetadata(i2.getMetadata()); + + // check ASCII fields + checkASCIIField( + dir1, "image 1 description", DESCRIPTION_1, N_DESCRIPTION); + checkASCIIField( + dir2, "image 2 description", DESCRIPTION_2, N_DESCRIPTION); + + checkASCIIField(dir1, "image 1 datetime", EXIF_DATA_1, N_EXIF); + checkASCIIField(dir2, "image 2 datetime", EXIF_DATA_2, N_EXIF); + + // check sizes + TIFFField f = dir1.getTIFFField(N_WIDTH); + check((f.getCount() == 1) && (f.getAsInt(0) == W1), + "invalid width field for image 1"); + f = dir2.getTIFFField(N_WIDTH); + check((f.getCount() == 1) && (f.getAsInt(0) == W2), + "invalid width field for image 2"); + + f = dir1.getTIFFField(N_HEIGHT); + check((f.getCount() == 1) && (f.getAsInt(0) == H1), + "invalid height field for image 1"); + f = dir2.getTIFFField(N_HEIGHT); + check((f.getCount() == 1) && (f.getAsInt(0) == H2), + "invalid height field for image 2"); + + // check fax data + check(dir1.containsTIFFField(N_FAX), "image 2 TIFF directory " + + "must contain clean fax data"); + f = dir1.getTIFFField(N_FAX); + check( + (f.getCount() == 1) && f.isIntegral() && (f.getAsInt(0) == FAX_DATA), + "invalid clean fax data"); + + check(!dir2.containsTIFFField(N_FAX), "image 2 TIFF directory " + + "must not contain fax fields"); + + // check GPS data + checkASCIIField(dir1, "GPS status", GPS_DATA, N_GPS); + + check(!dir2.containsTIFFField(N_GPS), "image 2 TIFF directory " + + "must not contain GPS fields"); + + // check ICC profile data + check(!dir1.containsTIFFField(N_ICC), "image 1 TIFF directory " + + "must not contain ICC Profile field"); + check(dir2.containsTIFFField(N_ICC), "image 2 TIFF directory " + + "must contain ICC Profile field"); + + f = dir2.getTIFFField(N_ICC); + check(f.getType() == TIFFTag.TIFF_UNDEFINED, + "invalid ICC profile field type"); + int cnt = f.getCount(); + byte icc[] = f.getAsBytes(); + check((cnt == ICC_PROFILE_2.length) && (cnt == icc.length), + "invalid ICC profile"); + for (int i = 0; i < cnt; i++) { + check(icc[i] == ICC_PROFILE_2[i], "invalid ICC profile data"); + } + + // check component sizes + check(dir1.getTIFFField(N_BPS).isIntegral() && + dir2.getTIFFField(N_BPS).isIntegral(), + "invalid bits per sample type"); + int sz1[] = bi1.getColorModel().getComponentSize(), + sz2[] = bi2.getColorModel().getComponentSize(), + bps1[] = dir1.getTIFFField(N_BPS).getAsInts(), + bps2[] = dir2.getTIFFField(N_BPS).getAsInts(); + + check((bps1.length == sz1.length) && (bps2.length == sz2.length), + "invalid component size count"); + + for (int i = 0; i < bps1.length; i++) { + check(bps1[i] == sz1[i], "image 1: invalid bits per sample data"); + } + + for (int i = 0; i < bps2.length; i++) { + check(bps2[i] == sz2[i], "image 2: invalid bits per sample data"); + } + + // check compression data + check(dir1.containsTIFFField(N_COMPRESSION) && + dir2.containsTIFFField(N_COMPRESSION), + "compression info lost"); + f = dir1.getTIFFField(N_COMPRESSION); + check(f.isIntegral() && (f.getCount() == 1) && + (f.getAsInt(0) == COMPRESSION_1), "invalid image 1 compression data"); + + f = dir2.getTIFFField(N_COMPRESSION); + check(f.isIntegral() && (f.getCount() == 1) && + (f.getAsInt(0) == COMPRESSION_2), "invalid image 2 compression data"); + + // check photometric interpretation + f = dir1.getTIFFField(N_PHOTO); + check(f.isIntegral() && (f.getCount() == 1) && + ((f.getAsInt(0) == GRAY_1) || (f.getAsInt(0) == GRAY_2)), + "invalid photometric interpretation for image 1"); + + f = dir2.getTIFFField(N_PHOTO); + check(f.isIntegral() && (f.getCount() == 1) && (f.getAsInt(0) == RGB), + "invalid photometric interpretation for image 2"); + } + + public void run() { + + try { + writeImage(); + readAndCheckImage(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void check(boolean ok, String msg) { + + if (!ok) { throw new RuntimeException(msg); } + } + + public static void main(String[] args) { + (new MultiPageImageTIFFFieldTest()).run(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java index eb668255ea6..45477608016 100644 --- a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java @@ -207,7 +207,8 @@ public class TIFFDirectoryWriteReadTest { // RGB: PhotometricInterpretation = 2 f = dir.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); check(f.getCount() == 1, "invalid count"); - check(f.getAsInt(0) == 2, "invalid photometric interpretation for RGB"); + check(f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB, + "invalid photometric interpretation value"); String rat = " resolution must be rational"; f = dir.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION); diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java new file mode 100644 index 00000000000..a50929e8a46 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8152183 + * @author a.stepanov + * @summary Some checks for TIFFField methods + * @run main TIFFFieldTest + */ + +import java.util.List; +import java.util.ArrayList; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.plugins.tiff.*; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +public class TIFFFieldTest { + + private final static String NAME = "tag"; // tag name + private final static int NUM = 12345; // tag number + private final static int MIN_TYPE = TIFFTag.MIN_DATATYPE; + private final static int MAX_TYPE = TIFFTag.MAX_DATATYPE; + private final static String CONSTRUCT = "can construct TIFFField with "; + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void testConstructors() { + + // test constructors + + TIFFTag tag = new TIFFTag( + NAME, NUM, 1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG); + TIFFField f; + + // constructor: TIFFField(tag, value) + boolean ok = false; + try { new TIFFField(null, 0); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid count"); + + // check value type recognition + int v = 1 << 16; + f = new TIFFField(tag, v - 1); + check(f.getType() == TIFFTag.TIFF_SHORT, "must be treated as short"); + check(f.isIntegral(), "must be integral"); + f = new TIFFField(tag, v); + check(f.getType() == TIFFTag.TIFF_LONG, "must be treated as long"); + + // other checks + check(f.getAsLongs().length == 1, "invalid long[] size"); + check(f.isIntegral(), "must be integral"); + check((f.getDirectory() == null) && !f.hasDirectory(), + "must not have directory"); + check(f.getValueAsString(0).equals(String.valueOf(v)), + "invalid string representation of value"); + check(f.getTag().getNumber() == f.getTagNumber(), + "invalid tag number"); + check(f.getCount() == 1, "invalid count"); + check(f.getTagNumber() == NUM, "invalid tag number"); + + // constructor: TIFFField(tag, type, count) + int type = TIFFTag.TIFF_SHORT; + + ok = false; + try { new TIFFField(null, type, 1); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, MAX_TYPE + 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid type tag"); + + // check that count == 1 for TIFF_IFD_POINTER + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "only count = 1 should be allowed for IFDPointer"); + + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 2); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "only count = 1 should be allowed for IFDPointer"); + + // check that count == 0 is not allowed for TIFF_RATIONAL, TIFF_SRATIONAL + // (see fix for JDK-8149120) + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_RATIONAL, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "count = 0 should not be allowed for Rational"); + + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_SRATIONAL, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "count = 0 should not be allowed for SRational"); + + ok = false; + try { new TIFFField(tag, type, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "with invalid data count"); + + f = new TIFFField(tag, type, 0); + check(f.getCount() == 0, "invalid count"); + check(!f.hasDirectory(), "must not have directory"); + + // constructor: TIFFField(tag, type, count, data) + double a[] = {0.1, 0.2, 0.3}; + ok = false; + try { new TIFFField(null, TIFFTag.TIFF_DOUBLE, a.length, a); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, type, a.length - 1, a); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data count"); + + String a2[] = {"one", "two"}; + ok = false; + try { new TIFFField(tag, type, 2, a2); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data type"); + check((f.getDirectory() == null) && !f.hasDirectory(), + "must not have directory"); + + // constructor: TIFFField(tag, type, offset, dir) + List tags = new ArrayList<>(); + tags.add(tag); + TIFFTagSet sets[] = {new TIFFTagSet(tags)}; + TIFFDirectory dir = new TIFFDirectory(sets, null); + + ok = false; + try { new TIFFField(null, type, 4L, dir); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, type, 0L, dir); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "non-positive offset"); + + long offset = 4; + + for (int t = MIN_TYPE; t <= MAX_TYPE; t++) { + + tag = new TIFFTag(NAME, NUM, 1 << t); + + // only TIFF_LONG and TIFF_IFD_POINTER types are allowed + if (t == TIFFTag.TIFF_LONG || t == TIFFTag.TIFF_IFD_POINTER) { + + f = new TIFFField(tag, t, offset, dir); + check(f.hasDirectory(), "must have directory"); + + check(f.getDirectory().getTag(NUM).getName().equals(NAME), + "invalid tag name"); + + check(f.getCount() == 1, "invalid count"); + check(f.getAsLong(0) == offset, "invalid offset"); + } else { + ok = false; + try { new TIFFField(tag, t, offset, dir); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data type"); + } + } + + type = TIFFTag.TIFF_IFD_POINTER; + tag = new TIFFTag(NAME, NUM, 1 << type); + ok = false; + try { new TIFFField(tag, type, offset, null); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null TIFFDirectory"); + + type = TIFFTag.TIFF_LONG; + tag = new TIFFTag(NAME, NUM, 1 << type); + ok = false; + try { new TIFFField(tag, type, offset, null); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null TIFFDirectory"); + } + + private void testTypes() { + + // test getTypeName(), getTypeByName() methods + + boolean ok = false; + try { TIFFField.getTypeName(MIN_TYPE - 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid data type number used"); + + ok = false; + try { TIFFField.getTypeName(MAX_TYPE + 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid data type number used"); + + for (int type = MIN_TYPE; type <= MAX_TYPE; type++) { + String name = TIFFField.getTypeName(type); + check(TIFFField.getTypeByName(name) == type, "invalid type"); + } + + for (int type = MIN_TYPE; type <= MAX_TYPE; type++) { + + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type); + TIFFField f = new TIFFField(tag, type, 1); + check(f.getType() == type, "invalid type"); + + // check that invalid data types can not be used + for (int type2 = MIN_TYPE; type2 <= MAX_TYPE; ++type2) { + if (type2 != type) { + ok = false; + try { new TIFFField(tag, type2, 1); } // invalid type + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid type was successfully set"); + } + } + } + } + + private void testGetAs() { + + // test getAs...() methods + + int type = TIFFTag.TIFF_SHORT; + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SHORT); + + short v = 123; + TIFFField f = new TIFFField(tag, v); + + check(f.getAsInt(0) == (int) v, "invalid int value"); + check(f.getAsLong(0) == (long) v, "invalid long value"); + check(f.getAsFloat(0) == (float) v, "invalid float value"); + check(f.getAsDouble(0) == (double) v, "invalid double value"); + check(f.getValueAsString(0).equals(Short.toString(v)), + "invalid string representation"); + + check(f.getAsInts().length == 1, "inavlid array size"); + check((int) v == f.getAsInts()[0], "invalid int value"); + + float fa[] = {0.01f, 1.01f}; + type = TIFFTag.TIFF_FLOAT; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, fa.length, fa); + check(f.getCount() == fa.length, "invalid count"); + float fa2[] = f.getAsFloats(); + check(fa2.length == fa.length, "invalid array size"); + + for (int i = 0; i < fa.length; i++) { + check(fa2[i] == fa[i], "invalid value"); + check(f.getAsDouble(i) == fa[i], "invalid value"); + check(f.getAsInt(i) == (int) fa[i], "invalid value"); // cast to int + check(f.getValueAsString(i).equals(Float.toString(fa[i])), + "invalid string representation"); + } + + byte ba[] = {-1, -10, -100}; + type = TIFFTag.TIFF_BYTE; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, ba.length, ba); + check(f.getCount() == ba.length, "invalid count"); + byte ba2[] = f.getAsBytes(); + check(ba2.length == ba.length, "invalid count"); + + for (int i = 0; i < ba.length; i++) { + check(ba[i] == ba2[i], "invalid value"); + check(ba[i] == (byte) f.getAsDouble(i), "invalid value"); + check(ba[i] == (byte) f.getAsLong(i), "invalid value"); + + int unsigned = ba[i] & 0xff; + check(f.getAsInt(i) == unsigned, "must be treated as unsigned"); + } + + char ca[] = {'a', 'z', 0xffff}; + type = TIFFTag.TIFF_SHORT; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, ca.length, ca); + check(f.getCount() == ca.length, "invalid count"); + char ca2[] = f.getAsChars(); + check(ba2.length == ba.length, "invalid count"); + + for (int i = 0; i < ca.length; i++) { + check(ca[i] == ca2[i], "invalid value"); + check(ca[i] == (char) f.getAsDouble(i), "invalid value"); + check(ca[i] == (char) f.getAsLong(i), "invalid value"); + check(ca[i] == (char) f.getAsInt(i), "invalid value"); + } + + type = TIFFTag.TIFF_DOUBLE; + double da[] = {0.1, 0.2, 0.3}; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, da.length, da); + check(!f.isIntegral(), "isIntegral must be false"); + + double da2[] = f.getAsDoubles(); + check(f.getData() instanceof double[], "invalid data type"); + double da3[] = (double[]) f.getData(); + check((da.length == da2.length) && + (da.length == da2.length) && + (da.length == f.getCount()), + "invalid data count"); + for (int i = 0; i < da.length; ++i) { + check(da[i] == da2[i], "invalid data"); + check(da[i] == da3[i], "invalid data"); + } + + boolean ok = false; + try { f.getAsShorts(); } + catch (ClassCastException e) { ok = true; } + check(ok, "invalid data cast"); + + ok = false; + try { f.getAsRationals(); } + catch (ClassCastException e) { ok = true; } + check(ok, "invalid data cast"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.MIN_DATATYPE - 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with invalid datatype"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.MAX_DATATYPE + 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with invalid datatype"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.TIFF_FLOAT, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with negative count"); + + int n = 3; + Object + RA = TIFFField.createArrayForType(TIFFTag.TIFF_RATIONAL, n), + SRA = TIFFField.createArrayForType(TIFFTag.TIFF_SRATIONAL, n); + check(RA instanceof long[][], "invalid data type"); + check(SRA instanceof int[][], "invalid data type"); + + long ra[][] = (long[][]) RA; + int sra[][] = (int[][]) SRA; + check((ra.length == n) && (sra.length == n), "invalid data size"); + for (int i = 0; i < n; i++) { + check((ra[i].length == 2) && (sra[i].length == 2), + "invalid data size"); + ra[i][0] = 1; ra[i][1] = 5 + i; + sra[i][0] = -1; sra[i][1] = 5 + i; + } + + type = TIFFTag.TIFF_RATIONAL; + TIFFField f1 = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, n, ra); + type = TIFFTag.TIFF_SRATIONAL; + TIFFField f2 = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, n, sra); + + check((f1.getCount() == ra.length) && (f2.getCount() == sra.length), + "invalid data count"); + + check(f1.getAsRationals().length == n, "invalid data count"); + check(f2.getAsSRationals().length == n, "invalid data count"); + for (int i = 0; i < n; i++) { + long r[] = f1.getAsRational(i); + check(r.length == 2, "invalid data format"); + check((r[0] == 1) && (r[1] == i + 5), "invalid data"); + + int sr[] = f2.getAsSRational(i); + check(sr.length == 2, "invalid data format"); + check((sr[0] == -1) && (sr[1] == i + 5), "invalid data"); + + // check string representation + String s = Long.toString(r[0]) + "/" + Long.toString(r[1]); + check(s.equals(f1.getValueAsString(i)), + "invalid string representation"); + + s = Integer.toString(sr[0]) + "/" + Integer.toString(sr[1]); + check(s.equals(f2.getValueAsString(i)), + "invalid string representation"); + + // see the documentation for getAsInt: + // TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated + // by dividing the numerator into the denominator using + // double-precision arithmetic and then casting to int + check(f1.getAsInt(i) == (int)(r[0] / r[1]), + "invalid result for getAsInt"); + check(f2.getAsInt(i) == (int)(r[0] / r[1]), + "invalid result for getAsInt"); + } + + ok = false; + try { f1.getAsRational(ra.length); } + catch (ArrayIndexOutOfBoundsException e) { ok = true; } + check(ok, "invalid index"); + + String sa[] = {"-1.e-25", "22", "-1.23E5"}; + type = TIFFTag.TIFF_ASCII; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, sa.length, sa); + + // test clone() method + TIFFField cloned = null; + try { cloned = f.clone(); } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + + check(f.getCount() == cloned.getCount(), "invalid cloned field count"); + + check(f.getCount() == sa.length, "invalid data count"); + for (int i = 0; i < sa.length; i++) { + check(sa[i].equals(f.getAsString(i)), "invalid data"); + // see docs: "data in TIFF_ASCII format will be parsed as by + // the Double.parseDouble method, with the result cast to int" + check(f.getAsInt(i) == + (int) Double.parseDouble(sa[i]), "invalid data"); + check(f.getAsDouble(i) == Double.parseDouble(sa[i]), "invalid data"); + + check(sa[i].equals(cloned.getAsString(i)), "invalid cloned data"); + } + } + + private void testCreateFromNode() { + + int type = TIFFTag.TIFF_LONG; + + List tags = new ArrayList<>(); + int v = 1234567; + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type); + tags.add(tag); + TIFFTagSet ts = new TIFFTagSet(tags); + + boolean ok = false; + try { TIFFField.createFromMetadataNode(ts, null); } + catch (NullPointerException e) { ok = true; } + check(ok, "can create TIFFField from a null node"); + + TIFFField f = new TIFFField(tag, v); + Node node = f.getAsNativeNode(); + check(node.getNodeName().equals(f.getClass().getSimpleName()), + "invalid node name"); + + NamedNodeMap attrs = node.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + String an = attrs.item(i).getNodeName().toLowerCase(); + String av = attrs.item(i).getNodeValue(); + if (an.contains("name")) { + check(av.equals(NAME), "invalid tag name"); + } else if (an.contains("number")) { + check(av.equals(Integer.toString(NUM)), "invalid tag number"); + } + } + + // invalid node + IIOMetadataNode nok = new IIOMetadataNode("NOK"); + + ok = false; + try { TIFFField.createFromMetadataNode(ts, nok); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid node name"); + + TIFFField f2 = TIFFField.createFromMetadataNode(ts, node); + check(f2.getType() == type, "invalid type"); + check(f2.getTagNumber() == NUM, "invalid tag number"); + check(f2.getTag().getName().equals(NAME), "invalid tag name"); + check(f2.getCount() == 1, "invalid count"); + check(f2.getAsInt(0) == v, "invalid value"); + } + + public static void main(String[] args) { + + TIFFFieldTest test = new TIFFFieldTest(); + test.testConstructors(); + test.testCreateFromNode(); + test.testTypes(); + test.testGetAs(); + } +} From fd6a72271b19efd83d54d758cdae294a70e87c2c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 8 Apr 2016 13:14:23 +0200 Subject: [PATCH 045/167] 8152666: The new Hotspot Build System Co-authored-by: Magnus Ihse Bursie Co-authored-by: Ingemar Aberg Reviewed-by: ihse, dcubed, erikj --- jdk/make/Import.gmk | 8 ++++---- jdk/make/copy/Copy-java.base.gmk | 22 +++++++++++----------- jdk/make/lib/CoreLibraries.gmk | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk index 42155494fb2..d479b095514 100644 --- a/jdk/make/Import.gmk +++ b/jdk/make/Import.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -83,20 +83,20 @@ ifneq ($(STATIC_BUILD), true) endif ifneq ($(OPENJDK_TARGET_OS), windows) - ifeq ($(JVM_VARIANT_SERVER), true) + ifeq ($(call check-jvm-variant, server), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (, $(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) endif endif - ifeq ($(JVM_VARIANT_CLIENT), true) + ifeq ($(call check-jvm-variant, client), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (, $(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) endif endif ifneq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (,$(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk index 04988de5f85..d50b52378f9 100644 --- a/jdk/make/copy/Copy-java.base.gmk +++ b/jdk/make/copy/Copy-java.base.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ endif # # How to install jvm.cfg. # -ifeq ($(JVM_VARIANT_ZERO), true) +ifeq ($(call check-jvm-variant, zero zeroshark), true) JVMCFG_ARCH := zero else JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY) @@ -99,7 +99,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) else JVMCFG_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/$(JVMCFG_ARCH)/jvm.cfg # Allow override by ALT_JVMCFG_SRC if it exists - JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC)) + JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC)) endif JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR) JVMCFG := $(JVMCFG_DIR)/jvm.cfg @@ -117,12 +117,12 @@ else # The main problem is deciding whether to use aliases for the VMs that are not # present and the current position is that we add aliases for client and server, but # not for minimal. - CLIENT_AND_SERVER := $(and $(findstring true, $(JVM_VARIANT_SERVER)), $(findstring true, $(JVM_VARIANT_CLIENT))) - ifeq ($(CLIENT_AND_SERVER), true) + CLIENT_AND_SERVER := $(call check-jvm-variant, client)+$(call check-jvm-variant, server) + ifeq ($(CLIENT_AND_SERVER), true+true) COPY_JVM_CFG_FILE := true else # For zero, the default jvm.cfg file is sufficient - ifeq ($(JVM_VARIANT_ZERO), true) + ifeq ($(call check-jvm-variant, zero zeroshark), true) COPY_JVM_CFG_FILE := true endif endif @@ -136,21 +136,21 @@ else $(MKDIR) -p $(@D) $(RM) $(@) # Now check for other permutations - ifeq ($(JVM_VARIANT_SERVER), true) + ifeq ($(call check-jvm-variant, server), true) $(PRINTF) "-server KNOWN\n">>$(@) $(PRINTF) "-client ALIASED_TO -server\n">>$(@) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) endif else - ifeq ($(JVM_VARIANT_CLIENT), true) + ifeq ($(call check-jvm-variant, client), true) $(PRINTF) "-client KNOWN\n">>$(@) $(PRINTF) "-server ALIASED_TO -client\n">>$(@) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) endif else - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) $(PRINTF) "-server ALIASED_TO -minimal\n">>$(@) $(PRINTF) "-client ALIASED_TO -minimal\n">>$(@) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index f114c9b7d33..bccf46bb824 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -289,7 +289,7 @@ LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli) LIBJLI_CFLAGS := $(CFLAGS_JDKLIB) -ifeq ($(JVM_VARIANT_ZERO), true) +ifeq ($(call check-jvm-variant, zero zeroshark), true) ERGO_FAMILY := zero else ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) From 74f12569ece839f772463d081d8ba954962a1af9 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Fri, 8 Apr 2016 12:26:47 -0700 Subject: [PATCH 046/167] 8153123: Streamline StackWalker code Reviewed-by: coleenp, dfuchs, mchung, redestad --- jdk/make/mapfiles/libjava/mapfile-vers | 3 +- .../classes/java/lang/StackFrameInfo.java | 92 +-- .../classes/java/lang/StackStreamFactory.java | 765 ++++++++---------- .../share/classes/java/lang/Thread.java | 5 +- .../share/classes/java/lang/Throwable.java | 18 +- .../classes/java/lang/invoke/MemberName.java | 4 + .../internal/misc/JavaLangInvokeAccess.java | 5 + jdk/src/java.base/share/native/include/jvm.h | 11 +- .../share/native/libjava/StackFrameInfo.c | 22 +- .../share/native/libjava/StackStreamFactory.c | 13 +- .../java/lang/StackWalker/DumpStackTest.java | 3 - .../lang/StackWalker/GetCallerClassTest.java | 3 +- .../java/lang/StackWalker/StackWalkTest.java | 4 - .../lang/StackWalker/VerifyStackTrace.java | 3 +- 14 files changed, 391 insertions(+), 560 deletions(-) diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index eb35a623fb2..24db66e8e29 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -139,8 +139,7 @@ SUNWprivate_1.1 { Java_java_lang_Double_doubleToRawLongBits; Java_java_lang_Float_intBitsToFloat; Java_java_lang_Float_floatToRawIntBits; - Java_java_lang_StackFrameInfo_fillInStackFrames; - Java_java_lang_StackFrameInfo_setMethodInfo; + Java_java_lang_StackFrameInfo_toStackTraceElement0; Java_java_lang_StackStreamFactory_checkStackWalkModes; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames; diff --git a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java index 0750af15b03..187a737d7c4 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java +++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java @@ -37,24 +37,14 @@ class StackFrameInfo implements StackFrame { private final static JavaLangInvokeAccess jlInvokeAccess = SharedSecrets.getJavaLangInvokeAccess(); - // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields; - // otherwise, VM will set the hidden fields (injected by the VM). - // -XX:+MemberNameInStackFrame is temporary to enable performance measurement - // - // Footprint improvement: MemberName::clazz and MemberName::name - // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName - // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name + // Footprint improvement: MemberName::clazz can replace + // StackFrameInfo::declaringClass. final StackWalker walker; final Class declaringClass; final Object memberName; - final int bci; - - // methodName, fileName, and lineNumber will be lazily set by the VM - // when first requested. - private String methodName; - private String fileName = null; // default for unavailable filename - private int lineNumber = -1; // default for unavailable lineNumber + final short bci; + private volatile StackTraceElement ste; /* * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser @@ -78,77 +68,53 @@ class StackFrameInfo implements StackFrame { return declaringClass; } - // Call the VM to set methodName, lineNumber, and fileName - private synchronized void ensureMethodInfoInitialized() { - if (methodName == null) { - setMethodInfo(); - } - } - @Override public String getMethodName() { - ensureMethodInfoInitialized(); - return methodName; + return jlInvokeAccess.getName(memberName); } @Override - public Optional getFileName() { - ensureMethodInfoInitialized(); - return fileName != null ? Optional.of(fileName) : Optional.empty(); + public final Optional getFileName() { + StackTraceElement ste = toStackTraceElement(); + return ste.getFileName() != null ? Optional.of(ste.getFileName()) : Optional.empty(); } @Override - public OptionalInt getLineNumber() { - ensureMethodInfoInitialized(); - return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty(); + public final OptionalInt getLineNumber() { + StackTraceElement ste = toStackTraceElement(); + return ste.getLineNumber() > 0 ? OptionalInt.of(ste.getLineNumber()) : OptionalInt.empty(); } @Override - public boolean isNativeMethod() { - ensureMethodInfoInitialized(); - return lineNumber == -2; + public final boolean isNativeMethod() { + StackTraceElement ste = toStackTraceElement(); + return ste.isNativeMethod(); } @Override public String toString() { - ensureMethodInfoInitialized(); - // similar format as StackTraceElement::toString - if (isNativeMethod()) { - return getClassName() + "." + getMethodName() + "(Native Method)"; - } else { - // avoid allocating Optional objects - return getClassName() + "." + getMethodName() + - "(" + (fileName != null ? fileName : "Unknown Source") + - (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")"; - } + StackTraceElement ste = toStackTraceElement(); + return ste.toString(); } /** - * Lazily initialize method name, file name, line number + * Fill in the fields of the given StackTraceElement */ - private native void setMethodInfo(); - - /** - * Fill in source file name and line number of the given StackFrame array. - */ - static native void fillInStackFrames(int startIndex, - Object[] stackframes, - int fromIndex, int toIndex); + private native void toStackTraceElement0(StackTraceElement ste); @Override public StackTraceElement toStackTraceElement() { - ensureMethodInfoInitialized(); - - Module module = declaringClass.getModule(); - String moduleName = module.isNamed() ? module.getName() : null; - String moduleVersion = null; - if (module.isNamed() && module.getDescriptor().version().isPresent()) { - moduleVersion = module.getDescriptor().version().get().toString(); + StackTraceElement s = ste; + if (s == null) { + synchronized (this) { + s = ste; + if (s == null) { + s = new StackTraceElement(); + toStackTraceElement0(s); + ste = s; + } + } } - return new StackTraceElement(moduleName, moduleVersion, - getClassName(), getMethodName(), - fileName, - lineNumber); + return s; } - } diff --git a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java index dcb471c4cc2..ac2e8916bea 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -24,9 +24,6 @@ */ package java.lang; -import jdk.internal.misc.VM; - -import java.io.PrintStream; import java.lang.StackWalker.Option; import java.lang.StackWalker.StackFrame; @@ -34,12 +31,9 @@ import java.lang.annotation.Native; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Arrays; -import java.util.EnumSet; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.Spliterator; import java.util.function.Consumer; @@ -60,8 +54,7 @@ import static java.lang.StackStreamFactory.WalkerState.*; * to avoid overhead of Stream/Lambda * 1. Support traversing Stream * 2. StackWalker::getCallerClass - * 3. Throwable::init and Throwable::getStackTrace - * 4. AccessControlContext getting ProtectionDomain + * 3. AccessControlContext getting ProtectionDomain */ final class StackStreamFactory { private StackStreamFactory() {} @@ -78,25 +71,22 @@ final class StackStreamFactory { // These flags must match the values maintained in the VM @Native private static final int DEFAULT_MODE = 0x0; @Native private static final int FILL_CLASS_REFS_ONLY = 0x2; - @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10; @Native private static final int SHOW_HIDDEN_FRAMES = 0x20; // LambdaForms are hidden by the VM @Native private static final int FILL_LIVE_STACK_FRAMES = 0x100; - /* * For Throwable to use StackWalker, set useNewThrowable to true. * Performance work and extensive testing is needed to replace the * VM built-in backtrace filled in Throwable with the StackWalker. */ - final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false); final static boolean isDebug = getProperty("stackwalk.debug", false); static StackFrameTraverser makeStackTraverser(StackWalker walker, Function, ? extends T> function) { if (walker.hasLocalsOperandsOption()) - return new LiveStackInfoTraverser(walker, function); + return new LiveStackInfoTraverser<>(walker, function); else - return new StackFrameTraverser(walker, function); + return new StackFrameTraverser<>(walker, function); } /** @@ -106,40 +96,31 @@ final class StackStreamFactory { return new CallerClassFinder(walker); } - static boolean useStackTrace(Throwable t) { - if (t instanceof VirtualMachineError) - return false; - - return VM.isBooted() && StackStreamFactory.useNewThrowable; - } - - /* - * This should only be used by Throwable::. - */ - static StackTrace makeStackTrace(Throwable ex) { - return StackTrace.dump(ex); - } - - /* - * This creates StackTrace for Thread::dumpThread to use. - */ - static StackTrace makeStackTrace() { - return StackTrace.dump(); - } - enum WalkerState { NEW, // the stream is new and stack walking has not started OPEN, // the stream is open when it is being traversed. CLOSED; // the stream is closed when the stack walking is done } - static abstract class AbstractStackWalker { + /** + * Subclass of AbstractStackWalker implements a specific stack walking logic. + * It needs to set up the frame buffer and stack walking mode. + * + * It initiates the VM stack walking via the callStackWalk method that serves + * as the anchored frame and VM will call up to AbstractStackWalker::doStackWalk. + * + * @param the type of the result returned from stack walking + * @param the type of the data gathered for each frame. + * For example, StackFrameInfo for StackWalker::walk or + * Class for StackWalker::getCallerClass + */ + static abstract class AbstractStackWalker { protected final StackWalker walker; protected final Thread thread; protected final int maxDepth; protected final long mode; - protected int depth; // traversed stack depth - protected FrameBuffer frameBuffer; // buffer for VM to fill in + protected int depth; // traversed stack depth + protected FrameBuffer frameBuffer; protected long anchor; // buffers to fill in stack frame information @@ -157,16 +138,13 @@ final class StackStreamFactory { private int toStackWalkMode(StackWalker walker, int mode) { int newMode = mode; if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) && - !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */) + (mode & FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY) newMode |= SHOW_HIDDEN_FRAMES; if (walker.hasLocalsOperandsOption()) newMode |= FILL_LIVE_STACK_FRAMES; return newMode; } - private boolean fillCallerClassOnly(int mode) { - return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY; - } /** * A callback method to consume the stack frames. This method is invoked * once stack walking begins (i.e. it is only invoked when walkFrames is called). @@ -179,7 +157,7 @@ final class StackStreamFactory { * * @return the number of consumed frames */ - protected abstract T consumeFrames(); + protected abstract R consumeFrames(); /** * Initialize FrameBuffer. Subclass should implement this method to @@ -252,7 +230,7 @@ final class StackStreamFactory { * Walks stack frames until {@link #consumeFrames} is done consuming * the frames it is interested in. */ - final T walk() { + final R walk() { checkState(NEW); try { // VM will need to stablize the stack before walking. It will invoke @@ -318,7 +296,7 @@ final class StackStreamFactory { } this.anchor = anchor; // set anchor for this bulk stack frame traversal - frameBuffer.setBatch(bufStartIndex, bufEndIndex); + frameBuffer.setBatch(depth, bufStartIndex, bufEndIndex); // traverse all frames and perform the action on the stack frames, if specified return consumeFrames(); @@ -381,15 +359,14 @@ final class StackStreamFactory { * If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will * fetch the next batch of stack frames to continue. */ - private T beginStackWalk() { + private R beginStackWalk() { // initialize buffers for VM to fill the stack frame info initFrameBuffer(); return callStackWalk(mode, 0, frameBuffer.curBatchFrameCount(), frameBuffer.startIndex(), - frameBuffer.classes, - frameBuffer.stackFrames); + frameBuffer.frames()); } /* @@ -404,8 +381,7 @@ final class StackStreamFactory { int endIndex = fetchStackFrames(mode, anchor, batchSize, startIndex, - frameBuffer.classes, - frameBuffer.stackFrames); + frameBuffer.frames()); if (isDebug) { System.out.format(" more stack walk requesting %d got %d to %d frames%n", batchSize, frameBuffer.startIndex(), endIndex); @@ -414,27 +390,26 @@ final class StackStreamFactory { if (numFrames == 0) { frameBuffer.freeze(); // done stack walking } else { - frameBuffer.setBatch(startIndex, endIndex); + frameBuffer.setBatch(depth, startIndex, endIndex); } return numFrames; } /** * Begins stack walking. This method anchors this frame and invokes - * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames. + * AbstractStackWalker::doStackWalk after fetching the first batch of stack frames. * * @param mode mode of stack walking * @param skipframes number of frames to be skipped before filling the frame buffer. * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. * @param startIndex start index of the frame buffers to be filled. - * @param classes Classes buffer of the stack frames - * @param frames StackFrame buffer, or null + * @param frames Either a Class array, if mode is {@link #FILL_CLASS_REFS_ONLY} + * or a {@link StackFrameInfo} (or derivative) array otherwise. * @return Result of AbstractStackWalker::doStackWalk */ - private native T callStackWalk(long mode, int skipframes, + private native R callStackWalk(long mode, int skipframes, int batchSize, int startIndex, - Class[] classes, - StackFrame[] frames); + T[] frames); /** * Fetch the next batch of stack frames. @@ -443,185 +418,14 @@ final class StackStreamFactory { * @param anchor * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. * @param startIndex start index of the frame buffers to be filled. - * @param classes Classes buffer of the stack frames - * @param frames StackFrame buffer, or null + * @param frames Either a Class array, if mode is {@link #FILL_CLASS_REFS_ONLY} + * or a {@link StackFrameInfo} (or derivative) array otherwise. * * @return the end index to the frame buffers */ private native int fetchStackFrames(long mode, long anchor, int batchSize, int startIndex, - Class[] classes, - StackFrame[] frames); - - - /* - * Frame buffer - * - * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer. - */ - class FrameBuffer { - static final int START_POS = 2; // 0th and 1st elements are reserved - - // buffers for VM to fill stack frame info - int currentBatchSize; // current batch size - Class[] classes; // caller class for fast path - - StackFrame[] stackFrames; - - int origin; // index to the current traversed stack frame - int fence; // index to the last frame in the current batch - - FrameBuffer(int initialBatchSize) { - if (initialBatchSize < MIN_BATCH_SIZE) { - throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE); - } - this.origin = START_POS; - this.fence = 0; - this.currentBatchSize = initialBatchSize; - this.classes = new Class[currentBatchSize]; - } - - int curBatchFrameCount() { - return currentBatchSize-START_POS; - } - - /* - * Tests if this frame buffer is empty. All frames are fetched. - */ - final boolean isEmpty() { - return origin >= fence || (origin == START_POS && fence == 0); - } - - /* - * Freezes this frame buffer. The stack stream source is done fetching. - */ - final void freeze() { - origin = 0; - fence = 0; - } - - /* - * Tests if this frame buffer is active. It is inactive when - * it is done for traversal. All stack frames have been traversed. - */ - final boolean isActive() { - return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize); - } - - /** - * Gets the class at the current frame and move to the next frame. - */ - final Class next() { - if (isEmpty()) { - throw new NoSuchElementException("origin=" + origin + " fence=" + fence); - } - Class c = classes[origin++]; - if (isDebug) { - int index = origin-1; - System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index, - Objects.toString(c), index, fence); - } - return c; - } - - /** - * Gets the class at the current frame. - */ - final Class get() { - if (isEmpty()) { - throw new NoSuchElementException("origin=" + origin + " fence=" + fence); - } - return classes[origin]; - } - - /* - * Returns the index of the current frame. - */ - final int getIndex() { - return origin; - } - - /* - * Set the start and end index of a new batch of stack frames that have - * been filled in this frame buffer. - */ - final void setBatch(int startIndex, int endIndex) { - if (startIndex <= 0 || endIndex <= 0) - throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex); - - this.origin = startIndex; - this.fence = endIndex; - if (depth == 0 && fence > 0) { - // filter the frames due to the stack stream implementation - for (int i = START_POS; i < fence; i++) { - Class c = classes[i]; - if (isDebug) System.err.format(" frame %d: %s%n", i, c); - if (filterStackWalkImpl(c)) { - origin++; - } else { - break; - } - } - } - } - - /* - * Checks if the origin is the expected start index. - */ - final void check(int skipFrames) { - int index = skipFrames + START_POS; - if (origin != index) { - // stack walk must continue with the previous frame depth - throw new IllegalStateException("origin " + origin + " != " + index); - } - } - - // ------ subclass may override the following methods ------- - /** - * Resizes the buffers for VM to fill in the next batch of stack frames. - * The next batch will start at the given startIndex with the maximum number - * of elements. - * - *

Subclass may override this method to manage the allocated buffers. - * - * @param startIndex the start index for the first frame of the next batch to fill in. - * @param elements the number of elements for the next batch to fill in. - * - */ - void resize(int startIndex, int elements) { - if (!isActive()) - throw new IllegalStateException("inactive frame buffer can't be resized"); - - int size = startIndex+elements; - if (classes.length < size) { - // copy the elements in classes array to the newly allocated one. - // classes[0] is a Thread object - Class[] prev = classes; - classes = new Class[size]; - System.arraycopy(prev, 0, classes, 0, START_POS); - } - currentBatchSize = size; - } - - /* - * Returns the start index for this frame buffer is refilled. - * - * This implementation reuses the allocated buffer for the next batch - * of stack frames. For subclass to retain the fetched stack frames, - * it should override this method to return the index at which the frame - * should be filled in for the next batch. - */ - int startIndex() { - return START_POS; - } - - /** - * Returns next StackFrame object in the current batch of stack frames - */ - StackFrame nextStackFrame() { - throw new InternalError("should not reach here"); - } - } + T[] frames); } /* @@ -629,46 +433,66 @@ final class StackStreamFactory { * * This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance. */ - static class StackFrameTraverser extends AbstractStackWalker + static class StackFrameTraverser extends AbstractStackWalker implements Spliterator { static { stackWalkImplClasses.add(StackFrameTraverser.class); } private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE; - class Buffer extends FrameBuffer { - Buffer(int initialBatchSize) { + + final class StackFrameBuffer extends FrameBuffer { + private StackFrameInfo[] stackFrames; + StackFrameBuffer(int initialBatchSize) { super(initialBatchSize); - this.stackFrames = new StackFrame[initialBatchSize]; + this.stackFrames = new StackFrameInfo[initialBatchSize]; for (int i = START_POS; i < initialBatchSize; i++) { stackFrames[i] = new StackFrameInfo(walker); } } @Override - void resize(int startIndex, int elements) { - super.resize(startIndex, elements); - - int size = startIndex+elements; - if (stackFrames.length < size) { - stackFrames = new StackFrame[size]; - } - for (int i = startIndex(); i < size; i++) { - stackFrames[i] = new StackFrameInfo(walker); - } + StackFrameInfo[] frames() { + return stackFrames; } @Override - StackFrame nextStackFrame() { + void resize(int startIndex, int elements) { + if (!isActive()) + throw new IllegalStateException("inactive frame buffer can't be resized"); + + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; + + int size = startIndex+elements; + if (stackFrames.length < size) { + StackFrameInfo[] newFrames = new StackFrameInfo[size]; + // copy initial magic... + System.arraycopy(stackFrames, 0, newFrames, 0, startIndex); + stackFrames = newFrames; + } + for (int i = startIndex; i < size; i++) { + stackFrames[i] = new StackFrameInfo(walker); + } + currentBatchSize = size; + } + + @Override + StackFrameInfo nextStackFrame() { if (isEmpty()) { throw new NoSuchElementException("origin=" + origin + " fence=" + fence); } - StackFrame frame = stackFrames[origin]; + StackFrameInfo frame = stackFrames[origin]; origin++; return frame; } + + @Override + final Class at(int index) { + return stackFrames[index].declaringClass; + } } final Function, ? extends T> function; // callback @@ -693,7 +517,7 @@ final class StackStreamFactory { return null; } - StackFrame frame = frameBuffer.nextStackFrame(); + StackFrameInfo frame = frameBuffer.nextStackFrame(); depth++; return frame; } @@ -710,7 +534,7 @@ final class StackStreamFactory { @Override protected void initFrameBuffer() { - this.frameBuffer = new Buffer(getNextBatchSize()); + this.frameBuffer = new StackFrameBuffer(getNextBatchSize()); } @Override @@ -781,7 +605,7 @@ final class StackStreamFactory { * CallerClassFinder is specialized to return Class for each stack frame. * StackFrame is not requested. */ - static class CallerClassFinder extends AbstractStackWalker { + static final class CallerClassFinder extends AbstractStackWalker> { static { stackWalkImplClasses.add(CallerClassFinder.class); } @@ -790,6 +614,54 @@ final class StackStreamFactory { CallerClassFinder(StackWalker walker) { super(walker, FILL_CLASS_REFS_ONLY); + assert (mode & FILL_CLASS_REFS_ONLY) == FILL_CLASS_REFS_ONLY + : "mode should contain FILL_CLASS_REFS_ONLY"; + } + + final class ClassBuffer extends FrameBuffer> { + Class[] classes; // caller class for fast path + ClassBuffer(int batchSize) { + super(batchSize); + classes = new Class[batchSize]; + } + + @Override + Class[] frames() { return classes;} + + @Override + final Class at(int index) { return classes[index];} + + + // ------ subclass may override the following methods ------- + /** + * Resizes the buffers for VM to fill in the next batch of stack frames. + * The next batch will start at the given startIndex with the maximum number + * of elements. + * + *

Subclass may override this method to manage the allocated buffers. + * + * @param startIndex the start index for the first frame of the next batch to fill in. + * @param elements the number of elements for the next batch to fill in. + * + */ + @Override + void resize(int startIndex, int elements) { + if (!isActive()) + throw new IllegalStateException("inactive frame buffer can't be resized"); + + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; + + int size = startIndex+elements; + if (classes.length < size) { + // copy the elements in classes array to the newly allocated one. + // classes[0] is a Thread object + Class[] prev = classes; + classes = new Class[size]; + System.arraycopy(prev, 0, classes, 0, startIndex); + } + currentBatchSize = size; + } } Class findCaller() { @@ -810,15 +682,15 @@ final class StackStreamFactory { if (isMethodHandleFrame(caller)) continue; frames[n++] = caller; } - - if (frames[1] == null) + if (frames[1] == null) { throw new IllegalStateException("no caller frame"); + } return n; } @Override protected void initFrameBuffer() { - this.frameBuffer = new FrameBuffer(getNextBatchSize()); + this.frameBuffer = new ClassBuffer(getNextBatchSize()); } @Override @@ -832,215 +704,64 @@ final class StackStreamFactory { } } - /* - * StackTrace caches all frames in the buffer. StackTraceElements are - * created lazily when Throwable::getStackTrace is called. - */ - static class StackTrace extends AbstractStackWalker { - static { - stackWalkImplClasses.add(StackTrace.class); - } - - class GrowableBuffer extends FrameBuffer { - GrowableBuffer(int initialBatchSize) { - super(initialBatchSize); - - this.stackFrames = new StackFrame[initialBatchSize]; - for (int i = START_POS; i < initialBatchSize; i++) { - stackFrames[i] = new StackFrameInfo(walker); - } - } - - /* - * Returns the next index to fill - */ - @Override - int startIndex() { - return origin; - } - - /** - * Initialize the buffers for VM to fill in the stack frame information. - * The next batch will start at the given startIndex to - * the length of the buffer. - */ - @Override - void resize(int startIndex, int elements) { - // Expand the frame buffer. - // Do not call super.resize that will reuse the filled elements - // in this frame buffer - int size = startIndex+elements; - if (classes.length < size) { - // resize the frame buffer - classes = Arrays.copyOf(classes, size); - stackFrames = Arrays.copyOf(stackFrames, size); - } - for (int i = startIndex; i < size; i++) { - stackFrames[i] = new StackFrameInfo(walker); - } - currentBatchSize = size; - } - - StackTraceElement get(int index) { - return new StackTraceElement(classes[index].getName(), "unknown", null, -1); - } - - /** - * Returns an array of StackTraceElement for all stack frames cached in - * this StackTrace object. - *

- * This method is intended for Throwable::getOurStackTrace use only. - */ - StackTraceElement[] toStackTraceElements() { - int startIndex = START_POS; - for (int i = startIndex; i < classes.length; i++) { - if (classes[i] != null && filterStackWalkImpl(classes[i])) { - startIndex++; - } else { - break; - } - } - - // VM fills in the method name, filename, line number info - StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth); - - StackTraceElement[] stes = new StackTraceElement[depth]; - for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) { - if (isDebug) { - System.err.println("StackFrame: " + i + " " + stackFrames[i]); - } - stes[j] = stackFrames[i].toStackTraceElement(); - } - return stes; - } - } - - private static final int MAX_STACK_FRAMES = 1024; - private static final StackWalker STACKTRACE_WALKER = - StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES)); - - private StackTraceElement[] stes; - static StackTrace dump() { - return new StackTrace(); - } - - static StackTrace dump(Throwable ex) { - return new StackTrace(ex); - } - - private StackTrace() { - this(STACKTRACE_WALKER, DEFAULT_MODE); - } - - /* - * Throwable::fillInStackTrace and of Throwable and subclasses - * are filtered in the VM. - */ - private StackTrace(Throwable ex) { - this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE); // skip Throwable::init frames - if (isDebug) { - System.err.println("dump stack for " + ex.getClass().getName()); - } - } - - StackTrace(StackWalker walker, int mode) { - super(walker, mode, MAX_STACK_FRAMES); - - // snapshot the stack trace - walk(); - } - - @Override - protected Integer consumeFrames() { - // traverse all frames and perform the action on the stack frames, if specified - int n = 0; - while (n < maxDepth && nextFrame() != null) { - n++; - } - return n; - } - - @Override - protected void initFrameBuffer() { - this.frameBuffer = new GrowableBuffer(getNextBatchSize()); - } - - // TODO: implement better heuristic - @Override - protected int batchSize(int lastBatchFrameCount) { - // chunk size of VM backtrace is 32 - return lastBatchFrameCount == 0 ? 32 : 32; - } - - /** - * Returns an array of StackTraceElement for all stack frames cached in - * this StackTrace object. - *

- * This method is intended for Throwable::getOurStackTrace use only. - */ - synchronized StackTraceElement[] getStackTraceElements() { - if (stes == null) { - stes = ((GrowableBuffer) frameBuffer).toStackTraceElements(); - // release the frameBuffer memory - frameBuffer = null; - } - return stes; - } - - /* - * Prints stack trace to the given PrintStream. - * - * Further implementation could skip creating StackTraceElement objects - * print directly to the PrintStream. - */ - void printStackTrace(PrintStream s) { - StackTraceElement[] stes = getStackTraceElements(); - synchronized (s) { - s.println("Stack trace"); - for (StackTraceElement traceElement : stes) - s.println("\tat " + traceElement); - } - } - } - - static class LiveStackInfoTraverser extends StackFrameTraverser { + static final class LiveStackInfoTraverser extends StackFrameTraverser { static { stackWalkImplClasses.add(LiveStackInfoTraverser.class); } // VM will fill in all method info and live stack info directly in StackFrameInfo - class Buffer extends FrameBuffer { - Buffer(int initialBatchSize) { + final class LiveStackFrameBuffer extends FrameBuffer { + private LiveStackFrameInfo[] stackFrames; + LiveStackFrameBuffer(int initialBatchSize) { super(initialBatchSize); - this.stackFrames = new StackFrame[initialBatchSize]; + this.stackFrames = new LiveStackFrameInfo[initialBatchSize]; for (int i = START_POS; i < initialBatchSize; i++) { stackFrames[i] = new LiveStackFrameInfo(walker); } } @Override - void resize(int startIndex, int elements) { - super.resize(startIndex, elements); - int size = startIndex + elements; + LiveStackFrameInfo[] frames() { + return stackFrames; + } + @Override + void resize(int startIndex, int elements) { + if (!isActive()) { + throw new IllegalStateException("inactive frame buffer can't be resized"); + } + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; + + int size = startIndex + elements; if (stackFrames.length < size) { - this.stackFrames = new StackFrame[size]; + LiveStackFrameInfo[] newFrames = new LiveStackFrameInfo[size]; + // copy initial magic... + System.arraycopy(stackFrames, 0, newFrames, 0, startIndex); + stackFrames = newFrames; } for (int i = startIndex(); i < size; i++) { stackFrames[i] = new LiveStackFrameInfo(walker); } + + currentBatchSize = size; } @Override - StackFrame nextStackFrame() { + LiveStackFrameInfo nextStackFrame() { if (isEmpty()) { throw new NoSuchElementException("origin=" + origin + " fence=" + fence); } - StackFrame frame = stackFrames[origin]; + LiveStackFrameInfo frame = stackFrames[origin]; origin++; return frame; } + + @Override + final Class at(int index) { + return stackFrames[index].declaringClass; + } } LiveStackInfoTraverser(StackWalker walker, @@ -1050,7 +771,183 @@ final class StackStreamFactory { @Override protected void initFrameBuffer() { - this.frameBuffer = new Buffer(getNextBatchSize()); + this.frameBuffer = new LiveStackFrameBuffer(getNextBatchSize()); + } + } + + /* + * Frame buffer + * + * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer. + */ + static abstract class FrameBuffer { + static final int START_POS = 2; // 0th and 1st elements are reserved + + // buffers for VM to fill stack frame info + int currentBatchSize; // current batch size + int origin; // index to the current traversed stack frame + int fence; // index to the last frame in the current batch + + FrameBuffer(int initialBatchSize) { + if (initialBatchSize < MIN_BATCH_SIZE) { + throw new IllegalArgumentException(initialBatchSize + + " < minimum batch size: " + MIN_BATCH_SIZE); + } + this.origin = START_POS; + this.fence = 0; + this.currentBatchSize = initialBatchSize; + } + + /** + * Returns an array of frames that may be used to store frame objects + * when walking the stack. + * + * May be an array of {@code Class} if the {@code AbstractStackWalker} + * mode is {@link #FILL_CLASS_REFS_ONLY}, or an array of + * {@link StackFrameInfo} (or derivative) array otherwise. + * + * @return An array of frames that may be used to store frame objects + * when walking the stack. Must not be null. + */ + abstract F[] frames(); // must not return null + + /** + * Resizes the buffers for VM to fill in the next batch of stack frames. + * The next batch will start at the given startIndex with the maximum number + * of elements. + * + *

Subclass may override this method to manage the allocated buffers. + * + * @param startIndex the start index for the first frame of the next batch to fill in. + * @param elements the number of elements for the next batch to fill in. + * + */ + abstract void resize(int startIndex, int elements); + + /** + * Return the class at the given position in the current batch. + * @param index the position of the frame. + * @return the class at the given position in the current batch. + */ + abstract Class at(int index); + + // ------ subclass may override the following methods ------- + + /* + * Returns the start index for this frame buffer is refilled. + * + * This implementation reuses the allocated buffer for the next batch + * of stack frames. For subclass to retain the fetched stack frames, + * it should override this method to return the index at which the frame + * should be filled in for the next batch. + */ + int startIndex() { + return START_POS; + } + + /** + * Returns next StackFrame object in the current batch of stack frames + */ + F nextStackFrame() { + throw new InternalError("should not reach here"); + } + + // ------ FrameBuffer implementation ------ + + final int curBatchFrameCount() { + return currentBatchSize-START_POS; + } + + /* + * Tests if this frame buffer is empty. All frames are fetched. + */ + final boolean isEmpty() { + return origin >= fence || (origin == START_POS && fence == 0); + } + + /* + * Freezes this frame buffer. The stack stream source is done fetching. + */ + final void freeze() { + origin = 0; + fence = 0; + } + + /* + * Tests if this frame buffer is active. It is inactive when + * it is done for traversal. All stack frames have been traversed. + */ + final boolean isActive() { + return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize); + } + + /** + * Gets the class at the current frame and move to the next frame. + */ + final Class next() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + Class c = at(origin); + origin++; + if (isDebug) { + int index = origin-1; + System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index, + Objects.toString(c), index, fence); + } + return c; + } + + /** + * Gets the class at the current frame. + */ + final Class get() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + return at(origin); + } + + /* + * Returns the index of the current frame. + */ + final int getIndex() { + return origin; + } + + /* + * Set the start and end index of a new batch of stack frames that have + * been filled in this frame buffer. + */ + final void setBatch(int depth, int startIndex, int endIndex) { + if (startIndex <= 0 || endIndex <= 0) + throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex); + + this.origin = startIndex; + this.fence = endIndex; + if (depth == 0 && fence > 0) { + // filter the frames due to the stack stream implementation + for (int i = START_POS; i < fence; i++) { + Class c = at(i); + if (isDebug) System.err.format(" frame %d: %s%n", i, c); + if (filterStackWalkImpl(c)) { + origin++; + } else { + break; + } + } + } + } + + /* + * Checks if the origin is the expected start index. + */ + final void check(int skipFrames) { + int index = skipFrames + START_POS; + if (origin != index) { + // stack walk must continue with the previous frame depth + throw new IllegalStateException("origin " + origin + " != " + index); + } } } diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index eb47a05427d..39afad9795f 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -1388,7 +1388,7 @@ class Thread implements Runnable { * This method is used only for debugging. */ public static void dumpStack() { - StackStreamFactory.makeStackTrace().printStackTrace(System.err); + new Exception("Stack trace").printStackTrace(); } /** @@ -1610,8 +1610,7 @@ class Thread implements Runnable { } return stackTrace; } else { - // Don't need JVM help for current thread - return StackStreamFactory.makeStackTrace().getStackTraceElements(); + return (new Exception()).getStackTrace(); } } diff --git a/jdk/src/java.base/share/classes/java/lang/Throwable.java b/jdk/src/java.base/share/classes/java/lang/Throwable.java index 72a3455e637..a609719c9cd 100644 --- a/jdk/src/java.base/share/classes/java/lang/Throwable.java +++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java @@ -785,11 +785,7 @@ public class Throwable implements Serializable { public synchronized Throwable fillInStackTrace() { if (stackTrace != null || backtrace != null /* Out of protocol state */ ) { - if (backtrace == null && StackStreamFactory.useStackTrace(this)) { - backtrace = StackStreamFactory.makeStackTrace(this); - } else { - fillInStackTrace(0); - } + fillInStackTrace(0); stackTrace = UNASSIGNED_STACK; } return this; @@ -830,15 +826,11 @@ public class Throwable implements Serializable { // backtrace if this is the first call to this method if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null) /* Out of protocol state */) { - if (backtrace instanceof StackStreamFactory.StackTrace) { - stackTrace = ((StackStreamFactory.StackTrace)backtrace).getStackTraceElements(); - } else { - stackTrace = new StackTraceElement[depth]; - for (int i = 0; i < depth; i++) { - stackTrace[i] = new StackTraceElement(); - } - getStackTraceElements(stackTrace); + stackTrace = new StackTraceElement[depth]; + for (int i = 0; i < depth; i++) { + stackTrace[i] = new StackTraceElement(); } + getStackTraceElements(stackTrace); } else if (stackTrace == null) { return UNASSIGNED_STACK; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index da91db90da3..5945bcc1f85 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -1132,6 +1132,10 @@ import java.util.Objects; public Object newMemberName() { return new MemberName(); } + public String getName(Object mname) { + MemberName memberName = (MemberName)mname; + return memberName.getName(); + } }); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java index 776c24dc95a..1a4aba5d79b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java @@ -30,4 +30,9 @@ public interface JavaLangInvokeAccess { * Create a new MemberName instance */ Object newMemberName(); + + /** + * Returns the name for the given MemberName + */ + String getName(Object mname); } diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h index c5fc7e91178..2011e58352a 100644 --- a/jdk/src/java.base/share/native/include/jvm.h +++ b/jdk/src/java.base/share/native/include/jvm.h @@ -179,7 +179,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements) */ enum { JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2, - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10, JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20, JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100 }; @@ -187,23 +186,15 @@ enum { JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT jint JNICALL JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT void JNICALL -JVM_FillStackFrames(JNIEnv* env, jclass cls, - jint start_index, - jobjectArray stackFrames, - jint from_index, jint toIndex); - -JNIEXPORT void JNICALL -JVM_SetMethodInfo(JNIEnv* env, jobject frame); +JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); JNIEXPORT jobjectArray JNICALL JVM_GetVmArguments(JNIEnv *env); diff --git a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c index f7930a45924..41c021a2027 100644 --- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c +++ b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c @@ -38,22 +38,10 @@ /* * Class: java_lang_StackFrameInfo - * Method: fillInStackFrames - * Signature: (I[Ljava/lang/Object;[Ljava/lang/Object;II)V + * Method: toStackTraceElement0 + * Signature: (Ljava/lang/StackTraceElement;)V */ -JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_fillInStackFrames - (JNIEnv *env, jclass dummy, jint startIndex, - jobjectArray stackFrames, jint fromIndex, jint toIndex) { - JVM_FillStackFrames(env, dummy, startIndex, - stackFrames, fromIndex, toIndex); -} - -/* - * Class: java_lang_StackFrameInfo - * Method: setMethodInfo - * Signature: (Ljava/lang/Class;)V - */ -JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_setMethodInfo - (JNIEnv *env, jobject stackframeinfo) { - JVM_SetMethodInfo(env, stackframeinfo); +JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0 + (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) { + JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo); } diff --git a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c index c23e9d04918..099b09b3cc6 100644 --- a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c +++ b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c @@ -45,7 +45,6 @@ JNIEXPORT jboolean JNICALL Java_java_lang_StackStreamFactory_checkStackWalkModes (JNIEnv *env, jclass dummy) { return JVM_STACKWALK_FILL_CLASS_REFS_ONLY == java_lang_StackStreamFactory_FILL_CLASS_REFS_ONLY && - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE == java_lang_StackStreamFactory_FILTER_FILL_IN_STACKTRACE && JVM_STACKWALK_SHOW_HIDDEN_FRAMES == java_lang_StackStreamFactory_SHOW_HIDDEN_FRAMES && JVM_STACKWALK_FILL_LIVE_STACK_FRAMES == java_lang_StackStreamFactory_FILL_LIVE_STACK_FRAMES; } @@ -53,26 +52,26 @@ JNIEXPORT jboolean JNICALL Java_java_lang_StackStreamFactory_checkStackWalkModes /* * Class: java_lang_StackStreamFactory_AbstractStackWalker * Method: callStackWalk - * Signature: (JIII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)Ljava/lang/Object; + * Signature: (JIII[Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk (JNIEnv *env, jobject stackstream, jlong mode, jint skipFrames, jint batchSize, jint startIndex, - jobjectArray classes, jobjectArray frames) + jobjectArray frames) { return JVM_CallStackWalk(env, stackstream, mode, skipFrames, batchSize, - startIndex, classes, frames); + startIndex, frames); } /* * Class: java_lang_StackStreamFactory_AbstractStackWalker * Method: fetchStackFrames - * Signature: (JJII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)I + * Signature: (JJII[Ljava/lang/Object;)I */ JNIEXPORT jint JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames (JNIEnv *env, jobject stackstream, jlong mode, jlong anchor, jint batchSize, jint startIndex, - jobjectArray classes, jobjectArray frames) + jobjectArray frames) { return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize, - startIndex, classes, frames); + startIndex, frames); } diff --git a/jdk/test/java/lang/StackWalker/DumpStackTest.java b/jdk/test/java/lang/StackWalker/DumpStackTest.java index 667e325a8f0..2aa97d7c93e 100644 --- a/jdk/test/java/lang/StackWalker/DumpStackTest.java +++ b/jdk/test/java/lang/StackWalker/DumpStackTest.java @@ -28,9 +28,6 @@ * This test should also been run against jdk9 successfully except of * VM option MemberNameInStackFrame. * @run main/othervm DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=false DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=true -XX:-MemberNameInStackFrame DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=true -XX:+MemberNameInStackFrame DumpStackTest */ import java.lang.invoke.MethodHandle; diff --git a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java index 53a3f70c52a..8276d721087 100644 --- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java +++ b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java @@ -25,8 +25,7 @@ * @test * @bug 8140450 * @summary Basic test for StackWalker.getCallerClass() - * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest - * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest + * @run main/othervm GetCallerClassTest * @run main/othervm GetCallerClassTest sm */ diff --git a/jdk/test/java/lang/StackWalker/StackWalkTest.java b/jdk/test/java/lang/StackWalker/StackWalkTest.java index 7bbcc6150f8..5c4782fb46a 100644 --- a/jdk/test/java/lang/StackWalker/StackWalkTest.java +++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java @@ -44,10 +44,6 @@ import jdk.testlibrary.RandomFactory; * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest * @run main/othervm StackWalkTest -random:50 * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest -random:50 - * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50 - * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50 - * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50 - * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50 * @author danielfuchs, bchristi * @key randomness */ diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java index b5f8653bc1b..d9cfcf6aba5 100644 --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java @@ -40,8 +40,7 @@ import static java.lang.StackWalker.Option.*; * @summary Verify stack trace information obtained with respect to StackWalker * options, when the stack contains lambdas, method handle invoke * virtual calls, and reflection. - * @run main/othervm -XX:-MemberNameInStackFrame VerifyStackTrace - * @run main/othervm -XX:+MemberNameInStackFrame VerifyStackTrace + * @run main/othervm VerifyStackTrace * @run main/othervm/java.security.policy=stackwalk.policy VerifyStackTrace * @author danielfuchs */ From c83f454c576ec65c108e24ffc9b05f59491cc0b8 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 11 Apr 2016 21:07:34 +0300 Subject: [PATCH 047/167] 6832045: DefaultSynthStyle.{getStateInfo,getMatchCount) should use Integer.bitCount Reviewed-by: alexsch, twisti --- .../javax/swing/plaf/nimbus/NimbusStyle.java | 13 ++------- .../swing/plaf/synth/DefaultSynthStyle.java | 28 ++----------------- 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java index 7fdbe384f57..ef49aab21a4 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -995,16 +995,7 @@ public final class NimbusStyle extends SynthStyle { // StateInfo match, otherwise a StateInfo with // SELECTED | ENABLED would match ENABLED, which we // don't want. - - // This comes from BigInteger.bitCnt - int bitCount = oState; - bitCount -= (0xaaaaaaaa & bitCount) >>> 1; - bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & - 0x33333333); - bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; - bitCount += bitCount >>> 8; - bitCount += bitCount >>> 16; - bitCount = bitCount & 0xff; + int bitCount = Integer.bitCount(oState); if (bitCount > bestCount) { bestIndex = counter; bestCount = bitCount; diff --git a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java index 8e4c2159679..587aceb454f 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -645,16 +645,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { // StateInfo match, otherwise a StateInfo with // SELECTED | ENABLED would match ENABLED, which we // don't want. - - // This comes from BigInteger.bitCnt - int bitCount = oState; - bitCount -= (0xaaaaaaaa & bitCount) >>> 1; - bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & - 0x33333333); - bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; - bitCount += bitCount >>> 8; - bitCount += bitCount >>> 16; - bitCount = bitCount & 0xff; + int bitCount = Integer.bitCount(oState); if (bitCount > bestCount) { bestIndex = counter; bestCount = bitCount; @@ -882,21 +873,6 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { return state; } - /** - * Returns the number of states that are similar between the - * ComponentState this StateInfo represents and val. - */ - private int getMatchCount(int val) { - // This comes from BigInteger.bitCnt - val &= state; - val -= (0xaaaaaaaa & val) >>> 1; - val = (val & 0x33333333) + ((val >>> 2) & 0x33333333); - val = val + (val >>> 4) & 0x0f0f0f0f; - val += val >>> 8; - val += val >>> 16; - return val & 0xff; - } - /** * Creates and returns a copy of this StateInfo. * From 9a51f0b1eb070de1b16dcc6a19c2149a778bd807 Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Mon, 11 Apr 2016 21:41:43 -0500 Subject: [PATCH 048/167] 8150056: Remove package access restriction of com.sun.java.accessibility.util.internal Remove use of Class.forName; remove package access check from getAccessible Reviewed-by: prr, asmotrak, ahgross --- .../java/accessibility/util/Translator.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java index 224b5375283..bb762ad0b42 100644 --- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java +++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,11 @@ package com.sun.java.accessibility.util; -import java.lang.*; +import com.sun.java.accessibility.util.internal.*; import java.beans.*; import java.util.*; import java.awt.*; import java.awt.event.*; -import java.awt.image.*; -import java.security.AccessControlException; // Do not import Swing classes. This module is intended to work // with both Swing and AWT. // import javax.swing.*; @@ -77,12 +75,26 @@ public class Translator extends AccessibleContext if (c == null) { return null; } - try { - t = Class.forName("com.sun.java.accessibility.util.internal." - + c.getSimpleName() - + "Translator"); + switch (c.getSimpleName()) { + case "Button": + t = ButtonTranslator.class; + break; + case "Checkbox": + t = CheckboxTranslator.class; + break; + case "Label": + t = LabelTranslator.class; + break; + case "List": + t = ListTranslator.class; + break; + case "TextComponent": + t = TextComponentTranslator.class; + break; + } + if (t != null) { return t; - } catch (Exception e) { + } else { return getTranslatorClass(c.getSuperclass()); } } @@ -106,10 +118,6 @@ public class Translator extends AccessibleContext if (o instanceof Accessible) { a = (Accessible)o; } else { - // About to "newInstance" an object of a class of a restricted package - // so ensure the caller is allowed access to that package. - String pkg = "com.sun.java.accessibility.util.internal"; - System.getSecurityManager().checkPackageAccess(pkg); Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { From a64d3028c346b5ae1b8c0eba04f18bc6367173b3 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 12 Apr 2016 00:43:57 -0700 Subject: [PATCH 049/167] 8153902: remove com/sun/jdi/InterfaceMethodsTest.java, com/sun/jdi/InvokeTest.java from ProblemList Enable the jdi tests again Reviewed-by: sundar --- jdk/test/ProblemList.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index cec532e0634..11e567fc1fa 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -333,10 +333,6 @@ com/sun/jdi/CatchPatternTest.sh 8068645 generic- com/sun/jdi/GetLocalVariables4Test.sh 8067354 windows-all -com/sun/jdi/InterfaceMethodsTest.java 8152586 generic-all - -com/sun/jdi/InvokeTest.java 8152586 generic-all - ############################################################################ # jdk_util From a3bb2ad45267d514411793d5bef9e928cece907a Mon Sep 17 00:00:00 2001 From: Ambarish Rapte Date: Tue, 12 Apr 2016 14:40:58 +0530 Subject: [PATCH 050/167] 6191390: Action Event triggered by list does not reflect the modifiers properly on win32 Reviewed-by: serb, psadhukhan --- .../classes/sun/awt/X11/XBaseMenuWindow.java | 4 +- .../classes/sun/awt/X11/XMenuItemPeer.java | 4 +- .../native/libawt/windows/awt_Button.cpp | 2 +- .../native/libawt/windows/awt_Component.cpp | 22 +++ .../native/libawt/windows/awt_Component.h | 1 + .../native/libawt/windows/awt_List.cpp | 2 +- .../native/libawt/windows/awt_MenuItem.cpp | 2 +- .../native/libawt/windows/awt_TrayIcon.cpp | 6 +- .../ActionEventTest/ActionEventTest.java | 109 +++++++++++++++ .../List/ActionEventTest/ActionEventTest.java | 100 +++++++++++++ .../ActionEventTest/ActionEventTest.java | 104 ++++++++++++++ .../ActionEventTest/ActionEventTest.java | 132 ++++++++++++++++++ 12 files changed, 478 insertions(+), 10 deletions(-) create mode 100644 jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java create mode 100644 jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java create mode 100644 jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java create mode 100644 jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java index 85481f55c46..bb74478d299 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java @@ -1087,7 +1087,7 @@ public abstract class XBaseMenuWindow extends XWindow { } } else { //Invoke action event - item.action(mouseEvent.getWhen()); + item.action(mouseEvent.getWhen(), mouseEvent.getModifiers()); ungrabInput(); } } else { @@ -1200,7 +1200,7 @@ public abstract class XBaseMenuWindow extends XWindow { if (citem instanceof XMenuPeer) { cwnd.selectItem(citem, true); } else if (citem != null) { - citem.action(event.getWhen()); + citem.action(event.getWhen(), event.getModifiers()); ungrabInput(); } break; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java index aa1c85d7908..d4e578961be 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java @@ -323,11 +323,11 @@ public class XMenuItemPeer implements MenuItemPeer { * on menu item. * @param when the timestamp of action event */ - void action(long when) { + void action(long when, int modifiers) { if (!isSeparator() && isTargetItemEnabled()) { XWindow.postEventStatic(new ActionEvent(target, ActionEvent.ACTION_PERFORMED, getTargetActionCommand(), when, - 0)); + modifiers)); } } /************************************************ diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp index f0550a9aa5d..e76582bf363 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp @@ -187,7 +187,7 @@ void AwtButton::NotifyListeners() { DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } MsgRouting diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index d5224df0b62..746b1114488 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -2587,6 +2588,27 @@ jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags) return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; } +/* Returns Java ActionEvent modifieres. + * When creating ActionEvent, modifiers provided by ActionEvent + * class should be set. + */ +jint +AwtComponent::GetActionModifiers() +{ + jint modifiers = GetJavaModifiers(); + + if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_CTRL_MASK; + } + if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_SHIFT_MASK; + } + if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_ALT_MASK; + } + return modifiers; +} + /* Returns Java extended InputEvent modifieres. * Since ::GetKeyState returns current state and Java modifiers represent * state before event, modifier on changed key are inverted. diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 83c6d8b8a4e..135ac39b874 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -438,6 +438,7 @@ public: static void InitDynamicKeyMapTable(); static void BuildDynamicKeyMapTable(); static jint GetJavaModifiers(); + static jint GetActionModifiers(); static jint GetButton(int mouseButton); static UINT GetButtonMK(int mouseButton); static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp index 39016b9ab59..4c32a472996 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp @@ -536,7 +536,7 @@ AwtList::WmNotify(UINT notifyCode) else if (notifyCode == LBN_DBLCLK) { DoCallback("handleAction", "(IJI)V", nCurrentSelection, ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } } } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp index ba0488187c5..80fc977e00d 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp @@ -667,7 +667,7 @@ void AwtMenuItem::DoCommand() DoCallback("handleAction", "(Z)V", ((nState & MF_CHECKED) == 0)); } else { DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp index ef376f31a3b..56280a583ac 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp @@ -409,7 +409,7 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } return mrConsume; } @@ -425,7 +425,7 @@ MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } lastKeySelectTime = now; @@ -442,7 +442,7 @@ MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } return mrConsume; } diff --git a/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java new file mode 100644 index 00000000000..9c6317d9a7d --- /dev/null +++ b/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main/manual ActionEventTest + */ + +import java.awt.AWTException; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Button; +import java.awt.TextArea; +import java.awt.Robot; +import java.awt.Point; +import java.awt.event.InputEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +public class ActionEventTest extends Frame { + Button button; + Robot robot; + TextArea instructions; + public static boolean isProgInterruption = false; + static Thread mainThread = null; + static int sleepTime = 300000; + + public ActionEventTest() { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + + button = new Button("ClickMe"); + button.setEnabled(true); + + instructions = new TextArea(10, 50); + instructions.setText( + " This is a manual test\n" + + " Keep the Alt, Shift & Ctrl Keys pressed &\n" + + " Click 'ClickMe' button with left mouse button\n" + + " Test exits automatically after mouse click."); + + add(button); + add(instructions); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + isProgInterruption = true; + mainThread.interrupt(); + if ((md & expectedMask) != expectedMask) { + throw new RuntimeException("Action Event modifiers" + + " are not set correctly."); + } + } + }); + } + + public static void main(String args[]) throws Exception { + mainThread = Thread.currentThread(); + ActionEventTest test = new ActionEventTest(); + try { + mainThread.sleep(sleepTime); + } catch (InterruptedException e) { + if (!isProgInterruption) { + throw e; + } + } + test.dispose(); + if (!isProgInterruption) { + throw new RuntimeException("Timed out after " + sleepTime / 1000 + + " seconds"); + } + } +} diff --git a/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java new file mode 100644 index 00000000000..f1cd8e32a46 --- /dev/null +++ b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main ActionEventTest + */ + +import java.awt.AWTException; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +public class ActionEventTest extends Frame { + List list; + Robot robot; + + public ActionEventTest() { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + + list = new List(1, false); + list.add("0"); + add(list); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + } + + void performTest() { + list.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + if ((md & expectedMask) != expectedMask) { + + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + dispose(); + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + + list.select(0); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + // Press Enter on list item, to generate action event. + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + } + + public static void main(String args[]) { + ActionEventTest test = new ActionEventTest(); + test.performTest(); + test.dispose(); + } +} diff --git a/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java new file mode 100644 index 00000000000..6af94798e31 --- /dev/null +++ b/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main/manual ActionEventTest + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public final class ActionEventTest extends Frame { + + MenuBar menuBar; + TextArea instructions; + public static boolean isProgInterruption = false; + static Thread mainThread = null; + static int sleepTime = 300000; + + public ActionEventTest() { + menuBar = new MenuBar(); + Menu menu = new Menu("Menu1"); + MenuItem menuItem = new MenuItem("MenuItem"); + + menuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + System.out.println("actionPerformed"); + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + isProgInterruption = true; + mainThread.interrupt(); + if ((md & expectedMask) != expectedMask) { + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + menu.add(menuItem); + menuBar.add(menu); + setMenuBar(menuBar); + + instructions = new TextArea(10, 50); + instructions.setText( + " This is a manual test\n" + + " Keep the Alt, Shift & Ctrl Keys pressed while doing next steps\n" + + " Click 'Menu1' Menu from the Menu Bar\n" + + " It will show 'MenuItem'\n" + + " Left mouse Click the 'MenuItem'\n" + + " Test exits automatically after mouse click."); + add(instructions); + + setSize(400, 400); + setVisible(true); + validate(); + } + + + public static void main(final String[] args) throws Exception { + mainThread = Thread.currentThread(); + ActionEventTest test = new ActionEventTest(); + try { + mainThread.sleep(sleepTime); + } catch (InterruptedException e) { + if (!isProgInterruption) { + throw e; + } + } + test.dispose(); + if (!isProgInterruption) { + throw new RuntimeException("Timed out after " + sleepTime / 1000 + + " seconds"); + } + } +} diff --git a/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java new file mode 100644 index 00000000000..7a5f87a38f3 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @library ../../../../lib/testlibrary ../ + * @build ExtendedRobot SystemTrayIconHelper + */ + +import java.awt.Image; +import java.awt.TrayIcon; +import java.awt.SystemTray; +import java.awt.Robot; +import java.awt.EventQueue; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; + +public class ActionEventTest { + + Image image; + TrayIcon icon; + Robot robot; + + public static void main(String[] args) throws Exception { + if (!SystemTray.isSupported()) { + System.out.println("SystemTray not supported on the platform." + + " Marking the test passed."); + } else { + if (System.getProperty("os.name").toLowerCase().startsWith("win")) { + System.err.println( + "Test can fail on Windows platform\n"+ + "On Windows 7, by default icon hides behind icon pool\n" + + "Due to which test might fail\n" + + "Set \"Right mouse click\" -> " + + "\"Customize notification icons\" -> \"Always show " + + "all icons and notifications on the taskbar\" true " + + "to avoid this problem.\nOR change behavior only for " + + "Java SE tray icon and rerun test."); + } + + ActionEventTest test = new ActionEventTest(); + test.doTest(); + test.clear(); + } + } + + public ActionEventTest() throws Exception { + robot = new Robot(); + EventQueue.invokeAndWait(this::initializeGUI); + } + + private void initializeGUI() { + + icon = new TrayIcon( + new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB), "ti"); + icon.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + if ((md & expectedMask) != expectedMask) { + clear(); + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + + try { + SystemTray.getSystemTray().add(icon); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void clear() { + SystemTray.getSystemTray().remove(icon); + } + + void doTest() throws Exception { + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + + Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon); + if (iconPosition == null) { + throw new RuntimeException("Unable to find the icon location!"); + } + + robot.mouseMove(iconPosition.x, iconPosition.y); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + robot.waitForIdle(); + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + } +} From 17344961d2026a3567c5e638cd6eef6a4efb9cda Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 13 Apr 2016 12:10:42 +0300 Subject: [PATCH 051/167] 8153856: com/sun/jdi/WatchFramePop.sh fails with exit code 1 Fixed sed expression in a test Reviewed-by: sla --- jdk/test/com/sun/jdi/ShellScaffold.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index ed5f79e58ac..eb7e6b45351 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -924,7 +924,7 @@ dojstack() # If jstack exists, so will jps # Show stack traces of jdb and debuggee as a possible debugging aid. jdbCmd=`$jdk/bin/jps -v | $grep $jdbKeyword` - realJdbPid=`echo "$jdbCmd" | sed -e 's@ TTY.*@@'` + realJdbPid=`echo "$jdbCmd" | sed -e 's@ .*@@'` if [ ! -z "$realJdbPid" ] ; then echo "-- jdb process info ----------------------" >&2 echo " $jdbCmd" >&2 From a98a7da445dc5f085a3a530ab7949ea8807e1a42 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 13 Apr 2016 11:13:15 +0200 Subject: [PATCH 052/167] 8154087: Fix AIX and Linux/ppc64le after the integration of the new hotspot build Reviewed-by: erikj, goetz --- jdk/make/lib/Awt2dLibraries.gmk | 7 +++++++ jdk/make/lib/CoreLibraries.gmk | 1 + jdk/make/lib/NioLibraries.gmk | 1 + 3 files changed, 9 insertions(+) diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index d6ba6443bf2..b8941c0b105 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -370,6 +370,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \ $(X_CFLAGS), \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := type-limits pointer-to-int-cast \ deprecated-declarations unused-result maybe-uninitialized format \ format-security int-to-pointer-cast parentheses, \ @@ -582,6 +583,7 @@ ifeq ($(BUILD_HEADLESS), true) $(CUPS_CFLAGS) \ $(X_CFLAGS) \ $(LIBAWT_HEADLESS_CFLAGS), \ + DISABLED_WARNINGS_xlc := 1506-356, \ DISABLED_WARNINGS_gcc := maybe-uninitialized int-to-pointer-cast, \ DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE \ E_EMPTY_TRANSLATION_UNIT, \ @@ -598,6 +600,10 @@ ifeq ($(BUILD_HEADLESS), true) OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \ )) + # AIX warning explanation: + # 1506-356 : (W) Compilation unit is empty. + # This happens during the headless build + $(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT) TARGETS += $(BUILD_LIBAWT_HEADLESS) @@ -695,6 +701,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \ OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \ CFLAGS_windows = -DCC_NOEX, \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \ type-limits missing-field-initializers, \ DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \ diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index bccf46bb824..e4a24e47904 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -146,6 +146,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ $(LIBJAVA_CFLAGS), \ System.c_CFLAGS := $(VERSION_CFLAGS), \ jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := unused-result, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ MAPFILE := $(LIBJAVA_MAPFILE), \ diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk index de2cdea0727..203447c513f 100644 --- a/jdk/make/lib/NioLibraries.gmk +++ b/jdk/make/lib/NioLibraries.gmk @@ -70,6 +70,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \ SRC := $(BUILD_LIBNIO_SRC), \ EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \ OPTIMIZATION := HIGH, \ + WARNINGS_AS_ERRORS_xlc := false, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBNIO_CFLAGS), \ MAPFILE := $(BUILD_LIBNIO_MAPFILE), \ From c536913c218e611cc81f22e92e980ca988414113 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 18 Apr 2016 10:57:11 -0700 Subject: [PATCH 053/167] 8154403: JRT filesystem loaded by JDK8 with URLClassLoader is not closable since JDK-8147460 Reviewed-by: alanb --- .../classes/jdk/internal/jrtfs/JrtFileSystemProvider.java | 4 ++-- jdk/test/jdk/internal/jrtfs/WithSecurityManager.java | 3 ++- jdk/test/jdk/internal/jrtfs/remote/Main.java | 6 ++++-- .../jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java | 4 +--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java index 19edf480961..746d61a273c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java @@ -101,10 +101,10 @@ public final class JrtFileSystemProvider extends FileSystemProvider { @Override public FileSystem newFileSystem(URI uri, Map env) throws IOException { + Objects.requireNonNull(env); checkPermission(); checkUri(uri); - - if (env != null && env.containsKey("java.home")) { + if (env.containsKey("java.home")) { return newFileSystem((String)env.get("java.home"), uri, env); } else { return new JrtFileSystem(this, env); diff --git a/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java b/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java index f6d111475ef..81336e20299 100644 --- a/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java +++ b/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java @@ -31,6 +31,7 @@ import java.net.URI; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; public class WithSecurityManager { public static void main(String[] args) throws Exception { @@ -61,7 +62,7 @@ public class WithSecurityManager { // check FileSystems.newFileSystem try { - FileSystems.newFileSystem(URI.create("jrt:/"), null); + FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); if (!allow) throw new RuntimeException("access not expected"); } catch (SecurityException se) { if (allow) diff --git a/jdk/test/jdk/internal/jrtfs/remote/Main.java b/jdk/test/jdk/internal/jrtfs/remote/Main.java index 8ef6303526d..9b22c8308d3 100644 --- a/jdk/test/jdk/internal/jrtfs/remote/Main.java +++ b/jdk/test/jdk/internal/jrtfs/remote/Main.java @@ -30,6 +30,7 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.stream.Stream; /** @@ -69,11 +70,12 @@ public class Main { private static FileSystem createFsWithURLClassloader(String javaHome) throws IOException{ URL url = Paths.get(javaHome, "jrt-fs.jar").toUri().toURL(); URLClassLoader loader = new URLClassLoader(new URL[] { url }); - return FileSystems.newFileSystem(URI.create("jrt:/"), null, loader); + return FileSystems.newFileSystem(URI.create("jrt:/"), + Collections.emptyMap(), + loader); } private static FileSystem createFsByInstalledProvider() throws IOException { return FileSystems.getFileSystem(URI.create("jrt:/")); } } - diff --git a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java index 2c3d588369f..7ea315ad5d6 100644 --- a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java +++ b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8141609 + * @bug 8141609 8154403 * @summary Verify JDK 8 can use jrt-fs.jar to work with jrt file system. * @run main RemoteRuntimeImageTest */ @@ -63,7 +63,6 @@ public class RemoteRuntimeImageTest { String java = jdk8Path.resolve("bin/java").toAbsolutePath().toString(); String javac = jdk8Path.resolve("bin/javac").toAbsolutePath().toString(); - Files.createDirectories(Paths.get(".", CLASSES_DIR)); String jrtJar = Paths.get(TEST_JAVAHOME, JRTFS_JAR).toAbsolutePath().toString(); @@ -121,4 +120,3 @@ public class RemoteRuntimeImageTest { return version.startsWith("\"1.8"); } } - From 1b0e8a4e73ab119238a4b7507ff55015f1ca5255 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Mon, 18 Apr 2016 19:40:48 +0100 Subject: [PATCH 054/167] 8153353: HPACK implementation Reviewed-by: chegar, rriggs --- .../hpack/BinaryRepresentationWriter.java | 34 + .../hpack/BulkSizeUpdateWriter.java | 78 ++ .../sun/net/httpclient/hpack/Decoder.java | 506 +++++++++++++ .../httpclient/hpack/DecodingCallback.java | 284 ++++++++ .../sun/net/httpclient/hpack/Encoder.java | 429 +++++++++++ .../sun/net/httpclient/hpack/HeaderTable.java | 511 +++++++++++++ .../sun/net/httpclient/hpack/Huffman.java | 676 ++++++++++++++++++ .../sun/net/httpclient/hpack/ISO_8859_1.java | 103 +++ .../hpack/IndexNameValueWriter.java | 101 +++ .../net/httpclient/hpack/IndexedWriter.java | 50 ++ .../net/httpclient/hpack/IntegerReader.java | 142 ++++ .../net/httpclient/hpack/IntegerWriter.java | 117 +++ .../hpack/LiteralNeverIndexedWriter.java | 32 + .../hpack/LiteralWithIndexingWriter.java | 85 +++ .../net/httpclient/hpack/LiteralWriter.java | 32 + .../httpclient/hpack/SizeUpdateWriter.java | 59 ++ .../net/httpclient/hpack/StringReader.java | 111 +++ .../net/httpclient/hpack/StringWriter.java | 126 ++++ .../net/httpclient/hpack/package-info.java | 34 + .../net/httpclient/http2/HpackDriver.java | 40 ++ .../hpack/BinaryPrimitivesTest.java | 347 +++++++++ .../httpclient/hpack/BuffersTestingKit.java | 210 ++++++ .../httpclient/hpack/CircularBufferTest.java | 125 ++++ .../sun/net/httpclient/hpack/DecoderTest.java | 595 +++++++++++++++ .../sun/net/httpclient/hpack/EncoderTest.java | 623 ++++++++++++++++ .../net/httpclient/hpack/HeaderTableTest.java | 375 ++++++++++ .../sun/net/httpclient/hpack/HuffmanTest.java | 623 ++++++++++++++++ .../sun/net/httpclient/hpack/SpecHelper.java | 70 ++ .../sun/net/httpclient/hpack/TestHelper.java | 164 +++++ 29 files changed, 6682 insertions(+) create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java create mode 100644 jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java create mode 100644 jdk/test/java/net/httpclient/http2/HpackDriver.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java new file mode 100644 index 00000000000..de60d58f6ac --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +interface BinaryRepresentationWriter { + + boolean write(HeaderTable table, ByteBuffer destination); + + BinaryRepresentationWriter reset(); +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java new file mode 100644 index 00000000000..1c064f627f5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Iterator; + +import static java.util.Objects.requireNonNull; + +final class BulkSizeUpdateWriter implements BinaryRepresentationWriter { + + private final SizeUpdateWriter writer = new SizeUpdateWriter(); + private Iterator maxSizes; + private boolean writing; + private boolean configured; + + BulkSizeUpdateWriter maxHeaderTableSizes(Iterable sizes) { + if (configured) { + throw new IllegalStateException("Already configured"); + } + requireNonNull(sizes, "sizes"); + maxSizes = sizes.iterator(); + configured = true; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!configured) { + throw new IllegalStateException("Configure first"); + } + while (true) { + if (writing) { + if (!writer.write(table, destination)) { + return false; + } + writing = false; + } else if (maxSizes.hasNext()) { + writing = true; + writer.reset(); + writer.maxHeaderTableSize(maxSizes.next()); + } else { + configured = false; + return true; + } + } + } + + @Override + public BulkSizeUpdateWriter reset() { + maxSizes = null; + writing = false; + configured = false; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java new file mode 100644 index 00000000000..afff906424a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.ProtocolException; +import java.nio.ByteBuffer; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * Decodes headers from their binary representation. + * + *

Typical lifecycle looks like this: + * + *

{@link #Decoder(int) new Decoder} + * ({@link #setMaxCapacity(int) setMaxCapacity}? + * {@link #decode(ByteBuffer, boolean, DecodingCallback) decode})* + * + * @apiNote + * + *

The design intentions behind Decoder were to facilitate flexible and + * incremental style of processing. + * + *

{@code Decoder} does not require a complete header block in a single + * {@code ByteBuffer}. The header block can be spread across many buffers of any + * size and decoded one-by-one the way it makes most sense for the user. This + * way also allows not to limit the size of the header block. + * + *

Headers are delivered to the {@linkplain DecodingCallback callback} as + * soon as they become decoded. Using the callback also gives the user a freedom + * to decide how headers are processed. The callback does not limit the number + * of headers decoded during single decoding operation. + * + * @since 9 + */ +public final class Decoder { + + private static final State[] states = new State[256]; + + static { + // To be able to do a quick lookup, each of 256 possibilities are mapped + // to corresponding states. + // + // We can safely do this since patterns 1, 01, 001, 0001, 0000 are + // Huffman prefixes and therefore are inherently not ambiguous. + // + // I do it mainly for better debugging (to not go each time step by step + // through if...else tree). As for performance win for the decoding, I + // believe is negligible. + for (int i = 0; i < states.length; i++) { + if ((i & 0b1000_0000) == 0b1000_0000) { + states[i] = State.INDEXED; + } else if ((i & 0b1100_0000) == 0b0100_0000) { + states[i] = State.LITERAL_WITH_INDEXING; + } else if ((i & 0b1110_0000) == 0b0010_0000) { + states[i] = State.SIZE_UPDATE; + } else if ((i & 0b1111_0000) == 0b0001_0000) { + states[i] = State.LITERAL_NEVER_INDEXED; + } else if ((i & 0b1111_0000) == 0b0000_0000) { + states[i] = State.LITERAL; + } else { + throw new InternalError(String.valueOf(i)); + } + } + } + + private final HeaderTable table; + + private State state = State.READY; + private final IntegerReader integerReader; + private final StringReader stringReader; + private final StringBuilder name; + private final StringBuilder value; + private int intValue; + private boolean firstValueRead; + private boolean firstValueIndex; + private boolean nameHuffmanEncoded; + private boolean valueHuffmanEncoded; + private int capacity; + + /** + * Constructs a {@code Decoder} with the specified initial capacity of the + * header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + */ + public Decoder(int capacity) { + setMaxCapacity(capacity); + table = new HeaderTable(capacity); + integerReader = new IntegerReader(); + stringReader = new StringReader(); + name = new StringBuilder(512); + value = new StringBuilder(1024); + } + + /** + * Sets a maximum capacity of the header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + */ + public void setMaxCapacity(int capacity) { + if (capacity < 0) { + throw new IllegalArgumentException("capacity >= 0: " + capacity); + } + // FIXME: await capacity update if less than what was prior to it + this.capacity = capacity; + } + + /** + * Decodes a header block from the given buffer to the given callback. + * + *

Suppose a header block is represented by a sequence of {@code + * ByteBuffer}s in the form of {@code Iterator}. And the + * consumer of decoded headers is represented by the callback. Then to + * decode the header block, the following approach might be used: + * + *

{@code
+     * while (buffers.hasNext()) {
+     *     ByteBuffer input = buffers.next();
+     *     decoder.decode(input, callback, !buffers.hasNext());
+     * }
+     * }
+ * + *

The decoder reads as much as possible of the header block from the + * given buffer, starting at the buffer's position, and increments its + * position to reflect the bytes read. The buffer's mark and limit will not + * be modified. + * + *

Once the method is invoked with {@code endOfHeaderBlock == true}, the + * current header block is deemed ended, and inconsistencies, if any, are + * reported immediately by throwing an {@code UncheckedIOException}. + * + *

Each callback method is called only after the implementation has + * processed the corresponding bytes. If the bytes revealed a decoding + * error, the callback method is not called. + * + *

In addition to exceptions thrown directly by the method, any + * exceptions thrown from the {@code callback} will bubble up. + * + * @apiNote The method asks for {@code endOfHeaderBlock} flag instead of + * returning it for two reasons. The first one is that the user of the + * decoder always knows which chunk is the last. The second one is to throw + * the most detailed exception possible, which might be useful for + * diagnosing issues. + * + * @implNote This implementation is not atomic in respect to decoding + * errors. In other words, if the decoding operation has thrown a decoding + * error, the decoder is no longer usable. + * + * @param headerBlock + * the chunk of the header block, may be empty + * @param endOfHeaderBlock + * true if the chunk is the final (or the only one) in the sequence + * + * @param consumer + * the callback + * @throws UncheckedIOException + * in case of a decoding error + * @throws NullPointerException + * if either headerBlock or consumer are null + */ + public void decode(ByteBuffer headerBlock, boolean endOfHeaderBlock, + DecodingCallback consumer) { + requireNonNull(headerBlock, "headerBlock"); + requireNonNull(consumer, "consumer"); + while (headerBlock.hasRemaining()) { + proceed(headerBlock, consumer); + } + if (endOfHeaderBlock && state != State.READY) { + throw new UncheckedIOException( + new ProtocolException("Unexpected end of header block")); + } + } + + private void proceed(ByteBuffer input, DecodingCallback action) { + switch (state) { + case READY: + resumeReady(input); + break; + case INDEXED: + resumeIndexed(input, action); + break; + case LITERAL: + resumeLiteral(input, action); + break; + case LITERAL_WITH_INDEXING: + resumeLiteralWithIndexing(input, action); + break; + case LITERAL_NEVER_INDEXED: + resumeLiteralNeverIndexed(input, action); + break; + case SIZE_UPDATE: + resumeSizeUpdate(input, action); + break; + default: + throw new InternalError( + "Unexpected decoder state: " + String.valueOf(state)); + } + } + + private void resumeReady(ByteBuffer input) { + int b = input.get(input.position()) & 0xff; // absolute read + State s = states[b]; + switch (s) { + case INDEXED: + integerReader.configure(7); + state = State.INDEXED; + firstValueIndex = true; + break; + case LITERAL: + state = State.LITERAL; + firstValueIndex = (b & 0b0000_1111) != 0; + if (firstValueIndex) { + integerReader.configure(4); + } + break; + case LITERAL_WITH_INDEXING: + state = State.LITERAL_WITH_INDEXING; + firstValueIndex = (b & 0b0011_1111) != 0; + if (firstValueIndex) { + integerReader.configure(6); + } + break; + case LITERAL_NEVER_INDEXED: + state = State.LITERAL_NEVER_INDEXED; + firstValueIndex = (b & 0b0000_1111) != 0; + if (firstValueIndex) { + integerReader.configure(4); + } + break; + case SIZE_UPDATE: + integerReader.configure(5); + state = State.SIZE_UPDATE; + firstValueIndex = true; + break; + default: + throw new InternalError(String.valueOf(s)); + } + if (!firstValueIndex) { + input.get(); // advance, next stop: "String Literal" + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 1 | Index (7+) | + // +---+---------------------------+ + // + private void resumeIndexed(ByteBuffer input, DecodingCallback action) { + if (!integerReader.read(input)) { + return; + } + intValue = integerReader.get(); + integerReader.reset(); + try { + HeaderTable.HeaderField f = table.get(intValue); + action.onIndexed(intValue, f.name, f.value); + } finally { + state = State.READY; + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | Index (4+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteral(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + action.onLiteral(intValue, f.name, value, valueHuffmanEncoded); + } else { + action.onLiteral(name, nameHuffmanEncoded, value, valueHuffmanEncoded); + } + } finally { + cleanUpAfterReading(); + } + } + + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | Index (6+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteralWithIndexing(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + // + // 1. (name, value) will be stored in the table as strings + // 2. Most likely the callback will also create strings from them + // ------------------------------------------------------------------------ + // Let's create those string beforehand (and only once!) to benefit everyone + // + String n; + String v = value.toString(); + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + n = f.name; + action.onLiteralWithIndexing(intValue, n, v, valueHuffmanEncoded); + } else { + n = name.toString(); + action.onLiteralWithIndexing(n, nameHuffmanEncoded, v, valueHuffmanEncoded); + } + table.put(n, v); + } catch (IllegalArgumentException | IllegalStateException e) { + throw new UncheckedIOException( + (IOException) new ProtocolException().initCause(e)); + } finally { + cleanUpAfterReading(); + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | Index (4+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteralNeverIndexed(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + action.onLiteralNeverIndexed(intValue, f.name, value, valueHuffmanEncoded); + } else { + action.onLiteralNeverIndexed(name, nameHuffmanEncoded, value, valueHuffmanEncoded); + } + } finally { + cleanUpAfterReading(); + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 1 | Max size (5+) | + // +---+---------------------------+ + // + private void resumeSizeUpdate(ByteBuffer input, DecodingCallback action) { + if (!integerReader.read(input)) { + return; + } + intValue = integerReader.get(); + assert intValue >= 0; + if (intValue > capacity) { + throw new UncheckedIOException(new ProtocolException( + format("Received capacity exceeds expected: " + + "capacity=%s, expected=%s", intValue, capacity))); + } + integerReader.reset(); + try { + action.onSizeUpdate(intValue); + table.setMaxSize(intValue); + } finally { + state = State.READY; + } + } + + private boolean completeReading(ByteBuffer input) { + if (!firstValueRead) { + if (firstValueIndex) { + if (!integerReader.read(input)) { + return false; + } + intValue = integerReader.get(); + integerReader.reset(); + } else { + if (!stringReader.read(input, name)) { + return false; + } + nameHuffmanEncoded = stringReader.isHuffmanEncoded(); + stringReader.reset(); + } + firstValueRead = true; + return false; + } else { + if (!stringReader.read(input, value)) { + return false; + } + } + valueHuffmanEncoded = stringReader.isHuffmanEncoded(); + stringReader.reset(); + return true; + } + + private void cleanUpAfterReading() { + name.setLength(0); + value.setLength(0); + firstValueRead = false; + state = State.READY; + } + + private enum State { + READY, + INDEXED, + LITERAL_NEVER_INDEXED, + LITERAL, + LITERAL_WITH_INDEXING, + SIZE_UPDATE + } + + HeaderTable getTable() { + return table; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java new file mode 100644 index 00000000000..d0d1ce5d5d5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +/** + * Delivers results of the {@link Decoder#decode(ByteBuffer, boolean, + * DecodingCallback) decoding operation}. + * + *

Methods of the callback are never called by a decoder with any of the + * arguments being {@code null}. + * + * @apiNote + * + *

The callback provides methods for all possible binary + * representations. This could be useful for implementing an intermediary, + * logging, debugging, etc. + * + *

The callback is an interface in order to interoperate with lambdas (in + * the most common use case): + *

{@code
+ *     DecodingCallback callback = (name, value) -> System.out.println(name + ", " + value);
+ * }
+ * + *

Names and values are {@link CharSequence}s rather than {@link String}s in + * order to allow users to decide whether or not they need to create objects. A + * {@code CharSequence} might be used in-place, for example, to be appended to + * an {@link Appendable} (e.g. {@link StringBuilder}) and then discarded. + * + *

That said, if a passed {@code CharSequence} needs to outlast the method + * call, it needs to be copied. + * + * @since 9 + */ +@FunctionalInterface +public interface DecodingCallback { + + /** + * A method the more specific methods of the callback forward their calls + * to. + * + * @param name + * header name + * @param value + * header value + */ + void onDecoded(CharSequence name, CharSequence value); + + /** + * A more finer-grained version of {@link #onDecoded(CharSequence, + * CharSequence)} that also reports on value sensitivity. + * + *

Value sensitivity must be considered, for example, when implementing + * an intermediary. A {@code value} is sensitive if it was represented as Literal Header + * Field Never Indexed. + * + *

It is required that intermediaries MUST use the {@linkplain + * Encoder#header(CharSequence, CharSequence, boolean) same representation} + * for encoding this header field in order to protect its value which is not + * to be put at risk by compressing it. + * + * @implSpec + * + *

The default implementation invokes {@code onDecoded(name, value)}. + * + * @param name + * header name + * @param value + * header value + * @param sensitive + * whether or not the value is sensitive + * + * @see #onLiteralNeverIndexed(int, CharSequence, CharSequence, boolean) + * @see #onLiteralNeverIndexed(CharSequence, boolean, CharSequence, boolean) + */ + default void onDecoded(CharSequence name, CharSequence value, + boolean sensitive) { + onDecoded(name, value); + } + + /** + * An Indexed + * Header Field decoded. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + */ + default void onIndexed(int index, CharSequence name, CharSequence value) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field without Indexing decoded, where a {@code name} was + * referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteral(int index, CharSequence name, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field without Indexing decoded, where both a {@code name} and + * a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteral(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field Never Indexed decoded, where a {@code name} + * was referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, true)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralNeverIndexed(int index, CharSequence name, + CharSequence value, + boolean valueHuffman) { + onDecoded(name, value, true); + } + + /** + * A Literal + * Header Field Never Indexed decoded, where both a {@code + * name} and a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, true)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralNeverIndexed(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, true); + } + + /** + * A Literal + * Header Field with Incremental Indexing decoded, where a {@code name} + * was referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralWithIndexing(int index, + CharSequence name, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field with Incremental Indexing decoded, where both a {@code + * name} and a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralWithIndexing(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Dynamic Table + * Size Update decoded. + * + * @implSpec + * + *

The default implementation does nothing. + * + * @param capacity + * new capacity of the header table + */ + default void onSizeUpdate(int capacity) { } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java new file mode 100644 index 00000000000..75ab8653457 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.nio.ReadOnlyBufferException; +import java.util.LinkedList; +import java.util.List; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * Encodes headers to their binary representation. + * + *

Typical lifecycle looks like this: + * + *

{@link #Encoder(int) new Encoder} + * ({@link #setMaxCapacity(int) setMaxCapacity}? + * {@link #encode(ByteBuffer) encode})* + * + *

Suppose headers are represented by {@code Map>}. A + * supplier and a consumer of {@link ByteBuffer}s in forms of {@code + * Supplier} and {@code Consumer} respectively. Then to + * encode headers, the following approach might be used: + * + *

{@code
+ *     for (Map.Entry> h : headers.entrySet()) {
+ *         String name = h.getKey();
+ *         for (String value : h.getValue()) {
+ *             encoder.header(name, value);        // Set up header
+ *             boolean encoded;
+ *             do {
+ *                 ByteBuffer b = buffersSupplier.get();
+ *                 encoded = encoder.encode(b);    // Encode the header
+ *                 buffersConsumer.accept(b);
+ *             } while (!encoded);
+ *         }
+ *     }
+ * }
+ * + *

Though the specification does not define how + * an encoder is to be implemented, a default implementation is provided by the + * method {@link #header(CharSequence, CharSequence, boolean)}. + * + *

To provide a custom encoding implementation, {@code Encoder} has to be + * extended. A subclass then can access methods for encoding using specific + * representations (e.g. {@link #literal(int, CharSequence, boolean) literal}, + * {@link #indexed(int) indexed}, etc.) + * + * @apiNote + * + *

An Encoder provides an incremental way of encoding headers. + * {@link #encode(ByteBuffer)} takes a buffer a returns a boolean indicating + * whether, or not, the buffer was sufficiently sized to hold the + * remaining of the encoded representation. + * + *

This way, there's no need to provide a buffer of a specific size, or to + * resize (and copy) the buffer on demand, when the remaining encoded + * representation will not fit in the buffer's remaining space. Instead, an + * array of existing buffers can be used, prepended with a frame that encloses + * the resulting header block afterwards. + * + *

Splitting the encoding operation into header set up and header encoding, + * separates long lived arguments ({@code name}, {@code value}, {@code + * sensitivity}, etc.) from the short lived ones (e.g. {@code buffer}), + * simplifying each operation itself. + * + * @implNote + * + *

The default implementation does not use dynamic table. It reports to a + * coupled Decoder a size update with the value of {@code 0}, and never changes + * it afterwards. + * + * @since 9 + */ +public class Encoder { + + // TODO: enum: no huffman/smart huffman/always huffman + private static final boolean DEFAULT_HUFFMAN = true; + + private final IndexedWriter indexedWriter = new IndexedWriter(); + private final LiteralWriter literalWriter = new LiteralWriter(); + private final LiteralNeverIndexedWriter literalNeverIndexedWriter + = new LiteralNeverIndexedWriter(); + private final LiteralWithIndexingWriter literalWithIndexingWriter + = new LiteralWithIndexingWriter(); + private final SizeUpdateWriter sizeUpdateWriter = new SizeUpdateWriter(); + private final BulkSizeUpdateWriter bulkSizeUpdateWriter + = new BulkSizeUpdateWriter(); + + private BinaryRepresentationWriter writer; + private final HeaderTable headerTable; + + private boolean encoding; + + private int maxCapacity; + private int currCapacity; + private int lastCapacity; + private long minCapacity; + private boolean capacityUpdate; + private boolean configuredCapacityUpdate; + + /** + * Constructs an {@code Encoder} with the specified maximum capacity of the + * header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param maxCapacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if maxCapacity is negative + */ + public Encoder(int maxCapacity) { + if (maxCapacity < 0) { + throw new IllegalArgumentException("maxCapacity >= 0: " + maxCapacity); + } + // Initial maximum capacity update mechanics + minCapacity = Long.MAX_VALUE; + currCapacity = -1; + setMaxCapacity(maxCapacity); + headerTable = new HeaderTable(lastCapacity); + } + + /** + * Sets up the given header {@code (name, value)}. + * + *

Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, CharSequence value) + throws IllegalStateException { + header(name, value, false); + } + + /** + * Sets up the given header {@code (name, value)} with possibly sensitive + * value. + * + *

Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * @param sensitive + * whether or not the value is sensitive + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence) + * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, CharSequence value, + boolean sensitive) throws IllegalStateException { + // Arguably a good balance between complexity of implementation and + // efficiency of encoding + requireNonNull(name, "name"); + requireNonNull(value, "value"); + HeaderTable t = getHeaderTable(); + int index = t.indexOf(name, value); + if (index > 0) { + indexed(index); + } else if (index < 0) { + if (sensitive) { + literalNeverIndexed(-index, value, DEFAULT_HUFFMAN); + } else { + literal(-index, value, DEFAULT_HUFFMAN); + } + } else { + if (sensitive) { + literalNeverIndexed(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN); + } else { + literal(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN); + } + } + } + + /** + * Sets a maximum capacity of the header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + *

May be called any number of times after or before a complete header + * has been encoded. + * + *

If the encoder decides to change the actual capacity, an update will + * be encoded before a new encoding operation starts. + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + */ + public void setMaxCapacity(int capacity) { + checkEncoding(); + if (capacity < 0) { + throw new IllegalArgumentException("capacity >= 0: " + capacity); + } + int calculated = calculateCapacity(capacity); + if (calculated < 0 || calculated > capacity) { + throw new IllegalArgumentException( + format("0 <= calculated <= capacity: calculated=%s, capacity=%s", + calculated, capacity)); + } + capacityUpdate = true; + // maxCapacity needs to be updated unconditionally, so the encoder + // always has the newest one (in case it decides to update it later + // unsolicitedly) + // Suppose maxCapacity = 4096, and the encoder has decided to use only + // 2048. It later can choose anything else from the region [0, 4096]. + maxCapacity = capacity; + lastCapacity = calculated; + minCapacity = Math.min(minCapacity, lastCapacity); + } + + protected int calculateCapacity(int maxCapacity) { + // Default implementation of the Encoder won't add anything to the + // table, therefore no need for a table space + return 0; + } + + /** + * Encodes the {@linkplain #header(CharSequence, CharSequence) set up} + * header into the given buffer. + * + *

The encoder writes as much as possible of the header's binary + * representation into the given buffer, starting at the buffer's position, + * and increments its position to reflect the bytes written. The buffer's + * mark and limit will not be modified. + * + *

Once the method has returned {@code true}, the current header is + * deemed encoded. A new header may be set up. + * + * @param headerBlock + * the buffer to encode the header into, may be empty + * + * @return {@code true} if the current header has been fully encoded, + * {@code false} otherwise + * + * @throws NullPointerException + * if the buffer is {@code null} + * @throws ReadOnlyBufferException + * if this buffer is read-only + * @throws IllegalStateException + * if there is no set up header + */ + public final boolean encode(ByteBuffer headerBlock) { + if (!encoding) { + throw new IllegalStateException("A header hasn't been set up"); + } + if (!prependWithCapacityUpdate(headerBlock)) { + return false; + } + boolean done = writer.write(headerTable, headerBlock); + if (done) { + writer.reset(); // FIXME: WHY? + encoding = false; + } + return done; + } + + private boolean prependWithCapacityUpdate(ByteBuffer headerBlock) { + if (capacityUpdate) { + if (!configuredCapacityUpdate) { + List sizes = new LinkedList<>(); + if (minCapacity < currCapacity) { + sizes.add((int) minCapacity); + if (minCapacity != lastCapacity) { + sizes.add(lastCapacity); + } + } else if (lastCapacity != currCapacity) { + sizes.add(lastCapacity); + } + bulkSizeUpdateWriter.maxHeaderTableSizes(sizes); + configuredCapacityUpdate = true; + } + boolean done = bulkSizeUpdateWriter.write(headerTable, headerBlock); + if (done) { + minCapacity = lastCapacity; + currCapacity = lastCapacity; + bulkSizeUpdateWriter.reset(); + capacityUpdate = false; + configuredCapacityUpdate = false; + } + return done; + } + return true; + } + + protected final void indexed(int index) throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = indexedWriter.index(index); + } + + protected final void literal(int index, CharSequence value, + boolean useHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalWriter + .index(index).value(value, useHuffman); + } + + protected final void literal(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void literalNeverIndexed(int index, + CharSequence value, + boolean valueHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalNeverIndexedWriter + .index(index).value(value, valueHuffman); + } + + protected final void literalNeverIndexed(CharSequence name, + boolean nameHuffman, + CharSequence value, + boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalNeverIndexedWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void literalWithIndexing(int index, + CharSequence value, + boolean valueHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalWithIndexingWriter + .index(index).value(value, valueHuffman); + } + + protected final void literalWithIndexing(CharSequence name, + boolean nameHuffman, + CharSequence value, + boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalWithIndexingWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void sizeUpdate(int capacity) + throws IllegalArgumentException { + checkEncoding(); + // Ensure subclass follows the contract + if (capacity > this.maxCapacity) { + throw new IllegalArgumentException( + format("capacity <= maxCapacity: capacity=%s, maxCapacity=%s", + capacity, maxCapacity)); + } + writer = sizeUpdateWriter.maxHeaderTableSize(capacity); + } + + protected final int getMaxCapacity() { + return maxCapacity; + } + + protected final HeaderTable getHeaderTable() { + return headerTable; + } + + protected final void checkEncoding() { + if (encoding) { + throw new IllegalStateException( + "Previous encoding operation hasn't finished yet"); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java new file mode 100644 index 00000000000..89820741a32 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +import static java.lang.String.format; + +// +// Header Table combined from two tables: static and dynamic. +// +// There is a single address space for index values. Index-aware methods +// correspond to the table as a whole. Size-aware methods only to the dynamic +// part of it. +// +final class HeaderTable { + + private static final HeaderField[] staticTable = { + null, // To make index 1-based, instead of 0-based + new HeaderField(":authority"), + new HeaderField(":method", "GET"), + new HeaderField(":method", "POST"), + new HeaderField(":path", "/"), + new HeaderField(":path", "/index.html"), + new HeaderField(":scheme", "http"), + new HeaderField(":scheme", "https"), + new HeaderField(":status", "200"), + new HeaderField(":status", "204"), + new HeaderField(":status", "206"), + new HeaderField(":status", "304"), + new HeaderField(":status", "400"), + new HeaderField(":status", "404"), + new HeaderField(":status", "500"), + new HeaderField("accept-charset"), + new HeaderField("accept-encoding", "gzip, deflate"), + new HeaderField("accept-language"), + new HeaderField("accept-ranges"), + new HeaderField("accept"), + new HeaderField("access-control-allow-origin"), + new HeaderField("age"), + new HeaderField("allow"), + new HeaderField("authorization"), + new HeaderField("cache-control"), + new HeaderField("content-disposition"), + new HeaderField("content-encoding"), + new HeaderField("content-language"), + new HeaderField("content-length"), + new HeaderField("content-location"), + new HeaderField("content-range"), + new HeaderField("content-type"), + new HeaderField("cookie"), + new HeaderField("date"), + new HeaderField("etag"), + new HeaderField("expect"), + new HeaderField("expires"), + new HeaderField("from"), + new HeaderField("host"), + new HeaderField("if-match"), + new HeaderField("if-modified-since"), + new HeaderField("if-none-match"), + new HeaderField("if-range"), + new HeaderField("if-unmodified-since"), + new HeaderField("last-modified"), + new HeaderField("link"), + new HeaderField("location"), + new HeaderField("max-forwards"), + new HeaderField("proxy-authenticate"), + new HeaderField("proxy-authorization"), + new HeaderField("range"), + new HeaderField("referer"), + new HeaderField("refresh"), + new HeaderField("retry-after"), + new HeaderField("server"), + new HeaderField("set-cookie"), + new HeaderField("strict-transport-security"), + new HeaderField("transfer-encoding"), + new HeaderField("user-agent"), + new HeaderField("vary"), + new HeaderField("via"), + new HeaderField("www-authenticate") + }; + + private static final int STATIC_TABLE_LENGTH = staticTable.length - 1; + private static final int ENTRY_SIZE = 32; + private static final Map> staticIndexes; + + static { + staticIndexes = new HashMap<>(STATIC_TABLE_LENGTH); + for (int i = 1; i <= STATIC_TABLE_LENGTH; i++) { + HeaderField f = staticTable[i]; + Map values = staticIndexes + .computeIfAbsent(f.name, k -> new LinkedHashMap<>()); + values.put(f.value, i); + } + } + + private final Table dynamicTable = new Table(0); + private int maxSize; + private int size; + + public HeaderTable(int maxSize) { + setMaxSize(maxSize); + } + + // + // The method returns: + // + // * a positive integer i where i (i = [1..Integer.MAX_VALUE]) is an + // index of an entry with a header (n, v), where n.equals(name) && + // v.equals(value) + // + // * a negative integer j where j (j = [-Integer.MAX_VALUE..-1]) is an + // index of an entry with a header (n, v), where n.equals(name) + // + // * 0 if there's no entry e such that e.getName().equals(name) + // + // The rationale behind this design is to allow to pack more useful data + // into a single invocation, facilitating a single pass where possible + // (the idea is the same as in java.util.Arrays.binarySearch(int[], int)). + // + public int indexOf(CharSequence name, CharSequence value) { + // Invoking toString() will possibly allocate Strings for the sake of + // the search, which doesn't feel right. + String n = name.toString(); + String v = value.toString(); + + // 1. Try exact match in the static region + Map values = staticIndexes.get(n); + if (values != null) { + Integer idx = values.get(v); + if (idx != null) { + return idx; + } + } + // 2. Try exact match in the dynamic region + int didx = dynamicTable.indexOf(n, v); + if (didx > 0) { + return STATIC_TABLE_LENGTH + didx; + } else if (didx < 0) { + if (values != null) { + // 3. Return name match from the static region + return -values.values().iterator().next(); // Iterator allocation + } else { + // 4. Return name match from the dynamic region + return -STATIC_TABLE_LENGTH + didx; + } + } else { + if (values != null) { + // 3. Return name match from the static region + return -values.values().iterator().next(); // Iterator allocation + } else { + return 0; + } + } + } + + public int size() { + return size; + } + + public int maxSize() { + return maxSize; + } + + public int length() { + return STATIC_TABLE_LENGTH + dynamicTable.size(); + } + + HeaderField get(int index) { + checkIndex(index); + if (index <= STATIC_TABLE_LENGTH) { + return staticTable[index]; + } else { + return dynamicTable.get(index - STATIC_TABLE_LENGTH); + } + } + + void put(CharSequence name, CharSequence value) { + // Invoking toString() will possibly allocate Strings. But that's + // unavoidable at this stage. If a CharSequence is going to be stored in + // the table, it must not be mutable (e.g. for the sake of hashing). + put(new HeaderField(name.toString(), value.toString())); + } + + private void put(HeaderField h) { + int entrySize = sizeOf(h); + while (entrySize > maxSize - size && size != 0) { + evictEntry(); + } + if (entrySize > maxSize - size) { + return; + } + size += entrySize; + dynamicTable.add(h); + } + + void setMaxSize(int maxSize) { + if (maxSize < 0) { + throw new IllegalArgumentException + ("maxSize >= 0: maxSize=" + maxSize); + } + while (maxSize < size && size != 0) { + evictEntry(); + } + this.maxSize = maxSize; + int upperBound = (maxSize / ENTRY_SIZE) + 1; + this.dynamicTable.setCapacity(upperBound); + } + + HeaderField evictEntry() { + HeaderField f = dynamicTable.remove(); + size -= sizeOf(f); + return f; + } + + @Override + public String toString() { + double used = maxSize == 0 ? 0 : 100 * (((double) size) / maxSize); + return format("entries: %d; used %s/%s (%.1f%%)", dynamicTable.size(), + size, maxSize, used); + } + + int checkIndex(int index) { + if (index < 1 || index > STATIC_TABLE_LENGTH + dynamicTable.size()) { + throw new IllegalArgumentException( + format("1 <= index <= length(): index=%s, length()=%s", + index, length())); + } + return index; + } + + int sizeOf(HeaderField f) { + return f.name.length() + f.value.length() + ENTRY_SIZE; + } + + // + // Diagnostic information in the form used in the RFC 7541 + // + String getStateString() { + if (size == 0) { + return "empty."; + } + + StringBuilder b = new StringBuilder(); + for (int i = 1, size = dynamicTable.size(); i <= size; i++) { + HeaderField e = dynamicTable.get(i); + b.append(format("[%3d] (s = %3d) %s: %s%n", i, + sizeOf(e), e.name, e.value)); + } + b.append(format(" Table size:%4s", this.size)); + return b.toString(); + } + + // Convert to a Value Object (JDK-8046159)? + static final class HeaderField { + + final String name; + final String value; + + public HeaderField(String name) { + this(name, ""); + } + + public HeaderField(String name, String value) { + this.name = name; + this.value = value; + } + + @Override + public String toString() { + return value.isEmpty() ? name : name + ": " + value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HeaderField that = (HeaderField) o; + return name.equals(that.name) && value.equals(that.value); + } + + @Override + public int hashCode() { + return 31 * (name.hashCode()) + value.hashCode(); + } + } + + // + // In order to be able to find an index of an entry with the given contents + // in the dynamic table an effective inverse mapping is needed. Here's a + // simple idea behind such a mapping. + // + // # The problem: + // + // We have a queue with an O(1) lookup by index: + // + // get: index -> x + // + // What we also want is an O(1) reverse lookup: + // + // indexOf: x -> index + // + // # Solution: + // + // Let's store an inverse mapping as a Map. This have a problem + // that when a new element is added to the queue all indexes in the map + // becomes invalid. Namely, each i becomes shifted by 1 to the right: + // + // i -> i + 1 + // + // And the new element is assigned with an index of 1. This would seem to + // require a pass through the map incrementing all indexes (map values) by + // 1, which is O(n). + // + // The good news is we can do much better then this! + // + // Let's create a single field of type long, called 'counter'. Then each + // time a new element 'x' is added to the queue, a value of this field gets + // incremented. Then the resulting value of the 'counter_x' is then put as a + // value under key 'x' to the map: + // + // map.put(x, counter_x) + // + // It gives us a map that maps an element to a value the counter had at the + // time the element had been added. + // + // In order to retrieve an index of any element 'x' in the queue (at any + // given time) we simply need to subtract the value (the snapshot of the + // counter at the time when the 'x' was added) from the current value of the + // counter. This operation basically answers the question: + // + // How many elements ago 'x' was the tail of the queue? + // + // Which is the same as its index in the queue now. Given, of course, it's + // still in the queue. + // + // I'm pretty sure in a real life long overflow will never happen, so it's + // not too practical to add recalibrating code, but a pedantic person might + // want to do so: + // + // if (counter == Long.MAX_VALUE) { + // recalibrate(); + // } + // + // Where 'recalibrate()' goes through the table doing this: + // + // value -= counter + // + // That's given, of course, the size of the table itself is less than + // Long.MAX_VALUE :-) + // + private static final class Table { + + private final Map> map; + private final CircularBuffer buffer; + private long counter = 1; + + Table(int capacity) { + buffer = new CircularBuffer<>(capacity); + map = new HashMap<>(capacity); + } + + void add(HeaderField f) { + buffer.add(f); + Map values = map.computeIfAbsent(f.name, k -> new HashMap<>()); + values.put(f.value, counter++); + } + + HeaderField get(int index) { + return buffer.get(index - 1); + } + + int indexOf(String name, String value) { + Map values = map.get(name); + if (values == null) { + return 0; + } + Long index = values.get(value); + if (index != null) { + return (int) (counter - index); + } else { + assert !values.isEmpty(); + Long any = values.values().iterator().next(); // Iterator allocation + return -(int) (counter - any); + } + } + + HeaderField remove() { + HeaderField f = buffer.remove(); + Map values = map.get(f.name); + Long index = values.remove(f.value); + assert index != null; + if (values.isEmpty()) { + map.remove(f.name); + } + return f; + } + + int size() { + return buffer.size; + } + + public void setCapacity(int capacity) { + buffer.resize(capacity); + } + } + + // head + // v + // [ ][ ][A][B][C][D][ ][ ][ ] + // ^ + // tail + // + // |<- size ->| (4) + // |<------ capacity ------->| (9) + // + static final class CircularBuffer { + + int tail, head, size, capacity; + Object[] elements; + + CircularBuffer(int capacity) { + this.capacity = capacity; + elements = new Object[capacity]; + } + + void add(E elem) { + if (size == capacity) { + throw new IllegalStateException( + format("No room for '%s': capacity=%s", elem, capacity)); + } + elements[head] = elem; + head = (head + 1) % capacity; + size++; + } + + @SuppressWarnings("unchecked") + E remove() { + if (size == 0) { + throw new NoSuchElementException("Empty"); + } + E elem = (E) elements[tail]; + elements[tail] = null; + tail = (tail + 1) % capacity; + size--; + return elem; + } + + @SuppressWarnings("unchecked") + E get(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException( + format("0 <= index <= capacity: index=%s, capacity=%s", + index, capacity)); + } + int idx = (tail + (size - index - 1)) % capacity; + return (E) elements[idx]; + } + + public void resize(int newCapacity) { + if (newCapacity < size) { + throw new IllegalStateException( + format("newCapacity >= size: newCapacity=%s, size=%s", + newCapacity, size)); + } + + Object[] newElements = new Object[newCapacity]; + + if (tail < head || size == 0) { + System.arraycopy(elements, tail, newElements, 0, size); + } else { + System.arraycopy(elements, tail, newElements, 0, elements.length - tail); + System.arraycopy(elements, 0, newElements, elements.length - tail, head); + } + + elements = newElements; + tail = 0; + head = size; + this.capacity = newCapacity; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java new file mode 100644 index 00000000000..9c58cc3acc2 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +import static java.lang.String.format; + +/** + * Huffman coding table. + * + *

Instances of this class are safe for use by multiple threads. + * + * @since 9 + */ +public final class Huffman { + + // TODO: check if reset is done in both reader and writer + + static final class Reader { + + private Node curr; // position in the trie + private int len; // length of the path from the root to 'curr' + private int p; // byte probe + + { + reset(); + } + + public void read(ByteBuffer source, Appendable destination, + boolean isLast) { + read(source, destination, true, isLast); + } + + // Takes 'isLast' rather than returns whether the reading is done or + // not, for more informative exceptions. + void read(ByteBuffer source, Appendable destination, boolean reportEOS, + boolean isLast) { + + Node c = curr; + int l = len; + /* + Since ByteBuffer is itself stateful, its position is + remembered here NOT as a part of Reader's state, + but to set it back in the case of a failure + */ + int pos = source.position(); + + while (source.hasRemaining()) { + int d = source.get(); + for (; p != 0; p >>= 1) { + c = c.getChild(p & d); + l++; + if (c.isLeaf()) { + if (reportEOS && c.isEOSPath) { + throw new IllegalArgumentException("Encountered EOS"); + } + try { + destination.append(c.getChar()); + } catch (RuntimeException | Error e) { + source.position(pos); + throw e; + } catch (IOException e) { + source.position(pos); + throw new UncheckedIOException(e); + } + c = INSTANCE.root; + l = 0; + } + curr = c; + len = l; + } + resetProbe(); + pos++; + } + if (!isLast) { + return; // it's too early to jump to any conclusions, let's wait + } + if (c.isLeaf()) { + return; // it's perfectly ok, no extra padding bits + } + if (c.isEOSPath && len <= 7) { + return; // it's ok, some extra padding bits + } + if (c.isEOSPath) { + throw new IllegalArgumentException( + "Padding is too long (len=" + len + ") " + + "or unexpected end of data"); + } + throw new IllegalArgumentException( + "Not a EOS prefix padding or unexpected end of data"); + } + + public void reset() { + curr = INSTANCE.root; + len = 0; + resetProbe(); + } + + private void resetProbe() { + p = 0x80; + } + } + + static final class Writer { + + private int pos; // position in 'source' + private int avail = 8; // number of least significant bits available in 'curr' + private int curr; // next byte to put to the destination + private int rem; // number of least significant bits in 'code' yet to be processed + private int code; // current code being written + + private CharSequence source; + private int end; + + public Writer from(CharSequence input, int start, int end) { + if (start < 0 || end < 0 || end > input.length() || start > end) { + throw new IndexOutOfBoundsException( + String.format("input.length()=%s, start=%s, end=%s", + input.length(), start, end)); + } + pos = start; + this.end = end; + this.source = input; + return this; + } + + public boolean write(ByteBuffer destination) { + for (; pos < end; pos++) { + if (rem == 0) { + Code desc = INSTANCE.codeOf(source.charAt(pos)); + rem = desc.length; + code = desc.code; + } + while (rem > 0) { + if (rem < avail) { + curr |= (code << (avail - rem)); + avail -= rem; + rem = 0; + } else { + int c = (curr | (code >>> (rem - avail))); + if (destination.hasRemaining()) { + destination.put((byte) c); + } else { + return false; + } + curr = c; + code <<= (32 - rem + avail); // throw written bits off the cliff (is this Sparta?) + code >>>= (32 - rem + avail); // return to the position + rem -= avail; + curr = 0; + avail = 8; + } + } + } + + if (avail < 8) { // have to pad + if (destination.hasRemaining()) { + destination.put((byte) (curr | (INSTANCE.EOS.code >>> (INSTANCE.EOS.length - avail)))); + avail = 8; + } else { + return false; + } + } + + return true; + } + + public Writer reset() { + source = null; + end = -1; + pos = -1; + avail = 8; + curr = 0; + code = 0; + return this; + } + } + + /** + * Shared instance. + */ + public static final Huffman INSTANCE = new Huffman(); + + private final Code EOS = new Code(0x3fffffff, 30); + private final Code[] codes = new Code[257]; + private final Node root = new Node() { + @Override + public String toString() { return "root"; } + }; + + // TODO: consider builder and immutable trie + private Huffman() { + // @formatter:off + addChar(0, 0x1ff8, 13); + addChar(1, 0x7fffd8, 23); + addChar(2, 0xfffffe2, 28); + addChar(3, 0xfffffe3, 28); + addChar(4, 0xfffffe4, 28); + addChar(5, 0xfffffe5, 28); + addChar(6, 0xfffffe6, 28); + addChar(7, 0xfffffe7, 28); + addChar(8, 0xfffffe8, 28); + addChar(9, 0xffffea, 24); + addChar(10, 0x3ffffffc, 30); + addChar(11, 0xfffffe9, 28); + addChar(12, 0xfffffea, 28); + addChar(13, 0x3ffffffd, 30); + addChar(14, 0xfffffeb, 28); + addChar(15, 0xfffffec, 28); + addChar(16, 0xfffffed, 28); + addChar(17, 0xfffffee, 28); + addChar(18, 0xfffffef, 28); + addChar(19, 0xffffff0, 28); + addChar(20, 0xffffff1, 28); + addChar(21, 0xffffff2, 28); + addChar(22, 0x3ffffffe, 30); + addChar(23, 0xffffff3, 28); + addChar(24, 0xffffff4, 28); + addChar(25, 0xffffff5, 28); + addChar(26, 0xffffff6, 28); + addChar(27, 0xffffff7, 28); + addChar(28, 0xffffff8, 28); + addChar(29, 0xffffff9, 28); + addChar(30, 0xffffffa, 28); + addChar(31, 0xffffffb, 28); + addChar(32, 0x14, 6); + addChar(33, 0x3f8, 10); + addChar(34, 0x3f9, 10); + addChar(35, 0xffa, 12); + addChar(36, 0x1ff9, 13); + addChar(37, 0x15, 6); + addChar(38, 0xf8, 8); + addChar(39, 0x7fa, 11); + addChar(40, 0x3fa, 10); + addChar(41, 0x3fb, 10); + addChar(42, 0xf9, 8); + addChar(43, 0x7fb, 11); + addChar(44, 0xfa, 8); + addChar(45, 0x16, 6); + addChar(46, 0x17, 6); + addChar(47, 0x18, 6); + addChar(48, 0x0, 5); + addChar(49, 0x1, 5); + addChar(50, 0x2, 5); + addChar(51, 0x19, 6); + addChar(52, 0x1a, 6); + addChar(53, 0x1b, 6); + addChar(54, 0x1c, 6); + addChar(55, 0x1d, 6); + addChar(56, 0x1e, 6); + addChar(57, 0x1f, 6); + addChar(58, 0x5c, 7); + addChar(59, 0xfb, 8); + addChar(60, 0x7ffc, 15); + addChar(61, 0x20, 6); + addChar(62, 0xffb, 12); + addChar(63, 0x3fc, 10); + addChar(64, 0x1ffa, 13); + addChar(65, 0x21, 6); + addChar(66, 0x5d, 7); + addChar(67, 0x5e, 7); + addChar(68, 0x5f, 7); + addChar(69, 0x60, 7); + addChar(70, 0x61, 7); + addChar(71, 0x62, 7); + addChar(72, 0x63, 7); + addChar(73, 0x64, 7); + addChar(74, 0x65, 7); + addChar(75, 0x66, 7); + addChar(76, 0x67, 7); + addChar(77, 0x68, 7); + addChar(78, 0x69, 7); + addChar(79, 0x6a, 7); + addChar(80, 0x6b, 7); + addChar(81, 0x6c, 7); + addChar(82, 0x6d, 7); + addChar(83, 0x6e, 7); + addChar(84, 0x6f, 7); + addChar(85, 0x70, 7); + addChar(86, 0x71, 7); + addChar(87, 0x72, 7); + addChar(88, 0xfc, 8); + addChar(89, 0x73, 7); + addChar(90, 0xfd, 8); + addChar(91, 0x1ffb, 13); + addChar(92, 0x7fff0, 19); + addChar(93, 0x1ffc, 13); + addChar(94, 0x3ffc, 14); + addChar(95, 0x22, 6); + addChar(96, 0x7ffd, 15); + addChar(97, 0x3, 5); + addChar(98, 0x23, 6); + addChar(99, 0x4, 5); + addChar(100, 0x24, 6); + addChar(101, 0x5, 5); + addChar(102, 0x25, 6); + addChar(103, 0x26, 6); + addChar(104, 0x27, 6); + addChar(105, 0x6, 5); + addChar(106, 0x74, 7); + addChar(107, 0x75, 7); + addChar(108, 0x28, 6); + addChar(109, 0x29, 6); + addChar(110, 0x2a, 6); + addChar(111, 0x7, 5); + addChar(112, 0x2b, 6); + addChar(113, 0x76, 7); + addChar(114, 0x2c, 6); + addChar(115, 0x8, 5); + addChar(116, 0x9, 5); + addChar(117, 0x2d, 6); + addChar(118, 0x77, 7); + addChar(119, 0x78, 7); + addChar(120, 0x79, 7); + addChar(121, 0x7a, 7); + addChar(122, 0x7b, 7); + addChar(123, 0x7ffe, 15); + addChar(124, 0x7fc, 11); + addChar(125, 0x3ffd, 14); + addChar(126, 0x1ffd, 13); + addChar(127, 0xffffffc, 28); + addChar(128, 0xfffe6, 20); + addChar(129, 0x3fffd2, 22); + addChar(130, 0xfffe7, 20); + addChar(131, 0xfffe8, 20); + addChar(132, 0x3fffd3, 22); + addChar(133, 0x3fffd4, 22); + addChar(134, 0x3fffd5, 22); + addChar(135, 0x7fffd9, 23); + addChar(136, 0x3fffd6, 22); + addChar(137, 0x7fffda, 23); + addChar(138, 0x7fffdb, 23); + addChar(139, 0x7fffdc, 23); + addChar(140, 0x7fffdd, 23); + addChar(141, 0x7fffde, 23); + addChar(142, 0xffffeb, 24); + addChar(143, 0x7fffdf, 23); + addChar(144, 0xffffec, 24); + addChar(145, 0xffffed, 24); + addChar(146, 0x3fffd7, 22); + addChar(147, 0x7fffe0, 23); + addChar(148, 0xffffee, 24); + addChar(149, 0x7fffe1, 23); + addChar(150, 0x7fffe2, 23); + addChar(151, 0x7fffe3, 23); + addChar(152, 0x7fffe4, 23); + addChar(153, 0x1fffdc, 21); + addChar(154, 0x3fffd8, 22); + addChar(155, 0x7fffe5, 23); + addChar(156, 0x3fffd9, 22); + addChar(157, 0x7fffe6, 23); + addChar(158, 0x7fffe7, 23); + addChar(159, 0xffffef, 24); + addChar(160, 0x3fffda, 22); + addChar(161, 0x1fffdd, 21); + addChar(162, 0xfffe9, 20); + addChar(163, 0x3fffdb, 22); + addChar(164, 0x3fffdc, 22); + addChar(165, 0x7fffe8, 23); + addChar(166, 0x7fffe9, 23); + addChar(167, 0x1fffde, 21); + addChar(168, 0x7fffea, 23); + addChar(169, 0x3fffdd, 22); + addChar(170, 0x3fffde, 22); + addChar(171, 0xfffff0, 24); + addChar(172, 0x1fffdf, 21); + addChar(173, 0x3fffdf, 22); + addChar(174, 0x7fffeb, 23); + addChar(175, 0x7fffec, 23); + addChar(176, 0x1fffe0, 21); + addChar(177, 0x1fffe1, 21); + addChar(178, 0x3fffe0, 22); + addChar(179, 0x1fffe2, 21); + addChar(180, 0x7fffed, 23); + addChar(181, 0x3fffe1, 22); + addChar(182, 0x7fffee, 23); + addChar(183, 0x7fffef, 23); + addChar(184, 0xfffea, 20); + addChar(185, 0x3fffe2, 22); + addChar(186, 0x3fffe3, 22); + addChar(187, 0x3fffe4, 22); + addChar(188, 0x7ffff0, 23); + addChar(189, 0x3fffe5, 22); + addChar(190, 0x3fffe6, 22); + addChar(191, 0x7ffff1, 23); + addChar(192, 0x3ffffe0, 26); + addChar(193, 0x3ffffe1, 26); + addChar(194, 0xfffeb, 20); + addChar(195, 0x7fff1, 19); + addChar(196, 0x3fffe7, 22); + addChar(197, 0x7ffff2, 23); + addChar(198, 0x3fffe8, 22); + addChar(199, 0x1ffffec, 25); + addChar(200, 0x3ffffe2, 26); + addChar(201, 0x3ffffe3, 26); + addChar(202, 0x3ffffe4, 26); + addChar(203, 0x7ffffde, 27); + addChar(204, 0x7ffffdf, 27); + addChar(205, 0x3ffffe5, 26); + addChar(206, 0xfffff1, 24); + addChar(207, 0x1ffffed, 25); + addChar(208, 0x7fff2, 19); + addChar(209, 0x1fffe3, 21); + addChar(210, 0x3ffffe6, 26); + addChar(211, 0x7ffffe0, 27); + addChar(212, 0x7ffffe1, 27); + addChar(213, 0x3ffffe7, 26); + addChar(214, 0x7ffffe2, 27); + addChar(215, 0xfffff2, 24); + addChar(216, 0x1fffe4, 21); + addChar(217, 0x1fffe5, 21); + addChar(218, 0x3ffffe8, 26); + addChar(219, 0x3ffffe9, 26); + addChar(220, 0xffffffd, 28); + addChar(221, 0x7ffffe3, 27); + addChar(222, 0x7ffffe4, 27); + addChar(223, 0x7ffffe5, 27); + addChar(224, 0xfffec, 20); + addChar(225, 0xfffff3, 24); + addChar(226, 0xfffed, 20); + addChar(227, 0x1fffe6, 21); + addChar(228, 0x3fffe9, 22); + addChar(229, 0x1fffe7, 21); + addChar(230, 0x1fffe8, 21); + addChar(231, 0x7ffff3, 23); + addChar(232, 0x3fffea, 22); + addChar(233, 0x3fffeb, 22); + addChar(234, 0x1ffffee, 25); + addChar(235, 0x1ffffef, 25); + addChar(236, 0xfffff4, 24); + addChar(237, 0xfffff5, 24); + addChar(238, 0x3ffffea, 26); + addChar(239, 0x7ffff4, 23); + addChar(240, 0x3ffffeb, 26); + addChar(241, 0x7ffffe6, 27); + addChar(242, 0x3ffffec, 26); + addChar(243, 0x3ffffed, 26); + addChar(244, 0x7ffffe7, 27); + addChar(245, 0x7ffffe8, 27); + addChar(246, 0x7ffffe9, 27); + addChar(247, 0x7ffffea, 27); + addChar(248, 0x7ffffeb, 27); + addChar(249, 0xffffffe, 28); + addChar(250, 0x7ffffec, 27); + addChar(251, 0x7ffffed, 27); + addChar(252, 0x7ffffee, 27); + addChar(253, 0x7ffffef, 27); + addChar(254, 0x7fffff0, 27); + addChar(255, 0x3ffffee, 26); + addEOS (256, EOS.code, EOS.length); + // @formatter:on + } + + + /** + * Calculates the number of bytes required to represent the given {@code + * CharSequence} with the Huffman coding. + * + * @param value + * characters + * + * @return number of bytes + * + * @throws NullPointerException + * if the value is null + */ + public int lengthOf(CharSequence value) { + return lengthOf(value, 0, value.length()); + } + + /** + * Calculates the number of bytes required to represent a subsequence of the + * given {@code CharSequence} with the Huffman coding. + * + * @param value + * characters + * @param start + * the start index, inclusive + * @param end + * the end index, exclusive + * + * @return number of bytes + * + * @throws NullPointerException + * if the value is null + * @throws IndexOutOfBoundsException + * if any invocation of {@code value.charAt(i)}, where {@code start + * <= i < end} would throw an IndexOutOfBoundsException + */ + public int lengthOf(CharSequence value, int start, int end) { + int len = 0; + for (int i = start; i < end; i++) { + char c = value.charAt(i); + len += INSTANCE.codeOf(c).length; + } + // Integer division with ceiling, assumption: + assert (len / 8 + (len % 8 != 0 ? 1 : 0)) == (len + 7) / 8 : len; + return (len + 7) / 8; + } + + private void addChar(int c, int code, int bitLength) { + addLeaf(c, code, bitLength, false); + codes[c] = new Code(code, bitLength); + } + + private void addEOS(int c, int code, int bitLength) { + addLeaf(c, code, bitLength, true); + codes[c] = new Code(code, bitLength); + } + + private void addLeaf(int c, int code, int bitLength, boolean isEOS) { + if (bitLength < 1) { + throw new IllegalArgumentException("bitLength < 1"); + } + Node curr = root; + for (int p = 1 << bitLength - 1; p != 0 && !curr.isLeaf(); p = p >> 1) { + curr.isEOSPath |= isEOS; // If it's already true, it can't become false + curr = curr.addChildIfAbsent(p & code); + } + curr.isEOSPath |= isEOS; // The last one needs to have this property as well + if (curr.isLeaf()) { + throw new IllegalStateException("Specified code is already taken"); + } + curr.setChar((char) c); + } + + private Code codeOf(char c) { + if (c > 255) { + throw new IllegalArgumentException("char=" + ((int) c)); + } + return codes[c]; + } + + // + // For debugging/testing purposes + // + Node getRoot() { + return root; + } + + // + // Guarantees: + // + // if (isLeaf() == true) => getChar() is a legal call + // if (isLeaf() == false) => getChild(i) is a legal call (though it can + // return null) + // + static class Node { + + Node left; + Node right; + boolean isEOSPath; + + boolean charIsSet; + char c; + + Node getChild(int selector) { + if (isLeaf()) { + throw new IllegalStateException("This is a leaf node"); + } + Node result = selector == 0 ? left : right; + if (result == null) { + throw new IllegalStateException(format( + "Node doesn't have a child (selector=%s)", selector)); + } + return result; + } + + boolean isLeaf() { + return charIsSet; + } + + char getChar() { + if (!isLeaf()) { + throw new IllegalStateException("This node is not a leaf node"); + } + return c; + } + + void setChar(char c) { + if (charIsSet) { + throw new IllegalStateException( + "This node has been taken already"); + } + if (left != null || right != null) { + throw new IllegalStateException("The node cannot be made " + + "a leaf as it's already has a child"); + } + this.c = c; + charIsSet = true; + } + + Node addChildIfAbsent(int i) { + if (charIsSet) { + throw new IllegalStateException("The node cannot have a child " + + "as it's already a leaf node"); + } + Node child; + if (i == 0) { + if ((child = left) == null) { + child = left = new Node(); + } + } else { + if ((child = right) == null) { + child = right = new Node(); + } + } + return child; + } + + @Override + public String toString() { + if (isLeaf()) { + if (isEOSPath) { + return "EOS"; + } else { + return format("char: (%3s) '%s'", (int) c, c); + } + } + return "/\\"; + } + } + + // TODO: value-based class? + // FIXME: can we re-use Node instead of this class? + private static final class Code { + + final int code; + final int length; + + private Code(int code, int length) { + this.code = code; + this.length = length; + } + + public int getCode() { + return code; + } + + public int getLength() { + return length; + } + + @Override + public String toString() { + long p = 1 << length; + return Long.toBinaryString(code + p).substring(1) + + ", length=" + length; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java new file mode 100644 index 00000000000..162c9839ae9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +// +// Custom implementation of ISO/IEC 8859-1:1998 +// +// The rationale behind this is not to deal with CharsetEncoder/CharsetDecoder, +// basically because it would require wrapping every single CharSequence into a +// CharBuffer and then copying it back. +// +// But why not to give a CharBuffer instead of Appendable? Because I can choose +// an Appendable (e.g. StringBuilder) that adjusts its length when needed and +// therefore not to deal with pre-sized CharBuffers or copying. +// +// The encoding is simple and well known: 1 byte <-> 1 char +// +final class ISO_8859_1 { + + private ISO_8859_1() { } + + public static final class Reader { + + public void read(ByteBuffer source, Appendable destination) { + for (int i = 0, len = source.remaining(); i < len; i++) { + char c = (char) (source.get() & 0xff); + try { + destination.append(c); + } catch (IOException e) { + throw new UncheckedIOException + ("Error appending to the destination", e); + } + } + } + + public Reader reset() { + return this; + } + } + + public static final class Writer { + + private CharSequence source; + private int pos; + private int end; + + public Writer configure(CharSequence source, int start, int end) { + this.source = source; + this.pos = start; + this.end = end; + return this; + } + + public boolean write(ByteBuffer destination) { + for (; pos < end; pos++) { + char c = source.charAt(pos); + if (c > '\u00FF') { + throw new IllegalArgumentException( + "Illegal ISO-8859-1 char: " + (int) c); + } + if (destination.hasRemaining()) { + destination.put((byte) c); + } else { + return false; + } + } + return true; + } + + public Writer reset() { + source = null; + pos = -1; + end = -1; + return this; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java new file mode 100644 index 00000000000..01b4decca00 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +abstract class IndexNameValueWriter implements BinaryRepresentationWriter { + + private final int pattern; + private final int prefix; + private final IntegerWriter intWriter = new IntegerWriter(); + private final StringWriter nameWriter = new StringWriter(); + private final StringWriter valueWriter = new StringWriter(); + + protected boolean indexedRepresentation; + + private static final int NEW = 0; + private static final int NAME_PART_WRITTEN = 1; + private static final int VALUE_WRITTEN = 2; + + private int state = NEW; + + protected IndexNameValueWriter(int pattern, int prefix) { + this.pattern = pattern; + this.prefix = prefix; + } + + IndexNameValueWriter index(int index) { + indexedRepresentation = true; + intWriter.configure(index, prefix, pattern); + return this; + } + + IndexNameValueWriter name(CharSequence name, boolean useHuffman) { + indexedRepresentation = false; + intWriter.configure(0, prefix, pattern); + nameWriter.configure(name, useHuffman); + return this; + } + + IndexNameValueWriter value(CharSequence value, boolean useHuffman) { + valueWriter.configure(value, useHuffman); + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (state < NAME_PART_WRITTEN) { + if (indexedRepresentation) { + if (!intWriter.write(destination)) { + return false; + } + } else { + if (!intWriter.write(destination) || !nameWriter.write(destination)) { + return false; + } + } + state = NAME_PART_WRITTEN; + } + if (state < VALUE_WRITTEN) { + if (!valueWriter.write(destination)) { + return false; + } + state = VALUE_WRITTEN; + } + return state == VALUE_WRITTEN; + } + + @Override + public IndexNameValueWriter reset() { + intWriter.reset(); + if (!indexedRepresentation) { + nameWriter.reset(); + } + valueWriter.reset(); + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java new file mode 100644 index 00000000000..4ccd9d76112 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class IndexedWriter implements BinaryRepresentationWriter { + + private final IntegerWriter intWriter = new IntegerWriter(); + + IndexedWriter() { } + + IndexedWriter index(int index) { + intWriter.configure(index, 7, 0b1000_0000); + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + return intWriter.write(destination); + } + + @Override + public BinaryRepresentationWriter reset() { + intWriter.reset(); + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java new file mode 100644 index 00000000000..0e7abcfd2f5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import static java.lang.String.format; + +final class IntegerReader { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int FIRST_BYTE_READ = 2; + private static final int DONE = 4; + + private int state = NEW; + + private int N; + private int maxValue; + private int value; + private long r; + private long b = 1; + + public IntegerReader configure(int N) { + return configure(N, Integer.MAX_VALUE); + } + + // + // Why is it important to configure 'maxValue' here. After all we can wait + // for the integer to be fully read and then check it. Can't we? + // + // Two reasons. + // + // 1. Value wraps around long won't be unnoticed. + // 2. It can spit out an exception as soon as it becomes clear there's + // an overflow. Therefore, no need to wait for the value to be fully read. + // + public IntegerReader configure(int N, int maxValue) { + if (state != NEW) { + throw new IllegalStateException("Already configured"); + } + checkPrefix(N); + if (maxValue < 0) { + throw new IllegalArgumentException( + "maxValue >= 0: maxValue=" + maxValue); + } + this.maxValue = maxValue; + this.N = N; + state = CONFIGURED; + return this; + } + + public boolean read(ByteBuffer input) { + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (state == DONE) { + return true; + } + if (!input.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + int max = (2 << (N - 1)) - 1; + int n = input.get() & max; + if (n != max) { + value = n; + state = DONE; + return true; + } else { + r = max; + } + state = FIRST_BYTE_READ; + } + if (state == FIRST_BYTE_READ) { + // variable-length quantity (VLQ) + byte i; + do { + if (!input.hasRemaining()) { + return false; + } + i = input.get(); + long increment = b * (i & 127); + if (r + increment > maxValue) { + throw new IllegalArgumentException(format( + "Integer overflow: maxValue=%,d, value=%,d", + maxValue, r + increment)); + } + r += increment; + b *= 128; + } while ((128 & i) == 128); + + value = (int) r; + state = DONE; + return true; + } + throw new InternalError(Arrays.toString( + new Object[]{state, N, maxValue, value, r, b})); + } + + public int get() throws IllegalStateException { + if (state != DONE) { + throw new IllegalStateException("Has not been fully read yet"); + } + return value; + } + + private static void checkPrefix(int N) { + if (N < 1 || N > 8) { + throw new IllegalArgumentException("1 <= N <= 8: N= " + N); + } + } + + public IntegerReader reset() { + b = 1; + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java new file mode 100644 index 00000000000..7fd1c108ab3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +final class IntegerWriter { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int FIRST_BYTE_WRITTEN = 2; + private static final int DONE = 4; + + private int state = NEW; + + private int payload; + private int N; + private int value; + + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | | | | | | | | | + // +---+---+---+-------------------+ + // |<--------->|<----------------->| + // payload N=5 + // + // payload is the contents of the left-hand side part of the octet; + // it is truncated to fit into 8-N bits, where 1 <= N <= 8; + // + public IntegerWriter configure(int value, int N, int payload) { + if (state != NEW) { + throw new IllegalStateException("Already configured"); + } + if (value < 0) { + throw new IllegalArgumentException("value >= 0: value=" + value); + } + checkPrefix(N); + this.value = value; + this.N = N; + this.payload = payload & 0xFF & (0xFFFFFFFF << N); + state = CONFIGURED; + return this; + } + + public boolean write(ByteBuffer output) { + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (state == DONE) { + return true; + } + + if (!output.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + int max = (2 << (N - 1)) - 1; + if (value < max) { + output.put((byte) (payload | value)); + state = DONE; + return true; + } + output.put((byte) (payload | max)); + value -= max; + state = FIRST_BYTE_WRITTEN; + } + if (state == FIRST_BYTE_WRITTEN) { + while (value >= 128 && output.hasRemaining()) { + output.put((byte) (value % 128 + 128)); + value /= 128; + } + if (!output.hasRemaining()) { + return false; + } + output.put((byte) value); + state = DONE; + return true; + } + throw new InternalError(Arrays.toString( + new Object[]{state, payload, N, value})); + } + + private static void checkPrefix(int N) { + if (N < 1 || N > 8) { + throw new IllegalArgumentException("1 <= N <= 8: N= " + N); + } + } + + public IntegerWriter reset() { + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java new file mode 100644 index 00000000000..92547ca13a9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +final class LiteralNeverIndexedWriter extends IndexNameValueWriter { + + LiteralNeverIndexedWriter() { + super(0b0001_0000, 4); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java new file mode 100644 index 00000000000..5926bd6820e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java @@ -0,0 +1,85 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class LiteralWithIndexingWriter extends IndexNameValueWriter { + + private boolean tableUpdated; + + private CharSequence name; + private CharSequence value; + private int index; + + LiteralWithIndexingWriter() { + super(0b0100_0000, 6); + } + + @Override + LiteralWithIndexingWriter index(int index) { + super.index(index); + this.index = index; + return this; + } + + @Override + LiteralWithIndexingWriter name(CharSequence name, boolean useHuffman) { + super.name(name, useHuffman); + this.name = name; + return this; + } + + @Override + LiteralWithIndexingWriter value(CharSequence value, boolean useHuffman) { + super.value(value, useHuffman); + this.value = value; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!tableUpdated) { + CharSequence n; + if (indexedRepresentation) { + n = table.get(index).name; + } else { + n = name; + } + table.put(n, value); + tableUpdated = true; + } + return super.write(table, destination); + } + + @Override + public IndexNameValueWriter reset() { + tableUpdated = false; + name = null; + value = null; + index = -1; + return super.reset(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java new file mode 100644 index 00000000000..430dac4a384 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +final class LiteralWriter extends IndexNameValueWriter { + + LiteralWriter() { + super(0b0000_0000, 4); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java new file mode 100644 index 00000000000..5148afeeddc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class SizeUpdateWriter implements BinaryRepresentationWriter { + + private final IntegerWriter intWriter = new IntegerWriter(); + private int maxSize; + private boolean tableUpdated; + + SizeUpdateWriter() { } + + SizeUpdateWriter maxHeaderTableSize(int size) { + intWriter.configure(size, 5, 0b0010_0000); + this.maxSize = size; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!tableUpdated) { + table.setMaxSize(maxSize); + tableUpdated = true; + } + return intWriter.write(destination); + } + + @Override + public BinaryRepresentationWriter reset() { + intWriter.reset(); + maxSize = -1; + tableUpdated = false; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java new file mode 100644 index 00000000000..e2bbefb1473 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +// +// 0 1 2 3 4 5 6 7 +// +---+---+---+---+---+---+---+---+ +// | H | String Length (7+) | +// +---+---------------------------+ +// | String Data (Length octets) | +// +-------------------------------+ +// +final class StringReader { + + private static final int NEW = 0; + private static final int FIRST_BYTE_READ = 1; + private static final int LENGTH_READ = 2; + private static final int DONE = 4; + + private final IntegerReader intReader = new IntegerReader(); + private final Huffman.Reader huffmanReader = new Huffman.Reader(); + private final ISO_8859_1.Reader plainReader = new ISO_8859_1.Reader(); + + private int state = NEW; + + private boolean huffman; + private int remainingLength; + + boolean read(ByteBuffer input, Appendable output) { + if (state == DONE) { + return true; + } + if (!input.hasRemaining()) { + return false; + } + if (state == NEW) { + int p = input.position(); + huffman = (input.get(p) & 0b10000000) != 0; + state = FIRST_BYTE_READ; + intReader.configure(7); + } + if (state == FIRST_BYTE_READ) { + boolean lengthRead = intReader.read(input); + if (!lengthRead) { + return false; + } + remainingLength = intReader.get(); + state = LENGTH_READ; + } + if (state == LENGTH_READ) { + boolean isLast = input.remaining() >= remainingLength; + int oldLimit = input.limit(); + if (isLast) { + input.limit(input.position() + remainingLength); + } + if (huffman) { + huffmanReader.read(input, output, isLast); + } else { + plainReader.read(input, output); + } + if (isLast) { + input.limit(oldLimit); + } + return isLast; + } + throw new InternalError(Arrays.toString( + new Object[]{state, huffman, remainingLength})); + } + + boolean isHuffmanEncoded() { + if (state < FIRST_BYTE_READ) { + throw new IllegalStateException("Has not been fully read yet"); + } + return huffman; + } + + void reset() { + if (huffman) { + huffmanReader.reset(); + } else { + plainReader.reset(); + } + intReader.reset(); + state = NEW; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java new file mode 100644 index 00000000000..5c58e371082 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +// +// 0 1 2 3 4 5 6 7 +// +---+---+---+---+---+---+---+---+ +// | H | String Length (7+) | +// +---+---------------------------+ +// | String Data (Length octets) | +// +-------------------------------+ +// +// StringWriter does not require a notion of endOfInput (isLast) in 'write' +// methods due to the nature of string representation in HPACK. Namely, the +// length of the string is put before string's contents. Therefore the length is +// always known beforehand. +// +// Expected use: +// +// configure write* (reset configure write*)* +// +final class StringWriter { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int LENGTH_WRITTEN = 2; + private static final int DONE = 4; + + private final IntegerWriter intWriter = new IntegerWriter(); + private final Huffman.Writer huffmanWriter = new Huffman.Writer(); + private final ISO_8859_1.Writer plainWriter = new ISO_8859_1.Writer(); + + private int state = NEW; + private boolean huffman; + + StringWriter configure(CharSequence input, boolean huffman) { + return configure(input, 0, input.length(), huffman); + } + + StringWriter configure(CharSequence input, int start, int end, + boolean huffman) { + if (start < 0 || end < 0 || end > input.length() || start > end) { + throw new IndexOutOfBoundsException( + String.format("input.length()=%s, start=%s, end=%s", + input.length(), start, end)); + } + if (!huffman) { + plainWriter.configure(input, start, end); + intWriter.configure(end - start, 7, 0b0000_0000); + } else { + huffmanWriter.from(input, start, end); + intWriter.configure(Huffman.INSTANCE.lengthOf(input, start, end), + 7, 0b1000_0000); + } + + this.huffman = huffman; + state = CONFIGURED; + return this; + } + + boolean write(ByteBuffer output) { + if (state == DONE) { + return true; + } + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (!output.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + if (intWriter.write(output)) { + state = LENGTH_WRITTEN; + } else { + return false; + } + } + if (state == LENGTH_WRITTEN) { + boolean written = huffman + ? huffmanWriter.write(output) + : plainWriter.write(output); + if (written) { + state = DONE; + return true; + } else { + return false; + } + } + throw new InternalError(Arrays.toString(new Object[]{state, huffman})); + } + + void reset() { + intWriter.reset(); + if (huffman) { + huffmanWriter.reset(); + } else { + plainWriter.reset(); + } + state = NEW; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java new file mode 100644 index 00000000000..5c035ff4662 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +/** + * HPACK (Header Compression for HTTP/2) implementation conforming to + * RFC 7541. + * + *

Headers can be decoded and encoded by {@link sun.net.httpclient.hpack.Decoder} + * and {@link sun.net.httpclient.hpack.Encoder} respectively. + * + *

Instances of these classes are not safe for use by multiple threads. + */ +package sun.net.httpclient.hpack; diff --git a/jdk/test/java/net/httpclient/http2/HpackDriver.java b/jdk/test/java/net/httpclient/http2/HpackDriver.java new file mode 100644 index 00000000000..3bf1bc39a4b --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/HpackDriver.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8153353 + * @modules java.httpclient/sun.net.httpclient.hpack + * @key randomness + * @compile/module=java.httpclient sun/net/httpclient/hpack/SpecHelper.java + * @compile/module=java.httpclient sun/net/httpclient/hpack/TestHelper.java + * @compile/module=java.httpclient sun/net/httpclient/hpack/BuffersTestingKit.java + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.BinaryPrimitivesTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.CircularBufferTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.DecoderTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.EncoderTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HeaderTableTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HuffmanTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.TestHelper + */ +public class HpackDriver { } diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java new file mode 100644 index 00000000000..dedd53329a8 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; +import static sun.net.httpclient.hpack.BuffersTestingKit.*; +import static sun.net.httpclient.hpack.TestHelper.newRandom; + +// +// Some of the tests below overlap in what they test. This allows to diagnose +// bugs quicker and with less pain by simply ruling out common working bits. +// +public final class BinaryPrimitivesTest { + + private final Random rnd = newRandom(); + + @Test + public void integerRead1() { + verifyRead(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5); + } + + @Test + public void integerRead2() { + verifyRead(bytes(0b00001010), 10, 5); + } + + @Test + public void integerRead3() { + verifyRead(bytes(0b00101010), 42, 8); + } + + @Test + public void integerWrite1() { + verifyWrite(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5); + } + + @Test + public void integerWrite2() { + verifyWrite(bytes(0b00001010), 10, 5); + } + + @Test + public void integerWrite3() { + verifyWrite(bytes(0b00101010), 42, 8); + } + + // + // Since readInteger(x) is the inverse of writeInteger(x), thus: + // + // for all x: readInteger(writeInteger(x)) == x + // + @Test + public void integerIdentity() { + final int MAX_VALUE = 1 << 22; + int totalCases = 0; + int maxFilling = 0; + IntegerReader r = new IntegerReader(); + IntegerWriter w = new IntegerWriter(); + ByteBuffer buf = ByteBuffer.allocate(8); + for (int N = 1; N < 9; N++) { + for (int expected = 0; expected <= MAX_VALUE; expected++) { + w.reset().configure(expected, N, 1).write(buf); + buf.flip(); + totalCases++; + maxFilling = Math.max(maxFilling, buf.remaining()); + r.reset().configure(N).read(buf); + assertEquals(r.get(), expected); + buf.clear(); + } + } + System.out.printf("totalCases: %,d, maxFilling: %,d, maxValue: %,d%n", + totalCases, maxFilling, MAX_VALUE); + } + + @Test + public void integerReadChunked() { + final int NUM_TESTS = 1024; + IntegerReader r = new IntegerReader(); + ByteBuffer bb = ByteBuffer.allocate(8); + IntegerWriter w = new IntegerWriter(); + for (int i = 0; i < NUM_TESTS; i++) { + final int N = 1 + rnd.nextInt(8); + final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1; + w.reset().configure(expected, N, rnd.nextInt()).write(bb); + bb.flip(); + + forEachSplit(bb, + (buffers) -> { + Iterable buf = relocateBuffers(injectEmptyBuffers(buffers)); + r.configure(N); + for (ByteBuffer b : buf) { + r.read(b); + } + assertEquals(r.get(), expected); + r.reset(); + }); + bb.clear(); + } + } + + // FIXME: use maxValue in the test + + @Test + // FIXME: tune values for better coverage + public void integerWriteChunked() { + ByteBuffer bb = ByteBuffer.allocate(6); + IntegerWriter w = new IntegerWriter(); + IntegerReader r = new IntegerReader(); + for (int i = 0; i < 1024; i++) { // number of tests + final int N = 1 + rnd.nextInt(8); + final int payload = rnd.nextInt(255); + final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1; + + forEachSplit(bb, + (buffers) -> { + List buf = new ArrayList<>(); + relocateBuffers(injectEmptyBuffers(buffers)).forEach(buf::add); + boolean written = false; + w.configure(expected, N, payload); // TODO: test for payload it can be read after written + for (ByteBuffer b : buf) { + int pos = b.position(); + written = w.write(b); + b.position(pos); + } + if (!written) { + fail("please increase bb size"); + } + r.configure(N).read(concat(buf)); + // TODO: check payload here + assertEquals(r.get(), expected); + w.reset(); + r.reset(); + bb.clear(); + }); + } + } + + + // + // Since readString(x) is the inverse of writeString(x), thus: + // + // for all x: readString(writeString(x)) == x + // + @Test + public void stringIdentity() { + final int MAX_STRING_LENGTH = 4096; + ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); // it takes 6 bytes to encode string length of Integer.MAX_VALUE + CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + StringReader reader = new StringReader(); + StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + for (int i = 0; i < 64; i++) { + // not so much "test in isolation", I know... we're testing .reset() as well + bytes.clear(); + chars.clear(); + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + boolean written = writer + .configure(CharBuffer.wrap(expected), 0, expected.length(), false) + .write(bytes); + + if (!written) { + fail("please increase 'bytes' size"); + } + bytes.flip(); + reader.read(bytes, chars); + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + writer.reset(); + } + } + } + +// @Test +// public void huffmanStringWriteChunked() { +// fail(); +// } +// +// @Test +// public void huffmanStringReadChunked() { +// fail(); +// } + + @Test + public void stringWriteChunked() { + final int MAX_STRING_LENGTH = 8; + final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); + final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + final StringReader reader = new StringReader(); + final StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + forEachSplit(bytes, (buffers) -> { + writer.configure(expected, 0, expected.length(), false); + boolean written = false; + for (ByteBuffer buf : buffers) { + int p0 = buf.position(); + written = writer.write(buf); + buf.position(p0); + } + if (!written) { + fail("please increase 'bytes' size"); + } + reader.read(concat(buffers), chars); + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + writer.reset(); + chars.clear(); + bytes.clear(); + }); + } + } + + @Test + public void stringReadChunked() { + final int MAX_STRING_LENGTH = 16; + final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); + final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + final StringReader reader = new StringReader(); + final StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + boolean written = writer + .configure(CharBuffer.wrap(expected), 0, expected.length(), false) + .write(bytes); + writer.reset(); + + if (!written) { + fail("please increase 'bytes' size"); + } + bytes.flip(); + + forEachSplit(bytes, (buffers) -> { + for (ByteBuffer buf : buffers) { + int p0 = buf.position(); + reader.read(buf, chars); + buf.position(p0); + } + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + chars.clear(); + }); + + bytes.clear(); + } + } + +// @Test +// public void test_Huffman_String_Identity() { +// StringWriter writer = new StringWriter(); +// StringReader reader = new StringReader(); +// // 256 * 8 gives 2048 bits in case of plain 8 bit coding +// // 256 * 30 gives you 7680 bits or 960 bytes in case of almost +// // improbable event of 256 30 bits symbols in a row +// ByteBuffer binary = ByteBuffer.allocate(960); +// CharBuffer text = CharBuffer.allocate(960 / 5); // 5 = minimum code length +// for (int len = 0; len < 128; len++) { +// for (int i = 0; i < 256; i++) { +// // not so much "test in isolation", I know... +// binary.clear(); +// +// byte[] bytes = new byte[len]; +// rnd.nextBytes(bytes); +// +// String s = new String(bytes, StandardCharsets.ISO_8859_1); +// +// writer.write(CharBuffer.wrap(s), binary, true); +// binary.flip(); +// reader.read(binary, text); +// text.flip(); +// assertEquals(text.toString(), s); +// } +// } +// } + + // TODO: atomic failures: e.g. readonly/overflow + + private static byte[] bytes(int... data) { + byte[] bytes = new byte[data.length]; + for (int i = 0; i < data.length; i++) { + bytes[i] = (byte) data[i]; + } + return bytes; + } + + private static void verifyRead(byte[] data, int expected, int N) { + ByteBuffer buf = ByteBuffer.wrap(data, 0, data.length); + IntegerReader reader = new IntegerReader(); + reader.configure(N).read(buf); + assertEquals(expected, reader.get()); + } + + private void verifyWrite(byte[] expected, int data, int N) { + IntegerWriter w = new IntegerWriter(); + ByteBuffer buf = ByteBuffer.allocate(2 * expected.length); + w.configure(data, N, 1).write(buf); + buf.flip(); + assertEquals(ByteBuffer.wrap(expected), buf); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java new file mode 100644 index 00000000000..4f9631647c7 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import static java.nio.ByteBuffer.allocate; + +public final class BuffersTestingKit { + + /** + * Relocates a {@code [position, limit)} region of the given buffer to + * corresponding region in a new buffer starting with provided {@code + * newPosition}. + * + *

Might be useful to make sure ByteBuffer's users do not rely on any + * absolute positions, but solely on what's reported by position(), limit(). + * + *

The contents between the given buffer and the returned one are not + * shared. + */ + public static ByteBuffer relocate(ByteBuffer buffer, int newPosition, + int newCapacity) { + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + if (newPosition + oldLimit - oldPosition > newCapacity) { + throw new IllegalArgumentException(); + } + + ByteBuffer result; + if (buffer.isDirect()) { + result = ByteBuffer.allocateDirect(newCapacity); + } else { + result = allocate(newCapacity); + } + + result.position(newPosition); + result.put(buffer).limit(result.position()).position(newPosition); + buffer.position(oldPosition); + + if (buffer.isReadOnly()) { + return result.asReadOnlyBuffer(); + } + return result; + } + + public static Iterable relocateBuffers( + Iterable source) { + return () -> + new Iterator() { + + private final Iterator it = source.iterator(); + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public ByteBuffer next() { + ByteBuffer buf = it.next(); + int remaining = buf.remaining(); + int newCapacity = remaining + random.nextInt(17); + int newPosition = random.nextInt(newCapacity - remaining + 1); + return relocate(buf, newPosition, newCapacity); + } + }; + } + + // TODO: not always of size 0 (it's fine for buffer to report !b.hasRemaining()) + public static Iterable injectEmptyBuffers( + Iterable source) { + return injectEmptyBuffers(source, () -> allocate(0)); + } + + public static Iterable injectEmptyBuffers( + Iterable source, + Supplier emptyBufferFactory) { + + return () -> + new Iterator() { + + private final Iterator it = source.iterator(); + private ByteBuffer next = calculateNext(); + + private ByteBuffer calculateNext() { + if (random.nextBoolean()) { + return emptyBufferFactory.get(); + } else if (it.hasNext()) { + return it.next(); + } else { + return null; + } + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public ByteBuffer next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + ByteBuffer next = this.next; + this.next = calculateNext(); + return next; + } + }; + } + + public static ByteBuffer concat(Iterable split) { + return concat(split, ByteBuffer::allocate); + } + + public static ByteBuffer concat(Iterable split, + Function concatBufferFactory) { + int size = 0; + for (ByteBuffer bb : split) { + size += bb.remaining(); + } + + ByteBuffer result = concatBufferFactory.apply(size); + for (ByteBuffer bb : split) { + result.put(bb); + } + + result.flip(); + return result; + } + + public static void forEachSplit(ByteBuffer bb, + Consumer> action) { + forEachSplit(bb.remaining(), + (lengths) -> { + int end = bb.position(); + List buffers = new LinkedList<>(); + for (int len : lengths) { + ByteBuffer d = bb.duplicate(); + d.position(end); + d.limit(end + len); + end += len; + buffers.add(d); + } + action.accept(buffers); + }); + } + + private static void forEachSplit(int n, Consumer> action) { + forEachSplit(n, new Stack<>(), action); + } + + private static void forEachSplit(int n, Stack path, + Consumer> action) { + if (n == 0) { + action.accept(path); + } else { + for (int i = 1; i <= n; i++) { + path.push(i); + forEachSplit(n - i, path, action); + path.pop(); + } + } + } + + private static final Random random = new Random(); + + private BuffersTestingKit() { + throw new InternalError(); + } + +// public static void main(String[] args) { +// +// List buffers = Arrays.asList( +// (ByteBuffer) allocate(3).position(1).limit(2), +// allocate(0), +// allocate(7)); +// +// Iterable buf = relocateBuffers(injectEmptyBuffers(buffers)); +// List result = new ArrayList<>(); +// buf.forEach(result::add); +// System.out.println(result); +// } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java new file mode 100644 index 00000000000..ebf1cb1d1ee --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import sun.net.httpclient.hpack.HeaderTable.CircularBuffer; + +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.ArrayBlockingQueue; + +import static org.testng.Assert.assertEquals; +import static sun.net.httpclient.hpack.TestHelper.newRandom; + +public final class CircularBufferTest { + + private final Random r = newRandom(); + + @BeforeClass + public void setUp() { + r.setSeed(System.currentTimeMillis()); + } + + @Test + public void queue() { + for (int capacity = 1; capacity <= 2048; capacity++) { + queueOnce(capacity, 32); + } + } + + @Test + public void resize() { + for (int capacity = 1; capacity <= 4096; capacity++) { + resizeOnce(capacity); + } + } + + @Test + public void downSizeEmptyBuffer() { + CircularBuffer buffer = new CircularBuffer<>(16); + buffer.resize(15); + } + + private void resizeOnce(int capacity) { + + int nextNumberToPut = 0; + + Queue referenceQueue = new ArrayBlockingQueue<>(capacity); + CircularBuffer buffer = new CircularBuffer<>(capacity); + + // Fill full, so the next add will wrap + for (int i = 0; i < capacity; i++, nextNumberToPut++) { + buffer.add(nextNumberToPut); + referenceQueue.add(nextNumberToPut); + } + int gets = r.nextInt(capacity); // [0, capacity) + for (int i = 0; i < gets; i++) { + referenceQueue.poll(); + buffer.remove(); + } + int puts = r.nextInt(gets + 1); // [0, gets] + for (int i = 0; i < puts; i++, nextNumberToPut++) { + buffer.add(nextNumberToPut); + referenceQueue.add(nextNumberToPut); + } + + Integer[] expected = referenceQueue.toArray(new Integer[0]); + buffer.resize(expected.length); + + assertEquals(buffer.elements, expected); + } + + private void queueOnce(int capacity, int numWraps) { + + Queue referenceQueue = new ArrayBlockingQueue<>(capacity); + CircularBuffer buffer = new CircularBuffer<>(capacity); + + int nextNumberToPut = 0; + int totalPuts = 0; + int putsLimit = capacity * numWraps; + int remainingCapacity = capacity; + int size = 0; + + while (totalPuts < putsLimit) { + assert remainingCapacity + size == capacity; + int puts = r.nextInt(remainingCapacity + 1); // [0, remainingCapacity] + remainingCapacity -= puts; + size += puts; + for (int i = 0; i < puts; i++, nextNumberToPut++) { + referenceQueue.add(nextNumberToPut); + buffer.add(nextNumberToPut); + } + totalPuts += puts; + int gets = r.nextInt(size + 1); // [0, size] + size -= gets; + remainingCapacity += gets; + for (int i = 0; i < gets; i++) { + Integer expected = referenceQueue.poll(); + Integer actual = buffer.remove(); + assertEquals(actual, expected); + } + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java new file mode 100644 index 00000000000..29a651fb0f7 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.io.UncheckedIOException; +import java.net.ProtocolException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static sun.net.httpclient.hpack.TestHelper.*; + +public final class DecoderTest { + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.1 + // + @Test + public void example1() { + // @formatter:off + test("400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" + + "746f 6d2d 6865 6164 6572", + + "[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55", + + "custom-key: custom-header"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.2 + // + @Test + public void example2() { + // @formatter:off + test("040c 2f73 616d 706c 652f 7061 7468", + "empty.", + ":path: /sample/path"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.3 + // + @Test + public void example3() { + // @formatter:off + test("1008 7061 7373 776f 7264 0673 6563 7265\n" + + "74", + "empty.", + "password: secret"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.4 + // + @Test + public void example4() { + // @formatter:off + test("82", + "empty.", + ":method: GET"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.3 + // + @Test + public void example5() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" + + "2e63 6f6d", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com"); + + test(d, "8286 84be 5808 6e6f 2d63 6163 6865", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com\n" + + "cache-control: no-cache"); + + test(d, "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" + + "0c63 7573 746f 6d2d 7661 6c75 65", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164", + + ":method: GET\n" + + ":scheme: https\n" + + ":path: /index.html\n" + + ":authority: www.example.com\n" + + "custom-key: custom-value"); + + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.4 + // + @Test + public void example6() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" + + "ff", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com"); + + test(d, "8286 84be 5886 a8eb 1064 9cbf", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com\n" + + "cache-control: no-cache"); + + test(d, "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" + + "a849 e95b b8e8 b4bf", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164", + + ":method: GET\n" + + ":scheme: https\n" + + ":path: /index.html\n" + + ":authority: www.example.com\n" + + "custom-key: custom-value"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.5 + // + @Test + public void example7() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "4803 3330 3258 0770 7269 7661 7465 611d\n" + + "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" + + "2032 303a 3133 3a32 3120 474d 546e 1768\n" + + "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" + + "6c65 2e63 6f6d", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222", + + ":status: 302\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "4803 3330 37c1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222", + + ":status: 307\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" + + "3230 3133 2032 303a 3133 3a32 3220 474d\n" + + "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" + + "444a 4b48 514b 425a 584f 5157 454f 5049\n" + + "5541 5851 5745 4f49 553b 206d 6178 2d61\n" + + "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" + + "3d31", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215", + + ":status: 200\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + "location: https://www.example.com\n" + + "content-encoding: gzip\n" + + "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.6 + // + @Test + public void example8() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" + + "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" + + "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" + + "e9ae 82ae 43d3", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222", + + ":status: 302\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "4883 640e ffc1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222", + + ":status: 307\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "88c1 6196 d07a be94 1054 d444 a820 0595\n" + + "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" + + "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" + + "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" + + "9587 3160 65c0 03ed 4ee5 b106 3d50 07", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215", + + ":status: 200\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + "location: https://www.example.com\n" + + "content-encoding: gzip\n" + + "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + // @formatter:on + } + + @Test + // One of responses from Apache Server that helped to catch a bug + public void testX() { + Decoder d = new Decoder(4096); + // @formatter:off + test(d, "3fe1 1f88 6196 d07a be94 03ea 693f 7504\n" + + "00b6 a05c b827 2e32 fa98 b46f 769e 86b1\n" + + "9272 b025 da5c 2ea9 fd70 a8de 7fb5 3556\n" + + "5ab7 6ece c057 02e2 2ad2 17bf 6c96 d07a\n" + + "be94 0854 cb6d 4a08 0075 40bd 71b6 6e05\n" + + "a531 68df 0f13 8efe 4522 cd32 21b6 5686\n" + + "eb23 781f cf52 848f d24a 8f0f 0d02 3435\n" + + "5f87 497c a589 d34d 1f", + + "[ 1] (s = 53) content-type: text/html\n" + + "[ 2] (s = 50) accept-ranges: bytes\n" + + "[ 3] (s = 74) last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" + + "[ 4] (s = 77) server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" + + "[ 5] (s = 65) date: Mon, 09 Nov 2015 16:26:39 GMT\n" + + " Table size: 319", + + ":status: 200\n" + + "date: Mon, 09 Nov 2015 16:26:39 GMT\n" + + "server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" + + "last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" + + "etag: \"2d-432a5e4a73a80\"\n" + + "accept-ranges: bytes\n" + + "content-length: 45\n" + + "content-type: text/html"); + // @formatter:on + } + + // + // This test is missing in the spec + // + @Test + public void sizeUpdate() { + Decoder d = new Decoder(4096); + assertEquals(d.getTable().maxSize(), 4096); + d.decode(ByteBuffer.wrap(new byte[]{0b00111110}), true, nopCallback()); // newSize = 30 + assertEquals(d.getTable().maxSize(), 30); + } + + @Test + public void incorrectSizeUpdate() { + ByteBuffer b = ByteBuffer.allocate(8); + Encoder e = new Encoder(8192) { + @Override + protected int calculateCapacity(int maxCapacity) { + return maxCapacity; + } + }; + e.header("a", "b"); + e.encode(b); + b.flip(); + { + Decoder d = new Decoder(4096); + UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(b, true, (name, value) -> { })); + + assertNotNull(ex.getCause()); + assertEquals(ex.getCause().getClass(), ProtocolException.class); + } + b.flip(); + { + Decoder d = new Decoder(4096); + UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(b, false, (name, value) -> { })); + + assertNotNull(ex.getCause()); + assertEquals(ex.getCause().getClass(), ProtocolException.class); + } + } + + @Test + public void corruptedHeaderBlockInteger() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + (byte) 0b10011010 // 25 + ... + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + // 5.1. Integer Representation + // ... + // Integer encodings that exceed implementation limits -- in value or octet + // length -- MUST be treated as decoding errors. Different limits can + // be set for each of the different uses of integers, based on + // implementation constraints. + @Test + public void headerBlockIntegerNoOverflow() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + 127 + // Integer.MAX_VALUE - 127 (base 128, little-endian): + (byte) 0b10000000, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b00000111 + }); + + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "index=2147483647"); + } + + @Test + public void headerBlockIntegerOverflow() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + 127 + // Integer.MAX_VALUE - 127 + 1 (base 128, little endian): + (byte) 0b10000001, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b00000111 + }); + + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Integer overflow"); + } + + @Test + public void corruptedHeaderBlockString1() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + 0b00001000, // huffman=false, length=8 + 0b00000000, // \ + 0b00000000, // but only 3 octets available... + 0b00000000 // / + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + @Test + public void corruptedHeaderBlockString2() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10001000, // huffman=true, length=8 + 0b00000000, // \ + 0b00000000, // \ + 0b00000000, // but only 5 octets available... + 0b00000000, // / + 0b00000000 // / + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + // 5.2. String Literal Representation + // ...A Huffman-encoded string literal containing the EOS symbol MUST be + // treated as a decoding error... + @Test + public void corruptedHeaderBlockHuffmanStringEOS() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000110, // huffman=true, length=6 + 0b00011001, 0b01001101, (byte) 0b11111111, + (byte) 0b11111111, (byte) 0b11111111, (byte) 0b11111100 + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Encountered EOS"); + } + + // 5.2. String Literal Representation + // ...A padding strictly longer than 7 bits MUST be treated as a decoding + // error... + @Test + public void corruptedHeaderBlockHuffmanStringLongPadding1() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01001101, (byte) 0b11111111 + // len("aei") + len(padding) = (5 + 5 + 5) + (9) + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Padding is too long", "len=9"); + } + + @Test + public void corruptedHeaderBlockHuffmanStringLongPadding2() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01111010, (byte) 0b11111111 + // len("aek") + len(padding) = (5 + 5 + 7) + (7) + }); + assertVoidDoesNotThrow(() -> d.decode(data, true, nopCallback())); + } + + // 5.2. String Literal Representation + // ...A padding not corresponding to the most significant bits of the code + // for the EOS symbol MUST be treated as a decoding error... + @Test + public void corruptedHeaderBlockHuffmanStringNotEOSPadding() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01111010, (byte) 0b11111110 + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Not a EOS prefix"); + } + + @Test + public void argsTestBiConsumerIsNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(ByteBuffer.allocate(16), true, null)); + } + + @Test + public void argsTestByteBufferIsNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(null, true, nopCallback())); + } + + @Test + public void argsTestBothAreNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(null, true, null)); + } + + private static void test(String hexdump, + String headerTable, String headerList) { + test(new Decoder(4096), hexdump, headerTable, headerList); + } + + // + // Sometimes we need to keep the same decoder along several runs, + // as it models the same connection + // + private static void test(Decoder d, String hexdump, + String expectedHeaderTable, String expectedHeaderList) { + + ByteBuffer source = SpecHelper.toBytes(hexdump); + + List actual = new LinkedList<>(); + d.decode(source, true, (name, value) -> { + if (value == null) { + actual.add(name.toString()); + } else { + actual.add(name + ": " + value); + } + }); + + assertEquals(d.getTable().getStateString(), expectedHeaderTable); + assertEquals(actual.stream().collect(Collectors.joining("\n")), expectedHeaderList); + } + + private static DecodingCallback nopCallback() { + return (t, u) -> { }; + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java new file mode 100644 index 00000000000..c7b375b1238 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import static java.util.Arrays.asList; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static sun.net.httpclient.hpack.SpecHelper.toHexdump; +import static sun.net.httpclient.hpack.TestHelper.assertVoidThrows; + +// TODO: map textual representation of commands from the spec to actual +// calls to encoder (actually, this is a good idea for decoder as well) +public final class EncoderTest { + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.1 + // + @Test + public void example1() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literalWithIndexing("custom-key", false, "custom-header", false); + // @formatter:off + test(e, + + "400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" + + "746f 6d2d 6865 6164 6572", + + "[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.2 + // + @Test + public void example2() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literal(4, "/sample/path", false); + // @formatter:off + test(e, + + "040c 2f73 616d 706c 652f 7061 7468", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.3 + // + @Test + public void example3() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literalNeverIndexed("password", false, "secret", false); + // @formatter:off + test(e, + + "1008 7061 7373 776f 7264 0673 6563 7265\n" + + "74", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.4 + // + @Test + public void example4() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.indexed(2); + // @formatter:off + test(e, + + "82", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.3 + // + @Test + public void example5() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(64); + e.indexed(2); + e.encode(output); + e.indexed(6); + e.encode(output); + e.indexed(4); + e.encode(output); + e.literalWithIndexing(1, "www.example.com", false); + e.encode(output); + + output.flip(); + + // @formatter:off + test(e, output, + + "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" + + "2e63 6f6d", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 6); + e.encode(output); + e.indexed( 4); + e.encode(output); + e.indexed(62); + e.encode(output); + e.literalWithIndexing(24, "no-cache", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "8286 84be 5808 6e6f 2d63 6163 6865", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 7); + e.encode(output); + e.indexed( 5); + e.encode(output); + e.indexed(63); + e.encode(output); + e.literalWithIndexing("custom-key", false, "custom-value", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" + + "0c63 7573 746f 6d2d 7661 6c75 65", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.4 + // + @Test + public void example6() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(64); + e.indexed(2); + e.encode(output); + e.indexed(6); + e.encode(output); + e.indexed(4); + e.encode(output); + e.literalWithIndexing(1, "www.example.com", true); + e.encode(output); + + output.flip(); + + // @formatter:off + test(e, output, + + "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" + + "ff", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 6); + e.encode(output); + e.indexed( 4); + e.encode(output); + e.indexed(62); + e.encode(output); + e.literalWithIndexing(24, "no-cache", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "8286 84be 5886 a8eb 1064 9cbf", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 7); + e.encode(output); + e.indexed( 5); + e.encode(output); + e.indexed(63); + e.encode(output); + e.literalWithIndexing("custom-key", true, "custom-value", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" + + "a849 e95b b8e8 b4bf", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.5 + // + @Test + public void example7() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(128); + // @formatter:off + e.literalWithIndexing( 8, "302", false); + e.encode(output); + e.literalWithIndexing(24, "private", false); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", false); + e.encode(output); + e.literalWithIndexing(46, "https://www.example.com", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "4803 3330 3258 0770 7269 7661 7465 611d\n" + + "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" + + "2032 303a 3133 3a32 3120 474d 546e 1768\n" + + "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" + + "6c65 2e63 6f6d", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222"); + + output.clear(); + + e.literalWithIndexing( 8, "307", false); + e.encode(output); + e.indexed(65); + e.encode(output); + e.indexed(64); + e.encode(output); + e.indexed(63); + e.encode(output); + + output.flip(); + + test(e, output, + + "4803 3330 37c1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222"); + + output.clear(); + + e.indexed( 8); + e.encode(output); + e.indexed(65); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", false); + e.encode(output); + e.indexed(64); + e.encode(output); + e.literalWithIndexing(26, "gzip", false); + e.encode(output); + e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" + + "3230 3133 2032 303a 3133 3a32 3220 474d\n" + + "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" + + "444a 4b48 514b 425a 584f 5157 454f 5049\n" + + "5541 5851 5745 4f49 553b 206d 6178 2d61\n" + + "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" + + "3d31", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.6 + // + @Test + public void example8() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(128); + // @formatter:off + e.literalWithIndexing( 8, "302", true); + e.encode(output); + e.literalWithIndexing(24, "private", true); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", true); + e.encode(output); + e.literalWithIndexing(46, "https://www.example.com", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" + + "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" + + "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" + + "e9ae 82ae 43d3", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222"); + + output.clear(); + + e.literalWithIndexing( 8, "307", true); + e.encode(output); + e.indexed(65); + e.encode(output); + e.indexed(64); + e.encode(output); + e.indexed(63); + e.encode(output); + + output.flip(); + + test(e, output, + + "4883 640e ffc1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222"); + + output.clear(); + + e.indexed( 8); + e.encode(output); + e.indexed(65); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", true); + e.encode(output); + e.indexed(64); + e.encode(output); + e.literalWithIndexing(26, "gzip", true); + e.encode(output); + e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "88c1 6196 d07a be94 1054 d444 a820 0595\n" + + "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" + + "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" + + "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" + + "9587 3160 65c0 03ed 4ee5 b106 3d50 07", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215"); + // @formatter:on + } + + @Test + public void initialSizeUpdateDefaultEncoder() { + Function e = Encoder::new; + testSizeUpdate(e, 1024, asList(), asList(0)); + testSizeUpdate(e, 1024, asList(1024), asList(0)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList(0)); + testSizeUpdate(e, 1024, asList(1024, 512), asList(0)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(0)); + testSizeUpdate(e, 1024, asList(512, 2048), asList(0)); + } + + @Test + public void initialSizeUpdateCustomEncoder() { + Function e = EncoderTest::newCustomEncoder; + testSizeUpdate(e, 1024, asList(), asList(1024)); + testSizeUpdate(e, 1024, asList(1024), asList(1024)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList(1024)); + testSizeUpdate(e, 1024, asList(1024, 512), asList(512)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(1024)); + testSizeUpdate(e, 1024, asList(512, 2048), asList(2048)); + } + + @Test + public void seriesOfSizeUpdatesDefaultEncoder() { + Function e = c -> { + Encoder encoder = new Encoder(c); + drainInitialUpdate(encoder); + return encoder; + }; + testSizeUpdate(e, 0, asList(0), asList()); + testSizeUpdate(e, 1024, asList(1024), asList()); + testSizeUpdate(e, 1024, asList(2048), asList()); + testSizeUpdate(e, 1024, asList(512), asList()); + testSizeUpdate(e, 1024, asList(1024, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 2048), asList()); + testSizeUpdate(e, 1024, asList(2048, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 512), asList()); + testSizeUpdate(e, 1024, asList(512, 1024), asList()); + } + + // + // https://tools.ietf.org/html/rfc7541#section-4.2 + // + @Test + public void seriesOfSizeUpdatesCustomEncoder() { + Function e = c -> { + Encoder encoder = newCustomEncoder(c); + drainInitialUpdate(encoder); + return encoder; + }; + testSizeUpdate(e, 0, asList(0), asList()); + testSizeUpdate(e, 1024, asList(1024), asList()); + testSizeUpdate(e, 1024, asList(2048), asList(2048)); + testSizeUpdate(e, 1024, asList(512), asList(512)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 2048), asList(2048)); + testSizeUpdate(e, 1024, asList(2048, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 512), asList(512)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(512, 1024)); + } + + @Test + public void callSequenceViolations() { + { // Hasn't set up a header + Encoder e = new Encoder(0); + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + { // Can't set up header while there's an unfinished encoding + Encoder e = new Encoder(0); + e.indexed(32); + assertVoidThrows(IllegalStateException.class, () -> e.indexed(32)); + } + { // Can't setMaxCapacity while there's an unfinished encoding + Encoder e = new Encoder(0); + e.indexed(32); + assertVoidThrows(IllegalStateException.class, () -> e.setMaxCapacity(512)); + } + { // Hasn't set up a header + Encoder e = new Encoder(0); + e.setMaxCapacity(256); + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + { // Hasn't set up a header after the previous encoding + Encoder e = new Encoder(0); + e.indexed(0); + boolean encoded = e.encode(ByteBuffer.allocate(16)); + assertTrue(encoded); // assumption + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + } + + private static void test(Encoder encoder, + String expectedTableState, + String expectedHexdump) { + + ByteBuffer b = ByteBuffer.allocate(128); + encoder.encode(b); + b.flip(); + test(encoder, b, expectedTableState, expectedHexdump); + } + + private static void test(Encoder encoder, + ByteBuffer output, + String expectedHexdump, + String expectedTableState) { + + String actualTableState = encoder.getHeaderTable().getStateString(); + assertEquals(actualTableState, expectedTableState); + + String actualHexdump = toHexdump(output); + assertEquals(actualHexdump, expectedHexdump.replaceAll("\\n", " ")); + } + + // initial size - the size encoder is constructed with + // updates - a sequence of values for consecutive calls to encoder.setMaxCapacity + // expected - a sequence of values expected to be decoded by a decoder + private void testSizeUpdate(Function encoder, + int initialSize, + List updates, + List expected) { + Encoder e = encoder.apply(initialSize); + updates.forEach(e::setMaxCapacity); + ByteBuffer b = ByteBuffer.allocate(64); + e.header("a", "b"); + e.encode(b); + b.flip(); + Decoder d = new Decoder(updates.isEmpty() ? initialSize : Collections.max(updates)); + List actual = new ArrayList<>(); + d.decode(b, true, new DecodingCallback() { + @Override + public void onDecoded(CharSequence name, CharSequence value) { } + + @Override + public void onSizeUpdate(int capacity) { + actual.add(capacity); + } + }); + assertEquals(actual, expected); + } + + // + // Default encoder does not need any table, therefore a subclass that + // behaves differently is needed + // + private static Encoder newCustomEncoder(int maxCapacity) { + return new Encoder(maxCapacity) { + @Override + protected int calculateCapacity(int maxCapacity) { + return maxCapacity; + } + }; + } + + private static void drainInitialUpdate(Encoder e) { + ByteBuffer b = ByteBuffer.allocate(4); + e.header("a", "b"); + boolean done; + do { + done = e.encode(b); + b.flip(); + } while (!done); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java new file mode 100644 index 00000000000..1bc12029ca6 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; +import sun.net.httpclient.hpack.HeaderTable.HeaderField; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.String.format; +import static org.testng.Assert.assertEquals; +import static sun.net.httpclient.hpack.TestHelper.*; + +public class HeaderTableTest { + + // + // https://tools.ietf.org/html/rfc7541#appendix-A + // + // @formatter:off + private static final String SPEC = + " | 1 | :authority | |\n" + + " | 2 | :method | GET |\n" + + " | 3 | :method | POST |\n" + + " | 4 | :path | / |\n" + + " | 5 | :path | /index.html |\n" + + " | 6 | :scheme | http |\n" + + " | 7 | :scheme | https |\n" + + " | 8 | :status | 200 |\n" + + " | 9 | :status | 204 |\n" + + " | 10 | :status | 206 |\n" + + " | 11 | :status | 304 |\n" + + " | 12 | :status | 400 |\n" + + " | 13 | :status | 404 |\n" + + " | 14 | :status | 500 |\n" + + " | 15 | accept-charset | |\n" + + " | 16 | accept-encoding | gzip, deflate |\n" + + " | 17 | accept-language | |\n" + + " | 18 | accept-ranges | |\n" + + " | 19 | accept | |\n" + + " | 20 | access-control-allow-origin | |\n" + + " | 21 | age | |\n" + + " | 22 | allow | |\n" + + " | 23 | authorization | |\n" + + " | 24 | cache-control | |\n" + + " | 25 | content-disposition | |\n" + + " | 26 | content-encoding | |\n" + + " | 27 | content-language | |\n" + + " | 28 | content-length | |\n" + + " | 29 | content-location | |\n" + + " | 30 | content-range | |\n" + + " | 31 | content-type | |\n" + + " | 32 | cookie | |\n" + + " | 33 | date | |\n" + + " | 34 | etag | |\n" + + " | 35 | expect | |\n" + + " | 36 | expires | |\n" + + " | 37 | from | |\n" + + " | 38 | host | |\n" + + " | 39 | if-match | |\n" + + " | 40 | if-modified-since | |\n" + + " | 41 | if-none-match | |\n" + + " | 42 | if-range | |\n" + + " | 43 | if-unmodified-since | |\n" + + " | 44 | last-modified | |\n" + + " | 45 | link | |\n" + + " | 46 | location | |\n" + + " | 47 | max-forwards | |\n" + + " | 48 | proxy-authenticate | |\n" + + " | 49 | proxy-authorization | |\n" + + " | 50 | range | |\n" + + " | 51 | referer | |\n" + + " | 52 | refresh | |\n" + + " | 53 | retry-after | |\n" + + " | 54 | server | |\n" + + " | 55 | set-cookie | |\n" + + " | 56 | strict-transport-security | |\n" + + " | 57 | transfer-encoding | |\n" + + " | 58 | user-agent | |\n" + + " | 59 | vary | |\n" + + " | 60 | via | |\n" + + " | 61 | www-authenticate | |\n"; + // @formatter:on + + private static final int STATIC_TABLE_LENGTH = createStaticEntries().size(); + private final Random rnd = newRandom(); + + @Test + public void staticData() { + HeaderTable table = new HeaderTable(0); + Map staticHeaderFields = createStaticEntries(); + + Map minimalIndexes = new HashMap<>(); + + for (Map.Entry e : staticHeaderFields.entrySet()) { + Integer idx = e.getKey(); + String hName = e.getValue().name; + Integer midx = minimalIndexes.get(hName); + if (midx == null) { + minimalIndexes.put(hName, idx); + } else { + minimalIndexes.put(hName, Math.min(idx, midx)); + } + } + + staticHeaderFields.entrySet().forEach( + e -> { + // lookup + HeaderField actualHeaderField = table.get(e.getKey()); + HeaderField expectedHeaderField = e.getValue(); + assertEquals(actualHeaderField, expectedHeaderField); + + // reverse lookup (name, value) + String hName = expectedHeaderField.name; + String hValue = expectedHeaderField.value; + int expectedIndex = e.getKey(); + int actualIndex = table.indexOf(hName, hValue); + + assertEquals(actualIndex, expectedIndex); + + // reverse lookup (name) + int expectedMinimalIndex = minimalIndexes.get(hName); + int actualMinimalIndex = table.indexOf(hName, "blah-blah"); + + assertEquals(-actualMinimalIndex, expectedMinimalIndex); + } + ); + } + + @Test + public void constructorSetsMaxSize() { + int size = rnd.nextInt(64); + HeaderTable t = new HeaderTable(size); + assertEquals(t.size(), 0); + assertEquals(t.maxSize(), size); + } + + @Test + public void negativeMaximumSize() { + int maxSize = -(rnd.nextInt(100) + 1); // [-100, -1] + IllegalArgumentException e = + assertVoidThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).setMaxSize(maxSize)); + assertExceptionMessageContains(e, "maxSize"); + } + + @Test + public void zeroMaximumSize() { + HeaderTable table = new HeaderTable(0); + table.setMaxSize(0); + assertEquals(table.maxSize(), 0); + } + + @Test + public void negativeIndex() { + int idx = -(rnd.nextInt(256) + 1); // [-256, -1] + IllegalArgumentException e = + assertVoidThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).get(idx)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void zeroIndex() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).get(0)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void length() { + HeaderTable table = new HeaderTable(0); + assertEquals(table.length(), STATIC_TABLE_LENGTH); + } + + @Test + public void indexOutsideStaticRange() { + HeaderTable table = new HeaderTable(0); + int idx = table.length() + (rnd.nextInt(256) + 1); + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, + () -> table.get(idx)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void entryPutAfterStaticArea() { + HeaderTable table = new HeaderTable(256); + int idx = table.length() + 1; + assertThrows(IllegalArgumentException.class, () -> table.get(idx)); + + byte[] bytes = new byte[32]; + rnd.nextBytes(bytes); + String name = new String(bytes, StandardCharsets.ISO_8859_1); + String value = "custom-value"; + + table.put(name, value); + HeaderField f = table.get(idx); + assertEquals(name, f.name); + assertEquals(value, f.value); + } + + @Test + public void staticTableHasZeroSize() { + HeaderTable table = new HeaderTable(0); + assertEquals(0, table.size()); + } + + @Test + public void lowerIndexPriority() { + HeaderTable table = new HeaderTable(256); + int oldLength = table.length(); + table.put("bender", "rodriguez"); + table.put("bender", "rodriguez"); + table.put("bender", "rodriguez"); + + assertEquals(table.length(), oldLength + 3); // more like an assumption + int i = table.indexOf("bender", "rodriguez"); + assertEquals(oldLength + 1, i); + } + + @Test + public void lowerIndexPriority2() { + HeaderTable table = new HeaderTable(256); + int oldLength = table.length(); + int idx = rnd.nextInt(oldLength) + 1; + HeaderField f = table.get(idx); + table.put(f.name, f.value); + assertEquals(table.length(), oldLength + 1); + int i = table.indexOf(f.name, f.value); + assertEquals(idx, i); + } + + // TODO: negative indexes check + // TODO: ensure full table clearance when adding huge header field + // TODO: ensure eviction deletes minimum needed entries, not more + + @Test + public void fifo() { + HeaderTable t = new HeaderTable(Integer.MAX_VALUE); + // Let's add a series of header fields + int NUM_HEADERS = 32; + for (int i = 1; i <= NUM_HEADERS; i++) { + String s = String.valueOf(i); + t.put(s, s); + } + // They MUST appear in a FIFO order: + // newer entries are at lower indexes + // older entries are at higher indexes + for (int j = 1; j <= NUM_HEADERS; j++) { + HeaderField f = t.get(STATIC_TABLE_LENGTH + j); + int actualName = Integer.parseInt(f.name); + int expectedName = NUM_HEADERS - j + 1; + assertEquals(expectedName, actualName); + } + // Entries MUST be evicted in the order they were added: + // the newer the entry the later it is evicted + for (int k = 1; k <= NUM_HEADERS; k++) { + HeaderField f = t.evictEntry(); + assertEquals(String.valueOf(k), f.name); + } + } + + @Test + public void indexOf() { + HeaderTable t = new HeaderTable(Integer.MAX_VALUE); + // Let's put a series of header fields + int NUM_HEADERS = 32; + for (int i = 1; i <= NUM_HEADERS; i++) { + String s = String.valueOf(i); + t.put(s, s); + } + // and verify indexOf (reverse lookup) returns correct indexes for + // full lookup + for (int j = 1; j <= NUM_HEADERS; j++) { + String s = String.valueOf(j); + int actualIndex = t.indexOf(s, s); + int expectedIndex = STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1; + assertEquals(expectedIndex, actualIndex); + } + // as well as for just a name lookup + for (int j = 1; j <= NUM_HEADERS; j++) { + String s = String.valueOf(j); + int actualIndex = t.indexOf(s, "blah"); + int expectedIndex = -(STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1); + assertEquals(expectedIndex, actualIndex); + } + // lookup for non-existent name returns 0 + assertEquals(0, t.indexOf("chupacabra", "1")); + } + + @Test + public void testToString() { + HeaderTable table = new HeaderTable(0); + { + table.setMaxSize(2048); + assertEquals("entries: 0; used 0/2048 (0.0%)", table.toString()); + } + + { + String name = "custom-name"; + String value = "custom-value"; + int size = 512; + + table.setMaxSize(size); + table.put(name, value); + String s = table.toString(); + + int used = name.length() + value.length() + 32; + double ratio = used * 100.0 / size; + + String expected = format("entries: 1; used %s/%s (%.1f%%)", used, size, ratio); + assertEquals(expected, s); + } + + { + table.setMaxSize(78); + table.put(":method", ""); + table.put(":status", ""); + String s = table.toString(); + assertEquals("entries: 2; used 78/78 (100.0%)", s); + } + } + + @Test + public void stateString() { + HeaderTable table = new HeaderTable(256); + table.put("custom-key", "custom-header"); + // @formatter:off + assertEquals("[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55", table.getStateString()); + // @formatter:on + } + + private static Map createStaticEntries() { + Pattern line = Pattern.compile( + "\\|\\s*(?\\d+?)\\s*\\|\\s*(?.+?)\\s*\\|\\s*(?.*?)\\s*\\|"); + Matcher m = line.matcher(SPEC); + Map result = new HashMap<>(); + while (m.find()) { + int index = Integer.parseInt(m.group("index")); + String name = m.group("name"); + String value = m.group("value"); + HeaderField f = new HeaderField(name, value); + result.put(index, f); + } + return Collections.unmodifiableMap(result); // lol + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java new file mode 100644 index 00000000000..502c7051a79 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.Integer.parseInt; +import static org.testng.Assert.*; + +public final class HuffmanTest { + + // + // https://tools.ietf.org/html/rfc7541#appendix-B + // + private static final String SPEC = + // @formatter:off + " code as bits as hex len\n" + + " sym aligned to MSB aligned in\n" + + " to LSB bits\n" + + " ( 0) |11111111|11000 1ff8 [13]\n" + + " ( 1) |11111111|11111111|1011000 7fffd8 [23]\n" + + " ( 2) |11111111|11111111|11111110|0010 fffffe2 [28]\n" + + " ( 3) |11111111|11111111|11111110|0011 fffffe3 [28]\n" + + " ( 4) |11111111|11111111|11111110|0100 fffffe4 [28]\n" + + " ( 5) |11111111|11111111|11111110|0101 fffffe5 [28]\n" + + " ( 6) |11111111|11111111|11111110|0110 fffffe6 [28]\n" + + " ( 7) |11111111|11111111|11111110|0111 fffffe7 [28]\n" + + " ( 8) |11111111|11111111|11111110|1000 fffffe8 [28]\n" + + " ( 9) |11111111|11111111|11101010 ffffea [24]\n" + + " ( 10) |11111111|11111111|11111111|111100 3ffffffc [30]\n" + + " ( 11) |11111111|11111111|11111110|1001 fffffe9 [28]\n" + + " ( 12) |11111111|11111111|11111110|1010 fffffea [28]\n" + + " ( 13) |11111111|11111111|11111111|111101 3ffffffd [30]\n" + + " ( 14) |11111111|11111111|11111110|1011 fffffeb [28]\n" + + " ( 15) |11111111|11111111|11111110|1100 fffffec [28]\n" + + " ( 16) |11111111|11111111|11111110|1101 fffffed [28]\n" + + " ( 17) |11111111|11111111|11111110|1110 fffffee [28]\n" + + " ( 18) |11111111|11111111|11111110|1111 fffffef [28]\n" + + " ( 19) |11111111|11111111|11111111|0000 ffffff0 [28]\n" + + " ( 20) |11111111|11111111|11111111|0001 ffffff1 [28]\n" + + " ( 21) |11111111|11111111|11111111|0010 ffffff2 [28]\n" + + " ( 22) |11111111|11111111|11111111|111110 3ffffffe [30]\n" + + " ( 23) |11111111|11111111|11111111|0011 ffffff3 [28]\n" + + " ( 24) |11111111|11111111|11111111|0100 ffffff4 [28]\n" + + " ( 25) |11111111|11111111|11111111|0101 ffffff5 [28]\n" + + " ( 26) |11111111|11111111|11111111|0110 ffffff6 [28]\n" + + " ( 27) |11111111|11111111|11111111|0111 ffffff7 [28]\n" + + " ( 28) |11111111|11111111|11111111|1000 ffffff8 [28]\n" + + " ( 29) |11111111|11111111|11111111|1001 ffffff9 [28]\n" + + " ( 30) |11111111|11111111|11111111|1010 ffffffa [28]\n" + + " ( 31) |11111111|11111111|11111111|1011 ffffffb [28]\n" + + " ' ' ( 32) |010100 14 [ 6]\n" + + " '!' ( 33) |11111110|00 3f8 [10]\n" + + " '\"' ( 34) |11111110|01 3f9 [10]\n" + + " '#' ( 35) |11111111|1010 ffa [12]\n" + + " '$' ( 36) |11111111|11001 1ff9 [13]\n" + + " '%' ( 37) |010101 15 [ 6]\n" + + " '&' ( 38) |11111000 f8 [ 8]\n" + + " ''' ( 39) |11111111|010 7fa [11]\n" + + " '(' ( 40) |11111110|10 3fa [10]\n" + + " ')' ( 41) |11111110|11 3fb [10]\n" + + " '*' ( 42) |11111001 f9 [ 8]\n" + + " '+' ( 43) |11111111|011 7fb [11]\n" + + " ',' ( 44) |11111010 fa [ 8]\n" + + " '-' ( 45) |010110 16 [ 6]\n" + + " '.' ( 46) |010111 17 [ 6]\n" + + " '/' ( 47) |011000 18 [ 6]\n" + + " '0' ( 48) |00000 0 [ 5]\n" + + " '1' ( 49) |00001 1 [ 5]\n" + + " '2' ( 50) |00010 2 [ 5]\n" + + " '3' ( 51) |011001 19 [ 6]\n" + + " '4' ( 52) |011010 1a [ 6]\n" + + " '5' ( 53) |011011 1b [ 6]\n" + + " '6' ( 54) |011100 1c [ 6]\n" + + " '7' ( 55) |011101 1d [ 6]\n" + + " '8' ( 56) |011110 1e [ 6]\n" + + " '9' ( 57) |011111 1f [ 6]\n" + + " ':' ( 58) |1011100 5c [ 7]\n" + + " ';' ( 59) |11111011 fb [ 8]\n" + + " '<' ( 60) |11111111|1111100 7ffc [15]\n" + + " '=' ( 61) |100000 20 [ 6]\n" + + " '>' ( 62) |11111111|1011 ffb [12]\n" + + " '?' ( 63) |11111111|00 3fc [10]\n" + + " '@' ( 64) |11111111|11010 1ffa [13]\n" + + " 'A' ( 65) |100001 21 [ 6]\n" + + " 'B' ( 66) |1011101 5d [ 7]\n" + + " 'C' ( 67) |1011110 5e [ 7]\n" + + " 'D' ( 68) |1011111 5f [ 7]\n" + + " 'E' ( 69) |1100000 60 [ 7]\n" + + " 'F' ( 70) |1100001 61 [ 7]\n" + + " 'G' ( 71) |1100010 62 [ 7]\n" + + " 'H' ( 72) |1100011 63 [ 7]\n" + + " 'I' ( 73) |1100100 64 [ 7]\n" + + " 'J' ( 74) |1100101 65 [ 7]\n" + + " 'K' ( 75) |1100110 66 [ 7]\n" + + " 'L' ( 76) |1100111 67 [ 7]\n" + + " 'M' ( 77) |1101000 68 [ 7]\n" + + " 'N' ( 78) |1101001 69 [ 7]\n" + + " 'O' ( 79) |1101010 6a [ 7]\n" + + " 'P' ( 80) |1101011 6b [ 7]\n" + + " 'Q' ( 81) |1101100 6c [ 7]\n" + + " 'R' ( 82) |1101101 6d [ 7]\n" + + " 'S' ( 83) |1101110 6e [ 7]\n" + + " 'T' ( 84) |1101111 6f [ 7]\n" + + " 'U' ( 85) |1110000 70 [ 7]\n" + + " 'V' ( 86) |1110001 71 [ 7]\n" + + " 'W' ( 87) |1110010 72 [ 7]\n" + + " 'X' ( 88) |11111100 fc [ 8]\n" + + " 'Y' ( 89) |1110011 73 [ 7]\n" + + " 'Z' ( 90) |11111101 fd [ 8]\n" + + " '[' ( 91) |11111111|11011 1ffb [13]\n" + + " '\\' ( 92) |11111111|11111110|000 7fff0 [19]\n" + + " ']' ( 93) |11111111|11100 1ffc [13]\n" + + " '^' ( 94) |11111111|111100 3ffc [14]\n" + + " '_' ( 95) |100010 22 [ 6]\n" + + " '`' ( 96) |11111111|1111101 7ffd [15]\n" + + " 'a' ( 97) |00011 3 [ 5]\n" + + " 'b' ( 98) |100011 23 [ 6]\n" + + " 'c' ( 99) |00100 4 [ 5]\n" + + " 'd' (100) |100100 24 [ 6]\n" + + " 'e' (101) |00101 5 [ 5]\n" + + " 'f' (102) |100101 25 [ 6]\n" + + " 'g' (103) |100110 26 [ 6]\n" + + " 'h' (104) |100111 27 [ 6]\n" + + " 'i' (105) |00110 6 [ 5]\n" + + " 'j' (106) |1110100 74 [ 7]\n" + + " 'k' (107) |1110101 75 [ 7]\n" + + " 'l' (108) |101000 28 [ 6]\n" + + " 'm' (109) |101001 29 [ 6]\n" + + " 'n' (110) |101010 2a [ 6]\n" + + " 'o' (111) |00111 7 [ 5]\n" + + " 'p' (112) |101011 2b [ 6]\n" + + " 'q' (113) |1110110 76 [ 7]\n" + + " 'r' (114) |101100 2c [ 6]\n" + + " 's' (115) |01000 8 [ 5]\n" + + " 't' (116) |01001 9 [ 5]\n" + + " 'u' (117) |101101 2d [ 6]\n" + + " 'v' (118) |1110111 77 [ 7]\n" + + " 'w' (119) |1111000 78 [ 7]\n" + + " 'x' (120) |1111001 79 [ 7]\n" + + " 'y' (121) |1111010 7a [ 7]\n" + + " 'z' (122) |1111011 7b [ 7]\n" + + " '{' (123) |11111111|1111110 7ffe [15]\n" + + " '|' (124) |11111111|100 7fc [11]\n" + + " '}' (125) |11111111|111101 3ffd [14]\n" + + " '~' (126) |11111111|11101 1ffd [13]\n" + + " (127) |11111111|11111111|11111111|1100 ffffffc [28]\n" + + " (128) |11111111|11111110|0110 fffe6 [20]\n" + + " (129) |11111111|11111111|010010 3fffd2 [22]\n" + + " (130) |11111111|11111110|0111 fffe7 [20]\n" + + " (131) |11111111|11111110|1000 fffe8 [20]\n" + + " (132) |11111111|11111111|010011 3fffd3 [22]\n" + + " (133) |11111111|11111111|010100 3fffd4 [22]\n" + + " (134) |11111111|11111111|010101 3fffd5 [22]\n" + + " (135) |11111111|11111111|1011001 7fffd9 [23]\n" + + " (136) |11111111|11111111|010110 3fffd6 [22]\n" + + " (137) |11111111|11111111|1011010 7fffda [23]\n" + + " (138) |11111111|11111111|1011011 7fffdb [23]\n" + + " (139) |11111111|11111111|1011100 7fffdc [23]\n" + + " (140) |11111111|11111111|1011101 7fffdd [23]\n" + + " (141) |11111111|11111111|1011110 7fffde [23]\n" + + " (142) |11111111|11111111|11101011 ffffeb [24]\n" + + " (143) |11111111|11111111|1011111 7fffdf [23]\n" + + " (144) |11111111|11111111|11101100 ffffec [24]\n" + + " (145) |11111111|11111111|11101101 ffffed [24]\n" + + " (146) |11111111|11111111|010111 3fffd7 [22]\n" + + " (147) |11111111|11111111|1100000 7fffe0 [23]\n" + + " (148) |11111111|11111111|11101110 ffffee [24]\n" + + " (149) |11111111|11111111|1100001 7fffe1 [23]\n" + + " (150) |11111111|11111111|1100010 7fffe2 [23]\n" + + " (151) |11111111|11111111|1100011 7fffe3 [23]\n" + + " (152) |11111111|11111111|1100100 7fffe4 [23]\n" + + " (153) |11111111|11111110|11100 1fffdc [21]\n" + + " (154) |11111111|11111111|011000 3fffd8 [22]\n" + + " (155) |11111111|11111111|1100101 7fffe5 [23]\n" + + " (156) |11111111|11111111|011001 3fffd9 [22]\n" + + " (157) |11111111|11111111|1100110 7fffe6 [23]\n" + + " (158) |11111111|11111111|1100111 7fffe7 [23]\n" + + " (159) |11111111|11111111|11101111 ffffef [24]\n" + + " (160) |11111111|11111111|011010 3fffda [22]\n" + + " (161) |11111111|11111110|11101 1fffdd [21]\n" + + " (162) |11111111|11111110|1001 fffe9 [20]\n" + + " (163) |11111111|11111111|011011 3fffdb [22]\n" + + " (164) |11111111|11111111|011100 3fffdc [22]\n" + + " (165) |11111111|11111111|1101000 7fffe8 [23]\n" + + " (166) |11111111|11111111|1101001 7fffe9 [23]\n" + + " (167) |11111111|11111110|11110 1fffde [21]\n" + + " (168) |11111111|11111111|1101010 7fffea [23]\n" + + " (169) |11111111|11111111|011101 3fffdd [22]\n" + + " (170) |11111111|11111111|011110 3fffde [22]\n" + + " (171) |11111111|11111111|11110000 fffff0 [24]\n" + + " (172) |11111111|11111110|11111 1fffdf [21]\n" + + " (173) |11111111|11111111|011111 3fffdf [22]\n" + + " (174) |11111111|11111111|1101011 7fffeb [23]\n" + + " (175) |11111111|11111111|1101100 7fffec [23]\n" + + " (176) |11111111|11111111|00000 1fffe0 [21]\n" + + " (177) |11111111|11111111|00001 1fffe1 [21]\n" + + " (178) |11111111|11111111|100000 3fffe0 [22]\n" + + " (179) |11111111|11111111|00010 1fffe2 [21]\n" + + " (180) |11111111|11111111|1101101 7fffed [23]\n" + + " (181) |11111111|11111111|100001 3fffe1 [22]\n" + + " (182) |11111111|11111111|1101110 7fffee [23]\n" + + " (183) |11111111|11111111|1101111 7fffef [23]\n" + + " (184) |11111111|11111110|1010 fffea [20]\n" + + " (185) |11111111|11111111|100010 3fffe2 [22]\n" + + " (186) |11111111|11111111|100011 3fffe3 [22]\n" + + " (187) |11111111|11111111|100100 3fffe4 [22]\n" + + " (188) |11111111|11111111|1110000 7ffff0 [23]\n" + + " (189) |11111111|11111111|100101 3fffe5 [22]\n" + + " (190) |11111111|11111111|100110 3fffe6 [22]\n" + + " (191) |11111111|11111111|1110001 7ffff1 [23]\n" + + " (192) |11111111|11111111|11111000|00 3ffffe0 [26]\n" + + " (193) |11111111|11111111|11111000|01 3ffffe1 [26]\n" + + " (194) |11111111|11111110|1011 fffeb [20]\n" + + " (195) |11111111|11111110|001 7fff1 [19]\n" + + " (196) |11111111|11111111|100111 3fffe7 [22]\n" + + " (197) |11111111|11111111|1110010 7ffff2 [23]\n" + + " (198) |11111111|11111111|101000 3fffe8 [22]\n" + + " (199) |11111111|11111111|11110110|0 1ffffec [25]\n" + + " (200) |11111111|11111111|11111000|10 3ffffe2 [26]\n" + + " (201) |11111111|11111111|11111000|11 3ffffe3 [26]\n" + + " (202) |11111111|11111111|11111001|00 3ffffe4 [26]\n" + + " (203) |11111111|11111111|11111011|110 7ffffde [27]\n" + + " (204) |11111111|11111111|11111011|111 7ffffdf [27]\n" + + " (205) |11111111|11111111|11111001|01 3ffffe5 [26]\n" + + " (206) |11111111|11111111|11110001 fffff1 [24]\n" + + " (207) |11111111|11111111|11110110|1 1ffffed [25]\n" + + " (208) |11111111|11111110|010 7fff2 [19]\n" + + " (209) |11111111|11111111|00011 1fffe3 [21]\n" + + " (210) |11111111|11111111|11111001|10 3ffffe6 [26]\n" + + " (211) |11111111|11111111|11111100|000 7ffffe0 [27]\n" + + " (212) |11111111|11111111|11111100|001 7ffffe1 [27]\n" + + " (213) |11111111|11111111|11111001|11 3ffffe7 [26]\n" + + " (214) |11111111|11111111|11111100|010 7ffffe2 [27]\n" + + " (215) |11111111|11111111|11110010 fffff2 [24]\n" + + " (216) |11111111|11111111|00100 1fffe4 [21]\n" + + " (217) |11111111|11111111|00101 1fffe5 [21]\n" + + " (218) |11111111|11111111|11111010|00 3ffffe8 [26]\n" + + " (219) |11111111|11111111|11111010|01 3ffffe9 [26]\n" + + " (220) |11111111|11111111|11111111|1101 ffffffd [28]\n" + + " (221) |11111111|11111111|11111100|011 7ffffe3 [27]\n" + + " (222) |11111111|11111111|11111100|100 7ffffe4 [27]\n" + + " (223) |11111111|11111111|11111100|101 7ffffe5 [27]\n" + + " (224) |11111111|11111110|1100 fffec [20]\n" + + " (225) |11111111|11111111|11110011 fffff3 [24]\n" + + " (226) |11111111|11111110|1101 fffed [20]\n" + + " (227) |11111111|11111111|00110 1fffe6 [21]\n" + + " (228) |11111111|11111111|101001 3fffe9 [22]\n" + + " (229) |11111111|11111111|00111 1fffe7 [21]\n" + + " (230) |11111111|11111111|01000 1fffe8 [21]\n" + + " (231) |11111111|11111111|1110011 7ffff3 [23]\n" + + " (232) |11111111|11111111|101010 3fffea [22]\n" + + " (233) |11111111|11111111|101011 3fffeb [22]\n" + + " (234) |11111111|11111111|11110111|0 1ffffee [25]\n" + + " (235) |11111111|11111111|11110111|1 1ffffef [25]\n" + + " (236) |11111111|11111111|11110100 fffff4 [24]\n" + + " (237) |11111111|11111111|11110101 fffff5 [24]\n" + + " (238) |11111111|11111111|11111010|10 3ffffea [26]\n" + + " (239) |11111111|11111111|1110100 7ffff4 [23]\n" + + " (240) |11111111|11111111|11111010|11 3ffffeb [26]\n" + + " (241) |11111111|11111111|11111100|110 7ffffe6 [27]\n" + + " (242) |11111111|11111111|11111011|00 3ffffec [26]\n" + + " (243) |11111111|11111111|11111011|01 3ffffed [26]\n" + + " (244) |11111111|11111111|11111100|111 7ffffe7 [27]\n" + + " (245) |11111111|11111111|11111101|000 7ffffe8 [27]\n" + + " (246) |11111111|11111111|11111101|001 7ffffe9 [27]\n" + + " (247) |11111111|11111111|11111101|010 7ffffea [27]\n" + + " (248) |11111111|11111111|11111101|011 7ffffeb [27]\n" + + " (249) |11111111|11111111|11111111|1110 ffffffe [28]\n" + + " (250) |11111111|11111111|11111101|100 7ffffec [27]\n" + + " (251) |11111111|11111111|11111101|101 7ffffed [27]\n" + + " (252) |11111111|11111111|11111101|110 7ffffee [27]\n" + + " (253) |11111111|11111111|11111101|111 7ffffef [27]\n" + + " (254) |11111111|11111111|11111110|000 7fffff0 [27]\n" + + " (255) |11111111|11111111|11111011|10 3ffffee [26]\n" + + " EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]"; + // @formatter:on + + @Test + public void read_table() { + Pattern line = Pattern.compile( + "\\(\\s*(?\\d+)\\s*\\)\\s*(?(\\|(0|1)+)+)\\s*" + + "(?[0-9a-zA-Z]+)\\s*\\[\\s*(?\\d+)\\s*\\]"); + Matcher m = line.matcher(SPEC); + int i = 0; + while (m.find()) { + String ascii = m.group("ascii"); + String binary = m.group("binary").replaceAll("\\|", ""); + String hex = m.group("hex"); + String len = m.group("len"); + + // Several sanity checks for the data read from the table, just to + // make sure what we read makes sense + assertEquals(parseInt(len), binary.length()); + assertEquals(parseInt(binary, 2), parseInt(hex, 16)); + + int expected = parseInt(ascii); + + // TODO: find actual eos, do not hardcode it! + byte[] bytes = intToBytes(0x3fffffff, 30, + parseInt(hex, 16), parseInt(len)); + + StringBuilder actual = new StringBuilder(); + Huffman.Reader t = new Huffman.Reader(); + t.read(ByteBuffer.wrap(bytes), actual, false, true); + + // What has been read MUST represent a single symbol + assertEquals(actual.length(), 1, "ascii: " + ascii); + + // It's a lot more visual to compare char as codes rather than + // characters (as some of them might not be visible) + assertEquals(actual.charAt(0), expected); + i++; + } + assertEquals(i, 257); // 256 + EOS + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.1 + // + @Test + public void read_1() { + read("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"); + } + + @Test + public void write_1() { + write("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.2 + // + @Test + public void read_2() { + read("a8eb 1064 9cbf", "no-cache"); + } + + @Test + public void write_2() { + write("no-cache", "a8eb 1064 9cbf"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.3 + // + @Test + public void read_3() { + read("25a8 49e9 5ba9 7d7f", "custom-key"); + } + + @Test + public void write_3() { + write("custom-key", "25a8 49e9 5ba9 7d7f"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.3 + // + @Test + public void read_4() { + read("25a8 49e9 5bb8 e8b4 bf", "custom-value"); + } + + @Test + public void write_4() { + write("custom-value", "25a8 49e9 5bb8 e8b4 bf"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_5() { + read("6402", "302"); + } + + @Test + public void write_5() { + write("302", "6402"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_6() { + read("aec3 771a 4b", "private"); + } + + @Test + public void write_6() { + write("private", "aec3 771a 4b"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_7() { + read("d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", + "Mon, 21 Oct 2013 20:13:21 GMT"); + } + + @Test + public void write_7() { + write("Mon, 21 Oct 2013 20:13:21 GMT", + "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_8() { + read("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", + "https://www.example.com"); + } + + @Test + public void write_8() { + write("https://www.example.com", + "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.2 + // + @Test + public void read_9() { + read("640e ff", "307"); + } + + @Test + public void write_9() { + write("307", "640e ff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_10() { + read("d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff", + "Mon, 21 Oct 2013 20:13:22 GMT"); + } + + @Test + public void write_10() { + write("Mon, 21 Oct 2013 20:13:22 GMT", + "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_11() { + read("9bd9 ab", "gzip"); + } + + @Test + public void write_11() { + write("gzip", "9bd9 ab"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_12() { + read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 " + + "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 " + + "3160 65c0 03ed 4ee5 b106 3d50 07", + "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + } + + @Test + public void test_trie_has_no_empty_nodes() { + Huffman.Node root = Huffman.INSTANCE.getRoot(); + Stack backlog = new Stack<>(); + backlog.push(root); + while (!backlog.isEmpty()) { + Huffman.Node n = backlog.pop(); + // The only type of nodes we couldn't possibly catch during + // construction is an empty node: no children and no char + if (n.left != null) { + backlog.push(n.left); + } + if (n.right != null) { + backlog.push(n.right); + } + assertFalse(!n.charIsSet && n.left == null && n.right == null, + "Empty node in the trie"); + } + } + + @Test + public void test_trie_has_257_nodes() { + int count = 0; + Huffman.Node root = Huffman.INSTANCE.getRoot(); + Stack backlog = new Stack<>(); + backlog.push(root); + while (!backlog.isEmpty()) { + Huffman.Node n = backlog.pop(); + if (n.left != null) { + backlog.push(n.left); + } + if (n.right != null) { + backlog.push(n.right); + } + if (n.isLeaf()) { + count++; + } + } + assertEquals(count, 257); + } + + @Test + public void cant_encode_outside_byte() { + TestHelper.Block coding = + () -> new Huffman.Writer() + .from(((char) 256) + "", 0, 1) + .write(ByteBuffer.allocate(1)); + RuntimeException e = + TestHelper.assertVoidThrows(RuntimeException.class, coding); + TestHelper.assertExceptionMessageContains(e, "char"); + } + + private static void read(String hexdump, String decoded) { + ByteBuffer source = SpecHelper.toBytes(hexdump); + Appendable actual = new StringBuilder(); + new Huffman.Reader().read(source, actual, true); + assertEquals(actual.toString(), decoded); + } + + private static void write(String decoded, String hexdump) { + int n = Huffman.INSTANCE.lengthOf(decoded); + ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok + Huffman.Writer writer = new Huffman.Writer(); + BuffersTestingKit.forEachSplit(destination, byteBuffers -> { + writer.from(decoded, 0, decoded.length()); + boolean written = false; + for (ByteBuffer b : byteBuffers) { + int pos = b.position(); + written = writer.write(b); + b.position(pos); + } + assertTrue(written); + ByteBuffer concated = BuffersTestingKit.concat(byteBuffers); + String actual = SpecHelper.toHexdump(concated); + assertEquals(actual, hexdump); + writer.reset(); + }); + } + + // + // It's not very pretty, yes I know that + // + // hex: + // + // |31|30|...|N-1|...|01|00| + // \ / + // codeLength + // + // hex <<= 32 - codeLength; (align to MSB): + // + // |31|30|...|32-N|...|01|00| + // \ / + // codeLength + // + // EOS: + // + // |31|30|...|M-1|...|01|00| + // \ / + // eosLength + // + // eos <<= 32 - eosLength; (align to MSB): + // + // pad with MSBs of EOS: + // + // |31|30|...|32-N|32-N-1|...|01|00| + // | 32|...| + // + // Finally, split into byte[] + // + private byte[] intToBytes(int eos, int eosLength, int hex, int codeLength) { + hex <<= 32 - codeLength; + eos >>= codeLength - (32 - eosLength); + hex |= eos; + int n = (int) Math.ceil(codeLength / 8.0); + byte[] result = new byte[n]; + for (int i = 0; i < n; i++) { + result[i] = (byte) (hex >> (32 - 8 * (i + 1))); + } + return result; + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java new file mode 100644 index 00000000000..88bd906514e --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java @@ -0,0 +1,70 @@ +/* + * 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. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// +// THIS IS NOT A TEST +// +public final class SpecHelper { + + private SpecHelper() { + throw new AssertionError(); + } + + public static ByteBuffer toBytes(String hexdump) { + Pattern hexByte = Pattern.compile("[0-9a-fA-F]{2}"); + List bytes = new ArrayList<>(); + Matcher matcher = hexByte.matcher(hexdump); + while (matcher.find()) { + bytes.add(matcher.group(0)); + } + ByteBuffer result = ByteBuffer.allocate(bytes.size()); + for (String f : bytes) { + result.put((byte) Integer.parseInt(f, 16)); + } + result.flip(); + return result; + } + + public static String toHexdump(ByteBuffer bb) { + List words = new ArrayList<>(); + int i = 0; + while (bb.hasRemaining()) { + if (i % 2 == 0) { + words.add(""); + } + byte b = bb.get(); + String hex = Integer.toHexString(256 + Byte.toUnsignedInt(b)).substring(1); + words.set(i / 2, words.get(i / 2) + hex); + i++; + } + return words.stream().collect(Collectors.joining(" ")); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java new file mode 100644 index 00000000000..b042b5f4cee --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.util.Objects; +import java.util.Random; + +public final class TestHelper { + + public static Random newRandom() { + long seed = Long.getLong("jdk.test.lib.random.seed", System.currentTimeMillis()); + System.out.println("new java.util.Random(" + seed + ")"); + return new Random(seed); + } + + public static T assertVoidThrows(Class clazz, Block code) { + return assertThrows(clazz, () -> { + code.run(); + return null; + }); + } + + public static T assertThrows(Class clazz, ReturningBlock code) { + Objects.requireNonNull(clazz, "clazz == null"); + Objects.requireNonNull(code, "code == null"); + try { + code.run(); + } catch (Throwable t) { + if (clazz.isInstance(t)) { + return clazz.cast(t); + } + throw new AssertionError("Expected to catch exception of type " + + clazz.getCanonicalName() + ", instead caught " + + t.getClass().getCanonicalName(), t); + + } + throw new AssertionError( + "Expected to catch exception of type " + clazz.getCanonicalName() + + ", but caught nothing"); + } + + public static T assertDoesNotThrow(ReturningBlock code) { + Objects.requireNonNull(code, "code == null"); + try { + return code.run(); + } catch (Throwable t) { + throw new AssertionError( + "Expected code block to exit normally, instead " + + "caught " + t.getClass().getCanonicalName(), t); + } + } + + public static void assertVoidDoesNotThrow(Block code) { + Objects.requireNonNull(code, "code == null"); + try { + code.run(); + } catch (Throwable t) { + throw new AssertionError( + "Expected code block to exit normally, instead " + + "caught " + t.getClass().getCanonicalName(), t); + } + } + + + public static void assertExceptionMessageContains(Throwable t, + CharSequence firstSubsequence, + CharSequence... others) { + assertCharSequenceContains(t.getMessage(), firstSubsequence, others); + } + + public static void assertCharSequenceContains(CharSequence s, + CharSequence firstSubsequence, + CharSequence... others) { + if (s == null) { + throw new NullPointerException("Exception message is null"); + } + String str = s.toString(); + String missing = null; + if (!str.contains(firstSubsequence.toString())) { + missing = firstSubsequence.toString(); + } else { + for (CharSequence o : others) { + if (!str.contains(o.toString())) { + missing = o.toString(); + break; + } + } + } + if (missing != null) { + throw new AssertionError("CharSequence '" + s + "'" + " does not " + + "contain subsequence '" + missing + "'"); + } + } + + public interface ReturningBlock { + T run() throws Throwable; + } + + public interface Block { + void run() throws Throwable; + } + + // tests + + @Test + public void assertThrows() { + assertThrows(NullPointerException.class, () -> ((Object) null).toString()); + } + + @Test + public void assertThrowsWrongType() { + try { + assertThrows(IllegalArgumentException.class, () -> ((Object) null).toString()); + } catch (AssertionError e) { + Throwable cause = e.getCause(); + String message = e.getMessage(); + if (cause != null + && cause instanceof NullPointerException + && message != null + && message.contains("instead caught")) { + return; + } + } + throw new AssertionError(); + } + + @Test + public void assertThrowsNoneCaught() { + try { + assertThrows(IllegalArgumentException.class, () -> null); + } catch (AssertionError e) { + Throwable cause = e.getCause(); + String message = e.getMessage(); + if (cause == null + && message != null + && message.contains("but caught nothing")) { + return; + } + } + throw new AssertionError(); + } +} From 22da92970991109600870cacd41f3d30224c0e0b Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 18 Apr 2016 20:58:19 +0100 Subject: [PATCH 055/167] 8147553: Remove sun.misc.ManagedLocalsThread from java.management Reviewed-by: dfuchs --- .../jmx/remote/internal/ClientCommunicatorAdmin.java | 10 +++++----- .../sun/jmx/remote/internal/ClientNotifForwarder.java | 8 +++++--- .../jmx/remote/internal/ServerCommunicatorAdmin.java | 7 +++++-- .../classes/javax/management/monitor/Monitor.java | 7 ++++--- jdk/src/java.management/share/classes/module-info.java | 2 -- .../classes/sun/management/jdp/JdpController.java | 3 +-- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java index 85f248311cb..5df5c243782 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java @@ -30,7 +30,6 @@ import java.io.InterruptedIOException; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; -import sun.misc.ManagedLocalsThread; public abstract class ClientCommunicatorAdmin { private static volatile long threadNo = 1; @@ -41,10 +40,11 @@ public abstract class ClientCommunicatorAdmin { if (period > 0) { checker = new Checker(); - Thread t = new ManagedLocalsThread( - checker, - "JMX client heartbeat " + (++threadNo) - ); + Thread t = new Thread(null, + checker, + "JMX client heartbeat " + (++threadNo), + 0, + false); t.setDaemon(true); t.start(); diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java index 05abd0ceeb5..e0860f8e1f0 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java @@ -52,7 +52,6 @@ import javax.management.remote.TargetedNotification; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; import java.rmi.UnmarshalException; -import sun.misc.ManagedLocalsThread; public abstract class ClientNotifForwarder { @@ -91,7 +90,8 @@ public abstract class ClientNotifForwarder { throw new IllegalArgumentException("More than one command"); this.command = command; if (thread == null) { - thread = new ManagedLocalsThread( + thread = new Thread( + null, ()-> { while (true) { Runnable r; @@ -107,7 +107,9 @@ public abstract class ClientNotifForwarder { r.run(); } }, - "ClientNotifForwarder-" + ++threadId + "ClientNotifForwarder-" + ++threadId, + 0, + false ); thread.setDaemon(true); thread.start(); diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java index 6df86f5931b..74fbbd4c329 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java @@ -27,7 +27,6 @@ package com.sun.jmx.remote.internal; import com.sun.jmx.remote.util.ClassLogger; -import sun.misc.ManagedLocalsThread; public abstract class ServerCommunicatorAdmin { public ServerCommunicatorAdmin(long timeout) { @@ -42,7 +41,11 @@ public abstract class ServerCommunicatorAdmin { timestamp = 0; if (timeout < Long.MAX_VALUE) { Runnable timeoutTask = new Timeout(); - final Thread t = new ManagedLocalsThread(timeoutTask); + final Thread t = new Thread(null, + timeoutTask, + "JMX-Server-Admin-Timeout", + 0, + false); t.setName("JMX server connection timeout " + t.getId()); // If you change this name you will need to change a unit test // (NoServerTimeoutTest) diff --git a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java index 6276fb33b50..eb2a59ac14a 100644 --- a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java +++ b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java @@ -61,7 +61,6 @@ import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; import javax.management.ReflectionException; import static javax.management.monitor.MonitorNotification.*; -import sun.misc.ManagedLocalsThread; /** * Defines the part common to all monitor MBeans. @@ -1637,10 +1636,12 @@ public abstract class Monitor } public Thread newThread(Runnable r) { - Thread t = new ManagedLocalsThread( + Thread t = new Thread( group, r, - namePrefix + threadNumber.getAndIncrement() + nameSuffix + namePrefix + threadNumber.getAndIncrement() + nameSuffix, + 0, + false ); t.setDaemon(true); diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java index 811c2de91bd..8f7bd1b909e 100644 --- a/jdk/src/java.management/share/classes/module-info.java +++ b/jdk/src/java.management/share/classes/module-info.java @@ -27,8 +27,6 @@ module java.management { requires public java.rmi; requires java.logging; requires java.naming; - // 8147553 - requires jdk.unsupported; exports java.lang.management; exports javax.management; diff --git a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java index 344d2db2b9e..f96227ce471 100644 --- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java +++ b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java @@ -34,7 +34,6 @@ import java.lang.management.RuntimeMXBean; import java.lang.reflect.Field; import java.lang.reflect.Method; import sun.management.VMManagement; -import sun.misc.ManagedLocalsThread; /** * JdpController is responsible to create and manage a broadcast loop. @@ -219,7 +218,7 @@ public final class JdpController { controller = new JDPControllerRunner(bcast, packet, pause); - Thread t = new ManagedLocalsThread(controller, "JDP broadcaster"); + Thread t = new Thread(null, controller, "JDP broadcaster", 0, false); t.setDaemon(true); t.start(); } From 5a117b7e566eaf1269a29928d20daf985bb9e7d4 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 18 Apr 2016 20:58:21 +0100 Subject: [PATCH 056/167] 8153372: Remove sun.misc.ManagedLocalsThread from jdk.httpserver Reviewed-by: alanb --- jdk/src/jdk.httpserver/share/classes/module-info.java | 3 +-- .../share/classes/sun/net/httpserver/ServerImpl.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/jdk/src/jdk.httpserver/share/classes/module-info.java b/jdk/src/jdk.httpserver/share/classes/module-info.java index e71e6a3f3c8..e26758b66e9 100644 --- a/jdk/src/jdk.httpserver/share/classes/module-info.java +++ b/jdk/src/jdk.httpserver/share/classes/module-info.java @@ -25,8 +25,7 @@ module jdk.httpserver { requires java.logging; - // 8153372 - requires jdk.unsupported; + exports com.sun.net.httpserver; exports com.sun.net.httpserver.spi; uses com.sun.net.httpserver.spi.HttpServerProvider; diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index 1c3ac29f936..a8566e8f7b6 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -36,7 +36,6 @@ import javax.net.ssl.*; import com.sun.net.httpserver.*; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.ManagedLocalsThread; import sun.net.httpserver.HttpConnection.State; /** @@ -143,7 +142,7 @@ class ServerImpl implements TimeSource { if (executor == null) { executor = new DefaultExecutor(); } - dispatcherThread = new ManagedLocalsThread(dispatcher); + dispatcherThread = new Thread(null, dispatcher, "HTTP-Dispatcher", 0, false); started = true; dispatcherThread.start(); } From 78ca5988bc81d78012b2f7c260eb105960c9ad27 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 18 Apr 2016 20:58:30 +0100 Subject: [PATCH 057/167] 8153158: Remove sun.misc.ManagedLocalsThread from java.logging Reviewed-by: dfuchs, redestad --- .../share/classes/java/util/logging/LogManager.java | 4 ++-- jdk/src/java.logging/share/classes/module-info.java | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java index 81f3387be8c..e15add5a4f8 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -42,7 +42,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.ManagedLocalsThread; import sun.util.logging.internal.LoggingProviderImpl; /** @@ -254,9 +253,10 @@ public class LogManager { // This private class is used as a shutdown hook. // It does a "reset" to close all open handlers. - private class Cleaner extends ManagedLocalsThread { + private class Cleaner extends Thread { private Cleaner() { + super(null, null, "Logging-Cleaner", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.logging/share/classes/module-info.java b/jdk/src/java.logging/share/classes/module-info.java index 0deda7677b5..47456e5ef5b 100644 --- a/jdk/src/java.logging/share/classes/module-info.java +++ b/jdk/src/java.logging/share/classes/module-info.java @@ -24,8 +24,6 @@ */ module java.logging { - // 8153158 - requires jdk.unsupported; exports java.util.logging; provides jdk.internal.logger.DefaultLoggerFinder with sun.util.logging.internal.LoggingProviderImpl; From ba908a90375f062ee7743c630ecbacdf749c38a6 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 18 Apr 2016 14:10:14 -0700 Subject: [PATCH 058/167] 8145468: update java.lang APIs with new deprecations Reviewed-by: alanb, psandoz, lancea, forax, scolebourne, chegar, martin --- .../share/classes/java/lang/Boolean.java | 28 ++++++++++------- .../share/classes/java/lang/Byte.java | 16 ++++++++-- .../share/classes/java/lang/Character.java | 26 +++++++++------- .../share/classes/java/lang/ClassLoader.java | 4 +-- .../share/classes/java/lang/Double.java | 16 ++++++++-- .../share/classes/java/lang/Float.java | 26 +++++++++++++--- .../share/classes/java/lang/Integer.java | 21 +++++++++---- .../share/classes/java/lang/Long.java | 14 ++++++++- .../share/classes/java/lang/Package.java | 2 +- .../share/classes/java/lang/Runtime.java | 9 ++++-- .../classes/java/lang/SecurityManager.java | 30 +++++++++++-------- .../share/classes/java/lang/Short.java | 14 ++++++++- .../share/classes/java/lang/String.java | 6 ++-- .../share/classes/java/lang/System.java | 3 +- .../share/classes/java/lang/Thread.java | 16 ++++++---- .../share/classes/java/lang/ThreadGroup.java | 8 ++--- .../classes/java/lang/invoke/MemberName.java | 1 + .../java/lang/reflect/ProxyGenerator.java | 2 +- .../share/classes/java/text/ChoiceFormat.java | 2 +- .../classes/java/text/DecimalFormat.java | 16 +++++----- .../util/concurrent/ThreadLocalRandom.java | 2 +- .../internal/org/objectweb/asm/Opcodes.java | 3 ++ .../classes/sun/nio/ch/InheritedChannel.java | 2 +- .../net/DualStackPlainDatagramSocketImpl.java | 2 +- .../sun/nio/ch/WindowsSelectorImpl.java | 6 ++-- .../security/krb5/internal/tools/Klist.java | 2 +- .../com/sun/rowset/CachedRowSetImpl.java | 8 ++--- .../sun/tools/jstat/ExpressionExecuter.java | 8 ++--- .../sun/tools/jstat/ExpressionResolver.java | 6 ++-- .../share/classes/sun/tools/jstat/Parser.java | 4 +-- .../sun/tools/example/debug/tty/Commands.java | 12 ++++---- .../example/debug/tty/MessageOutput.java | 2 +- 32 files changed, 211 insertions(+), 106 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Boolean.java b/jdk/src/java.base/share/classes/java/lang/Boolean.java index b53995193f1..eeda751719c 100644 --- a/jdk/src/java.base/share/classes/java/lang/Boolean.java +++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java @@ -79,13 +79,16 @@ public final class Boolean implements java.io.Serializable, * Allocates a {@code Boolean} object representing the * {@code value} argument. * - *

Note: It is rarely appropriate to use this constructor. - * Unless a new instance is required, the static factory - * {@link #valueOf(boolean)} is generally a better choice. It is - * likely to yield significantly better space and time performance. - * * @param value the value of the {@code Boolean}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(boolean)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. + * Also consider using the final fields {@link #TRUE} and {@link #FALSE} + * if possible. */ + @Deprecated(since="9") public Boolean(boolean value) { this.value = value; } @@ -94,15 +97,18 @@ public final class Boolean implements java.io.Serializable, * Allocates a {@code Boolean} object representing the value * {@code true} if the string argument is not {@code null} * and is equal, ignoring case, to the string {@code "true"}. - * Otherwise, allocate a {@code Boolean} object representing the - * value {@code false}. Examples:

- * {@code new Boolean("True")} produces a {@code Boolean} object - * that represents {@code true}.
- * {@code new Boolean("yes")} produces a {@code Boolean} object - * that represents {@code false}. + * Otherwise, allocates a {@code Boolean} object representing the + * value {@code false}. * * @param s the string to be converted to a {@code Boolean}. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseBoolean(String)} to convert a string to a + * {@code boolean} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Boolean} object. */ + @Deprecated(since="9") public Boolean(String s) { this(parseBoolean(s)); } diff --git a/jdk/src/java.base/share/classes/java/lang/Byte.java b/jdk/src/java.base/share/classes/java/lang/Byte.java index 51f687cb389..877af689556 100644 --- a/jdk/src/java.base/share/classes/java/lang/Byte.java +++ b/jdk/src/java.base/share/classes/java/lang/Byte.java @@ -297,7 +297,13 @@ public final class Byte extends Number implements Comparable { * * @param value the value to be represented by the * {@code Byte}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(byte)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Byte(byte value) { this.value = value; } @@ -311,10 +317,16 @@ public final class Byte extends Number implements Comparable { * * @param s the {@code String} to be converted to a * {@code Byte} - * @throws NumberFormatException If the {@code String} + * @throws NumberFormatException if the {@code String} * does not contain a parsable {@code byte}. - * @see java.lang.Byte#parseByte(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseByte(String)} to convert a string to a + * {@code byte} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Byte} object. */ + @Deprecated(since="9") public Byte(String s) throws NumberFormatException { this.value = parseByte(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Character.java b/jdk/src/java.base/share/classes/java/lang/Character.java index ea42bfb3d6e..9f9e4de1972 100644 --- a/jdk/src/java.base/share/classes/java/lang/Character.java +++ b/jdk/src/java.base/share/classes/java/lang/Character.java @@ -1256,14 +1256,14 @@ class Character implements java.io.Serializable, Comparable { new UnicodeBlock("SPECIALS"); /** - * @deprecated As of J2SE 5, use {@link #HIGH_SURROGATES}, - * {@link #HIGH_PRIVATE_USE_SURROGATES}, and - * {@link #LOW_SURROGATES}. These new constants match - * the block definitions of the Unicode Standard. - * The {@link #of(char)} and {@link #of(int)} methods - * return the new constants, not SURROGATES_AREA. + * @deprecated + * Instead of {@code SURROGATES_AREA}, use {@link #HIGH_SURROGATES}, + * {@link #HIGH_PRIVATE_USE_SURROGATES}, and {@link #LOW_SURROGATES}. + * These constants match the block definitions of the Unicode Standard. + * The {@link #of(char)} and {@link #of(int)} methods return the + * standard constants. */ - @Deprecated + @Deprecated(since="1.5") public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA"); @@ -7451,7 +7451,13 @@ class Character implements java.io.Serializable, Comparable { * * @param value the value to be represented by the * {@code Character} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(char)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Character(char value) { this.value = value; } @@ -8799,7 +8805,7 @@ class Character implements java.io.Serializable, Comparable { * @since 1.0.2 * @deprecated Replaced by isJavaIdentifierStart(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isJavaLetter(char ch) { return isJavaIdentifierStart(ch); } @@ -8835,7 +8841,7 @@ class Character implements java.io.Serializable, Comparable { * @since 1.0.2 * @deprecated Replaced by isJavaIdentifierPart(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isJavaLetterOrDigit(char ch) { return isJavaIdentifierPart(ch); } @@ -9580,7 +9586,7 @@ class Character implements java.io.Serializable, Comparable { * @see Character#isWhitespace(char) * @deprecated Replaced by isWhitespace(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isSpace(char ch) { return (ch <= 0x0020) && (((((1L << 0x0009) | diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 33e5105bb3d..1fcd03b760f 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -727,7 +727,7 @@ public abstract class ClassLoader { * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) * defineClass(String, byte[], int, int)} */ - @Deprecated + @Deprecated(since="1.1") protected final Class defineClass(byte[] b, int off, int len) throws ClassFormatError { @@ -2012,7 +2012,7 @@ public abstract class ClassLoader { * * @since 1.2 */ - @Deprecated + @Deprecated(since="9") protected Package getPackage(String name) { Package pkg = getDefinedPackage(name); if (pkg == null) { diff --git a/jdk/src/java.base/share/classes/java/lang/Double.java b/jdk/src/java.base/share/classes/java/lang/Double.java index 473b86dd909..75a227e5282 100644 --- a/jdk/src/java.base/share/classes/java/lang/Double.java +++ b/jdk/src/java.base/share/classes/java/lang/Double.java @@ -589,7 +589,13 @@ public final class Double extends Number implements Comparable { * represents the primitive {@code double} argument. * * @param value the value to be represented by the {@code Double}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(double)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Double(double value) { this.value = value; } @@ -601,10 +607,16 @@ public final class Double extends Number implements Comparable { * {@code double} value as if by the {@code valueOf} method. * * @param s a string to be converted to a {@code Double}. - * @throws NumberFormatException if the string does not contain a + * @throws NumberFormatException if the string does not contain a * parsable number. - * @see java.lang.Double#valueOf(java.lang.String) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseDouble(String)} to convert a string to a + * {@code double} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Double} object. */ + @Deprecated(since="9") public Double(String s) throws NumberFormatException { value = parseDouble(s); } diff --git a/jdk/src/java.base/share/classes/java/lang/Float.java b/jdk/src/java.base/share/classes/java/lang/Float.java index 334d3d033da..60e08db7ad5 100644 --- a/jdk/src/java.base/share/classes/java/lang/Float.java +++ b/jdk/src/java.base/share/classes/java/lang/Float.java @@ -502,7 +502,13 @@ public final class Float extends Number implements Comparable { * represents the primitive {@code float} argument. * * @param value the value to be represented by the {@code Float}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(float)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Float(float value) { this.value = value; } @@ -512,7 +518,13 @@ public final class Float extends Number implements Comparable { * represents the argument converted to type {@code float}. * * @param value the value to be represented by the {@code Float}. + * + * @deprecated + * It is rarely appropriate to use this constructor. Instead, use the + * static factory method {@link #valueOf(float)} method as follows: + * {@code Float.valueOf((float)value)}. */ + @Deprecated(since="9") public Float(double value) { this.value = (float)value; } @@ -523,11 +535,17 @@ public final class Float extends Number implements Comparable { * represented by the string. The string is converted to a * {@code float} value as if by the {@code valueOf} method. * - * @param s a string to be converted to a {@code Float}. - * @throws NumberFormatException if the string does not contain a - * parsable number. - * @see java.lang.Float#valueOf(java.lang.String) + * @param s a string to be converted to a {@code Float}. + * @throws NumberFormatException if the string does not contain a + * parsable number. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseFloat(String)} to convert a string to a + * {@code float} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Float} object. */ + @Deprecated(since="9") public Float(String s) throws NumberFormatException { value = parseFloat(s); } diff --git a/jdk/src/java.base/share/classes/java/lang/Integer.java b/jdk/src/java.base/share/classes/java/lang/Integer.java index 2a846c4d07f..7765d784e07 100644 --- a/jdk/src/java.base/share/classes/java/lang/Integer.java +++ b/jdk/src/java.base/share/classes/java/lang/Integer.java @@ -1106,7 +1106,13 @@ public final class Integer extends Number implements Comparable { * * @param value the value to be represented by the * {@code Integer} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(int)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Integer(int value) { this.value = value; } @@ -1118,12 +1124,17 @@ public final class Integer extends Number implements Comparable { * {@code int} value in exactly the manner used by the * {@code parseInt} method for radix 10. * - * @param s the {@code String} to be converted to an - * {@code Integer}. - * @exception NumberFormatException if the {@code String} does not - * contain a parsable integer. - * @see java.lang.Integer#parseInt(java.lang.String, int) + * @param s the {@code String} to be converted to an {@code Integer}. + * @throws NumberFormatException if the {@code String} does not + * contain a parsable integer. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseInt(String)} to convert a string to a + * {@code int} primitive, or use {@link #valueOf(String)} + * to convert a string to an {@code Integer} object. */ + @Deprecated(since="9") public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Long.java b/jdk/src/java.base/share/classes/java/lang/Long.java index ae93a7ca827..793d15e53b2 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -1340,7 +1340,13 @@ public final class Long extends Number implements Comparable { * * @param value the value to be represented by the * {@code Long} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(long)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Long(long value) { this.value = value; } @@ -1356,8 +1362,14 @@ public final class Long extends Number implements Comparable { * {@code Long}. * @throws NumberFormatException if the {@code String} does not * contain a parsable {@code long}. - * @see java.lang.Long#parseLong(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseLong(String)} to convert a string to a + * {@code long} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Long} object. */ + @Deprecated(since="9") public Long(String s) throws NumberFormatException { this.value = parseLong(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Package.java b/jdk/src/java.base/share/classes/java/lang/Package.java index 3b328ca199f..1aa9e98fbf2 100644 --- a/jdk/src/java.base/share/classes/java/lang/Package.java +++ b/jdk/src/java.base/share/classes/java/lang/Package.java @@ -333,7 +333,7 @@ public class Package extends NamedPackage implements java.lang.reflect.Annotated * @see ClassLoader#getDefinedPackage */ @CallerSensitive - @Deprecated + @Deprecated(since="9") @SuppressWarnings("deprecation") public static Package getPackage(String name) { ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 64b22de4bd6..a5deffc16b8 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -289,6 +289,7 @@ public class Runtime { * finalizers being called on live objects while other threads are * concurrently manipulating those objects, resulting in erratic * behavior or deadlock. + * This method is subject to removal in a future version of Java SE. * * @throws SecurityException * if a security manager exists and its {@code checkExit} @@ -299,7 +300,7 @@ public class Runtime { * @see java.lang.SecurityManager#checkExit(int) * @since 1.1 */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public static void runFinalizersOnExit(boolean value) { SecurityManager security = System.getSecurityManager(); if (security != null) { @@ -894,8 +895,9 @@ public class Runtime { * stream in the local encoding into a character stream in Unicode is via * the {@code InputStreamReader} and {@code BufferedReader} * classes. + * This method is subject to removal in a future version of Java SE. */ - @Deprecated + @Deprecated(since="1.1", forRemoval=true) public InputStream getLocalizedInputStream(InputStream in) { return in; } @@ -915,6 +917,7 @@ public class Runtime { * Unicode character stream into a byte stream in the local encoding is via * the {@code OutputStreamWriter}, {@code BufferedWriter}, and * {@code PrintWriter} classes. + * This method is subject to removal in a future version of Java SE. * * @param out OutputStream to localize * @return a localized output stream @@ -923,7 +926,7 @@ public class Runtime { * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream) */ - @Deprecated + @Deprecated(since="1.1", forRemoval=true) public OutputStream getLocalizedOutputStream(OutputStream out) { return out; } diff --git a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java index 8ea8f09d103..e88a5eaa181 100644 --- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java +++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java @@ -229,7 +229,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") protected boolean inCheck; /* @@ -262,7 +262,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") public boolean getInCheck() { return inCheck; } @@ -345,7 +345,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected ClassLoader currentClassLoader() { ClassLoader cl = currentClassLoader0(); if ((cl != null) && hasAllPermission()) @@ -391,7 +391,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected Class currentLoadedClass() { Class c = currentLoadedClass0(); if ((c != null) && hasAllPermission()) @@ -411,7 +411,7 @@ class SecurityManager { * call be used instead. * */ - @Deprecated + @Deprecated(since="1.2") protected native int classDepth(String name); /** @@ -449,7 +449,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected int classLoaderDepth() { int depth = classLoaderDepth0(); if (depth != -1) { @@ -474,7 +474,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") protected boolean inClass(String name) { return classDepth(name) >= 0; } @@ -491,7 +491,7 @@ class SecurityManager { * call be used instead. * @see #currentClassLoader() currentClassLoader */ - @Deprecated + @Deprecated(since="1.2") protected boolean inClassLoader() { return currentClassLoader() != null; } @@ -1217,7 +1217,7 @@ class SecurityManager { * @deprecated Use #checkPermission(java.security.Permission) instead * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.4") public void checkMulticast(InetAddress maddr, byte ttl) { String host = maddr.getHostAddress(); if (!host.startsWith("[") && host.indexOf(':') != -1) { @@ -1297,9 +1297,10 @@ class SecurityManager { * was trusted to bring up a top-level window. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("showWindowWithoutWarningBanner")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public boolean checkTopLevelWindow(Object window) { if (window == null) { throw new NullPointerException("window can't be null"); @@ -1340,9 +1341,10 @@ class SecurityManager { * thread could access the system clipboard. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("accessClipboard")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public void checkSystemClipboardAccess() { checkPermission(SecurityConstants.ALL_PERMISSION); } @@ -1358,9 +1360,10 @@ class SecurityManager { * thread could access the AWT event queue. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("accessEventQueue")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public void checkAwtEventQueueAccess() { checkPermission(SecurityConstants.ALL_PERMISSION); } @@ -1626,12 +1629,13 @@ class SecurityManager { * Users of this method should instead invoke {@link #checkPermission} * directly. This method will be changed in a future release * to check the permission {@code java.security.AllPermission}. + * This method is subject to removal in a future version of Java SE. * * @see java.lang.reflect.Member * @since 1.1 * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) @CallerSensitive public void checkMemberAccess(Class clazz, int which) { if (clazz == null) { diff --git a/jdk/src/java.base/share/classes/java/lang/Short.java b/jdk/src/java.base/share/classes/java/lang/Short.java index 9fa79f3d8c2..57b291fc03a 100644 --- a/jdk/src/java.base/share/classes/java/lang/Short.java +++ b/jdk/src/java.base/share/classes/java/lang/Short.java @@ -302,7 +302,13 @@ public final class Short extends Number implements Comparable { * * @param value the value to be represented by the * {@code Short}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(short)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Short(short value) { this.value = value; } @@ -318,8 +324,14 @@ public final class Short extends Number implements Comparable { * {@code Short} * @throws NumberFormatException If the {@code String} * does not contain a parsable {@code short}. - * @see java.lang.Short#parseShort(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseShort(String)} to convert a string to a + * {@code short} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Short} object. */ + @Deprecated(since="9") public Short(String s) throws NumberFormatException { this.value = parseShort(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index a609223d42f..a1772977727 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -363,7 +363,7 @@ public final class String * @see #String(byte[], java.nio.charset.Charset) * @see #String(byte[]) */ - @Deprecated + @Deprecated(since="1.1") public String(byte ascii[], int hibyte, int offset, int count) { checkBoundsOffCount(offset, count, ascii.length); if (count == 0) { @@ -415,7 +415,7 @@ public final class String * @see #String(byte[], java.nio.charset.Charset) * @see #String(byte[]) */ - @Deprecated + @Deprecated(since="1.1") public String(byte ascii[], int hibyte) { this(ascii, hibyte, 0, ascii.length); } @@ -911,7 +911,7 @@ public final class String * dst.length} * */ - @Deprecated + @Deprecated(since="1.1") public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { checkBoundsBeginEnd(srcBegin, srcEnd, length()); Objects.requireNonNull(dst); diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 02975912bc0..2ddd37f5da1 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1715,6 +1715,7 @@ public final class System { * finalizers being called on live objects while other threads are * concurrently manipulating those objects, resulting in erratic * behavior or deadlock. + * This method is subject to removal in a future version of Java SE. * @param value indicating enabling or disabling of finalization * @throws SecurityException * if a security manager exists and its checkExit @@ -1725,7 +1726,7 @@ public final class System { * @see java.lang.SecurityManager#checkExit(int) * @since 1.1 */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public static void runFinalizersOnExit(boolean value) { Runtime.runFinalizersOnExit(value); } diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index 9c275ac1be9..040e1e98e5c 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -890,7 +890,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void stop() { SecurityManager security = System.getSecurityManager(); if (security != null) { @@ -922,8 +922,9 @@ class Thread implements Runnable { * For more information, see * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + * This method is subject to removal in a future version of Java SE. */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public final synchronized void stop(Throwable obj) { throw new UnsupportedOperationException(); } @@ -1043,9 +1044,10 @@ class Thread implements Runnable { * "frozen" processes. For more information, see * * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + * This method is subject to removal in a future version of Java SE. * @throws NoSuchMethodError always */ - @Deprecated + @Deprecated(since="1.5", forRemoval=true) public void destroy() { throw new NoSuchMethodError(); } @@ -1083,7 +1085,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void suspend() { checkAccess(); suspend0(); @@ -1109,7 +1111,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void resume() { checkAccess(); resume0(); @@ -1270,8 +1272,10 @@ class Thread implements Runnable { * @deprecated The definition of this call depends on {@link #suspend}, * which is deprecated. Further, the results of this call * were never well-defined. + * This method is subject to removal in a future version of Java SE. + * @see StackWalker */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public native int countStackFrames(); /** diff --git a/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java b/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java index e477800f61c..0a97e4cad94 100644 --- a/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -607,7 +607,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * @deprecated This method is inherently unsafe. See * {@link Thread#stop} for details. */ - @Deprecated + @Deprecated(since="1.2") public final void stop() { if (stopOrSuspend(false)) Thread.currentThread().stop(); @@ -669,7 +669,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * @deprecated This method is inherently deadlock-prone. See * {@link Thread#suspend} for details. */ - @Deprecated + @Deprecated(since="1.2") @SuppressWarnings("deprecation") public final void suspend() { if (stopOrSuspend(true)) @@ -732,7 +732,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * both of which have been deprecated, as they are inherently * deadlock-prone. See {@link Thread#suspend} for details. */ - @Deprecated + @Deprecated(since="1.2") @SuppressWarnings("deprecation") public final void resume() { int ngroupsSnapshot; @@ -1073,7 +1073,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * which is deprecated. Further, the behavior of this call * was never specified. */ - @Deprecated + @Deprecated(since="1.2") public boolean allowThreadSuspension(boolean b) { this.vmAllowSuspension = b; if (!b) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index c2e68753e7b..993faf3fc0d 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -733,6 +733,7 @@ import java.util.Objects; } @Override + @SuppressWarnings("deprecation") public int hashCode() { // Avoid autoboxing getReferenceKind(), since this is used early and will force // early initialization of Byte$ByteCache diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index 12e1723e0df..cc8dbbfffab 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -1750,7 +1750,7 @@ class ProxyGenerator { * Get or assign the index for a CONSTANT_Float entry. */ public short getFloat(float f) { - return getValue(new Float(f)); + return getValue(f); } /** diff --git a/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java b/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java index 8355dee87d4..98c66365c1b 100644 --- a/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java +++ b/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java @@ -437,7 +437,7 @@ public class ChoiceFormat extends NumberFormat { if (status.index == start) { status.errorIndex = furthest; } - return new Double(bestNumber); + return Double.valueOf(bestNumber); } /** diff --git a/jdk/src/java.base/share/classes/java/text/DecimalFormat.java b/jdk/src/java.base/share/classes/java/text/DecimalFormat.java index a82011fd7d5..587a64e13f1 100644 --- a/jdk/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/jdk/src/java.base/share/classes/java/text/DecimalFormat.java @@ -1996,7 +1996,7 @@ public class DecimalFormat extends NumberFormat { // special case NaN if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) { pos.index = pos.index + symbols.getNaN().length(); - return new Double(Double.NaN); + return Double.valueOf(Double.NaN); } boolean[] status = new boolean[STATUS_LENGTH]; @@ -2007,19 +2007,19 @@ public class DecimalFormat extends NumberFormat { // special case INFINITY if (status[STATUS_INFINITE]) { if (status[STATUS_POSITIVE] == (multiplier >= 0)) { - return new Double(Double.POSITIVE_INFINITY); + return Double.valueOf(Double.POSITIVE_INFINITY); } else { - return new Double(Double.NEGATIVE_INFINITY); + return Double.valueOf(Double.NEGATIVE_INFINITY); } } if (multiplier == 0) { if (digitList.isZero()) { - return new Double(Double.NaN); + return Double.valueOf(Double.NaN); } else if (status[STATUS_POSITIVE]) { - return new Double(Double.POSITIVE_INFINITY); + return Double.valueOf(Double.POSITIVE_INFINITY); } else { - return new Double(Double.NEGATIVE_INFINITY); + return Double.valueOf(Double.NEGATIVE_INFINITY); } } @@ -2093,8 +2093,8 @@ public class DecimalFormat extends NumberFormat { !isParseIntegerOnly(); } - return gotDouble ? - (Number)new Double(doubleResult) : (Number)Long.valueOf(longResult); + // cast inside of ?: because of binary numeric promotion, JLS 15.25 + return gotDouble ? (Number)doubleResult : (Number)longResult; } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 69ecc46cf6d..2af74b20961 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -455,7 +455,7 @@ public class ThreadLocalRandom extends Random { s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); - nextLocalGaussian.set(new Double(v2 * multiplier)); + nextLocalGaussian.set(Double.valueOf(v2 * multiplier)); return v1 * multiplier; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index d40facdafa4..e6a7cded42f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -70,6 +70,7 @@ package jdk.internal.org.objectweb.asm; * @author Eric Bruneton * @author Eugene Kuleshov */ +@SuppressWarnings("deprecation") // for Integer(int) constructor public interface Opcodes { // ASM API versions @@ -176,6 +177,8 @@ public interface Opcodes { */ int F_SAME1 = 4; + // For reference comparison purposes, construct new instances + // instead of using valueOf() or autoboxing. Integer TOP = new Integer(0); Integer INTEGER = new Integer(1); Integer FLOAT = new Integer(2); diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index 2bb712e7867..8e52936ccb0 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -168,7 +168,7 @@ class InheritedChannel { Class paramTypes[] = { int.class }; Constructor ctr = Reflect.lookupConstructor("java.io.FileDescriptor", paramTypes); - Object args[] = { new Integer(fdVal) }; + Object args[] = { Integer.valueOf(fdVal) }; FileDescriptor fd = (FileDescriptor)Reflect.invoke(ctr, args); diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 8f464ddfd07..294cd5985bf 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -220,7 +220,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl case IP_TOS : case SO_RCVBUF : case SO_SNDBUF : - returnValue = new Integer(value); + returnValue = Integer.valueOf(value); break; default: /* shouldn't get here */ throw new SocketException("Option not supported"); diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index cb74298d3dc..8e01c9e7332 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -87,13 +87,13 @@ final class WindowsSelectorImpl extends SelectorImpl { private static final class FdMap extends HashMap { static final long serialVersionUID = 0L; private MapEntry get(int desc) { - return get(new Integer(desc)); + return get(Integer.valueOf(desc)); } private MapEntry put(SelectionKeyImpl ski) { - return put(new Integer(ski.channel.getFDVal()), new MapEntry(ski)); + return put(Integer.valueOf(ski.channel.getFDVal()), new MapEntry(ski)); } private MapEntry remove(SelectionKeyImpl ski) { - Integer fd = new Integer(ski.channel.getFDVal()); + Integer fd = Integer.valueOf(ski.channel.getFDVal()); MapEntry x = get(fd); if ((x != null) && (x.ski.channel == ski.channel)) return remove(fd); diff --git a/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java b/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java index c32e9d0eea4..a1abeac9763 100644 --- a/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java +++ b/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java @@ -134,7 +134,7 @@ public class Klist { Character arg; for (int i = 0; i < args.length; i++) { if ((args[i].length() >= 2) && (args[i].startsWith("-"))) { - arg = new Character(args[i].charAt(1)); + arg = Character.valueOf(args[i].charAt(1)); switch (arg.charValue()) { case 'c': action = 'c'; diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java index b17cd507e9e..55179670edb 100644 --- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java +++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java @@ -1963,7 +1963,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return (float)0; } try { - return ((new Float(value.toString())).floatValue()); + return Float.parseFloat(value.toString()); } catch (NumberFormatException ex) { throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(), new Object[] {value.toString().trim(), columnIndex})); @@ -2007,7 +2007,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return (double)0; } try { - return ((new Double(value.toString().trim())).doubleValue()); + return Double.parseDouble(value.toString().trim()); } catch (NumberFormatException ex) { throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(), new Object[] {value.toString().trim(), columnIndex})); @@ -4017,9 +4017,9 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return new BigDecimal(srcObj.toString().trim()); case java.sql.Types.REAL: case java.sql.Types.FLOAT: - return new Float(srcObj.toString().trim()); + return Float.valueOf(srcObj.toString().trim()); case java.sql.Types.DOUBLE: - return new Double(srcObj.toString().trim()); + return Double.valueOf(srcObj.toString().trim()); case java.sql.Types.CHAR: case java.sql.Types.VARCHAR: case java.sql.Types.LONGVARCHAR: diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java index a9aece44e30..c49cdf55502 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java @@ -83,14 +83,14 @@ public class ExpressionExecuter implements ExpressionEvaluator { if (op == null) { return evaluate(l); } else { - Double lval = new Double(((Number)evaluate(l)).doubleValue()); - Double rval = new Double(((Number)evaluate(r)).doubleValue()); - double result = op.eval(lval.doubleValue(), rval.doubleValue()); + double lval = ((Number)evaluate(l)).doubleValue(); + double rval = ((Number)evaluate(r)).doubleValue(); + double result = op.eval(lval, rval); if (debug) { System.out.println("Performed Operation: " + lval + op + rval + " = " + result); } - return new Double(result); + return Double.valueOf(result); } } } diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java index c0e198438c6..63505988b8e 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java @@ -71,7 +71,7 @@ public class ExpressionResolver implements ExpressionEvaluator { if (m == null) { System.err.println("Warning: Unresolved Symbol: " + id.getName() + " substituted NaN"); - return new Literal(new Double(Double.NaN)); + return new Literal(Double.valueOf(Double.NaN)); } if (m.getVariability() == Variability.CONSTANT) { if (debug) { @@ -105,7 +105,7 @@ public class ExpressionResolver implements ExpressionEvaluator { Literal rl = (Literal)r; boolean warn = false; - Double nan = new Double(Double.NaN); + Double nan = Double.valueOf(Double.NaN); if (ll.getValue() instanceof String) { warn = true; ll.setValue(nan); } @@ -129,7 +129,7 @@ public class ExpressionResolver implements ExpressionEvaluator { + " (right = " + rn.doubleValue() + ")" + " to literal value " + result); } - return new Literal(new Double(result)); + return new Literal(Double.valueOf(result)); } } diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java index 33b17b95323..a9f9b203e20 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java @@ -324,7 +324,7 @@ public class Parser { case StreamTokenizer.TT_NUMBER: double literal = lookahead.nval; matchNumber(); - e = new Literal(new Double(literal)); + e = new Literal(Double.valueOf(literal)); log(pdebug, "Parsed: number -> " + literal); break; default: @@ -360,7 +360,7 @@ public class Parser { e1.setOperator(op); e1.setRight(e); log(pdebug, "Parsed: unary -> " + e1); - e1.setLeft(new Literal(new Double(0))); + e1.setLeft(new Literal(Double.valueOf(0))); e = e1; } } diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java index 61823822d0e..bbae8bc44c8 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java @@ -478,7 +478,7 @@ class Commands { ThreadGroupReference tg = it.nextThreadGroup(); ++cnt; MessageOutput.println("thread group number description name", - new Object [] { new Integer (cnt), + new Object [] { Integer.valueOf(cnt), Env.description(tg), tg.name()}); } @@ -1014,7 +1014,7 @@ class Commands { return MessageOutput.format("locationString", new Object [] {loc.declaringType().name(), loc.method().name(), - new Integer (loc.lineNumber()), + Integer.valueOf(loc.lineNumber()), Long.valueOf(loc.codeIndex())}); } @@ -1467,7 +1467,7 @@ class Commands { MessageOutput.println("Line number information not available for"); } else if (Env.sourceLine(loc, lineno) == null) { MessageOutput.println("is an invalid line number for", - new Object [] {new Integer (lineno), + new Object [] {Integer.valueOf(lineno), refType.name()}); } else { for (int i = startLine; i <= endLine; i++) { @@ -1477,11 +1477,11 @@ class Commands { } if (i == lineno) { MessageOutput.println("source line number current line and line", - new Object [] {new Integer (i), + new Object [] {Integer.valueOf(i), sourceLine}); } else { MessageOutput.println("source line number and line", - new Object [] {new Integer (i), + new Object [] {Integer.valueOf(i), sourceLine}); } } @@ -1725,7 +1725,7 @@ class Commands { } else { MessageOutput.println("Owned by:", new Object [] {owner.name(), - new Integer (object.entryCount())}); + Integer.valueOf(object.entryCount())}); } List waiters = object.waitingThreads(); if (waiters.size() == 0) { diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java index 8de0675183c..ac3decf432a 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java @@ -198,7 +198,7 @@ public class MessageOutput { (MessageOutput.format("jdb prompt thread name and current stack frame", new Object [] { threadInfo.getThread().name(), - new Integer (threadInfo.getCurrentFrameIndex() + 1)})); + Integer.valueOf(threadInfo.getCurrentFrameIndex() + 1)})); } System.out.flush(); } From 6f26ab8d1258ae7752dfc866f35371f93253a181 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Mon, 18 Apr 2016 22:12:52 -0700 Subject: [PATCH 059/167] 8154498: fix to 8154403 results in failure of UserModuleTest.java on all platforms Reviewed-by: darcy, sundar --- .../plugins/InstalledModuleDescriptors/src/m1/p1/Main.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java index 4e516970d4d..915416c0802 100644 --- a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java +++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java @@ -29,6 +29,7 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.Set; public class Main { @@ -40,7 +41,8 @@ public class Main { validate(Main.class.getModule().getDescriptor()); // read m1/module-info.class - FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), null); + FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), + Collections.emptyMap()); Path path = fs.getPath("/", "modules", "m1", "module-info.class"); validate(ModuleDescriptor.read(Files.newInputStream(path))); } From 2ea14c96f7523f91f80c3aadbb5e18b0c8ad02c8 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Tue, 19 Apr 2016 01:40:13 -0700 Subject: [PATCH 060/167] 8146758: NetworkInterfaceStreamTest.java fails intermittently at comparing network interfaces Reviewed-by: chegar --- .../NetworkInterface/NetworkInterfaceStreamTest.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java index 7d8646d5361..08075ac7472 100644 --- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java +++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java @@ -28,7 +28,6 @@ * @build java.base/java.util.stream.OpTestCase * @run testng/othervm NetworkInterfaceStreamTest * @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest - * @key intermittent */ import org.testng.annotations.Test; @@ -52,21 +51,26 @@ public class NetworkInterfaceStreamTest extends OpTestCase { public void testNetworkInterfaces() throws SocketException { Supplier> ss = () -> { try { - return NetworkInterface.networkInterfaces(); + return allNetworkInterfaces(); } catch (SocketException e) { throw new RuntimeException(e); } }; - Collection expected = Collections.list(NetworkInterface.getNetworkInterfaces()); + Collection enums = Collections.list(NetworkInterface.getNetworkInterfaces()); + Collection expected = new ArrayList<>(); + enums.forEach(ni -> { + if (isIncluded(ni)) { + expected.add(ni); + } + }); withData(TestData.Factory.ofSupplier("Top-level network interfaces", ss)) .stream(s -> s) .expectedResult(expected) .exercise(); } - private Collection getAllNetworkInterfaces() throws SocketException { Collection anis = new ArrayList<>(); for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) { From 2e3fd9639634142ab397b5e25f01050f6258e55a Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 19 Apr 2016 12:20:26 +0100 Subject: [PATCH 061/167] 8154487: java.httpclient/sun.net.httpclient.hpack.DecoderTest failing on Windows Reviewed-by: chegar --- .../share/classes/sun/net/httpclient/hpack/HeaderTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java index 89820741a32..ab824a3df88 100644 --- a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java @@ -269,7 +269,7 @@ final class HeaderTable { StringBuilder b = new StringBuilder(); for (int i = 1, size = dynamicTable.size(); i <= size; i++) { HeaderField e = dynamicTable.get(i); - b.append(format("[%3d] (s = %3d) %s: %s%n", i, + b.append(format("[%3d] (s = %3d) %s: %s\n", i, sizeOf(e), e.name, e.value)); } b.append(format(" Table size:%4s", this.size)); From 402c448d0ac6ad2c3a8ce2fbd56d394f699de951 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Tue, 19 Apr 2016 14:39:35 +0200 Subject: [PATCH 062/167] 8150956: j.l.i.MethodHandles.whileLoop(...) and .iteratedLoop(...) throw unexpected exceptions in the case of 'init' return type is void Reviewed-by: psandoz --- .../java/lang/invoke/MethodHandles.java | 41 +++++++---- .../java/lang/invoke/LoopCombinatorTest.java | 70 ++++++++++++++++++- 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index ea688b14815..5f9fc90b54d 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -28,6 +28,7 @@ package java.lang.invoke; import java.lang.reflect.*; import java.util.ArrayList; import java.util.BitSet; +import java.util.Iterator; import java.util.List; import java.util.Arrays; import java.util.Objects; @@ -53,6 +54,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; +import static java.lang.invoke.MethodType.methodType; /** * This class consists exclusively of static methods that operate on or return @@ -3000,7 +3002,7 @@ assert((int)twice.invokeExact(21) == 42); private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length]; private static MethodHandle makeIdentity(Class ptype) { - MethodType mtype = MethodType.methodType(ptype, ptype); + MethodType mtype = methodType(ptype, ptype); LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY); } @@ -3018,7 +3020,7 @@ assert((int)twice.invokeExact(21) == 42); } private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length]; private static MethodHandle makeZero(Class rtype) { - MethodType mtype = MethodType.methodType(rtype); + MethodType mtype = methodType(rtype); LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO); } @@ -3929,7 +3931,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); MethodHandle throwException(Class returnType, Class exType) { if (!Throwable.class.isAssignableFrom(exType)) throw new ClassCastException(exType.getName()); - return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType)); + return MethodHandleImpl.throwException(methodType(returnType, exType)); } /** @@ -4166,7 +4168,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); for (int i = 0; i < nclauses; ++i) { Class t = iterationVariableTypes.get(i); if (init.get(i) == null) { - init.set(i, empty(MethodType.methodType(t, commonSuffix))); + init.set(i, empty(methodType(t, commonSuffix))); } if (step.get(i) == null) { step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i)); @@ -4175,7 +4177,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); pred.set(i, dropArguments(constant(boolean.class, true), 0, commonParameterSequence)); } if (fini.get(i) == null) { - fini.set(i, empty(MethodType.methodType(t, commonParameterSequence))); + fini.set(i, empty(methodType(t, commonParameterSequence))); } } @@ -4269,7 +4271,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) { - MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType()); + MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) : + identity(init.type().returnType()); MethodHandle[] checkExit = {null, null, pred, fin}; MethodHandle[] varBody = {init, body}; return loop(checkExit, varBody); @@ -4335,7 +4338,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) { - MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType()); + MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) : + identity(init.type().returnType()); MethodHandle[] clause = {init, body, pred, fin}; return loop(clause); } @@ -4472,8 +4476,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle returnVar = dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), - 0, int.class, int.class); + MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ? + zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class); MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; MethodHandle[] bodyClause = {init, @@ -4485,6 +4489,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); /** * Constructs a loop that ranges over the elements produced by an {@code Iterator}. * The iterator will be produced by the evaluation of the {@code iterator} handle. + * This handle must have {@link java.util.Iterator} as its return type. * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead, * and will be applied to a leading argument of the loop handle. * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter. @@ -4534,7 +4539,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * assertEquals(reversedList, (List) loop.invoke(list)); * } *

- * @implSpec The implementation of this method is equivalent to: + * @implSpec The implementation of this method is equivalent to (excluding error handling): *

{@code
      * MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
      *     // assume MH_next and MH_hasNext are handles to methods of Iterator
@@ -4550,6 +4555,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * }
* * @param iterator a handle to return the iterator to start the loop. + * The handle must have {@link java.util.Iterator} as its return type. * Passing {@code null} will make the loop call {@link Iterable#iterator()} on the first * incoming value. * @param init initializer for additional loop state. This determines the loop's result type. @@ -4565,21 +4571,23 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { - checkIteratedLoop(body); + checkIteratedLoop(iterator, body); + final boolean voidInit = init == null || init.type().returnType() == void.class; MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); MethodHandle initIterator = iterator == null ? - initit.asType(initit.type().changeParameterType(0, body.type().parameterType(init == null ? 1 : 2))) : + initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) : iterator; Class itype = initIterator.type().returnType(); Class ttype = body.type().parameterType(0); MethodHandle returnVar = - dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), 0, itype); + dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype); MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext); MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype)); - MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), returnVar}; + MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), + returnVar}; MethodHandle[] bodyClause = {init, filterArgument(body, 0, nextVal)}; return loop(iterVar, bodyClause); @@ -4833,7 +4841,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); } } - private static void checkIteratedLoop(MethodHandle body) { + private static void checkIteratedLoop(MethodHandle iterator, MethodHandle body) { + if (null != iterator && !Iterator.class.isAssignableFrom(iterator.type().returnType())) { + throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type"); + } if (null == body) { throw newIllegalArgumentException("iterated loop body must not be null"); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 71e4b0e89d8..1df672fb997 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -26,6 +26,7 @@ /* @test * @bug 8139885 * @bug 8150635 + * @bug 8150956 * @bug 8150957 * @bug 8153637 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest @@ -265,6 +266,28 @@ public class LoopCombinatorTest { assertEquals(v, w.i); } + @Test + public static void testWhileVoidInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.whileLoop(While.MH_voidInit.bindTo(w), While.MH_voidPred.bindTo(w), + While.MH_voidBody.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + + @Test + public static void testDoWhileVoidInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.doWhileLoop(While.MH_voidInit.bindTo(w), While.MH_voidBody.bindTo(w), + While.MH_voidPred.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testCountedLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme @@ -274,6 +297,14 @@ public class LoopCombinatorTest { assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!")); } + @Test + public static void testCountedLoopVoidInit() throws Throwable { + MethodHandle fit5 = MethodHandles.constant(int.class, 5); + MethodHandle loop = MethodHandles.countedLoop(fit5, MethodHandles.zero(void.class), Counted.MH_printHello); + assertEquals(Counted.MT_countedPrinting, loop.type()); + loop.invoke(); + } + @Test public static void testCountedArrayLoop() throws Throwable { // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13 @@ -360,7 +391,8 @@ public class LoopCombinatorTest { public static void testIterateNullBody() { boolean caught = false; try { - MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null); + MethodHandles.iteratedLoop(MethodHandles.empty(methodType(Iterator.class, int.class)), + MethodHandles.identity(int.class), null); } catch (IllegalArgumentException iae) { assertEquals("iterated loop body must not be null", iae.getMessage()); caught = true; @@ -368,6 +400,26 @@ public class LoopCombinatorTest { assertTrue(caught); } + @Test + public static void testIterateVoidIterator() { + boolean caught = false; + MethodType v = methodType(void.class); + try { + MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); + } catch(IllegalArgumentException iae) { + assertEquals("iteratedLoop first argument must have Iterator return type", iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + + @Test + public static void testIterateVoidInit() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_voidInit, Iterate.MH_printStep); + assertEquals(Iterate.MT_print, loop.type()); + loop.invoke(Arrays.asList("hello", "world")); + } + static class Empty { static void f() { } @@ -604,6 +656,10 @@ public class LoopCombinatorTest { private int i = 0; + void voidInit(int k) { + // empty + } + void voidBody(int k) { ++i; } @@ -623,6 +679,7 @@ public class LoopCombinatorTest { static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class); static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class); static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class); + static final MethodType MT_voidInit = methodType(void.class, int.class); static final MethodType MT_voidBody = methodType(void.class, int.class); static final MethodType MT_voidPred = methodType(boolean.class, int.class); @@ -635,6 +692,7 @@ public class LoopCombinatorTest { static final MethodHandle MH_zipInitZip; static final MethodHandle MH_zipPred; static final MethodHandle MH_zipStep; + static final MethodHandle MH_voidInit; static final MethodHandle MH_voidBody; static final MethodHandle MH_voidPred; @@ -654,6 +712,7 @@ public class LoopCombinatorTest { MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip); MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred); MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep); + MH_voidInit = LOOKUP.findVirtual(WHILE, "voidInit", MT_voidInit); MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody); MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred); } catch (Exception e) { @@ -768,6 +827,10 @@ public class LoopCombinatorTest { System.out.print(s); } + static void voidInit() { + // empty + } + static final Class ITERATE = Iterate.class; static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class); @@ -783,6 +846,8 @@ public class LoopCombinatorTest { static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class); static final MethodType MT_printStep = methodType(void.class, String.class, List.class); + static final MethodType MT_voidInit = methodType(void.class); + static final MethodHandle MH_sumIterator; static final MethodHandle MH_sumInit; static final MethodHandle MH_sumStep; @@ -797,6 +862,8 @@ public class LoopCombinatorTest { static final MethodHandle MH_mapInit; static final MethodHandle MH_mapStep; + static final MethodHandle MH_voidInit; + static final MethodType MT_sum = methodType(int.class, Integer[].class); static final MethodType MT_reverse = methodType(List.class, List.class); static final MethodType MT_length = methodType(int.class, List.class); @@ -815,6 +882,7 @@ public class LoopCombinatorTest { MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit); MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep); MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep); + MH_voidInit = LOOKUP.findStatic(ITERATE, "voidInit", MT_voidInit); } catch (Exception e) { throw new ExceptionInInitializerError(e); } From dc9721e592c013135b85736f3c026071def08d70 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Mon, 18 Apr 2016 09:38:38 -0700 Subject: [PATCH 063/167] 8154470: defines.h confused about PROGNAME and JAVA_ARGS Fiddle with const_progname initializations Reviewed-by: ksrini, alanb --- .../java.base/share/native/launcher/defines.h | 12 ++-- jdk/test/tools/launcher/Arrrghs.java | 4 +- .../tools/launcher/DefaultLocaleTestRun.java | 2 +- .../tools/launcher/ExecutionEnvironment.java | 14 ++-- jdk/test/tools/launcher/FXLauncherTest.java | 6 +- jdk/test/tools/launcher/I18NTest.java | 2 +- jdk/test/tools/launcher/MiscTests.java | 30 ++++---- jdk/test/tools/launcher/Settings.java | 71 +++++++++---------- jdk/test/tools/launcher/TestHelper.java | 12 ++-- jdk/test/tools/launcher/TestSpecialArgs.java | 2 +- .../tools/launcher/TooSmallStackSize.java | 7 +- jdk/test/tools/launcher/ToolsOpts.java | 2 +- jdk/test/tools/launcher/VersionCheck.java | 3 +- 13 files changed, 78 insertions(+), 89 deletions(-) diff --git a/jdk/src/java.base/share/native/launcher/defines.h b/jdk/src/java.base/share/native/launcher/defines.h index e3b18882df4..3b63e038f9d 100644 --- a/jdk/src/java.base/share/native/launcher/defines.h +++ b/jdk/src/java.base/share/native/launcher/defines.h @@ -45,7 +45,11 @@ #ifdef JAVA_ARGS #define HAS_JAVA_ARGS JNI_TRUE -static const char* const_progname = "java"; +#ifdef PROGNAME +static const char* const_progname = PROGNAME; +#else +static char* const_progname = NULL; +#endif static const char* const_jargs[] = JAVA_ARGS; /* * ApplicationHome is prepended to each of these entries; the resulting @@ -59,11 +63,7 @@ static const char* const_appclasspath[] = APP_CLASSPATH; #endif /* APP_CLASSPATH */ #else /* !JAVA_ARGS */ #define HAS_JAVA_ARGS JNI_FALSE -#ifdef PROGNAME -static const char* const_progname = PROGNAME; -#else -static char* const_progname = NULL; -#endif +static const char* const_progname = "java"; static const char** const_jargs = NULL; static const char* const_appclasspath[] = { NULL }; #endif /* JAVA_ARGS */ diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index cb36d2dfe8a..9045e010473 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -489,7 +489,7 @@ public class Arrrghs extends TestHelper { return; } - TestResult tr = null; + TestResult tr; // a missing class createJar("MIA", new File("some.jar"), new File("Foo"), @@ -592,7 +592,7 @@ public class Arrrghs extends TestHelper { if (!isEnglishLocale()) { // only english version return; } - TestResult tr = null; + TestResult tr; // a missing class createJar("MIA", new File("some.jar"), new File("Foo"), (String[])null); diff --git a/jdk/test/tools/launcher/DefaultLocaleTestRun.java b/jdk/test/tools/launcher/DefaultLocaleTestRun.java index c1183e78814..2d4091912e2 100644 --- a/jdk/test/tools/launcher/DefaultLocaleTestRun.java +++ b/jdk/test/tools/launcher/DefaultLocaleTestRun.java @@ -41,7 +41,7 @@ public class DefaultLocaleTestRun extends TestHelper { System.out.println("Test passes vacuously on non-windows"); return; } - TestResult tr = null; + TestResult tr; tr = doExec(javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(), "DefaultLocaleTest", "-w", "x.out"); diff --git a/jdk/test/tools/launcher/ExecutionEnvironment.java b/jdk/test/tools/launcher/ExecutionEnvironment.java index 58acf380b0e..62903b33ecb 100644 --- a/jdk/test/tools/launcher/ExecutionEnvironment.java +++ b/jdk/test/tools/launcher/ExecutionEnvironment.java @@ -120,15 +120,14 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testEcoFriendly() { - TestResult tr = null; - Map env = new HashMap<>(); for (String x : LD_PATH_STRINGS) { String pairs[] = x.split("="); env.put(pairs[0], pairs[1]); } - tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); + TestResult tr = + doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); if (!tr.isNotZeroOutput()) { flagError(tr, "Error: No output at all. Did the test execute ?"); @@ -180,7 +179,7 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testJavaLibraryPath() { - TestResult tr = null; + TestResult tr; Map env = new HashMap<>(); @@ -240,17 +239,14 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testVmSelection() { - - TestResult tr = null; - if (haveClientVM) { - tr = doExec(javaCmd, "-client", "-version"); + TestResult tr = doExec(javaCmd, "-client", "-version"); if (!tr.matches(".*Client VM.*")) { flagError(tr, "the expected vm -client did not launch"); } } if (haveServerVM) { - tr = doExec(javaCmd, "-server", "-version"); + TestResult tr = doExec(javaCmd, "-server", "-version"); if (!tr.matches(".*Server VM.*")) { flagError(tr, "the expected vm -server did not launch"); } diff --git a/jdk/test/tools/launcher/FXLauncherTest.java b/jdk/test/tools/launcher/FXLauncherTest.java index a885cb8dbf6..0ee9d981cda 100644 --- a/jdk/test/tools/launcher/FXLauncherTest.java +++ b/jdk/test/tools/launcher/FXLauncherTest.java @@ -239,7 +239,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(StdMainClass, fxMC)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]); } else { @@ -290,7 +290,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(ExtMainClass, fxMC)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-cp", sTestJar, ExtMainClass, APP_PARMS[0], APP_PARMS[1]); } else { @@ -359,7 +359,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(NonFXMainClass, null)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]); diff --git a/jdk/test/tools/launcher/I18NTest.java b/jdk/test/tools/launcher/I18NTest.java index 3af5d593afc..aa1ce24e798 100644 --- a/jdk/test/tools/launcher/I18NTest.java +++ b/jdk/test/tools/launcher/I18NTest.java @@ -60,7 +60,7 @@ public class I18NTest extends TestHelper { // compile the generate code using the javac compiler vs. the api, to // as a bonus point to see if the argument is passed correctly - TestResult tr = null; + TestResult tr; tr = doExec(javacCmd, fileName + JAVA_FILE_EXT); if (!tr.isOK()) { System.out.println(tr); diff --git a/jdk/test/tools/launcher/MiscTests.java b/jdk/test/tools/launcher/MiscTests.java index 3769d117894..7b82abc4f48 100644 --- a/jdk/test/tools/launcher/MiscTests.java +++ b/jdk/test/tools/launcher/MiscTests.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6856415 8154212 + * @bug 6856415 8154212 8154470 * @summary Miscellaneous tests, Exceptions * @compile -XDignore.symbol.file MiscTests.java * @run main MiscTests @@ -95,30 +95,34 @@ public class MiscTests extends TestHelper { TestResult tr = doExec(javaCmd, "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak"); - for (String s : tr.testOutput) { - System.out.println(s); - } if (!tr.contains("java.security.AccessControlException:" + " access denied (\"java.lang.RuntimePermission\"" + " \"accessClassInPackage.sun.security.pkcs11\")")) { - System.out.println(tr.status); + System.out.println(tr); } } - static void testJLDEnvWithTool() { - final Map envMap = new HashMap<>(); - envMap.put("_JAVA_LAUNCHER_DEBUG", "true"); - TestResult tr = doExec(envMap, javacCmd, "-version"); - tr.checkPositive(); - if (!tr.isOK()) { - System.out.println(tr); + static void testJLDEnv() { + final Map envToSet = new HashMap<>(); + envToSet.put("_JAVA_LAUNCHER_DEBUG", "true"); + for (String cmd : new String[] { javaCmd, javacCmd }) { + TestResult tr = doExec(envToSet, cmd, "-version"); + tr.checkPositive(); + String javargs = cmd.equals(javacCmd) ? "on" : "off"; + String progname = cmd.equals(javacCmd) ? "javac" : "java"; + if (!tr.isOK() + || !tr.matches("\\s*debug:on$") + || !tr.matches("\\s*javargs:" + javargs + "$") + || !tr.matches("\\s*program name:" + progname + "$")) { + System.out.println(tr); + } } } public static void main(String... args) throws IOException { testWithClassPathSetViaProperty(); test6856415(); - testJLDEnvWithTool(); + testJLDEnv(); if (testExitValue != 0) { throw new Error(testExitValue + " tests failed"); } diff --git a/jdk/test/tools/launcher/Settings.java b/jdk/test/tools/launcher/Settings.java index 8d45c8288b6..bd8f238108a 100644 --- a/jdk/test/tools/launcher/Settings.java +++ b/jdk/test/tools/launcher/Settings.java @@ -55,9 +55,9 @@ public class Settings extends TestHelper { } } - static void checkNoContains(TestResult tr, String str) { - if (tr.contains(str)) { - System.out.println(tr.status); + static void checkNotContains(TestResult tr, String str) { + if (!tr.notContains(str)) { + System.out.println(tr); throw new RuntimeException(str + " found"); } } @@ -77,84 +77,77 @@ public class Settings extends TestHelper { if (getArch().equals("ppc64") || getArch().equals("ppc64le")) { stackSize = "800"; } - TestResult tr = null; + TestResult tr; tr = doExec(javaCmd, "-Xms64m", "-Xmx512m", "-Xss" + stackSize + "k", "-XshowSettings", "-jar", testJar.getAbsolutePath()); containsAllOptions(tr); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } tr = doExec(javaCmd, "-Xms65536k", "-Xmx712m", "-Xss" + stackSize + "000", "-XshowSettings", "-jar", testJar.getAbsolutePath()); containsAllOptions(tr); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } } static void runTestOptionAll() throws IOException { init(); - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:all"); + TestResult tr = doExec(javaCmd, "-XshowSettings:all"); containsAllOptions(tr); } static void runTestOptionVM() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:vm"); + TestResult tr = doExec(javaCmd, "-XshowSettings:vm"); checkContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); } static void runTestOptionProperty() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:properties"); - checkNoContains(tr, VM_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettings:properties"); + checkNotContains(tr, VM_SETTINGS); checkContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); } static void runTestOptionLocale() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:locale"); - checkNoContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettings:locale"); + checkNotContains(tr, VM_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); } static void runTestBadOptions() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettingsBadOption"); - checkNoContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettingsBadOption"); + checkNotContains(tr, VM_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); checkContains(tr, "Unrecognized option: -XshowSettingsBadOption"); } static void runTest7123582() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings", "-version"); + TestResult tr = doExec(javaCmd, "-XshowSettings", "-version"); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } containsAllOptions(tr); } - public static void main(String... args) { - try { - runTestOptionAll(); - runTestOptionDefault(); - runTestOptionVM(); - runTestOptionProperty(); - runTestOptionLocale(); - runTestBadOptions(); - runTest7123582(); - } catch (IOException ioe) { - throw new RuntimeException(ioe); + public static void main(String... args) throws IOException { + runTestOptionAll(); + runTestOptionDefault(); + runTestOptionVM(); + runTestOptionProperty(); + runTestOptionLocale(); + runTestBadOptions(); + runTest7123582(); + if (testExitValue != 0) { + throw new Error(testExitValue + " tests failed"); } } } diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 402102b2cd5..6724daf2396 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -603,23 +603,23 @@ public class TestHelper { return true; } - boolean matches(String stringToMatch) { + boolean matches(String regexToMatch) { for (String x : testOutput) { - if (x.matches(stringToMatch)) { + if (x.matches(regexToMatch)) { return true; } } - appendError("string <" + stringToMatch + "> not found"); + appendError("regex <" + regexToMatch + "> not matched"); return false; } - boolean notMatches(String stringToMatch) { + boolean notMatches(String regexToMatch) { for (String x : testOutput) { - if (!x.matches(stringToMatch)) { + if (!x.matches(regexToMatch)) { return true; } } - appendError("string <" + stringToMatch + "> found"); + appendError("regex <" + regexToMatch + "> matched"); return false; } } diff --git a/jdk/test/tools/launcher/TestSpecialArgs.java b/jdk/test/tools/launcher/TestSpecialArgs.java index 307a4e06fb4..0cb75908b8f 100644 --- a/jdk/test/tools/launcher/TestSpecialArgs.java +++ b/jdk/test/tools/launcher/TestSpecialArgs.java @@ -241,7 +241,7 @@ public class TestSpecialArgs extends TestHelper { @Test void testNMArgumentProcessing() throws FileNotFoundException { - TestResult tr = null; + TestResult tr; // the direct invokers of the VM String options[] = { "-version", "-fullversion", "-help", "-?", "-X" diff --git a/jdk/test/tools/launcher/TooSmallStackSize.java b/jdk/test/tools/launcher/TooSmallStackSize.java index dac1c7f0325..7cc02ab56df 100644 --- a/jdk/test/tools/launcher/TooSmallStackSize.java +++ b/jdk/test/tools/launcher/TooSmallStackSize.java @@ -85,11 +85,10 @@ public class TooSmallStackSize extends TestHelper { */ static String checkStack(String stackSize) { String min_stack_allowed; - TestResult tr; if (verbose) System.out.println("*** Testing " + stackSize); - tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); + TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); if (verbose) printTestOutput(tr); @@ -114,11 +113,9 @@ public class TooSmallStackSize extends TestHelper { * Run the JVM with the minimum allowed stack size. This should always succeed. */ static void checkMinStackAllowed(String stackSize) { - TestResult tr = null; - if (verbose) System.out.println("*** Testing " + stackSize); - tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); + TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); if (verbose) printTestOutput(tr); diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java index bff769a54ff..a0f67d24203 100644 --- a/jdk/test/tools/launcher/ToolsOpts.java +++ b/jdk/test/tools/launcher/ToolsOpts.java @@ -149,7 +149,7 @@ public class ToolsOpts extends TestHelper { */ static void runTestOptions() throws IOException { init(); - TestResult tr = null; + TestResult tr; int jpos = -1; for (String arg[] : optionPatterns) { jpos = indexOfJoption(arg); diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index 08a18bd2a28..13dac4f01be 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -151,12 +151,11 @@ public class VersionCheck extends TestHelper { * of the -version output as they are inconsistent. */ static boolean testToolVersion() { - TestResult tr = null; TestHelper.testExitValue = 0; for (File f : new File(JAVA_BIN).listFiles(new ToolFilter(BLACKLIST_VERSION))) { String x = f.getAbsolutePath(); System.out.println("Testing (-version): " + x); - tr = doExec(x, "-version"); + TestResult tr = doExec(x, "-version"); tr.checkPositive(); } return TestHelper.testExitValue == 0; From d7b161662353d8817648dca8eb8e1f4741b45f69 Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Tue, 19 Apr 2016 11:42:29 -0700 Subject: [PATCH 064/167] 8154365: JFrame.setDefaultCloseOperation is prohibited in jtreg Reviewed-by: prr, alexsch --- jdk/test/sanity/client/lib/SwingSet3/README | 2 +- .../src/com/sun/swingset3/demos/button/ButtonDemo.java | 1 - .../src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java | 1 - .../SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java | 1 - .../src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java | 1 - .../com/sun/swingset3/demos/progressbar/ProgressBarDemo.java | 1 - .../src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java | 1 - .../src/com/sun/swingset3/demos/spinner/SpinnerDemo.java | 1 - .../src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java | 1 - .../src/com/sun/swingset3/demos/textfield/TextFieldDemo.java | 1 - .../com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java | 1 - .../SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java | 1 - .../src/com/sun/swingset3/demos/window/WindowDemo.java | 1 - 13 files changed, 1 insertion(+), 13 deletions(-) diff --git a/jdk/test/sanity/client/lib/SwingSet3/README b/jdk/test/sanity/client/lib/SwingSet3/README index 1952a70cd26..cf0406460ef 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/README +++ b/jdk/test/sanity/client/lib/SwingSet3/README @@ -1,4 +1,4 @@ This content of this src folder was originally taken from SwingSet3 demo project: https://java.net/projects/swingset3/. Then it was modified to increase testability and remove extra content and extra dependencies. -Do NOT modify files in it. \ No newline at end of file +This is NOT the official location of the SwingSet3 demo. \ No newline at end of file diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java index 728e0543b68..e3aa888e5f3 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java @@ -215,7 +215,6 @@ public final class ButtonDemo extends JPanel { javax.swing.SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(buttonDemo); frame.pack(); frame.setVisible(true); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java index 5fc080f95bb..f204e64437d 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java @@ -120,7 +120,6 @@ public class ComboBoxDemo extends JPanel implements ActionListener { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ComboBoxDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java index b8dce72ba9e..02b55129f60 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java @@ -90,7 +90,6 @@ public final class ListDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ListDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java index 0e8c1e46a13..ca04135c2a1 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java @@ -93,7 +93,6 @@ public class OptionPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new OptionPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java index e49b47926ea..5e9d38bd7a3 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java @@ -64,7 +64,6 @@ public class ProgressBarDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ProgressBarDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java index 5a492ea53fd..40fb29cfaa6 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java @@ -64,7 +64,6 @@ public class ScrollPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ScrollPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java index 0694a843341..97dbd2d5002 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java @@ -58,7 +58,6 @@ public class SpinnerDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new SpinnerDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java index 0bc0cd78f0f..64bc9b2ccaf 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java @@ -86,7 +86,6 @@ public class SplitPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new SplitPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java index be7c9a7e7d0..16537bfccf5 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java @@ -115,7 +115,6 @@ public class TextFieldDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TextFieldDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java index 5adf5f7a62b..625c9fe1fda 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java @@ -151,7 +151,6 @@ public class ToggleButtonDemo extends JPanel implements ChangeListener { public static void main(String[] args) { JFrame frame = new JFrame(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ToggleButtonDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java index 1a4c555945e..e6f8e326571 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java @@ -65,7 +65,6 @@ public class TreeDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TreeDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java index cf83135d1e8..89b87776ba2 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java @@ -150,7 +150,6 @@ public final class WindowDemo extends JPanel { JFrame frame = new JFrame(); WindowDemo demo = new WindowDemo(); frame.add(demo); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); demo.start(); From 16ee51bad76c18e8fe7531a417073bee50c53998 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Tue, 19 Apr 2016 22:24:51 +0000 Subject: [PATCH 065/167] 8077360: Lower the number of providers created when using ServiceLoader Change ProviderLoader to be singleton and keep providers in java.base internal Reviewed-by: mullan --- jdk/src/java.base/share/classes/module-info.java | 6 +----- .../share/classes/sun/security/jca/ProviderConfig.java | 9 +++++---- .../share/classes/sun/security/jgss/SunProvider.java | 4 +--- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 8cc37dd7b2d..942c0582ea0 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -300,9 +300,5 @@ module java.base { provides java.nio.file.spi.FileSystemProvider with jdk.internal.jrtfs.JrtFileSystemProvider; - provides java.security.Provider with sun.security.provider.Sun; - provides java.security.Provider with sun.security.rsa.SunRsaSign; - provides java.security.Provider with com.sun.crypto.provider.SunJCE; - provides java.security.Provider with com.sun.net.ssl.internal.ssl.Provider; } diff --git a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java index 4ab324914bd..bf65180af6f 100644 --- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java +++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,9 +236,8 @@ final class ProviderConfig { if (debug != null) { debug.println("Loading provider " + ProviderConfig.this); } - ProviderLoader pl = new ProviderLoader(); try { - Provider p = pl.load(provName); + Provider p = ProviderLoader.INSTANCE.load(provName); if (p != null) { if (hasArgument()) { p = p.configure(argument); @@ -303,9 +302,11 @@ final class ProviderConfig { // Inner class for loading security providers listed in java.security file private static final class ProviderLoader { + static final ProviderLoader INSTANCE = new ProviderLoader(); + private final ServiceLoader services; - ProviderLoader() { + private ProviderLoader() { // VM should already been booted at this point, if not // - Only providers in java.base should be loaded, don't use // ServiceLoader diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java index ece97a92afd..3e664d7cccc 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,8 +97,6 @@ public final class SunProvider extends Provider { } } - public static final SunProvider INSTANCE = new SunProvider(); - public SunProvider() { /* We are the Sun JGSS provider */ super("SunJGSS", 9.0d, INFO); From 89499e85dbb74c8b6b24ee6cc3400528284944b9 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Tue, 19 Apr 2016 22:25:41 +0000 Subject: [PATCH 066/167] 8153371: Remove sun.misc.ManagedLocalsThread from jdk.crypto.pkcs11 Replace usage of ManagedLocalsThread with the new Thread constructor Reviewed-by: xuelei, chegar --- jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java | 4 +--- .../share/classes/sun/security/pkcs11/SunPKCS11.java | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java index 065b8d2f000..07f4c1bf3e1 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ module jdk.crypto.pkcs11 { // Depends on SunEC provider for EC related functionality requires jdk.crypto.ec; - // 8153371 - requires jdk.unsupported; provides java.security.Provider with sun.security.pkcs11.SunPKCS11; } diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java index de0bef55897..890587ad790 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ import javax.security.auth.callback.ConfirmationCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.TextOutputCallback; -import sun.misc.ManagedLocalsThread; import sun.security.util.Debug; import sun.security.util.ResourcesMgr; @@ -816,7 +815,7 @@ public final class SunPKCS11 extends AuthProvider { return; } final TokenPoller poller = new TokenPoller(this); - Thread t = new ManagedLocalsThread(poller, "Poller " + getName()); + Thread t = new Thread(null, poller, "Poller " + getName(), 0, false); t.setDaemon(true); t.setPriority(Thread.MIN_PRIORITY); t.start(); From a6a4976af0bde57f4757919da08d7089a3ebe2c1 Mon Sep 17 00:00:00 2001 From: Rajan Halade Date: Tue, 19 Apr 2016 18:09:58 -0700 Subject: [PATCH 067/167] 8137231: sun/security/rsa/SpecTest.java timeout with Agent error: java.lang.Exception Reviewed-by: valeriep --- jdk/test/sun/security/rsa/SpecTest.java | 84 +++++++++++-------------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/jdk/test/sun/security/rsa/SpecTest.java b/jdk/test/sun/security/rsa/SpecTest.java index c13f1d91989..24cddfe3591 100644 --- a/jdk/test/sun/security/rsa/SpecTest.java +++ b/jdk/test/sun/security/rsa/SpecTest.java @@ -20,32 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/** + * @test + * @bug 8044199 8137231 + * @key intermittent + * @summary Check same KeyPair's private key and public key have same modulus. + * also check public key's public exponent equals to given spec's public + * exponent. Only key size 1024 is tested with RSAKeyGenParameterSpec.F0 (3). + * @run main SpecTest 512 + * @run main SpecTest 768 + * @run main SpecTest 1024 + * @run main SpecTest 1024 3 + * @run main SpecTest 2048 + * @run main/timeout=240 SpecTest 4096 + * @run main/timeout=240 SpecTest 5120 + */ import java.math.BigInteger; -import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.interfaces.RSAKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.RSAKeyGenParameterSpec; -/** - * @test - * @bug 8044199 - * @key intermittent - * @summary Check same KeyPair's private key and public key have same modulus. - * also check public key's public exponent equals to given spec's public - * exponent. - * @run main SpecTest 512 - * @run main SpecTest 768 - * @run main SpecTest 1024 - * @run main SpecTest 2048 - * @run main/timeout=240 SpecTest 4096 - * @run main/timeout=240 SpecTest 5120 - */ public class SpecTest { + /** * ALGORITHM name, fixed as RSA. */ @@ -70,14 +70,14 @@ public class SpecTest { // test the getModulus method if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) { if (!priv.getModulus().equals(pub.getModulus())) { - System.err.println("priv.getModulus() = " + priv.getModulus()); - System.err.println("pub.getModulus() = " + pub.getModulus()); + System.out.println("priv.getModulus() = " + priv.getModulus()); + System.out.println("pub.getModulus() = " + pub.getModulus()); passed = false; } if (!pubExponent.equals(pub.getPublicExponent())) { - System.err.println("pubExponent = " + pubExponent); - System.err.println("pub.getPublicExponent() = " + System.out.println("pubExponent = " + pubExponent); + System.out.println("pub.getPublicExponent() = " + pub.getPublicExponent()); passed = false; } @@ -85,36 +85,26 @@ public class SpecTest { return passed; } - public static void main(String[] args) { - int failCount = 0; + public static void main(String[] args) throws Exception { - // Test key size. - int size = Integer.parseInt(args[0]); + int size = 0; - try { - KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); - kpg1.initialize(new RSAKeyGenParameterSpec(size, - RSAKeyGenParameterSpec.F4)); - if (!specTest(kpg1.generateKeyPair(), - RSAKeyGenParameterSpec.F4)) { - failCount++; - } - - KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); - kpg2.initialize(new RSAKeyGenParameterSpec(size, - RSAKeyGenParameterSpec.F0)); - if (!specTest(kpg2.generateKeyPair(), RSAKeyGenParameterSpec.F0)) { - failCount++; - } - } catch (NoSuchAlgorithmException | NoSuchProviderException - | InvalidAlgorithmParameterException ex) { - ex.printStackTrace(System.err); - failCount++; + if (args.length >= 1) { + size = Integer.parseInt(args[0]); + } else { + throw new RuntimeException("Missing keysize to test with"); } - if (failCount != 0) { - throw new RuntimeException("There are " + failCount - + " tests failed."); + BigInteger publicExponent + = (args.length >= 2) ? new BigInteger(args[1]) : RSAKeyGenParameterSpec.F4; + + System.out.println("Running test with key size: " + size + + " and public exponent: " + publicExponent); + + KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); + kpg1.initialize(new RSAKeyGenParameterSpec(size, publicExponent)); + if (!specTest(kpg1.generateKeyPair(), publicExponent)) { + throw new RuntimeException("Test failed."); } } } From 187b51a62cbdb386f263fbbe7ef74f20d514ffb0 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Wed, 20 Apr 2016 00:35:02 -0700 Subject: [PATCH 068/167] 8154543: NetworkInterfaceStreamTest.java fails intermittently after JDK-8146758 Reviewed-by: chegar --- .../java/net/NetworkInterface/NetworkInterfaceStreamTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java index 08075ac7472..1fa3a557941 100644 --- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java +++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java @@ -51,7 +51,8 @@ public class NetworkInterfaceStreamTest extends OpTestCase { public void testNetworkInterfaces() throws SocketException { Supplier> ss = () -> { try { - return allNetworkInterfaces(); + return NetworkInterface.networkInterfaces() + .filter(ni -> isIncluded(ni)); } catch (SocketException e) { throw new RuntimeException(e); From 611a14587e919590c6609a2c3ae419978a3747d9 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 20 Apr 2016 16:47:12 +0100 Subject: [PATCH 069/167] 8154707: java/util/ServiceLoader/modules/BasicTest.java failing Reviewed-by: chegar --- .../modules/{BasicTest.java => MiscTests.java} | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) rename jdk/test/java/util/ServiceLoader/modules/{BasicTest.java => MiscTests.java} (82%) diff --git a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java similarity index 82% rename from jdk/test/java/util/ServiceLoader/modules/BasicTest.java rename to jdk/test/java/util/ServiceLoader/modules/MiscTests.java index 3b64a1d7d9a..5a99a30737c 100644 --- a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java +++ b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java @@ -30,11 +30,11 @@ import static org.testng.Assert.*; /* * @test - * @run testng BasicTest + * @run testng MiscTests * @summary Basic test of ServiceLoader with modules */ -public class BasicTest { +public class MiscTests { @Test public void testEmptyLayer() { @@ -43,18 +43,6 @@ public class BasicTest { assertFalse(sl.iterator().hasNext()); } - @Test - public void testBootLayer() { - ServiceLoader sl - = ServiceLoader.load(Layer.boot(), Provider.class); - boolean found = false; - for (Provider provider : sl) { - if (provider.getName().equals("SunJCE")) - found = true; - } - assertTrue(found); - } - @Test(expectedExceptions = { NullPointerException.class }) public void testNullLayer() { ServiceLoader.load(null, Provider.class); From 29fc25717aa618bb32b0da5bc255d4a9b4018055 Mon Sep 17 00:00:00 2001 From: Sean Coffey Date: Wed, 20 Apr 2016 22:46:47 +0100 Subject: [PATCH 070/167] 8071125: Improve exception messages in URLPermission Reviewed-by: chegar, prappo --- .../share/classes/java/net/URLPermission.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/net/URLPermission.java b/jdk/src/java.base/share/classes/java/net/URLPermission.java index 78373e1087f..e188c81d73b 100644 --- a/jdk/src/java.base/share/classes/java/net/URLPermission.java +++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java @@ -170,7 +170,8 @@ public final class URLPermission extends Permission { parseURI(getName()); int colon = actions.indexOf(':'); if (actions.lastIndexOf(':') != colon) { - throw new IllegalArgumentException("invalid actions string"); + throw new IllegalArgumentException( + "Invalid actions string: \"" + actions + "\""); } String methods, headers; @@ -371,7 +372,8 @@ public final class URLPermission extends Permission { l.add(s); b = new StringBuilder(); } else if (c == ' ' || c == '\t') { - throw new IllegalArgumentException("white space not allowed"); + throw new IllegalArgumentException( + "White space not allowed in methods: \"" + methods + "\""); } else { if (c >= 'a' && c <= 'z') { c += 'A' - 'a'; @@ -398,7 +400,8 @@ public final class URLPermission extends Permission { } b.append(c); } else if (c == ' ' || c == '\t') { - throw new IllegalArgumentException("white space not allowed"); + throw new IllegalArgumentException( + "White space not allowed in headers: \"" + headers + "\""); } else if (c == '-') { capitalizeNext = true; b.append(c); @@ -423,14 +426,16 @@ public final class URLPermission extends Permission { int len = url.length(); int delim = url.indexOf(':'); if (delim == -1 || delim + 1 == len) { - throw new IllegalArgumentException("invalid URL string"); + throw new IllegalArgumentException( + "Invalid URL string: \"" + url + "\""); } scheme = url.substring(0, delim).toLowerCase(); this.ssp = url.substring(delim + 1); if (!ssp.startsWith("//")) { if (!ssp.equals("*")) { - throw new IllegalArgumentException("invalid URL string"); + throw new IllegalArgumentException( + "Invalid URL string: \"" + url + "\""); } this.authority = new Authority(scheme, "*"); return; From 6e3d77a8bacc227b4bfbdab0ec4c23f02adf92cd Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 20 Apr 2016 15:06:13 -0700 Subject: [PATCH 071/167] 8154183: (spec) Spec of read(byte[],int,int) and readFully(byte[],int,int) is confusing/incomplete Clarify and expand specification of ObjectInputStream.read(byte[],int,int) and both variants of {DataInput,DataInputStream,ObjectInputStream,RandomAccessfile}.readFully(). Reviewed-by: rriggs, smarks --- .../share/classes/java/io/DataInput.java | 27 ++++++++------- .../classes/java/io/DataInputStream.java | 33 +++++++++++-------- .../classes/java/io/ObjectInputStream.java | 13 ++++++-- .../classes/java/io/RandomAccessFile.java | 27 ++++++++------- 4 files changed, 62 insertions(+), 38 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/io/DataInput.java b/jdk/src/java.base/share/classes/java/io/DataInput.java index dca9187d4a7..60e03c2173c 100644 --- a/jdk/src/java.base/share/classes/java/io/DataInput.java +++ b/jdk/src/java.base/share/classes/java/io/DataInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,10 +182,11 @@ interface DataInput { * not all bytes of {@code b} have been * updated with data from the input stream. * - * @param b the buffer into which the data is read. - * @exception EOFException if this stream reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this stream reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ void readFully(byte b[]) throws IOException; @@ -226,12 +227,16 @@ interface DataInput { * and so on. The number of bytes read is, * at most, equal to {@code len}. * - * @param b the buffer into which the data is read. - * @param off an int specifying the offset into the data. - * @param len an int specifying the number of bytes to read. - * @exception EOFException if this stream reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @param off an int specifying the offset in the data array {@code b}. + * @param len an int specifying the number of bytes to read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. + * @throws EOFException if this stream reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ void readFully(byte b[], int off, int len) throws IOException; diff --git a/jdk/src/java.base/share/classes/java/io/DataInputStream.java b/jdk/src/java.base/share/classes/java/io/DataInputStream.java index 6ce6b233ee6..f92c4f91b0c 100644 --- a/jdk/src/java.base/share/classes/java/io/DataInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/DataInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,38 +150,43 @@ class DataInputStream extends FilterInputStream implements DataInput { } /** - * See the general contract of the readFully - * method of DataInput. + * See the general contract of the {@code readFully} + * method of {@code DataInput}. *

* Bytes * for this operation are read from the contained * input stream. * - * @param b the buffer into which the data is read. - * @exception EOFException if this input stream reaches the end before - * reading all the bytes. - * @exception IOException the stream has been closed and the contained - * input stream does not support reading after close, or - * another I/O error occurs. - * @see java.io.FilterInputStream#in + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this input stream reaches the end before + * reading all the bytes. + * @throws IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in */ public final void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); } /** - * See the general contract of the readFully - * method of DataInput. + * See the general contract of the {@code readFully} + * method of {@code DataInput}. *

* Bytes * for this operation are read from the contained * input stream. * * @param b the buffer into which the data is read. - * @param off the start offset of the data. + * @param off the start offset in the data array {@code b}. * @param len the number of bytes to read. + * @exception NullPointerException if {@code b} is {@code null}. + * @exception IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. * @exception EOFException if this input stream reaches the end before - * reading all the bytes. + * reading all the bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index cd040d3d7e5..a591136419d 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -856,10 +856,14 @@ public class ObjectInputStream * exactly 'length' bytes. * * @param buf the buffer into which the data is read - * @param off the start offset of the data + * @param off the start offset in the destination array {@code buf} * @param len the maximum number of bytes read * @return the actual number of bytes read, -1 is returned when the end of * the stream is reached. + * @throws NullPointerException if {@code buf} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code buf.length - off}. * @throws IOException If an I/O error has occurred. * @see java.io.DataInputStream#readFully(byte[],int,int) */ @@ -1017,6 +1021,7 @@ public class ObjectInputStream * Reads bytes, blocking until all bytes are read. * * @param buf the buffer into which the data is read + * @throws NullPointerException If {@code buf} is {@code null}. * @throws EOFException If end of file is reached. * @throws IOException If other I/O error has occurred. */ @@ -1028,8 +1033,12 @@ public class ObjectInputStream * Reads bytes, blocking until all bytes are read. * * @param buf the buffer into which the data is read - * @param off the start offset of the data + * @param off the start offset into the data array {@code buf} * @param len the maximum number of bytes to read + * @throws NullPointerException If {@code buf} is {@code null}. + * @throws IndexOutOfBoundsException If {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code buf.length - off}. * @throws EOFException If end of file is reached. * @throws IOException If other I/O error has occurred. */ diff --git a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java index db6ae71f89f..1a8344df88b 100644 --- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -418,10 +418,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * read. This method blocks until the requested number of bytes are * read, the end of the stream is detected, or an exception is thrown. * - * @param b the buffer into which the data is read. - * @exception EOFException if this file reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this file reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ public final void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); @@ -434,12 +435,16 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * read. This method blocks until the requested number of bytes are * read, the end of the stream is detected, or an exception is thrown. * - * @param b the buffer into which the data is read. - * @param off the start offset of the data. - * @param len the number of bytes to read. - * @exception EOFException if this file reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @param off the start offset into the data array {@code b}. + * @param len the number of bytes to read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. + * @throws EOFException if this file reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ public final void readFully(byte b[], int off, int len) throws IOException { int n = 0; From b909478b3d0e4d165ce32d49e43dc22f494974eb Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Thu, 21 Apr 2016 14:56:40 +0800 Subject: [PATCH 072/167] 8152936: java/lang/Class/GetPackageTest.java needs update to work with newer testng Reviewed-by: alanb --- jdk/test/java/lang/Class/GetPackageTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/lang/Class/GetPackageTest.java b/jdk/test/java/lang/Class/GetPackageTest.java index d1ffea75ecb..f9cb5fb31ff 100644 --- a/jdk/test/java/lang/Class/GetPackageTest.java +++ b/jdk/test/java/lang/Class/GetPackageTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ public class GetPackageTest { assertEquals(fooClass.getClassLoader(), loader); } - @DataProvider(name = "testclasses") + @DataProvider(name = "testClasses") public Object[][] testClasses() { return new Object[][] { // primitive type, void, array types From 2b5207e74decb484e85ef01e4dd6d30f2d5e1d4c Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 21 Apr 2016 13:39:53 +0200 Subject: [PATCH 073/167] 8154231: Simplify access to System properties from JDK code Reviewed-by: rriggs, chegar, weijun --- .../sun/nio/fs/LinuxFileSystemProvider.java | 4 +- .../sun/nio/ch/KQueueArrayWrapper.java | 8 +-- .../sun/nio/fs/MacOSXFileSystemProvider.java | 5 +- .../java.base/share/classes/java/io/File.java | 5 +- .../classes/java/lang/ProcessBuilder.java | 13 ++-- .../classes/java/lang/StackStreamFactory.java | 12 +--- .../invoke/InnerClassLambdaMetafactory.java | 3 +- .../java/lang/invoke/MethodHandleStatics.java | 51 +++++++--------- .../java/lang/invoke/StringConcatFactory.java | 18 +++--- .../java/lang/module/ModuleFinder.java | 3 +- .../classes/java/lang/reflect/Proxy.java | 7 +-- .../net/AbstractPlainDatagramSocketImpl.java | 5 +- .../share/classes/java/net/InetAddress.java | 7 +-- .../classes/java/net/SocksSocketImpl.java | 7 +-- .../java.base/share/classes/java/net/URL.java | 9 +-- .../share/classes/java/net/URLConnection.java | 5 +- .../share/classes/java/net/URLEncoder.java | 11 +--- .../classes/java/nio/charset/Charset.java | 7 +-- .../classes/java/nio/file/TempFileHelper.java | 3 +- .../share/classes/java/util/Locale.java | 34 +++++------ .../java/util/PropertyResourceBundle.java | 5 +- .../share/classes/java/util/TimeZone.java | 6 +- .../share/classes/java/util/jar/JarFile.java | 9 ++- .../share/classes/java/util/jar/Pack200.java | 4 +- .../util/regex/PatternSyntaxException.java | 3 +- .../java/util/zip/ZipOutputStream.java | 5 +- .../javax/net/ssl/SSLSocketFactory.java | 6 +- .../java.base/share/classes/jdk/Version.java | 10 +-- .../jdk/internal/loader/URLClassPath.java | 15 ++--- .../internal/logger/LoggerFinderLoader.java | 11 ++-- .../internal/logger/SimpleConsoleLogger.java | 10 +-- .../jdk/internal/reflect/Reflection.java | 16 ++--- .../internal/reflect/ReflectionFactory.java | 61 +++++++++---------- .../classes/sun/net/ResourceManager.java | 5 +- .../share/classes/sun/net/sdp/SdpSupport.java | 4 +- .../classes/sun/net/smtp/SmtpClient.java | 8 +-- .../classes/sun/net/www/MimeLauncher.java | 4 +- .../classes/sun/net/www/http/HttpClient.java | 14 ++--- .../www/protocol/ftp/FtpURLConnection.java | 10 +-- .../protocol/http/AuthenticationHeader.java | 6 +- .../www/protocol/http/HttpURLConnection.java | 46 ++++++-------- .../net/www/protocol/https/HttpsClient.java | 12 ++-- .../jrt/JavaRuntimeURLConnection.java | 10 +-- .../sun/net/www/protocol/netdoc/Handler.java | 9 ++- .../classes/sun/nio/ch/FileChannelImpl.java | 5 +- .../share/classes/sun/nio/ch/Net.java | 21 ++----- .../share/classes/sun/nio/ch/Util.java | 11 +--- .../sun/nio/cs/StandardCharsets.java.template | 13 +--- .../share/classes/sun/nio/fs/Util.java | 5 +- .../sun/security/action/GetIntegerAction.java | 39 +++++++++++- .../security/action/GetPropertyAction.java | 60 +++++++++++++++++- .../sun/security/provider/DSAKeyFactory.java | 3 +- .../sun/security/rsa/RSAKeyFactory.java | 5 +- .../ssl/ClientKeyExchangeService.java | 5 +- .../share/classes/sun/security/ssl/Debug.java | 7 +-- .../sun/security/ssl/SSLContextImpl.java | 3 +- .../sun/security/ssl/ServerHandshaker.java | 4 +- .../security/ssl/StatusResponseManager.java | 4 +- .../classes/sun/security/util/Debug.java | 10 ++- .../util/calendar/LocalGregorianCalendar.java | 5 +- .../sun/util/calendar/ZoneInfoFile.java | 11 ++-- .../provider/LocaleProviderAdapter.java | 5 +- .../classes/sun/nio/fs/SolarisFileSystem.java | 4 +- .../sun/nio/fs/SolarisFileSystemProvider.java | 5 +- .../unix/classes/java/io/UnixFileSystem.java | 12 ++-- .../unix/classes/java/lang/ProcessImpl.java | 14 ++--- .../net/DefaultDatagramSocketImplFactory.java | 5 +- .../unix/classes/sun/net/sdp/SdpProvider.java | 7 +-- .../http/ntlm/NTLMAuthentication.java | 13 ++-- .../DefaultAsynchronousChannelProvider.java | 4 +- .../ch/UnixAsynchronousSocketChannelImpl.java | 5 +- .../sun/nio/fs/DefaultFileSystemProvider.java | 4 +- .../classes/sun/nio/fs/UnixFileSystem.java | 5 +- .../classes/java/io/WinNTFileSystem.java | 9 ++- .../net/DefaultDatagramSocketImplFactory.java | 13 ++-- .../http/ntlm/NTLMAuthentication.java | 6 +- .../sun/nio/ch/FileDispatcherImpl.java | 11 +--- .../sun/nio/fs/WindowsFileAttributes.java | 5 +- 78 files changed, 391 insertions(+), 453 deletions(-) diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java index f6abaf69d7e..8a2307d2ff6 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java @@ -102,8 +102,8 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + String userHome = GetPropertyAction.getProperty("user.home"); + Path userMimeTypes = Paths.get(userHome, ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); return chain(new GioFileTypeDetector(), diff --git a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java index 2aa3fbcbaa2..7598cf9e37f 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java @@ -32,9 +32,9 @@ package sun.nio.ch; import java.io.IOException; -import java.io.FileDescriptor; import java.util.Iterator; import java.util.LinkedList; +import sun.security.action.GetPropertyAction; /* * struct kevent { // 32-bit 64-bit @@ -84,10 +84,8 @@ class KQueueArrayWrapper { static { IOUtil.load(); initStructSizes(); - String datamodel = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.arch.data.model") - ); - is64bit = datamodel.equals("64"); + String datamodel = GetPropertyAction.getProperty("sun.arch.data.model"); + is64bit = "64".equals(datamodel); } KQueueArrayWrapper() { diff --git a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java index 0dcee95bfc3..6b9a56a9fa7 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.spi.FileTypeDetector; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -47,8 +46,8 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + Path userMimeTypes = Paths.get( + GetPropertyAction.getProperty("user.home"), ".mime.types"); return chain(new MimeTypesFileTypeDetector(userMimeTypes), new UTIFileTypeDetector()); diff --git a/jdk/src/java.base/share/classes/java/io/File.java b/jdk/src/java.base/share/classes/java/io/File.java index 089171bab9e..7f23340920b 100644 --- a/jdk/src/java.base/share/classes/java/io/File.java +++ b/jdk/src/java.base/share/classes/java/io/File.java @@ -31,7 +31,6 @@ import java.net.MalformedURLException; import java.net.URISyntaxException; import java.util.List; import java.util.ArrayList; -import java.security.AccessController; import java.security.SecureRandom; import java.nio.file.Path; import java.nio.file.FileSystems; @@ -1896,8 +1895,8 @@ public class File private TempDirectory() { } // temporary directory location - private static final File tmpdir = new File(AccessController - .doPrivileged(new GetPropertyAction("java.io.tmpdir"))); + private static final File tmpdir = new File( + GetPropertyAction.getProperty("java.io.tmpdir")); static File location() { return tmpdir; } diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index ebd47fcfe87..638be0e9f72 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -30,13 +30,12 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.Pipe; import java.util.Arrays; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.security.AccessController; -import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + /** * This class is used to create operating system processes. * @@ -468,11 +467,9 @@ public final class ProcessBuilder * @since 1.7 */ public abstract static class Redirect { - private static final File NULL_FILE = AccessController.doPrivileged( - (PrivilegedAction) () -> { - return new File((System.getProperty("os.name") - .startsWith("Windows") ? "NUL" : "/dev/null")); - } + private static final File NULL_FILE = new File( + (GetPropertyAction.getProperty("os.name") + .startsWith("Windows") ? "NUL" : "/dev/null") ); /** diff --git a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java index 8dccef351fe..73446062bea 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -30,8 +30,6 @@ import java.lang.StackWalker.StackFrame; import java.lang.annotation.Native; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Objects; @@ -41,6 +39,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import sun.security.action.GetPropertyAction; import static java.lang.StackStreamFactory.WalkerState.*; @@ -990,14 +989,9 @@ final class StackStreamFactory { } private static boolean getProperty(String key, boolean value) { - String s = AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public String run() { - return System.getProperty(key); - } - }); + String s = GetPropertyAction.getProperty(key); if (s != null) { - return Boolean.valueOf(s); + return Boolean.parseBoolean(s); } return value; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 739573507ab..a0df622f501 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -88,8 +88,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; static { final String key = "jdk.internal.lambda.dumpProxyClasses"; - String path = AccessController.doPrivileged( - new GetPropertyAction(key)); + String path = GetPropertyAction.getProperty(key); dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index df1cba46fa8..4fbc1d84671 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -25,9 +25,9 @@ package java.lang.invoke; -import java.security.AccessController; -import java.security.PrivilegedAction; +import java.util.Properties; import jdk.internal.misc.Unsafe; +import sun.security.action.GetPropertyAction; /** * This class consists exclusively of static names internal to the @@ -53,32 +53,27 @@ import jdk.internal.misc.Unsafe; static final boolean VAR_HANDLE_GUARDS; static { - final Object[] values = new Object[10]; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); - values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"); - values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"); - values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); - values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0); - values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); - values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); - values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true")); - values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127); - values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true")); - return null; - } - }); - DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0]; - DUMP_CLASS_FILES = (Boolean) values[1]; - TRACE_INTERPRETER = (Boolean) values[2]; - TRACE_METHOD_LINKAGE = (Boolean) values[3]; - COMPILE_THRESHOLD = (Integer) values[4]; - DONT_INLINE_THRESHOLD = (Integer) values[5]; - PROFILE_LEVEL = (Integer) values[6]; - PROFILE_GWT = (Boolean) values[7]; - CUSTOMIZE_THRESHOLD = (Integer) values[8]; - VAR_HANDLE_GUARDS = (Boolean) values[9]; + Properties props = GetPropertyAction.getProperties(); + DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES")); + DUMP_CLASS_FILES = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES")); + TRACE_INTERPRETER = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER")); + TRACE_METHOD_LINKAGE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE")); + COMPILE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0")); + DONT_INLINE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", "30")); + PROFILE_LEVEL = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.PROFILE_LEVEL", "0")); + PROFILE_GWT = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true")); + CUSTOMIZE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", "127")); + VAR_HANDLE_GUARDS = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true")); if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) { throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range"); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 6469a4b8a6d..44f29a4a136 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -33,7 +33,6 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.misc.Unsafe; import java.lang.invoke.MethodHandles.Lookup; -import java.security.AccessController; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -188,14 +187,15 @@ public final class StringConcatFactory { private static final ProxyClassesDumper DUMPER; static { - final String strategy = AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat")); - CACHE_ENABLE = Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.cache"))); - DEBUG = Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.debug"))); - final String dumpPath = AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.dumpClasses")); + Properties props = GetPropertyAction.getProperties(); + final String strategy = + props.getProperty("java.lang.invoke.stringConcat"); + CACHE_ENABLE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.stringConcat.cache")); + DEBUG = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.stringConcat.debug")); + final String dumpPath = + props.getProperty("java.lang.invoke.stringConcat.dumpClasses"); STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy); CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null; diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java index 83d8fc59aaf..1cdd12838b1 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -39,6 +39,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import sun.security.action.GetPropertyAction; /** * A finder of modules. A {@code ModuleFinder} is used to find modules during @@ -152,7 +153,7 @@ public interface ModuleFinder { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - PrivilegedAction pa = () -> System.getProperty("java.home"); + PrivilegedAction pa = new GetPropertyAction("java.home"); home = AccessController.doPrivileged(pa); Permission p = new FilePermission(home + File.separator + "-", "read"); sm.checkPermission(p); diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java index 12abe79d4ea..8802abeda76 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -50,6 +50,7 @@ import jdk.internal.misc.VM; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import sun.reflect.misc.ReflectUtil; +import sun.security.action.GetPropertyAction; import sun.security.util.SecurityConstants; /** @@ -581,11 +582,7 @@ public class Proxy implements java.io.Serializable { } private static final String DEBUG = - AccessController.doPrivileged(new PrivilegedAction<>() { - public String run() { - return System.getProperty("jdk.proxy.debug", ""); - } - }); + GetPropertyAction.getProperty("jdk.proxy.debug", ""); private static boolean isDebug() { return !DEBUG.isEmpty(); diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index 7a9b7fc17ed..debc60f74b9 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -31,6 +31,7 @@ import sun.net.ResourceManager; import java.util.Set; import java.util.HashSet; import java.util.Collections; +import sun.security.action.GetPropertyAction; /** * Abstract datagram and multicast socket implementation base class. @@ -51,9 +52,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl protected InetAddress connectedAddress = null; private int connectedPort = -1; - private static final String os = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("os.name") - ); + private static final String os = GetPropertyAction.getProperty("os.name"); /** * flag set if the native connect() call not to be used diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index 8e0d46152ff..e79c5115413 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -1123,8 +1123,8 @@ class InetAddress implements java.io.Serializable { */ private static NameService createNameService() { - String hostsFileName = AccessController - .doPrivileged(new GetPropertyAction("jdk.net.hosts.file")); + String hostsFileName = + GetPropertyAction.getProperty("jdk.net.hosts.file"); NameService theNameService; if (hostsFileName != null) { theNameService = new HostsFileNameService(hostsFileName); @@ -1643,8 +1643,7 @@ class InetAddress implements java.io.Serializable { * property can vary across implementations of the java. * classes. The default is an empty String "". */ - String prefix = AccessController.doPrivileged( - new GetPropertyAction("impl.prefix", "")); + String prefix = GetPropertyAction.getProperty("impl.prefix", ""); try { impl = Class.forName("java.net." + prefix + implName).newInstance(); } catch (ClassNotFoundException e) { diff --git a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java index f7974d0d705..c3a0d1c675a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java @@ -33,6 +33,7 @@ import java.security.PrivilegedExceptionAction; import sun.net.SocksProxy; import sun.net.spi.DefaultProxySelector; import sun.net.www.ParseUtil; +import sun.security.action.GetPropertyAction; /* import org.ietf.jgss.*; */ /** @@ -177,8 +178,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = pw.getUserName(); password = new String(pw.getPassword()); } else { - userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + userName = GetPropertyAction.getProperty("user.name"); } if (userName == null) return false; @@ -1088,8 +1088,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = System.getProperty("user.name"); } catch (SecurityException se) { /* swallow Exception */ } } else { - userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + userName = GetPropertyAction.getProperty("user.name"); } return userName; } diff --git a/jdk/src/java.base/share/classes/java/net/URL.java b/jdk/src/java.base/share/classes/java/net/URL.java index cce9cf9425a..099e8b9e0c8 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -42,6 +42,7 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import sun.security.util.SecurityConstants; +import sun.security.action.GetPropertyAction; /** * Class {@code URL} represents a Uniform Resource @@ -1210,12 +1211,8 @@ public final class URL implements java.io.Serializable { } private static URLStreamHandler lookupViaProperty(String protocol) { - String packagePrefixList = java.security.AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - return System.getProperty(protocolPathProp, null); - } - }); + String packagePrefixList = + GetPropertyAction.getProperty(protocolPathProp); if (packagePrefixList == null) { // not set return null; diff --git a/jdk/src/java.base/share/classes/java/net/URLConnection.java b/jdk/src/java.base/share/classes/java/net/URLConnection.java index 87f4378b2ad..459a820bcde 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -43,6 +43,7 @@ import java.security.Permission; import java.security.AccessController; import sun.security.util.SecurityConstants; import sun.net.www.MessageHeader; +import sun.security.action.GetPropertyAction; /** * The abstract class {@code URLConnection} is the superclass @@ -1395,8 +1396,8 @@ public abstract class URLConnection { * is always the last one on the returned package list. */ private String getContentHandlerPkgPrefixes() { - String packagePrefixList = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(contentPathProp, "")); + String packagePrefixList = + GetPropertyAction.getProperty(contentPathProp, ""); if (packagePrefixList != "") { packagePrefixList += "|"; diff --git a/jdk/src/java.base/share/classes/java/net/URLEncoder.java b/jdk/src/java.base/share/classes/java/net/URLEncoder.java index 5ad817bc72c..2f2c3e6c9c4 100644 --- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java +++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java @@ -25,19 +25,12 @@ package java.net; -import java.io.ByteArrayOutputStream; -import java.io.BufferedWriter; -import java.io.OutputStreamWriter; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.CharArrayWriter; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException ; import java.util.BitSet; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetBooleanAction; import sun.security.action.GetPropertyAction; /** @@ -140,9 +133,7 @@ public class URLEncoder { dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); - dfltEncName = AccessController.doPrivileged( - new GetPropertyAction("file.encoding") - ); + dfltEncName = GetPropertyAction.getProperty("file.encoding"); } /** diff --git a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java index 78ee33e764a..de49a8c6271 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java @@ -283,8 +283,8 @@ public abstract class Charset if (level == null) { if (!VM.isBooted()) return false; - bugLevel = level = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.cs.bugLevel", "")); + bugLevel = level = + GetPropertyAction.getProperty("sun.nio.cs.bugLevel", ""); } return level.equals(bl); } @@ -609,8 +609,7 @@ public abstract class Charset public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { - String csn = AccessController.doPrivileged( - new GetPropertyAction("file.encoding")); + String csn = GetPropertyAction.getProperty("file.encoding"); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs; diff --git a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java index 2bc3d992c60..a6af1a15b1f 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java +++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java @@ -28,7 +28,6 @@ package java.nio.file; import java.util.Set; import java.util.EnumSet; import java.security.SecureRandom; -import static java.security.AccessController.*; import java.io.IOException; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; @@ -47,7 +46,7 @@ class TempFileHelper { // temporary directory location private static final Path tmpdir = - Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir"))); + Paths.get(GetPropertyAction.getProperty("java.io.tmpdir")); private static final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); diff --git a/jdk/src/java.base/share/classes/java/util/Locale.java b/jdk/src/java.base/share/classes/java/util/Locale.java index 2d121e2e7ef..e05904f6f6b 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -45,7 +45,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.io.Serializable; -import java.security.AccessController; import java.text.MessageFormat; import java.util.spi.LocaleNameProvider; @@ -859,11 +858,10 @@ public final class Locale implements Cloneable, Serializable { private static Locale initDefault() { String language, region, script, country, variant; - language = AccessController.doPrivileged( - new GetPropertyAction("user.language", "en")); + Properties props = GetPropertyAction.getProperties(); + language = props.getProperty("user.language", "en"); // for compatibility, check for old user.region property - region = AccessController.doPrivileged( - new GetPropertyAction("user.region")); + region = props.getProperty("user.region"); if (region != null) { // region can be of form country, country_variant, or _variant int i = region.indexOf('_'); @@ -876,27 +874,25 @@ public final class Locale implements Cloneable, Serializable { } script = ""; } else { - script = AccessController.doPrivileged( - new GetPropertyAction("user.script", "")); - country = AccessController.doPrivileged( - new GetPropertyAction("user.country", "")); - variant = AccessController.doPrivileged( - new GetPropertyAction("user.variant", "")); + script = props.getProperty("user.script", ""); + country = props.getProperty("user.country", ""); + variant = props.getProperty("user.variant", ""); } return getInstance(language, script, country, variant, null); } private static Locale initDefault(Locale.Category category) { + Properties props = GetPropertyAction.getProperties(); return getInstance( - AccessController.doPrivileged( - new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())), - AccessController.doPrivileged( - new GetPropertyAction(category.scriptKey, defaultLocale.getScript())), - AccessController.doPrivileged( - new GetPropertyAction(category.countryKey, defaultLocale.getCountry())), - AccessController.doPrivileged( - new GetPropertyAction(category.variantKey, defaultLocale.getVariant())), + props.getProperty(category.languageKey, + defaultLocale.getLanguage()), + props.getProperty(category.scriptKey, + defaultLocale.getScript()), + props.getProperty(category.countryKey, + defaultLocale.getCountry()), + props.getProperty(category.variantKey, + defaultLocale.getVariant()), null); } diff --git a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java index 58ff7570269..9c20a680733 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -43,7 +43,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnmappableCharacterException; @@ -142,8 +141,8 @@ public class PropertyResourceBundle extends ResourceBundle { // Check whether the strict encoding is specified. // The possible encoding is either "ISO-8859-1" or "UTF-8". private static final String encoding = - AccessController.doPrivileged( - new GetPropertyAction("java.util.PropertyResourceBundle.encoding", "")) + GetPropertyAction + .getProperty("java.util.PropertyResourceBundle.encoding", "") .toUpperCase(Locale.ROOT); /** diff --git a/jdk/src/java.base/share/classes/java/util/TimeZone.java b/jdk/src/java.base/share/classes/java/util/TimeZone.java index 3bf886b2721..22c382cb0a2 100644 --- a/jdk/src/java.base/share/classes/java/util/TimeZone.java +++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java @@ -660,14 +660,12 @@ public abstract class TimeZone implements Serializable, Cloneable { private static synchronized TimeZone setDefaultZone() { TimeZone tz; // get the time zone ID from the system properties - String zoneID = AccessController.doPrivileged( - new GetPropertyAction("user.timezone")); + String zoneID = GetPropertyAction.getProperty("user.timezone"); // if the time zone ID is not set (yet), perform the // platform to Java time zone ID mapping. if (zoneID == null || zoneID.isEmpty()) { - String javaHome = AccessController.doPrivileged( - new GetPropertyAction("java.home")); + String javaHome = GetPropertyAction.getProperty("java.home"); try { zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index f28750c3a97..ff26faad4f4 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -34,7 +34,6 @@ import java.util.stream.StreamSupport; import java.util.zip.*; import java.security.CodeSigner; import java.security.cert.Certificate; -import java.security.AccessController; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; import sun.security.action.GetPropertyAction; @@ -155,16 +154,16 @@ class JarFile extends ZipFile { BASE_VERSION = 8; // one less than lowest version for versioned entries int runtimeVersion = jdk.Version.current().major(); - String jarVersion = AccessController.doPrivileged( - new GetPropertyAction("jdk.util.jar.version")); + String jarVersion = + GetPropertyAction.getProperty("jdk.util.jar.version"); if (jarVersion != null) { int jarVer = Integer.parseInt(jarVersion); runtimeVersion = (jarVer > runtimeVersion) ? runtimeVersion : Math.max(jarVer, 0); } RUNTIME_VERSION = runtimeVersion; - String enableMultiRelease = AccessController.doPrivileged( - new GetPropertyAction("jdk.util.jar.enableMultiRelease", "true")); + String enableMultiRelease = GetPropertyAction + .getProperty("jdk.util.jar.enableMultiRelease", "true"); switch (enableMultiRelease) { case "true": default: diff --git a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java index 44f1cccd080..ac47ad12032 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java @@ -29,6 +29,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.File; import java.io.IOException; +import sun.security.action.GetPropertyAction; /** @@ -694,8 +695,7 @@ public abstract class Pack200 { Class impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl; if (impl == null) { // The first time, we must decide which class to use. - implName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(prop,"")); + implName = GetPropertyAction.getProperty(prop,""); if (implName != null && !implName.equals("")) impl = Class.forName(implName); else if (PACK_PROVIDER.equals(prop)) diff --git a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java index 94d7abc78a5..f7768da27da 100644 --- a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java +++ b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java @@ -94,8 +94,7 @@ public class PatternSyntaxException } private static final String nl = - java.security.AccessController - .doPrivileged(new GetPropertyAction("line.separator")); + GetPropertyAction.getProperty("line.separator"); /** * Returns a multi-line string containing the description of the syntax diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 6b480aa1d5e..ff76017651b 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -33,6 +33,7 @@ import java.util.Vector; import java.util.HashSet; import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; +import sun.security.action.GetPropertyAction; /** * This class implements an output stream filter for writing files in the @@ -54,9 +55,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { */ private static final boolean inhibitZip64 = Boolean.parseBoolean( - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "jdk.util.zip.inhibitZip64", "false"))); + GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64")); private static class XEntry { final ZipEntry entry; diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java index 316016aac35..b436414308f 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -51,9 +51,9 @@ public abstract class SSLSocketFactory extends SocketFactory static final boolean DEBUG; static { - String s = java.security.AccessController.doPrivileged( - new GetPropertyAction("javax.net.debug", "")).toLowerCase( - Locale.ENGLISH); + String s = GetPropertyAction.getProperty("javax.net.debug", "") + .toLowerCase(Locale.ENGLISH); + DEBUG = s.contains("all") || s.contains("ssl"); } diff --git a/jdk/src/java.base/share/classes/jdk/Version.java b/jdk/src/java.base/share/classes/jdk/Version.java index 75c6b35c444..756af9ec051 100644 --- a/jdk/src/java.base/share/classes/jdk/Version.java +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -26,8 +26,6 @@ package jdk; import java.math.BigInteger; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,6 +33,7 @@ import java.util.stream.Collectors; import java.util.Collections; import java.util.List; import java.util.Optional; +import sun.security.action.GetPropertyAction; /** * A representation of the JDK version-string which contains a version @@ -274,12 +273,7 @@ public final class Version */ public static Version current() { if (current == null) { - current = parse(AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - return System.getProperty("java.version"); - } - })); + current = parse(GetPropertyAction.getProperty("java.version")); } return current; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java index 15688e1a573..234a86a9271 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java @@ -52,6 +52,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Properties; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; @@ -69,6 +70,7 @@ import jdk.internal.util.jar.InvalidJarIndexError; import jdk.internal.util.jar.JarIndex; import sun.net.util.URLUtil; import sun.net.www.ParseUtil; +import sun.security.action.GetPropertyAction; /** * This class is used to maintain a search path of URLs for loading classes @@ -78,20 +80,15 @@ import sun.net.www.ParseUtil; */ public class URLClassPath { private static final String USER_AGENT_JAVA_VERSION = "UA-Java-Version"; - private static final String JAVA_HOME; private static final String JAVA_VERSION; private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; static { - JAVA_HOME = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.home")); - JAVA_VERSION = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.version")); - DEBUG = (java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null); - String p = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking")); + Properties props = GetPropertyAction.getProperties(); + JAVA_VERSION = props.getProperty("java.version"); + DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); + String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java index 7d315ba7057..58f235d6ccd 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java @@ -33,6 +33,7 @@ import java.util.Locale; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import sun.security.util.SecurityConstants; +import sun.security.action.GetPropertyAction; /** * Helper class used to load the {@link java.lang.System.LoggerFinder}. @@ -79,9 +80,8 @@ public final class LoggerFinderLoader { // Get configuration error policy private static ErrorPolicy configurationErrorPolicy() { - final PrivilegedAction getConfigurationErrorPolicy = - () -> System.getProperty("jdk.logger.finder.error"); - String errorPolicy = AccessController.doPrivileged(getConfigurationErrorPolicy); + String errorPolicy = + GetPropertyAction.getProperty("jdk.logger.finder.error"); if (errorPolicy == null || errorPolicy.isEmpty()) { return ErrorPolicy.WARNING; } @@ -95,9 +95,8 @@ public final class LoggerFinderLoader { // Whether multiple provider should be considered as an error. // This is further submitted to the configuration error policy. private static boolean ensureSingletonProvider() { - final PrivilegedAction ensureSingletonProvider = - () -> Boolean.getBoolean("jdk.logger.finder.singleton"); - return AccessController.doPrivileged(ensureSingletonProvider); + return Boolean.parseBoolean( + GetPropertyAction.getProperty("jdk.logger.finder.singleton")); } private static Iterator findLoggerFinderProviders() { diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java index de4451fd35c..c90a7b24e38 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java @@ -55,8 +55,8 @@ public class SimpleConsoleLogger extends LoggerConfiguration PlatformLogger.toPlatformLevel(DEFAULT_LEVEL); static Level getDefaultLevel() { - String levelName = AccessController.doPrivileged( - new GetPropertyAction("jdk.system.logger.level", "INFO")); + String levelName = GetPropertyAction + .getProperty("jdk.system.logger.level", "INFO"); try { return Level.valueOf(levelName); } catch (IllegalArgumentException iae) { @@ -425,8 +425,8 @@ public class SimpleConsoleLogger extends LoggerConfiguration // Make it easier to wrap Logger... static private final String[] skips; static { - String additionalPkgs = AccessController.doPrivileged( - new GetPropertyAction("jdk.logger.packages")); + String additionalPkgs = + GetPropertyAction.getProperty("jdk.logger.packages"); skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(","); } @@ -485,7 +485,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration // jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java // to fail - because that test has a testcase which somehow references // PlatformLogger and counts the number of generated lambda classes. - String format = AccessController.doPrivileged(new GetPropertyAction(key)); + String format = GetPropertyAction.getProperty(key); if (format == null && defaultPropertyGetter != null) { format = defaultPropertyGetter.apply(key); diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 88e6a8349ca..636b0940345 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -27,13 +27,12 @@ package jdk.internal.reflect; import java.lang.reflect.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.misc.VM; +import sun.security.action.GetPropertyAction; /** Common utility routines used by both java.lang and java.lang.reflect */ @@ -344,15 +343,10 @@ public class Reflection { private static void printStackTraceIfNeeded(Throwable e) { if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) { - // can't use method reference here, might be too early in startup - PrivilegedAction pa = new PrivilegedAction() { - public Boolean run() { - String s; - s = System.getProperty("sun.reflect.debugModuleAccessChecks"); - return (s != null && !s.equalsIgnoreCase("false")); - } - }; - printStackWhenAccessFails = AccessController.doPrivileged(pa); + String s = GetPropertyAction + .getProperty("sun.reflect.debugModuleAccessChecks"); + printStackWhenAccessFails = + (s != null && !s.equalsIgnoreCase("false")); printStackWhenAccessFailsSet = true; } if (printStackWhenAccessFails) { diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java index 898f56c214f..b40c584efcd 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java @@ -30,10 +30,11 @@ import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; -import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +import java.util.Properties; import sun.reflect.misc.ReflectUtil; +import sun.security.action.GetPropertyAction; /**

The master factory for all reflective objects, both those in java.lang.reflect (Fields, Methods, Constructors) as well as their @@ -382,41 +383,37 @@ public class ReflectionFactory { run, before the system properties are set up. */ private static void checkInitted() { if (initted) return; - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - // Tests to ensure the system properties table is fully - // initialized. This is needed because reflection code is - // called very early in the initialization process (before - // command-line arguments have been parsed and therefore - // these user-settable properties installed.) We assume that - // if System.out is non-null then the System class has been - // fully initialized and that the bulk of the startup code - // has been run. - if (System.out == null) { - // java.lang.System not yet fully initialized - return null; - } + // Tests to ensure the system properties table is fully + // initialized. This is needed because reflection code is + // called very early in the initialization process (before + // command-line arguments have been parsed and therefore + // these user-settable properties installed.) We assume that + // if System.out is non-null then the System class has been + // fully initialized and that the bulk of the startup code + // has been run. - String val = System.getProperty("sun.reflect.noInflation"); - if (val != null && val.equals("true")) { - noInflation = true; - } + if (System.out == null) { + // java.lang.System not yet fully initialized + return; + } - val = System.getProperty("sun.reflect.inflationThreshold"); - if (val != null) { - try { - inflationThreshold = Integer.parseInt(val); - } catch (NumberFormatException e) { - throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e); - } - } + Properties props = GetPropertyAction.getProperties(); + String val = props.getProperty("sun.reflect.noInflation"); + if (val != null && val.equals("true")) { + noInflation = true; + } - initted = true; - return null; - } - }); + val = props.getProperty("sun.reflect.inflationThreshold"); + if (val != null) { + try { + inflationThreshold = Integer.parseInt(val); + } catch (NumberFormatException e) { + throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e); + } + } + + initted = true; } private static LangReflectAccess langReflectAccess() { diff --git a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java index 068b8484728..9c68d7c6bed 100644 --- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java +++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java @@ -53,9 +53,8 @@ public class ResourceManager { private static final AtomicInteger numSockets; static { - String prop = java.security.AccessController.doPrivileged( - new GetPropertyAction("sun.net.maxDatagramSockets") - ); + String prop = + GetPropertyAction.getProperty("sun.net.maxDatagramSockets"); int defmax = DEFAULT_MAX_SOCKETS; try { if (prop != null) { diff --git a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java index d24a7fed491..797bc7fed50 100644 --- a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java +++ b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java @@ -31,6 +31,7 @@ import java.security.AccessController; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaIOFileDescriptorAccess; +import sun.security.action.GetPropertyAction; /** @@ -39,8 +40,7 @@ import jdk.internal.misc.JavaIOFileDescriptorAccess; */ public final class SdpSupport { - private static final String os = AccessController - .doPrivileged(new sun.security.action.GetPropertyAction("os.name")); + private static final String os = GetPropertyAction.getProperty("os.name"); private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux"))); private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); diff --git a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java index fda15ea9234..ac3f7b8a43f 100644 --- a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java @@ -25,10 +25,10 @@ package sun.net.smtp; -import java.util.StringTokenizer; import java.io.*; import java.net.*; import sun.net.TransferProtocolClient; +import sun.security.action.GetPropertyAction; /** * This class implements the SMTP client. @@ -157,8 +157,7 @@ public class SmtpClient extends TransferProtocolClient { } try { String s; - mailhost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("mail.host")); + mailhost = GetPropertyAction.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; @@ -184,8 +183,7 @@ public class SmtpClient extends TransferProtocolClient { setConnectTimeout(to); try { String s; - mailhost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("mail.host")); + mailhost = GetPropertyAction.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; diff --git a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java index d95ca3774ba..ba26f96e52e 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java +++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java @@ -27,6 +27,7 @@ package sun.net.www; import java.net.URL; import java.io.*; import java.util.StringTokenizer; +import sun.security.action.GetPropertyAction; class MimeLauncher extends Thread { java.net.URLConnection uc; @@ -182,8 +183,7 @@ class MimeLauncher extends Thread { } String execPathList; - execPathList = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("exec.path")); + execPathList = GetPropertyAction.getProperty("exec.path"); if (execPathList == null) { // exec.path property not set return false; diff --git a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 02c9f98b7a6..392d9ea52dc 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -28,6 +28,7 @@ package sun.net.www.http; import java.io.*; import java.net.*; import java.util.Locale; +import java.util.Properties; import sun.net.NetworkClient; import sun.net.ProgressSource; import sun.net.www.MessageHeader; @@ -37,6 +38,7 @@ import sun.net.www.ParseUtil; import sun.net.www.protocol.http.HttpURLConnection; import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*; +import sun.security.action.GetPropertyAction; /** * @author Herb Jellinek @@ -143,20 +145,18 @@ public class HttpClient extends NetworkClient { } static { - String keepAlive = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.keepAlive")); - - String retryPost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.net.http.retryPost")); + Properties props = GetPropertyAction.getProperties(); + String keepAlive = props.getProperty("http.keepAlive"); + String retryPost = props.getProperty("sun.net.http.retryPost"); if (keepAlive != null) { - keepAliveProp = Boolean.valueOf(keepAlive).booleanValue(); + keepAliveProp = Boolean.parseBoolean(keepAlive); } else { keepAliveProp = true; } if (retryPost != null) { - retryPostProp = Boolean.valueOf(retryPost).booleanValue(); + retryPostProp = Boolean.parseBoolean(retryPost); } else retryPostProp = true; diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index 38d64d23009..b397ba1243f 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -46,6 +46,7 @@ import java.net.ProxySelector; import java.util.StringTokenizer; import java.util.Iterator; import java.security.Permission; +import java.util.Properties; import sun.net.NetworkClient; import sun.net.www.MessageHeader; import sun.net.www.MeteredStream; @@ -277,11 +278,10 @@ public class FtpURLConnection extends URLConnection { if (user == null) { user = "anonymous"; - String vers = java.security.AccessController.doPrivileged( - new GetPropertyAction("java.version")); - password = java.security.AccessController.doPrivileged( - new GetPropertyAction("ftp.protocol.user", - "Java" + vers + "@")); + Properties props = GetPropertyAction.getProperties(); + String vers = props.getProperty("java.version"); + password = props.getProperty("ftp.protocol.user", + "Java" + vers + "@"); } try { ftp = FtpClient.create(); diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 42f692c3738..b6168d0c2c5 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -25,9 +25,10 @@ package sun.net.www.protocol.http; -import sun.net.www.*; import java.util.Iterator; import java.util.HashMap; +import sun.net.www.*; +import sun.security.action.GetPropertyAction; /** * This class is used to parse the information in WWW-Authenticate: and Proxy-Authenticate: @@ -93,8 +94,7 @@ public class AuthenticationHeader { } static { - authPref = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.preference")); + authPref = GetPropertyAction.getProperty("http.auth.preference"); // http.auth.preference can be set to SPNEGO or Kerberos. // In fact they means "Negotiate with SPNEGO" and "Negotiate with diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 5754c047219..ebabc26182e 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -52,7 +52,6 @@ import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import java.io.*; -import java.net.*; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -78,12 +77,15 @@ import java.text.SimpleDateFormat; import java.util.TimeZone; import java.net.MalformedURLException; import java.nio.ByteBuffer; +import java.util.Properties; import static sun.net.www.protocol.http.AuthScheme.BASIC; import static sun.net.www.protocol.http.AuthScheme.DIGEST; import static sun.net.www.protocol.http.AuthScheme.NTLM; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; +import sun.security.action.GetIntegerAction; +import sun.security.action.GetPropertyAction; /** * A class to represent an HTTP connection to a remote object. @@ -205,46 +207,38 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }; static { - maxRedirects = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "http.maxRedirects", defaultmaxRedirects)).intValue(); - version = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.version")); - String agent = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.agent")); + Properties props = GetPropertyAction.getProperties(); + maxRedirects = GetIntegerAction.getProperty("http.maxRedirects", + defaultmaxRedirects); + version = props.getProperty("java.version"); + String agent = props.getProperty("http.agent"); if (agent == null) { agent = "Java/"+version; } else { agent = agent + " Java/"+version; } userAgent = agent; - validateProxy = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "http.auth.digest.validateProxy")).booleanValue(); - validateServer = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "http.auth.digest.validateServer")).booleanValue(); + validateProxy = Boolean.parseBoolean( + props.getProperty("http.auth.digest.validateProxy")); + validateServer = Boolean.parseBoolean( + props.getProperty("http.auth.digest.validateServer")); - enableESBuffer = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "sun.net.http.errorstream.enableBuffering")).booleanValue(); - timeout4ESBuffer = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "sun.net.http.errorstream.timeout", 300)).intValue(); + enableESBuffer = Boolean.parseBoolean( + props.getProperty("sun.net.http.errorstream.enableBuffering")); + timeout4ESBuffer = GetIntegerAction + .getProperty("sun.net.http.errorstream.timeout", 300); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } - bufSize4ES = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "sun.net.http.errorstream.bufferSize", 4096)).intValue(); + bufSize4ES = GetIntegerAction + .getProperty("sun.net.http.errorstream.bufferSize", 4096); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default } - allowRestrictedHeaders = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "sun.net.http.allowRestrictedHeaders")).booleanValue(); + allowRestrictedHeaders = Boolean.parseBoolean( + props.getProperty("sun.net.http.allowRestrictedHeaders")); if (!allowRestrictedHeaders) { restrictedHeaderSet = new HashSet<>(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 3aecc419cb2..437c3969148 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -41,7 +41,6 @@ import java.security.Principal; import java.security.cert.*; import java.util.StringTokenizer; import java.util.Vector; -import java.security.AccessController; import javax.security.auth.x500.X500Principal; @@ -139,8 +138,8 @@ final class HttpsClient extends HttpClient // If ciphers are assigned, sort them into an array. // String ciphers []; - String cipherString = AccessController.doPrivileged( - new GetPropertyAction("https.cipherSuites")); + String cipherString = + GetPropertyAction.getProperty("https.cipherSuites"); if (cipherString == null || "".equals(cipherString)) { ciphers = null; @@ -163,8 +162,8 @@ final class HttpsClient extends HttpClient // If protocols are assigned, sort them into an array. // String protocols []; - String protocolString = AccessController.doPrivileged( - new GetPropertyAction("https.protocols")); + String protocolString = + GetPropertyAction.getProperty("https.protocols"); if (protocolString == null || "".equals(protocolString)) { protocols = null; @@ -184,8 +183,7 @@ final class HttpsClient extends HttpClient } private String getUserAgent() { - String userAgent = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("https.agent")); + String userAgent = GetPropertyAction.getProperty("https.agent"); if (userAgent == null || userAgent.length() == 0) { userAgent = "JSSE"; } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java index cde9d438714..f58ce457f7a 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java @@ -32,10 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; import java.security.Permission; -import java.security.PrivilegedAction; -import java.util.List; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; @@ -45,6 +42,7 @@ import jdk.internal.loader.URLClassPath; import jdk.internal.loader.Resource; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; +import sun.security.action.GetPropertyAction; /** * URLConnection implementation that can be used to connect to resources @@ -163,11 +161,7 @@ public class JavaRuntimeURLConnection extends URLConnection { public Permission getPermission() throws IOException { Permission p = permission; if (p == null) { - // using lambda expression here leads to recursive initialization - PrivilegedAction pa = new PrivilegedAction() { - public String run() { return System.getProperty("java.home"); } - }; - String home = AccessController.doPrivileged(pa); + String home = GetPropertyAction.getProperty("java.home"); p = new FilePermission(home + File.separator + "-", "read"); permission = p; } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java index fbcddcb826b..81139707655 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java @@ -40,6 +40,7 @@ import java.net.MalformedURLException; import java.net.URLStreamHandler; import java.io.InputStream; import java.io.IOException; +import sun.security.action.GetPropertyAction; public class Handler extends URLStreamHandler { static URL base; @@ -54,12 +55,10 @@ public class Handler extends URLStreamHandler { URLConnection uc = null; URL ru; - Boolean tmp = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction("newdoc.localonly")); - boolean localonly = tmp.booleanValue(); + boolean localonly = Boolean.parseBoolean( + GetPropertyAction.getProperty("newdoc.localonly")); - String docurl = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("doc.url")); + String docurl = GetPropertyAction.getProperty("doc.url"); String file = u.getFile(); if (!localonly) { diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 671fe79efcc..8a287bc2839 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1019,9 +1019,8 @@ public class FileChannelImpl if (!propertyChecked) { synchronized (FileChannelImpl.class) { if (!propertyChecked) { - String value = AccessController.doPrivileged( - new GetPropertyAction( - "sun.nio.ch.disableSystemWideOverlappingFileLockCheck")); + String value = GetPropertyAction.getProperty( + "sun.nio.ch.disableSystemWideOverlappingFileLockCheck"); isSharedFileLockTable = ((value == null) || value.equals("false")); propertyChecked = true; } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 062ce35468e..9a5c4dcb6f8 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -33,6 +33,7 @@ import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; import sun.net.ExtendedOptionsImpl; +import sun.security.action.GetPropertyAction; public class Net { @@ -382,13 +383,8 @@ public class Net { } public static boolean isFastTcpLoopbackRequested() { - String loopbackProp = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.net.useFastTcpLoopback"); - } - }); + String loopbackProp = + GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback"); boolean enable; if ("".equals(loopbackProp)) { enable = true; @@ -647,16 +643,9 @@ public class Net { int availLevel = isExclusiveBindAvailable(); if (availLevel >= 0) { String exclBindProp = - java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty( - "sun.net.useExclusiveBind"); - } - }); + GetPropertyAction.getProperty("sun.net.useExclusiveBind"); if (exclBindProp != null) { - exclusiveBind = exclBindProp.length() == 0 ? + exclusiveBind = exclBindProp.isEmpty() ? true : Boolean.parseBoolean(exclBindProp); } else if (availLevel == 1) { exclusiveBind = true; diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index af89eca4544..e71e628ede1 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -64,13 +64,7 @@ public class Util { * for potential future-proofing. */ private static long getMaxCachedBufferSize() { - String s = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.nio.maxCachedBufferSize"); - } - }); + String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize"); if (s != null) { try { long m = Long.parseLong(s); @@ -471,8 +465,7 @@ public class Util { if (bugLevel == null) { if (!jdk.internal.misc.VM.isBooted()) return false; - String value = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.ch.bugLevel")); + String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel"); bugLevel = (value != null) ? value : ""; } return bugLevel.equals(bl); diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template index dd4d3994240..2ad055e50ec 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template +++ b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template @@ -34,8 +34,7 @@ import java.nio.charset.spi.CharsetProvider; import java.util.Iterator; import java.util.Locale; import java.util.Map; -import java.security.AccessController; -import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; public class StandardCharsets extends CharsetProvider { @@ -201,15 +200,7 @@ public class StandardCharsets extends CharsetProvider { } private static String getProperty(String key) { - // this method may be called during initialization of - // system class loader and thus not using lambda - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty(key); - } - }); + return GetPropertyAction.getProperty(key); } diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java index 2d5c8cb6443..45d90b99222 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java @@ -28,8 +28,7 @@ package sun.nio.fs; import java.util.*; import java.nio.file.*; import java.nio.charset.Charset; -import java.security.*; -import sun.security.action.*; +import sun.security.action.GetPropertyAction; /** * Utility methods @@ -39,7 +38,7 @@ class Util { private Util() { } private static final Charset jnuEncoding = Charset.forName( - AccessController.doPrivileged(new GetPropertyAction("sun.jnu.encoding"))); + GetPropertyAction.getProperty("sun.jnu.encoding")); /** * Returns {@code Charset} corresponding to the sun.jnu.encoding property diff --git a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java index ff2b2019b48..c454b431861 100644 --- a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java +++ b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java @@ -25,6 +25,8 @@ package sun.security.action; +import java.security.AccessController; + /** * A convenience class for retrieving the integer value of a system property * as a privileged action. @@ -67,7 +69,7 @@ public class GetIntegerAction implements java.security.PrivilegedAction { private String theProp; private int defaultVal; - private boolean defaultSet = false; + private boolean defaultSet; /** * Constructor that takes the name of the system property whose integer @@ -110,4 +112,39 @@ public class GetIntegerAction return defaultVal; return value; } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + */ + public static Integer getProperty(String theProp) { + if (System.getSecurityManager() == null) { + return Integer.getInteger(theProp); + } else { + return AccessController.doPrivileged( + new GetIntegerAction(theProp)); + } + } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + * @param defaultVal the default value. + */ + public static Integer getProperty(String theProp, int defaultVal) { + Integer value; + if (System.getSecurityManager() == null) { + value = Integer.getInteger(theProp); + } else { + value = AccessController.doPrivileged( + new GetIntegerAction(theProp)); + } + return (value != null) ? value : defaultVal; + } } diff --git a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java index 95a113c3bef..bba172b06bc 100644 --- a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java +++ b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java @@ -25,6 +25,10 @@ package sun.security.action; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Properties; + /** * A convenience class for retrieving the string value of a system * property as a privileged action. @@ -46,8 +50,7 @@ package sun.security.action; * @since 1.2 */ -public class GetPropertyAction - implements java.security.PrivilegedAction { +public class GetPropertyAction implements PrivilegedAction { private String theProp; private String defaultVal; @@ -84,4 +87,57 @@ public class GetPropertyAction String value = System.getProperty(theProp); return (value == null) ? defaultVal : value; } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + */ + public static String getProperty(String theProp) { + if (System.getSecurityManager() == null) { + return System.getProperty(theProp); + } else { + return AccessController.doPrivileged( + new GetPropertyAction(theProp)); + } + } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + * @param defaultVal the default value. + */ + public static String getProperty(String theProp, String defaultVal) { + if (System.getSecurityManager() == null) { + return System.getProperty(theProp, defaultVal); + } else { + return AccessController.doPrivileged( + new GetPropertyAction(theProp, defaultVal)); + } + } + + /** + * Convenience method to call System.getProperties without + * having to go through doPrivileged if no security manager is present. + * This is unsafe for inclusion in a public API but allowable here since + * this class is now encapsulated. + */ + public static Properties getProperties() { + if (System.getSecurityManager() == null) { + return System.getProperties(); + } else { + return AccessController.doPrivileged( + new PrivilegedAction() { + public Properties run() { + return System.getProperties(); + } + } + ); + } + } } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java index 72797aea18b..731f6b13e45 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java @@ -70,8 +70,7 @@ public class DSAKeyFactory extends KeyFactorySpi { * By default this is false. * This incompatibility was introduced by 4532506. */ - String prop = AccessController.doPrivileged - (new GetPropertyAction(SERIAL_PROP, null)); + String prop = GetPropertyAction.getProperty(SERIAL_PROP); SERIAL_INTEROP = "true".equalsIgnoreCase(prop); } diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java index d869a8aaca4..d3497aea557 100644 --- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java +++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java @@ -84,9 +84,8 @@ public final class RSAKeyFactory extends KeyFactorySpi { public static final int MAX_RESTRICTED_EXPLEN = 64; private static final boolean restrictExpLen = - "true".equalsIgnoreCase(AccessController.doPrivileged( - new GetPropertyAction( - "sun.security.rsa.restrictRSAExponent", "true"))); + "true".equalsIgnoreCase(GetPropertyAction.getProperty( + "sun.security.rsa.restrictRSAExponent", "true")); // instance used for static translateKey(); private static final RSAKeyFactory INSTANCE = new RSAKeyFactory(); diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java index 8da221961a0..8f849f8d54f 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java @@ -50,10 +50,7 @@ public interface ClientKeyExchangeService { providers = new HashMap<>(); static { - final String key = "java.home"; - String path = AccessController.doPrivileged( - new GetPropertyAction(key), null, - new PropertyPermission(key, "read")); + String path = GetPropertyAction.getProperty("java.home"); ServiceLoader sc = AccessController.doPrivileged( (PrivilegedAction>) diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java index 494dd3257ba..c05505edf4a 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java @@ -26,7 +26,6 @@ package sun.security.ssl; import java.io.PrintStream; -import java.security.AccessController; import java.util.Locale; import sun.security.util.HexDumpEncoder; @@ -46,8 +45,7 @@ public class Debug { private static String args; static { - args = java.security.AccessController.doPrivileged( - new GetPropertyAction("javax.net.debug", "")); + args = GetPropertyAction.getProperty("javax.net.debug", ""); args = args.toLowerCase(Locale.ENGLISH); if (args.equals("help")) { Help(); @@ -184,8 +182,7 @@ public class Debug { */ static boolean getBooleanProperty(String propName, boolean defaultValue) { // if set, require value of either true or false - String b = AccessController.doPrivileged( - new GetPropertyAction(propName)); + String b = GetPropertyAction.getProperty(propName); if (b == null) { return defaultValue; } else if (b.equalsIgnoreCase("false")) { diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 903f6fb376a..f3384c5b746 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -656,8 +656,7 @@ public abstract class SSLContextImpl extends SSLContextSpi { // the provider service. Instead, please handle the initialization // exception in the caller's constructor. static { - String property = AccessController.doPrivileged( - new GetPropertyAction(PROPERTY_NAME)); + String property = GetPropertyAction.getProperty(PROPERTY_NAME); if (property != null && property.length() != 0) { // remove double quote marks from beginning/end of the property if (property.length() > 1 && property.charAt(0) == '"' && diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index 32e434aa6b4..5ce147a3af3 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -119,8 +119,8 @@ final class ServerHandshaker extends Handshaker { private long statusRespTimeout; static { - String property = AccessController.doPrivileged( - new GetPropertyAction("jdk.tls.ephemeralDHKeySize")); + String property = + GetPropertyAction.getProperty("jdk.tls.ephemeralDHKeySize"); if (property == null || property.length() == 0) { useLegacyEphemeralDHKeys = false; useSmartEphemeralDHKeys = false; diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java index b618ab31a13..3e21616e48e 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java @@ -73,8 +73,8 @@ final class StatusResponseManager { DEFAULT_CACHE_LIFETIME)); cacheLifetime = life > 0 ? life : 0; - String uriStr = AccessController.doPrivileged( - new GetPropertyAction("jdk.tls.stapling.responderURI")); + String uriStr = + GetPropertyAction.getProperty("jdk.tls.stapling.responderURI"); URI tmpURI; try { tmpURI = ((uriStr != null && !uriStr.isEmpty()) ? diff --git a/jdk/src/java.base/share/classes/sun/security/util/Debug.java b/jdk/src/java.base/share/classes/sun/security/util/Debug.java index 35ce8d66348..514608dc73c 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/Debug.java +++ b/jdk/src/java.base/share/classes/sun/security/util/Debug.java @@ -29,6 +29,7 @@ import java.math.BigInteger; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.Locale; +import sun.security.action.GetPropertyAction; /** * A utility class for debuging. @@ -42,13 +43,10 @@ public class Debug { private static String args; static { - args = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction - ("java.security.debug")); + args = GetPropertyAction.getProperty("java.security.debug"); - String args2 = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction - ("java.security.auth.debug")); + String args2 = + GetPropertyAction.getProperty("java.security.auth.debug"); if (args == null) { args = args2; diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java index 10cbbdceee1..90389c73252 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java @@ -27,6 +27,7 @@ package sun.util.calendar; import java.security.AccessController; import java.util.TimeZone; +import sun.security.action.GetPropertyAction; /** * @@ -142,8 +143,8 @@ public class LocalGregorianCalendar extends BaseCalendar { } // Append an era to the predefined eras if it's given by the property. - String prop = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("jdk.calendar.japanese.supplemental.era")); + String prop = GetPropertyAction + .getProperty("jdk.calendar.japanese.supplemental.era"); if (prop != null) { Era era = parseEraEntry(prop); if (era != null) { diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java index 365e0e7967c..26fbb59a9f4 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -245,11 +245,8 @@ public final class ZoneInfoFile { }; static { - String oldmapping = AccessController.doPrivileged( - new GetPropertyAction("sun.timezone.ids.oldmapping", "false")).toLowerCase(Locale.ROOT); - USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true")); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + USE_OLDMAPPING = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { try { String libDir = System.getProperty("java.home") + File.separator + "lib"; try (DataInputStream dis = new DataInputStream( @@ -260,7 +257,9 @@ public final class ZoneInfoFile { } catch (Exception x) { throw new Error(x); } - return null; + String oldmapping = System.getProperty("sun.timezone.ids.oldmapping", "false") + .toLowerCase(Locale.ROOT); + return (oldmapping.equals("yes") || oldmapping.equals("true")); } }); } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index e19a6c8c531..75f235c73e7 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -25,7 +25,6 @@ package sun.util.locale.provider; -import java.security.AccessController; import java.text.spi.BreakIteratorProvider; import java.text.spi.CollatorProvider; import java.text.spi.DateFormatProvider; @@ -47,6 +46,7 @@ import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; import java.util.spi.TimeZoneNameProvider; +import sun.security.action.GetPropertyAction; import sun.util.spi.CalendarProvider; /** @@ -116,8 +116,7 @@ public abstract class LocaleProviderAdapter { adapterCache = new ConcurrentHashMap<>(); static { - String order = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.locale.providers")); + String order = GetPropertyAction.getProperty("java.locale.providers"); List typeList = new ArrayList<>(); // Check user specified adapter preference diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java index 8b4177e3fde..140473283c8 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.file.*; import java.io.IOException; import java.util.*; -import java.security.AccessController; import sun.security.action.GetPropertyAction; import static sun.nio.fs.SolarisNativeDispatcher.*; @@ -43,8 +42,7 @@ class SolarisFileSystem extends UnixFileSystem { super(provider, dir); // check os.version - String osversion = AccessController - .doPrivileged(new GetPropertyAction("os.version")); + String osversion = GetPropertyAction.getProperty("os.version"); String[] vers = Util.split(osversion, '.'); assert vers.length >= 2; int majorVersion = Integer.parseInt(vers[0]); diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java index 4fcb617a200..affdfb96c7f 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java @@ -29,7 +29,6 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.nio.file.spi.FileTypeDetector; import java.io.IOException; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -85,8 +84,8 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + Path userMimeTypes = Paths.get( + GetPropertyAction.getProperty("user.home"), ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); return chain(new GioFileTypeDetector(), diff --git a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java index c0ca02dd4ad..c829994cc85 100644 --- a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java +++ b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java @@ -25,7 +25,7 @@ package java.io; -import java.security.AccessController; +import java.util.Properties; import sun.security.action.GetPropertyAction; @@ -36,12 +36,10 @@ class UnixFileSystem extends FileSystem { private final String javaHome; public UnixFileSystem() { - slash = AccessController.doPrivileged( - new GetPropertyAction("file.separator")).charAt(0); - colon = AccessController.doPrivileged( - new GetPropertyAction("path.separator")).charAt(0); - javaHome = AccessController.doPrivileged( - new GetPropertyAction("java.home")); + Properties props = GetPropertyAction.getProperties(); + slash = props.getProperty("file.separator").charAt(0); + colon = props.getProperty("path.separator").charAt(0); + javaHome = props.getProperty("java.home"); } diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java index 5f9a546f4bd..8a1b8ca085e 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -46,8 +46,10 @@ import static java.security.AccessController.doPrivileged; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Properties; import jdk.internal.misc.JavaIOFileDescriptorAccess; import jdk.internal.misc.SharedSecrets; +import sun.security.action.GetPropertyAction; /** * java.lang.Process subclass in the UNIX environment. @@ -123,11 +125,9 @@ final class ProcessImpl extends Process { } String helperPath() { - return AccessController.doPrivileged( - (PrivilegedAction) () -> - helperPath(System.getProperty("java.home"), - System.getProperty("os.arch")) - ); + Properties props = GetPropertyAction.getProperties(); + return helperPath(props.getProperty("java.home"), + props.getProperty("os.arch")); } LaunchMechanism launchMechanism() { @@ -159,9 +159,7 @@ final class ProcessImpl extends Process { } static Platform get() { - String osName = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("os.name") - ); + String osName = GetPropertyAction.getProperty("os.name"); if (osName.equals("Linux")) { return LINUX; } if (osName.contains("OS X")) { return BSD; } diff --git a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java index ad62c582691..dd1a6548d6a 100644 --- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -24,7 +24,7 @@ */ package java.net; -import java.security.AccessController; +import sun.security.action.GetPropertyAction; /** * This class defines a factory for creating DatagramSocketImpls. It defaults @@ -40,8 +40,7 @@ class DefaultDatagramSocketImplFactory { static { String prefix = null; try { - prefix = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("impl.prefix", null)); + prefix = GetPropertyAction.getProperty("impl.prefix", null); if (prefix != null) prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); } catch (Exception e) { diff --git a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java index 2b1c3fd841e..a9f15a617f0 100644 --- a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java +++ b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java @@ -34,7 +34,6 @@ import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintStream; -import java.security.AccessController; import sun.net.sdp.SdpSupport; import sun.security.action.GetPropertyAction; @@ -57,8 +56,7 @@ public class SdpProvider extends NetHooks.Provider { public SdpProvider() { // if this property is not defined then there is nothing to do. - String file = AccessController.doPrivileged( - new GetPropertyAction("com.sun.sdp.conf")); + String file = GetPropertyAction.getProperty("com.sun.sdp.conf"); if (file == null) { this.enabled = false; this.rules = null; @@ -77,8 +75,7 @@ public class SdpProvider extends NetHooks.Provider { // check if debugging is enabled PrintStream out = null; - String logfile = AccessController.doPrivileged( - new GetPropertyAction("com.sun.sdp.debug")); + String logfile = GetPropertyAction.getProperty("com.sun.sdp.debug"); if (logfile != null) { out = System.out; if (logfile.length() > 0) { diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 0e067d0681f..f205eaf7545 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -39,6 +39,7 @@ import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; import sun.net.www.protocol.http.AuthScheme; import sun.net.www.protocol.http.HttpURLConnection; +import sun.security.action.GetPropertyAction; /** * NTLMAuthentication: @@ -73,12 +74,9 @@ public class NTLMAuthentication extends AuthenticationInfo { NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); private String hostname; - private static String defaultDomain; /* Domain to use if not specified by user */ - - static { - defaultDomain = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", "")); - }; + /* Domain to use if not specified by user */ + private static String defaultDomain = + GetPropertyAction.getProperty("http.auth.ntlm.domain", ""); public static boolean supportsTransparentAuth () { return false; @@ -143,8 +141,7 @@ public class NTLMAuthentication extends AuthenticationInfo { password = pw.getPassword(); init0(); try { - String version = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("ntlm.version")); + String version = GetPropertyAction.getProperty("ntlm.version"); client = new Client(version, hostname, username, ntdomain, password); } catch (NTLMException ne) { try { diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java index 7a0ce392299..9018f0fe6a0 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java @@ -26,7 +26,6 @@ package sun.nio.ch; import java.nio.channels.spi.AsynchronousChannelProvider; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -60,8 +59,7 @@ public class DefaultAsynchronousChannelProvider { * Returns the default AsynchronousChannelProvider. */ public static AsynchronousChannelProvider create() { - String osname = AccessController - .doPrivileged(new GetPropertyAction("os.name")); + String osname = GetPropertyAction.getProperty("os.name"); if (osname.equals("SunOS")) return createProvider("sun.nio.ch.SolarisAsynchronousChannelProvider"); if (osname.equals("Linux")) diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 3307c40d8c5..f8c31b5ac94 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -31,7 +31,6 @@ import java.net.*; import java.util.concurrent.*; import java.io.IOException; import java.io.FileDescriptor; -import java.security.AccessController; import sun.net.NetHooks; import sun.security.action.GetPropertyAction; @@ -47,8 +46,8 @@ class UnixAsynchronousSocketChannelImpl private static final boolean disableSynchronousRead; static { - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.ch.disableSynchronousRead", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.ch.disableSynchronousRead", "false"); disableSynchronousRead = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); } diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java index 595f3c6d187..62f6d5ce145 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java @@ -26,7 +26,6 @@ package sun.nio.fs; import java.nio.file.spi.FileSystemProvider; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -55,8 +54,7 @@ public class DefaultFileSystemProvider { * Returns the default FileSystemProvider. */ public static FileSystemProvider create() { - String osname = AccessController - .doPrivileged(new GetPropertyAction("os.name")); + String osname = GetPropertyAction.getProperty("os.name"); if (osname.equals("SunOS")) return createProvider("sun.nio.fs.SolarisFileSystemProvider"); if (osname.equals("Linux")) diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index d394ac10173..7cf295b0d6d 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -31,7 +31,6 @@ import java.nio.file.spi.*; import java.io.IOException; import java.util.*; import java.util.regex.Pattern; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -57,8 +56,8 @@ abstract class UnixFileSystem // if process-wide chdir is allowed or default directory is not the // process working directory then paths must be resolved against the // default directory. - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.fs.chdirAllowed", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.fs.chdirAllowed", "false"); boolean chdirAllowed = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); if (chdirAllowed) { diff --git a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java index 9ee66bf4169..50ccacc3d1e 100644 --- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java +++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java @@ -25,8 +25,8 @@ package java.io; -import java.security.AccessController; import java.util.Locale; +import java.util.Properties; import sun.security.action.GetPropertyAction; /** @@ -42,10 +42,9 @@ class WinNTFileSystem extends FileSystem { private final char semicolon; public WinNTFileSystem() { - slash = AccessController.doPrivileged( - new GetPropertyAction("file.separator")).charAt(0); - semicolon = AccessController.doPrivileged( - new GetPropertyAction("path.separator")).charAt(0); + Properties props = GetPropertyAction.getProperties(); + slash = props.getProperty("file.separator").charAt(0); + semicolon = props.getProperty("path.separator").charAt(0); altSlash = (this.slash == '\\') ? '/' : '\\'; } diff --git a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java index fb632a4a816..c12378da67d 100644 --- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -24,8 +24,7 @@ */ package java.net; -import java.security.AccessController; -import java.security.PrivilegedAction; +import java.util.Properties; import sun.security.action.GetPropertyAction; /** @@ -57,12 +56,11 @@ class DefaultDatagramSocketImplFactory static { Class prefixImplClassLocal = null; + Properties props = GetPropertyAction.getProperties(); preferIPv4Stack = Boolean.parseBoolean( - AccessController.doPrivileged( - new GetPropertyAction("java.net.preferIPv4Stack"))); + props.getProperty("java.net.preferIPv4Stack")); - String exclBindProp = AccessController.doPrivileged( - new GetPropertyAction("sun.net.useExclusiveBind", "")); + String exclBindProp = props.getProperty("sun.net.useExclusiveBind", ""); exclusiveBind = (exclBindProp.isEmpty()) ? true : Boolean.parseBoolean(exclBindProp); @@ -70,8 +68,7 @@ class DefaultDatagramSocketImplFactory // impl.prefix String prefix = null; try { - prefix = AccessController.doPrivileged( - new GetPropertyAction("impl.prefix", null)); + prefix = props.getProperty("impl.prefix"); if (prefix != null) prefixImplClassLocal = Class.forName("java.net."+prefix+"DatagramSocketImpl"); } catch (Exception e) { diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 0e17de44b4c..5583842d0cb 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -34,6 +34,7 @@ import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; import sun.net.www.protocol.http.AuthScheme; import sun.net.www.protocol.http.HttpURLConnection; +import sun.security.action.GetPropertyAction; /** * NTLMAuthentication: @@ -52,9 +53,8 @@ public class NTLMAuthentication extends AuthenticationInfo { private static String defaultDomain; /* Domain to use if not specified by user */ static { - defaultDomain = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", - "domain")); + defaultDomain = GetPropertyAction.getProperty("http.auth.ntlm.domain", + "domain"); }; private void init0() { diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java index 4b812d35a4d..5390b55a3ab 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -27,9 +27,9 @@ package sun.nio.ch; import java.io.FileDescriptor; import java.io.IOException; -import java.security.PrivilegedAction; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaIOFileDescriptorAccess; +import sun.security.action.GetPropertyAction; class FileDispatcherImpl extends FileDispatcher { @@ -119,13 +119,8 @@ class FileDispatcherImpl extends FileDispatcher { } static boolean isFastFileTransferRequested() { - String fileTransferProp = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.nio.enableFastFileTransfer"); - } - }); + String fileTransferProp = GetPropertyAction + .getProperty("jdk.nio.enableFastFileTransfer"); boolean enable; if ("".equals(fileTransferProp)) { enable = true; diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java index 02226053f8d..4d2d3e97c4c 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -27,7 +27,6 @@ package sun.nio.fs; import java.nio.file.attribute.*; import java.util.concurrent.TimeUnit; -import java.security.AccessController; import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; @@ -115,8 +114,8 @@ class WindowsFileAttributes // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; static { - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.fs.ensureAccurateMetadata", "false"); ensureAccurateMetadata = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); } From 6e1f8aab874a9667e21b1c35352685e5a3d95de9 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Thu, 21 Apr 2016 17:21:31 +0200 Subject: [PATCH 074/167] 8154853: java/util/TimeZone/OldIDMappingTest.sh fails after JDK-8154231 Reviewed-by: chegar --- .../classes/sun/util/calendar/ZoneInfoFile.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java index 26fbb59a9f4..58c0c5bbe01 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -245,8 +245,12 @@ public final class ZoneInfoFile { }; static { - USE_OLDMAPPING = AccessController.doPrivileged(new PrivilegedAction() { - public Boolean run() { + String oldmapping = GetPropertyAction + .getProperty("sun.timezone.ids.oldmapping", "false") + .toLowerCase(Locale.ROOT); + USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true")); + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { try { String libDir = System.getProperty("java.home") + File.separator + "lib"; try (DataInputStream dis = new DataInputStream( @@ -257,9 +261,7 @@ public final class ZoneInfoFile { } catch (Exception x) { throw new Error(x); } - String oldmapping = System.getProperty("sun.timezone.ids.oldmapping", "false") - .toLowerCase(Locale.ROOT); - return (oldmapping.equals("yes") || oldmapping.equals("true")); + return null; } }); } From d8acc2fbcf4d2a4373c7ec11fd85e4886bc1137b Mon Sep 17 00:00:00 2001 From: Rajan Halade Date: Thu, 21 Apr 2016 09:55:04 -0700 Subject: [PATCH 075/167] 8129329: sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java failed intermittently Reviewed-by: xuelei --- .../ssl/SSLContextImpl/MD2InTrustAnchor.java | 358 +++++++----------- 1 file changed, 129 insertions(+), 229 deletions(-) diff --git a/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java index 9d8ee1d5287..f2e06337dd3 100644 --- a/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java +++ b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,106 +37,88 @@ * @run main/othervm MD2InTrustAnchor PKIX TLSv1.2 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2 */ - -import java.net.*; -import java.util.*; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; import javax.net.ssl.*; import java.security.Security; import java.security.KeyStore; import java.security.KeyFactory; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; -import java.security.spec.*; -import java.security.interfaces.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; +import java.util.concurrent.CountDownLatch; public class MD2InTrustAnchor { - /* - * ============================================================= - * Set the various variables needed for the tests, then - * specify what tests to run on each side. - */ - - /* - * Should we run the client or server in a separate thread? - * Both sides can throw exceptions, but do you have a preference - * as to which side should be the main thread. - */ - static boolean separateServerThread = false; - /* * Certificates and key used in the test. */ - // It's a trust anchor signed with MD2 hash function. - static String trustedCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + - "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + - "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + - "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + - "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + - "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + - "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + - "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + - "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + - "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + - "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + - "-----END CERTIFICATE-----"; + private static final String TRUSTED_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + + "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + + "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + + "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + + "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + + "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + + "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + + "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + + "-----END CERTIFICATE-----"; // The certificate issued by above trust anchor, signed with MD5 - static String targetCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + - "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + - "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + - "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + - "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + - "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + - "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + - "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + - "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + - "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + - "yvudOlX4BkVR0l1K\n" + - "-----END CERTIFICATE-----"; + private static final String TARGET_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + + "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + + "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + + "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + + "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + + "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + + "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + + "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + + "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + + "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + + "yvudOlX4BkVR0l1K\n" + + "-----END CERTIFICATE-----"; // Private key in the format of PKCS#8. - static String targetPrivateKey = - "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" + - "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" + - "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" + - "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" + - "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" + - "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" + - "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" + - "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" + - "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" + - "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" + - "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" + - "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" + - "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" + - "njWHoKY3axDQ8OU=\n"; + private static final String TARGET_PRIV_KEY_STR = "MIICdwIBADANBgkqhkiG9w0B\n" + + "AQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4F5NVEtFXCbEFcVLRjMp3AL3j\n" + + "LswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa9+uHt0Z9Wmh4wjHAZhX5Tm5x\n" + + "p4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPMKBpyzK6rusorkwpWywTyvH1s\n" + + "016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+KSH9tFt+WQbiojjz9ac49trkv\n" + + "Ufu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck5mOIYV4uZK8jfNMSQ8v0tFEe\n" + + "IPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+HaY3d76hR5qly+Ys+Ww0CQQDj\n" + + "eOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ6t0v/xryVIdvOYcRBvKnqEog\n" + + "OH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7ez3TDpU9w1B0JXklcV5HddYsR\n" + + "qp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3ML11xwwJBAKsZ+Hur3x0tUY29\n" + + "No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDElhIM6Rqv12kwCMuQE9i7vo1o3\n" + + "WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXsekdXAA4d2d5zGI7q/aGD9SYU6\n" + + "phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRTA5kokFb+E3Gplu29tJvCUpfw\n" + + "gBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiEnjWHoKY3axDQ8OU="; - - static char passphrase[] = "passphrase".toCharArray(); + private static final char PASSPHRASE[] = "passphrase".toCharArray(); /* * Is the server ready to serve? */ - volatile static boolean serverReady = false; + private static volatile CountDownLatch sync = new CountDownLatch(1); /* * Turn on SSL debugging? */ - static boolean debug = false; + private static final boolean DEBUG = false; /* * Define the server side of the test. @@ -144,29 +126,30 @@ public class MD2InTrustAnchor { * If the server prematurely exits, serverReady will be set to true * to avoid infinite hangs. */ - void doServerSide() throws Exception { - SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, - targetPrivateKey); + private void doServerSide() throws Exception { + SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, + TARGET_PRIV_KEY_STR); SSLServerSocketFactory sslssf = context.getServerSocketFactory(); - SSLServerSocket sslServerSocket = - (SSLServerSocket)sslssf.createServerSocket(serverPort); - sslServerSocket.setNeedClientAuth(true); - serverPort = sslServerSocket.getLocalPort(); + try (SSLServerSocket sslServerSocket + = (SSLServerSocket) sslssf.createServerSocket(serverPort)) { + sslServerSocket.setNeedClientAuth(true); + serverPort = sslServerSocket.getLocalPort(); + /* + * Signal Client, we're ready for his connect. + */ + System.out.println("Signal server ready"); + sync.countDown(); - /* - * Signal Client, we're ready for his connect. - */ - serverReady = true; + System.out.println("Waiting for client connection"); + try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); - SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslIS.read(); - sslOS.write('A'); - sslOS.flush(); - - sslSocket.close(); + sslIS.read(); + sslOS.write('A'); + sslOS.flush(); + } + } } /* @@ -175,33 +158,31 @@ public class MD2InTrustAnchor { * If the server prematurely exits, serverReady will be set to true * to avoid infinite hangs. */ - void doClientSide() throws Exception { + private void doClientSide() throws Exception { /* * Wait for server to get started. */ - while (!serverReady) { - Thread.sleep(50); - } + System.out.println("Waiting for server ready"); + sync.await(); - SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, - targetPrivateKey); + SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, + TARGET_PRIV_KEY_STR); SSLSocketFactory sslsf = context.getSocketFactory(); - SSLSocket sslSocket = - (SSLSocket)sslsf.createSocket("localhost", serverPort); + System.out.println("Connect to server on port: " + serverPort); + try (SSLSocket sslSocket + = (SSLSocket) sslsf.createSocket("localhost", serverPort)) { + // enable the specified TLS protocol + sslSocket.setEnabledProtocols(new String[]{tlsProtocol}); - // enable the specified TLS protocol - sslSocket.setEnabledProtocols(new String[] {tlsProtocol}); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslOS.write('B'); - sslOS.flush(); - sslIS.read(); - - sslSocket.close(); + sslOS.write('B'); + sslOS.flush(); + sslIS.read(); + } } /* @@ -240,10 +221,10 @@ public class MD2InTrustAnchor { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - Base64.getMimeDecoder().decode(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); - RSAPrivateKey priKey = - (RSAPrivateKey)kf.generatePrivate(priKeySpec); + RSAPrivateKey priKey + = (RSAPrivateKey) kf.generatePrivate(priKeySpec); // generate certificate chain is = new ByteArrayInputStream(keyCertStr.getBytes()); @@ -257,7 +238,7 @@ public class MD2InTrustAnchor { chain[0] = keyCert; // import the key entry. - ks.setKeyEntry("Whatever", priKey, passphrase, chain); + ks.setKeyEntry("Whatever", priKey, PASSPHRASE, chain); } // create SSL context @@ -267,7 +248,7 @@ public class MD2InTrustAnchor { SSLContext ctx = SSLContext.getInstance(tlsProtocol); if (keyCertStr != null && !keyCertStr.isEmpty()) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); - kmf.init(ks, passphrase); + kmf.init(ks, PASSPHRASE); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); ks = null; @@ -278,12 +259,10 @@ public class MD2InTrustAnchor { return ctx; } - // use any free port by default - volatile int serverPort = 0; + private volatile int serverPort = 0; - volatile Exception serverException = null; - volatile Exception clientException = null; + private volatile Exception serverException = null; public static void main(String[] args) throws Exception { // MD5 is used in this test case, don't disable MD5 algorithm. @@ -292,140 +271,61 @@ public class MD2InTrustAnchor { Security.setProperty("jdk.tls.disabledAlgorithms", "SSLv3, RC4, DH keySize < 768"); - if (debug) + if (DEBUG) { System.setProperty("javax.net.debug", "all"); + } /* * Get the customized arguments. */ parseArguments(args); - /* * Start the tests. */ - new MD2InTrustAnchor(); + new MD2InTrustAnchor().runTest(); } - Thread clientThread = null; - Thread serverThread = null; + private Thread serverThread = null; /* - * Primary constructor, used to drive remainder of the test. + * Used to drive remainder of the test. * * Fork off the other side, then do your work. */ - MD2InTrustAnchor() throws Exception { - try { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); - } - } catch (Exception e) { - // swallow for now. Show later - } + public void runTest() throws Exception { + startServerThread(); + doClientSide(); /* * Wait for other side to close down. */ - if (separateServerThread) { - serverThread.join(); - } else { - clientThread.join(); - } + serverThread.join(); - /* - * When we get here, the test is pretty much over. - * Which side threw the error? - */ - Exception local; - Exception remote; - String whichRemote; - - if (separateServerThread) { - remote = serverException; - local = clientException; - whichRemote = "server"; - } else { - remote = clientException; - local = serverException; - whichRemote = "client"; - } - - /* - * If both failed, return the curthread's exception, but also - * print the remote side Exception - */ - if ((local != null) && (remote != null)) { - System.out.println(whichRemote + " also threw:"); - remote.printStackTrace(); - System.out.println(); - throw local; - } - - if (remote != null) { - throw remote; - } - - if (local != null) { - throw local; + if (serverException != null) { + throw serverException; } } - void startServer(boolean newThread) throws Exception { - if (newThread) { - serverThread = new Thread() { - public void run() { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died..."); - serverReady = true; - serverException = e; - } + private void startServerThread() { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + e.printStackTrace(System.out); + serverException = e; + sync.countDown(); } - }; - serverThread.start(); - } else { - try { - doServerSide(); - } catch (Exception e) { - serverException = e; - } finally { - serverReady = true; } - } - } + }; - void startClient(boolean newThread) throws Exception { - if (newThread) { - clientThread = new Thread() { - public void run() { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died..."); - clientException = e; - } - } - }; - clientThread.start(); - } else { - try { - doClientSide(); - } catch (Exception e) { - clientException = e; - } - } + serverThread.start(); } } From 183d5aad2e36238fdc92148cbed0125b5ae7f63a Mon Sep 17 00:00:00 2001 From: Nadeesh TV Date: Thu, 21 Apr 2016 17:51:18 +0000 Subject: [PATCH 076/167] 8154050: java.time.format.DateTimeFormatter can't parse localized zone-offset Corrected the mistake in calculating parse end position Reviewed-by: rriggs, scolebourne --- .../time/format/DateTimeFormatterBuilder.java | 18 +++----- .../TCKLocalizedOffsetIdPrinterParser.java | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index d7baf69c5b5..c77a8c5f888 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1539,8 +1539,8 @@ public final class DateTimeFormatterBuilder { *
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffsetPrefixed(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffsetPrefixed(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT);
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL);
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -3519,9 +3519,7 @@ public final class DateTimeFormatterBuilder {
                 return false;
             }
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                buf.append(gmtText);
-            }
+            buf.append(gmtText);
             int totalSecs = Math.toIntExact(offsetSecs);
             if (totalSecs != 0) {
                 int absHours = Math.abs((totalSecs / 3600) % 100);  // anything larger than 99 silently dropped
@@ -3565,14 +3563,12 @@ public final class DateTimeFormatterBuilder {
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int pos = position;
-            int end = pos + text.length();
+            int end = text.length();
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
+            if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
                     return ~position;
                 }
-                pos += gmtText.length();
-            }
+            pos += gmtText.length();
             // parse normal plus/minus offset
             int negative = 0;
             if (pos == end) {
diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
new file mode 100644
index 00000000000..d0a1f189e92
--- /dev/null
+++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tck.java.time.format;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test localized behavior of formatter.
+ */
+@Test
+public class TCKLocalizedOffsetIdPrinterParser {
+    @Test
+    public void test_localized_offset_parse() {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O")
+                                                       .withLocale(Locale.ENGLISH);
+        String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC));
+        formatter.parse(date) ;
+     }
+}

From 40263e2a3452c165a67024165c98057a277e1ff8 Mon Sep 17 00:00:00 2001
From: Lana Steuck 
Date: Thu, 21 Apr 2016 12:57:11 -0700
Subject: [PATCH 077/167] Added tag jdk-9+115 for changeset 3414aeff4a80

---
 jdk/.hgtags | 1 +
 1 file changed, 1 insertion(+)

diff --git a/jdk/.hgtags b/jdk/.hgtags
index e9974a728e5..74ad9bf9055 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -357,3 +357,4 @@ b2a69d66dc65ad1d3aeb3bd362cf5bb0deba040e jdk-9+111
 1565a0efe6f0ca411a6df277df1e069431c60988 jdk-9+112
 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113
 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114
+35225b837d66582037eeadeb471c13235dfd793d jdk-9+115

From ac4936ef857e31fcdbff28798e42f33e8065df64 Mon Sep 17 00:00:00 2001
From: Amy Lu 
Date: Fri, 22 Apr 2016 13:01:41 +0800
Subject: [PATCH 078/167] 8153933: Remove intermittent key from
 TimeZone/Bug6772689.java and move back to tier1

Reviewed-by: darcy
---
 jdk/test/TEST.groups                        | 2 --
 jdk/test/java/util/TimeZone/Bug6772689.java | 1 -
 2 files changed, 3 deletions(-)

diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index cf3f0abfd9d..673b0862d5c 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -32,7 +32,6 @@ tier1 = \
     -java/util/WeakHashMap/GCDuringIteration.java \
     -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
-    -java/util/TimeZone/Bug6772689.java \
     sun/nio/cs/ISO8859x.java \
     java/nio/Buffer \
     com/sun/crypto/provider/Cipher \
@@ -43,7 +42,6 @@ tier2 = \
     java/util/WeakHashMap/GCDuringIteration.java \
     java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
     java/util/concurrent/forkjoin/FJExceptionTableLeak.java \
-    java/util/TimeZone/Bug6772689.java \
     :jdk_io \
     :jdk_nio \
     -sun/nio/cs/ISO8859x.java \
diff --git a/jdk/test/java/util/TimeZone/Bug6772689.java b/jdk/test/java/util/TimeZone/Bug6772689.java
index a1ce49682b4..f730567013d 100644
--- a/jdk/test/java/util/TimeZone/Bug6772689.java
+++ b/jdk/test/java/util/TimeZone/Bug6772689.java
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 6772689
- * @key intermittent
  * @summary Test for standard-to-daylight transitions at midnight:
  * date stays on the given day.
  */

From d9e44503b4843911e00cd3a79c3dd04f7b5c0405 Mon Sep 17 00:00:00 2001
From: Nadeesh TV 
Date: Fri, 22 Apr 2016 05:46:54 +0000
Subject: [PATCH 079/167] 8148947: DateTimeFormatter pattern letter 'g'

Handled 'g'  in the required places

Reviewed-by: rriggs, scolebourne
---
 .../java/time/format/DateTimeFormatter.java   | 11 ++--
 .../time/format/DateTimeFormatterBuilder.java | 58 ++++++++++---------
 .../java/time/temporal/JulianFields.java      | 10 +++-
 .../format/TCKDateTimeFormatterBuilder.java   | 35 ++++++++++-
 4 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
index 3478af25761..9810a088b48 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -284,6 +284,7 @@ import java.util.Set;
  *   D       day-of-year                 number            189
  *   M/L     month-of-year               number/text       7; 07; Jul; July; J
  *   d       day-of-month                number            10
+ *   g       modified-julian-day         number            2451334
  *
  *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
  *   Y       week-based-year             year              1996; 96
@@ -308,10 +309,10 @@ import java.util.Set;
  *
  *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
  *   z       time-zone name              zone-name         Pacific Standard Time; PST
- *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
- *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
- *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
- *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+ *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00
+ *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
+ *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15
+ *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00
  *
  *   p       pad next                    pad modifier      1
  *
diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index c77a8c5f888..e8ca3f1e99f 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -90,6 +90,7 @@ import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeTextProvider.LocaleStore;
 import java.time.temporal.ChronoField;
 import java.time.temporal.IsoFields;
+import java.time.temporal.JulianFields;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQueries;
@@ -1383,6 +1384,7 @@ public final class DateTimeFormatterBuilder {
      *   D       day-of-year                 number            189
      *   M/L     month-of-year               number/text       7; 07; Jul; July; J
      *   d       day-of-month                number            10
+     *   g       modified-julian-day         number            2451334
      *
      *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
      *   Y       week-based-year             year              1996; 96
@@ -1408,9 +1410,9 @@ public final class DateTimeFormatterBuilder {
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
-     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
-     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
-     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
+     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15
+     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00
      *
      *   p       pad next                    pad modifier      1
      *
@@ -1437,37 +1439,37 @@ public final class DateTimeFormatterBuilder {
      *    GGGG    4      appendText(ChronoField.ERA, TextStyle.FULL)
      *    GGGGG   5      appendText(ChronoField.ERA, TextStyle.NARROW)
      *
-     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL);
-     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000);
-     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL);
-     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD);
-     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL);
-     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000);
-     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL);
-     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD);
+     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL)
+     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000)
+     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL)
+     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD)
+     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL)
+     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000)
+     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL)
+     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD)
      *    Y       1      append special localized WeekFields element for numeric week-based-year
-     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits;
-     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL);
-     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD);
+     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits
+     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL)
+     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD)
      *
-     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    QQQ     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT)
      *    QQQQ    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL)
      *    QQQQQ   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW)
-     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    qqq     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    qqqq    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    qqqqq   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW_STANDALONE)
      *
-     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    MMM     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT)
      *    MMMM    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL)
      *    MMMMM   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW)
-     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    LLL     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    LLLL    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    LLLLL   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW_STANDALONE)
@@ -1481,6 +1483,7 @@ public final class DateTimeFormatterBuilder {
      *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2)
      *    DDD     3      appendValue(ChronoField.DAY_OF_YEAR, 3)
      *    F       1      appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)
+     *    g..g    1..n   appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL)
      *    E       1      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EE      2      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EEE     3      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
@@ -1539,8 +1542,8 @@ public final class DateTimeFormatterBuilder {
      * 
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffset(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT)
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL)
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -1554,7 +1557,7 @@ public final class DateTimeFormatterBuilder {
      *    Z       1      appendOffset("+HHMM","+0000")
      *    ZZ      2      appendOffset("+HHMM","+0000")
      *    ZZZ     3      appendOffset("+HHMM","+0000")
-     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL);
+     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL)
      *    ZZZZZ   5      appendOffset("+HH:MM:ss","Z")
      * 
*

@@ -1836,6 +1839,9 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Too many pattern letters: " + cur); } break; + case 'g': + appendValue(field, count, 19, SignStyle.NORMAL); + break; default: if (count == 1) { appendValue(field); @@ -1874,6 +1880,7 @@ public final class DateTimeFormatterBuilder { FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); // LDML FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); // 310 (proposed for LDML) FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); // 310 (proposed for LDML) + FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY); // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 // 310 - Z - matches SimpleDateFormat and LDML // 310 - V - time-zone id, matches LDML @@ -1884,7 +1891,6 @@ public final class DateTimeFormatterBuilder { // LDML - U - cycle year name, not supported by 310 yet // LDML - l - deprecated // LDML - j - not relevant - // LDML - g - modified-julian-day // LDML - v,V - extended time-zone names } diff --git a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java index 327037981eb..7fc501cb9dd 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,13 @@ public final class JulianFields { * *

Astronomical and Scientific Notes

* The standard astronomical definition uses a fraction to indicate the time-of-day, - * thus 3.25 would represent the time 18:00, since days start at midday. + * where each day is counted from midday to midday. For example, + * a fraction of 0 represents midday, a fraction of 0.25 + * represents 18:00, a fraction of 0.5 represents midnight and a fraction + * of 0.75 represents 06:00. + *

+ * By contrast, this implementation has no fractional part, and counts + * days from midnight to midnight. * This implementation uses an integer and days starting at midnight. * The integer value for the Julian Day Number is the astronomical Julian Day value at midday * of the date in question. diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 696ba8109cc..2fde35b5e2c 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -661,6 +661,8 @@ public class TCKDateTimeFormatterBuilder { {"W"}, {"W"}, + {"g"}, + {"ggggg"}, }; } @@ -761,6 +763,37 @@ public class TCKDateTimeFormatterBuilder { return LocalDate.of(y, m, d); } + //----------------------------------------------------------------------- + @DataProvider(name="modJulianFieldPattern") + Object[][] data_modJuilanFieldPattern() { + return new Object[][] { + {"g", "1"}, + {"g", "123456"}, + {"gggggg", "123456"}, + }; + } + + @Test(dataProvider="modJulianFieldPattern") + public void test_modJulianFieldPattern(String pattern, String input) throws Exception { + DateTimeFormatter.ofPattern(pattern).parse(input); + } + + @DataProvider(name="modJulianFieldValues") + Object[][] data_modJuilanFieldValues() { + return new Object[][] { + {1970, 1, 1, "40587"}, + {1858, 11, 17, "0"}, + {1858, 11, 16, "-1"}, + }; + } + + @Test(dataProvider="modJulianFieldValues") + public void test_modJulianFieldValues(int y, int m, int d, String expected) throws Exception { + DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter(); + assertEquals(LocalDate.of(y, m, d).format(df), expected); + } + + //----------------------------------------------------------------------- @Test public void test_adjacent_strict_firstFixedWidth() throws Exception { From 4cd4074db4a9d554b2e5b579292106821f7a2478 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Fri, 22 Apr 2016 17:07:54 +0800 Subject: [PATCH 080/167] 8154277: JavaDoc warnings in VirtualMachineManager.java and Pool.java Reviewed-by: alanb --- .../share/classes/com/sun/jdi/VirtualMachineManager.java | 6 +++--- .../share/classes/jdk/tools/jlink/plugin/Pool.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java index 5a6fd8b596c..58c435accf3 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java @@ -257,11 +257,11 @@ import java.io.IOException; * delegate to the {@link com.sun.jdi.connect.spi.TransportService#description() * description()} method of the underlying transport service. Both * the AttachingConnector and the ListeningConnector will have two - * Connector {@link com.sun.jdi.connect.Connector$Argument Arguments}. - * A {@link com.sun.jdi.connect.Connector$StringArgument StringArgument} + * Connector {@link com.sun.jdi.connect.Connector.Argument Arguments}. + * A {@link com.sun.jdi.connect.Connector.StringArgument StringArgument} * named {@code address} is the connector argument to specify the * address to attach too, or to listen on. A - * {@link com.sun.jdi.connect.Connector$IntegerArgument IntegerArgument} + * {@link com.sun.jdi.connect.Connector.IntegerArgument IntegerArgument} * named {@code timeout} is the connector argument to specify the * timeout when attaching, or accepting. The timeout connector may be * ignored depending on if the transport service supports an attach diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java index 3645f57c5f4..380ca41ac1a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java @@ -226,7 +226,7 @@ public abstract class Pool { *

  • For jimage content: /{module name}/{package1}/.../{packageN}/{file * name}
  • *
  • For other files (shared lib, launchers, config, ...):/{module name}/ - * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}
  • + * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name} * */ public static class ModuleData { From 741bd9b060d59f544558315041879f6a60b484bc Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 22 Apr 2016 09:27:35 +0000 Subject: [PATCH 081/167] 8144566: Custom HostnameVerifier disables SNI extension Reviewed-by: mullan, wetmore --- .../sun/security/ssl/SSLSocketImpl.java | 99 +++-- .../ServerName/BestEffortOnLazyConnected.java | 337 +++++++++++++++ .../https/HttpsURLConnection/ImpactOnSNI.java | 390 ++++++++++++++++++ 3 files changed, 802 insertions(+), 24 deletions(-) create mode 100644 jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java create mode 100644 jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 412c3ec8544..95258b2ec2b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -209,6 +209,12 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { Collection sniMatchers = Collections.emptyList(); + // Is the serverNames set to empty with SSLParameters.setServerNames()? + private boolean noSniExtension = false; + + // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()? + private boolean noSniMatcher = false; + // Configured application protocol values String[] applicationProtocols = new String[0]; @@ -642,6 +648,11 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { } super.connect(endpoint, timeout); + + if (host == null || host.length() == 0) { + useImplicitHost(false); + } + doneConnect(); } @@ -2098,41 +2109,62 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { outputRecord.setVersion(protocolVersion); } + // + // ONLY used by ClientHandshaker for the server hostname during handshaking + // synchronized String getHost() { // Note that the host may be null or empty for localhost. if (host == null || host.length() == 0) { - if (!trustNameService) { - // If the local name service is not trustworthy, reverse host - // name resolution should not be performed for endpoint - // identification. Use the application original specified - // hostname or IP address instead. - host = getOriginalHostname(getInetAddress()); - } else { - host = getInetAddress().getHostName(); - } + useImplicitHost(true); } return host; } /* - * Get the original application specified hostname. + * Try to set and use the implicit specified hostname */ - private static String getOriginalHostname(InetAddress inetAddress) { - /* - * Get the original hostname via jdk.internal.misc.SharedSecrets. - */ - JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess(); - String originalHostname = jna.getOriginalHostName(inetAddress); + private synchronized void useImplicitHost(boolean noSniUpdate) { - /* - * If no application specified hostname, use the IP address. - */ - if (originalHostname == null || originalHostname.length() == 0) { - originalHostname = inetAddress.getHostAddress(); + // Note: If the local name service is not trustworthy, reverse + // host name resolution should not be performed for endpoint + // identification. Use the application original specified + // hostname or IP address instead. + + // Get the original hostname via jdk.internal.misc.SharedSecrets + InetAddress inetAddress = getInetAddress(); + if (inetAddress == null) { // not connected + return; } - return originalHostname; + JavaNetInetAddressAccess jna = + SharedSecrets.getJavaNetInetAddressAccess(); + String originalHostname = jna.getOriginalHostName(inetAddress); + if ((originalHostname != null) && + (originalHostname.length() != 0)) { + + host = originalHostname; + if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) { + serverNames = + Utilities.addToSNIServerNameList(serverNames, host); + + if (!roleIsServer && + (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } + } + + return; + } + + // No explicitly specified hostname, no server name indication. + if (!trustNameService) { + // The local name service is not trustworthy, use IP address. + host = inetAddress.getHostAddress(); + } else { + // Use the underlying reverse host name resolution service. + host = getInetAddress().getHostName(); + } } // ONLY used by HttpsClient to setup the URI specified hostname @@ -2144,6 +2176,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { this.host = host; this.serverNames = Utilities.addToSNIServerNameList(this.serverNames, this.host); + + if (!roleIsServer && (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } } /** @@ -2533,8 +2569,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { // the super implementation does not handle the following parameters params.setEndpointIdentificationAlgorithm(identificationProtocol); params.setAlgorithmConstraints(algorithmConstraints); - params.setSNIMatchers(sniMatchers); - params.setServerNames(serverNames); + + if (sniMatchers.isEmpty() && !noSniMatcher) { + // 'null' indicates none has been set + params.setSNIMatchers(null); + } else { + params.setSNIMatchers(sniMatchers); + } + + if (serverNames.isEmpty() && !noSniExtension) { + // 'null' indicates none has been set + params.setServerNames(null); + } else { + params.setServerNames(serverNames); + } + params.setUseCipherSuitesOrder(preferLocalCipherSuites); params.setMaximumPacketSize(maximumPacketSize); params.setApplicationProtocols(applicationProtocols); @@ -2568,11 +2617,13 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { List sniNames = params.getServerNames(); if (sniNames != null) { + noSniExtension = sniNames.isEmpty(); serverNames = sniNames; } Collection matchers = params.getSNIMatchers(); if (matchers != null) { + noSniMatcher = matchers.isEmpty(); sniMatchers = matchers; } diff --git a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java new file mode 100644 index 00000000000..ba3e5f10e50 --- /dev/null +++ b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/** + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm BestEffortOnLazyConnected + */ + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.net.*; +import javax.net.ssl.*; + +public class BestEffortOnLazyConnected { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = "../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { + + sslSocket.connect(new InetSocketAddress(hostname, serverPort), 0); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } + } + + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new BestEffortOnLazyConnected(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + BestEffortOnLazyConnected() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java new file mode 100644 index 00000000000..4e0f0bdac59 --- /dev/null +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm ImpactOnSNI + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; + +public class ImpactOnSNI { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = + "../../../../../../javax/net/ssl/etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Is the connection ready to close? + */ + private static volatile boolean closeReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * Message posted + */ + private static final String postMsg = "HTTP post on a https server"; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + /* + * Accept connections + */ + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + BufferedReader br = + new BufferedReader(new InputStreamReader(sslIS)); + PrintStream ps = new PrintStream(sslOS); + + // process HTTP POST request from client + System.out.println("status line: " + br.readLine()); + String msg = null; + while ((msg = br.readLine()) != null && msg.length() > 0); + + msg = br.readLine(); + if (msg.equals(postMsg)) { + ps.println("HTTP/1.1 200 OK\n\n"); + } else { + ps.println("HTTP/1.1 500 Not OK\n\n"); + } + ps.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + + // close the socket + while (!closeReady) { + Thread.sleep(50); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + // Send HTTP POST request to server + URL url = new URL("https://" + hostname + ":" + serverPort); + + HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); + HttpsURLConnection http = (HttpsURLConnection)url.openConnection(); + http.setDoOutput(true); + + http.setRequestMethod("POST"); + PrintStream ps = new PrintStream(http.getOutputStream()); + try { + ps.println(postMsg); + ps.flush(); + if (http.getResponseCode() != 200) { + throw new RuntimeException("test Failed"); + } + } finally { + ps.close(); + http.disconnect(); + closeReady = true; + } + } + + private static class NameVerifier implements HostnameVerifier { + public boolean verify(String hostname, SSLSession session) { + return true; + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new ImpactOnSNI(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ImpactOnSNI() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} From 5b392c0abcaffb23ae12d2dbc6bdfefa3a30faf6 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 13:36:22 +0200 Subject: [PATCH 082/167] 8152667: MHs.iteratedLoop(...) throws unexpected WMTE, disallows Iterator subclasses, generates inconsistent loop result type Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 21 +++-- .../java/lang/invoke/LoopCombinatorTest.java | 83 ++++++++++++++++++- 2 files changed, 94 insertions(+), 10 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 5f9fc90b54d..2b5fdfebfe9 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4572,17 +4572,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); */ public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { checkIteratedLoop(iterator, body); - final boolean voidInit = init == null || init.type().returnType() == void.class; + Class resultType = init == null ? + body == null ? void.class : body.type().returnType() : + init.type().returnType(); + boolean voidResult = resultType == void.class; + + MethodHandle initIterator; + if (iterator == null) { + MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); + initIterator = initit.asType(initit.type().changeParameterType(0, + body.type().parameterType(voidResult ? 1 : 2))); + } else { + initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class)); + } - MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); - MethodHandle initIterator = iterator == null ? - initit.asType(initit.type().changeParameterType(0, body.type().parameterType(voidInit ? 1 : 2))) : - iterator; - Class itype = initIterator.type().returnType(); Class ttype = body.type().parameterType(0); MethodHandle returnVar = - dropArguments(voidInit ? zero(void.class) : identity(init.type().returnType()), 0, itype); + dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class); MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext); MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype)); diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 1df672fb997..67edb08a8cd 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -28,6 +28,7 @@ * @bug 8150635 * @bug 8150956 * @bug 8150957 + * @bug 8152667 * @bug 8153637 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -400,10 +401,15 @@ public class LoopCombinatorTest { assertTrue(caught); } - @Test - public static void testIterateVoidIterator() { + @DataProvider + static Object[][] wrongIteratorTypes() { + return new Object[][]{{void.class}, {Object.class}, {Iterable.class}}; + } + + @Test(dataProvider = "wrongIteratorTypes") + public static void testIterateVoidIterator(Class it) { boolean caught = false; - MethodType v = methodType(void.class); + MethodType v = methodType(it); try { MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); } catch(IllegalArgumentException iae) { @@ -420,6 +426,77 @@ public class LoopCombinatorTest { loop.invoke(Arrays.asList("hello", "world")); } + @DataProvider + static Object[][] iterateParameters() { + MethodType i = methodType(int.class); + MethodType sil_i = methodType(int.class, String.class, int.class, List.class); + MethodType sl_v = methodType(void.class, String.class, List.class); + MethodType l_it = methodType(Iterator.class, List.class); + MethodType li_it = methodType(Iterator.class, List.class, int.class); + MethodType l_i = methodType(int.class, List.class); + MethodType _it = methodType(Iterator.class); + MethodType si_i = methodType(int.class, String.class, int.class); + MethodType s_i = methodType(int.class, String.class); + return new Object[][]{ + {null, null, sl_v}, + {null, i, sil_i}, + {null, l_i, sil_i}, + {l_it, null, sl_v}, + {l_it, i, sil_i}, + {li_it, l_i, sil_i}, + {l_it, null, sil_i}, + {li_it, null, sl_v}, + {_it, l_i, si_i}, + {_it, l_i, s_i} + }; + } + + @Test(dataProvider = "iterateParameters") + public static void testIterateParameters(MethodType it, MethodType in, MethodType bo) throws Throwable { + MethodHandle iterator = it == null ? null : MethodHandles.empty(it); + MethodHandle init = in == null ? null : MethodHandles.empty(in); + MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo)); + MethodType lt = loop.type(); + if (it == null && in == null) { + assertEquals(bo.dropParameterTypes(0, 1), lt); + } else if (it == null) { + if (in.parameterCount() == 0) { + assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt); + } else { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } + } else if (in == null) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() > in.parameterCount()) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() < in.parameterCount()) { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } else { + // both it, in present; with equal parameter list lengths + assertEquals(it.parameterList(), lt.parameterList()); + assertEquals(in.parameterList(), lt.parameterList()); + assertEquals(bo.returnType(), lt.returnType()); + } + } + + @Test + public static void testIteratorSubclass() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)), + null, MethodHandles.empty(methodType(void.class, String.class))); + assertEquals(methodType(void.class, List.class), loop.type()); + } + + static class BogusIterator implements Iterator { + @Override + public boolean hasNext() { + return false; + } + @Override + public Object next() { + return null; + } + } + static class Empty { static void f() { } From e53e280d376074035a3281aae0f466167ddcc06a Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 15:05:26 +0200 Subject: [PATCH 083/167] 8154751: MethodHandles.countedLoop does not accept empty bodies Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 12 ++++++++---- .../java/lang/invoke/LoopCombinatorTest.java | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 2b5fdfebfe9..9992483de04 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4476,12 +4476,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ? - zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class); + MethodHandle defaultResultHandle = init == null || init.type().returnType() == void.class ? + zero(void.class) : + identity(init.type().returnType()); + MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), + returnVar}; MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(body, 1, int.class), 0, + filterArgument(dropArguments(adaptedBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 67edb08a8cd..5637a9958a0 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -30,6 +30,7 @@ * @bug 8150957 * @bug 8152667 * @bug 8153637 + * @bug 8154751 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -347,6 +348,23 @@ public class LoopCombinatorTest { assertEquals(10, loop.invoke()); } + @Test + public static void testCountedLoopEmpty() throws Throwable { + // for (int i = 0; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedRangeLoopEmpty() throws Throwable { + // for (int i = -5; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, -5), + MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + @Test public static void testIterateSum() throws Throwable { // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21 From cafabcafce8227c4f8146c253b51bf4962bbbbaf Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Fri, 22 Apr 2016 15:05:54 +0200 Subject: [PATCH 084/167] 8154754: MethodHandles.countedLoop errors in deriving loop arguments, result type, and local state Reviewed-by: redestad --- .../java/lang/invoke/MethodHandles.java | 24 +++-- .../java/lang/invoke/LoopCombinatorTest.java | 88 +++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 9992483de04..6c37371a57b 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4476,16 +4476,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle defaultResultHandle = init == null || init.type().returnType() == void.class ? - zero(void.class) : - identity(init.type().returnType()); - MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + Class resultType; + MethodHandle actualInit; + if (init == null) { + resultType = body == null ? void.class : body.type().returnType(); + actualInit = empty(methodType(resultType)); + } else { + resultType = init.type().returnType(); + actualInit = init; + } + MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType); + MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); + MethodHandle actualEnd = end == null ? constant(int.class, 0) : end; MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), - returnVar}; - MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(adaptedBody, 1, int.class), 0, + MethodHandle[] loopLimit = {actualEnd, null, + MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] bodyClause = {actualInit, + filterArgument(dropArguments(actualBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 5637a9958a0..625e55c611d 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -31,6 +31,7 @@ * @bug 8152667 * @bug 8153637 * @bug 8154751 + * @bug 8154754 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -326,6 +327,74 @@ public class LoopCombinatorTest { loop.invoke(); } + @Test + public static void testCountedLoopNullBody() throws Throwable { + MethodHandle h5 = MethodHandles.constant(int.class, 5); + MethodHandle h13 = MethodHandles.constant(int.class, 13); + MethodHandle loop = MethodHandles.countedLoop(h5, h13, null); + assertEquals(methodType(int.class), loop.type()); + assertEquals(13, loop.invoke()); + } + + @Test + public static void testCountedLoopNullIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(null, null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopNullInitAndBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @DataProvider + static Object[][] countedLoopBodyParameters() { + return new Object[][] { + {methodType(String.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class, String.class)} + }; + } + + @Test(dataProvider = "countedLoopBodyParameters") + public static void testCountedLoopBodyParameters(MethodType initType, MethodType bodyType) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), + MethodHandles.empty(initType), MethodHandles.empty(bodyType)); + assertEquals(initType, loop.type()); + } + + @DataProvider + static Object[][] countedLoopTypes() { + return new Object[][]{{void.class}, {int.class}, {Object.class}, {String.class}, {List.class}}; + } + + @Test(dataProvider = "countedLoopTypes") + public static void testCountedLoopBodyParametersNullInit(Class t) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, + MethodHandles.empty(methodType(t, int.class))); + assertEquals(methodType(t), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopStateDefinedByBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, Counted.MH_stateBody); + assertEquals(Counted.MT_bodyDeterminesState, loop.type()); + assertEquals("sssssnull01234", loop.invoke()); + } + + @Test + public static void testCountedLoopArgsDefinedByIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop( + MethodHandles.dropArguments(MethodHandles.constant(int.class, 3), 0, String.class), + null, Counted.MH_append); + assertEquals(Counted.MT_iterationsDefineArgs, loop.type()); + assertEquals("hello012", loop.invoke("hello")); + } + @Test public static void testCountedRangeLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme @@ -839,6 +908,17 @@ public class LoopCombinatorTest { return x + counter; } + static String stateBody(int counter, String s) { + return "s" + s + counter; + } + + static String append(int counter, String localState, String loopArg) { + if (null == localState) { + return loopArg + counter; + } + return localState + counter; + } + static final Class COUNTED = Counted.class; static final MethodType MT_start = methodType(String.class, String.class); @@ -846,6 +926,8 @@ public class LoopCombinatorTest { static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class); static final MethodType MT_printHello = methodType(void.class, int.class); static final MethodType MT_addCounter = methodType(int.class, int.class, int.class); + static final MethodType MT_stateBody = methodType(String.class, int.class, String.class); + static final MethodType MT_append = methodType(String.class, int.class, String.class, String.class); static final MethodHandle MH_13; static final MethodHandle MH_m5; @@ -855,11 +937,15 @@ public class LoopCombinatorTest { static final MethodHandle MH_stepUpdateArray; static final MethodHandle MH_printHello; static final MethodHandle MH_addCounter; + static final MethodHandle MH_stateBody; + static final MethodHandle MH_append; static final MethodType MT_counted = methodType(String.class, String.class); static final MethodType MT_arrayCounted = methodType(void.class, int[].class); static final MethodType MT_countedPrinting = methodType(void.class); static final MethodType MT_counterInit = methodType(int.class); + static final MethodType MT_bodyDeterminesState = methodType(String.class); + static final MethodType MT_iterationsDefineArgs = methodType(String.class, String.class); static { try { @@ -871,6 +957,8 @@ public class LoopCombinatorTest { MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray); MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello); MH_addCounter = LOOKUP.findStatic(COUNTED, "addCounter", MT_addCounter); + MH_stateBody = LOOKUP.findStatic(COUNTED, "stateBody", MT_stateBody); + MH_append = LOOKUP.findStatic(COUNTED, "append", MT_append); } catch (Exception e) { throw new ExceptionInInitializerError(e); } From ddff1247c6f871881800a0b7456c7ba05ffd9dae Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 22 Apr 2016 09:43:19 -0700 Subject: [PATCH 085/167] 8154837: Class::getPackage with exploded modules when classes in modules defined to the boot loader Reviewed-by: alanb, chegar --- .../classes/jdk/internal/loader/BootLoader.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java index 6fc5e7d4ec8..269c193dbe4 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java @@ -30,6 +30,7 @@ import java.lang.module.ModuleReference; import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -184,9 +185,9 @@ public class BootLoader { /** * Define the {@code Package} with the given name. The specified - * location is a jrt URL to a named module in the run-time image, a - * file path to a module in an exploded run-time image, or the file - * path to an enty on the boot class path (java agent Boot-Class-Path + * location is a jrt URL to a named module in the run-time image, + * a file URL to a module in an exploded run-time image, or a file + * path to an entry on the boot class path (java agent Boot-Class-Path * or -Xbootclasspath/a. * *

    If the given location is a JAR file containing a manifest, @@ -194,7 +195,9 @@ public class BootLoader { * the manifest, if present. * * @param name package name - * @param location location where the package is (jrt URL or file path) + * @param location location where the package is (jrt URL or file URL + * for a named module in the run-time or exploded image; + * a file path for a package from -Xbootclasspath/a) */ static Package definePackage(String name, String location) { Module module = findModule(location); @@ -222,9 +225,9 @@ public class BootLoader { if (location.startsWith("jrt:/")) { // named module in runtime image ("jrt:/".length() == 5) mn = location.substring(5, location.length()); - } else { + } else if (location.startsWith("file:/")) { // named module in exploded image - Path path = Paths.get(location); + Path path = Paths.get(URI.create(location)); Path modulesDir = Paths.get(JAVA_HOME, "modules"); if (path.startsWith(modulesDir)) { mn = path.getFileName().toString(); From 48a86ddf3e17f7244d3e87b89d0f00b51ba0d7eb Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Fri, 22 Apr 2016 13:10:53 -0700 Subject: [PATCH 086/167] 8153330: deprecate Runtime.traceInstructions() and traceMethodCalls() Reviewed-by: alanb, dholmes, mchung --- .../share/classes/java/lang/Runtime.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index a5deffc16b8..3c73d5b61a3 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -718,41 +718,27 @@ public class Runtime { } /** - * Enables/Disables tracing of instructions. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each instruction in the virtual machine as it - * is executed. The format of this information, and the file or other - * output stream to which it is emitted, depends on the host environment. - * The virtual machine may ignore this request if it does not support - * this feature. The destination of the trace output is system - * dependent. - *

    - * If the {@code boolean} argument is {@code false}, this - * method causes the virtual machine to stop performing the - * detailed instruction trace it is performing. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control instruction tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceInstructions(boolean on) { } /** - * Enables/Disables tracing of method calls. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each method in the virtual machine as it is - * called. The format of this information, and the file or other output - * stream to which it is emitted, depends on the host environment. The - * virtual machine may ignore this request if it does not support - * this feature. - *

    - * Calling this method with argument false suggests that the - * virtual machine cease emitting per-call debugging information. + * Not implemented, does nothing. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @deprecated + * This method was intended to control method call tracing. + * It has been superseded by JVM-specific tracing mechanisms. + * + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceMethodCalls(boolean on) { } /** From 6c1f9eea71e8790bc5076204f33495cd559a5354 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sun, 24 Apr 2016 08:44:36 +0100 Subject: [PATCH 087/167] 8154919: Remove superfluous jdk.unsupported from tools/launcher/modules/limitmods/LimitModsTest.java Reviewed-by: alanb --- jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java index f11aa003e00..0cafaf42e66 100644 --- a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java +++ b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java @@ -103,10 +103,9 @@ public class LimitModsTest { public void testWithAddMods() throws Exception { int exitValue; - // java -limitmods java.base -addmods java.logging,jdk.unsupported -listmods + // java -limitmods java.base -addmods java.logging -listmods exitValue = executeTestJava("-limitmods", "java.base", - "-addmods", - "java.logging,jdk.unsupported", // TODO: add bug No. + "-addmods", "java.logging", "-listmods") .outputTo(System.out) .errorTo(System.out) From 3f14fca9652114ba863e408e59e477a0b93dbc44 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sun, 24 Apr 2016 08:51:04 +0100 Subject: [PATCH 088/167] 8147543: Remove sun.misc.ManagedLocalsThread Reviewed-by: rriggs --- .../classes/sun/misc/ManagedLocalsThread.java | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java diff --git a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java b/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java deleted file mode 100644 index 58d9013c261..00000000000 --- a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; - -/** - * A thread that has it's thread locals, and inheritable thread - * locals erased on construction. - */ -public class ManagedLocalsThread extends Thread { - private static final jdk.internal.misc.Unsafe UNSAFE; - private static final long THREAD_LOCALS; - private static final long INHERITABLE_THREAD_LOCALS; - - public ManagedLocalsThread() { - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target) { - super(target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(String name) { - super(name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target) { - super(group, target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target, String name) { - super(target, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, String name) { - super(group, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - eraseThreadLocals(); - } - - /** - * Drops all thread locals (and inherited thread locals). - */ - public final void eraseThreadLocals() { - UNSAFE.putObject(this, THREAD_LOCALS, null); - UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null); - } - - static { - UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); - Class t = Thread.class; - try { - THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("threadLocals")); - INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("inheritableThreadLocals")); - } catch (Exception e) { - throw new Error(e); - } - } -} - From 52e49f6e86dd564c1cfc1c845a0478d4996458e5 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 3 Mar 2016 12:47:46 +0100 Subject: [PATCH 089/167] 8150460: (linux|bsd|aix)_close.c: file descriptor table may become large or may not work at all Reviewed-by: dsamersoff, rriggs --- .../java.base/aix/native/libnet/aix_close.c | 133 ++++++++++++++---- .../linux/native/libnet/linux_close.c | 124 ++++++++++++++-- .../macosx/native/libnet/bsd_close.c | 133 ++++++++++++++---- 3 files changed, 317 insertions(+), 73 deletions(-) diff --git a/jdk/src/java.base/aix/native/libnet/aix_close.c b/jdk/src/java.base/aix/native/libnet/aix_close.c index 0165c9a1959..77b5daecf60 100644 --- a/jdk/src/java.base/aix/native/libnet/aix_close.c +++ b/jdk/src/java.base/aix/native/libnet/aix_close.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE 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 @@ -50,6 +51,8 @@ ... */ +#include +#include #include #include #include @@ -86,10 +89,35 @@ typedef struct { static int sigWakeup = (SIGRTMAX - 1); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable = NULL; -static int fdCount = 0; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -108,42 +136,42 @@ void aix_close_init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* Check already initialized */ - if (fdCount > 0 && fdTable != NULL) { - return; - } - - /* - * Allocate table based on the maximum number of - * file descriptors. - */ + /* Determine the maximum number of possible file descriptors. */ if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { fprintf(stderr, "library initialization failed - " "unable to get max # of allocated fds\n"); abort(); } - fdCount = nbr_files.rlim_max; - /* - * We have a conceptual problem here, when the number of files is - * unlimited. As a kind of workaround, we ensure the table is big - * enough for handle even a large number of files. Since SAP itself - * recommends a limit of 32000 files, we just use 64000 as 'infinity'. - */ - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = 64000; + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - { - int i; - for (i=0; i < fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); } } @@ -161,17 +189,60 @@ void aix_close_init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. diff --git a/jdk/src/java.base/linux/native/libnet/linux_close.c b/jdk/src/java.base/linux/native/libnet/linux_close.c index f2e186f731e..45ab7b4dc1b 100644 --- a/jdk/src/java.base/linux/native/libnet/linux_close.c +++ b/jdk/src/java.base/linux/native/libnet/linux_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -59,10 +61,35 @@ typedef struct { static int sigWakeup = (__SIGRTMAX - 2); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -78,18 +105,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - fdCount = nbr_files.rlim_max; - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } + } + + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -106,15 +158,57 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } /* diff --git a/jdk/src/java.base/macosx/native/libnet/bsd_close.c b/jdk/src/java.base/macosx/native/libnet/bsd_close.c index 21478ce6e5f..728ea8bf1d7 100644 --- a/jdk/src/java.base/macosx/native/libnet/bsd_close.c +++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -61,18 +63,35 @@ typedef struct { static int sigWakeup = SIGIO; /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; -/* - * This limit applies if getlimit() returns unlimited. - * Unfortunately, this means if someone wants a higher limit - * then they have to set an explicit limit, higher than this, - * which is probably counter-intuitive. +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. */ -#define MAX_FD_COUNT 4096 +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -88,26 +107,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; - int i; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = MAX_FD_COUNT; - } else { - fdCount = nbr_files.rlim_max; + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - for (i=0; i fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -124,17 +160,60 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. From 0e76458fca8c289d1e0349757d78ab152b7a6ed6 Mon Sep 17 00:00:00 2001 From: Kirill Zhaldybin Date: Mon, 14 Mar 2016 20:00:57 +0300 Subject: [PATCH 090/167] 8144073: Refactor hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java Reviewed-by: tschatzl, dfazunen --- .../humongousObjects/TestHumongousThreshold.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java index a9a83728195..3b66bc7507c 100644 --- a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java +++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015,2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public class TestHumongousThreshold { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int REGION_SIZE = WHITE_BOX.g1RegionSize(); private static final int MAX_CONTINUOUS_SIZE_CHECK = 129; - private static final int NON_HUMONGOUS_DIVIDER = 10; + private static final int NON_HUMONGOUS_STEPS = 10; /** * The method allocates byte[] with specified size and checks that: @@ -84,7 +84,7 @@ public class TestHumongousThreshold { * @return allocated byte array */ - private static byte[] allocateAndCheck(int arraySize, boolean expectedHumongous) { + private static void allocateAndCheck(int arraySize, boolean expectedHumongous) { byte[] storage = new byte[arraySize]; long objectSize = WHITE_BOX.getObjectSize(storage); boolean shouldBeHumongous = objectSize > (REGION_SIZE / 2); @@ -98,7 +98,6 @@ public class TestHumongousThreshold { "Object should be allocated as " + (shouldBeHumongous ? "humongous" : "non-humongous") + " but it wasn't; Allocation size = " + arraySize + "; Object size = " + objectSize + "; region size = " + REGION_SIZE); - return storage; } public static void main(String[] args) { @@ -108,7 +107,7 @@ public class TestHumongousThreshold { int maxByteArrayNonHumongousSize = (REGION_SIZE / 2) - byteArrayMemoryOverhead; // Increment for non-humongous testing - int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_DIVIDER; + int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_STEPS; // Maximum byte[] that takes one region int maxByteArrayOneRegionSize = REGION_SIZE - byteArrayMemoryOverhead; @@ -131,10 +130,10 @@ public class TestHumongousThreshold { allocateAndCheck(i, false); } - // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_DIVIDER + // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_STEPS System.out.format("Testing allocations with byte[] with length from 0 to %d with step %d%n", - nonHumongousStep * NON_HUMONGOUS_DIVIDER, nonHumongousStep); - for (int i = 0; i < NON_HUMONGOUS_DIVIDER; ++i) { + nonHumongousStep * NON_HUMONGOUS_STEPS, nonHumongousStep); + for (int i = 0; i < NON_HUMONGOUS_STEPS; ++i) { allocateAndCheck(i * nonHumongousStep, false); } From b51a55a78cb36b057e1ee217f2b634a9773fbb5c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 6 Apr 2016 10:50:19 +0300 Subject: [PATCH 091/167] 8153277: [TESTBUG] gc/arguments/TestMaxMinHeapFreeRatioFlags is too sensitive for stray allocations in verifyRatio Reviewed-by: mgerdin, dfazunen --- hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index 055ea672adb..af37af4947c 100644 --- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -168,6 +168,11 @@ public class TestMaxMinHeapFreeRatioFlags { long maxHeapSize = getMax(); int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1); + // Initial checks. This also links up everything in these helper methods, + // in case it brings more garbage. + forceGC(gcTries); + verifyRatio(minRatio, maxRatio); + // commit 0.5 of total heap size to have enough space // to both shink and expand while (getCommitted() < maxHeapSize / 2) { @@ -215,7 +220,6 @@ public class TestMaxMinHeapFreeRatioFlags { if (previouslyCommitted <= getCommitted()) { throw new RuntimeException("Heap was not shrinked."); } - } public static void forceGC(int gcTries) { From 0c06163b35d78b2ef3c006593fc241528b796a20 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 6 Apr 2016 13:32:48 +0200 Subject: [PATCH 092/167] 8077144: Concurrent mark initialization takes too long Remove per-marking thread liveness bitmaps and recreate liveness bitmap concurrently after the cleanup pause. Reviewed-by: mgerdin, ehelin, kbarrett --- .../share/vm/gc/g1/concurrentMarkThread.cpp | 5 + .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 817 ++++++++---------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 151 +--- .../vm/gc/g1/g1ConcurrentMark.inline.hpp | 147 +--- hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp | 7 +- .../share/vm/gc/g1/g1OopClosures.inline.hpp | 6 +- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 3 + hotspot/src/share/vm/utilities/bitMap.cpp | 4 + hotspot/src/share/vm/utilities/bitMap.hpp | 7 + hotspot/test/gc/g1/Test2GbHeap.java | 16 +- 10 files changed, 452 insertions(+), 711 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index c72cbae1474..7eef582e3db 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -183,6 +183,11 @@ void ConcurrentMarkThread::run_service() { } } while (cm()->restart_for_overflow()); + if (!cm()->has_aborted()) { + G1ConcPhaseTimer t(_cm, "Concurrent Create Live Data"); + cm()->create_live_data(); + } + double end_time = os::elapsedVTime(); // Update the total virtual time before doing this, since it will try // to measure it to get the vtime for this marking. We purposely diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 2ed3dd0f4ed..a181b467c7d 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -48,6 +48,7 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/vmGCOperations.hpp" #include "logging/log.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -355,10 +356,8 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _sleep_factor(0.0), _marking_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/), - _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >> - CardTableModRefBS::card_shift, - false /* in_resource_area*/), + _region_live_bm(), + _card_live_bm(), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -390,8 +389,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _parallel_workers(NULL), - _count_card_bitmaps(NULL), - _count_marked_bytes(NULL), _completed_initialization(false) { _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage); @@ -502,43 +499,28 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* return; } + allocate_internal_bitmaps(); + + if (G1PretouchAuxiliaryMemory) { + pretouch_internal_bitmaps(); + } + _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); - _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); - _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC); - - BitMap::idx_t card_bm_size = _card_bm.size(); - // so that the assertion in MarkingTaskQueue::task_queue doesn't fail _active_tasks = _max_worker_id; - uint max_regions = _g1h->max_regions(); for (uint i = 0; i < _max_worker_id; ++i) { G1CMTaskQueue* task_queue = new G1CMTaskQueue(); task_queue->initialize(); _task_queues->register_queue(i, task_queue); - _count_card_bitmaps[i] = BitMap(card_bm_size, false); - _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); - - _tasks[i] = new G1CMTask(i, this, - _count_marked_bytes[i], - &_count_card_bitmaps[i], - task_queue, _task_queues); + _tasks[i] = new G1CMTask(i, this, task_queue, _task_queues); _accum_task_vtime[i] = 0.0; } - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_bottom_card_num = - intptr_t(uintptr_t(_g1h->reserved_region().start()) >> - CardTableModRefBS::card_shift); - - // Clear all the liveness counting data - clear_all_count_data(); - // so that the call below can read a sensible value _heap_start = g1h->reserved_region().start(); set_non_marking_state(); @@ -716,10 +698,11 @@ void G1ConcurrentMark::cleanup_for_next_mark() { clear_bitmap(_nextMarkBitMap, _parallel_workers, true); - // Clear the liveness counting data. If the marking has been aborted, the abort() + // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_all_count_data(); + clear_all_live_data(_parallel_workers); + DEBUG_ONLY(verify_all_live_data()); } // Repeat the asserts from above. @@ -1107,14 +1090,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // marking due to overflowing the global mark stack. reset_marking_state(); } else { - { - GCTraceTime(Debug, gc, phases) trace("Aggregate Data", _gc_timer_cm); - - // Aggregate the per-task counting data that we have accumulated - // while marking. - aggregate_count_data(); - } - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); // We're done with marking. // This is the end of the marking cycle, we're expected all @@ -1150,17 +1125,81 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { _gc_tracer_cm->report_object_count_after_gc(&is_alive); } -// Base class of the closures that finalize and verify the -// liveness counting data. -class G1CMCountDataClosureBase: public HeapRegionClosure { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - +// Helper class that provides functionality to generate the Live Data Count +// information. +class G1LiveDataHelper VALUE_OBJ_CLASS_SPEC { +private: BitMap* _region_bm; BitMap* _card_bm; + // The card number of the bottom of the G1 heap. Used for converting addresses + // to bitmap indices quickly. + BitMap::idx_t _heap_card_bias; + + // Utility routine to set an exclusive range of bits on the given + // bitmap, optimized for very small ranges. + // There must be at least one bit to set. + inline void set_card_bitmap_range(BitMap* bm, + BitMap::idx_t start_idx, + BitMap::idx_t end_idx) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one bit"); + assert(end_idx <= bm->size(), "sanity"); + + // For small ranges use a simple loop; otherwise use set_range or + // use par_at_put_range (if parallel). The range is made up of the + // cards that are spanned by an object/mem region so 8 cards will + // allow up to object sizes up to 4K to be handled using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + bm->set_bit(i); + } + } else { + bm->set_range(start_idx, end_idx); + } + } + + // We cache the last mark set. This avoids setting the same bit multiple times. + // This is particularly interesting for dense bitmaps, as this avoids doing + // lots of work most of the time. + BitMap::idx_t _last_marked_bit_idx; + + // Mark the card liveness bitmap for the object spanning from start to end. + void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { + BitMap::idx_t start_idx = card_live_bitmap_index_for(start); + BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); + + assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); + + if (start_idx == _last_marked_bit_idx) { + start_idx++; + } + if (start_idx == end_idx) { + return; + } + + // Set the bits in the card bitmap for the cards spanned by this object. + set_card_bitmap_range(_card_bm, start_idx, end_idx); + _last_marked_bit_idx = end_idx - 1; + } + + void reset_mark_cache() { + _last_marked_bit_idx = (BitMap::idx_t)-1; + } + +public: + // Returns the index in the per-card liveness count bitmap + // for the given address + inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + BitMap::idx_t card_num = (BitMap::idx_t)(uintptr_t(addr) >> CardTableModRefBS::card_shift); + return card_num - _heap_card_bias; + } + // Takes a region that's not empty (i.e., it has at least one // live object in it and sets its corresponding bit on the region // bitmap to 1. @@ -1169,136 +1208,128 @@ protected: _region_bm->par_at_put(index, true); } -public: - G1CMCountDataClosureBase(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm): - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _region_bm(region_bm), _card_bm(card_bm) { } -}; + // Mark the range of bits covered by allocations done since the last marking + // in the given heap region, i.e. from NTAMS to top of the given region. + // Returns if there has been some allocation in this region since the last marking. + bool mark_allocated_since_marking(HeapRegion* hr) { + reset_mark_cache(); -// Closure that calculates the # live objects per region. Used -// for verification purposes during the cleanup pause. -class CalcLiveObjectsClosure: public G1CMCountDataClosureBase { - G1CMBitMapRO* _bm; - size_t _region_marked_bytes; + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); -public: - CalcLiveObjectsClosure(G1CMBitMapRO *bm, G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm), - _bm(bm), _region_marked_bytes(0) { } + assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + // Mark the allocated-since-marking portion... + if (ntams < top) { + mark_card_bitmap_range(ntams, top); + return true; + } else { + return false; + } + } + + // Mark the range of bits covered by live objects on the mark bitmap between + // bottom and NTAMS of the given region. + // Returns the number of live bytes marked within that area for the given + // heap region. + size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { + reset_mark_cache(); + + size_t marked_bytes = 0; - bool doHeapRegion(HeapRegion* hr) { HeapWord* ntams = hr->next_top_at_mark_start(); HeapWord* start = hr->bottom(); + if (ntams <= start) { + // Skip empty regions. + return 0; + } else if (hr->is_humongous()) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), "Preconditions not met - " "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, p2i(start), p2i(ntams), p2i(hr->end())); // Find the first marked object at or after "start". - start = _bm->getNextMarkedWordAddress(start, ntams); - - size_t marked_bytes = 0; - + start = mark_bitmap->getNextMarkedWordAddress(start, ntams); while (start < ntams) { oop obj = oop(start); int obj_sz = obj->size(); HeapWord* obj_end = start + obj_sz; - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(obj_end); + assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); - // Note: if we're looking at the last region in heap - obj_end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(obj_end) && !_ct_bs->is_card_aligned(obj_end)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - - // Set the bits in the card BM for the cards spanned by this object. - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); + mark_card_bitmap_range(start, obj_end); // Add the size of this object to the number of marked bytes. marked_bytes += (size_t)obj_sz * HeapWordSize; - // This will happen if we are handling a humongous object that spans - // several heap regions. - if (obj_end > hr->end()) { - break; - } // Find the next marked object after this one. - start = _bm->getNextMarkedWordAddress(obj_end, ntams); + start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); } - // Mark the allocated-since-marking portion... - HeapWord* top = hr->top(); - if (ntams < top) { - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); - - // This definitely means the region has live objects. - set_bit_for_region(hr); - } - - // Update the live region bitmap. - if (marked_bytes > 0) { - set_bit_for_region(hr); - } - - // Set the marked bytes for the current region so that - // it can be queried by a calling verification routine - _region_marked_bytes = marked_bytes; - - return false; + return marked_bytes; } - size_t region_marked_bytes() const { return _region_marked_bytes; } + G1LiveDataHelper(BitMap* region_bm, + BitMap* card_bm): + _region_bm(region_bm), + _card_bm(card_bm) { + //assert(region_bm != NULL, ""); + assert(card_bm != NULL, ""); + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_card_bias = + (BitMap::idx_t)(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> CardTableModRefBS::card_shift); + } }; -// Heap region closure used for verifying the counting data -// that was accumulated concurrently and aggregated during +// Heap region closure used for verifying the live count data +// that was created concurrently and finalized during // the remark pause. This closure is applied to the heap // regions during the STW cleanup pause. - -class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { +class G1VerifyLiveDataHRClosure: public HeapRegionClosure { +private: G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CalcLiveObjectsClosure _calc_cl; - BitMap* _region_bm; // Region BM to be verified - BitMap* _card_bm; // Card BM to be verified + G1CMBitMap* _mark_bitmap; + G1LiveDataHelper _calc_helper; + + BitMap* _act_region_bm; // Region BM to be verified + BitMap* _act_card_bm; // Card BM to be verified BitMap* _exp_region_bm; // Expected Region BM values BitMap* _exp_card_bm; // Expected card BM values int _failures; + // Updates the live data count for the given heap region and returns the number + // of bytes marked. + size_t create_live_data_count(HeapRegion* hr) { + size_t bytes_marked = _calc_helper.mark_marked_during_marking(_mark_bitmap, hr); + bool allocated_since_marking = _calc_helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || bytes_marked > 0) { + _calc_helper.set_bit_for_region(hr); + } + return bytes_marked; + } + public: - VerifyLiveObjectDataHRClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm, - BitMap* exp_region_bm, - BitMap* exp_card_bm) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _calc_cl(_cm->nextMarkBitMap(), g1h, exp_region_bm, exp_card_bm), - _region_bm(region_bm), _card_bm(card_bm), - _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), + G1VerifyLiveDataHRClosure(G1CollectedHeap* g1h, + G1CMBitMap* mark_bitmap, + BitMap* act_region_bm, + BitMap* act_card_bm, + BitMap* exp_region_bm, + BitMap* exp_card_bm) : + _g1h(g1h), + _mark_bitmap(mark_bitmap), + _calc_helper(exp_region_bm, exp_card_bm), + _act_region_bm(act_region_bm), + _act_card_bm(act_card_bm), + _exp_region_bm(exp_region_bm), + _exp_card_bm(exp_card_bm), _failures(0) { } int failures() const { return _failures; } @@ -1306,35 +1337,16 @@ public: bool doHeapRegion(HeapRegion* hr) { int failures = 0; - // Call the CalcLiveObjectsClosure to walk the marking bitmap for - // this region and set the corresponding bits in the expected region - // and card bitmaps. - bool res = _calc_cl.doHeapRegion(hr); - assert(res == false, "should be continuing"); - - // Verify the marked bytes for this region. - size_t exp_marked_bytes = _calc_cl.region_marked_bytes(); + // Walk the marking bitmap for this region and set the corresponding bits + // in the expected region and card bitmaps. + size_t exp_marked_bytes = create_live_data_count(hr); size_t act_marked_bytes = hr->next_marked_bytes(); + // Verify the marked bytes for this region. - if (exp_marked_bytes > act_marked_bytes) { - if (hr->is_starts_humongous()) { - // For start_humongous regions, the size of the whole object will be - // in exp_marked_bytes. - HeapRegion* region = hr; - int num_regions; - for (num_regions = 0; region != NULL; num_regions++) { - region = _g1h->next_region_in_humongous(region); - } - if ((num_regions-1) * HeapRegion::GrainBytes >= exp_marked_bytes) { - failures += 1; - } else if (num_regions * HeapRegion::GrainBytes < exp_marked_bytes) { - failures += 1; - } - } else { - // We're not OK if expected marked bytes > actual marked bytes. It means - // we have missed accounting some objects during the actual marking. - failures += 1; - } + if (exp_marked_bytes != act_marked_bytes) { + failures += 1; + } else if (exp_marked_bytes > HeapRegion::GrainBytes) { + failures += 1; } // Verify the bit, for this region, in the actual and expected @@ -1344,7 +1356,7 @@ public: BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); bool expected = _exp_region_bm->at(index); - bool actual = _region_bm->at(index); + bool actual = _act_region_bm->at(index); if (expected && !actual) { failures += 1; } @@ -1353,12 +1365,12 @@ public: // region match. We have an error if we have a set bit in the expected // bit map and the corresponding bit in the actual bitmap is not set. - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(hr->bottom()); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(hr->top()); + BitMap::idx_t start_idx = _calc_helper.card_live_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _calc_helper.card_live_bitmap_index_for(hr->top()); for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { expected = _exp_card_bm->at(i); - actual = _card_bm->at(i); + actual = _act_card_bm->at(i); if (expected && !actual) { failures += 1; @@ -1373,137 +1385,100 @@ public: } }; -class G1ParVerifyFinalCountTask: public AbstractGangTask { +class G1VerifyLiveDataTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; + G1CMBitMap* _mark_bitmap; BitMap* _actual_region_bm; BitMap* _actual_card_bm; - uint _n_workers; - - BitMap* _expected_region_bm; - BitMap* _expected_card_bm; + BitMap _expected_region_bm; + BitMap _expected_card_bm; int _failures; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm, - BitMap* expected_region_bm, BitMap* expected_card_bm) - : AbstractGangTask("G1 verify final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), - _failures(0), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { + G1VerifyLiveDataTask(G1CollectedHeap* g1h, + G1CMBitMap* bitmap, + BitMap* region_bm, + BitMap* card_bm, + uint n_workers) + : AbstractGangTask("G1 verify final counting"), + _g1h(g1h), + _mark_bitmap(bitmap), + _actual_region_bm(region_bm), + _actual_card_bm(card_bm), + _expected_region_bm(region_bm->size(), true /* in_resource_area */), + _expected_card_bm(card_bm->size(), true /* in_resource_area */), + _failures(0), + _hr_claimer(n_workers) { assert(VerifyDuringGC, "don't call this otherwise"); - assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); - assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); } void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); + G1VerifyLiveDataHRClosure cl(_g1h, + _mark_bitmap, + _actual_region_bm, + _actual_card_bm, + &_expected_region_bm, + &_expected_card_bm); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - VerifyLiveObjectDataHRClosure verify_cl(_g1h, - _actual_region_bm, _actual_card_bm, - _expected_region_bm, - _expected_card_bm); - - _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); - - Atomic::add(verify_cl.failures(), &_failures); + Atomic::add(cl.failures(), &_failures); } int failures() const { return _failures; } }; -// Closure that finalizes the liveness counting data. -// Used during the cleanup pause. -// Sets the bits corresponding to the interval [NTAMS, top] -// (which contains the implicitly live objects) in the -// card liveness bitmap. Also sets the bit for each region, -// containing live data, in the region liveness bitmap. +class G1FinalizeLiveDataTask: public AbstractGangTask { + // Finalizes the liveness counting data. + // Sets the bits corresponding to the interval [NTAMS, top] + // (which contains the implicitly live objects) in the + // card liveness bitmap. Also sets the bit for each region + // containing live data, in the region liveness bitmap. + class G1FinalizeCountDataClosure: public HeapRegionClosure { + private: + G1LiveDataHelper _helper; + public: + G1FinalizeCountDataClosure(G1CMBitMap* bitmap, + BitMap* region_bm, + BitMap* card_bm) : + HeapRegionClosure(), + _helper(region_bm, card_bm) { } -class FinalCountDataUpdateClosure: public G1CMCountDataClosureBase { - public: - FinalCountDataUpdateClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm) { } - - bool doHeapRegion(HeapRegion* hr) { - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* top = hr->top(); - - assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); - - // Mark the allocated-since-marking portion... - if (ntams < top) { - // This definitely means the region has live objects. - set_bit_for_region(hr); - - // Now set the bits in the card bitmap for [ntams, top) - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; + bool doHeapRegion(HeapRegion* hr) { + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || hr->next_marked_bytes() > 0) { + _helper.set_bit_for_region(hr); } - - assert(end_idx <= _card_bm->size(), - "oob: end_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - end_idx, _card_bm->size()); - assert(start_idx < _card_bm->size(), - "oob: start_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - start_idx, _card_bm->size()); - - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); + return false; } + }; - // Set the bit for the region if it contains live data - if (hr->next_marked_bytes() > 0) { - set_bit_for_region(hr); - } + G1CMBitMap* _bitmap; - return false; - } -}; - -class G1ParFinalCountTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; BitMap* _actual_region_bm; BitMap* _actual_card_bm; - uint _n_workers; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) - : AbstractGangTask("G1 final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { + G1FinalizeLiveDataTask(G1CMBitMap* bitmap, BitMap* region_bm, BitMap* card_bm, uint n_workers) : + AbstractGangTask("G1 final counting"), + _bitmap(bitmap), + _actual_region_bm(region_bm), + _actual_card_bm(card_bm), + _hr_claimer(n_workers) { } void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); + G1FinalizeCountDataClosure cl(_bitmap, + _actual_region_bm, + _actual_card_bm); - FinalCountDataUpdateClosure final_update_cl(_g1h, - _actual_region_bm, - _actual_card_bm); - - _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); + G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); } }; @@ -1637,31 +1612,29 @@ void G1ConcurrentMark::cleanup() { HeapRegionRemSet::reset_for_cleanup_tasks(); - // Do counting once more with the world stopped for good measure. - G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); - - g1h->workers()->run_task(&g1_par_count_task); - - if (VerifyDuringGC) { - // Verify that the counting data accumulated during marking matches - // that calculated by walking the marking bitmap. - - // Bitmaps to hold expected values - BitMap expected_region_bm(_region_bm.size(), true); - BitMap expected_card_bm(_card_bm.size(), true); - - G1ParVerifyFinalCountTask g1_par_verify_task(g1h, - &_region_bm, - &_card_bm, - &expected_region_bm, - &expected_card_bm); - - g1h->workers()->run_task(&g1_par_verify_task); - - guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); + { + // Finalize the live data. + G1FinalizeLiveDataTask cl(_nextMarkBitMap, + &_region_live_bm, + &_card_live_bm, + g1h->workers()->active_workers()); + g1h->workers()->run_task(&cl); + } + + if (VerifyDuringGC) { + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + ResourceMark rm; + G1VerifyLiveDataTask cl(G1CollectedHeap::heap(), + _nextMarkBitMap, + &_region_live_bm, + &_card_live_bm, + g1h->workers()->active_workers()); + g1h->workers()->run_task(&cl); + + guarantee(cl.failures() == 0, "Unexpected accounting failures"); } - size_t start_used_bytes = g1h->used(); g1h->collector_state()->set_mark_in_progress(false); double count_end = os::elapsedTime(); @@ -1696,7 +1669,7 @@ void G1ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - g1h->scrub_rem_set(&_region_bm, &_card_bm); + g1h->scrub_rem_set(&_region_live_bm, &_card_live_bm); _total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start); } @@ -2142,6 +2115,35 @@ void G1ConcurrentMark::swapMarkBitMaps() { _nextMarkBitMap = (G1CMBitMap*) temp; } +BitMap G1ConcurrentMark::allocate_large_bitmap(BitMap::idx_t size_in_bits) { + size_t size_in_words = BitMap::size_in_words(size_in_bits); + + BitMap::bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); + + return BitMap(map, size_in_bits); +} + +void G1ConcurrentMark::allocate_internal_bitmaps() { + double start_time = os::elapsedTime(); + + _region_live_bm = allocate_large_bitmap(_g1h->max_regions()); + + guarantee(_g1h->max_capacity() % CardTableModRefBS::card_size == 0, + "Heap capacity must be aligned to card size."); + _card_live_bm = allocate_large_bitmap(_g1h->max_capacity() / CardTableModRefBS::card_size); + + log_debug(gc, marking)("Allocating internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); +} + +void G1ConcurrentMark::pretouch_internal_bitmaps() { + double start_time = os::elapsedTime(); + + _region_live_bm.pretouch(); + _card_live_bm.pretouch(); + + log_debug(gc, marking)("Pre-touching internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); +} + // Closure for marking entries in SATB buffers. class G1CMSATBBufferClosure : public SATBBufferClosure { private: @@ -2160,7 +2162,7 @@ private: oop obj = static_cast(entry); assert(obj->is_oop(true /* ignore mark word */), "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)); - _task->make_reference_grey(obj, hr); + _task->make_reference_grey(obj); } } @@ -2402,165 +2404,117 @@ void G1ConcurrentMark::verify_no_cset_oops() { } #endif // PRODUCT -// Aggregate the counting data that was constructed concurrently -// with marking. -class AggregateCountDataHRClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - BitMap* _cm_card_bm; - uint _max_worker_id; +class G1CreateLiveDataTask: public AbstractGangTask { + // Aggregate the counting data that was constructed concurrently + // with marking. + class G1CreateLiveDataHRClosure: public HeapRegionClosure { + G1LiveDataHelper _helper; - public: - AggregateCountDataHRClosure(G1CollectedHeap* g1h, - BitMap* cm_card_bm, - uint max_worker_id) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { } + G1CMBitMap* _mark_bitmap; - bool doHeapRegion(HeapRegion* hr) { - HeapWord* start = hr->bottom(); - HeapWord* limit = hr->next_top_at_mark_start(); - HeapWord* end = hr->end(); + G1ConcurrentMark* _cm; + public: + G1CreateLiveDataHRClosure(G1ConcurrentMark* cm, + G1CMBitMap* mark_bitmap, + BitMap* cm_card_bm) : + HeapRegionClosure(), + _helper(NULL, cm_card_bm), + _mark_bitmap(mark_bitmap), + _cm(cm) { } - assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", " - "top: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end())); + bool doHeapRegion(HeapRegion* hr) { + size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); + if (marked_bytes > 0) { + hr->add_to_marked_bytes(marked_bytes); + } - assert(hr->next_marked_bytes() == 0, "Precondition"); - - if (start == limit) { - // NTAMS of this region has not been set so nothing to do. + if (_cm->do_yield_check() && _cm->has_aborted()) { + return true; + } return false; } + }; - // 'start' should be in the heap. - assert(_g1h->is_in_g1_reserved(start) && _ct_bs->is_card_aligned(start), "sanity"); - // 'end' *may* be just beyond the end of the heap (if hr is the last region) - assert(!_g1h->is_in_g1_reserved(end) || _ct_bs->is_card_aligned(end), "sanity"); - - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t limit_idx = _cm->card_bitmap_index_for(limit); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(end); - - // If ntams is not card aligned then we bump card bitmap index - // for limit so that we get the all the cards spanned by - // the object ending at ntams. - // Note: if this is the last region in the heap then ntams - // could be actually just beyond the end of the the heap; - // limit_idx will then correspond to a (non-existent) card - // that is also outside the heap. - if (_g1h->is_in_g1_reserved(limit) && !_ct_bs->is_card_aligned(limit)) { - limit_idx += 1; - } - - assert(limit_idx <= end_idx, "or else use atomics"); - - // Aggregate the "stripe" in the count data associated with hr. - uint hrm_index = hr->hrm_index(); - size_t marked_bytes = 0; - - for (uint i = 0; i < _max_worker_id; i += 1) { - size_t* marked_bytes_array = _cm->count_marked_bytes_array_for(i); - BitMap* task_card_bm = _cm->count_card_bitmap_for(i); - - // Fetch the marked_bytes in this region for task i and - // add it to the running total for this region. - marked_bytes += marked_bytes_array[hrm_index]; - - // Now union the bitmaps[0,max_worker_id)[start_idx..limit_idx) - // into the global card bitmap. - BitMap::idx_t scan_idx = task_card_bm->get_next_one_offset(start_idx, limit_idx); - - while (scan_idx < limit_idx) { - assert(task_card_bm->at(scan_idx) == true, "should be"); - _cm_card_bm->set_bit(scan_idx); - assert(_cm_card_bm->at(scan_idx) == true, "should be"); - - // BitMap::get_next_one_offset() can handle the case when - // its left_offset parameter is greater than its right_offset - // parameter. It does, however, have an early exit if - // left_offset == right_offset. So let's limit the value - // passed in for left offset here. - BitMap::idx_t next_idx = MIN2(scan_idx + 1, limit_idx); - scan_idx = task_card_bm->get_next_one_offset(next_idx, limit_idx); - } - } - - // Update the marked bytes for this region. - hr->add_to_marked_bytes(marked_bytes); - - // Next heap region - return false; - } -}; - -class G1AggregateCountDataTask: public AbstractGangTask { -protected: G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; BitMap* _cm_card_bm; - uint _max_worker_id; - uint _active_workers; - HeapRegionClaimer _hrclaimer; + HeapRegionClaimer _hr_claimer; public: - G1AggregateCountDataTask(G1CollectedHeap* g1h, - G1ConcurrentMark* cm, - BitMap* cm_card_bm, - uint max_worker_id, - uint n_workers) : - AbstractGangTask("Count Aggregation"), - _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), - _max_worker_id(max_worker_id), - _active_workers(n_workers), - _hrclaimer(_active_workers) { + G1CreateLiveDataTask(G1CollectedHeap* g1h, + BitMap* cm_card_bm, + uint n_workers) : + AbstractGangTask("Create Live Data"), + _g1h(g1h), + _cm_card_bm(cm_card_bm), + _hr_claimer(n_workers) { } void work(uint worker_id) { - AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); + SuspendibleThreadSetJoiner sts_join; - _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); + G1CreateLiveDataHRClosure cl(_g1h->concurrent_mark(), _g1h->concurrent_mark()->nextMarkBitMap(), _cm_card_bm); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); } }; -void G1ConcurrentMark::aggregate_count_data() { - uint n_workers = _g1h->workers()->active_workers(); +void G1ConcurrentMark::create_live_data() { + uint n_workers = _parallel_workers->active_workers(); - G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, - _max_worker_id, n_workers); - - _g1h->workers()->run_task(&g1_par_agg_task); + G1CreateLiveDataTask cl(_g1h, + &_card_live_bm, + n_workers); + _parallel_workers->run_task(&cl); } -// Clear the per-worker arrays used to store the per-region counting data -void G1ConcurrentMark::clear_all_count_data() { - // Clear the global card bitmap - it will be filled during - // liveness count aggregation (during remark) and the - // final counting task. - _card_bm.clear(); - - // Clear the global region bitmap - it will be filled as part - // of the final counting task. - _region_bm.clear(); - - uint max_regions = _g1h->max_regions(); - assert(_max_worker_id > 0, "uninitialized"); - - for (uint i = 0; i < _max_worker_id; i += 1) { - BitMap* task_card_bm = count_card_bitmap_for(i); - size_t* marked_bytes_array = count_marked_bytes_array_for(i); - - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - assert(marked_bytes_array != NULL, "uninitialized"); - - memset(marked_bytes_array, 0, (size_t) max_regions * sizeof(size_t)); - task_card_bm->clear(); +class G1ClearAllLiveDataTask : public AbstractGangTask { + BitMap* _bitmap; + size_t _num_tasks; + size_t _cur_task; +public: + G1ClearAllLiveDataTask(BitMap* bitmap, size_t num_tasks) : + AbstractGangTask("Clear All Live Data"), + _bitmap(bitmap), + _num_tasks(num_tasks), + _cur_task(0) { } + + virtual void work(uint worker_id) { + while (true) { + size_t to_process = Atomic::add(1, &_cur_task) - 1; + if (to_process >= _num_tasks) { + break; + } + + BitMap::idx_t start = M * BitsPerByte * to_process; + BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap->size()); + _bitmap->clear_range(start, end); + } + } +}; + +void G1ConcurrentMark::clear_all_live_data(WorkGang* workers) { + double start_time = os::elapsedTime(); + + guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); + + size_t const num_chunks = align_size_up(_card_live_bm.size_in_words() * HeapWordSize, M) / M; + + G1ClearAllLiveDataTask cl(&_card_live_bm, num_chunks); + workers->run_task(&cl); + + // The region live bitmap is always very small, even for huge heaps. Clear + // directly. + _region_live_bm.clear(); + + + log_debug(gc, marking)("Clear Live Data took %.3fms", (os::elapsedTime() - start_time) * 1000.0); +} + +void G1ConcurrentMark::verify_all_live_data() { + assert(_card_live_bm.count_one_bits() == 0, "Master card bitmap not clear"); + assert(_region_live_bm.count_one_bits() == 0, "Master region bitmap not clear"); } void G1ConcurrentMark::print_stats() { @@ -2574,7 +2528,6 @@ void G1ConcurrentMark::print_stats() { } } -// abandon current marking iteration due to a Full GC void G1ConcurrentMark::abort() { if (!cmThread()->during_cycle() || _has_aborted) { // We haven't started a concurrent cycle or we have already aborted it. No need to do anything. @@ -2589,8 +2542,8 @@ void G1ConcurrentMark::abort() { // since VerifyDuringGC verifies the objects marked during // a full GC against the previous bitmap. - // Clear the liveness counting data - clear_all_count_data(); + clear_all_live_data(_g1h->workers()); + DEBUG_ONLY(verify_all_live_data()); // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { @@ -2634,7 +2587,7 @@ void G1ConcurrentMark::print_summary_info() { } print_ms_time_info(" ", "cleanups", _cleanup_times); - log.trace(" Final counting total time = %8.2f s (avg = %8.2f ms).", + log.trace(" Finalize live data total time = %8.2f s (avg = %8.2f ms).", _total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0)); if (G1ScrubRemSets) { log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).", @@ -3473,8 +3426,6 @@ void G1CMTask::do_marking_step(double time_target_ms, G1CMTask::G1CMTask(uint worker_id, G1ConcurrentMark* cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues) : _g1h(G1CollectedHeap::heap()), @@ -3483,9 +3434,7 @@ G1CMTask::G1CMTask(uint worker_id, _nextMarkBitMap(NULL), _hash_seed(17), _task_queue(task_queue), _task_queues(task_queues), - _cm_oop_closure(NULL), - _marked_bytes_array(marked_bytes), - _card_bm(card_bm) { + _cm_oop_closure(NULL) { guarantee(task_queue != NULL, "invariant"); guarantee(task_queues != NULL, "invariant"); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 1608c81f96f..fb621e34980 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -266,7 +266,7 @@ class ConcurrentMarkThread; class G1ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; friend class G1ParNoteEndTask; - friend class CalcLiveObjectsClosure; + friend class G1VerifyLiveDataClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; friend class G1CMKeepAliveAndDrainClosure; @@ -298,8 +298,14 @@ protected: G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap - BitMap _region_bm; - BitMap _card_bm; + // Liveness count data. After marking G1 iterates over the recently gathered mark + // bitmap and records rough information about liveness on card and region basis. + // This information can be used for e.g. remembered set scrubbing. + + // A set bit indicates whether the given region contains any live object. + BitMap _region_live_bm; + // A set bit indicates that the given card contains a live object. + BitMap _card_live_bm; // Heap bounds HeapWord* _heap_start; @@ -373,6 +379,14 @@ protected: void swapMarkBitMaps(); + // Allocates and returns a zero-ed out "large" bitmap of the given size in bits. + // It is always allocated using virtual memory. + BitMap allocate_large_bitmap(BitMap::idx_t size_in_bits); + // Allocates the memory for all bitmaps used by the concurrent marking. + void allocate_internal_bitmaps(); + // Pre-touches the internal bitmaps. + void pretouch_internal_bitmaps(); + // It resets the global marking data structures, as well as the // task local ones; should be called during initial mark. void reset(); @@ -461,23 +475,6 @@ protected: void enter_first_sync_barrier(uint worker_id); void enter_second_sync_barrier(uint worker_id); - // Live Data Counting data structures... - // These data structures are initialized at the start of - // marking. They are written to while marking is active. - // They are aggregated during remark; the aggregated values - // are then used to populate the _region_bm, _card_bm, and - // the total live bytes, which are then subsequently updated - // during cleanup. - - // An array of bitmaps (one bit map per task). Each bitmap - // is used to record the cards spanned by the live objects - // marked by that task/worker. - BitMap* _count_card_bitmaps; - - // Used to record the number of marked live bytes - // (for each region, by worker thread). - size_t** _count_marked_bytes; - // Card index of the bottom of the G1 heap. Used for biasing indices into // the card bitmaps. intptr_t _heap_bottom_card_num; @@ -563,18 +560,10 @@ public: // G1CollectedHeap // This notifies CM that a root during initial-mark needs to be - // grayed. It is MT-safe. word_size is the size of the object in - // words. It is passed explicitly as sometimes we cannot calculate - // it from the given object because it might be in an inconsistent - // state (e.g., in to-space and being copied). So the caller is - // responsible for dealing with this issue (e.g., get the size from - // the from-space image when the to-space image might be - // inconsistent) and always passing the size. hr is the region that + // grayed. It is MT-safe. hr is the region that // contains the object and it's passed optionally from callers who // might already have it (no point in recalculating it). inline void grayRoot(oop obj, - size_t word_size, - uint worker_id, HeapRegion* hr = NULL); // Prepare internal data structures for the next mark cycle. This includes clearing @@ -641,7 +630,7 @@ public: inline bool do_yield_check(uint worker_i = 0); - // Called to abort the marking cycle after a Full GC takes place. + // Abandon current marking iteration due to a Full GC. void abort(); bool has_aborted() { return _has_aborted; } @@ -652,75 +641,8 @@ public: void print_on_error(outputStream* st) const; - // Liveness counting - - // Utility routine to set an exclusive range of cards on the given - // card liveness bitmap - inline void set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par); - - // Returns the card number of the bottom of the G1 heap. - // Used in biasing indices into accounting card bitmaps. - intptr_t heap_bottom_card_num() const { - return _heap_bottom_card_num; - } - - // Returns the card bitmap for a given task or worker id. - BitMap* count_card_bitmap_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_card_bitmaps != NULL, "uninitialized"); - BitMap* task_card_bm = &_count_card_bitmaps[worker_id]; - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - return task_card_bm; - } - - // Returns the array containing the marked bytes for each region, - // for the given worker or task id. - size_t* count_marked_bytes_array_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_marked_bytes != NULL, "uninitialized"); - size_t* marked_bytes_array = _count_marked_bytes[worker_id]; - assert(marked_bytes_array != NULL, "uninitialized"); - return marked_bytes_array; - } - - // Returns the index in the liveness accounting card table bitmap - // for the given address - inline BitMap::idx_t card_bitmap_index_for(HeapWord* addr); - - // Counts the size of the given memory region in the the given - // marked_bytes array slot for the given HeapRegion. - // Sets the bits in the given card bitmap that are associated with the - // cards that are spanned by the memory region. - inline void count_region(MemRegion mr, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Counts the given object in the given task/worker counting - // data structures. - inline void count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size); - - // Attempts to mark the given object and, if successful, counts - // the object in the given task/worker counting structures. - inline bool par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Attempts to mark the given object and, if successful, counts - // the object in the task/worker counting structures for the - // given worker id. - inline bool par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id); + // Attempts to mark the given object on the next mark bitmap. + inline bool par_mark(oop obj); // Returns true if initialization was successfully completed. bool completed_initialization() const { @@ -730,19 +652,19 @@ public: ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } -protected: - // Clear all the per-task bitmaps and arrays used to store the - // counting data. - void clear_all_count_data(); +private: + // Clear (Reset) all liveness count data. + void clear_all_live_data(WorkGang* workers); - // Aggregates the counting data for each worker/task - // that was constructed while marking. Also sets - // the amount of marked bytes for each region and - // the top at concurrent mark count. - void aggregate_count_data(); + // Verify all of the above data structures that they are in initial state. + void verify_all_live_data(); + + // Aggregates the per-card liveness data based on the current marking. Also sets + // the amount of marked bytes for each region. + void create_live_data(); // Verification routine - void verify_count_data(); + void verify_live_data(); }; // A class representing a marking task. @@ -844,12 +766,6 @@ private: TruncatedSeq _marking_step_diffs_ms; - // Counting data structures. Embedding the task's marked_bytes_array - // and card bitmap into the actual task saves having to go through - // the ConcurrentMark object. - size_t* _marked_bytes_array; - BitMap* _card_bm; - // it updates the local fields after this task has claimed // a new region to scan void setup_for_region(HeapRegion* hr); @@ -936,9 +852,8 @@ public: // Grey the object by marking it. If not already marked, push it on // the local queue if below the finger. - // Precondition: obj is in region. // Precondition: obj is below region's NTAMS. - inline void make_reference_grey(oop obj, HeapRegion* region); + inline void make_reference_grey(oop obj); // Grey the object (by calling make_grey_reference) if required, // e.g. obj is below its containing region's NTAMS. @@ -976,8 +891,6 @@ public: G1CMTask(uint worker_id, G1ConcurrentMark *cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 4a934e0b15e..053de4b9673 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -29,138 +29,8 @@ #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/shared/taskqueue.inline.hpp" -// Utility routine to set an exclusive range of cards on the given -// card liveness bitmap -inline void G1ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par) { - - // Set the exclusive bit range [start_idx, end_idx). - assert((end_idx - start_idx) > 0, "at least one card"); - assert(end_idx <= card_bm->size(), "sanity"); - - // Silently clip the end index - end_idx = MIN2(end_idx, card_bm->size()); - - // For small ranges use a simple loop; otherwise use set_range or - // use par_at_put_range (if parallel). The range is made up of the - // cards that are spanned by an object/mem region so 8 cards will - // allow up to object sizes up to 4K to be handled using the loop. - if ((end_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { - if (is_par) { - card_bm->par_set_bit(i); - } else { - card_bm->set_bit(i); - } - } - } else { - // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive. - if (is_par) { - card_bm->par_at_put_range(start_idx, end_idx, true); - } else { - card_bm->set_range(start_idx, end_idx); - } - } -} - -// Returns the index in the liveness accounting card bitmap -// for the given address -inline BitMap::idx_t G1ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { - // Below, the term "card num" means the result of shifting an address - // by the card shift -- address 0 corresponds to card number 0. One - // must subtract the card num of the bottom of the heap to obtain a - // card table index. - intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift); - return card_num - heap_bottom_card_num(); -} - -// Counts the given memory region in the given task/worker -// counting data structures. -inline void G1ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - G1CollectedHeap* g1h = _g1h; - CardTableModRefBS* ct_bs = g1h->g1_barrier_set(); - - HeapWord* start = mr.start(); - HeapWord* end = mr.end(); - size_t region_size_bytes = mr.byte_size(); - uint index = hr->hrm_index(); - - assert(hr == g1h->heap_region_containing(start), "sanity"); - assert(marked_bytes_array != NULL, "pre-condition"); - assert(task_card_bm != NULL, "pre-condition"); - - // Add to the task local marked bytes for this region. - marked_bytes_array[index] += region_size_bytes; - - BitMap::idx_t start_idx = card_bitmap_index_for(start); - BitMap::idx_t end_idx = card_bitmap_index_for(end); - - // Note: if we're looking at the last region in heap - end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) { - // end of region is not card aligned - increment to cover - // all the cards spanned by the region. - end_idx += 1; - } - // The card bitmap is task/worker specific => no need to use - // the 'par' BitMap routines. - // Set bits in the exclusive bit range [start_idx, end_idx). - set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */); -} - -// Counts the given object in the given task/worker counting data structures. -inline void G1ConcurrentMark::count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size) { - assert(!hr->is_continues_humongous(), "Cannot enter count_object with continues humongous"); - if (!hr->is_starts_humongous()) { - MemRegion mr((HeapWord*)obj, word_size); - count_region(mr, hr, marked_bytes_array, task_card_bm); - } else { - do { - MemRegion mr(hr->bottom(), hr->top()); - count_region(mr, hr, marked_bytes_array, task_card_bm); - hr = _g1h->next_region_in_humongous(hr); - } while (hr != NULL); - } -} - -// Attempts to mark the given object and, if successful, counts -// the object in the given task/worker counting structures. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - // Update the task specific count data for the object. - count_object(obj, hr, marked_bytes_array, task_card_bm, obj->size()); - return true; - } - return false; -} - -// Attempts to mark the given object and, if successful, counts -// the object in the task/worker counting structures for the -// given worker id. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); - BitMap* task_card_bm = count_card_bitmap_for(worker_id); - count_object(obj, hr, marked_bytes_array, task_card_bm, word_size); - return true; - } - return false; +inline bool G1ConcurrentMark::par_mark(oop obj) { + return _nextMarkBitMap->parMark((HeapWord*)obj); } inline bool G1CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { @@ -294,10 +164,8 @@ inline void G1CMTask::process_grey_object(oop obj) { check_limits(); } - - -inline void G1CMTask::make_reference_grey(oop obj, HeapRegion* hr) { - if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { +inline void G1CMTask::make_reference_grey(oop obj) { + if (_cm->par_mark(obj)) { // No OrderAccess:store_load() is needed. It is implicit in the // CAS done in G1CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); @@ -348,7 +216,7 @@ inline void G1CMTask::deal_with_reference(oop obj) { // anything with it). HeapRegion* hr = _g1h->heap_region_containing(obj); if (!hr->obj_allocated_since_next_marking(obj)) { - make_reference_grey(obj, hr); + make_reference_grey(obj); } } } @@ -370,8 +238,7 @@ bool G1ConcurrentMark::isPrevMarked(oop p) const { return _prevMarkBitMap->isMarked(addr); } -inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, - uint worker_id, HeapRegion* hr) { +inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; if (hr == NULL) { @@ -386,7 +253,7 @@ inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, if (addr < hr->next_top_at_mark_start()) { if (!_nextMarkBitMap->isMarked(addr)) { - par_mark_and_count(obj, word_size, hr, worker_id); + par_mark(obj); } } } diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index 06721ee9295..82d655ed232 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -95,8 +95,6 @@ public: void do_object(oop obj) { HeapWord* obj_addr = (HeapWord*) obj; assert(_hr->is_in(obj_addr), "sanity"); - size_t obj_size = obj->size(); - HeapWord* obj_end = obj_addr + obj_size; if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. @@ -119,8 +117,10 @@ public: // explicitly and all objects in the CSet are considered // (implicitly) live. So, we won't mark them explicitly and // we'll leave them over NTAMS. - _cm->grayRoot(obj, obj_size, _worker_id, _hr); + _cm->grayRoot(obj, _hr); } + size_t obj_size = obj->size(); + _marked_bytes += (obj_size * HeapWordSize); obj->set_mark(markOopDesc::prototype()); @@ -138,6 +138,7 @@ public: // the collection set. So, we'll recreate such entries now. obj->oop_iterate(_update_rset_cl); + HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; _hr->cross_threshold(obj_addr, obj_end); } diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index 932bcbbfc4c..34db8d6c207 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -131,7 +131,7 @@ inline void G1RootRegionScanClosure::do_oop_nv(T* p) { if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj); - _cm->grayRoot(obj, obj->size(), _worker_id, hr); + _cm->grayRoot(obj, hr); } } @@ -246,7 +246,7 @@ void G1ParCopyHelper::mark_object(oop obj) { assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet"); // We know that the object is not moving so it's safe to read its size. - _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); + _cm->grayRoot(obj); } void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { @@ -261,7 +261,7 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { // worker so we cannot trust that its to-space image is // well-formed. So we have to read its size from its from-space // image which we know should not be changing. - _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); + _cm->grayRoot(to_obj); } template diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index ac78d2b0e8a..f015e4e9ee1 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -260,6 +260,9 @@ "The target number of mixed GCs after a marking cycle.") \ range(0, max_uintx) \ \ + experimental(bool, G1PretouchAuxiliaryMemory, false, \ + "Pre-touch large auxiliary data structures used by the GC.") \ + \ experimental(bool, G1EagerReclaimHumongousObjects, true, \ "Try to reclaim dead large objects at every young GC.") \ \ diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index fced8fbb522..7804c988487 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -68,6 +68,10 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { } } +void BitMap::pretouch() { + os::pretouch_memory((char*)word_addr(0), (char*)word_addr(size())); +} + void BitMap::set_range_within_word(idx_t beg, idx_t end) { // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index e57264b2e9a..0e46cea9917 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -135,12 +135,19 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // use the same value for "in_resource_area".) void resize(idx_t size_in_bits, bool in_resource_area = true); + // Pretouch the entire range of memory this BitMap covers. + void pretouch(); + // Accessing idx_t size() const { return _size; } idx_t size_in_words() const { return word_index(size() + BitsPerWord - 1); } + static idx_t size_in_words(size_t size_in_bits) { + return word_index(size_in_bits + BitsPerWord - 1); + } + bool at(idx_t index) const { verify_index(index); return (*word_addr(index) & bit_mask(index)) != 0; diff --git a/hotspot/test/gc/g1/Test2GbHeap.java b/hotspot/test/gc/g1/Test2GbHeap.java index 8aa2c4828ce..c0c6afa5f89 100644 --- a/hotspot/test/gc/g1/Test2GbHeap.java +++ b/hotspot/test/gc/g1/Test2GbHeap.java @@ -25,6 +25,9 @@ * @test Test2GbHeap * @bug 8031686 * @summary Regression test to ensure we can start G1 with 2gb heap. + * Skip test on 32 bit Windows: it typically does not support the many and large virtual memory reservations needed. + * @requires (vm.gc == "G1" | vm.gc == "null") + * @requires !((sun.arch.data.model == "32") & (os.family == "windows")) * @key gc * @key regression * @library /testlibrary @@ -48,17 +51,6 @@ public class Test2GbHeap { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testArguments.toArray(new String[0])); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // Avoid failing test for setups not supported. - if (output.getOutput().contains("Could not reserve enough space for 2097152KB object heap")) { - // Will fail on machines with too little memory (and Windows 32-bit VM), ignore such failures. - output.shouldHaveExitValue(1); - } else if (output.getOutput().contains("-XX:+UseG1GC not supported in this VM")) { - // G1 is not supported on embedded, ignore such failures. - output.shouldHaveExitValue(1); - } else { - // Normally everything should be fine. - output.shouldHaveExitValue(0); - } + output.shouldHaveExitValue(0); } } From 2904ea7d45992a6973374e4852e308bf5b38212b Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Wed, 6 Apr 2016 07:37:15 -0400 Subject: [PATCH 093/167] 8152846: Creation of ModuleEntryTable Investigate Need For OrderAccess::storestore() Remove the unneeded OrderAccess::storestore() call Reviewed-by: acorn, coleenp --- hotspot/src/share/vm/classfile/classLoaderData.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 0fb7a86af4f..0c0eb37196f 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -373,13 +373,10 @@ PackageEntryTable* ClassLoaderData::packages() { // Lazily create the package entry table at first request. if (_packages == NULL) { MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Check again if _packages has been allocated while we were getting this lock. - if (_packages != NULL) { - return _packages; + // Check if _packages got allocated while we were waiting for this lock. + if (_packages == NULL) { + _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } - // Ensure _packages is stable, since it is examined without a lock - OrderAccess::storestore(); - _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } return _packages; } From a009aa9ca73241bc8740e3056bce2918f17f12b3 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 6 Apr 2016 13:41:59 +0200 Subject: [PATCH 094/167] 8151386: Extract card live data out of G1ConcurrentMark Move card live data management out of G1ConcurrentMark into extra class G1CardLiveData managed by G1RemSet Reviewed-by: mgerdin, kbarrett --- .../share/vm/gc/g1/concurrentMarkThread.cpp | 1 + hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp | 552 +++++++++++++++++ hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp | 99 +++ .../share/vm/gc/g1/g1CardLiveData.inline.hpp | 52 ++ .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 15 +- .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 3 +- .../share/vm/gc/g1/g1CollectedHeap.inline.hpp | 2 +- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 579 ++---------------- .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 32 +- .../vm/gc/g1/g1ConcurrentMark.inline.hpp | 10 + hotspot/src/share/vm/gc/g1/g1OopClosures.hpp | 6 +- hotspot/src/share/vm/gc/g1/g1RemSet.cpp | 50 +- hotspot/src/share/vm/gc/g1/g1RemSet.hpp | 21 +- .../src/share/vm/gc/g1/heapRegionRemSet.cpp | 22 +- .../src/share/vm/gc/g1/heapRegionRemSet.hpp | 8 +- hotspot/src/share/vm/utilities/bitMap.cpp | 2 +- hotspot/src/share/vm/utilities/bitMap.hpp | 7 +- 17 files changed, 848 insertions(+), 613 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp create mode 100644 hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index 7eef582e3db..9727b023268 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1MMUTracker.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "gc/g1/vm_operations_g1.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp new file mode 100644 index 00000000000..009179150a9 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" +#include "gc/shared/workgroup.hpp" +#include "memory/universe.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/debug.hpp" + +G1CardLiveData::G1CardLiveData() : + _max_capacity(0), + _cards_per_region(0), + _live_regions(NULL), + _live_regions_size_in_bits(0), + _live_cards(NULL), + _live_cards_size_in_bits(0) { +} + +G1CardLiveData::~G1CardLiveData() { + free_large_bitmap(_live_cards, _live_cards_size_in_bits); + free_large_bitmap(_live_regions, _live_regions_size_in_bits); +} + +G1CardLiveData::bm_word_t* G1CardLiveData::allocate_large_bitmap(size_t size_in_bits) { + size_t size_in_words = BitMap::calc_size_in_words(size_in_bits); + + bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); + + return map; +} + +void G1CardLiveData::free_large_bitmap(bm_word_t* bitmap, size_t size_in_bits) { + MmapArrayAllocator::free(bitmap, size_in_bits / BitsPerWord); +} + +void G1CardLiveData::initialize(size_t max_capacity, uint num_max_regions) { + assert(max_capacity % num_max_regions == 0, + "Given capacity must be evenly divisible by region size."); + size_t region_size = max_capacity / num_max_regions; + assert(region_size % (G1SATBCardTableModRefBS::card_size * BitsPerWord) == 0, + "Region size must be evenly divisible by area covered by a single word."); + _max_capacity = max_capacity; + _cards_per_region = region_size / G1SATBCardTableModRefBS::card_size; + + _live_regions_size_in_bits = live_region_bitmap_size_in_bits(); + _live_regions = allocate_large_bitmap(_live_regions_size_in_bits); + _live_cards_size_in_bits = live_card_bitmap_size_in_bits(); + _live_cards = allocate_large_bitmap(_live_cards_size_in_bits); +} + +void G1CardLiveData::pretouch() { + live_cards_bm().pretouch(); + live_regions_bm().pretouch(); +} + +size_t G1CardLiveData::live_region_bitmap_size_in_bits() const { + return _max_capacity / (_cards_per_region << G1SATBCardTableModRefBS::card_shift); +} + +size_t G1CardLiveData::live_card_bitmap_size_in_bits() const { + return _max_capacity >> G1SATBCardTableModRefBS::card_shift; +} + +// Helper class that provides functionality to generate the Live Data Count +// information. +class G1CardLiveDataHelper VALUE_OBJ_CLASS_SPEC { +private: + BitMap _region_bm; + BitMap _card_bm; + + // The card number of the bottom of the G1 heap. + // Used in biasing indices into accounting card bitmaps. + BitMap::idx_t _heap_card_bias; + + // Utility routine to set an exclusive range of bits on the given + // bitmap, optimized for very small ranges. + // There must be at least one bit to set. + void set_card_bitmap_range(BitMap::idx_t start_idx, + BitMap::idx_t end_idx) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one bit"); + + // For small ranges use a simple loop; otherwise use set_range. + // The range is made up of the cards that are spanned by an object/mem + // region so 8 cards will allow up to object sizes up to 4K to be handled + // using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + _card_bm.set_bit(i); + } + } else { + _card_bm.set_range(start_idx, end_idx); + } + } + + // We cache the last mark set. This avoids setting the same bit multiple times. + // This is particularly interesting for dense bitmaps, as this avoids doing + // lots of work most of the time. + BitMap::idx_t _last_marked_bit_idx; + + // Mark the card liveness bitmap for the object spanning from start to end. + void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { + BitMap::idx_t start_idx = card_live_bitmap_index_for(start); + BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); + + assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); + + if (start_idx == _last_marked_bit_idx) { + start_idx++; + } + if (start_idx == end_idx) { + return; + } + + // Set the bits in the card bitmap for the cards spanned by this object. + set_card_bitmap_range(start_idx, end_idx); + _last_marked_bit_idx = end_idx - 1; + } + + void reset_mark_cache() { + _last_marked_bit_idx = (BitMap::idx_t)-1; + } + +public: + // Returns the index in the per-card liveness count bitmap + // for the given address + inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + BitMap::idx_t card_num = uintptr_t(addr) >> CardTableModRefBS::card_shift; + return card_num - _heap_card_bias; + } + + // Takes a region that's not empty (i.e., it has at least one + // live object in it and sets its corresponding bit on the region + // bitmap to 1. + void set_bit_for_region(HeapRegion* hr) { + _region_bm.par_set_bit(hr->hrm_index()); + } + + // Mark the range of bits covered by allocations done since the last marking + // in the given heap region, i.e. from NTAMS to top of the given region. + // Returns if there has been some allocation in this region since the last marking. + bool mark_allocated_since_marking(HeapRegion* hr) { + reset_mark_cache(); + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); + + assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + // Mark the allocated-since-marking portion... + if (ntams < top) { + mark_card_bitmap_range(ntams, top); + return true; + } else { + return false; + } + } + + // Mark the range of bits covered by live objects on the mark bitmap between + // bottom and NTAMS of the given region. + // Returns the number of live bytes marked within that area for the given + // heap region. + size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { + reset_mark_cache(); + + size_t marked_bytes = 0; + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* start = hr->bottom(); + + if (ntams <= start) { + // Skip empty regions. + return 0; + } + if (hr->is_humongous()) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } + + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), + "Preconditions not met - " + "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, + p2i(start), p2i(ntams), p2i(hr->end())); + + // Find the first marked object at or after "start". + start = mark_bitmap->getNextMarkedWordAddress(start, ntams); + while (start < ntams) { + oop obj = oop(start); + size_t obj_size = obj->size(); + HeapWord* obj_end = start + obj_size; + + assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); + + mark_card_bitmap_range(start, obj_end); + + // Add the size of this object to the number of marked bytes. + marked_bytes += obj_size * HeapWordSize; + + // Find the next marked object after this one. + start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); + } + + return marked_bytes; + } + + G1CardLiveDataHelper(G1CardLiveData* live_data, HeapWord* base_address) : + _region_bm(live_data->live_regions_bm()), + _card_bm(live_data->live_cards_bm()) { + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_card_bias = + uintptr_t(base_address) >> CardTableModRefBS::card_shift; + } +}; + +class G1CreateCardLiveDataTask: public AbstractGangTask { + // Aggregate the counting data that was constructed concurrently + // with marking. + class G1CreateLiveDataClosure : public HeapRegionClosure { + G1CardLiveDataHelper _helper; + + G1CMBitMap* _mark_bitmap; + + G1ConcurrentMark* _cm; + public: + G1CreateLiveDataClosure(G1CollectedHeap* g1h, + G1ConcurrentMark* cm, + G1CMBitMap* mark_bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()), + _mark_bitmap(mark_bitmap), + _cm(cm) { } + + bool doHeapRegion(HeapRegion* hr) { + size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); + if (marked_bytes > 0) { + hr->add_to_marked_bytes(marked_bytes); + } + + return (_cm->do_yield_check() && _cm->has_aborted()); + } + }; + + G1ConcurrentMark* _cm; + G1CardLiveData* _live_data; + HeapRegionClaimer _hr_claimer; + +public: + G1CreateCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* live_data, + uint n_workers) : + AbstractGangTask("G1 Create Live Data"), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + SuspendibleThreadSetJoiner sts_join; + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1ConcurrentMark* cm = g1h->concurrent_mark(); + G1CreateLiveDataClosure cl(g1h, cm, cm->nextMarkBitMap(), _live_data); + g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::create(WorkGang* workers, G1CMBitMap* mark_bitmap) { + uint n_workers = workers->active_workers(); + + G1CreateCardLiveDataTask cl(mark_bitmap, + this, + n_workers); + workers->run_task(&cl); +} + +class G1FinalizeCardLiveDataTask: public AbstractGangTask { + // Finalizes the liveness counting data. + // Sets the bits corresponding to the interval [NTAMS, top] + // (which contains the implicitly live objects) in the + // card liveness bitmap. Also sets the bit for each region + // containing live data, in the region liveness bitmap. + class G1FinalizeCardLiveDataClosure: public HeapRegionClosure { + private: + G1CardLiveDataHelper _helper; + public: + G1FinalizeCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()) { } + + bool doHeapRegion(HeapRegion* hr) { + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || hr->next_marked_bytes() > 0) { + _helper.set_bit_for_region(hr); + } + return false; + } + }; + + G1CMBitMap* _bitmap; + + G1CardLiveData* _live_data; + + HeapRegionClaimer _hr_claimer; + +public: + G1FinalizeCardLiveDataTask(G1CMBitMap* bitmap, G1CardLiveData* live_data, uint n_workers) : + AbstractGangTask("G1 Finalize Card Live Data"), + _bitmap(bitmap), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + G1FinalizeCardLiveDataClosure cl(G1CollectedHeap::heap(), _bitmap, _live_data); + + G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::finalize(WorkGang* workers, G1CMBitMap* mark_bitmap) { + // Finalize the live data. + G1FinalizeCardLiveDataTask cl(mark_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); +} + +class G1ClearCardLiveDataTask : public AbstractGangTask { + BitMap _bitmap; + size_t _num_chunks; + size_t _cur_chunk; +public: + G1ClearCardLiveDataTask(BitMap bitmap, size_t num_tasks) : + AbstractGangTask("G1 Clear Card Live Data"), + _bitmap(bitmap), + _num_chunks(num_tasks), + _cur_chunk(0) { + } + + static size_t chunk_size() { return M; } + + virtual void work(uint worker_id) { + while (true) { + size_t to_process = Atomic::add(1, &_cur_chunk) - 1; + if (to_process >= _num_chunks) { + break; + } + + BitMap::idx_t start = M * BitsPerByte * to_process; + BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap.size()); + _bitmap.clear_range(start, end); + } + } +}; + +void G1CardLiveData::clear(WorkGang* workers) { + guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); + + size_t const num_chunks = align_size_up(live_cards_bm().size_in_bytes(), G1ClearCardLiveDataTask::chunk_size()) / G1ClearCardLiveDataTask::chunk_size(); + + G1ClearCardLiveDataTask cl(live_cards_bm(), num_chunks); + workers->run_task(&cl); + + // The region live bitmap is always very small, even for huge heaps. Clear + // directly. + live_regions_bm().clear(); +} + +class G1VerifyCardLiveDataTask: public AbstractGangTask { + // Heap region closure used for verifying the live count data + // that was created concurrently and finalized during + // the remark pause. This closure is applied to the heap + // regions during the STW cleanup pause. + class G1VerifyCardLiveDataClosure: public HeapRegionClosure { + private: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + G1CardLiveDataHelper _helper; + + G1CardLiveData* _act_live_data; + + G1CardLiveData* _exp_live_data; + + int _failures; + + // Completely recreates the live data count for the given heap region and + // returns the number of bytes marked. + size_t create_live_data_count(HeapRegion* hr) { + size_t bytes_marked = _helper.mark_marked_during_marking(_mark_bitmap, hr); + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || bytes_marked > 0) { + _helper.set_bit_for_region(hr); + } + return bytes_marked; + } + public: + G1VerifyCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* mark_bitmap, + G1CardLiveData* act_live_data, + G1CardLiveData* exp_live_data) : + _g1h(g1h), + _mark_bitmap(mark_bitmap), + _helper(exp_live_data, g1h->reserved_region().start()), + _act_live_data(act_live_data), + _exp_live_data(exp_live_data), + _failures(0) { } + + int failures() const { return _failures; } + + bool doHeapRegion(HeapRegion* hr) { + int failures = 0; + + // Walk the marking bitmap for this region and set the corresponding bits + // in the expected region and card bitmaps. + size_t exp_marked_bytes = create_live_data_count(hr); + size_t act_marked_bytes = hr->next_marked_bytes(); + // Verify the marked bytes for this region. + + if (exp_marked_bytes != act_marked_bytes) { + failures += 1; + } else if (exp_marked_bytes > HeapRegion::GrainBytes) { + failures += 1; + } + + // Verify the bit, for this region, in the actual and expected + // (which was just calculated) region bit maps. + // We're not OK if the bit in the calculated expected region + // bitmap is set and the bit in the actual region bitmap is not. + uint index = hr->hrm_index(); + + bool expected = _exp_live_data->is_region_live(index); + bool actual = _act_live_data->is_region_live(index); + if (expected && !actual) { + failures += 1; + } + + // Verify that the card bit maps for the cards spanned by the current + // region match. We have an error if we have a set bit in the expected + // bit map and the corresponding bit in the actual bitmap is not set. + + BitMap::idx_t start_idx = _helper.card_live_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _helper.card_live_bitmap_index_for(hr->top()); + + for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { + expected = _exp_live_data->is_card_live_at(i); + actual = _act_live_data->is_card_live_at(i); + + if (expected && !actual) { + failures += 1; + } + } + + _failures += failures; + + // We could stop iteration over the heap when we + // find the first violating region by returning true. + return false; + } + }; +protected: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + + G1CardLiveData* _act_live_data; + + G1CardLiveData _exp_live_data; + + int _failures; + + HeapRegionClaimer _hr_claimer; + +public: + G1VerifyCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* act_live_data, + uint n_workers) + : AbstractGangTask("G1 Verify Card Live Data"), + _g1h(G1CollectedHeap::heap()), + _mark_bitmap(bitmap), + _act_live_data(act_live_data), + _exp_live_data(), + _failures(0), + _hr_claimer(n_workers) { + assert(VerifyDuringGC, "don't call this otherwise"); + _exp_live_data.initialize(_g1h->max_capacity(), _g1h->max_regions()); + } + + void work(uint worker_id) { + G1VerifyCardLiveDataClosure cl(_g1h, + _mark_bitmap, + _act_live_data, + &_exp_live_data); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + + Atomic::add(cl.failures(), &_failures); + } + + int failures() const { return _failures; } +}; + +void G1CardLiveData::verify(WorkGang* workers, G1CMBitMap* actual_bitmap) { + ResourceMark rm; + + G1VerifyCardLiveDataTask cl(actual_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); + + guarantee(cl.failures() == 0, "Unexpected accounting failures"); +} + +#ifndef PRODUCT +void G1CardLiveData::verify_is_clear() { + assert(live_cards_bm().count_one_bits() == 0, "Live cards bitmap must be clear."); + assert(live_regions_bm().count_one_bits() == 0, "Live regions bitmap must be clear."); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp new file mode 100644 index 00000000000..d76fa66d3c4 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP + +#include "gc/g1/g1CollectedHeap.hpp" +#include "utilities/bitMap.hpp" +#include "utilities/globalDefinitions.hpp" + +class G1CollectedHeap; +class G1CMBitMap; +class WorkGang; + +// Information about object liveness on the Java heap on a "card" basis. +// Can be used for various purposes, like as remembered set for completely +// coarsened remembered sets, scrubbing remembered sets or estimating liveness. +// This information is created as part of the concurrent marking cycle. +class G1CardLiveData VALUE_OBJ_CLASS_SPEC { + friend class G1CardLiveDataHelper; + friend class G1VerifyCardLiveDataTask; +private: + typedef BitMap::bm_word_t bm_word_t; + // Store some additional information about the covered area to be able to test. + size_t _max_capacity; + size_t _cards_per_region; + + // The per-card liveness bitmap. + bm_word_t* _live_cards; + size_t _live_cards_size_in_bits; + // The per-region liveness bitmap. + bm_word_t* _live_regions; + size_t _live_regions_size_in_bits; + // The bits in this bitmap contain for every card whether it contains + // at least part of at least one live object. + BitMap live_cards_bm() const { return BitMap(_live_cards, _live_cards_size_in_bits); } + // The bits in this bitmap indicate that a given region contains some live objects. + BitMap live_regions_bm() const { return BitMap(_live_regions, _live_regions_size_in_bits); } + + // Allocate a "large" bitmap from virtual memory with the given size in bits. + bm_word_t* allocate_large_bitmap(size_t size_in_bits); + void free_large_bitmap(bm_word_t* map, size_t size_in_bits); + + inline BitMap live_card_bitmap(uint region); + + inline bool is_card_live_at(BitMap::idx_t idx) const; + + size_t live_region_bitmap_size_in_bits() const; + size_t live_card_bitmap_size_in_bits() const; +public: + inline bool is_region_live(uint region) const; + + inline void remove_nonlive_cards(uint region, BitMap* bm); + inline void remove_nonlive_regions(BitMap* bm); + + G1CardLiveData(); + ~G1CardLiveData(); + + void initialize(size_t max_capacity, uint num_max_regions); + void pretouch(); + + // Create the initial liveness data based on the marking result from the bottom + // to the ntams of every region in the heap and the marks in the given bitmap. + void create(WorkGang* workers, G1CMBitMap* mark_bitmap); + // Finalize the liveness data. + void finalize(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify(WorkGang* workers, G1CMBitMap* actual_bitmap); + // Clear all data structures, prepare for next processing. + void clear(WorkGang* workers); + + void verify_is_clear() PRODUCT_RETURN; +}; + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP */ + diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp new file mode 100644 index 00000000000..fc14ed8bcf3 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP + +#include "gc/g1/g1CardLiveData.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +inline BitMap G1CardLiveData::live_card_bitmap(uint region) { + return BitMap(_live_cards + ((size_t)region * _cards_per_region >> LogBitsPerWord), _cards_per_region); +} + +inline bool G1CardLiveData::is_card_live_at(BitMap::idx_t idx) const { + return live_cards_bm().at(idx); +} + +inline bool G1CardLiveData::is_region_live(uint region) const { + return live_regions_bm().at(region); +} + +inline void G1CardLiveData::remove_nonlive_cards(uint region, BitMap* bm) { + bm->set_intersection(live_card_bitmap(region)); +} + +inline void G1CardLiveData::remove_nonlive_regions(BitMap* bm) { + bm->set_intersection(live_regions_bm()); +} + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP */ diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 03d4e76f3a8..2861baf232d 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1425,6 +1425,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { + GCTraceTime(Debug, gc)("Clear Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); @@ -1944,7 +1945,7 @@ jint G1CollectedHeap::initialize() { const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); - G1RemSet::initialize(max_regions()); + g1_rem_set()->initialize(max_capacity(), max_regions()); size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); @@ -4787,27 +4788,23 @@ public: class G1ParScrubRemSetTask: public AbstractGangTask { protected: G1RemSet* _g1rs; - BitMap* _region_bm; - BitMap* _card_bm; HeapRegionClaimer _hrclaimer; public: - G1ParScrubRemSetTask(G1RemSet* g1_rs, BitMap* region_bm, BitMap* card_bm, uint num_workers) : + G1ParScrubRemSetTask(G1RemSet* g1_rs, uint num_workers) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1_rs), - _region_bm(region_bm), - _card_bm(card_bm), _hrclaimer(num_workers) { } void work(uint worker_id) { - _g1rs->scrub(_region_bm, _card_bm, worker_id, &_hrclaimer); + _g1rs->scrub(worker_id, &_hrclaimer); } }; -void G1CollectedHeap::scrub_rem_set(BitMap* region_bm, BitMap* card_bm) { +void G1CollectedHeap::scrub_rem_set() { uint num_workers = workers()->active_workers(); - G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), region_bm, card_bm, num_workers); + G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), num_workers); workers()->run_task(&g1_par_scrub_rs_task); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 4bde7c70d04..e98d57af7fb 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -992,7 +992,8 @@ public: // The rem set and barrier set. G1RemSet* g1_rem_set() const { return _g1_rem_set; } - void scrub_rem_set(BitMap* region_bm, BitMap* card_bm); + // Try to minimize the remembered set. + void scrub_rem_set(); unsigned get_gc_time_stamp() { return _gc_time_stamp; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index eaf329b3acd..040367b5be1 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -28,7 +28,7 @@ #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" -#include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index a181b467c7d..526387c018e 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -33,6 +33,7 @@ #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" @@ -48,7 +49,6 @@ #include "gc/shared/taskqueue.inline.hpp" #include "gc/shared/vmGCOperations.hpp" #include "logging/log.hpp" -#include "logging/logTag.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -356,8 +356,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _sleep_factor(0.0), _marking_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_live_bm(), - _card_live_bm(), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -499,12 +497,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* return; } - allocate_internal_bitmaps(); - - if (G1PretouchAuxiliaryMemory) { - pretouch_internal_bitmaps(); - } - _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); @@ -701,8 +693,8 @@ void G1ConcurrentMark::cleanup_for_next_mark() { // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_all_live_data(_parallel_workers); - DEBUG_ONLY(verify_all_live_data()); + clear_live_data(_parallel_workers); + DEBUG_ONLY(verify_live_data_clear()); } // Repeat the asserts from above. @@ -884,7 +876,7 @@ public: double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; _cm->clear_has_overflown(); - _cm->do_yield_check(worker_id); + _cm->do_yield_check(); jlong sleep_time_ms; if (!_cm->has_aborted() && the_task->has_aborted()) { @@ -934,10 +926,10 @@ uint G1ConcurrentMark::calc_parallel_marking_threads() { return n_conc_workers; } -void G1ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { +void G1ConcurrentMark::scanRootRegion(HeapRegion* hr) { // Currently, only survivors can be root regions. assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); - G1RootRegionScanClosure cl(_g1h, this, worker_id); + G1RootRegionScanClosure cl(_g1h, this); const uintx interval = PrefetchScanIntervalInBytes; HeapWord* curr = hr->bottom(); @@ -966,7 +958,7 @@ public: G1CMRootRegions* root_regions = _cm->root_regions(); HeapRegion* hr = root_regions->claim_next(); while (hr != NULL) { - _cm->scanRootRegion(hr, worker_id); + _cm->scanRootRegion(hr); hr = root_regions->claim_next(); } } @@ -1125,363 +1117,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { _gc_tracer_cm->report_object_count_after_gc(&is_alive); } -// Helper class that provides functionality to generate the Live Data Count -// information. -class G1LiveDataHelper VALUE_OBJ_CLASS_SPEC { -private: - BitMap* _region_bm; - BitMap* _card_bm; - - // The card number of the bottom of the G1 heap. Used for converting addresses - // to bitmap indices quickly. - BitMap::idx_t _heap_card_bias; - - // Utility routine to set an exclusive range of bits on the given - // bitmap, optimized for very small ranges. - // There must be at least one bit to set. - inline void set_card_bitmap_range(BitMap* bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx) { - - // Set the exclusive bit range [start_idx, end_idx). - assert((end_idx - start_idx) > 0, "at least one bit"); - assert(end_idx <= bm->size(), "sanity"); - - // For small ranges use a simple loop; otherwise use set_range or - // use par_at_put_range (if parallel). The range is made up of the - // cards that are spanned by an object/mem region so 8 cards will - // allow up to object sizes up to 4K to be handled using the loop. - if ((end_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { - bm->set_bit(i); - } - } else { - bm->set_range(start_idx, end_idx); - } - } - - // We cache the last mark set. This avoids setting the same bit multiple times. - // This is particularly interesting for dense bitmaps, as this avoids doing - // lots of work most of the time. - BitMap::idx_t _last_marked_bit_idx; - - // Mark the card liveness bitmap for the object spanning from start to end. - void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { - BitMap::idx_t start_idx = card_live_bitmap_index_for(start); - BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); - - assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); - - if (start_idx == _last_marked_bit_idx) { - start_idx++; - } - if (start_idx == end_idx) { - return; - } - - // Set the bits in the card bitmap for the cards spanned by this object. - set_card_bitmap_range(_card_bm, start_idx, end_idx); - _last_marked_bit_idx = end_idx - 1; - } - - void reset_mark_cache() { - _last_marked_bit_idx = (BitMap::idx_t)-1; - } - -public: - // Returns the index in the per-card liveness count bitmap - // for the given address - inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { - // Below, the term "card num" means the result of shifting an address - // by the card shift -- address 0 corresponds to card number 0. One - // must subtract the card num of the bottom of the heap to obtain a - // card table index. - BitMap::idx_t card_num = (BitMap::idx_t)(uintptr_t(addr) >> CardTableModRefBS::card_shift); - return card_num - _heap_card_bias; - } - - // Takes a region that's not empty (i.e., it has at least one - // live object in it and sets its corresponding bit on the region - // bitmap to 1. - void set_bit_for_region(HeapRegion* hr) { - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - _region_bm->par_at_put(index, true); - } - - // Mark the range of bits covered by allocations done since the last marking - // in the given heap region, i.e. from NTAMS to top of the given region. - // Returns if there has been some allocation in this region since the last marking. - bool mark_allocated_since_marking(HeapRegion* hr) { - reset_mark_cache(); - - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* top = hr->top(); - - assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); - - // Mark the allocated-since-marking portion... - if (ntams < top) { - mark_card_bitmap_range(ntams, top); - return true; - } else { - return false; - } - } - - // Mark the range of bits covered by live objects on the mark bitmap between - // bottom and NTAMS of the given region. - // Returns the number of live bytes marked within that area for the given - // heap region. - size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { - reset_mark_cache(); - - size_t marked_bytes = 0; - - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* start = hr->bottom(); - - if (ntams <= start) { - // Skip empty regions. - return 0; - } else if (hr->is_humongous()) { - mark_card_bitmap_range(start, hr->top()); - return pointer_delta(hr->top(), start, 1); - } - - assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(ntams), p2i(hr->end())); - - // Find the first marked object at or after "start". - start = mark_bitmap->getNextMarkedWordAddress(start, ntams); - while (start < ntams) { - oop obj = oop(start); - int obj_sz = obj->size(); - HeapWord* obj_end = start + obj_sz; - - assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); - - mark_card_bitmap_range(start, obj_end); - - // Add the size of this object to the number of marked bytes. - marked_bytes += (size_t)obj_sz * HeapWordSize; - - // Find the next marked object after this one. - start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); - } - - return marked_bytes; - } - - G1LiveDataHelper(BitMap* region_bm, - BitMap* card_bm): - _region_bm(region_bm), - _card_bm(card_bm) { - //assert(region_bm != NULL, ""); - assert(card_bm != NULL, ""); - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_card_bias = - (BitMap::idx_t)(uintptr_t(G1CollectedHeap::heap()->reserved_region().start()) >> CardTableModRefBS::card_shift); - } -}; - -// Heap region closure used for verifying the live count data -// that was created concurrently and finalized during -// the remark pause. This closure is applied to the heap -// regions during the STW cleanup pause. -class G1VerifyLiveDataHRClosure: public HeapRegionClosure { -private: - G1CollectedHeap* _g1h; - G1CMBitMap* _mark_bitmap; - G1LiveDataHelper _calc_helper; - - BitMap* _act_region_bm; // Region BM to be verified - BitMap* _act_card_bm; // Card BM to be verified - - BitMap* _exp_region_bm; // Expected Region BM values - BitMap* _exp_card_bm; // Expected card BM values - - int _failures; - - // Updates the live data count for the given heap region and returns the number - // of bytes marked. - size_t create_live_data_count(HeapRegion* hr) { - size_t bytes_marked = _calc_helper.mark_marked_during_marking(_mark_bitmap, hr); - bool allocated_since_marking = _calc_helper.mark_allocated_since_marking(hr); - if (allocated_since_marking || bytes_marked > 0) { - _calc_helper.set_bit_for_region(hr); - } - return bytes_marked; - } - -public: - G1VerifyLiveDataHRClosure(G1CollectedHeap* g1h, - G1CMBitMap* mark_bitmap, - BitMap* act_region_bm, - BitMap* act_card_bm, - BitMap* exp_region_bm, - BitMap* exp_card_bm) : - _g1h(g1h), - _mark_bitmap(mark_bitmap), - _calc_helper(exp_region_bm, exp_card_bm), - _act_region_bm(act_region_bm), - _act_card_bm(act_card_bm), - _exp_region_bm(exp_region_bm), - _exp_card_bm(exp_card_bm), - _failures(0) { } - - int failures() const { return _failures; } - - bool doHeapRegion(HeapRegion* hr) { - int failures = 0; - - // Walk the marking bitmap for this region and set the corresponding bits - // in the expected region and card bitmaps. - size_t exp_marked_bytes = create_live_data_count(hr); - size_t act_marked_bytes = hr->next_marked_bytes(); - // Verify the marked bytes for this region. - - if (exp_marked_bytes != act_marked_bytes) { - failures += 1; - } else if (exp_marked_bytes > HeapRegion::GrainBytes) { - failures += 1; - } - - // Verify the bit, for this region, in the actual and expected - // (which was just calculated) region bit maps. - // We're not OK if the bit in the calculated expected region - // bitmap is set and the bit in the actual region bitmap is not. - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - - bool expected = _exp_region_bm->at(index); - bool actual = _act_region_bm->at(index); - if (expected && !actual) { - failures += 1; - } - - // Verify that the card bit maps for the cards spanned by the current - // region match. We have an error if we have a set bit in the expected - // bit map and the corresponding bit in the actual bitmap is not set. - - BitMap::idx_t start_idx = _calc_helper.card_live_bitmap_index_for(hr->bottom()); - BitMap::idx_t end_idx = _calc_helper.card_live_bitmap_index_for(hr->top()); - - for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { - expected = _exp_card_bm->at(i); - actual = _act_card_bm->at(i); - - if (expected && !actual) { - failures += 1; - } - } - - _failures += failures; - - // We could stop iteration over the heap when we - // find the first violating region by returning true. - return false; - } -}; - -class G1VerifyLiveDataTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1CMBitMap* _mark_bitmap; - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - BitMap _expected_region_bm; - BitMap _expected_card_bm; - - int _failures; - - HeapRegionClaimer _hr_claimer; - -public: - G1VerifyLiveDataTask(G1CollectedHeap* g1h, - G1CMBitMap* bitmap, - BitMap* region_bm, - BitMap* card_bm, - uint n_workers) - : AbstractGangTask("G1 verify final counting"), - _g1h(g1h), - _mark_bitmap(bitmap), - _actual_region_bm(region_bm), - _actual_card_bm(card_bm), - _expected_region_bm(region_bm->size(), true /* in_resource_area */), - _expected_card_bm(card_bm->size(), true /* in_resource_area */), - _failures(0), - _hr_claimer(n_workers) { - assert(VerifyDuringGC, "don't call this otherwise"); - } - - void work(uint worker_id) { - G1VerifyLiveDataHRClosure cl(_g1h, - _mark_bitmap, - _actual_region_bm, - _actual_card_bm, - &_expected_region_bm, - &_expected_card_bm); - _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - - Atomic::add(cl.failures(), &_failures); - } - - int failures() const { return _failures; } -}; - -class G1FinalizeLiveDataTask: public AbstractGangTask { - // Finalizes the liveness counting data. - // Sets the bits corresponding to the interval [NTAMS, top] - // (which contains the implicitly live objects) in the - // card liveness bitmap. Also sets the bit for each region - // containing live data, in the region liveness bitmap. - class G1FinalizeCountDataClosure: public HeapRegionClosure { - private: - G1LiveDataHelper _helper; - public: - G1FinalizeCountDataClosure(G1CMBitMap* bitmap, - BitMap* region_bm, - BitMap* card_bm) : - HeapRegionClosure(), - _helper(region_bm, card_bm) { } - - bool doHeapRegion(HeapRegion* hr) { - bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); - if (allocated_since_marking || hr->next_marked_bytes() > 0) { - _helper.set_bit_for_region(hr); - } - return false; - } - }; - - G1CMBitMap* _bitmap; - - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - HeapRegionClaimer _hr_claimer; - -public: - G1FinalizeLiveDataTask(G1CMBitMap* bitmap, BitMap* region_bm, BitMap* card_bm, uint n_workers) : - AbstractGangTask("G1 final counting"), - _bitmap(bitmap), - _actual_region_bm(region_bm), - _actual_card_bm(card_bm), - _hr_claimer(n_workers) { - } - - void work(uint worker_id) { - G1FinalizeCountDataClosure cl(_bitmap, - _actual_region_bm, - _actual_card_bm); - - G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - } -}; - class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { G1CollectedHeap* _g1; size_t _freed_bytes; @@ -1613,26 +1248,13 @@ void G1ConcurrentMark::cleanup() { HeapRegionRemSet::reset_for_cleanup_tasks(); { - // Finalize the live data. - G1FinalizeLiveDataTask cl(_nextMarkBitMap, - &_region_live_bm, - &_card_live_bm, - g1h->workers()->active_workers()); - g1h->workers()->run_task(&cl); + GCTraceTime(Debug, gc)("Finalize Live Data"); + finalize_live_data(); } if (VerifyDuringGC) { - // Verify that the liveness count data created concurrently matches one created - // during this safepoint. - ResourceMark rm; - G1VerifyLiveDataTask cl(G1CollectedHeap::heap(), - _nextMarkBitMap, - &_region_live_bm, - &_card_live_bm, - g1h->workers()->active_workers()); - g1h->workers()->run_task(&cl); - - guarantee(cl.failures() == 0, "Unexpected accounting failures"); + GCTraceTime(Debug, gc)("Verify Live Data"); + verify_live_data(); } g1h->collector_state()->set_mark_in_progress(false); @@ -1669,7 +1291,7 @@ void G1ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - g1h->scrub_rem_set(&_region_live_bm, &_card_live_bm); + g1h->scrub_rem_set(); _total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start); } @@ -2115,35 +1737,6 @@ void G1ConcurrentMark::swapMarkBitMaps() { _nextMarkBitMap = (G1CMBitMap*) temp; } -BitMap G1ConcurrentMark::allocate_large_bitmap(BitMap::idx_t size_in_bits) { - size_t size_in_words = BitMap::size_in_words(size_in_bits); - - BitMap::bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); - - return BitMap(map, size_in_bits); -} - -void G1ConcurrentMark::allocate_internal_bitmaps() { - double start_time = os::elapsedTime(); - - _region_live_bm = allocate_large_bitmap(_g1h->max_regions()); - - guarantee(_g1h->max_capacity() % CardTableModRefBS::card_size == 0, - "Heap capacity must be aligned to card size."); - _card_live_bm = allocate_large_bitmap(_g1h->max_capacity() / CardTableModRefBS::card_size); - - log_debug(gc, marking)("Allocating internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); -} - -void G1ConcurrentMark::pretouch_internal_bitmaps() { - double start_time = os::elapsedTime(); - - _region_live_bm.pretouch(); - _card_live_bm.pretouch(); - - log_debug(gc, marking)("Pre-touching internal bitmaps took %1.2f seconds.", os::elapsedTime() - start_time); -} - // Closure for marking entries in SATB buffers. class G1CMSATBBufferClosure : public SATBBufferClosure { private: @@ -2403,120 +1996,28 @@ void G1ConcurrentMark::verify_no_cset_oops() { } } #endif // PRODUCT - -class G1CreateLiveDataTask: public AbstractGangTask { - // Aggregate the counting data that was constructed concurrently - // with marking. - class G1CreateLiveDataHRClosure: public HeapRegionClosure { - G1LiveDataHelper _helper; - - G1CMBitMap* _mark_bitmap; - - G1ConcurrentMark* _cm; - public: - G1CreateLiveDataHRClosure(G1ConcurrentMark* cm, - G1CMBitMap* mark_bitmap, - BitMap* cm_card_bm) : - HeapRegionClosure(), - _helper(NULL, cm_card_bm), - _mark_bitmap(mark_bitmap), - _cm(cm) { } - - bool doHeapRegion(HeapRegion* hr) { - size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); - if (marked_bytes > 0) { - hr->add_to_marked_bytes(marked_bytes); - } - - if (_cm->do_yield_check() && _cm->has_aborted()) { - return true; - } - return false; - } - }; - - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - BitMap* _cm_card_bm; - HeapRegionClaimer _hr_claimer; - -public: - G1CreateLiveDataTask(G1CollectedHeap* g1h, - BitMap* cm_card_bm, - uint n_workers) : - AbstractGangTask("Create Live Data"), - _g1h(g1h), - _cm_card_bm(cm_card_bm), - _hr_claimer(n_workers) { - } - - void work(uint worker_id) { - SuspendibleThreadSetJoiner sts_join; - - G1CreateLiveDataHRClosure cl(_g1h->concurrent_mark(), _g1h->concurrent_mark()->nextMarkBitMap(), _cm_card_bm); - _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); - } -}; - - void G1ConcurrentMark::create_live_data() { - uint n_workers = _parallel_workers->active_workers(); - - G1CreateLiveDataTask cl(_g1h, - &_card_live_bm, - n_workers); - _parallel_workers->run_task(&cl); + _g1h->g1_rem_set()->create_card_live_data(_parallel_workers, _nextMarkBitMap); } -class G1ClearAllLiveDataTask : public AbstractGangTask { - BitMap* _bitmap; - size_t _num_tasks; - size_t _cur_task; -public: - G1ClearAllLiveDataTask(BitMap* bitmap, size_t num_tasks) : - AbstractGangTask("Clear All Live Data"), - _bitmap(bitmap), - _num_tasks(num_tasks), - _cur_task(0) { - } - - virtual void work(uint worker_id) { - while (true) { - size_t to_process = Atomic::add(1, &_cur_task) - 1; - if (to_process >= _num_tasks) { - break; - } - - BitMap::idx_t start = M * BitsPerByte * to_process; - BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap->size()); - _bitmap->clear_range(start, end); - } - } -}; - -void G1ConcurrentMark::clear_all_live_data(WorkGang* workers) { - double start_time = os::elapsedTime(); - - guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); - - size_t const num_chunks = align_size_up(_card_live_bm.size_in_words() * HeapWordSize, M) / M; - - G1ClearAllLiveDataTask cl(&_card_live_bm, num_chunks); - workers->run_task(&cl); - - // The region live bitmap is always very small, even for huge heaps. Clear - // directly. - _region_live_bm.clear(); - - - log_debug(gc, marking)("Clear Live Data took %.3fms", (os::elapsedTime() - start_time) * 1000.0); +void G1ConcurrentMark::finalize_live_data() { + _g1h->g1_rem_set()->finalize_card_live_data(_g1h->workers(), _nextMarkBitMap); } -void G1ConcurrentMark::verify_all_live_data() { - assert(_card_live_bm.count_one_bits() == 0, "Master card bitmap not clear"); - assert(_region_live_bm.count_one_bits() == 0, "Master region bitmap not clear"); +void G1ConcurrentMark::verify_live_data() { + _g1h->g1_rem_set()->verify_card_live_data(_g1h->workers(), _nextMarkBitMap); } +void G1ConcurrentMark::clear_live_data(WorkGang* workers) { + _g1h->g1_rem_set()->clear_card_live_data(workers); +} + +#ifdef ASSERT +void G1ConcurrentMark::verify_live_data_clear() { + _g1h->g1_rem_set()->verify_card_live_data_is_clear(); +} +#endif + void G1ConcurrentMark::print_stats() { if (!log_is_enabled(Debug, gc, stats)) { return; @@ -2536,14 +2037,22 @@ void G1ConcurrentMark::abort() { // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next // concurrent bitmap clearing. - clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); - + { + GCTraceTime(Debug, gc)("Clear Next Bitmap"); + clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); + } // Note we cannot clear the previous marking bitmap here // since VerifyDuringGC verifies the objects marked during // a full GC against the previous bitmap. - clear_all_live_data(_g1h->workers()); - DEBUG_ONLY(verify_all_live_data()); + { + GCTraceTime(Debug, gc)("Clear Live Data"); + clear_live_data(_g1h->workers()); + } + DEBUG_ONLY({ + GCTraceTime(Debug, gc)("Verify Live Data Clear"); + verify_live_data_clear(); + }) // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { @@ -2610,16 +2119,6 @@ void G1ConcurrentMark::print_on_error(outputStream* st) const { _nextMarkBitMap->print_on_error(st, " Next Bits: "); } -// We take a break if someone is trying to stop the world. -bool G1ConcurrentMark::do_yield_check(uint worker_id) { - if (SuspendibleThreadSet::should_yield()) { - SuspendibleThreadSet::yield(); - return true; - } else { - return false; - } -} - // Closure for iteration over bitmaps class G1CMBitMapClosure : public BitMapClosure { private: diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index fb621e34980..36fb602de82 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -298,15 +298,6 @@ protected: G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap - // Liveness count data. After marking G1 iterates over the recently gathered mark - // bitmap and records rough information about liveness on card and region basis. - // This information can be used for e.g. remembered set scrubbing. - - // A set bit indicates whether the given region contains any live object. - BitMap _region_live_bm; - // A set bit indicates that the given card contains a live object. - BitMap _card_live_bm; - // Heap bounds HeapWord* _heap_start; HeapWord* _heap_end; @@ -379,14 +370,6 @@ protected: void swapMarkBitMaps(); - // Allocates and returns a zero-ed out "large" bitmap of the given size in bits. - // It is always allocated using virtual memory. - BitMap allocate_large_bitmap(BitMap::idx_t size_in_bits); - // Allocates the memory for all bitmaps used by the concurrent marking. - void allocate_internal_bitmaps(); - // Pre-touches the internal bitmaps. - void pretouch_internal_bitmaps(); - // It resets the global marking data structures, as well as the // task local ones; should be called during initial mark. void reset(); @@ -592,7 +575,7 @@ public: void scan_root_regions(); // Scan a single root region and mark everything reachable from it. - void scanRootRegion(HeapRegion* hr, uint worker_id); + void scanRootRegion(HeapRegion* hr); // Do concurrent phase of marking, to a tentative transitive closure. void mark_from_roots(); @@ -628,7 +611,7 @@ public: inline bool isPrevMarked(oop p) const; - inline bool do_yield_check(uint worker_i = 0); + inline bool do_yield_check(); // Abandon current marking iteration due to a Full GC. void abort(); @@ -654,16 +637,19 @@ public: private: // Clear (Reset) all liveness count data. - void clear_all_live_data(WorkGang* workers); + void clear_live_data(WorkGang* workers); +#ifdef ASSERT // Verify all of the above data structures that they are in initial state. - void verify_all_live_data(); + void verify_live_data_clear(); +#endif // Aggregates the per-card liveness data based on the current marking. Also sets // the amount of marked bytes for each region. void create_live_data(); - // Verification routine + void finalize_live_data(); + void verify_live_data(); }; @@ -852,7 +838,7 @@ public: // Grey the object by marking it. If not already marked, push it on // the local queue if below the finger. - // Precondition: obj is below region's NTAMS. + // obj is below its region's NTAMS. inline void make_reference_grey(oop obj); // Grey the object (by calling make_grey_reference) if required, diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 053de4b9673..b0401d35935 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -27,6 +27,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" #include "gc/shared/taskqueue.inline.hpp" inline bool G1ConcurrentMark::par_mark(oop obj) { @@ -258,4 +259,13 @@ inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { } } +inline bool G1ConcurrentMark::do_yield_check() { + if (SuspendibleThreadSet::should_yield()) { + SuspendibleThreadSet::yield(); + return true; + } else { + return false; + } +} + #endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index 05f90f75f4e..5de38f71bd2 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -186,11 +186,9 @@ class G1RootRegionScanClosure : public MetadataAwareOopClosure { private: G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; - uint _worker_id; public: - G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, - uint worker_id) : - _g1h(g1h), _cm(cm), _worker_id(worker_id) { } + G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm) : + _g1h(g1h), _cm(cm) { } template void do_oop_nv(T* p); virtual void do_oop( oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index eb091443887..12ed0506d94 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -38,6 +38,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -84,8 +85,16 @@ uint G1RemSet::num_par_rem_sets() { return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); } -void G1RemSet::initialize(uint max_regions) { +void G1RemSet::initialize(size_t capacity, uint max_regions) { G1FromCardCache::initialize(num_par_rem_sets(), max_regions); + { + GCTraceTime(Debug, gc, marking)("Initialize Card Live Data"); + _card_live_data.initialize(capacity, max_regions); + } + if (G1PretouchAuxiliaryMemory) { + GCTraceTime(Debug, gc, marking)("Pre-Touch Card Live Data"); + _card_live_data.pretouch(); + } } ScanRSClosure::ScanRSClosure(G1ParPushHeapRSClosure* oc, @@ -312,27 +321,24 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { _into_cset_dirty_card_queue_set.clear_n_completed_buffers(); } -class ScrubRSClosure: public HeapRegionClosure { +class G1ScrubRSClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - BitMap* _region_bm; - BitMap* _card_bm; - CardTableModRefBS* _ctbs; + G1CardLiveData* _live_data; public: - ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : + G1ScrubRSClosure(G1CardLiveData* live_data) : _g1h(G1CollectedHeap::heap()), - _region_bm(region_bm), _card_bm(card_bm), - _ctbs(_g1h->g1_barrier_set()) {} + _live_data(live_data) { } bool doHeapRegion(HeapRegion* r) { if (!r->is_continues_humongous()) { - r->rem_set()->scrub(_ctbs, _region_bm, _card_bm); + r->rem_set()->scrub(_live_data); } return false; } }; -void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { - ScrubRSClosure scrub_cl(region_bm, card_bm); +void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) { + G1ScrubRSClosure scrub_cl(&_card_live_data); _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); } @@ -580,3 +586,25 @@ void G1RemSet::prepare_for_verify() { assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); } } + +void G1RemSet::create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.create(workers, mark_bitmap); +} + +void G1RemSet::finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.finalize(workers, mark_bitmap); +} + +void G1RemSet::verify_card_live_data(WorkGang* workers, G1CMBitMap* bitmap) { + _card_live_data.verify(workers, bitmap); +} + +void G1RemSet::clear_card_live_data(WorkGang* workers) { + _card_live_data.clear(workers); +} + +#ifdef ASSERT +void G1RemSet::verify_card_live_data_is_clear() { + _card_live_data.verify_is_clear(); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp index 8aab4ca498c..381d5fd8f72 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_G1_G1REMSET_HPP #include "gc/g1/dirtyCardQueue.hpp" +#include "gc/g1/g1CardLiveData.hpp" #include "gc/g1/g1RemSetSummary.hpp" #include "gc/g1/heapRegion.hpp" #include "memory/allocation.hpp" @@ -48,9 +49,10 @@ class HeapRegionClaimer; // A G1RemSet in which each heap region has a rem set that records the // external heap references into it. Uses a mod ref bs to track updates, // so that they can be used to update the individual region remsets. - class G1RemSet: public CHeapObj { private: + G1CardLiveData _card_live_data; + G1RemSetSummary _prev_period_summary; // A DirtyCardQueueSet that is used to hold cards that contain @@ -83,7 +85,7 @@ public: static uint num_par_rem_sets(); // Initialize data that depends on the heap size being known. - static void initialize(uint max_regions); + void initialize(size_t capacity, uint max_regions); // This is called to reset dual hash tables after the gc pause // is finished and the initial hash table is no longer being @@ -140,7 +142,7 @@ public: // set entries that correspond to dead heap ranges. "worker_num" is the // parallel thread id of the current thread, and "hrclaimer" is the // HeapRegionClaimer that should be used. - void scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer* hrclaimer); + void scrub(uint worker_num, HeapRegionClaimer* hrclaimer); // Refine the card corresponding to "card_ptr". // If check_for_refs_into_cset is true, a true result is returned @@ -162,6 +164,19 @@ public: size_t conc_refine_cards() const { return _conc_refine_cards; } + + void create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + void finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify_card_live_data(WorkGang* workers, G1CMBitMap* actual_bitmap); + + void clear_card_live_data(WorkGang* workers); + +#ifdef ASSERT + void verify_card_live_data_is_clear(); +#endif }; class ScanRSClosure : public HeapRegionClosure { diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 26d5ce3e7e0..4fee9c4ecfc 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -26,6 +26,7 @@ #include "gc/g1/concurrentG1Refine.hpp" #include "gc/g1/g1BlockOffsetTable.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/space.inline.hpp" @@ -141,10 +142,8 @@ public: add_reference_work(from, /*parallel*/ false); } - void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) { - HeapWord* hr_bot = hr()->bottom(); - size_t hr_first_card_index = ctbs->index_for(hr_bot); - bm()->set_intersection_at_offset(*card_bm, hr_first_card_index); + void scrub(G1CardLiveData* live_data) { + live_data->remove_nonlive_cards(hr()->hrm_index(), &_bm); recount_occupied(); } @@ -515,14 +514,12 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { return max; } -void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { +void OtherRegionsTable::scrub(G1CardLiveData* live_data) { // First eliminated garbage regions from the coarse map. log_develop_trace(gc, remset, scrub)("Scrubbing region %u:", _hr->hrm_index()); - assert(_coarse_map.size() == region_bm->size(), "Precondition"); log_develop_trace(gc, remset, scrub)(" Coarse map: before = " SIZE_FORMAT "...", _n_coarse_entries); - _coarse_map.set_intersection(*region_bm); + live_data->remove_nonlive_regions(&_coarse_map); _n_coarse_entries = _coarse_map.count_one_bits(); log_develop_trace(gc, remset, scrub)(" after = " SIZE_FORMAT ".", _n_coarse_entries); @@ -534,7 +531,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, PerRegionTable* nxt = cur->collision_list_next(); // If the entire region is dead, eliminate. log_develop_trace(gc, remset, scrub)(" For other region %u:", cur->hr()->hrm_index()); - if (!region_bm->at((size_t) cur->hr()->hrm_index())) { + if (!live_data->is_region_live(cur->hr()->hrm_index())) { *prev = nxt; cur->set_collision_list_next(NULL); _n_fine_entries--; @@ -544,7 +541,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, } else { // Do fine-grain elimination. log_develop_trace(gc, remset, scrub)(" occ: before = %4d.", cur->occupied()); - cur->scrub(ctbs, card_bm); + cur->scrub(live_data); log_develop_trace(gc, remset, scrub)(" after = %4d.", cur->occupied()); // Did that empty the table completely? if (cur->occupied() == 0) { @@ -773,9 +770,8 @@ void HeapRegionRemSet::reset_for_par_iteration() { assert(verify_ready_for_par_iteration(), "post-condition"); } -void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { - _other_regions.scrub(ctbs, region_bm, card_bm); +void HeapRegionRemSet::scrub(G1CardLiveData* live_data) { + _other_regions.scrub(live_data); } // Code roots support diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp index 5a286bc2836..c884dab2484 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp @@ -35,6 +35,7 @@ class G1CollectedHeap; class G1BlockOffsetTable; +class G1CardLiveData; class HeapRegion; class HeapRegionRemSetIterator; class PerRegionTable; @@ -143,7 +144,7 @@ public: // Removes any entries shown by the given bitmaps to contain only dead // objects. Not thread safe. // Set bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // Returns whether this remembered set (and all sub-sets) does not contain any entry. bool is_empty() const; @@ -230,10 +231,9 @@ public: _other_regions.add_reference(from, tid); } - // Removes any entries in the remembered set shown by the given bitmaps to + // Removes any entries in the remembered set shown by the given card live data to // contain only dead objects. Not thread safe. - // One bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // The region is being reclaimed; clear its remset, and any mention of // entries for this region in other remsets. diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index 7804c988487..bb7ae8ede14 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -69,7 +69,7 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { } void BitMap::pretouch() { - os::pretouch_memory((char*)word_addr(0), (char*)word_addr(size())); + os::pretouch_memory(word_addr(0), word_addr(size())); } void BitMap::set_range_within_word(idx_t beg, idx_t end) { diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index 0e46cea9917..b925d66442f 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,11 +140,12 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // Accessing idx_t size() const { return _size; } + idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; } idx_t size_in_words() const { - return word_index(size() + BitsPerWord - 1); + return calc_size_in_words(size()); } - static idx_t size_in_words(size_t size_in_bits) { + static idx_t calc_size_in_words(size_t size_in_bits) { return word_index(size_in_bits + BitsPerWord - 1); } From af3081628b5fbb42ed672b4a035fab3f66e109c3 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 6 Apr 2016 20:43:03 +0900 Subject: [PATCH 095/167] 8152435: (CL)HSDB should be started with no argument Reviewed-by: dsamersoff --- .../classes/sun/jvm/hotspot/SAGetopt.java | 12 +++--- .../sun/jvm/hotspot/SAGetoptException.java | 33 ++++++++++++++++ .../classes/sun/jvm/hotspot/SALauncher.java | 39 +++++++++---------- 3 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java index 3d4ffb0171b..d23a057f584 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java @@ -55,11 +55,11 @@ public class SAGetopt { private void extractOptarg(String opt) { // Argument expected if (_optind > _argv.length) { - throw new RuntimeException("Not enough arguments for '" + opt + "'"); + throw new SAGetoptException("Not enough arguments for '" + opt + "'"); } if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') { - throw new RuntimeException("Argument is expected for '" + opt + "'"); + throw new SAGetoptException("Argument is expected for '" + opt + "'"); } _optarg = _argv[_optind]; @@ -72,7 +72,7 @@ public class SAGetopt { if (los.contains(ca[0])) { if (ca.length > 1) { - throw new RuntimeException("Argument is not expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is not expected for '" + ca[0] + "'"); } return carg; } @@ -87,14 +87,14 @@ public class SAGetopt { try { extractOptarg(ca[0]); } catch (ArrayIndexOutOfBoundsException e) { - throw new RuntimeException("Argument is expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is expected for '" + ca[0] + "'"); } } return ca[0]; } - throw new RuntimeException("Invalid option '" + ca[0] + "'"); + throw new SAGetoptException("Invalid option '" + ca[0] + "'"); } public String next(String optStr, String[] longOptStr) { @@ -148,7 +148,7 @@ public class SAGetopt { int chIndex = optStr.indexOf(ch); if (chIndex == -1) { - throw new RuntimeException("Invalid option '" + ch + "'"); + throw new SAGetoptException("Invalid option '" + ch + "'"); } if (_optopt >= carg.length()) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java new file mode 100644 index 00000000000..f6ba480ca33 --- /dev/null +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot; + +public class SAGetoptException extends IllegalArgumentException { + + public SAGetoptException(String message) { + super(message); + } + +} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java index 4b1f280a6d7..dfbbb6ff440 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java @@ -111,34 +111,31 @@ public class SALauncher { return launcherHelp(); } - private static void buildAttachArgs(ArrayList newArgs, - String pid, String exe, String core) { - if ((pid == null) && (exe == null)) { - throw new IllegalArgumentException( - "You have to set --pid or --exe."); + private static void buildAttachArgs(ArrayList newArgs, String pid, + String exe, String core, boolean allowEmpty) { + if (!allowEmpty && (pid == null) && (exe == null)) { + throw new SAGetoptException("You have to set --pid or --exe."); } if (pid != null) { // Attach to live process if (exe != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --exe"); + throw new SAGetoptException("Unnecessary argument: --exe"); } else if (core != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --core"); + throw new SAGetoptException("Unnecessary argument: --core"); } else if (!pid.matches("^\\d+$")) { - throw new IllegalArgumentException("Invalid pid: " + pid); + throw new SAGetoptException("Invalid pid: " + pid); } newArgs.add(pid); - } else { + } else if (exe != null) { if (exe.length() == 0) { - throw new IllegalArgumentException("You have to set --exe."); + throw new SAGetoptException("You have to set --exe."); } newArgs.add(exe); if ((core == null) || (core.length() == 0)) { - throw new IllegalArgumentException("You have to set --core."); + throw new SAGetoptException("You have to set --core."); } newArgs.add(core); @@ -170,7 +167,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -199,7 +196,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); HSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -237,7 +234,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JStack.main(newArgs.toArray(new String[newArgs.size()])); } @@ -287,7 +284,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JMap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -325,7 +322,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JInfo.main(newArgs.toArray(new String[newArgs.size()])); } @@ -358,7 +355,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JSnap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -416,8 +413,8 @@ public class SALauncher { return; } - throw new IllegalArgumentException("Unknown tool: " + args[0]); - } catch (Exception e) { + throw new SAGetoptException("Unknown tool: " + args[0]); + } catch (SAGetoptException e) { System.err.println(e.getMessage()); toolHelp(args[0]); } From c282f259646f0648c1dabe0252de7572cd78e3ba Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 6 Apr 2016 11:40:45 -0700 Subject: [PATCH 096/167] 8152329: jvm should treat the "Multi-Release" jar manifest attribute name as case insensitive Reviewed-by: iklam, jiangli, mseledtsov --- hotspot/src/share/vm/classfile/classLoader.cpp | 12 ++++++++++-- hotspot/src/share/vm/classfile/classLoader.hpp | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index bdf18bc55e0..a8a86765970 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -233,6 +233,7 @@ ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_ strcpy(copy, zip_name); _zip_name = copy; _is_boot_append = is_boot_append; + _multi_versioned = _unknown; } ClassPathZipEntry::~ClassPathZipEntry() { @@ -330,13 +331,20 @@ u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TR bool ClassPathZipEntry::is_multiple_versioned(TRAPS) { assert(DumpSharedSpaces, "called only at dump time"); + if (_multi_versioned != _unknown) { + return (_multi_versioned == _yes) ? true : false; + } jint size; - char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false); + char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, true, CHECK_false); if (buffer != NULL) { - if (strstr(buffer, "Multi-Release: true") != NULL) { + char* p = buffer; + for ( ; *p; ++p) *p = tolower(*p); + if (strstr(buffer, "multi-release: true") != NULL) { + _multi_versioned = _yes; return true; } } + _multi_versioned = _no; return false; } #endif // INCLUDE_CDS diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 8ac282727d5..fc1d335b7ab 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -101,10 +101,17 @@ typedef struct { class ClassPathZipEntry: public ClassPathEntry { + enum { + _unknown = 0, + _yes = 1, + _no = 2 + }; private: jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive bool _is_boot_append; // entry coming from -Xbootclasspath/a + u1 _multi_versioned; // indicates if the jar file has multi-versioned entries. + // It can have value of "_unknown", "_yes", or "_no" public: bool is_jrt() { return false; } bool is_jar_file() const { return true; } From f22c068365fdb645e21786cd190874021f89b4b5 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Thu, 7 Apr 2016 10:55:54 +0200 Subject: [PATCH 097/167] 8152312: ParNew: Restore preserved marks in parallel Reviewed-by: tschatzl --- .../share/vm/gc/serial/defNewGeneration.cpp | 5 +- .../src/share/vm/gc/shared/preservedMarks.cpp | 75 ++++++++++++++----- .../src/share/vm/gc/shared/preservedMarks.hpp | 37 +++++++-- .../vm/gc/shared/preservedMarks.inline.hpp | 52 ++++++++++++- 4 files changed, 137 insertions(+), 32 deletions(-) diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index a9b404604b0..247c7e3e49a 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -692,7 +692,7 @@ void DefNewGeneration::collect(bool full, _promo_failure_scan_stack.clear(true); // Clear cached segments. remove_forwarding_pointers(); - log_debug(gc)("Promotion failed"); + log_info(gc, promotion)("Promotion failed"); // Add to-space to the list of space to compact // when a promotion failure has occurred. In that // case there can be live objects in to-space @@ -739,8 +739,7 @@ void DefNewGeneration::remove_forwarding_pointers() { eden()->object_iterate(&rspc); from()->object_iterate(&rspc); - // Now restore saved marks, if any. - _preserved_marks_set.restore(); + _preserved_marks_set.restore(GenCollectedHeap::heap()->workers()); } void DefNewGeneration::handle_promotion_failure(oop old) { diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp index e6950ff78b6..96d124e2259 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp @@ -24,24 +24,30 @@ #include "precompiled.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shared/workgroup.hpp" #include "memory/allocation.inline.hpp" -#include "oops/oop.inline.hpp" void PreservedMarks::restore() { - // First, iterate over the stack and restore all marks. - StackIterator iter(_stack); - while (!iter.is_empty()) { - OopAndMarkOop elem = iter.next(); + while (!_stack.is_empty()) { + const OopAndMarkOop elem = _stack.pop(); elem.set_mark(); } - - // Second, reclaim all the stack memory - _stack.clear(true /* clear_cache */); + assert_empty(); } +#ifndef PRODUCT +void PreservedMarks::assert_empty() { + assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT, + _stack.size()); + assert(_stack.cache_size() == 0, + "stack expected to have no cached segments, cache size = "SIZE_FORMAT, + _stack.cache_size()); +} +#endif // ndef PRODUCT + void RemoveForwardedPointerClosure::do_object(oop obj) { if (obj->is_forwarded()) { - obj->init_mark(); + PreservedMarks::init_forwarded_mark(obj); } } @@ -61,15 +67,48 @@ void PreservedMarksSet::init(uint num) { assert_empty(); } -void PreservedMarksSet::restore() { - size_t total_size = 0; - for (uint i = 0; i < _num; i += 1) { - total_size += get(i)->size(); - get(i)->restore(); - } - assert_empty(); +class ParRestoreTask : public AbstractGangTask { +private: + PreservedMarksSet* const _preserved_marks_set; + SequentialSubTasksDone _sub_tasks; + volatile size_t* const _total_size_addr; - log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); +public: + virtual void work(uint worker_id) { + uint task_id = 0; + while (!_sub_tasks.is_task_claimed(/* reference */ task_id)) { + PreservedMarks* const preserved_marks = _preserved_marks_set->get(task_id); + const size_t size = preserved_marks->size(); + preserved_marks->restore(); + // Only do the atomic add if the size is > 0. + if (size > 0) { + Atomic::add(size, _total_size_addr); + } + } + _sub_tasks.all_tasks_completed(); + } + + ParRestoreTask(uint worker_num, + PreservedMarksSet* preserved_marks_set, + volatile size_t* total_size_addr) + : AbstractGangTask("Parallel Preserved Mark Restoration"), + _preserved_marks_set(preserved_marks_set), + _total_size_addr(total_size_addr) { + _sub_tasks.set_n_threads(worker_num); + _sub_tasks.set_n_tasks(preserved_marks_set->num()); + } +}; + +void PreservedMarksSet::restore_internal(WorkGang* workers, + volatile size_t* total_size_addr) { + assert(workers != NULL, "pre-condition"); + ParRestoreTask task(workers->active_workers(), this, total_size_addr); + workers->run_task(&task); +} + +// temporary, used by PS +void PreservedMarksSet::restore() { + restore(NULL); } void PreservedMarksSet::reclaim() { @@ -92,7 +131,7 @@ void PreservedMarksSet::reclaim() { void PreservedMarksSet::assert_empty() { assert(_stacks != NULL && _num > 0, "should have been initialized"); for (uint i = 0; i < _num; i += 1) { - assert(get(i)->is_empty(), "stack should be empty"); + get(i)->assert_empty(); } } #endif // ndef PRODUCT diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp index 729f0666b17..6ab52ba0fb4 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp @@ -44,6 +44,8 @@ public: }; typedef Stack OopAndMarkOopStack; +class WorkGang; + class PreservedMarks VALUE_OBJ_CLASS_SPEC { private: OopAndMarkOopStack _stack; @@ -52,13 +54,19 @@ private: inline void push(oop obj, markOop m); public: - bool is_empty() const { return _stack.is_empty(); } size_t size() const { return _stack.size(); } inline void push_if_necessary(oop obj, markOop m); - // Iterate over the stack, restore the preserved marks, then reclaim - // the memory taken up by stack chunks. + // Iterate over the stack, restore all preserved marks, and + // reclaim the memory taken up by the stack segments. void restore(); - ~PreservedMarks() { assert(is_empty(), "should have been cleared"); } + + inline static void init_forwarded_mark(oop obj); + + // Assert the stack is empty and has no cached segments. + void assert_empty() PRODUCT_RETURN; + + inline PreservedMarks(); + ~PreservedMarks() { assert_empty(); } }; class RemoveForwardedPointerClosure: public ObjectClosure { @@ -82,7 +90,12 @@ private: // or == NULL if they have not. Padded* _stacks; + // Internal version of restore() that uses a WorkGang for parallelism. + void restore_internal(WorkGang* workers, volatile size_t* total_size_addr); + public: + uint num() const { return _num; } + // Return the i'th stack. PreservedMarks* get(uint i = 0) const { assert(_num > 0 && _stacks != NULL, "stacks should have been initialized"); @@ -92,13 +105,23 @@ public: // Allocate stack array. void init(uint num); - // Iterate over all stacks, restore all preserved marks, then - // reclaim the memory taken up by stack chunks. + + // Itrerate over all stacks, restore all presered marks, and reclaim + // the memory taken up by the stack segments. If the executor is + // NULL, restoration will be done serially. If the executor is not + // NULL, restoration could be done in parallel (when it makes + // sense). Supported executors: WorkGang (Serial, CMS, G1) + template + inline void restore(E* executor); + + // Do the restoration serially. Temporary, to be used by PS until we + // can support GCTaskManager in restore(E*). void restore(); + // Reclaim stack array. void reclaim(); - // Assert all the stacks are empty. + // Assert all the stacks are empty and have no cached segments. void assert_empty() PRODUCT_RETURN; PreservedMarksSet(bool in_c_heap) diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp index 32c83115a69..fc1039ad40b 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp @@ -22,13 +22,13 @@ * */ -#include "gc/shared/preservedMarks.hpp" -#include "oops/markOop.inline.hpp" -#include "utilities/stack.inline.hpp" - #ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP #define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP +#include "gc/shared/preservedMarks.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/stack.inline.hpp" + inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const { return m->must_be_preserved_for_promotion_failure(obj); } @@ -45,4 +45,48 @@ inline void PreservedMarks::push_if_necessary(oop obj, markOop m) { } } +inline void PreservedMarks::init_forwarded_mark(oop obj) { + obj->init_mark(); +} + +template +inline void PreservedMarksSet::restore(E* executor) { + volatile size_t total_size = 0; + +#ifdef ASSERT + // This is to make sure the total_size we'll calculate below is correct. + size_t total_size_before = 0; + for (uint i = 0; i < _num; i += 1) { + total_size_before += get(i)->size(); + } +#endif // def ASSERT + + if (executor == NULL) { + for (uint i = 0; i < _num; i += 1) { + total_size += get(i)->size(); + get(i)->restore(); + } + } else { + // Right now, if the executor is not NULL we do the work in + // parallel. In the future we might want to do the restoration + // serially, if there's only a small number of marks per stack. + restore_internal(executor, &total_size); + } + assert_empty(); + + assert(total_size == total_size_before, + "total_size = " SIZE_FORMAT " before = " SIZE_FORMAT, + total_size, total_size_before); + + log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); +} + +inline PreservedMarks::PreservedMarks() + : _stack(OopAndMarkOopStack::default_segment_size(), + // This stack should be used very infrequently so there's + // no point in caching stack segments (there will be a + // waste of space most of the time). So we set the max + // cache size to 0. + 0 /* max_cache_size */) { } + #endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP From 2b7a70a9d3d9b4ca94605d22d3d4f3c78a5c8d8b Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Thu, 7 Apr 2016 17:42:30 +0400 Subject: [PATCH 098/167] 8152432: Implement setting jtreg @requires properties vm.flavor, vm.bits, vm.compMode Reviewed-by: iignatyev --- hotspot/test/TEST.ROOT | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 55979b0a554..29c9696e7be 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -30,6 +30,10 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] + +# Source files for classes that will be used at the beginning of each test suite run, +# to determine additional characteristics of the system for use with the @requires tag. +requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java requires.properties=sun.arch.data.model # Tests using jtreg 4.2 b01 features From 412ce42184a379abe9a75b8ffb25055073d4b23d Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 7 Apr 2016 15:58:24 +0300 Subject: [PATCH 099/167] 8148376: Test for PLAB behavior at evacuation failure Reviewed-by: tschatzl, dfazunen --- .../gc/g1/plab/TestPLABEvacuationFailure.java | 203 ++++++++++++++++++ .../g1/plab/lib/AppPLABEvacuationFailure.java | 54 +++++ 2 files changed, 257 insertions(+) create mode 100644 hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java create mode 100644 hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java diff --git a/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java new file mode 100644 index 00000000000..5bcad7f2404 --- /dev/null +++ b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test TestPLABEvacuationFailure + * @bug 8148376 + * @summary Checks PLAB statistics on evacuation failure + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary / + * @modules java.management + * @build gc.g1.plab.lib.LogParser + * gc.g1.plab.lib.AppPLABEvacuationFailure + * @run main gc.g1.plab.TestPLABEvacuationFailure + */ +package gc.g1.plab; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Utils; + +import gc.g1.plab.lib.LogParser; +import gc.g1.plab.lib.AppPLABEvacuationFailure; +import gc.g1.plab.lib.PlabInfo; + +/** + * The test runs the AppPLABEvacuationFailure application to provoke a number of + * Evacuation Failures, parses GC log and analyzes PLAB statistics. The test checks + * that both fields 'failure_waste' and 'failure_used' for Evacuation Failure statistic + * are non zero, and zero for other statistics. + */ +public class TestPLABEvacuationFailure { + + /* PLAB statistics fields which are checked. + * Test expects to find 0 in this fields in survivor statistics. + * Expects to find 0 in old statistics for GC when evacuation failure + * did not happen. And expects to find not 0 in old statistics in case when + * GC causes to evacuation failure. + */ + private static final List FAILURE_STAT_FIELDS = new ArrayList<>(Arrays.asList( + "failure used", + "failure wasted")); + + private static final String[] COMMON_OPTIONS = { + "-Xlog:gc=debug,gc+plab=debug,gc+phases=trace", + "-XX:+UseG1GC", + "-XX:InitiatingHeapOccupancyPercent=100", + "-XX:-G1UseAdaptiveIHOP", + "-XX:G1HeapRegionSize=1m"}; + + private static final Pattern GC_ID_PATTERN = Pattern.compile("GC\\((\\d+)\\)"); + private static List evacuationFailureIDs; + private static LogParser logParser; + private static String appPlabEvacFailureOutput; + + public static void main(String[] args) throws Throwable { + // ParallelGCBufferWastePct, PLAB Size, ParallelGCBufferWastePct, MaxHeapSize, is plab fixed. + runTest(10, 1024, 3, 16, true); + runTest(15, 2048, 4, 256, true); + runTest(20, 65536, 7, 128, false); + runTest(25, 1024, 3, 16, true); + runTest(30, 16384, 7, 256, false); + runTest(10, 65536, 4, 32, false); + } + + private static void runTest(int wastePct, int plabSize, int parGCThreads, int heapSize, boolean plabIsFixed) throws Throwable { + System.out.println("Test case details:"); + System.out.println(" Heap size : " + heapSize + "M"); + System.out.println(" Initial PLAB size : " + plabSize); + System.out.println(" Parallel GC buffer waste pct : " + wastePct); + System.out.println(" Parallel GC threads : " + parGCThreads); + System.out.println(" PLAB size is fixed: " + (plabIsFixed ? "yes" : "no")); + // Set up test GC and PLAB options + List testOptions = new ArrayList<>(); + Collections.addAll(testOptions, COMMON_OPTIONS); + Collections.addAll(testOptions, Utils.getTestJavaOpts()); + Collections.addAll(testOptions, + "-XX:ParallelGCThreads=" + parGCThreads, + "-XX:ParallelGCBufferWastePct=" + wastePct, + "-XX:OldPLABSize=" + plabSize, + "-XX:YoungPLABSize=" + plabSize, + "-XX:" + (plabIsFixed ? "-" : "+") + "ResizePLAB", + "-XX:MaxHeapSize=" + heapSize + "m"); + testOptions.add(AppPLABEvacuationFailure.class.getName()); + OutputAnalyzer out = ProcessTools.executeTestJvm(testOptions.toArray(new String[testOptions.size()])); + + appPlabEvacFailureOutput = out.getOutput(); + if (out.getExitValue() != 0) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("Expect exit code 0."); + } + // Get list of GC ID on evacuation failure + evacuationFailureIDs = getGcIdPlabEvacFailures(out); + logParser = new LogParser(appPlabEvacFailureOutput); + checkResults(); + } + + private static void checkResults() { + + if (evacuationFailureIDs.isEmpty()) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("AppPLABEvacuationFailure did not reach Evacuation Failure."); + } + + Map valuesToCheck = getNonEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that SURVIVOR PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getNonEvacFailureOldStats(); + checkValuesIsZero(valuesToCheck, "Expect that OLD PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that failure statistics should be 0 in SURVIVOR PLAB statistics at evacuation failure"); + + valuesToCheck = getEvacFailureOldStats(); + checkValuesIsNotZero(valuesToCheck, "Expect that failure statistics should not be 0 in OLD PLAB statistics at evacuation failure"); + } + + /** + * Checks logItems for non-zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, true); + } + + /** + * Checks logItems for zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsNotZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, false); + } + + private static void checkValues(Map logItems, String errorMessage, boolean expectZero) { + logItems.entrySet() + .forEach(item -> item.getValue() + .values() + .forEach(items -> { + if (expectZero != (items == 0)) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException(errorMessage); + } + }) + ); + } + + /** + * For tracking PLAB statistics for specified PLAB type - survivor and old + */ + private static Map getNonEvacFailureSurvivorStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getNonEvacFailureOldStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureSurvivorStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureOldStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static List getGcIdPlabEvacFailures(OutputAnalyzer out) { + return out.asLines().stream() + .filter(line -> line.contains("Evacuation Failure")) + .map(line -> LogParser.getGcIdFromLine(line, GC_ID_PATTERN)) + .collect(Collectors.toList()); + } +} diff --git a/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java new file mode 100644 index 00000000000..25d797ecda5 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package gc.g1.plab.lib; + +import java.util.ArrayList; + +/** + * Application that provokes Evacuation Failure + */ +public class AppPLABEvacuationFailure { + + public static final int CHUNK = 10000; + public static ArrayList arr = new ArrayList<>(); + + public static void main(String[] args) { + System.gc(); + // First attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + // Second attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + } +} From 0202ef201cc0bc4a2d209e8fd978dbea9b7c4bc5 Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 7 Apr 2016 16:01:16 +0300 Subject: [PATCH 100/167] 8153516: Hotspot TEST.group has error in GC groups definition Reviewed-by: tschatzl, dfazunen --- hotspot/test/TEST.groups | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 527de350443..fd320ecf20f 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -386,7 +386,8 @@ hotspot_jprt = \ :hotspot_fast_compiler_2 \ :hotspot_fast_compiler_3 \ :hotspot_fast_compiler_closed \ - :hotspot_fast_gc \ + :hotspot_fast_gc_1 \ + :hotspot_fast_gc_2 \ :hotspot_fast_gc_closed \ :hotspot_fast_gc_gcold \ :hotspot_fast_runtime \ From a9cf95480ff53ae3345554488298297aba0f3345 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 7 Apr 2016 15:17:08 +0200 Subject: [PATCH 101/167] 8153734: TestHumongousReferenceObject.java occasionally crashes with "unable to allocate heap of 1g" on win32 Decrease the heap size used in the test from 1g to 128M. Reviewed-by: dfazunen, sjohanss --- .../test/gc/TestHumongousReferenceObject.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/test/gc/TestHumongousReferenceObject.java b/hotspot/test/gc/TestHumongousReferenceObject.java index 728b8911de8..7e09abfe274 100644 --- a/hotspot/test/gc/TestHumongousReferenceObject.java +++ b/hotspot/test/gc/TestHumongousReferenceObject.java @@ -27,26 +27,26 @@ import jdk.internal.vm.annotation.Contended; * @test * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries on G1, with references in them works. * @requires vm.gc == "null" - * @bug 8151499 + * @bug 8151499 8153734 * @modules java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject */ public class TestHumongousReferenceObject { /* Due to 300 fields with 8K @Contended padding around each field, it takes 2.4M bytes per instance. With small G1 regions, it is bound to cross regions. G1 should properly (card) mark the object nevertheless. - With 1G heap, it is enough to allocate ~400 of these objects to provoke at least one GC. + With 128M heap, it is enough to allocate ~100 of these objects to provoke at least one GC. */ static volatile Object instance; public static void main(String[] args) { - for (int c = 0; c < 400; c++) { + for (int c = 0; c < 100; c++) { instance = new TestHumongousReferenceObject(); } } From 24a9e0ac188a37dc57cc4d1bb8d8635abb4c4f89 Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Thu, 7 Apr 2016 17:43:35 +0400 Subject: [PATCH 102/167] 8152432: Implement setting jtreg @requires properties vm.flavor, vm.bits, vm.compMode Reviewed-by: iignatyev --- test/jtreg-ext/requires/VMProps.java | 136 +++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 test/jtreg-ext/requires/VMProps.java diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java new file mode 100644 index 00000000000..ef7de8faf39 --- /dev/null +++ b/test/jtreg-ext/requires/VMProps.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package requires; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * The Class to be invoked by jtreg prior Test Suite execution to + * collect information about VM. + * Properties set by this Class will be available in the @requires expressions. + */ +public class VMProps implements Callable> { + + /** + * Collects information about VM properties. + * This method will be invoked by jtreg. + * + * @return Map of property-value pairs. + */ + @Override + public Map call() { + Map map = new HashMap<>(); + map.put("vm.flavor", vmFlavor()); + map.put("vm.compMode", vmCompMode()); + map.put("vm.bits", vmBits()); + dump(map); + return map; + } + + /** + * @return VM type value extracted from the "java.vm.name" property. + */ + protected String vmFlavor() { + // E.g. "Java HotSpot(TM) 64-Bit Server VM" + String vmName = System.getProperty("java.vm.name"); + if (vmName == null) { + return null; + } + + Pattern startP = Pattern.compile(".* (\\S+) VM"); + Matcher m = startP.matcher(vmName); + if (m.matches()) { + return m.group(1).toLowerCase(); + } + return null; + } + + /** + * @return VM compilation mode extracted from the "java.vm.info" property. + */ + protected String vmCompMode() { + // E.g. "mixed mode" + String vmInfo = System.getProperty("java.vm.info"); + if (vmInfo == null) { + return null; + } + int k = vmInfo.toLowerCase().indexOf(" mode"); + if (k < 0) { + return null; + } + vmInfo = vmInfo.substring(0, k); + switch (vmInfo) { + case "mixed" : return "Xmixed"; + case "compiled" : return "Xcomp"; + case "interpreted" : return "Xint"; + default: return null; + } + } + + /** + * @return VM bitness, the value of the "sun.arch.data.model" property. + */ + protected String vmBits() { + return System.getProperty("sun.arch.data.model"); + } + + /** + * Dumps the map to the file if the file name is given as the property. + * This functionality could be helpful to know context in the real + * execution. + * + * @param map + */ + protected void dump(Map map) { + String dumpFileName = System.getProperty("vmprops.dump"); + if (dumpFileName == null) { + return; + } + List lines = new ArrayList<>(); + map.forEach((k,v) -> lines.add(k + ":" + v)); + try { + Files.write(Paths.get(dumpFileName), lines); + } catch (IOException e) { + throw new RuntimeException("Failed to dump properties into '" + + dumpFileName + "'", e); + } + } + + /** + * This method is for the testing purpose only. + * @param args + */ + public static void main(String args[]) { + Map map = new VMProps().call(); + map.forEach((k,v) -> System.out.println(k + ": '" + v + "'")); + } +} From 02d268d76065f5c12d79bca25ed95482e812b17d Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 7 Apr 2016 13:11:15 -0400 Subject: [PATCH 103/167] 8152896: Convert PrintCompressedOopsMode to Unified Logging Converted -XX:+PrintCompressedOopsMode to -Xlog:gc+heap+coops and aliased old option Reviewed-by: coleenp, sjohanss, kvn, hseigel --- hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/memory/universe.cpp | 10 ++- hotspot/src/share/vm/memory/virtualspace.cpp | 38 ++++----- hotspot/src/share/vm/runtime/arguments.cpp | 16 ++-- hotspot/src/share/vm/runtime/globals.hpp | 3 - .../CompressedClassPointers.java | 5 +- .../CompressedOops/UseCompressedOops.java | 3 +- .../runtime/logging/CompressedOopsTest.java | 82 +++++++++++++++++++ 8 files changed, 113 insertions(+), 45 deletions(-) create mode 100644 hotspot/test/runtime/logging/CompressedOopsTest.java diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 78cb944c345..5e4fcc6a142 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -48,6 +48,7 @@ LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(constraints) \ + LOG_TAG(coops) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ LOG_TAG(defaultmethods) \ diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index f33afa87ea2..11037c539f0 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -747,8 +747,10 @@ jint Universe::initialize_heap() { Universe::set_narrow_ptrs_base(Universe::narrow_oop_base()); - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - Universe::print_compressed_oops_mode(tty); + if (log_is_enabled(Info, gc, heap, coops)) { + ResourceMark rm; + outputStream* logst = Log(gc, heap, coops)::info_stream(); + Universe::print_compressed_oops_mode(logst); } // Tell tests in which mode we run. @@ -776,8 +778,8 @@ jint Universe::initialize_heap() { } void Universe::print_compressed_oops_mode(outputStream* st) { - st->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", - p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); + st->print("Heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", + p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); st->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode())); diff --git a/hotspot/src/share/vm/memory/virtualspace.cpp b/hotspot/src/share/vm/memory/virtualspace.cpp index 76f45090ec2..31fddb745c7 100644 --- a/hotspot/src/share/vm/memory/virtualspace.cpp +++ b/hotspot/src/share/vm/memory/virtualspace.cpp @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "memory/virtualspace.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -78,10 +80,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address, // Different reserve address may be acceptable in other cases // but for compressed oops heap should be at requested address. assert(UseCompressedOops, "currently requested address used only for compressed oops"); - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); - } + log_debug(gc, heap, coops)("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); // OS ignored requested address. Try different address. if (special) { if (!os::release_memory_special(base, size)) { @@ -143,10 +142,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } } } @@ -286,11 +282,10 @@ void ReservedHeapSpace::establish_noaccess_prefix() { if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE, _special)) { fatal("cannot protect protection page"); } - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Protected page at the reserved heap base: " - PTR_FORMAT " / " INTX_FORMAT " bytes", p2i(_base), _noaccess_prefix); - } + log_debug(gc, heap, coops)("Protected page at the reserved heap base: " + PTR_FORMAT " / " INTX_FORMAT " bytes", + p2i(_base), + _noaccess_prefix); assert(Universe::narrow_oop_use_implicit_null_checks() == true, "not initialized?"); } else { Universe::set_narrow_oop_use_implicit_null_checks(false); @@ -321,10 +316,10 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, bool special = large && !os::can_commit_large_page_memory(); char* base = NULL; - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address " PTR_FORMAT " heap of size " SIZE_FORMAT_HEX ".\n", - p2i(requested_address), size); - } + log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT + " heap of size " SIZE_FORMAT_HEX, + p2i(requested_address), + size); if (special) { base = os::reserve_memory_special(size, alignment, requested_address, false); @@ -343,10 +338,7 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, // Failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } // Optimistically assume that the OSes returns an aligned base pointer. @@ -558,9 +550,7 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Last, desperate try without any placement. if (_base == NULL) { - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX ".\n", size + noaccess_prefix); - } + log_trace(gc, heap, coops)("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX, size + noaccess_prefix); initialize(size + noaccess_prefix, alignment, large, NULL, false); } } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d82452bceeb..67cf5784d0d 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -407,7 +407,9 @@ static AliasedFlag const aliased_jvm_flags[] = { { NULL, NULL} }; +// NOTE: A compatibility request will be necessary for each alias to be removed. static AliasedLoggingFlag const aliased_logging_flags[] = { + { "PrintCompressedOopsMode", LogLevel::Info, true, LOG_TAGS(gc, heap, coops) }, { "TraceBiasedLocking", LogLevel::Info, true, LOG_TAGS(biasedlocking) }, { "TraceClassLoading", LogLevel::Info, true, LOG_TAGS(classload) }, { "TraceClassLoadingPreorder", LogLevel::Debug, true, LOG_TAGS(classload, preorder) }, @@ -2184,15 +2186,11 @@ void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) { if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) { // matches compressed oops printing flags - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - jio_fprintf(defaultStream::error_stream(), - "HeapBaseMinAddress must be at least " SIZE_FORMAT - " (" SIZE_FORMAT "G) which is greater than value given " - SIZE_FORMAT "\n", - DefaultHeapBaseMinAddress, - DefaultHeapBaseMinAddress/G, - HeapBaseMinAddress); - } + log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least " SIZE_FORMAT + " (" SIZE_FORMAT "G) which is greater than value given " SIZE_FORMAT, + DefaultHeapBaseMinAddress, + DefaultHeapBaseMinAddress/G, + HeapBaseMinAddress); FLAG_SET_ERGO(size_t, HeapBaseMinAddress, DefaultHeapBaseMinAddress); } } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 105e02d8be5..12408be3ab9 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -641,9 +641,6 @@ public: "region.") \ range(1, max_uintx) \ \ - diagnostic(bool, PrintCompressedOopsMode, false, \ - "Print compressed oops base address and encoding mode") \ - \ lp64_product(intx, ObjectAlignmentInBytes, 8, \ "Default object alignment in bytes, 8 is minimum") \ range(8, 256) \ diff --git a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java index 54616e4b176..158f2fc90cd 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java +++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,8 +85,7 @@ public class CompressedClassPointers { public static void heapBaseMinAddressTest() throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:HeapBaseMinAddress=1m", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=debug", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("HeapBaseMinAddress must be at least"); diff --git a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java index ac60e764e75..707bf2f4a6e 100644 --- a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java +++ b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,6 @@ public class UseCompressedOops { ArrayList args = new ArrayList<>(); // Always run with these three: - args.add("-XX:+UnlockDiagnosticVMOptions"); args.add("-XX:+PrintCompressedOopsMode"); args.add("-Xms32m"); diff --git a/hotspot/test/runtime/logging/CompressedOopsTest.java b/hotspot/test/runtime/logging/CompressedOopsTest.java new file mode 100644 index 00000000000..fed2233674c --- /dev/null +++ b/hotspot/test/runtime/logging/CompressedOopsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149991 + * @requires (sun.arch.data.model == "64") + * @summary -Xlog:gc+heap+coops=info should have output from the code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver CompressedOopsTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class CompressedOopsTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[gc,heap,coops] Heap address"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[gc,heap,coops]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=off", + InnerClass.class.getName()); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + "-XX:-PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Compressed Oops (gc+heap+coops) test"); + } + } +} From 0d3e7977aebcb1eb717735cb5faf0903c728fdd7 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 7 Apr 2016 16:37:35 -0400 Subject: [PATCH 104/167] 8151939: VM_Version_init() print buffer is too small Increase buffer size, use logging to print out version and os information Reviewed-by: kvn, rprotacio, mockner --- hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp | 41 +++++---- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 46 +++++----- hotspot/src/os/aix/vm/os_aix.cpp | 6 +- hotspot/src/os/bsd/vm/os_bsd.cpp | 24 +----- hotspot/src/os/linux/vm/os_linux.cpp | 32 ++----- hotspot/src/os/solaris/vm/os_solaris.cpp | 40 +++------ hotspot/src/os/windows/vm/os_windows.cpp | 86 +++++-------------- hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp | 6 +- hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp | 20 ++--- .../src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp | 8 +- .../linux_aarch64/vm/os_linux_aarch64.cpp | 8 +- .../src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp | 6 +- .../os_cpu/linux_sparc/vm/os_linux_sparc.cpp | 8 +- .../linux_sparc/vm/vm_version_linux_sparc.cpp | 6 +- .../src/os_cpu/linux_x86/vm/os_linux_x86.cpp | 30 ++----- .../os_cpu/linux_zero/vm/os_linux_zero.cpp | 6 +- .../solaris_sparc/vm/os_solaris_sparc.cpp | 9 +- .../vm/vm_version_solaris_sparc.cpp | 20 ++--- .../os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 21 ++--- hotspot/src/share/vm/logging/log.cpp | 8 +- hotspot/src/share/vm/runtime/vm_version.cpp | 11 +-- .../runtime/logging/OsCpuLoggingTest.java | 64 ++++++++++++++ 22 files changed, 206 insertions(+), 300 deletions(-) create mode 100644 hotspot/test/runtime/logging/OsCpuLoggingTest.java diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 34041ed9943..93c8d40891e 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -368,36 +369,38 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } - if (PrintMiscellaneous && Verbose) { - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); - tty->print("Allocation"); + if (log_is_enabled(Info, os, cpu)) { + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0) { - tty->print_cr(": no prefetching"); + log->print(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCH"); + log->print("PREFETCH"); } else if (AllocatePrefetchInstr == 1) { - tty->print("BIS"); + log->print("BIS"); } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } } @@ -408,7 +411,7 @@ void VM_Version::print_features() { int VM_Version::determine_features() { if (UseV8InstrsOnly) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-V8"); } + log_info(os, cpu)("Version is Forced-V8"); return generic_v8_m; } @@ -416,7 +419,7 @@ int VM_Version::determine_features() { if (features == unknown_m) { features = generic_v9_m; - warning("Cannot recognize SPARC version. Default to V9"); + log_info(os)("Cannot recognize SPARC version. Default to V9"); } assert(is_T_family(features) == is_niagara(features), "Niagara should be T series"); @@ -424,12 +427,12 @@ int VM_Version::determine_features() { if (is_T_family(features)) { // Happy to accomodate... } else { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Niagara"); } + log_info(os, cpu)("Version is Forced-Niagara"); features |= T_family_m; } } else { if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Not-Niagara"); } + log_info(os, cpu)("Version is Forced-Not-Niagara"); features &= ~(T_family_m | T1_model_m); } else { // Happy to accomodate... diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 94c7e156d7e..6d871ce92de 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -1223,59 +1224,60 @@ void VM_Version::get_processor_features() { } #ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("Logical CPUs per core: %u", + if (log_is_enabled(Info, os, cpu)) { + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("Logical CPUs per core: %u", logical_processors_per_package()); - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print("UseSSE=%d", (int) UseSSE); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print("UseSSE=%d", (int) UseSSE); if (UseAVX > 0) { - tty->print(" UseAVX=%d", (int) UseAVX); + log->print(" UseAVX=%d", (int) UseAVX); } if (UseAES) { - tty->print(" UseAES=1"); + log->print(" UseAES=1"); } #ifdef COMPILER2 if (MaxVectorSize > 0) { - tty->print(" MaxVectorSize=%d", (int) MaxVectorSize); + log->print(" MaxVectorSize=%d", (int) MaxVectorSize); } #endif - tty->cr(); - tty->print("Allocation"); + log->cr(); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { - tty->print_cr(": no prefetching"); + log->print_cr(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (UseSSE == 0 && supports_3dnow_prefetch()) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } else if (UseSSE >= 1) { if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCHNTA"); + log->print("PREFETCHNTA"); } else if (AllocatePrefetchInstr == 1) { - tty->print("PREFETCHT0"); + log->print("PREFETCHT0"); } else if (AllocatePrefetchInstr == 2) { - tty->print("PREFETCHT2"); + log->print("PREFETCHT2"); } else if (AllocatePrefetchInstr == 3) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } #endif // !PRODUCT diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 31002c5bd60..22e016b65f2 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -3612,14 +3612,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 getrlimit failed"); + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 setrlimit failed"); + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 9cf4f74d2cf..ce3f6e005fd 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3459,25 +3459,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -3519,9 +3507,7 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; @@ -3534,9 +3520,7 @@ jint os::init_2(void) { status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d8811d46528..228ac835ffb 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2163,7 +2163,7 @@ static bool print_model_name_and_flags(outputStream* st, char* buf, size_t bufle bool model_name_printed = false; if (strstr(buf, "model name") != NULL) { if (!model_name_printed) { - st->print_raw("\nCPU Model and flags from /proc/cpuinfo:\n"); + st->print_raw("CPU Model and flags from /proc/cpuinfo:\n"); st->print_raw(buf); model_name_printed = true; } else { @@ -4671,25 +4671,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -4732,10 +4720,8 @@ jint os::init_2(void) { #endif Linux::libpthread_init(); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[HotSpot is running with %s, %s]\n", - Linux::glibc_version(), Linux::libpthread_version()); - } + log_info(os)("HotSpot is running with %s, %s", + Linux::glibc_version(), Linux::libpthread_version()); if (UseNUMA) { if (!Linux::libnuma_init()) { @@ -4776,16 +4762,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index d64b56a3a5a..68f4a58c30a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -2754,13 +2754,13 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { pd_unmap_memory(addr, bytes); } - if (PrintMiscellaneous && Verbose) { + if (log_is_enabled(Warning, os)) { char buf[256]; buf[0] = '\0'; if (addr == NULL) { jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err)); } - warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " + log_info(os)("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT "%s", bytes, requested_addr, addr, buf); } @@ -2790,9 +2790,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { assert(i > 0, "gap adjustment code problem"); have_adjusted_gap = true; // adjust the gap only once, just in case gap = actual_gap; - if (PrintMiscellaneous && Verbose) { - warning("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); - } + log_info(os)("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); unmap_memory(base[i], bytes); unmap_memory(base[i-1], size[i-1]); i-=2; @@ -2824,8 +2822,8 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { } else { size_t bottom_overlap = base[i] + bytes - requested_addr; if (bottom_overlap >= 0 && bottom_overlap < bytes) { - if (PrintMiscellaneous && Verbose && bottom_overlap == 0) { - warning("attempt_reserve_memory_at: possible alignment bug"); + if (bottom_overlap == 0) { + log_info(os)("attempt_reserve_memory_at: possible alignment bug"); } unmap_memory(requested_addr, bottom_overlap); size[i] = bytes - bottom_overlap; @@ -4355,8 +4353,8 @@ static pset_getloadavg_type pset_getloadavg_ptr = NULL; void init_pset_getloadavg_ptr(void) { pset_getloadavg_ptr = (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg"); - if (PrintMiscellaneous && Verbose && pset_getloadavg_ptr == NULL) { - warning("pset_getloadavg function not found"); + if (pset_getloadavg_ptr == NULL) { + log_warning(os)("pset_getloadavg function not found"); } } @@ -4439,25 +4437,13 @@ jint os::init_2(void) { } os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)Solaris::mmap_chunk(NULL, page_size, MAP_PRIVATE, PROT_READ | PROT_WRITE); guarantee(mem_serialize_page != NULL, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Check minimum allowable stack size for thread creation and to initialize @@ -4537,16 +4523,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index f85eb0f273c..53e4528c0cc 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2436,14 +2436,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s", addr, - page_start, (res ? "success" : os::strerror(errno))); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s", p2i(addr), + p2i(page_start), (res ? "success" : os::strerror(errno))); // Set last_addr so if we fault again at the same address, we don't // end up in an endless loop. @@ -2896,12 +2892,12 @@ static bool numa_interleaving_init() { NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity); if (numa_node_list_holder.build()) { - if (PrintMiscellaneous && Verbose) { - tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); + if (log_is_enabled(Debug, os, cpu)) { + Log(os, cpu) log; + log.debug("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); for (int i = 0; i < numa_node_list_holder.get_count(); i++) { - tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); + log.debug(" %d ", numa_node_list_holder.get_node_list_entry(i)); } - tty->print("\n"); } success = true; } else { @@ -4119,13 +4115,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); @@ -4135,13 +4125,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Setup Windows Exceptions @@ -4769,10 +4753,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFile() failed: GetLastError->%ld.", GetLastError()); return NULL; } @@ -4790,10 +4771,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*) VirtualAlloc(addr, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualAlloc() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualAlloc() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4807,10 +4785,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, // number of bytes were read before returning. bool res = ReadFile(hFile, base, (DWORD)bytes, &bytes_read, &overlapped) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("ReadFile() failed: GetLastError->%ld.", err); - } + log_info(os)("ReadFile() failed: GetLastError->%ld.", GetLastError()); release_memory(base, bytes); CloseHandle(hFile); return NULL; @@ -4819,10 +4794,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL /* file_name */); if (hMap == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFileMapping() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4831,20 +4803,14 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*)MapViewOfFileEx(hMap, access, 0, (DWORD)file_offset, (DWORD)bytes, addr); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("MapViewOfFileEx() failed: GetLastError->%ld.", err); - } + log_info(os)("MapViewOfFileEx() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hMap); CloseHandle(hFile); return NULL; } if (CloseHandle(hMap) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hMap) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hMap) failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return base; } @@ -4856,10 +4822,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, bool res = VirtualProtect(base, bytes, exec_access, &old_protect) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualProtect() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualProtect() failed: GetLastError->%ld.", GetLastError()); // Don't consider this a hard error, on IA32 even if the // VirtualProtect fails, we should still be able to execute CloseHandle(hFile); @@ -4868,10 +4831,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, } if (CloseHandle(hFile) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hFile) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hFile) failed: GetLastError->%ld.", GetLastError()); return base; } @@ -4904,10 +4864,7 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, bool os::pd_unmap_memory(char* addr, size_t bytes) { MEMORY_BASIC_INFORMATION mem_info; if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualQuery() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualQuery() failed: GetLastError->%ld.", GetLastError()); return false; } @@ -4924,10 +4881,7 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) { BOOL result = UnmapViewOfFile(addr); if (result == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("UnmapViewOfFile() failed: GetLastError->%ld.", err); - } + log_info(os)("UnmapViewOfFile() failed: GetLastError->%ld.", GetLastError()); return false; } return true; diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index f109a111047..537595f95ad 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -184,9 +184,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec if (os::Aix::chained_handler(sig, info, ucVoid)) { return 1; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return 1; } } diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index f8e7dc509b9..73acdebfb47 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -469,11 +469,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -728,14 +724,10 @@ JVM_handle_bsd_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp index c3801dfab64..72d57858e09 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -159,11 +159,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp index 4e47e27628f..2a354fbb72c 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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. * @@ -270,11 +270,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index b7318c22c08..117bf1067f3 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -198,9 +198,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 30b321dc228..44a5a7df1f9 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,11 +561,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp index f9c596e4d79..c6bb5033db6 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,12 +66,12 @@ int VM_Version::platform_features(int features) { features = generic_v9_m; if (detect_niagara()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on Niagara"); } + log_info(os, cpu)("Detected Linux on Niagara"); features = niagara1_m | T_family_m; } if (detect_M_family()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on M family"); } + log_info(os, cpu)("Detected Linux on M family"); features = sun4v_m | generic_v9_m | M_family_m | T_family_m; } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index ec6ba97235a..0eb7a9e511f 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,11 +287,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -542,14 +538,10 @@ JVM_handle_linux_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end @@ -645,12 +637,8 @@ bool os::supports_sse() { int major = strtol(uts.release,&minor_string,10); int minor = strtol(minor_string+1,NULL,10); bool result = (major > 2 || (major==2 && minor >= 4)); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("OS version is %d.%d, which %s support SSE/SSE2\n", + log_info(os)("OS version is %d.%d, which %s support SSE/SSE2", major,minor, result ? "DOES" : "does NOT"); - } -#endif return result; #endif // AMD64 } @@ -939,9 +927,7 @@ void os::workaround_expand_exec_shield_cs_limit() { MemTracker::record_virtual_memory_type((address)codebuf, mtInternal); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[CS limit NX emulation work-around, exec code at: %p]", codebuf); - } + log_info(os)("[CS limit NX emulation work-around, exec code at: %p]", codebuf); // Some code to exec: the 'ret' instruction codebuf[0] = 0xC3; diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index b1e93a82dc8..abd52961976 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -154,11 +154,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index 5fd0e0a78af..da39ee79790 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,12 +338,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 837607e6781..def37cd0b63 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "runtime/os.hpp" @@ -361,15 +362,10 @@ int VM_Version::platform_features(int features) { assert(avn <= 2, "should return two or less av's"); uint_t av = avs[0]; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("getisax(2) returned: " PTR32_FORMAT, av); - if (avn > 1) { - tty->print(", " PTR32_FORMAT, avs[1]); - } - tty->cr(); + log_info(os, cpu)("getisax(2) returned: " PTR32_FORMAT, av); + if (avn > 1) { + log_info(os, cpu)(" " PTR32_FORMAT, avs[1]); } -#endif if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; if (av & AV_SPARC_DIV32) features |= hardware_div32_m; @@ -464,11 +460,7 @@ int VM_Version::platform_features(int features) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); has_implementation = true; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("cpu_info.implementation: %s", implementation); - } -#endif + log_info(os, cpu)("cpu_info.implementation: %s", implementation); features |= parse_features(implementation); break; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 79a7f19a281..0784f3f25f7 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -403,12 +403,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -640,14 +635,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 3d676219d89..6c6566b386e 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -377,7 +377,7 @@ void Test_loghandle_on() { assert(log_handle.is_debug(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.debug("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -408,7 +408,7 @@ void Test_loghandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.debug("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. @@ -440,7 +440,7 @@ static void Test_logtargethandle_on() { assert(log_handle.is_enabled(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.print("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -471,7 +471,7 @@ static void Test_logtargethandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.print("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index cf2bf5a4644..c36098a31f7 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" @@ -274,12 +275,12 @@ unsigned int Abstract_VM_Version::jvm_version() { void VM_Version_init() { VM_Version::initialize(); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - char buf[512]; - os::print_cpu_info(tty, buf, sizeof(buf)); + if (log_is_enabled(Info, os, cpu)) { + char buf[1024]; + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + os::print_cpu_info(log, buf, sizeof(buf)); } -#endif } unsigned int Abstract_VM_Version::nof_parallel_worker_threads( diff --git a/hotspot/test/runtime/logging/OsCpuLoggingTest.java b/hotspot/test/runtime/logging/OsCpuLoggingTest.java new file mode 100644 index 00000000000..ab23e194f8f --- /dev/null +++ b/hotspot/test/runtime/logging/OsCpuLoggingTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8151939 + * @summary os+cpu output should contain some os,cpu information + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver OsCpuLoggingTest + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.*; + +public class OsCpuLoggingTest { + + static void analyzeOutputForOsLog(OutputAnalyzer output) throws Exception { + // Aix has it's own logging + if (!Platform.isAix()) { + output.shouldContain("SafePoint Polling address"); + } + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForOsCpuLog(OutputAnalyzer output) throws Exception { + output.shouldContain("CPU:total"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+cpu", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsCpuLog(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsLog(output); + } +} From 10c7cac93e527336865caa6398572766487a22d4 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Thu, 7 Apr 2016 15:33:25 -0700 Subject: [PATCH 105/167] 8152180: SIGFPE in CMSCollector::preclean with big CMSScheduleRemarkSamplingRatio Rephrased the calculation routine to avoid an overflow for CMSScheduleRemarkSamplingRatio Reviewed-by: jwilhelm, drwhite --- hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 42fd21dc65d..1e7a4991dd3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -3598,7 +3598,7 @@ void CMSCollector::preclean() { size_t capacity = get_eden_capacity(); // Don't start sampling unless we will get sufficiently // many samples. - if (used < (capacity/(CMSScheduleRemarkSamplingRatio * 100) + if (used < (((capacity / CMSScheduleRemarkSamplingRatio) / 100) * CMSScheduleRemarkEdenPenetration)) { _start_sampling = true; } else { From 25f35cda7d82c3c1fd3d0b4470806e48cd6dca99 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Thu, 7 Apr 2016 15:34:21 -0700 Subject: [PATCH 106/167] 8152182: Possible overflow in initialzation of _rescan_task_size and _marking_task_size Add constraints for CMSRescanMultiple and CMSConcMarkMultiple flags Reviewed-by: jwilhelm, jmasa --- .../vm/gc/cms/compactibleFreeListSpace.cpp | 5 +++ .../vm/gc/cms/compactibleFreeListSpace.hpp | 2 + .../runtime/commandLineFlagConstraintsGC.cpp | 45 +++++++++++++++++++ .../runtime/commandLineFlagConstraintsGC.hpp | 2 + hotspot/src/share/vm/runtime/globals.hpp | 8 +++- 5 files changed, 60 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index ac9d84e5d12..c048f08b4a1 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -2836,6 +2836,11 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n par_get_chunk_of_blocks_dictionary(word_sz, n, fl); } +const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { + const size_t ergo_max = _old_gen->reserved().word_size() / (CardTableModRefBS::card_size_in_words * BitsPerWord); + return ergo_max; +} + // Set up the space's par_seq_tasks structure for work claiming // for parallel rescan. See CMSParRemarkTask where this is currently used. // XXX Need to suitably abstract and generalize this and the next diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index eeaa07ce280..92a2764afd0 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -345,6 +345,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Support for parallelization of rescan and marking. const size_t rescan_task_size() const { return _rescan_task_size; } const size_t marking_task_size() const { return _marking_task_size; } + // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. + const size_t max_flag_size_for_task_size() const; SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } void initialize_sequential_subtasks_for_rescan(int n_threads); void initialize_sequential_subtasks_for_marking(int n_threads, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp index 4390644d708..5dce24113af 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp @@ -457,6 +457,51 @@ Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) { } } +static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) { +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen(); + const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size(); + if (value > ergo_max) { + CommandLineError::print(verbose, + "%s (" SIZE_FORMAT ") must be " + "less than or equal to ergonomic maximum (" SIZE_FORMAT ") " + "which is based on the maximum size of the old generation of the Java heap\n", + name, value, ergo_max); + return Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return Flag::SUCCESS; +} + +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) { + Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose); + +#if INCLUDE_ALL_GCS + if (status == Flag::SUCCESS && UseConcMarkSweepGC) { + // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size() + // to be aligned to CardTableModRefBS::card_size * BitsPerWord. + // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize' + // because rescan_task_size() is CardTableModRefBS::card_size / HeapWordSize * BitsPerWord. + if (value % HeapWordSize != 0) { + CommandLineError::print(verbose, + "CMSRescanMultiple (" SIZE_FORMAT ") must be " + "a multiple of " SIZE_FORMAT "\n", + value, HeapWordSize); + status = Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return status; +} + +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) { + return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose); +} + Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp index ee8bf3f668b..9470a1c4ec4 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp @@ -60,6 +60,8 @@ Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose); Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose); Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose); Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose); +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose); +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose); Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose); Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose); Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index be97e61c9b0..49e24ed385a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1806,13 +1806,17 @@ public: "enough work per iteration") \ range(0, max_intx) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSRescanMultiple, 32, \ "Size (in cards) of CMS parallel rescan task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSConcMarkMultiple, 32, \ "Size (in cards) of CMS concurrent MT marking task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit) \ \ product(bool, CMSAbortSemantics, false, \ "Whether abort-on-overflow semantics is implemented") \ From 2d2abce433c95b7edaf3e77b1a337650007750c1 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Fri, 8 Apr 2016 12:26:29 -0700 Subject: [PATCH 107/167] 8153123: Streamline StackWalker code Reviewed-by: coleenp, dfuchs, mchung, redestad --- hotspot/make/share/makefiles/mapfile-vers | 3 +- hotspot/makefiles/symbols/symbols-unix | 3 +- .../src/share/vm/classfile/javaClasses.cpp | 110 +++------------- .../src/share/vm/classfile/javaClasses.hpp | 22 +--- hotspot/src/share/vm/prims/jvm.cpp | 62 +++------ hotspot/src/share/vm/prims/jvm.h | 11 +- hotspot/src/share/vm/prims/stackwalk.cpp | 120 +++++++----------- hotspot/src/share/vm/prims/stackwalk.hpp | 19 ++- hotspot/src/share/vm/runtime/globals.hpp | 3 - 9 files changed, 91 insertions(+), 262 deletions(-) diff --git a/hotspot/make/share/makefiles/mapfile-vers b/hotspot/make/share/makefiles/mapfile-vers index a937f93b84c..f7d08e50b98 100644 --- a/hotspot/make/share/makefiles/mapfile-vers +++ b/hotspot/make/share/makefiles/mapfile-vers @@ -41,7 +41,6 @@ JVM_DumpAllStacks; JVM_DumpThreads; JVM_FillInStackTrace; - JVM_FillStackFrames; JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromBootLoader; @@ -157,13 +156,13 @@ JVM_SetClassSigners; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetMethodInfo; JVM_SetThreadPriority; JVM_Sleep; JVM_StartThread; JVM_StopThread; JVM_SuspendThread; JVM_SupportsCX8; + JVM_ToStackTraceElement; JVM_TotalMemory; JVM_UnloadLibrary; JVM_Yield; diff --git a/hotspot/makefiles/symbols/symbols-unix b/hotspot/makefiles/symbols/symbols-unix index 5d876710e65..406d6f99db3 100644 --- a/hotspot/makefiles/symbols/symbols-unix +++ b/hotspot/makefiles/symbols/symbols-unix @@ -58,7 +58,6 @@ JVM_DoPrivileged JVM_DumpAllStacks JVM_DumpThreads JVM_FillInStackTrace -JVM_FillStackFrames JVM_FindClassFromCaller JVM_FindClassFromClass JVM_FindLibraryEntry @@ -169,7 +168,6 @@ JVM_ReleaseUTF JVM_ResumeThread JVM_SetArrayElement JVM_SetClassSigners -JVM_SetMethodInfo JVM_SetNativeThreadName JVM_SetPrimitiveArrayElement JVM_SetThreadPriority @@ -178,6 +176,7 @@ JVM_StartThread JVM_StopThread JVM_SupportsCX8 JVM_SuspendThread +JVM_ToStackTraceElement JVM_TotalMemory JVM_UnloadLibrary JVM_Yield diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index f61e466e8f2..5365e1df8d6 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2187,43 +2187,19 @@ void java_lang_StackTraceElement::fill_in(Handle element, } Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { - if (MemberNameInStackFrame) { - Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); - Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); - // we should expand MemberName::name when Throwable uses StackTrace - // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); - return method; - } else { - short mid = stackFrame->short_field(_mid_offset); - short version = stackFrame->short_field(_version_offset); - return holder->method_with_orig_idnum(mid, version); - } -} - -Symbol* java_lang_StackFrameInfo::get_file_name(Handle stackFrame, InstanceKlass* holder) { - if (MemberNameInStackFrame) { - return holder->source_file_name(); - } else { - short version = stackFrame->short_field(_version_offset); - return Backtrace::get_source_file_name(holder, version); - } + Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); + Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); + // we should expand MemberName::name when Throwable uses StackTrace + // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); + return method; } void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) { // set Method* or mid/cpref - if (MemberNameInStackFrame) { - oop mname = stackFrame->obj_field(_memberName_offset); - InstanceKlass* ik = method->method_holder(); - CallInfo info(method(), ik); - MethodHandles::init_method_MemberName(mname, info); - } else { - int mid = method->orig_method_idnum(); - int cpref = method->name_index(); - assert((jushort)mid == mid, "mid should be short"); - assert((jushort)cpref == cpref, "cpref should be short"); - java_lang_StackFrameInfo::set_mid(stackFrame(), (short)mid); - java_lang_StackFrameInfo::set_cpref(stackFrame(), (short)cpref); - } + oop mname = stackFrame->obj_field(_memberName_offset); + InstanceKlass* ik = method->method_holder(); + CallInfo info(method(), ik); + MethodHandles::init_method_MemberName(mname, info); // set bci java_lang_StackFrameInfo::set_bci(stackFrame(), bci); // method may be redefined; store the version @@ -2232,52 +2208,23 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho java_lang_StackFrameInfo::set_version(stackFrame(), (short)version); } -void java_lang_StackFrameInfo::fill_methodInfo(Handle stackFrame, TRAPS) { +void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) { ResourceMark rm(THREAD); - oop k = stackFrame->obj_field(_declaringClass_offset); - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k)); + Handle k (THREAD, stackFrame->obj_field(_declaringClass_offset)); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k())); Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); - int bci = stackFrame->int_field(_bci_offset); - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : NULL; - if (MemberNameInStackFrame) { - assert(sym != NULL, "MemberName must have method name"); - } else { - // The method can be NULL if the requested class version is gone - if (sym == NULL) { - short cpref = stackFrame->short_field(_cpref_offset); - sym = holder->constants()->symbol_at(cpref); - } - } - - // set method name - oop methodname = StringTable::intern(sym, CHECK); - java_lang_StackFrameInfo::set_methodName(stackFrame(), methodname); - - // set file name and line number - Symbol* source = get_file_name(stackFrame, holder); - if (source != NULL) { - oop filename = StringTable::intern(source, CHECK); - java_lang_StackFrameInfo::set_fileName(stackFrame(), filename); - } - - // if the method has been redefined, the bci is no longer applicable short version = stackFrame->short_field(_version_offset); - if (version_matches(method, version)) { - int line_number = Backtrace::get_line_number(method, bci); - java_lang_StackFrameInfo::set_lineNumber(stackFrame(), line_number); - } + short bci = stackFrame->short_field(_bci_offset); + int cpref = method->name_index(); + java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK); } void java_lang_StackFrameInfo::compute_offsets() { Klass* k = SystemDictionary::StackFrameInfo_klass(); compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature()); compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature()); - compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::int_signature()); - compute_offset(_methodName_offset, k, vmSymbols::methodName_name(), vmSymbols::string_signature()); - compute_offset(_fileName_offset, k, vmSymbols::fileName_name(), vmSymbols::string_signature()); - compute_offset(_lineNumber_offset, k, vmSymbols::lineNumber_name(), vmSymbols::int_signature()); + compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature()); STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } @@ -3690,12 +3637,7 @@ int java_lang_StackTraceElement::moduleVersion_offset; int java_lang_StackFrameInfo::_declaringClass_offset; int java_lang_StackFrameInfo::_memberName_offset; int java_lang_StackFrameInfo::_bci_offset; -int java_lang_StackFrameInfo::_methodName_offset; -int java_lang_StackFrameInfo::_fileName_offset; -int java_lang_StackFrameInfo::_lineNumber_offset; -int java_lang_StackFrameInfo::_mid_offset; int java_lang_StackFrameInfo::_version_offset; -int java_lang_StackFrameInfo::_cpref_offset; int java_lang_LiveStackFrameInfo::_monitors_offset; int java_lang_LiveStackFrameInfo::_locals_offset; int java_lang_LiveStackFrameInfo::_operands_offset; @@ -3741,34 +3683,14 @@ void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) { element->obj_field_put(_declaringClass_offset, value); } -void java_lang_StackFrameInfo::set_mid(oop element, short value) { - element->short_field_put(_mid_offset, value); -} - void java_lang_StackFrameInfo::set_version(oop element, short value) { element->short_field_put(_version_offset, value); } -void java_lang_StackFrameInfo::set_cpref(oop element, short value) { - element->short_field_put(_cpref_offset, value); -} - void java_lang_StackFrameInfo::set_bci(oop element, int value) { element->int_field_put(_bci_offset, value); } -void java_lang_StackFrameInfo::set_fileName(oop element, oop value) { - element->obj_field_put(_fileName_offset, value); -} - -void java_lang_StackFrameInfo::set_methodName(oop element, oop value) { - element->obj_field_put(_methodName_offset, value); -} - -void java_lang_StackFrameInfo::set_lineNumber(oop element, int value) { - element->int_field_put(_lineNumber_offset, value); -} - void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) { element->obj_field_put(_monitors_offset, value); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 560bab7d5f8..4ff32acd6c1 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1364,25 +1364,16 @@ class Backtrace: AllStatic { // Interface to java.lang.StackFrameInfo objects #define STACKFRAMEINFO_INJECTED_FIELDS(macro) \ - macro(java_lang_StackFrameInfo, mid, short_signature, false) \ - macro(java_lang_StackFrameInfo, version, short_signature, false) \ - macro(java_lang_StackFrameInfo, cpref, short_signature, false) + macro(java_lang_StackFrameInfo, version, short_signature, false) class java_lang_StackFrameInfo: AllStatic { private: static int _declaringClass_offset; static int _memberName_offset; static int _bci_offset; - static int _methodName_offset; - static int _fileName_offset; - static int _lineNumber_offset; - - static int _mid_offset; static int _version_offset; - static int _cpref_offset; static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS); - static Symbol* get_file_name(Handle stackFrame, InstanceKlass* holder); public: // Setters @@ -1390,19 +1381,12 @@ public: static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci); static void set_bci(oop info, int value); - // set method info in an instance of StackFrameInfo - static void fill_methodInfo(Handle info, TRAPS); - static void set_methodName(oop info, oop value); - static void set_fileName(oop info, oop value); - static void set_lineNumber(oop info, int value); - - // these injected fields are only used if -XX:-MemberNameInStackFrame set - static void set_mid(oop info, short value); static void set_version(oop info, short value); - static void set_cpref(oop info, short value); static void compute_offsets(); + static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS); + // Debugging friend class JavaClasses; }; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7665065c9df..2bf88e40b22 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -534,7 +534,6 @@ JVM_END JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_CallStackWalk"); JavaThread* jt = (JavaThread*) THREAD; @@ -543,78 +542,51 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index + frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL); } Handle result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, - start_index, classes_array_h, - frames_array_h, CHECK_NULL); + start_index, frames_array_h, CHECK_NULL); return JNIHandles::make_local(env, result()); JVM_END JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_MoreStackWalk"); JavaThread* jt = (JavaThread*) THREAD; - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index+frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers"); } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count, - start_index, classes_array_h, - frames_array_h, THREAD); + start_index, frames_array_h, THREAD); JVM_END -JVM_ENTRY(void, JVM_FillStackFrames(JNIEnv *env, jclass stackStream, - jint start_index, - jobjectArray frames, - jint from_index, jint to_index)) - JVMWrapper("JVM_FillStackFrames"); - if (TraceStackWalk) { - tty->print("JVM_FillStackFrames() start_index=%d from_index=%d to_index=%d\n", - start_index, from_index, to_index); - } - - JavaThread* jt = (JavaThread*) THREAD; - - objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); - objArrayHandle frames_array_h(THREAD, fa); - - if (frames_array_h->length() < to_index) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array length not matched"); - } - - for (int i = from_index; i < to_index; i++) { - Handle stackFrame(THREAD, frames_array_h->obj_at(i)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, CHECK); - } -JVM_END - -JVM_ENTRY(void, JVM_SetMethodInfo(JNIEnv *env, jobject frame)) - JVMWrapper("JVM_SetMethodInfo"); - Handle stackFrame(THREAD, JNIHandles::resolve(frame)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, THREAD); +JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack)) + JVMWrapper("JVM_ToStackTraceElement"); + Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame)); + Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack)); + java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); JVM_END // java.lang.Object /////////////////////////////////////////////// diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index dafc3955101..5a055995d1c 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -209,7 +209,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements) */ enum { JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2, - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10, JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20, JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100 }; @@ -217,23 +216,15 @@ enum { JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT jint JNICALL JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT void JNICALL -JVM_FillStackFrames(JNIEnv* env, jclass cls, - jint start_index, - jobjectArray frames, - jint from_index, jint toIndex); - -JNIEXPORT void JNICALL -JVM_SetMethodInfo(JNIEnv* env, jobject frame); +JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); /* * java.lang.Thread diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index 3e292641a79..d772620dcf5 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -37,22 +37,22 @@ #include "utilities/globalDefinitions.hpp" // setup and cleanup actions -void StackWalkAnchor::setup_magic_on_entry(objArrayHandle classes_array) { - classes_array->obj_at_put(magic_pos, _thread->threadObj()); +void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) { + frames_array->obj_at_put(magic_pos, _thread->threadObj()); _anchor = address_value(); - assert(check_magic(classes_array), "invalid magic"); + assert(check_magic(frames_array), "invalid magic"); } -bool StackWalkAnchor::check_magic(objArrayHandle classes_array) { - oop m1 = classes_array->obj_at(magic_pos); +bool StackWalkAnchor::check_magic(objArrayHandle frames_array) { + oop m1 = frames_array->obj_at(magic_pos); jlong m2 = _anchor; if (m1 == _thread->threadObj() && m2 == address_value()) return true; return false; } -bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { - bool ok = check_magic(classes_array); - classes_array->obj_at_put(magic_pos, NULL); +bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) { + bool ok = check_magic(frames_array); + frames_array->obj_at_put(magic_pos, NULL); _anchor = 0L; return ok; } @@ -62,18 +62,18 @@ bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { // Parameters: // thread Current Java thread. // magic Magic value used for each stack walking -// classes_array User-supplied buffers. The 0th element is reserved +// frames_array User-supplied buffers. The 0th element is reserved // to this StackWalkAnchor to use // StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, - objArrayHandle classes_array) + objArrayHandle frames_array) { assert(thread != NULL && thread->is_Java_thread(), ""); - oop m1 = classes_array->obj_at(magic_pos); + oop m1 = frames_array->obj_at(magic_pos); if (m1 != thread->threadObj()) return NULL; if (magic == 0L) return NULL; StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic; - if (!anchor->is_valid_in(thread, classes_array)) return NULL; + if (!anchor->is_valid_in(thread, frames_array)) return NULL; return anchor; } @@ -88,24 +88,24 @@ StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, // vfst vFrameStream. // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. -// frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames_array Buffer to store Class or StackFrame in, starting at start_index. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS) { if (TraceStackWalk) { tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d", - max_nframes, start_index, classes_array->length()); + max_nframes, start_index, frames_array->length()); } assert(max_nframes > 0, "invalid max_nframes"); - assert(start_index + max_nframes <= classes_array->length(), "oob"); + assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !vfst.at_end(); vfst.next()) { @@ -129,14 +129,18 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, tty->print_cr(" bci=%d", bci); } - classes_array->obj_at_put(index, method->method_holder()->java_mirror()); // fill in StackFrameInfo and initialize MemberName if (live_frame_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get live frame"); Handle stackFrame(frames_array->obj_at(index)); fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0); } else if (need_method_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get stack frame"); Handle stackFrame(frames_array->obj_at(index)); fill_stackframe(stackFrame, method, bci); + } else { + assert (use_frames_array(mode) == false, "Bad mode for get caller class"); + frames_array->obj_at_put(index, method->method_holder()->java_mirror()); } if (++frames_decoded >= max_nframes) break; } @@ -279,15 +283,15 @@ void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& meth // skip_frames Number of frames to be skipped. // frame_count Number of frames to be traversed. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // // Returns Object returned from AbstractStackWalker::doStackWalk call. // oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; @@ -296,10 +300,8 @@ oop StackWalk::walk(Handle stackStream, jlong mode, mode, skip_frames, frame_count); } - if (need_method_info(mode)) { - if (frames_array.is_null()) { - THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); - } + if (frames_array.is_null()) { + THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); @@ -313,48 +315,17 @@ oop StackWalk::walk(Handle stackStream, jlong mode, vframeStream& vfst = anchor.vframe_stream(); { - // Skip all methods from AbstractStackWalker and StackWalk (enclosing method) - if (!fill_in_stacktrace(mode)) { - while (!vfst.at_end()) { - InstanceKlass* ik = vfst.method()->method_holder(); - if (ik != stackWalker_klass && - ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { - break; - } - - if (TraceStackWalk) { - tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + while (!vfst.at_end()) { + InstanceKlass* ik = vfst.method()->method_holder(); + if (ik != stackWalker_klass && + ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { + break; } - } - // For exceptions, skip Throwable::fillInStackTrace and methods - // of the exception class and superclasses - if (fill_in_stacktrace(mode)) { - bool skip_to_fillInStackTrace = false; - bool skip_throwableInit_check = false; - while (!vfst.at_end() && !skip_throwableInit_check) { - InstanceKlass* ik = vfst.method()->method_holder(); - Method* method = vfst.method(); - if (!skip_to_fillInStackTrace) { - if (ik == SystemDictionary::Throwable_klass() && - method->name() == vmSymbols::fillInStackTrace_name()) { - // this frame will be skipped - skip_to_fillInStackTrace = true; - } - } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) && - method->name() == vmSymbols::object_initializer_name())) { - // there are none or we've seen them all - either way stop checking - skip_throwableInit_check = true; - break; - } - - if (TraceStackWalk) { - tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + if (TraceStackWalk) { + tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); } + vfst.next(); } // stack frame has been traversed individually and resume stack walk @@ -372,7 +343,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode, int end_index = start_index; int numFrames = 0; if (!vfst.at_end()) { - numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + numFrames = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); @@ -392,12 +363,12 @@ oop StackWalk::walk(Handle stackStream, jlong mode, args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object - anchor.setup_magic_on_entry(classes_array); + anchor.setup_magic_on_entry(frames_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects - bool ok = anchor.cleanup_magic_on_exit(classes_array); + bool ok = anchor.cleanup_magic_on_exit(frames_array); // Throw pending exception if we must (void) (CHECK_NULL); @@ -419,31 +390,28 @@ oop StackWalk::walk(Handle stackStream, jlong mode, // magic Must be valid value to continue the stack walk // frame_count Number of frames to be decoded. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. // // Returns the end index of frame filled in the buffer. // jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; - StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array); + StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array); if (existing_anchor == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } - if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) { + if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L); } if (TraceStackWalk) { tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d", - frame_count, p2i(existing_anchor), start_index, classes_array->length()); + frame_count, p2i(existing_anchor), start_index, frames_array->length()); } int end_index = start_index; if (frame_count <= 0) { @@ -451,14 +419,14 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, } int count = frame_count + start_index; - assert (classes_array->length() >= count, "not enough space in buffers"); + assert (frames_array->length() >= count, "not enough space in buffers"); StackWalkAnchor& anchor = (*existing_anchor); vframeStream& vfst = anchor.vframe_stream(); if (!vfst.at_end()) { vfst.next(); // this was the last frame decoded in the previous batch if (!vfst.at_end()) { - int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + int n = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_0); if (n < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); diff --git a/hotspot/src/share/vm/prims/stackwalk.hpp b/hotspot/src/share/vm/prims/stackwalk.hpp index 1fa906815be..2eb41aeb711 100644 --- a/hotspot/src/share/vm/prims/stackwalk.hpp +++ b/hotspot/src/share/vm/prims/stackwalk.hpp @@ -45,12 +45,12 @@ public: vframeStream& vframe_stream() { return _vfst; } JavaThread* thread() { return _thread; } - void setup_magic_on_entry(objArrayHandle classes_array); - bool check_magic(objArrayHandle classes_array); - bool cleanup_magic_on_exit(objArrayHandle classes_array); + void setup_magic_on_entry(objArrayHandle frames_array); + bool check_magic(objArrayHandle frames_array); + bool cleanup_magic_on_exit(objArrayHandle frames_array); - bool is_valid_in(Thread* thread, objArrayHandle classes_array) { - return (_thread == thread && check_magic(classes_array)); + bool is_valid_in(Thread* thread, objArrayHandle frames_array) { + return (_thread == thread && check_magic(frames_array)); } jlong address_value() { @@ -64,7 +64,6 @@ class StackWalk : public AllStatic { private: static int fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS); @@ -82,20 +81,18 @@ private: static inline bool live_frame_info(int mode) { return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0; } - static inline bool fill_in_stacktrace(int mode) { - return (mode & JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE) != 0; - } public: + static inline bool use_frames_array(int mode) { + return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; + } static oop walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); static jint moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); }; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 49e24ed385a..044e26e3ccf 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2958,9 +2958,6 @@ public: develop(bool, TraceStackWalk, false, \ "Trace stack walking") \ \ - product(bool, MemberNameInStackFrame, true, \ - "Use MemberName in StackFrame") \ - \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ NOT_EMBEDDED(diagnostic(intx, GuaranteedSafepointInterval, 1000, \ From 28edd79d641a53032589868b3a6ee9441a7b8966 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Thu, 7 Apr 2016 22:03:04 -0700 Subject: [PATCH 108/167] 8145221: Use trampolines for i2i and i2c entries in Methods that are stored in CDS archive This optimization reduces the size of the RW region of the CDS archive. It also reduces the amount of pages in the RW region that are actually written into during runtime. Co-authored-by: Ioi Lam Co-authored-by: Goetz Lindenmaier Reviewed-by: dlong, iklam, jiangli --- .../cpu/aarch64/vm/sharedRuntime_aarch64.cpp | 10 +++ hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp | 12 +++ .../cpu/sparc/vm/metaspaceShared_sparc.cpp | 2 - .../src/cpu/sparc/vm/sharedRuntime_sparc.cpp | 10 +++ .../src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 8 ++ .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 8 ++ .../src/cpu/zero/vm/sharedRuntime_zero.cpp | 9 ++ .../src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp | 9 ++ .../linux_aarch64/vm/thread_linux_aarch64.cpp | 9 ++ .../linux_sparc/vm/thread_linux_sparc.cpp | 9 ++ .../os_cpu/linux_x86/vm/thread_linux_x86.cpp | 9 ++ .../solaris_sparc/vm/thread_solaris_sparc.cpp | 9 ++ .../solaris_x86/vm/thread_solaris_x86.cpp | 9 ++ .../windows_x86/vm/thread_windows_x86.cpp | 9 ++ .../vm/interpreter/abstractInterpreter.cpp | 33 ++++++- .../vm/interpreter/abstractInterpreter.hpp | 12 +++ .../templateInterpreterGenerator.cpp | 1 + hotspot/src/share/vm/memory/filemap.cpp | 10 +++ hotspot/src/share/vm/memory/filemap.hpp | 16 ++++ .../src/share/vm/memory/metaspaceShared.cpp | 30 ++++++- .../src/share/vm/memory/metaspaceShared.hpp | 25 ++++-- hotspot/src/share/vm/oops/constMethod.hpp | 30 +++++++ hotspot/src/share/vm/oops/method.cpp | 85 +++++++++++++------ hotspot/src/share/vm/oops/method.hpp | 29 +++++-- .../src/share/vm/runtime/sharedRuntime.cpp | 45 +++++++++- .../src/share/vm/runtime/sharedRuntime.hpp | 16 ++++ hotspot/src/share/vm/runtime/vmStructs.cpp | 1 - 27 files changed, 408 insertions(+), 47 deletions(-) diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index 0aeba4cb33c..760256da378 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -198,6 +198,16 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { bool SharedRuntime::is_wide_vector(int size) { return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ mov(rscratch1, destination); + __ br(rscratch1); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index 49df282945d..ee8685f4f0a 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -483,6 +483,18 @@ bool SharedRuntime::is_wide_vector(int size) { assert(size <= 8, "%d bytes vectors are not supported", size); return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return Assembler::load_const_size + 8; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + Register Rtemp = R12; + __ load_const(Rtemp, destination); + __ mtctr(Rtemp); + __ bctr(); +} + #ifdef COMPILER2 static int reg2slot(VMReg r) { return r->reg2stack() + SharedRuntime::out_preserve_stack_slots(); diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp index 28f606be3b0..cc0141c283e 100644 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp @@ -65,8 +65,6 @@ void MetaspaceShared::generate_vtable_methods(void** vtbl_list, *vtable = dummy_vtable; *md_top += vtable_bytes; - guarantee(*md_top <= md_end, "Insufficient space for vtables."); - // Get ready to generate dummy methods. CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index ab9fed0d5d1..6727c14d63b 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -324,6 +324,16 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 8; } +size_t SharedRuntime::trampoline_size() { + return 40; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ set((intptr_t)destination, G3_scratch); + __ JMP(G3_scratch, 0); + __ delayed()->nop(); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index abe9a369eaa..3763b058b8b 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -355,6 +355,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index a5c8f82e6ef..8fca552dd34 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -391,6 +391,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp index 3fbe12e94f9..0fb36b01b75 100644 --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp @@ -132,6 +132,15 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha return generate_empty_runtime_stub("resolve_blob"); } +size_t SharedRuntime::trampoline_size() { + ShouldNotCallThis(); + return 0; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + ShouldNotCallThis(); + return; +} int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, diff --git a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp index c4f991aa650..df36e6edbe1 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp index cd6f71efe2c..07206d873d7 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -66,6 +67,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #ifdef COMPILER2 diff --git a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp index dac85519a0c..c571507e675 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // we were running Java code when SIGPROF came in if (isInJava) { // If we have a last_Java_sp, then the SIGPROF signal caught us diff --git a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp index 55e5bbac4e2..3075dd19dd3 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -65,6 +66,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp index 9964114a787..ddbaa702063 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -77,6 +78,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); // we were running Java code when SIGPROF came in diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp index d41f3e7167f..48af49f7497 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -70,6 +71,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // If sp and fp are nonsense just leave them out if (!jt->on_local_stack((address)ret_sp)) { diff --git a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp index 08afec24834..ba5be5736cf 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -72,6 +73,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp index 96fb64403cd..3717ae061d9 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/interpreter.hpp" @@ -32,6 +33,7 @@ #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" #include "memory/allocation.inline.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" #include "oops/methodData.hpp" @@ -93,6 +95,7 @@ address AbstractInterpreter::_native_entry_begin = NU address AbstractInterpreter::_native_entry_end = NULL; address AbstractInterpreter::_slow_signature_handler; address AbstractInterpreter::_entry_table [AbstractInterpreter::number_of_method_entries]; +address AbstractInterpreter::_cds_entry_table [AbstractInterpreter::number_of_method_entries]; address AbstractInterpreter::_native_abi_to_tosca [AbstractInterpreter::number_of_result_handlers]; //------------------------------------------------------------------------------------------------------------------------ @@ -204,14 +207,41 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m) return zerolocals; } +#if INCLUDE_CDS + +address AbstractInterpreter::get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) { + const size_t trampoline_size = SharedRuntime::trampoline_size(); + address addr = MetaspaceShared::cds_i2i_entry_code_buffers((size_t)(AbstractInterpreter::number_of_method_entries) * trampoline_size); + addr += (size_t)(kind) * trampoline_size; + + return addr; +} + +void AbstractInterpreter::update_cds_entry_table(AbstractInterpreter::MethodKind kind) { + if (DumpSharedSpaces || UseSharedSpaces) { + address trampoline = get_trampoline_code_buffer(kind); + _cds_entry_table[kind] = trampoline; + + CodeBuffer buffer(trampoline, (int)(SharedRuntime::trampoline_size())); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, _entry_table[kind]); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } +} + +#endif void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kind, address entry) { assert(kind >= method_handle_invoke_FIRST && kind <= method_handle_invoke_LAST, "late initialization only for MH entry points"); assert(_entry_table[kind] == _entry_table[abstract], "previous value must be AME entry"); _entry_table[kind] = entry; -} + update_cds_entry_table(kind); +} // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). @@ -416,5 +446,6 @@ void AbstractInterpreter::initialize_method_handle_entries() { for (int i = method_handle_invoke_FIRST; i <= method_handle_invoke_LAST; i++) { MethodKind kind = (MethodKind) i; _entry_table[kind] = _entry_table[Interpreter::abstract]; + Interpreter::update_cds_entry_table(kind); } } diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 8be852bae60..db31ac83400 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -113,6 +113,7 @@ class AbstractInterpreter: AllStatic { // method entry points static address _entry_table[number_of_method_entries]; // entry points for a given method + static address _cds_entry_table[number_of_method_entries]; // entry points for methods in the CDS archive static address _native_abi_to_tosca[number_of_result_handlers]; // for native method result handlers static address _slow_signature_handler; // the native method generic (slow) signature handler @@ -132,6 +133,17 @@ class AbstractInterpreter: AllStatic { static address entry_for_kind(MethodKind k) { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; } static address entry_for_method(methodHandle m) { return entry_for_kind(method_kind(m)); } + static address entry_for_cds_method(methodHandle m) { + MethodKind k = method_kind(m); + assert(0 <= k && k < number_of_method_entries, "illegal kind"); + return _cds_entry_table[k]; + } + + // used by class data sharing + static void update_cds_entry_table(MethodKind kind) NOT_CDS_RETURN; + + static address get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) NOT_CDS_RETURN_(0); + // used for bootstrapping method handles: static void set_entry_for_kind(MethodKind k, address e); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index 0fbe6f8ddac..a10981c48af 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -212,6 +212,7 @@ void TemplateInterpreterGenerator::generate_all() { #define method_entry(kind) \ { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ + Interpreter::update_cds_entry_table(Interpreter::kind); \ } // all non-native method kinds diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 606b7bd6960..ec3b9462959 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -959,6 +959,16 @@ bool FileMapInfo::is_in_shared_space(const void* p) { return false; } +// Check if a given address is within one of the shared regions (ro, rw, md, mc) +bool FileMapInfo::is_in_shared_region(const void* p, int idx) { + assert((idx >= MetaspaceShared::ro) && (idx <= MetaspaceShared::mc), "invalid region index"); + char* base = _header->region_addr(idx); + if (p >= base && p < base + _header->_space[idx]._used) { + return true; + } + return false; +} + void FileMapInfo::print_shared_spaces() { tty->print_cr("Shared Spaces:"); for (int i = 0; i < MetaspaceShared::n_regions; i++) { diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index 7cb179434b9..2c02b427f0b 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -107,6 +107,8 @@ public: int _narrow_klass_shift; // save narrow klass base and shift address _narrow_klass_base; char* _misc_data_patching_start; + address _cds_i2i_entry_code_buffers; + size_t _cds_i2i_entry_code_buffers_size; struct space_info { int _crc; // crc checksum of the current space @@ -195,6 +197,19 @@ public: char* misc_data_patching_start() { return _header->_misc_data_patching_start; } void set_misc_data_patching_start(char* p) { _header->_misc_data_patching_start = p; } + address cds_i2i_entry_code_buffers() { + return _header->_cds_i2i_entry_code_buffers; + } + void set_cds_i2i_entry_code_buffers(address addr) { + _header->_cds_i2i_entry_code_buffers = addr; + } + size_t cds_i2i_entry_code_buffers_size() { + return _header->_cds_i2i_entry_code_buffers_size; + } + void set_cds_i2i_entry_code_buffers_size(size_t s) { + _header->_cds_i2i_entry_code_buffers_size = s; + } + static FileMapInfo* current_info() { CDS_ONLY(return _current_info;) NOT_CDS(return NULL;) @@ -234,6 +249,7 @@ public: // Return true if given address is in the mapped shared space. bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); void print_shared_spaces() NOT_CDS_RETURN; static size_t shared_spaces_size() { diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 36efacfc4ab..fa4d31a54be 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -59,6 +59,8 @@ bool MetaspaceShared::_link_classes_made_progress; bool MetaspaceShared::_check_classes_made_progress; bool MetaspaceShared::_has_error_classes; bool MetaspaceShared::_archive_loading_failed = false; +address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL; +size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0; SharedMiscRegion MetaspaceShared::_mc; SharedMiscRegion MetaspaceShared::_md; @@ -129,6 +131,21 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { soc->do_tag(666); } +address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) { + if (DumpSharedSpaces) { + if (_cds_i2i_entry_code_buffers == NULL) { + _cds_i2i_entry_code_buffers = (address)misc_data_space_alloc(total_size); + _cds_i2i_entry_code_buffers_size = total_size; + } + } else if (UseSharedSpaces) { + assert(_cds_i2i_entry_code_buffers != NULL, "must already been initialized"); + } else { + return NULL; + } + + assert(_cds_i2i_entry_code_buffers_size == total_size, "must not change"); + return _cds_i2i_entry_code_buffers; +} // CDS code for dumping shared archive. @@ -576,6 +593,8 @@ void VM_PopulateDumpSharedSpace::doit() { &md_top, md_end, &mc_top, mc_end); + guarantee(md_top <= md_end, "Insufficient space for vtables."); + // Reorder the system dictionary. (Moving the symbols affects // how the hash table indices are calculated.) // Not doing this either. @@ -668,6 +687,8 @@ void VM_PopulateDumpSharedSpace::doit() { FileMapInfo* mapinfo = new FileMapInfo(); mapinfo->populate_header(MetaspaceShared::max_alignment()); mapinfo->set_misc_data_patching_start((char*)vtbl_list); + mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers()); + mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size()); for (int pass=1; pass<=2; pass++) { if (pass == 1) { @@ -686,7 +707,7 @@ void VM_PopulateDumpSharedSpace::doit() { mapinfo->write_region(MetaspaceShared::md, _md_vs.low(), pointer_delta(md_top, _md_vs.low(), sizeof(char)), SharedMiscDataSize, - false, false); + false, true); mapinfo->write_region(MetaspaceShared::mc, _mc_vs.low(), pointer_delta(mc_top, _mc_vs.low(), sizeof(char)), SharedMiscCodeSize, @@ -980,6 +1001,11 @@ bool MetaspaceShared::is_in_shared_space(const void* p) { return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p); } +// Return true if given address is in the misc data region +bool MetaspaceShared::is_in_shared_region(const void* p, int idx) { + return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_region(p, idx); +} + bool MetaspaceShared::is_string_region(int idx) { return (idx >= MetaspaceShared::first_string && idx < MetaspaceShared::first_string + MetaspaceShared::max_strings); @@ -1053,6 +1079,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { void MetaspaceShared::initialize_shared_spaces() { FileMapInfo *mapinfo = FileMapInfo::current_info(); + _cds_i2i_entry_code_buffers = mapinfo->cds_i2i_entry_code_buffers(); + _cds_i2i_entry_code_buffers_size = mapinfo->cds_i2i_entry_code_buffers_size(); char* buffer = mapinfo->misc_data_patching_start(); // Skip over (reserve space for) a list of addresses of C++ vtables diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index c78f78122cf..e759464591d 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -50,17 +50,14 @@ #define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(9*M)) // the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on -// MetaspaceShared::generate_vtable_methods(). -// The minimum size only accounts for the vtable methods. Any size less than the -// minimum required size would cause vm crash when allocating the vtable methods. -#define SHARED_MISC_SIZE_FOR(size) (DEFAULT_VTBL_VIRTUALS_COUNT*DEFAULT_VTBL_LIST_SIZE*size) +// the sizes required for dumping the archive using the default classlist. The sizes +// are multiplied by 1.5 for a safety margin. #define DEFAULT_SHARED_MISC_DATA_SIZE (NOT_LP64(2*M) LP64_ONLY(4*M)) -#define MIN_SHARED_MISC_DATA_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))) +#define MIN_SHARED_MISC_DATA_SIZE (NOT_LP64(1*M) LP64_ONLY(1200*K)) #define DEFAULT_SHARED_MISC_CODE_SIZE (120*K) -#define MIN_SHARED_MISC_CODE_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))+SHARED_MISC_SIZE_FOR(DEFAULT_VTBL_METHOD_SIZE)+DEFAULT_VTBL_COMMON_CODE_SIZE) - +#define MIN_SHARED_MISC_CODE_SIZE (NOT_LP64(63*K) LP64_ONLY(69*K)) #define DEFAULT_COMBINED_SIZE (DEFAULT_SHARED_READ_WRITE_SIZE+DEFAULT_SHARED_READ_ONLY_SIZE+DEFAULT_SHARED_MISC_DATA_SIZE+DEFAULT_SHARED_MISC_CODE_SIZE) // the max size is the MAX size (ie. 0x7FFFFFFF) - the total size of @@ -128,6 +125,8 @@ class MetaspaceShared : AllStatic { static bool _check_classes_made_progress; static bool _has_error_classes; static bool _archive_loading_failed; + static address _cds_i2i_entry_code_buffers; + static size_t _cds_i2i_entry_code_buffers_size; // Used only during dumping. static SharedMiscRegion _md; @@ -185,6 +184,9 @@ class MetaspaceShared : AllStatic { // Return true if given address is in the mapped shared space. static bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + // Return true if given address is in the shared region corresponding to the idx + static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); + static bool is_string_region(int idx) NOT_CDS_RETURN_(false); static void generate_vtable_methods(void** vtbl_list, @@ -218,6 +220,15 @@ class MetaspaceShared : AllStatic { static char* misc_code_space_alloc(size_t num_bytes) { return _mc.alloc(num_bytes); } static char* misc_data_space_alloc(size_t num_bytes) { return _md.alloc(num_bytes); } + static address cds_i2i_entry_code_buffers(size_t total_size); + + static address cds_i2i_entry_code_buffers() { + return _cds_i2i_entry_code_buffers; + } + static size_t cds_i2i_entry_code_buffers_size() { + return _cds_i2i_entry_code_buffers_size; + } + static SharedMiscRegion* misc_code_region() { assert(DumpSharedSpaces, "used during dumping only"); return &_mc; diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 7d959fb516b..01df3b1a3d8 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -121,6 +121,7 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { }; class KlassSizeStats; +class AdapterHandlerEntry; // Class to collect the sizes of ConstMethod inline tables #define INLINE_TABLES_DO(do_element) \ @@ -201,6 +202,12 @@ private: // Raw stackmap data for the method Array* _stackmap_data; + // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. + union { + AdapterHandlerEntry* _adapter; + AdapterHandlerEntry** _adapter_trampoline; + }; + int _constMethod_size; u2 _flags; @@ -276,6 +283,29 @@ public: void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS); bool has_stackmap_table() const { return _stackmap_data != NULL; } + // adapter + void set_adapter_entry(AdapterHandlerEntry* adapter) { + assert(!is_shared(), "shared methods have fixed adapter_trampoline"); + _adapter = adapter; + } + void set_adapter_trampoline(AdapterHandlerEntry** trampoline) { + assert(DumpSharedSpaces, "must be"); + assert(*trampoline == NULL, "must be NULL during dump time, to be initialized at run time"); + _adapter_trampoline = trampoline; + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + assert(is_shared(), "must be"); + *_adapter_trampoline = adapter; + assert(this->adapter() == adapter, "must be"); + } + AdapterHandlerEntry* adapter() { + if (is_shared()) { + return *_adapter_trampoline; + } else { + return _adapter; + } + } + void init_fingerprint() { const uint64_t initval = UCONST64(0x8000000000000000); _fingerprint = initval; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index efaaaa5009a..b3f2b868b64 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -38,6 +38,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/constMethod.hpp" @@ -123,18 +124,18 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) { } address Method::get_i2c_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_i2c_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_i2c_entry(); } address Method::get_c2i_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_entry(); } address Method::get_c2i_unverified_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_unverified_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_unverified_entry(); } char* Method::name_and_sig_as_C_string() const { @@ -892,10 +893,10 @@ void Method::clear_code() { // this may be NULL if c2i adapters have not been made yet // Only should happen at allocate time. - if (_adapter == NULL) { + if (adapter() == NULL) { _from_compiled_entry = NULL; } else { - _from_compiled_entry = _adapter->get_c2i_entry(); + _from_compiled_entry = adapter()->get_c2i_entry(); } OrderAccess::storestore(); _from_interpreted_entry = _i2i_entry; @@ -903,47 +904,68 @@ void Method::clear_code() { _code = NULL; } +#if INCLUDE_CDS // Called by class data sharing to remove any entry points (which are not shared) void Method::unlink_method() { _code = NULL; - _i2i_entry = NULL; - _from_interpreted_entry = NULL; + + assert(DumpSharedSpaces, "dump time only"); + // Set the values to what they should be at run time. Note that + // this Method can no longer be executed during dump time. + _i2i_entry = Interpreter::entry_for_cds_method(this); + _from_interpreted_entry = _i2i_entry; + if (is_native()) { *native_function_addr() = NULL; set_signature_handler(NULL); } NOT_PRODUCT(set_compiled_invocation_count(0);) - _adapter = NULL; - _from_compiled_entry = NULL; + + CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter(); + constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline()); + _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline(); + assert(*((int*)_from_compiled_entry) == 0, "must be NULL during dump time, to be initialized at run time"); + // In case of DumpSharedSpaces, _method_data should always be NULL. - // - // During runtime (!DumpSharedSpaces), when we are cleaning a - // shared class that failed to load, this->link_method() may - // have already been called (before an exception happened), so - // this->_method_data may not be NULL. - assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); + assert(_method_data == NULL, "unexpected method data?"); set_method_data(NULL); clear_method_counters(); } +#endif // Called when the method_holder is getting linked. Setup entrypoints so the method // is ready to be called from interpreter, compiler, and vtables. void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. - if (_i2i_entry != NULL) return; + if (is_shared()) { + if (adapter() != NULL) return; + } else { + if (_i2i_entry != NULL) return; - assert(_adapter == NULL, "init'd to NULL" ); + assert(adapter() == NULL, "init'd to NULL" ); + } assert( _code == NULL, "nothing compiled yet" ); // Setup interpreter entrypoint assert(this == h_method(), "wrong h_method()" ); - address entry = Interpreter::entry_for_method(h_method); + address entry; + + if (this->is_shared()) { + entry = Interpreter::entry_for_cds_method(h_method); + } else { + entry = Interpreter::entry_for_method(h_method); + } assert(entry != NULL, "interpreter entry must be non-null"); - // Sets both _i2i_entry and _from_interpreted_entry - set_interpreter_entry(entry); + if (is_shared()) { + assert(entry == _i2i_entry && entry == _from_interpreted_entry, + "should be correctly set during dump time"); + } else { + // Sets both _i2i_entry and _from_interpreted_entry + set_interpreter_entry(entry); + } // Don't overwrite already registered native entries. if (is_native() && !has_native_function()) { @@ -975,8 +997,13 @@ address Method::make_adapters(methodHandle mh, TRAPS) { THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for adapters"); } - mh->set_adapter_entry(adapter); - mh->_from_compiled_entry = adapter->get_c2i_entry(); + if (mh->is_shared()) { + assert(mh->adapter() == adapter, "must be"); + assert(mh->_from_compiled_entry != NULL, "must be"); // FIXME, the instructions also not NULL + } else { + mh->set_adapter_entry(adapter); + mh->_from_compiled_entry = adapter->get_c2i_entry(); + } return adapter->get_c2i_entry(); } @@ -992,6 +1019,14 @@ void Method::restore_unshareable_info(TRAPS) { } } +volatile address Method::from_compiled_entry_no_trampoline() const { + nmethod *code = (nmethod *)OrderAccess::load_ptr_acquire(&_code); + if (code) { + return code->verified_entry_point(); + } else { + return adapter()->get_c2i_entry(); + } +} // The verified_code_entry() must be called when a invoke is resolved // on this method. diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 8fc7b133a16..d7a705fd84f 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -93,8 +93,6 @@ class Method : public Metadata { #endif // Entry point for calling both from and to the interpreter. address _i2i_entry; // All-args-on-stack calling convention - // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. - AdapterHandlerEntry* _adapter; // Entry point for calling from compiled code, to compiled code if it exists // or else the interpreter. volatile address _from_compiled_entry; // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry() @@ -137,6 +135,7 @@ class Method : public Metadata { static address make_adapters(methodHandle mh, TRAPS); volatile address from_compiled_entry() const { return (address)OrderAccess::load_ptr_acquire(&_from_compiled_entry); } + volatile address from_compiled_entry_no_trampoline() const; volatile address from_interpreted_entry() const{ return (address)OrderAccess::load_ptr_acquire(&_from_interpreted_entry); } // access flag @@ -431,15 +430,23 @@ class Method : public Metadata { nmethod* volatile code() const { assert( check_code(), "" ); return (nmethod *)OrderAccess::load_ptr_acquire(&_code); } void clear_code(); // Clear out any compiled code static void set_code(methodHandle mh, nmethod* code); - void set_adapter_entry(AdapterHandlerEntry* adapter) { _adapter = adapter; } + void set_adapter_entry(AdapterHandlerEntry* adapter) { + constMethod()->set_adapter_entry(adapter); + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + constMethod()->update_adapter_trampoline(adapter); + } + address get_i2c_entry(); address get_c2i_entry(); address get_c2i_unverified_entry(); - AdapterHandlerEntry* adapter() { return _adapter; } + AdapterHandlerEntry* adapter() const { + return constMethod()->adapter(); + } // setup entry points void link_method(const methodHandle& method, TRAPS); - // clear entry points. Used by sharing code - void unlink_method(); + // clear entry points. Used by sharing code during dump time + void unlink_method() NOT_CDS_RETURN; // vtable index enum VtableIndexFlag { @@ -465,7 +472,15 @@ class Method : public Metadata { // interpreter entry address interpreter_entry() const { return _i2i_entry; } // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry - void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; } + void set_interpreter_entry(address entry) { + assert(!is_shared(), "shared method's interpreter entry should not be changed at run time"); + if (_i2i_entry != entry) { + _i2i_entry = entry; + } + if (_from_interpreted_entry != entry) { + _from_interpreted_entry = entry; + } + } // native function (used for native methods only) enum { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 89d0f2c66d3..d38d493f198 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -38,6 +38,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "logging/log.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/klass.hpp" @@ -1788,7 +1789,7 @@ void SharedRuntime::check_member_name_argument_is_last_argument(const methodHand IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc)) Method* moop(method); - address entry_point = moop->from_compiled_entry(); + address entry_point = moop->from_compiled_entry_no_trampoline(); // It's possible that deoptimization can occur at a call site which hasn't // been resolved yet, in which case this function will be called from @@ -2351,12 +2352,15 @@ class AdapterHandlerTable : public BasicHashtable { public: AdapterHandlerTable() - : BasicHashtable(293, sizeof(AdapterHandlerEntry)) { } + : BasicHashtable(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { } // Create a new entry suitable for insertion in the table AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) { AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); + if (DumpSharedSpaces) { + ((CDSAdapterHandlerEntry*)entry)->init(); + } return entry; } @@ -2519,6 +2523,28 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger } AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) { + AdapterHandlerEntry* entry = get_adapter0(method); + if (method->is_shared()) { + MutexLocker mu(AdapterHandlerLibrary_lock); + if (method->adapter() == NULL) { + method->update_adapter_trampoline(entry); + } + address trampoline = method->from_compiled_entry(); + if (*(int*)trampoline == 0) { + CodeBuffer buffer(trampoline, (int)SharedRuntime::trampoline_size()); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, entry->get_c2i_entry()); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } + } + + return entry; +} + +AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter0(const methodHandle& method) { // Use customized signature handler. Need to lock around updates to // the AdapterHandlerTable (it is not safe for concurrent readers // and a single writer: this could be fixed if it becomes a @@ -2535,7 +2561,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth // make sure data structure is initialized initialize(); - if (CodeCacheExtensions::skip_compiler_support()) { + // during dump time, always generate adapters, even if the + // compiler has been turned off. + if (!DumpSharedSpaces && CodeCacheExtensions::skip_compiler_support()) { // adapters are useless and should not be used, including the // abstract_method_handler. However, some callers check that // an adapter was installed. @@ -3017,6 +3045,17 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const { } +#if INCLUDE_CDS + +void CDSAdapterHandlerEntry::init() { + assert(DumpSharedSpaces, "used during dump time only"); + _c2i_entry_trampoline = (address)MetaspaceShared::misc_data_space_alloc(SharedRuntime::trampoline_size()); + _adapter_trampoline = (AdapterHandlerEntry**)MetaspaceShared::misc_data_space_alloc(sizeof(AdapterHandlerEntry*)); +}; + +#endif // INCLUDE_CDS + + #ifndef PRODUCT void AdapterHandlerLibrary::print_statistics() { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index b3f87cdc7c6..68baebc4686 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -398,6 +398,10 @@ class SharedRuntime: AllStatic { static void convert_ints_to_longints(int i2l_argcnt, int& in_args_count, BasicType*& in_sig_bt, VMRegPair*& in_regs); + static size_t trampoline_size(); + + static void generate_trampoline(MacroAssembler *masm, address destination); + // Generate I2C and C2I adapters. These adapters are simple argument marshalling // blobs. Unlike adapters in the tiger and earlier releases the code in these // blobs does not create a new frame and are therefore virtually invisible @@ -680,6 +684,17 @@ class AdapterHandlerEntry : public BasicHashtableEntry { void print_adapter_on(outputStream* st) const; }; +class CDSAdapterHandlerEntry: public AdapterHandlerEntry { + address _c2i_entry_trampoline; // allocated from shared spaces "MC" region + AdapterHandlerEntry** _adapter_trampoline; // allocated from shared spaces "MD" region + +public: + address get_c2i_entry_trampoline() const { return _c2i_entry_trampoline; } + AdapterHandlerEntry** get_adapter_trampoline() const { return _adapter_trampoline; } + void init() NOT_CDS_RETURN; +}; + + class AdapterHandlerLibrary: public AllStatic { private: static BufferBlob* _buffer; // the temporary code buffer in CodeCache @@ -687,6 +702,7 @@ class AdapterHandlerLibrary: public AllStatic { static AdapterHandlerEntry* _abstract_method_handler; static BufferBlob* buffer_blob(); static void initialize(); + static AdapterHandlerEntry* get_adapter0(const methodHandle& method); public: diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index d7e1f5cb07c..943bf9c83ea 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -400,7 +400,6 @@ typedef CompactHashtable SymbolCompactHashTable; nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \ volatile_nonstatic_field(Method, _code, nmethod*) \ nonstatic_field(Method, _i2i_entry, address) \ - nonstatic_field(Method, _adapter, AdapterHandlerEntry*) \ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ volatile_nonstatic_field(Method, _from_interpreted_entry, address) \ volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \ From 67ed0253791b39a59de25d70937b528186296b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Lid=C3=A9n?= Date: Fri, 8 Apr 2016 08:51:45 +0200 Subject: [PATCH 109/167] 8152989: serviceability/tmtools/jstat/GcCauseTest02.java fails with OOME Reviewed-by: dsamersoff, sjohanss, dfazunen --- .../serviceability/tmtools/jstat/GcCapacityTest.java | 4 ++-- .../serviceability/tmtools/jstat/GcCauseTest01.java | 2 +- .../serviceability/tmtools/jstat/GcCauseTest02.java | 4 ++-- .../serviceability/tmtools/jstat/GcCauseTest03.java | 4 ++-- .../test/serviceability/tmtools/jstat/GcNewTest.java | 4 ++-- .../test/serviceability/tmtools/jstat/GcTest01.java | 2 +- .../test/serviceability/tmtools/jstat/GcTest02.java | 10 ++-------- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index 6ec4db9829b..ec6d1bc2f4d 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -27,13 +27,13 @@ import utils.*; * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. - * @ignore 8149778 * @library /test/lib/share/classes * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcCapacityTest + * @ignore 8149778 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCapacityTest */ public class GcCapacityTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java index 55ee941e38c..508b7865a3c 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java @@ -34,7 +34,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcCauseTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCauseTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java index bc8f0058034..95200d453c5 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest02 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java index 1ebb98b00b5..94514d4b634 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest03 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest03 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java index e91ee8ecdf6..bdb06c1e6b2 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcNewTest + * @run main/othervm -XX:+UsePerfData -Xmx128M GcNewTest */ public class GcNewTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java index ee731adb144..2a6b0c544a8 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java @@ -37,7 +37,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java index c2e55229688..bcdc258c934 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcTest02 */ public class GcTest02 { @@ -58,10 +58,4 @@ public class GcTest02 { // Assert that space has been utilized acordingly JstatResults.assertSpaceUtilization(measurement2, targetMemoryUsagePercent); } - - private static void assertThat(boolean result, String message) { - if (!result) { - throw new RuntimeException(message); - }; - } } From 890207217fbce11ee25a3bc61643b9ece636458c Mon Sep 17 00:00:00 2001 From: Frederic Parain Date: Fri, 8 Apr 2016 00:38:00 -0700 Subject: [PATCH 110/167] 8146093: [sparc only] compiler/interpreter/7116216/StackOverflow.java Program terminates with signal 11, Segmentation fault. in __1cLRegisterMap2t6MpnKJavaThread_b_v_ () Reviewed-by: dcubed, coleenp --- .../sparc/vm/templateInterpreterGenerator_sparc.cpp | 2 +- .../src/share/vm/interpreter/interpreterRuntime.cpp | 13 +------------ .../src/share/vm/interpreter/interpreterRuntime.hpp | 2 -- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index 153bd2b2319..008fcee7a6a 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -616,7 +616,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe // compute the beginning of the protected zone minus the requested frame size __ sub( Rscratch, Rscratch2, Rscratch ); - __ set( JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size(), Rscratch2 ); + __ set(MAX2(JavaThread::stack_shadow_zone_size(), JavaThread::stack_guard_zone_size()), Rscratch2 ); __ add( Rscratch, Rscratch2, Rscratch ); // Add in the size of the frame (which is the same as subtracting it from the diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 2de3339c33e..4ddc09a77eb 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -313,18 +313,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* thread) THROW_HANDLE(exception); IRT_END -IRT_ENTRY(address, InterpreterRuntime::check_ReservedStackAccess_annotated_methods(JavaThread* thread)) - frame fr = thread->last_frame(); - assert(fr.is_java_frame(), "Must be a Java frame"); - frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); - if (activation.sp() != NULL) { - thread->disable_stack_reserved_zone(); - thread->set_reserved_stack_activation((address)activation.unextended_sp()); - } - return (address)activation.sp(); -IRT_END - - IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) +IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) Handle exception = get_preinitialized_exception( SystemDictionary::StackOverflowError_klass(), CHECK); diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 02fc2cf3b2e..2039adba2a0 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -91,8 +91,6 @@ class InterpreterRuntime: AllStatic { // Quicken instance-of and check-cast bytecodes static void quicken_io_cc(JavaThread* thread); - static address check_ReservedStackAccess_annotated_methods(JavaThread* thread); - // Exceptions thrown by the interpreter static void throw_AbstractMethodError(JavaThread* thread); static void throw_IncompatibleClassChangeError(JavaThread* thread); From e709aa268df64b2dc000433a1d9621a2fb0940f0 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 8 Apr 2016 13:14:23 +0200 Subject: [PATCH 111/167] 8152666: The new Hotspot Build System Co-authored-by: Magnus Ihse Bursie Co-authored-by: Ingemar Aberg Reviewed-by: ihse, dcubed, erikj --- common/autoconf/basics.m4 | 7 +- common/autoconf/build-performance.m4 | 3 + common/autoconf/buildjdk-spec.gmk.in | 11 + common/autoconf/compare.sh.in | 1 + common/autoconf/configure | 2 +- common/autoconf/configure.ac | 14 +- common/autoconf/flags.m4 | 860 +++++--- common/autoconf/generated-configure.sh | 2630 ++++++++++++++++++++---- common/autoconf/help.m4 | 13 +- common/autoconf/hotspot-spec.gmk.in | 13 +- common/autoconf/hotspot.m4 | 491 +++-- common/autoconf/jdk-options.m4 | 30 +- common/autoconf/jdk-version.m4 | 1 + common/autoconf/lib-std.m4 | 16 +- common/autoconf/libraries.m4 | 4 +- common/autoconf/platform.m4 | 245 +-- common/autoconf/spec.gmk.in | 74 +- common/autoconf/toolchain.m4 | 11 + common/autoconf/version-numbers | 1 + common/bin/compare.sh | 52 +- common/bin/compare_exceptions.sh.incl | 122 +- common/conf/jib-profiles.js | 8 +- make/Jprt.gmk | 21 +- make/Main.gmk | 13 +- make/common/MakeBase.gmk | 12 +- make/common/NativeCompilation.gmk | 141 +- make/jprt.properties | 8 +- 27 files changed, 3729 insertions(+), 1075 deletions(-) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 753d170beb2..f295a46d3c4 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -749,8 +749,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], BASIC_PREPEND_TO_PATH([PATH],$EXTRA_PATH) if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi AC_MSG_CHECKING([for sysroot]) @@ -777,7 +777,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], # Create a default ./build/target-variant-debuglevel output root. if test "x${CONF_NAME}" = x; then AC_MSG_RESULT([in default location]) - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else AC_MSG_RESULT([in build directory with custom name]) fi @@ -1037,6 +1037,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], BASIC_PATH_PROGS(HG, hg) BASIC_PATH_PROGS(STAT, stat) BASIC_PATH_PROGS(TIME, time) + BASIC_PATH_PROGS(DTRACE, dtrace) BASIC_PATH_PROGS(PATCH, [gpatch patch]) # Check if it's GNU time IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index a3c69e02d08..0de3a9ee7f8 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -364,6 +364,9 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS], elif test "x$ICECC" != "x"; then AC_MSG_RESULT([no, does not work effectively with icecc]) USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + AC_MSG_RESULT([no, does not work with Solaris Studio]) + USE_PRECOMPILED_HEADER=0 else AC_MSG_RESULT([yes]) fi diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in index f92602edc34..89167a388fb 100644 --- a/common/autoconf/buildjdk-spec.gmk.in +++ b/common/autoconf/buildjdk-spec.gmk.in @@ -57,6 +57,12 @@ OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@ OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@ OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@ +HOTSPOT_TARGET_OS := @HOTSPOT_BUILD_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_BUILD_OS_TYPE@ +HOTSPOT_TARGET_CPU := @HOTSPOT_BUILD_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_BUILD_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_BUILD_CPU_DEFINE@ + CFLAGS_JDKLIB := @OPENJDK_BUILD_CFLAGS_JDKLIB@ CXXFLAGS_JDKLIB := @OPENJDK_BUILD_CXXFLAGS_JDKLIB@ LDFLAGS_JDKLIB := @OPENJDK_BUILD_LDFLAGS_JDKLIB@ @@ -65,6 +71,11 @@ CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@ LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@ OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@ +JVM_CFLAGS := @OPENJDK_BUILD_JVM_CFLAGS@ +JVM_LDFLAGS := @OPENJDK_BUILD_JVM_LDFLAGS@ +JVM_ASFLAGS := @OPENJDK_BUILD_JVM_ASFLAGS@ +JVM_LIBS := @OPENJDK_BUILD_JVM_LIBS@ + # The compiler for the build platform is likely not warning compatible with the official # compiler. WARNINGS_AS_ERRORS := false diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index f8f97ec02d2..e03ff07387c 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -34,6 +34,7 @@ export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@ export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@" export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@" export OPENJDK_TARGET_CPU_LIBDIR="@OPENJDK_TARGET_CPU_LIBDIR@" +export DEBUG_LEVEL="@DEBUG_LEVEL@" export AWK="@AWK@" export BASH="@BASH@" diff --git a/common/autoconf/configure b/common/autoconf/configure index 6815da9a3b1..547cb33fbc8 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -283,7 +283,7 @@ Additional (non-autoconf) OpenJDK Options: EOT - # Print additional help, e.g. a list of toolchains. + # Print additional help, e.g. a list of toolchains and JVM features. # This must be done by the autoconf script. ( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $conf_script_to_run PRINTF=printf ) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index c7bab7c53a8..7d5056cb47d 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -95,10 +95,8 @@ JDKOPT_SETUP_OPEN_OR_CUSTOM # These are needed to be able to create a configuration name (and thus the output directory) JDKOPT_SETUP_JDK_VARIANT -HOTSPOT_SETUP_JVM_INTERPRETER -HOTSPOT_SETUP_JVM_VARIANTS JDKOPT_SETUP_DEBUG_LEVEL -HOTSPOT_SETUP_DEBUG_LEVEL +HOTSPOT_SETUP_JVM_VARIANTS # With basic setup done, call the custom early hook. CUSTOM_EARLY_HOOK @@ -135,7 +133,6 @@ BASIC_SETUP_DEFAULT_MAKE_TARGET # We need build & target for this. JDKOPT_SETUP_JDK_OPTIONS JDKOPT_SETUP_JLINK_OPTIONS -HOTSPOT_SETUP_HOTSPOT_OPTIONS JDKVER_SETUP_JDK_VERSION_NUMBERS ############################################################################### @@ -207,6 +204,10 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC JDKOPT_SETUP_DEBUG_SYMBOLS JDKOPT_SETUP_CODE_COVERAGE +# Need toolchain to setup dtrace +HOTSPOT_SETUP_DTRACE +HOTSPOT_SETUP_JVM_FEATURES + ############################################################################### # # Check dependencies for external and internal libraries. @@ -225,7 +226,7 @@ LIB_SETUP_LIBRARIES # ############################################################################### -HOTSPOT_SETUP_BUILD_TWEAKS +HOTSPOT_SETUP_LEGACY_BUILD JDKOPT_DETECT_INTREE_EC ############################################################################### @@ -267,6 +268,9 @@ BASIC_TEST_USABILITY_ISSUES # At the end, call the custom hook. (Dummy macro if no custom sources available) CUSTOM_LATE_HOOK +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. +HOTSPOT_VALIDATE_JVM_FEATURES + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index b738ef49e22..5e9fc128843 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -61,6 +61,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS], AC_SUBST(LEGACY_EXTRA_CXXFLAGS) AC_SUBST(LEGACY_EXTRA_LDFLAGS) + AC_SUBST(EXTRA_CFLAGS) + AC_SUBST(EXTRA_CXXFLAGS) + AC_SUBST(EXTRA_LDFLAGS) + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -211,8 +215,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -228,8 +234,19 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi AC_SUBST(RC_FLAGS) + AC_SUBST(JVM_RCFLAGS) if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. @@ -237,7 +254,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], fi ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], [ ############################################################################### # @@ -255,6 +272,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -280,6 +298,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,[$]1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -339,11 +361,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], AC_SUBST(SET_SHARED_LIBRARY_MAPFILE) AC_SUBST(SHARED_LIBRARY_FLAGS) - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. ]) @@ -434,6 +451,22 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], AC_SUBST(CFLAGS_DEBUG_SYMBOLS) AC_SUBST(CXXFLAGS_DEBUG_SYMBOLS) + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + AC_SUBST(JVM_CFLAGS_SYMBOLS) + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -444,7 +477,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -455,40 +488,59 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -498,48 +550,75 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -554,260 +633,43 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac + AC_SUBST(C_O_FLAG_HIGHEST_JVM) AC_SUBST(C_O_FLAG_HIGHEST) AC_SUBST(C_O_FLAG_HI) AC_SUBST(C_O_FLAG_NORM) AC_SUBST(C_O_FLAG_DEBUG) AC_SUBST(C_O_FLAG_NONE) + AC_SUBST(C_O_FLAG_SIZE) + AC_SUBST(CXX_O_FLAG_HIGHEST_JVM) AC_SUBST(CXX_O_FLAG_HIGHEST) AC_SUBST(CXX_O_FLAG_HI) AC_SUBST(CXX_O_FLAG_NORM) AC_SUBST(CXX_O_FLAG_DEBUG) AC_SUBST(CXX_O_FLAG_NONE) + AC_SUBST(CXX_O_FLAG_SIZE) ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], + +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], [ - # Special extras... - if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - fi - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" - elif test "x$TOOLCHAIN_TYPE" = xxlc; then - CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" - elif test "x$TOOLCHAIN_TYPE" = xgcc; then - CXXSTD_CXXFLAG="-std=gnu++98" - FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$CXXSTD_CXXFLAG -Werror], - IF_FALSE: [CXXSTD_CXXFLAG=""]) - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" - AC_SUBST([CXXSTD_CXXFLAG]) - fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" - - ############################################################################### - # - # Now setup the CFLAGS and LDFLAGS for the JDK build. - # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. - # - - # Setup compiler/platform specific flags into - # CFLAGS_JDK - C Compiler flags - # CXXFLAGS_JDK - C++ Compiler flags - # COMMON_CCXXFLAGS_JDK - common to C and C++ - if test "x$TOOLCHAIN_TYPE" = xgcc; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then - # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" - fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - arm ) - # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - ppc ) - # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS) - elif test "x$TOOLCHAIN_TYPE" = xclang; then - if test "x$OPENJDK_TARGET_OS" = xlinux; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then - # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" - fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ - -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in - ppc ) - # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" - ;; - esac - fi - elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" - if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" - fi - - CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" - CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" - elif test "x$TOOLCHAIN_TYPE" = xxlc; then - CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK \ - -MD -Zc:wchar_t- -W3 -wd4800 \ - -DWIN32_LEAN_AND_MEAN \ - -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ - -D_WINSOCK_DEPRECATED_NO_WARNINGS \ - -DWIN32 -DIAL" - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" - fi - # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to - # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual - # studio. - if test "x$TOOLCHAIN_VERSION" = "x2010"; then - STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" - fi - fi - - ############################################################################### - - # Adjust flags according to debug level. - case $DEBUG_LEVEL in - fastdebug | slowdebug ) - CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" - CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" - JAVAC_FLAGS="$JAVAC_FLAGS -g" - ;; - release ) - ;; - * ) - AC_MSG_ERROR([Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL]) - ;; - esac - - # Set some common defines. These works for all compilers, but assume - # -D is universally accepted. - - # Setup endianness - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then - # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the - # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN - # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). - # Note: -Dmacro is the same as #define macro 1 - # -Dmacro= is the same as #define macro - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" - fi - else - # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they - # are defined in the system? - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" - fi - fi - - # Setup target OS define. Use OS target name but in upper case. - OPENJDK_TARGET_OS_UPPERCASE=`$ECHO $OPENJDK_TARGET_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" - - # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ - -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" - - # Setup debug/release defines - if test "x$DEBUG_LEVEL" = xrelease; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DNDEBUG" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DTRIMMED" - fi - else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DDEBUG" - fi - - # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" - elif test "x$OPENJDK_TARGET_OS" = xbsd; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" - fi - - # Additional macosx handling - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # Setting these parameters makes it an error to link to macosx APIs that are - # newer than the given OS version and makes the linked binaries compatible - # even if built on a newer version of the OS. - # The expected format is X.Y.Z - MACOSX_VERSION_MIN=10.7.0 - AC_SUBST(MACOSX_VERSION_MIN) - - # The macro takes the version with no dots, ex: 1070 - # Let the flags variables get resolved in make for easier override on make - # command line. - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - fi - - # Setup some hard coded includes - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ - -I${JDK_TOPDIR}/src/java.base/share/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ - -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" - - # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - AC_SUBST(CFLAGS_JDKLIB) - AC_SUBST(CFLAGS_JDKEXE) - AC_SUBST(CXXFLAGS_JDKLIB) - AC_SUBST(CXXFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKEXE) + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([TARGET]) + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([BUILD], [OPENJDK_BUILD_]) + # Tests are only ever compiled for TARGET # Flags for compiling test libraries CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" @@ -821,52 +683,425 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], AC_SUBST(CXXFLAGS_TESTLIB) AC_SUBST(CXXFLAGS_TESTEXE) + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" + LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + + AC_SUBST(LDFLAGS_TESTLIB) + AC_SUBST(LDFLAGS_TESTEXE) + +]) + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], +[ + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + $2CXXSTD_CXXFLAG="-std=gnu++98" + FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [[$]$2CXXSTD_CXXFLAG -Werror], + IF_FALSE: [$2CXXSTD_CXXFLAG=""]) + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2CXXSTD_CXXFLAG}" + AC_SUBST([$2CXXSTD_CXXFLAG]) + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + $2CFLAGS_JDK="${$2CFLAGS_JDK} ${$2EXTRA_CFLAGS}" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2EXTRA_CXXFLAGS}" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} ${$2EXTRA_LDFLAGS}" + + ############################################################################### + # + # Now setup the CFLAGS and LDFLAGS for the JDK build. + # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. + # + + # Setup compiler/platform specific flags into + # $2CFLAGS_JDK - C Compiler flags + # $2CXXFLAGS_JDK - C++ Compiler flags + # $2COMMON_CCXXFLAGS_JDK - common to C and C++ + if test "x$TOOLCHAIN_TYPE" = xgcc; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_$1_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" + fi + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_$1_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS) + elif test "x$TOOLCHAIN_TYPE" = xclang; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" + fi + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-sometimes-uninitialized" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_$1_CPU_ARCH in + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSPARC_WORKS" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_$1_CPU_LEGACY_LIB" + fi + + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK \ + -MD -Zc:wchar_t- -W3 -wd4800 \ + -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -D_WINSOCK_DEPRECATED_NO_WARNINGS \ + -DWIN32 -DIAL" + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to + # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual + # studio. + if test "x$TOOLCHAIN_VERSION" = "x2010"; then + STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS $STATIC_CPPLIB_FLAGS" + fi + fi + + ############################################################################### + + # Adjust flags according to debug level. + case $DEBUG_LEVEL in + fastdebug | slowdebug ) + $2CFLAGS_JDK="[$]$2CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + release ) + ;; + * ) + AC_MSG_ERROR([Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL]) + ;; + esac + + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + + # Setup endianness + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then + # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the + # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN + # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). + # Note: -Dmacro is the same as #define macro 1 + # -Dmacro= is the same as #define macro + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + fi + else + # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they + # are defined in the system? + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + fi + fi + + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_$1_OS_UPPERCASE=`$ECHO $OPENJDK_$1_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D$OPENJDK_$1_OS_UPPERCASE" + + # Setup target CPU + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ + $OPENJDK_$1_ADD_LP64 \ + -DARCH='\"$OPENJDK_$1_CPU_LEGACY\"' -D$OPENJDK_$1_CPU_LEGACY" + + # Setup debug/release defines + if test "x$DEBUG_LEVEL" = xrelease; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DTRIMMED" + fi + else + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DDEBUG" + fi + + # Set some additional per-OS defines. + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DLINUX" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_$1_OS-$OPENJDK_$1_CPU" = xwindows-x86; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_$1_CPU" = xppc64; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_$1_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_$1_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_OS" != xsolaris && test "x$OPENJDK_$1_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set $2JVM_CFLAGS warning handling + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: [4.8], + IF_AT_LEAST: [ + # These flags either do not work or give spurious warnings prior to gcc 4.8. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + ] + ) + fi + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # Non-zero builds have stricter warnings + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" + fi + + # Additional macosx handling + if test "x$OPENJDK_$1_OS" = xmacosx; then + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + AC_SUBST(MACOSX_VERSION_MIN) + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + + # Setup some hard coded includes + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ + -I${JDK_TOPDIR}/src/java.base/share/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava" + + # The shared libraries are compiled using the picflag. + $2CFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK $PICFLAG [$]$2CFLAGS_JDKLIB_EXTRA" + $2CXXFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK $PICFLAG [$]$2CXXFLAGS_JDKLIB_EXTRA" + + # Executable flags + $2CFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK" + $2CXXFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK" + + AC_SUBST($2CFLAGS_JDKLIB) + AC_SUBST($2CFLAGS_JDKEXE) + AC_SUBST($2CXXFLAGS_JDKLIB) + AC_SUBST($2CXXFLAGS_JDKEXE) + # Setup LDFLAGS et al. # if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_$1_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SAFESH" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:I386" + else + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_$1_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? # We have previously set HAS_GNU_HASH if this is the case if test -n "$HAS_GNU_HASH"; then - LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + $2LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} [$]$2LDFLAGS_HASH_STYLE" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS [$]$2LDFLAGS_HASH_STYLE" fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_$1_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -876,85 +1111,122 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_SOLSTUDIO="-Wl,-z,defs" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_XLC" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables - LDFLAGS_JDKEXE="${LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDK}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then + if test "x$OPENJDK_$1_CPU_BITS" = "x64"; then LDFLAGS_STACK_SIZE=1048576 else LDFLAGS_STACK_SIZE=327680 fi - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" - elif test "x$OPENJDK_TARGET_OS" = xlinux; then - LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_$1_OS" = xlinux; then + $2LDFLAGS_JDKEXE="[$]$2LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} ${$2EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs - LDFLAGS_JDKLIB="${LDFLAGS_JDK}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDK}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" - JDKLIB_LIBS="" + $2JDKLIB_LIBS="" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)" + if test "x$1" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if HOTSPOT_CHECK_JVM_VARIANT(server); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + elif HOTSPOT_CHECK_JVM_VARIANT(client); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/client" + elif HOTSPOT_CHECK_JVM_VARIANT(minimal); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + fi + elif test "x$1" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" fi - JDKLIB_LIBS="-ljava -ljvm" + $2JDKLIB_LIBS="-ljava -ljvm" if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - JDKLIB_LIBS="$JDKLIB_LIBS -lc" + $2JDKLIB_LIBS="[$]$2JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" + # Set $2JVM_LIBS (per os) + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + $2JVM_LIBS="[$]$2JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_LIBS="[$]$2JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_LIBS="[$]$2JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi - AC_SUBST(LDFLAGS_JDKLIB) - AC_SUBST(LDFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE) - AC_SUBST(JDKLIB_LIBS) - AC_SUBST(JDKEXE_LIBS) - AC_SUBST(LDFLAGS_CXX_JDK) - AC_SUBST(LDFLAGS_HASH_STYLE) + # Set $2JVM_ASFLAGS + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi - LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" - LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${$2EXTRA_LDFLAGS_JDK}" + + AC_SUBST($2LDFLAGS_JDKLIB) + AC_SUBST($2LDFLAGS_JDKEXE) + AC_SUBST($2JDKLIB_LIBS) + AC_SUBST($2JDKEXE_LIBS) + AC_SUBST($2LDFLAGS_CXX_JDK) + AC_SUBST($2LDFLAGS_HASH_STYLE) + + AC_SUBST($2JVM_CFLAGS) + AC_SUBST($2JVM_LDFLAGS) + AC_SUBST($2JVM_ASFLAGS) + AC_SUBST($2JVM_LIBS) - AC_SUBST(LDFLAGS_TESTLIB) - AC_SUBST(LDFLAGS_TESTEXE) ]) # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 0c503ce2be9..d97c4b4ebc7 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -651,7 +651,21 @@ JOBS MEMORY_SIZE NUM_CORES ENABLE_INTREE_EC +JVM_VARIANT_CORE +JVM_VARIANT_ZEROSHARK +JVM_VARIANT_ZERO +JVM_VARIANT_HOTSPOT +JVM_VARIANT_MINIMAL1 +JVM_VARIANT_CLIENT +JVM_VARIANT_SERVER +JVM_VARIANTS_COMMA +TEST_IN_BUILD HOTSPOT_MAKE_ARGS +MACOSX_UNIVERSAL +DEBUG_CLASSFILES +FASTDEBUG +VARIANT +USE_NEW_HOTSPOT_BUILD LIBZIP_CAN_USE_MMAP LIBDL LIBM @@ -687,6 +701,15 @@ LIBCXX STATIC_CXX_SETTING FIXPATH_DETACH_FLAG FIXPATH +VALID_JVM_FEATURES +JVM_FEATURES_custom +JVM_FEATURES_zeroshark +JVM_FEATURES_zero +JVM_FEATURES_minimal +JVM_FEATURES_core +JVM_FEATURES_client +JVM_FEATURES_server +INCLUDE_DTRACE GCOV_ENABLED STRIP_POLICY DEBUG_BINARIES @@ -702,22 +725,35 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG ZERO_ARCHFLAG LDFLAGS_TESTEXE LDFLAGS_TESTLIB -LDFLAGS_HASH_STYLE -LDFLAGS_CXX_JDK -JDKEXE_LIBS -JDKLIB_LIBS -OPENJDK_BUILD_LDFLAGS_JDKEXE -OPENJDK_BUILD_LDFLAGS_JDKLIB -LDFLAGS_JDKEXE -LDFLAGS_JDKLIB CXXFLAGS_TESTEXE CXXFLAGS_TESTLIB CFLAGS_TESTEXE CFLAGS_TESTLIB +OPENJDK_BUILD_JVM_LIBS +OPENJDK_BUILD_JVM_ASFLAGS +OPENJDK_BUILD_JVM_LDFLAGS +OPENJDK_BUILD_JVM_CFLAGS +OPENJDK_BUILD_LDFLAGS_HASH_STYLE +OPENJDK_BUILD_LDFLAGS_CXX_JDK +OPENJDK_BUILD_JDKEXE_LIBS +OPENJDK_BUILD_JDKLIB_LIBS +OPENJDK_BUILD_LDFLAGS_JDKEXE +OPENJDK_BUILD_LDFLAGS_JDKLIB OPENJDK_BUILD_CXXFLAGS_JDKEXE OPENJDK_BUILD_CXXFLAGS_JDKLIB OPENJDK_BUILD_CFLAGS_JDKEXE OPENJDK_BUILD_CFLAGS_JDKLIB +OPENJDK_BUILD_CXXSTD_CXXFLAG +JVM_LIBS +JVM_ASFLAGS +JVM_LDFLAGS +JVM_CFLAGS +LDFLAGS_HASH_STYLE +LDFLAGS_CXX_JDK +JDKEXE_LIBS +JDKLIB_LIBS +LDFLAGS_JDKEXE +LDFLAGS_JDKLIB CXXFLAGS_JDKEXE CXXFLAGS_JDKLIB CFLAGS_JDKEXE @@ -726,16 +762,21 @@ MACOSX_VERSION_MIN NO_LIFETIME_DSE_CFLAG NO_NULL_POINTER_CHECK_CFLAG CXXSTD_CXXFLAG +CXX_O_FLAG_SIZE CXX_O_FLAG_NONE CXX_O_FLAG_DEBUG CXX_O_FLAG_NORM CXX_O_FLAG_HI CXX_O_FLAG_HIGHEST +CXX_O_FLAG_HIGHEST_JVM +C_O_FLAG_SIZE C_O_FLAG_NONE C_O_FLAG_DEBUG C_O_FLAG_NORM C_O_FLAG_HI C_O_FLAG_HIGHEST +C_O_FLAG_HIGHEST_JVM +JVM_CFLAGS_SYMBOLS CXXFLAGS_DEBUG_SYMBOLS CFLAGS_DEBUG_SYMBOLS CXX_FLAG_DEPS @@ -747,6 +788,7 @@ SET_SHARED_LIBRARY_ORIGIN SET_EXECUTABLE_ORIGIN CXX_FLAG_REORDER C_FLAG_REORDER +JVM_RCFLAGS RC_FLAGS AR_OUT_OPTION LD_OUT_OPTION @@ -759,6 +801,7 @@ COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG JT_HOME JTREGEXE +HOTSPOT_TOOLCHAIN_TYPE USING_BROKEN_SUSE_LD PACKAGE_PATH USE_CLANG @@ -821,6 +864,9 @@ VS_PATH CYGWIN_LINK SYSROOT_LDFLAGS SYSROOT_CFLAGS +EXTRA_LDFLAGS +EXTRA_CXXFLAGS +EXTRA_CFLAGS LEGACY_EXTRA_LDFLAGS LEGACY_EXTRA_CXXFLAGS LEGACY_EXTRA_CFLAGS @@ -877,12 +923,12 @@ VERSION_MINOR VERSION_MAJOR MACOSX_BUNDLE_ID_BASE MACOSX_BUNDLE_NAME_BASE +HOTSPOT_VM_DISTRO COMPANY_NAME JDK_RC_PLATFORM_NAME PRODUCT_SUFFIX PRODUCT_NAME LAUNCHER_NAME -TEST_IN_BUILD JLINK_KEEP_PACKAGED_MODULES COPYRIGHT_YEAR COMPRESS_JARS @@ -904,6 +950,7 @@ XATTR DSYMUTIL IS_GNU_TIME PATCH +DTRACE TIME STAT HG @@ -927,20 +974,10 @@ CONF_NAME SPEC SDKROOT XCODEBUILD -BUILD_VARIANT_RELEASE -DEBUG_CLASSFILES -FASTDEBUG -VARIANT -DEBUG_LEVEL -MACOSX_UNIVERSAL -JVM_VARIANT_CORE -JVM_VARIANT_ZEROSHARK -JVM_VARIANT_ZERO -JVM_VARIANT_MINIMAL1 -JVM_VARIANT_CLIENT -JVM_VARIANT_SERVER +VALID_JVM_VARIANTS JVM_VARIANTS -JVM_INTERPRETER +DEBUG_LEVEL +HOTSPOT_DEBUG_LEVEL JDK_VARIANT SET_OPENJDK USERNAME @@ -949,16 +986,29 @@ ORIGINAL_TOPDIR TOPDIR PATH_SEP ZERO_ARCHDEF -DEFINE_CROSS_COMPILE_ARCH -LP64 -OPENJDK_TARGET_OS_EXPORT_DIR +HOTSPOT_BUILD_CPU_DEFINE +HOTSPOT_BUILD_CPU_ARCH +HOTSPOT_BUILD_CPU +HOTSPOT_BUILD_OS_TYPE +HOTSPOT_BUILD_OS +OPENJDK_BUILD_OS_EXPORT_DIR OPENJDK_BUILD_CPU_JLI_CFLAGS -OPENJDK_TARGET_CPU_JLI_CFLAGS -OPENJDK_TARGET_CPU_OSARCH -OPENJDK_TARGET_CPU_ISADIR +OPENJDK_BUILD_CPU_OSARCH +OPENJDK_BUILD_CPU_ISADIR OPENJDK_BUILD_CPU_LIBDIR OPENJDK_BUILD_CPU_LEGACY_LIB OPENJDK_BUILD_CPU_LEGACY +HOTSPOT_TARGET_CPU_DEFINE +HOTSPOT_TARGET_CPU_ARCH +HOTSPOT_TARGET_CPU +HOTSPOT_TARGET_OS_TYPE +HOTSPOT_TARGET_OS +DEFINE_CROSS_COMPILE_ARCH +LP64 +OPENJDK_TARGET_OS_EXPORT_DIR +OPENJDK_TARGET_CPU_JLI_CFLAGS +OPENJDK_TARGET_CPU_OSARCH +OPENJDK_TARGET_CPU_ISADIR OPENJDK_TARGET_CPU_LIBDIR OPENJDK_TARGET_CPU_LEGACY_LIB OPENJDK_TARGET_CPU_LEGACY @@ -1088,10 +1138,9 @@ with_target_bits enable_openjdk_only with_custom_make_dir with_jdk_variant -with_jvm_interpreter -with_jvm_variants enable_debug with_debug_level +with_jvm_variants with_devkit with_sys_root with_sysroot @@ -1107,7 +1156,6 @@ with_cacerts_file enable_unlimited_crypto with_copyright_year enable_keep_packaged_modules -enable_hotspot_test_in_build with_milestone with_update_version with_user_release_suffix @@ -1147,6 +1195,9 @@ with_native_debug_symbols enable_debug_symbols enable_zip_debug_info enable_native_coverage +enable_dtrace +with_jvm_features +with_jvm_interpreter with_stdc__lib with_msvcr_dll with_msvcp_dll @@ -1172,6 +1223,8 @@ with_lcms with_dxsdk with_dxsdk_lib with_dxsdk_include +enable_new_hotspot_build +enable_hotspot_test_in_build with_num_cores with_memory_size with_jobs @@ -1244,6 +1297,7 @@ READELF HG STAT TIME +DTRACE PATCH DSYMUTIL XATTR @@ -1923,8 +1977,6 @@ Optional Features: Enable unlimited crypto policy [disabled] --disable-keep-packaged-modules Do not keep packaged modules in jdk image [enable] - --enable-hotspot-test-in-build - run the Queens test after Hotspot build [disabled] --enable-static-build enable static library build [disabled] --disable-warnings-as-errors do not consider native warnings to be an error @@ -1936,10 +1988,18 @@ Optional Features: --enable-native-coverage enable native compilation with code coverage data[disabled] + --enable-dtrace[=yes/no/auto] + enable dtrace. Default is auto, where dtrace is + enabled if all dependencies are present. --disable-freetype-bundling disable bundling of the freetype library with the build result [enabled on Windows or when using --with-freetype, disabled otherwise] + --disable-new-hotspot-build + disable the new hotspot build system (use the old) + [enabled] + --enable-hotspot-test-in-build + run the Queens test after Hotspot build [disabled] --enable-sjavac use sjavac to do fast incremental compiles [disabled] --disable-javac-server disable javac server [enabled] @@ -1959,11 +2019,11 @@ Optional Packages: --with-custom-make-dir Deprecated. Option is kept for backwards compatibility and is ignored --with-jdk-variant JDK variant to build (normal) [normal] - --with-jvm-interpreter JVM interpreter to build (template, cpp) [template] - --with-jvm-variants JVM variants (separated by commas) to build (server, - client, minimal1, zero, zeroshark, core) [server] --with-debug-level set the debug level (release, fastdebug, slowdebug, optimized) [release] + --with-jvm-variants JVM variants (separated by commas) to build + (server,client,minimal,core,zero,zeroshark,custom) + [server] --with-devkit use this devkit for compilers, tools and resources --with-sys-root alias for --with-sysroot for backwards compatability --with-sysroot use this directory as sysroot @@ -2050,6 +2110,10 @@ Optional Packages: --with-native-debug-symbols set the native debug symbol configuration (none, internal, external, zipped) [varying] + --with-jvm-features additional JVM features to enable (separated by + comma), use '--help' to show possible values [none] + --with-jvm-interpreter Deprecated. Option is kept for backwards + compatibility and is ignored --with-stdc++lib=,, force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as @@ -2170,6 +2234,7 @@ Some influential environment variables: HG Override default value for HG STAT Override default value for STAT TIME Override default value for TIME + DTRACE Override default value for DTRACE PATCH Override default value for PATCH DSYMUTIL Override default value for DSYMUTIL XATTR Override default value for XATTR @@ -3969,6 +4034,13 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. + + # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ @@ -4093,6 +4165,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -4162,37 +4236,66 @@ pkgadd_help() { # questions. # -############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) - - - -############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then # -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. + + +############################################################################### +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. + + +############################################################################### +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features # +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. +# +############################################################################### +# Set up all JVM features for each JVM variant. +# + + +############################################################################### +# Validate JVM features once all setup is complete, including custom setup. +# + + +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. +# # @@ -4529,7 +4632,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4613,7 +4716,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4664,6 +4767,9 @@ pkgadd_help() { # +# $1 - Either TARGET or BUILD to setup the variables for. + + #%%% Build and target systems %%% @@ -4950,7 +5056,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1458755892 +DATE_WHEN_GENERATED=1460103573 ############################################################################### # @@ -4975,6 +5081,13 @@ DATE_WHEN_GENERATED=1458755892 TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -15215,6 +15328,7 @@ $as_echo "$COMPILE_TYPE" >&6; } + # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" @@ -15245,37 +15359,6 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - # Now do the same for OPENJDK_BUILD_CPU... - # Also store the legacy naming of the cpu. - # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY="i586" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_BUILD_CPU_LEGACY="amd64" - fi - - - # And the second legacy naming of the cpu. - # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then - OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" - fi - - - # This is the name of the cpu (but using i386 and amd64 instead of - # x86 and x86_64, respectively), preceeded by a /, to be used when - # locating libraries. On macosx, it's empty, though. - OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" - if test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_CPU_LIBDIR="" - fi - - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so @@ -15318,6 +15401,140 @@ $as_echo "$COMPILE_TYPE" >&6; } fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_OS_EXPORT_DIR=macosx + else + OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + fi + + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + A_LP64="LP64:=" + # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in + # unpack200.exe + if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_ADD_LP64="-D_LP64=1" + fi + fi + LP64=$A_LP64 + + + if test "x$COMPILE_TYPE" = "xcross"; then + # FIXME: ... or should this include reduced builds..? + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + else + DEFINE_CROSS_COMPILE_ARCH="" + fi + + + # Convert openjdk platform names to hotspot names + + HOTSPOT_TARGET_OS=${OPENJDK_TARGET_OS} + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + HOTSPOT_TARGET_OS=bsd + fi + + + HOTSPOT_TARGET_OS_TYPE=${OPENJDK_TARGET_OS_TYPE} + if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then + HOTSPOT_TARGET_OS_TYPE=posix + fi + + + HOTSPOT_TARGET_CPU=${OPENJDK_TARGET_CPU} + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU=x86_32 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU=sparc + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_TARGET_CPU_ARCH=${OPENJDK_TARGET_CPU_ARCH} + + + # Setup HOTSPOT_TARGET_CPU_DEFINE + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU_DEFINE=IA32 + elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then + HOTSPOT_TARGET_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xaarch64; then + HOTSPOT_TARGET_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_TARGET_CPU" = xsparc; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xppc; then + HOTSPOT_TARGET_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_TARGET_CPU" = xs390; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + elif test "x$OPENJDK_TARGET_CPU" = ss390x; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + fi + + + + + # Also store the legacy naming of the cpu. + # Ie i586 and amd64 instead of x86 and x86_64 + OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_CPU_LEGACY="i586" + elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + # On all platforms except MacOSX replace x86_64 with amd64. + OPENJDK_BUILD_CPU_LEGACY="amd64" + fi + + + # And the second legacy naming of the cpu. + # Ie i386 and amd64 instead of x86 and x86_64. + OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_CPU_LEGACY_LIB="i386" + elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" + fi + + + # This is the name of the cpu (but using i386 and amd64 instead of + # x86 and x86_64, respectively), preceeded by a /, to be used when + # locating libraries. On macosx, it's empty, though. + OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_CPU_LIBDIR="" + fi + + + # OPENJDK_BUILD_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # /amd64 or /sparcv9. This string is appended to some library paths, like this: + # /usr/lib${OPENJDK_BUILD_CPU_ISADIR}/libexample.so + OPENJDK_BUILD_CPU_ISADIR="" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_CPU_ISADIR="/sparcv9" + fi + fi + + + # Setup OPENJDK_BUILD_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_BUILD_CPU_OSARCH="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_OS" = xlinux && test "x$OPENJDK_BUILD_CPU" = xx86; then + # On linux only, we replace x86 with i386. + OPENJDK_BUILD_CPU_OSARCH="i386" + elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + # On all platforms except macosx, we replace x86_64 with amd64. + OPENJDK_BUILD_CPU_OSARCH="amd64" + fi + + OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU" if test "x$OPENJDK_BUILD_CPU" = xx86; then OPENJDK_BUILD_CPU_JLI="i386" @@ -15336,47 +15553,90 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_BUILD_OS_EXPORT_DIR=${OPENJDK_BUILD_OS_TYPE} fi - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" - fi - fi - LP64=$A_LP64 - - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then OPENJDK_BUILD_ADD_LP64="-D_LP64=1" fi fi + LP64=$A_LP64 + if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_BUILD_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac + # Convert openjdk platform names to hotspot names + + HOTSPOT_BUILD_OS=${OPENJDK_BUILD_OS} + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + HOTSPOT_BUILD_OS=bsd + fi + + + HOTSPOT_BUILD_OS_TYPE=${OPENJDK_BUILD_OS_TYPE} + if test "x$OPENJDK_BUILD_OS_TYPE" = xunix; then + HOTSPOT_BUILD_OS_TYPE=posix + fi + + + HOTSPOT_BUILD_CPU=${OPENJDK_BUILD_CPU} + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU=x86_32 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU=sparc + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_BUILD_CPU_ARCH=${OPENJDK_BUILD_CPU_ARCH} + + + # Setup HOTSPOT_BUILD_CPU_DEFINE + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU_DEFINE=IA32 + elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then + HOTSPOT_BUILD_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xaarch64; then + HOTSPOT_BUILD_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_BUILD_CPU" = xsparc; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xppc; then + HOTSPOT_BUILD_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_BUILD_CPU" = xs390; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + elif test "x$OPENJDK_BUILD_CPU" = ss390x; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + fi + + + + + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + @@ -15915,98 +16175,6 @@ fi $as_echo "$JDK_VARIANT" >&6; } - -# Check whether --with-jvm-interpreter was given. -if test "${with_jvm_interpreter+set}" = set; then : - withval=$with_jvm_interpreter; -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which interpreter of the JVM to build" >&5 -$as_echo_n "checking which interpreter of the JVM to build... " >&6; } - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_INTERPRETER" >&5 -$as_echo "$JVM_INTERPRETER" >&6; } - - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - as_fn_error $? "The available JVM interpreters are: template, cpp" "$LINENO" 5 - fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 -$as_echo_n "checking which variants of the JVM to build... " >&6; } - -# Check whether --with-jvm-variants was given. -if test "${with_jvm_variants+set}" = set; then : - withval=$with_jvm_variants; -fi - - - if test "x$with_jvm_variants" = x; then - with_jvm_variants="server" - fi - - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` - - if test "x$TEST_VARIANTS" != "x,"; then - as_fn_error $? "The available JVM variants are: server, client, minimal1, zero, zeroshark, core" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jvm_variants" >&5 -$as_echo "$with_jvm_variants" >&6; } - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes - else - BUILDING_MULTIPLE_JVM_VARIANTS=no - fi - - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - as_fn_error $? "You cannot build multiple variants with zero." "$LINENO" 5 - fi - - - - - - - - - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" - fi - - - - DEBUG_LEVEL="release" { $as_echo "$as_me:${as_lineno-$LINENO}: checking which debug level to use" >&5 $as_echo_n "checking which debug level to use... " >&6; } @@ -16042,106 +16210,89 @@ $as_echo "$DEBUG_LEVEL" >&6; } as_fn_error $? "Allowed debug levels are: release, fastdebug, slowdebug and optimized" "$LINENO" 5 fi + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi - case $DEBUG_LEVEL in - release ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" - ;; - slowdebug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" - ;; - esac - - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. DEBUG_LEVEL="release" fi - ##### - # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... - HOTSPOT_TARGET="" - if test "x$JVM_VARIANT_SERVER" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " + + + + +# Check whether --with-jvm-variants was given. +if test "${with_jvm_variants+set}" = set; then : + withval=$with_jvm_variants; +fi + + + if test "x$with_jvm_variants" = x; then + with_jvm_variants="server" + fi + JVM_VARIANTS_OPT="$with_jvm_variants" + + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [[ "$JVM_VARIANTS_OPT" =~ "," ]] ; then + BUILDING_MULTIPLE_JVM_VARIANTS=true + else + BUILDING_MULTIPLE_JVM_VARIANTS=false + fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 +$as_echo_n "checking which variants of the JVM to build... " >&6; } + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_VARIANTS" >&5 +$as_echo "$JVM_VARIANTS" >&6; } + + # Check that the selected variants are valid + + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Unknown variant(s) specified: $INVALID_VARIANTS" >&5 +$as_echo "$as_me: Unknown variant(s) specified: $INVALID_VARIANTS" >&6;} + as_fn_error $? "The available JVM variants are: $VALID_JVM_VARIANTS" "$LINENO" 5 fi - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + as_fn_error $? "You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS." "$LINENO" 5 fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " + + + + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero fi - if test "x$JVM_VARIANT_ZERO" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " - fi - - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " - fi - - if test "x$JVM_VARIANT_CORE" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " - fi - - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" - - # On Macosx universal binaries are produced, but they only contain - # 64 bit intel. This invalidates control of which jvms are built - # from configure, but only server is valid anyway. Fix this - # when hotspot makefiles are rewritten. - if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} - fi - - ##### - - - - - - - # With basic setup done, call the custom early hook. @@ -16589,8 +16740,8 @@ $as_echo "$as_me: WARNING: Both SYSROOT and --with-sdk-name are set, only SYSROO if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 @@ -16629,7 +16780,7 @@ $as_echo_n "checking where to store configuration... " >&6; } if test "x${CONF_NAME}" = x; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default location" >&5 $as_echo "in default location" >&6; } - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5 $as_echo "in build directory with custom name" >&6; } @@ -22126,6 +22277,203 @@ $as_echo "$tool_specified" >&6; } + # Publish this variable in the help. + + + if [ -z "${DTRACE+x}" ]; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in dtrace +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DTRACE" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !DTRACE! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!DTRACE!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xDTRACE" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in dtrace +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DTRACE" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if we try to supply an empty value + if test "x$DTRACE" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool DTRACE= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool DTRACE= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + # Check if the provided tool contains a complete path. + tool_specified="$DTRACE" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool DTRACE=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool DTRACE=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$DTRACE" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool DTRACE=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool DTRACE=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool DTRACE=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + fi + + + + # Publish this variable in the help. @@ -23408,10 +23756,7 @@ fi # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then @@ -23473,22 +23818,6 @@ $as_echo "yes (default)" >&6; } - # Control wether Hotspot runs Queens test after build. - # Check whether --enable-hotspot-test-in-build was given. -if test "${enable_hotspot_test_in_build+set}" = set; then : - enableval=$enable_hotspot_test_in_build; -else - enable_hotspot_test_in_build=no -fi - - if test "x$enable_hotspot_test_in_build" = "xyes"; then - TEST_IN_BUILD=true - else - TEST_IN_BUILD=false - fi - - - # Warn user that old version arguments are deprecated. @@ -23539,6 +23868,7 @@ fi + # Override version from arguments # If --with-version-string is set, process it first. It is possible to @@ -30611,6 +30941,10 @@ fi + + + + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -46738,6 +47072,17 @@ $as_echo "yes" >&6; } fi + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + + # Setup the JTReg Regression Test Harness. @@ -47217,8 +47562,10 @@ $as_echo "no" >&6; } # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -47234,9 +47581,20 @@ $as_echo "no" >&6; } -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. COMMON_CCXXFLAGS="$COMMON_CCXXFLAGS -nologo" @@ -47402,6 +47760,10 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + elif test "x$COMPILE_TYPE" = xreduced; then if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then # Specify -m if running reduced on unix platforms @@ -47422,8 +47784,17 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check for ac_header in stdio.h @@ -47548,6 +47919,10 @@ $as_echo "$as_me: Retrying with platforms compiler target bits flag to ${COMPILE CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + # We have to unset 'ac_cv_sizeof_int_p' first, otherwise AC_CHECK_SIZEOF will use the previously cached value! unset ac_cv_sizeof_int_p @@ -47894,6 +48269,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -47919,6 +48295,10 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/$1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,$1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -47978,11 +48358,6 @@ $as_echo "$ac_cv_c_bigendian" >&6; } - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. @@ -48040,6 +48415,22 @@ $as_echo "$ac_cv_c_bigendian" >&6; } + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -48050,7 +48441,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -48325,40 +48716,59 @@ $as_echo "$supports" >&6; } CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -48368,48 +48778,75 @@ $as_echo "$supports" >&6; } if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -48424,12 +48861,16 @@ $as_echo "$supports" >&6; } ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac @@ -48445,6 +48886,12 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... if test "x$TOOLCHAIN_TYPE" = xsolstudio; then if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then @@ -48556,10 +49003,23 @@ $as_echo "$supports" >&6; } CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + CFLAGS_JDK="${CFLAGS_JDK} ${EXTRA_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK} ${EXTRA_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK} ${EXTRA_LDFLAGS}" ############################################################################### # @@ -48572,9 +49032,13 @@ $as_echo "$supports" >&6; } # CXXFLAGS_JDK - C++ Compiler flags # COMMON_CCXXFLAGS_JDK - common to C and C++ if test "x$TOOLCHAIN_TYPE" = xgcc; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT" + JVM_CFLAGS="$JVM_CFLAGS -fcheck-new" if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" @@ -49211,11 +49675,19 @@ $as_echo "$supports" >&6; } elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + JVM_CFLAGS="$JVM_CFLAGS -flimit-debug-info" if test "x$OPENJDK_TARGET_OS" = xlinux; then if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi + JVM_CFLAGS="$JVM_CFLAGS -Wno-sometimes-uninitialized" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" case $OPENJDK_TARGET_CPU_ARCH in @@ -49230,6 +49702,7 @@ $as_echo "$supports" >&6; } esac fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS="$JVM_CFLAGS -DSPARC_WORKS" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" @@ -49238,6 +49711,7 @@ $as_echo "$supports" >&6; } CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -49258,6 +49732,7 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_VERSION" = "x2010"; then STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + JVM_CFLAGS="$JVM_CFLAGS $STATIC_CPPLIB_FLAGS" fi fi @@ -49307,12 +49782,9 @@ $as_echo "$supports" >&6; } COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ + COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ + $OPENJDK_TARGET_ADD_LP64 \ -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" # Setup debug/release defines if test "x$DEBUG_LEVEL" = xrelease; then @@ -49325,10 +49797,171 @@ $as_echo "$supports" >&6; } fi # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -DLINUX" + JVM_CFLAGS="$JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS" + JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + JVM_CFLAGS="$JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" elif test "x$OPENJDK_TARGET_OS" = xbsd; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_CFLAGS="$JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + JVM_CFLAGS="$JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = xwindows-x86; then + JVM_CFLAGS="$JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + JVM_CFLAGS="$JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then + JVM_CFLAGS="$JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_TARGET_OS" != xsolaris && test "x$OPENJDK_TARGET_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + JVM_CFLAGS="$JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set JVM_CFLAGS warning handling + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + JVM_CFLAGS="$JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + JVM_CFLAGS="$JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + JVM_CFLAGS="$JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" fi # Additional macosx handling @@ -49356,43 +49989,14 @@ $as_echo "$supports" >&6; } -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - - - - - - - - - - # Flags for compiling test libraries - CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Flags for compiling test executables - CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" - CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $EXTRA_CFLAGS_JDK" + CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" @@ -49405,9 +50009,21 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + JVM_LDFLAGS="$JVM_LDFLAGS -machine:I386" + else + JVM_LDFLAGS="$JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_LDFLAGS="$JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? @@ -49415,36 +50031,57 @@ $as_echo "$supports" >&6; } if test -n "$HAS_GNU_HASH"; then LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi if test "x$OPENJDK_TARGET_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_LDFLAGS="$JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -49457,9 +50094,14 @@ $as_echo "$supports" >&6; } LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + JVM_LDFLAGS="$JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables @@ -49477,7 +50119,6 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs @@ -49492,18 +50133,24 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + if test "xTARGET" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + fi + elif test "xTARGET" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi JDKLIB_LIBS="-ljava -ljvm" @@ -49511,12 +50158,41 @@ $as_echo "$supports" >&6; } JDKLIB_LIBS="$JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" + # Set JVM_LIBS (per os) + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_LIBS="$JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + JVM_LIBS="$JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_LIBS="$JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xbsd; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_LIBS="$JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set JVM_ASFLAGS + if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_ASFLAGS="$JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_ASFLAGS="$JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" @@ -49528,6 +50204,801 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_CXXSTD_CXXFLAG="-std=gnu++98" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"" >&5 +$as_echo_n "checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"... " >&6; } + supports=yes + + saved_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAG $OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int i; +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + supports=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="$saved_cxxflags" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5 +$as_echo "$supports" >&6; } + if test "x$supports" = "xyes" ; then + : + + else + : + OPENJDK_BUILD_CXXSTD_CXXFLAG="" + fi + + + + + + + + + + + + + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_CXXSTD_CXXFLAG}" + + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CFLAGS}" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CXXFLAGS}" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_LDFLAGS}" + + ############################################################################### + # + # Now setup the CFLAGS and LDFLAGS for the JDK build. + # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. + # + + # Setup compiler/platform specific flags into + # OPENJDK_BUILD_CFLAGS_JDK - C Compiler flags + # OPENJDK_BUILD_CXXFLAGS_JDK - C++ Compiler flags + # OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK - common to C and C++ + if test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=6 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + else + : + + fi + + + + + + + + + + + + + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-sometimes-uninitialized" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSPARC_WORKS" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_BUILD_CPU_LEGACY_LIB" + fi + + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -MD -Zc:wchar_t- -W3 -wd4800 \ + -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -D_WINSOCK_DEPRECATED_NO_WARNINGS \ + -DWIN32 -DIAL" + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to + # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual + # studio. + if test "x$TOOLCHAIN_VERSION" = "x2010"; then + STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS $STATIC_CPPLIB_FLAGS" + fi + fi + + ############################################################################### + + # Adjust flags according to debug level. + case $DEBUG_LEVEL in + fastdebug | slowdebug ) + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + release ) + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + + # Setup endianness + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the + # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN + # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). + # Note: -Dmacro is the same as #define macro 1 + # -Dmacro= is the same as #define macro + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + fi + else + # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they + # are defined in the system? + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + fi + fi + + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_BUILD_OS_UPPERCASE=`$ECHO $OPENJDK_BUILD_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D$OPENJDK_BUILD_OS_UPPERCASE" + + # Setup target CPU + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_ADD_LP64 \ + -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" + + # Setup debug/release defines + if test "x$DEBUG_LEVEL" = xrelease; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRIMMED" + fi + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DDEBUG" + fi + + # Set some additional per-OS defines. + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DLINUX" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" = xwindows-x86; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xbig; then + # fixes `relocation truncated to fit' error for gcc 4.1. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + else + # Little endian machine uses ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qarch=ppc64" + fi + fi + + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_OS" != xsolaris && test "x$OPENJDK_BUILD_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set OPENJDK_BUILD_JVM_CFLAGS warning handling + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" + fi + + # Additional macosx handling + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + + # Setup some hard coded includes + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -I${JDK_TOPDIR}/src/java.base/share/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava" + + # The shared libraries are compiled using the picflag. + OPENJDK_BUILD_CFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA" + OPENJDK_BUILD_CXXFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA" + + # Executable flags + OPENJDK_BUILD_CFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK" + OPENJDK_BUILD_CXXFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK" + + + + + + + # Setup LDFLAGS et al. + # + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + LDFLAGS_MICROSOFT="-nologo -opt:ref" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_BUILD_CPU_BITS" = "x32"; then + LDFLAGS_SAFESH="-safeseh" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SAFESH" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:I386" + else + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # If this is a --hash-style=gnu system, use --hash-style=both, why? + # We have previously set HAS_GNU_HASH if this is the case + if test -n "$HAS_GNU_HASH"; then + OPENJDK_BUILD_LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_BUILD_OS" = xlinux; then + # And since we now know that the linker is gnu, then add -z defs, to forbid + # undefined symbols in object files. + LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -march=i586" + fi + case $DEBUG_LEVEL in + release ) + # tell linker to optimize libraries. + # Should this be supplied to the OSS linker as well? + LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + slowdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_NOW" = "xtrue"; then + # do relocations at load + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_NOW_FLAG" + fi + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + fastdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + LDFLAGS_SOLSTUDIO="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + LDFLAGS_CXX_SOLSTUDIO="-norunpath" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -xarch=sparc" + fi + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_XLC" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_XLC" + fi + + # Customize LDFLAGS for executables + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDK}" + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$OPENJDK_BUILD_CPU_BITS" = "x64"; then + LDFLAGS_STACK_SIZE=1048576 + else + LDFLAGS_STACK_SIZE=327680 + fi + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_LDFLAGS_JDKEXE="$OPENJDK_BUILD_LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + fi + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + # Customize LDFLAGS for libs + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDK}" + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" + OPENJDK_BUILD_JDKLIB_LIBS="" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)" + + if test "xBUILD" = "xTARGET"; then + # On some platforms (mac) the linker warns about non existing -L dirs. + # Add server first if available. Linking aginst client does not always produce the same results. + # Only add client/minimal dir if client/minimal is being built. + # Default to server for other variants. + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/minimal" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + elif test "xBUILD" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + + OPENJDK_BUILD_JDKLIB_LIBS="-ljava -ljvm" + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JDKLIB_LIBS="$OPENJDK_BUILD_JDKLIB_LIBS -lc" + fi + + fi + + # Set OPENJDK_BUILD_JVM_LIBS (per os) + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set OPENJDK_BUILD_JVM_ASFLAGS + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + + + + + + + + + + + + + + + # Tests are only ever compiled for TARGET + # Flags for compiling test libraries + CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" + CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" + + # Flags for compiling test executables + CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" + CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + + + + + + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" @@ -49535,6 +51006,7 @@ $as_echo "$supports" >&6; } + # Some Zero and Shark settings. # ZERO_ARCHFLAG tells the compiler which mode to build for case "${OPENJDK_TARGET_CPU}" in @@ -50883,6 +52355,222 @@ $as_echo "no" >&6; } +# Need toolchain to setup dtrace + + # Test for dtrace dependencies + # Check whether --enable-dtrace was given. +if test "${enable_dtrace+set}" = set; then : + enableval=$enable_dtrace; +fi + + + DTRACE_DEP_MISSING=false + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dtrace tool" >&5 +$as_echo_n "checking for dtrace tool... " >&6; } + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found, cannot build dtrace" >&5 +$as_echo "not found, cannot build dtrace" >&6; } + DTRACE_DEP_MISSING=true + fi + + for ac_header in sys/sdt.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sdt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SDT_H 1 +_ACEOF + DTRACE_HEADERS_OK=yes +else + DTRACE_HEADERS_OK=no +fi + +done + + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dtrace should be built" >&5 +$as_echo_n "checking if dtrace should be built... " >&6; } + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + + # Print a helpful message on how to acquire the necessary build dependency. + # dtrace is the help tag: freetype, cups, alsa etc + MISSING_DEPENDENCY=dtrace + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + cygwin_help $MISSING_DEPENDENCY + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + msys_help $MISSING_DEPENDENCY + else + PKGHANDLER_COMMAND= + + case $PKGHANDLER in + apt-get) + apt_help $MISSING_DEPENDENCY ;; + yum) + yum_help $MISSING_DEPENDENCY ;; + port) + port_help $MISSING_DEPENDENCY ;; + pkgutil) + pkgutil_help $MISSING_DEPENDENCY ;; + pkgadd) + pkgadd_help $MISSING_DEPENDENCY ;; + esac + + if test "x$PKGHANDLER_COMMAND" != x; then + HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." + fi + fi + + as_fn_error $? "Cannot enable dtrace with missing dependencies. See above. $HELP_MSG" "$LINENO" 5 + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, non-open linux build" >&5 +$as_echo "no, non-open linux build" >&6; } + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, dependencies present" >&5 +$as_echo "yes, dependencies present" >&6; } + fi + else + as_fn_error $? "Invalid value for --enable-dtrace: $enable_dtrace" "$LINENO" 5 + fi + + + + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + +# Check whether --with-jvm-features was given. +if test "${with_jvm_features+set}" = set; then : + withval=$with_jvm_features; +fi + + if test "x$with_jvm_features" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking additional JVM features" >&5 +$as_echo_n "checking additional JVM features... " >&6; } + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES" >&5 +$as_echo "$JVM_FEATURES" >&6; } + fi + + # Verify that dependencies are met for explicitly set features. + if [[ " $JVM_FEATURES " =~ " jvmti " ]] && ! [[ " $JVM_FEATURES " =~ " services " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmti' requires feature 'services'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " management " ]] && ! [[ " $JVM_FEATURES " =~ " nmt " ]] ; then + as_fn_error $? "Specified JVM feature 'management' requires feature 'nmt'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " jvmci " ]] && ! [[ " $JVM_FEATURES " =~ " compiler2 " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmci' requires feature 'compiler2'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " compiler2 " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'compiler2' requires feature 'all-gcs'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " vm-structs " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'vm-structs' requires feature 'all-gcs'" "$LINENO" 5 + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if [[ " $JVM_FEATURES " =~ " dtrace " ]] ; then + as_fn_error $? "To enable dtrace, you must use --enable-dtrace" "$LINENO" 5 + fi + fi + + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" + else + if [[ " $JVM_FEATURES " =~ " static-build " ]] ; then + as_fn_error $? "To enable static-build, you must use --enable-static-build" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " zero " ]] ; then + as_fn_error $? "To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " shark " ]] ; then + as_fn_error $? "To enable shark, you must use --with-jvm-variants=zeroshark" "$LINENO" 5 + fi + fi + + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" + fi + + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + + + + + + + + + + # Used for verification of Makefiles by check-jvm-feature + + + # We don't support --with-jvm-interpreter anymore, use zero instead. + + +# Check whether --with-jvm-interpreter was given. +if test "${with_jvm_interpreter+set}" = set; then : + withval=$with_jvm_interpreter; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&2;} +fi + + + + ############################################################################### # # Check dependencies for external and internal libraries. @@ -51009,7 +52697,7 @@ $as_echo "yes" >&6; } fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -51132,14 +52820,26 @@ $as_echo "$has_static_libstdcxx" >&6; } # If dynamic wasn't requested, go with static unless it isn't available. { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libstdc++" >&5 $as_echo_n "checking how to link with libstdc++... " >&6; } - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic" >&5 $as_echo "dynamic" >&6; } else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 @@ -61291,7 +62991,7 @@ $as_echo "$LIBFFI_WORKS" >&6; } - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then # Extract the first word of "llvm-config", so it can be a program name with args. set dummy llvm-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -62017,9 +63717,143 @@ fi ############################################################################### + # Check whether --enable-new-hotspot-build was given. +if test "${enable_new_hotspot_build+set}" = set; then : + enableval=$enable_new_hotspot_build; +fi + + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + + + case $HOTSPOT_DEBUG_LEVEL in + product ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + fastdebug ) + VARIANT="DBG" + FASTDEBUG="true" + DEBUG_CLASSFILES="true" + ;; + debug ) + VARIANT="DBG" + FASTDEBUG="false" + DEBUG_CLASSFILES="true" + ;; + optimized ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + esac + + + + + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + MACOSX_UNIVERSAL="true" + fi + + + + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` + + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` + + ##### + # Generate the legacy makefile targets for hotspot. + HOTSPOT_TARGET="" + + if test "x$JVM_VARIANT_SERVER" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " + fi + + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " + fi + + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " + fi + + if test "x$JVM_VARIANT_ZERO" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " + fi + + if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " + fi + + if test "x$JVM_VARIANT_CORE" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " + fi + + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" + + # On Macosx universal binaries are produced, but they only contain + # 64 bit intel. This invalidates control of which jvms are built + # from configure, but only server is valid anyway. Fix this + # when hotspot makefiles are rewritten. + if test "x$MACOSX_UNIVERSAL" = xtrue; then + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} + fi + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + # Control wether Hotspot runs Queens test after build. + # Check whether --enable-hotspot-test-in-build was given. +if test "${enable_hotspot_test_in_build+set}" = set; then : + enableval=$enable_hotspot_test_in_build; +else + enable_hotspot_test_in_build=no +fi + + if test "x$enable_hotspot_test_in_build" = "xyes"; then + TEST_IN_BUILD=true + else + TEST_IN_BUILD=false + fi + + + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + as_fn_error $? "You cannot build a custom JVM using the old hotspot build system." "$LINENO" 5 + fi + fi + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5 $as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; } @@ -63269,6 +65103,10 @@ $as_echo "no, forced" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work effectively with icecc" >&5 $as_echo "no, does not work effectively with icecc" >&6; } USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with Solaris Studio" >&5 +$as_echo "no, does not work with Solaris Studio" >&6; } + USE_PRECOMPILED_HEADER=0 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -63689,6 +65527,32 @@ $as_echo "$OUTPUT_DIR_IS_LOCAL" >&6; } # At the end, call the custom hook. (Dummy macro if no custom sources available) +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. + + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking JVM features for JVM variant '$variant'" >&5 +$as_echo_n "checking JVM features for JVM variant '$variant'... " >&6; } + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES_TO_TEST" >&5 +$as_echo "$JVM_FEATURES_TO_TEST" >&6; } + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + as_fn_error $? "Invalid JVM feature(s): $INVALID_FEATURES" "$LINENO" 5 + fi + done + + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" @@ -64912,7 +66776,7 @@ fi printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -64938,7 +66802,7 @@ fi fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index d0892c56256..e7ccdca3cf3 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -119,6 +119,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -170,6 +172,13 @@ AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -206,7 +215,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -232,7 +241,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in index 54b6ca2f9ed..50d790876a6 100644 --- a/common/autoconf/hotspot-spec.gmk.in +++ b/common/autoconf/hotspot-spec.gmk.in @@ -38,6 +38,16 @@ include $(BASE_SPEC) # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ +JVM_VARIANTS:=@JVM_VARIANTS_COMMA@ + +JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ +JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ +JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ +JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ +JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ +JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ +JVM_VARIANT_CUSTOM:=@JVM_VARIANT_HOTSPOT@ + # Legacy setting: OPT or DBG VARIANT:=@VARIANT@ # Legacy setting: true or false @@ -92,8 +102,7 @@ LLVM_LDFLAGS=@LLVM_LDFLAGS@ ALT_OUTPUTDIR=$(HOTSPOT_OUTPUTDIR) ALT_EXPORT_PATH=$(HOTSPOT_DIST) -JVM_INTERPRETER:=@JVM_INTERPRETER@ -ifeq ($(JVM_INTERPRETER), cpp) +ifeq ($(HOTSPOT_TARGET_CPU), zero) CC_INTERP=true endif diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index fe3eec0ecde..4fffa86983d 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -23,170 +23,344 @@ # questions. # -############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter -AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_INTERPRETER], -[ - AC_ARG_WITH([jvm-interpreter], [AS_HELP_STRING([--with-jvm-interpreter], - [JVM interpreter to build (template, cpp) @<:@template@:>@])]) +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" - AC_MSG_CHECKING([which interpreter of the JVM to build]) - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - AC_MSG_RESULT([$JVM_INTERPRETER]) - - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - AC_MSG_ERROR([The available JVM interpreters are: template, cpp]) - fi - - AC_SUBST(JVM_INTERPRETER) -]) +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_VARIANT], +[ [ [[ " $JVM_VARIANTS " =~ " $1 " ]] ] ]) + +############################################################################### +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_FEATURE], +[ [ [[ " $JVM_FEATURES " =~ " $1 " ]] ] ]) + +############################################################################### +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features +# AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], [ - AC_MSG_CHECKING([which variants of the JVM to build]) AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants], - [JVM variants (separated by commas) to build (server, client, minimal1, zero, zeroshark, core) @<:@server@:>@])]) + [JVM variants (separated by commas) to build (server,client,minimal,core,zero,zeroshark,custom) @<:@server@:>@])]) if test "x$with_jvm_variants" = x; then with_jvm_variants="server" fi + JVM_VARIANTS_OPT="$with_jvm_variants" - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` - - if test "x$TEST_VARIANTS" != "x,"; then - AC_MSG_ERROR([The available JVM variants are: server, client, minimal1, zero, zeroshark, core]) - fi - AC_MSG_RESULT([$with_jvm_variants]) - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) - fi - fi - - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [ [[ "$JVM_VARIANTS_OPT" =~ "," ]] ]; then + BUILDING_MULTIPLE_JVM_VARIANTS=true else - BUILDING_MULTIPLE_JVM_VARIANTS=no + BUILDING_MULTIPLE_JVM_VARIANTS=false + fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` + + AC_MSG_CHECKING([which variants of the JVM to build]) + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + AC_MSG_RESULT([$JVM_VARIANTS]) + + # Check that the selected variants are valid + + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + AC_MSG_NOTICE([Unknown variant(s) specified: $INVALID_VARIANTS]) + AC_MSG_ERROR([The available JVM variants are: $VALID_JVM_VARIANTS]) fi - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - AC_MSG_ERROR([You cannot build multiple variants with zero.]) + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + AC_MSG_ERROR([You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS.]) fi AC_SUBST(JVM_VARIANTS) - AC_SUBST(JVM_VARIANT_SERVER) - AC_SUBST(JVM_VARIANT_CLIENT) - AC_SUBST(JVM_VARIANT_MINIMAL1) - AC_SUBST(JVM_VARIANT_ZERO) - AC_SUBST(JVM_VARIANT_ZEROSHARK) - AC_SUBST(JVM_VARIANT_CORE) + AC_SUBST(VALID_JVM_VARIANTS) + + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero + fi +]) + +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE], +[ + # Test for dtrace dependencies + AC_ARG_ENABLE([dtrace], [AS_HELP_STRING([--enable-dtrace@<:@=yes/no/auto@:>@], + [enable dtrace. Default is auto, where dtrace is enabled if all dependencies + are present.])]) + + DTRACE_DEP_MISSING=false + + AC_MSG_CHECKING([for dtrace tool]) + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + AC_MSG_RESULT([$DTRACE]) + else + AC_MSG_RESULT([not found, cannot build dtrace]) + DTRACE_DEP_MISSING=true + fi + + AC_CHECK_HEADERS([sys/sdt.h], [DTRACE_HEADERS_OK=yes],[DTRACE_HEADERS_OK=no]) + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + AC_MSG_CHECKING([if dtrace should be built]) + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + AC_MSG_RESULT([no, missing dependencies]) + HELP_MSG_MISSING_DEPENDENCY([dtrace]) + AC_MSG_ERROR([Cannot enable dtrace with missing dependencies. See above. $HELP_MSG]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, forced]) + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, forced]) + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, non-open linux build]) + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, missing dependencies]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, dependencies present]) + fi + else + AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace]) + fi + AC_SUBST(INCLUDE_DTRACE) +]) + +############################################################################### +# Set up all JVM features for each JVM variant. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], +[ + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + AC_ARG_WITH([jvm-features], [AS_HELP_STRING([--with-jvm-features], + [additional JVM features to enable (separated by comma), use '--help' to show possible values @<:@none@:>@])]) + if test "x$with_jvm_features" != x; then + AC_MSG_CHECKING([additional JVM features]) + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + AC_MSG_RESULT([$JVM_FEATURES]) + fi + + # Verify that dependencies are met for explicitly set features. + if HOTSPOT_CHECK_JVM_FEATURE(jvmti) && ! HOTSPOT_CHECK_JVM_FEATURE(services); then + AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(management) && ! HOTSPOT_CHECK_JVM_FEATURE(nmt); then + AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(jvmci) && ! HOTSPOT_CHECK_JVM_FEATURE(compiler2); then + AC_MSG_ERROR([Specified JVM feature 'jvmci' requires feature 'compiler2']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(compiler2) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'compiler2' requires feature 'all-gcs']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(vm-structs) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'vm-structs' requires feature 'all-gcs']) + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if HOTSPOT_CHECK_JVM_FEATURE(dtrace); then + AC_MSG_ERROR([To enable dtrace, you must use --enable-dtrace]) + fi + fi + + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" + else + if HOTSPOT_CHECK_JVM_FEATURE(static-build); then + AC_MSG_ERROR([To enable static-build, you must use --enable-static-build]) + fi + fi + + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(zero); then + AC_MSG_ERROR([To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark]) + fi + fi + + if ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(shark); then + AC_MSG_ERROR([To enable shark, you must use --with-jvm-variants=zeroshark]) + fi + fi + + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" + fi + + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + + AC_SUBST(JVM_FEATURES_server) + AC_SUBST(JVM_FEATURES_client) + AC_SUBST(JVM_FEATURES_core) + AC_SUBST(JVM_FEATURES_minimal) + AC_SUBST(JVM_FEATURES_zero) + AC_SUBST(JVM_FEATURES_zeroshark) + AC_SUBST(JVM_FEATURES_custom) + + # Used for verification of Makefiles by check-jvm-feature + AC_SUBST(VALID_JVM_FEATURES) + + # We don't support --with-jvm-interpreter anymore, use zero instead. + BASIC_DEPRECATED_ARG_WITH(jvm-interpreter) +]) + +############################################################################### +# Validate JVM features once all setup is complete, including custom setup. +# +AC_DEFUN_ONCE([HOTSPOT_VALIDATE_JVM_FEATURES], +[ + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + AC_MSG_CHECKING([JVM features for JVM variant '$variant']) + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + AC_MSG_RESULT([$JVM_FEATURES_TO_TEST]) + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + AC_MSG_ERROR([Invalid JVM feature(s): $INVALID_FEATURES]) + fi + done +]) + +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_LEGACY_BUILD], +[ + AC_ARG_ENABLE(new-hotspot-build, [AS_HELP_STRING([--disable-new-hotspot-build], + [disable the new hotspot build system (use the old) @<:@enabled@:>@])]) + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + AC_SUBST(USE_NEW_HOTSPOT_BUILD) + + case $HOTSPOT_DEBUG_LEVEL in + product ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + fastdebug ) + VARIANT="DBG" + FASTDEBUG="true" + DEBUG_CLASSFILES="true" + ;; + debug ) + VARIANT="DBG" + FASTDEBUG="false" + DEBUG_CLASSFILES="true" + ;; + optimized ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + esac + AC_SUBST(VARIANT) + AC_SUBST(FASTDEBUG) + AC_SUBST(DEBUG_CLASSFILES) if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then MACOSX_UNIVERSAL="true" fi AC_SUBST(MACOSX_UNIVERSAL) -]) + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` -############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. -# -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts -# -AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], -[ - case $DEBUG_LEVEL in - release ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" - ;; - slowdebug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" - ;; - esac - - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. - if test "x$DEBUG_LEVEL" = xoptimized; then - DEBUG_LEVEL="release" - fi + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` ##### # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... HOTSPOT_TARGET="" if test "x$JVM_VARIANT_SERVER" = xtrue; then @@ -213,27 +387,19 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " fi - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" # On Macosx universal binaries are produced, but they only contain # 64 bit intel. This invalidates control of which jvms are built # from configure, but only server is valid anyway. Fix this # when hotspot makefiles are rewritten. if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} fi - ##### + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + AC_SUBST(HOTSPOT_MAKE_ARGS) - AC_SUBST(DEBUG_LEVEL) - AC_SUBST(VARIANT) - AC_SUBST(FASTDEBUG) - AC_SUBST(DEBUG_CLASSFILES) - AC_SUBST(BUILD_VARIANT_RELEASE) -]) - -AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], -[ # Control wether Hotspot runs Queens test after build. AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build], [run the Queens test after Hotspot build @<:@disabled@:>@])],, @@ -244,10 +410,29 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], TEST_IN_BUILD=false fi AC_SUBST(TEST_IN_BUILD) -]) -AC_DEFUN_ONCE([HOTSPOT_SETUP_BUILD_TWEAKS], -[ - HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" - AC_SUBST(HOTSPOT_MAKE_ARGS) + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + AC_MSG_ERROR([You cannot build a custom JVM using the old hotspot build system.]) + fi + fi + + AC_SUBST(JVM_VARIANTS_COMMA) + AC_SUBST(JVM_VARIANT_SERVER) + AC_SUBST(JVM_VARIANT_CLIENT) + AC_SUBST(JVM_VARIANT_MINIMAL1) + AC_SUBST(JVM_VARIANT_HOTSPOT) + AC_SUBST(JVM_VARIANT_ZERO) + AC_SUBST(JVM_VARIANT_ZEROSHARK) + AC_SUBST(JVM_VARIANT_CORE) ]) diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 3c677d8adde..0b45cbc877e 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -81,6 +81,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL], test "x$DEBUG_LEVEL" != xslowdebug; then AC_MSG_ERROR([Allowed debug levels are: release, fastdebug, slowdebug and optimized]) fi + + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi + + if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. + DEBUG_LEVEL="release" + fi + + AC_SUBST(HOTSPOT_DEBUG_LEVEL) + AC_SUBST(DEBUG_LEVEL) ]) ############################################################################### @@ -178,10 +203,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then diff --git a/common/autoconf/jdk-version.m4 b/common/autoconf/jdk-version.m4 index 2dc63865c49..3b2fbfb60f1 100644 --- a/common/autoconf/jdk-version.m4 +++ b/common/autoconf/jdk-version.m4 @@ -72,6 +72,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(PRODUCT_SUFFIX) AC_SUBST(JDK_RC_PLATFORM_NAME) AC_SUBST(COMPANY_NAME) + AC_SUBST(HOTSPOT_VM_DISTRO) AC_SUBST(MACOSX_BUNDLE_NAME_BASE) AC_SUBST(MACOSX_BUNDLE_ID_BASE) diff --git a/common/autoconf/lib-std.m4 b/common/autoconf/lib-std.m4 index d3f94609630..6fa0b4844af 100644 --- a/common/autoconf/lib-std.m4 +++ b/common/autoconf/lib-std.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -88,13 +88,25 @@ AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS], # If dynamic was requested, it's available since it would fail above otherwise. # If dynamic wasn't requested, go with static unless it isn't available. AC_MSG_CHECKING([how to link with libstdc++]) - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" AC_MSG_RESULT([dynamic]) else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" AC_MSG_RESULT([static]) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index a6a8bd4f19b..e1e91d678d6 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -74,7 +74,7 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -102,7 +102,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], ################################################################################ AC_DEFUN_ONCE([LIB_SETUP_LLVM], [ - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then AC_CHECK_PROG([LLVM_CONFIG], [llvm-config], [llvm-config]) if test "x$LLVM_CONFIG" != xllvm-config; then diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index fe5a201ecd9..587f80dbcd5 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -273,169 +273,169 @@ AC_DEFUN([PLATFORM_SETUP_TARGET_CPU_BITS], # Setup the legacy variables, for controlling the old makefiles. # AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS], +[ + PLATFORM_SETUP_LEGACY_VARS_HELPER([TARGET]) + PLATFORM_SETUP_LEGACY_VARS_HELPER([BUILD]) + + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + AC_SUBST(ZERO_ARCHDEF) + +]) + +# $1 - Either TARGET or BUILD to setup the variables for. +AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], [ # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY="i586" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY="i586" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_TARGET_CPU_LEGACY="amd64" + OPENJDK_$1_CPU_LEGACY="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY) + AC_SUBST(OPENJDK_$1_CPU_LEGACY) # And the second legacy naming of the cpu. # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_TARGET_CPU_LEGACY_LIB="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_LEGACY_LIB="amd64" + OPENJDK_$1_CPU_LEGACY_LIB="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY_LIB="i386" + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY_LIB="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY_LIB) + AC_SUBST(OPENJDK_$1_CPU_LEGACY_LIB) # This is the name of the cpu (but using i386 and amd64 instead of # x86 and x86_64, respectively), preceeded by a /, to be used when # locating libraries. On macosx, it's empty, though. - OPENJDK_TARGET_CPU_LIBDIR="/$OPENJDK_TARGET_CPU_LEGACY_LIB" - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_CPU_LIBDIR="" + OPENJDK_$1_CPU_LIBDIR="/$OPENJDK_$1_CPU_LEGACY_LIB" + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_CPU_LIBDIR="" fi - AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR) + AC_SUBST(OPENJDK_$1_CPU_LIBDIR) - # Now do the same for OPENJDK_BUILD_CPU... - # Also store the legacy naming of the cpu. - # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY="i586" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_BUILD_CPU_LEGACY="amd64" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY) - - # And the second legacy naming of the cpu. - # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then - OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY_LIB) - - # This is the name of the cpu (but using i386 and amd64 instead of - # x86 and x86_64, respectively), preceeded by a /, to be used when - # locating libraries. On macosx, it's empty, though. - OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" - if test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_CPU_LIBDIR="" - fi - AC_SUBST(OPENJDK_BUILD_CPU_LIBDIR) - - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # OPENJDK_$1_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: - # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so - OPENJDK_TARGET_CPU_ISADIR="" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_ISADIR="/amd64" - elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then - OPENJDK_TARGET_CPU_ISADIR="/sparcv9" + # /usr/lib${OPENJDK_$1_CPU_ISADIR}/libexample.so + OPENJDK_$1_CPU_ISADIR="" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + OPENJDK_$1_CPU_ISADIR="/sparcv9" fi fi - AC_SUBST(OPENJDK_TARGET_CPU_ISADIR) + AC_SUBST(OPENJDK_$1_CPU_ISADIR) - # Setup OPENJDK_TARGET_CPU_OSARCH, which is used to set the os.arch Java system property - OPENJDK_TARGET_CPU_OSARCH="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xx86; then + # Setup OPENJDK_$1_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_$1_CPU_OSARCH="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_OS" = xlinux && test "x$OPENJDK_$1_CPU" = xx86; then # On linux only, we replace x86 with i386. - OPENJDK_TARGET_CPU_OSARCH="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_OSARCH="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_OSARCH="amd64" + OPENJDK_$1_CPU_OSARCH="amd64" fi - AC_SUBST(OPENJDK_TARGET_CPU_OSARCH) + AC_SUBST(OPENJDK_$1_CPU_OSARCH) - OPENJDK_TARGET_CPU_JLI="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_JLI="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_JLI="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_JLI="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_JLI="amd64" + OPENJDK_$1_CPU_JLI="amd64" fi # Now setup the -D flags for building libjli. - OPENJDK_TARGET_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_TARGET_CPU_JLI\"'" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" + OPENJDK_$1_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_$1_CPU_JLI\"'" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU_ARCH" = xsparc; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" + elif test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" fi fi - AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS) + AC_SUBST(OPENJDK_$1_CPU_JLI_CFLAGS) - OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_JLI="i386" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then - # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_BUILD_CPU_JLI="amd64" - fi - # Now setup the -D flags for building libjli. - OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'" - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" - fi - fi - AC_SUBST(OPENJDK_BUILD_CPU_JLI_CFLAGS) - - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_$1_OS_EXPORT_DIR=${OPENJDK_$1_OS_TYPE} fi - AC_SUBST(OPENJDK_TARGET_OS_EXPORT_DIR) + AC_SUBST(OPENJDK_$1_OS_EXPORT_DIR) - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" + if test "x$OPENJDK_$1_OS" = xlinux || test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_ADD_LP64="-D_LP64=1" fi fi AC_SUBST(LP64,$A_LP64) - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then - if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_ADD_LP64="-D_LP64=1" - fi - fi if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_$1_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi AC_SUBST(DEFINE_CROSS_COMPILE_ARCH) - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac - AC_SUBST(ZERO_ARCHDEF) + # Convert openjdk platform names to hotspot names + + HOTSPOT_$1_OS=${OPENJDK_$1_OS} + if test "x$OPENJDK_$1_OS" = xmacosx; then + HOTSPOT_$1_OS=bsd + fi + AC_SUBST(HOTSPOT_$1_OS) + + HOTSPOT_$1_OS_TYPE=${OPENJDK_$1_OS_TYPE} + if test "x$OPENJDK_$1_OS_TYPE" = xunix; then + HOTSPOT_$1_OS_TYPE=posix + fi + AC_SUBST(HOTSPOT_$1_OS_TYPE) + + HOTSPOT_$1_CPU=${OPENJDK_$1_CPU} + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU=x86_32 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU=sparc + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU=ppc_64 + fi + AC_SUBST(HOTSPOT_$1_CPU) + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_$1_CPU_ARCH=${OPENJDK_$1_CPU_ARCH} + AC_SUBST(HOTSPOT_$1_CPU_ARCH) + + # Setup HOTSPOT_$1_CPU_DEFINE + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU_DEFINE=IA32 + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + HOTSPOT_$1_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xaarch64; then + HOTSPOT_$1_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_$1_CPU" = xsparc; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xppc; then + HOTSPOT_$1_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_$1_CPU" = xs390; then + HOTSPOT_$1_CPU_DEFINE=S390 + elif test "x$OPENJDK_$1_CPU" = ss390x; then + HOTSPOT_$1_CPU_DEFINE=S390 + fi + AC_SUBST(HOTSPOT_$1_CPU_DEFINE) + ]) AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], @@ -521,6 +521,10 @@ AC_DEFUN([PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS], CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" ]) AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], @@ -542,6 +546,11 @@ AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check AC_CHECK_HEADERS([stdio.h], , [ diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 0af5e6d0e2d..a30346427a2 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -82,6 +82,13 @@ OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@ OPENJDK_TARGET_CPU_JLI_CFLAGS:=@OPENJDK_TARGET_CPU_JLI_CFLAGS@ OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@ +HOTSPOT_TARGET_OS := @HOTSPOT_TARGET_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_TARGET_OS_TYPE@ + +HOTSPOT_TARGET_CPU := @HOTSPOT_TARGET_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@ + # We are building on this build system. # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ @@ -192,6 +199,7 @@ PRODUCT_NAME:=@PRODUCT_NAME@ PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@ JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@ COMPANY_NAME:=@COMPANY_NAME@ +HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@ MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@ MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@ USERNAME:=@USERNAME@ @@ -201,11 +209,32 @@ RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX) # How to compile the code: release, fastdebug or slowdebug DEBUG_LEVEL:=@DEBUG_LEVEL@ +HOTSPOT_DEBUG_LEVEL:=@HOTSPOT_DEBUG_LEVEL@ # This is the JDK variant to build. # The JDK variant is a name for a specific set of modules to be compiled for the JDK. JDK_VARIANT:=@JDK_VARIANT@ +# Which JVM variants to build (space-separated list) +JVM_VARIANTS := @JVM_VARIANTS@ + +# Lists of features per variant. Only relevant for the variants listed in +# JVM_VARIANTS. +JVM_FEATURES_server := @JVM_FEATURES_server@ +JVM_FEATURES_client := @JVM_FEATURES_client@ +JVM_FEATURES_core := @JVM_FEATURES_core@ +JVM_FEATURES_minimal := @JVM_FEATURES_minimal@ +JVM_FEATURES_zero := @JVM_FEATURES_zero@ +JVM_FEATURES_zeroshark := @JVM_FEATURES_zeroshark@ +JVM_FEATURES_custom := @JVM_FEATURES_custom@ + +# Used for make-time verifications +VALID_JVM_FEATURES := @VALID_JVM_FEATURES@ +VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@ + +# Control use of precompiled header in hotspot libjvm build +USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ + # Should we compile support for running with a graphical UI? (ie headful) # Should we compile support for running without? (ie headless) SUPPORT_HEADFUL:=@SUPPORT_HEADFUL@ @@ -213,25 +242,11 @@ SUPPORT_HEADLESS:=@SUPPORT_HEADLESS@ # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ -# These are the libjvms that we want to build. -# The java launcher uses the default. -# The others can be selected by specifying -client -server -minimal1 -zero or -zeroshark -# on the java launcher command line. -JVM_VARIANTS:=@JVM_VARIANTS@ -JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ -JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ -JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ -JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ -JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ -JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ +# Legacy support +USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@ -# Universal binaries on macosx MACOSX_UNIVERSAL=@MACOSX_UNIVERSAL@ -# Legacy setting: -debug or -fastdebug -# Still used in version string... -BUILD_VARIANT_RELEASE:=@BUILD_VARIANT_RELEASE@ - # JDK_OUTPUTDIR specifies where a working jvm is built. # You can run $(JDK_OUTPUTDIR)/bin/java # Though the layout of the contents of $(JDK_OUTPUTDIR) is not @@ -318,6 +333,11 @@ MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ # Toolchain type: gcc, clang, solstudio, lxc, microsoft... TOOLCHAIN_TYPE:=@TOOLCHAIN_TYPE@ TOOLCHAIN_VERSION := @TOOLCHAIN_VERSION@ +CC_VERSION_NUMBER := @CC_VERSION_NUMBER@ +CXX_VERSION_NUMBER := @CXX_VERSION_NUMBER@ + +# Legacy support +HOTSPOT_TOOLCHAIN_TYPE := @HOTSPOT_TOOLCHAIN_TYPE@ # Option used to tell the compiler whether to create 32- or 64-bit executables COMPILER_TARGET_BITS_FLAG:=@COMPILER_TARGET_BITS_FLAG@ @@ -336,14 +356,18 @@ LD_OUT_OPTION:=@LD_OUT_OPTION@ AR_OUT_OPTION:=@AR_OUT_OPTION@ # Flags used for overriding the default opt setting for a C/C++ source file. +C_O_FLAG_HIGHEST_JVM:=@C_O_FLAG_HIGHEST_JVM@ C_O_FLAG_HIGHEST:=@C_O_FLAG_HIGHEST@ C_O_FLAG_HI:=@C_O_FLAG_HI@ C_O_FLAG_NORM:=@C_O_FLAG_NORM@ C_O_FLAG_NONE:=@C_O_FLAG_NONE@ +C_O_FLAG_SIZE:=@C_O_FLAG_SIZE@ +CXX_O_FLAG_HIGHEST_JVM:=@CXX_O_FLAG_HIGHEST_JVM@ CXX_O_FLAG_HIGHEST:=@CXX_O_FLAG_HIGHEST@ CXX_O_FLAG_HI:=@CXX_O_FLAG_HI@ CXX_O_FLAG_NORM:=@CXX_O_FLAG_NORM@ CXX_O_FLAG_NONE:=@CXX_O_FLAG_NONE@ +CXX_O_FLAG_SIZE:=@CXX_O_FLAG_SIZE@ C_FLAG_DEPS:=@C_FLAG_DEPS@ CXX_FLAG_DEPS:=@CXX_FLAG_DEPS@ @@ -372,6 +396,23 @@ CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@ LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@ +JVM_CFLAGS := @JVM_CFLAGS@ +JVM_CFLAGS_SYMBOLS := @JVM_CFLAGS_SYMBOLS@ +JVM_LDFLAGS := @JVM_LDFLAGS@ +JVM_ASFLAGS := @JVM_ASFLAGS@ +JVM_LIBS := @JVM_LIBS@ +JVM_RCFLAGS := @JVM_RCFLAGS@ + +# Flags for zeroshark +LLVM_CFLAGS := @LLVM_CFLAGS@ +LLVM_LIBS := @LLVM_LIBS@ +LLVM_LDFLAGS := @LLVM_LDFLAGS@ + +# These flags might contain variables set by a custom extension that is included later. +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ +EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ + CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ CPP:=@FIXPATH@ @CPP@ @@ -628,6 +669,7 @@ XATTR:=@XATTR@ JT_HOME:=@JT_HOME@ JTREGEXE:=@JTREGEXE@ XCODEBUILD=@XCODEBUILD@ +DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ # Build setup diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 263c0a8ff2c..7e7a07c5d8b 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -930,6 +930,17 @@ AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS], rm -rf version-script.map main.c a.out fi AC_SUBST(USING_BROKEN_SUSE_LD) + + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + AC_SUBST(HOTSPOT_TOOLCHAIN_TYPE) ]) # Setup the JTReg Regression Test Harness. diff --git a/common/autoconf/version-numbers b/common/autoconf/version-numbers index dcde2286a29..98f106680b5 100644 --- a/common/autoconf/version-numbers +++ b/common/autoconf/version-numbers @@ -32,6 +32,7 @@ PRODUCT_NAME=OpenJDK PRODUCT_SUFFIX="Runtime Environment" JDK_RC_PLATFORM_NAME=Platform COMPANY_NAME=N/A +HOTSPOT_VM_DISTRO="OpenJDK" # Might need better names for these MACOSX_BUNDLE_NAME_BASE="OpenJDK" diff --git a/common/bin/compare.sh b/common/bin/compare.sh index d073fbbda32..0447334042e 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -732,6 +732,13 @@ compare_bin_file() { SYM_SORT_CMD="cat" fi + if [ -n "$SYMBOLS_DIFF_FILTER" ] && [ -z "$NEED_SYMBOLS_DIFF_FILTER" ] \ + || [[ "$NEED_SYMBOLS_DIFF_FILTER" = *"$BIN_FILE"* ]]; then + this_SYMBOLS_DIFF_FILTER="$SYMBOLS_DIFF_FILTER" + else + this_SYMBOLS_DIFF_FILTER="$CAT" + fi + # Check symbols if [ "$OPENJDK_TARGET_OS" = "windows" ]; then # The output from dumpbin on windows differs depending on if the debug symbol @@ -750,8 +757,16 @@ compare_bin_file() { $NM -j $ORIG_OTHER_FILE 2> /dev/null | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other $NM -j $ORIG_THIS_FILE 2> /dev/null | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this else - $NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other - $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this + $NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME \ + | $AWK '{print $2, $3, $4, $5}' \ + | eval "$this_SYMBOLS_DIFF_FILTER" \ + | $SYM_SORT_CMD \ + > $WORK_FILE_BASE.symbols.other + $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME \ + | $AWK '{print $2, $3, $4, $5}' \ + | eval "$this_SYMBOLS_DIFF_FILTER" \ + | $SYM_SORT_CMD \ + > $WORK_FILE_BASE.symbols.this fi LC_ALL=C $DIFF $WORK_FILE_BASE.symbols.other $WORK_FILE_BASE.symbols.this > $WORK_FILE_BASE.symbols.diff @@ -828,9 +843,10 @@ compare_bin_file() { FULLDUMP_DIFF_FILTER="$CAT" fi $FULLDUMP_CMD $OTHER_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \ - > $WORK_FILE_BASE.fulldump.other 2>&1 + > $WORK_FILE_BASE.fulldump.other 2>&1 & $FULLDUMP_CMD $THIS_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \ - > $WORK_FILE_BASE.fulldump.this 2>&1 + > $WORK_FILE_BASE.fulldump.this 2>&1 & + wait LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this \ > $WORK_FILE_BASE.fulldump.diff @@ -854,18 +870,19 @@ compare_bin_file() { FULLDUMP_MSG=" " DIFF_FULLDUMP= if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then - FULLDUMP_MSG=" ! " + FULLDUMP_MSG=" ! " fi fi fi # Compare disassemble output if [ -n "$DIS_CMD" ] && [ -z "$SKIP_DIS_DIFF" ]; then - # By default we filter out differences that include references to symbols. - # To get a raw diff with the complete disassembly, set - # DIS_DIFF_FILTER="$CAT" - if [ -z "$DIS_DIFF_FILTER" ]; then - DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$' | $SED -r -e 's/(\b|x)([0-9a-fA-F]+)(\b|:|>)/X/g'" + this_DIS_DIFF_FILTER="$CAT" + if [ -n "$DIS_DIFF_FILTER" ]; then + if [ -z "$NEED_DIS_DIFF_FILTER" ] \ + || [[ "$NEED_DIS_DIFF_FILTER" = *"$BIN_FILE"* ]]; then + this_DIS_DIFF_FILTER="$DIS_DIFF_FILTER" + fi fi if [ "$OPENJDK_TARGET_OS" = "windows" ]; then DIS_GREP_ARG=-a @@ -873,9 +890,10 @@ compare_bin_file() { DIS_GREP_ARG= fi $DIS_CMD $OTHER_FILE | $GREP $DIS_GREP_ARG -v $NAME \ - | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1 + | eval "$this_DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1 & $DIS_CMD $THIS_FILE | $GREP $DIS_GREP_ARG -v $NAME \ - | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1 + | eval "$this_DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1 & + wait LC_ALL=C $DIFF $WORK_FILE_BASE.dis.other $WORK_FILE_BASE.dis.this > $WORK_FILE_BASE.dis.diff @@ -884,11 +902,15 @@ compare_bin_file() { DIS_MSG=$($PRINTF "%8d" $DIS_DIFF_SIZE) if [[ "$ACCEPTED_DIS_DIFF" != *"$BIN_FILE"* ]]; then DIFF_DIS=true - if [[ "$KNOWN_DIS_DIFF" != *"$BIN_FILE"* ]]; then + if [ "$MAX_KNOWN_DIS_DIFF_SIZE" = "" ]; then + MAX_KNOWN_DIS_DIFF_SIZE="0" + fi + if [[ "$KNOWN_DIS_DIFF" = *"$BIN_FILE"* ]] \ + && [ "$DIS_DIFF_SIZE" -lt "$MAX_KNOWN_DIS_DIFF_SIZE" ]; then + DIS_MSG=" $DIS_MSG " + else DIS_MSG="*$DIS_MSG*" REGRESSIONS=true - else - DIS_MSG=" $DIS_MSG " fi else DIS_MSG="($DIS_MSG)" diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index 30ae49c6fc1..9a6f85fb734 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -113,21 +113,36 @@ if [ "$OPENJDK_TARGET_OS" = "linux" ]; then ./bin/xjc " - # Issue with __FILE__ usage in generated header files prevent clean fulldump diff of - # server jvm with old hotspot build. - KNOWN_FULLDUMP_DIFF=" - ./lib$OPENJDK_TARGET_CPU_LIBDIR/client/libjvm.so - ./lib$OPENJDK_TARGET_CPU_LIBDIR/server/libjvm.so - ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so - " - - if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then - KNOWN_DIS_DIFF=" - ./lib$OPENJDK_TARGET_CPU_LIBDIR/server/libjvm.so + if [ "$OPENJDK_TARGET_CPU" = "arm" ]; then + # NOTE: When comparing the old and new hotspot builds, the link time + # optimization makes good comparisons impossible. Fulldump compare always + # fails and disassembly can end up with some functions in different order. + # So for now, accept the difference but put a limit on the size. The + # different order of functions shouldn't result in a very big diff. + KNOWN_FULLDUMP_DIFF=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + + # Link time optimization adds random numbers to symbol names + NEED_DIS_DIFF_FILTER=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + DIS_DIFF_FILTER="$SED -r \ + -e 's/\.[0-9]+/.X/g' \ + -e 's/\t[0-9a-f]{4} [0-9a-f]{4} /\tXXXX XXXX /' \ + -e 's/\t[0-9a-f]{5,} /\t /' \ + " + KNOWN_DIS_DIFF=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + MAX_KNOWN_DIS_DIFF_SIZE="3000" + + NEED_SYMBOLS_DIFF_FILTER=" + ./lib$OPENJDK_TARGET_CPU_LIBDIR/minimal/libjvm.so + " + SYMBOLS_DIFF_FILTER="$SED -r \ + -e 's/\.[0-9]+/.X/g' " - DIS_DIFF_FILTER="$SED \ - -e 's/\(:\t\)\([0-9a-z]\{2,2\} \)\{1,7\}/\1/g' \ - -e 's/0x[0-9a-z]\{2,9\}//g'" fi fi @@ -250,15 +265,10 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; SKIP_FULLDUMP_DIFF="true" - # Filter random C++ symbol strings. - # Some numbers differ randomly. + # Random strings looking like this differ: <.XAKoKoPIac2W0OA. DIS_DIFF_FILTER="$SED \ - -e 's/\.[a-zA-Z0-9_\$]\{15\}//g' \ - -e 's/\(\# \)[0-9a-f]*\( <\)/\1\2/g' \ - -e 's/0x[0-9a-f]*$//g' \ - -e 's/0x[0-9a-f]*\([,(>]\)/\1/g' \ - -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /g' \ - -e 's/ [\.A-Za-z0-9%@]\{16\}$/ /g'" + -e 's/<\.[A-Za-z0-9]\{\15}\./<.SYM./' \ + " fi @@ -380,23 +390,18 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "sparcv9" ] ./bin/xjc " - # Some numbers differ randomly. DIS_DIFF_FILTER="$SED \ - -e 's/\$[a-zA-Z0-9_\$]\{15\}//g' \ - -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /g' \ - -e 's/, [0-9a-fx\-]\{1,8\}/, /g' \ - -e 's/call [0-9a-f]\{7\}/call /g' \ + -e 's/^[0-9a-f]\{16\}/:/' \ + -e 's/^ *[0-9a-f]\{3,8\}:/ :/' \ + -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: /' \ + -e 's/\$[a-zA-Z0-9_\$]\{15\}\././' \ -e 's/0x[0-9a-f]\{1,8\}//g' \ - -e 's/\! [0-9a-f]\{1,8\} /! /g'" + -e 's/\! [0-9a-f]\{1,8\} /! /' \ + -e 's/, [0-9a-fx\-]\{1,8\}/, /g' \ + -e 's/call [0-9a-f]\{4,7\}/call /' \ + " - # libjvm.so - # __FILE__ macro usage in debug.hpp causes differences between old and new - # hotspot builds in ad_sparc.o and ad_sparc_clone.o. The .o files compare - # equal when stripped, but at link time differences appear. Removing - # __FILE__ from ShouldNotCallThis() and ShouldNotReachHere() removes - # the differences. KNOWN_DIS_DIFF=" - ./lib/sparcv9/server/libjvm.so ./lib/sparcv9/libsaproc.so " @@ -419,6 +424,7 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then ./demo/jvmti/minst/lib/minst.dll ./bin/attach.dll ./bin/jsoundds.dll + ./bin/client/jvm.dll ./bin/server/jvm.dll ./bin/appletviewer.exe ./bin/idlj.exe @@ -469,22 +475,39 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then ./bin/jabswitch.exe " - # On windows, there are unavoidable allignment issues making - # a perfect disasm diff impossible. Filter out the following: - # * Random parts of C++ symbols (this is a bit greedy, but does the trick) - # @XXXXX - # * Hexadecimal addresses that are sometimes alligned differently. - # * Dates in version strings XXXX_XX_XX. - DIS_DIFF_FILTER="$SED \ - -e 's/^ [0-9A-F]\{16\}: //g' \ - -e 's/[@?][A-Za-z0-9_]\{1,25\}//g' \ - -e 's/\([\[+]\)[0-9A-F]\{4,16\}h\]/\1]/g' \ - -e 's/_[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}/_/g'" - #DIS_DIFF_FILTER="$CAT" + if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then + DIS_DIFF_FILTER="$SED -r \ + -e 's/^ [0-9A-F]{16}: //' \ + -e 's/^ [0-9A-F]{8}: / : /' \ + -e 's/(offset \?\?)_C@_.*/\1/' \ + -e 's/[@?][A-Za-z0-9_]{1,25}//' \ + -e 's/([-,+])[0-9A-F]{2,16}/\1/g' \ + -e 's/\[[0-9A-F]{4,16}h\]/[]/' \ + -e 's/: ([a-z]{2}[a-z ]{2}) [0-9A-F]{2,16}h?$/: \1 /' \ + -e 's/_20[0-9]{2}_[0-1][0-9]_[0-9]{2}/_/' \ + " + elif [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then + DIS_DIFF_FILTER="$SED -r \ + -e 's/^ [0-9A-F]{16}: //' \ + -e 's/\[[0-9A-F]{4,16}h\]/[]/' \ + -e 's/([,+])[0-9A-F]{2,16}h/\1/' \ + -e 's/([a-z]{2}[a-z ]{2}) [0-9A-F]{4,16}$/\1 /' \ + -e 's/\[\?\?_C@_.*/[]/' \ + " + fi SKIP_BIN_DIFF="true" SKIP_FULLDUMP_DIFF="true" + # NOTE: When comparing the old and new hotspot builds, the server jvm.dll + # cannot be made equal in disassembly. Some functions just always end up + # in different order. So for now, accept the difference but put a limit + # on the size. The different order of functions shouldn't result in a very + # big diff. + KNOWN_DIS_DIFF=" + ./bin/server/jvm.dll + " + MAX_KNOWN_DIS_DIFF_SIZE="2000000" fi @@ -565,6 +588,7 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then ./Contents/Home/lib/libverify.dylib ./Contents/Home/lib/libsaproc.dylib ./Contents/Home/lib/libsplashscreen.dylib + ./Contents/Home/lib/server/libjsig.dylib ./Contents/Home/lib/server/libjvm.dylib ./Contents/Home/lib/deploy/JavaControlPanel.prefPane/Contents/MacOS/JavaControlPanel ./Contents/Resources/JavaControlPanelHelper @@ -590,6 +614,7 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then ./lib/libverify.dylib ./lib/libsaproc.dylib ./lib/libsplashscreen.dylib + ./lib/server/libjsig.dylib ./lib/server/libjvm.dylib ./lib/deploy/JavaControlPanel.prefPane/Contents/MacOS/JavaControlPanel ./Versions/A/Resources/finish_installation.app/Contents/MacOS/finish_installation @@ -606,7 +631,8 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then DIS_DIFF_FILTER="LANG=C $SED \ -e 's/0x[0-9a-f]\{3,16\}//g' -e 's/^[0-9a-f]\{12,20\}//' \ - -e 's/## literal pool for: .Java HotSpot(TM) 64-Bit Server VM.*//g' + -e 's/-20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]-[0-2][0-9]\{5\}//g' \ + -e 's/), built on .*/), /' \ " fi diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index a3372cf3fe2..123c6be1f29 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -241,7 +241,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "linux", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -259,7 +259,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "macosx", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -267,7 +267,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -275,7 +275,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "sparcv9", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, diff --git a/make/Jprt.gmk b/make/Jprt.gmk index 6b778293d2a..e7eba24bd31 100644 --- a/make/Jprt.gmk +++ b/make/Jprt.gmk @@ -108,7 +108,9 @@ SRC_JDK_MACOSX_BUNDLE_DIR := $(JDK_MACOSX_BUNDLE_DIR) SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR) # Bundle up the images -bundles: all +JPRT_TARGET ?= all +ifeq ($(JPRT_TARGET), all) + bundles: $(JPRT_TARGET) @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r \ @@ -128,9 +130,24 @@ bundles: all $(BUILD_OUTPUT)/bundles/$(SYMBOLS_IMAGE_SUBDIR).zip . ; \ fi @$(call TargetExit) +else + # Just fake the bundles + bundles: $(JPRT_TARGET) + @$(call TargetEnter) + $(MKDIR) -p $(BUILD_OUTPUT)/bundles + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/modules.zip README + @$(call TargetExit) +endif # Copy images to one unified location regardless of platform etc. -final-images: all +final-images: $(JPRT_TARGET) @$(call TargetEnter) $(RM) -r $(BUILD_OUTPUT)/final-images $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) diff --git a/make/Main.gmk b/make/Main.gmk index 5d8137f2b47..6f77baa92eb 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -229,10 +229,17 @@ ALL_TARGETS += $(LAUNCHER_TARGETS) ifeq ($(BUILD_HOTSPOT),true) hotspot: - +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + ifeq ($(USE_NEW_HOTSPOT_BUILD), true) + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f BuildHotspot.gmk) + else + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + endif endif -ALL_TARGETS += hotspot +hotspot-ide-project: + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f ide/CreateVSProject.gmk) + +ALL_TARGETS += hotspot hotspot-ide-project ################################################################################ # Build demos and samples targets @@ -462,6 +469,8 @@ else $(JAVA_TARGETS): interim-langtools + hotspot-ide-project: hotspot exploded-image + import-hotspot: hotspot generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 7ed52135f28..dd9de199f37 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -730,6 +730,16 @@ endif PathList = \ "$(subst $(SPACE),$(PATH_SEP),$(strip $1))" +################################################################################ +# Check if a specified hotspot variant is being built, or at least one of a +# list of variants. Will return 'true' or 'false'. +# $1 - the variant to test for +check-jvm-variant = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_VARIANTS), $1), \ + $(error Internal error: Invalid variant tested: $1)) \ + $(if $(filter $1, $(JVM_VARIANTS)), true, false)) + ################################################################################ # Hook to include the corresponding custom file, if present. diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index d6a003a8c8e..d595e044013 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -197,14 +197,51 @@ define add_native_source $1_$2_THIS_FILE = -DTHIS_FILE='"$$( Disable the given warnings for the specified toolchain # DISABLED_WARNINGS_C_ Disable the given warnings for the specified toolchain # when compiling C code @@ -331,7 +372,11 @@ endef # toolchain when compiling C++ code # STRIP_SYMBOLS Set to true to strip the final binary if the toolchain allows for it # DEBUG_SYMBOLS Set to false to disable generation of debug symbols +# CFLAGS_DEBUG_SYMBOLS Overrides the default cflags for enabling debug symbols +# CXXFLAGS_DEBUG_SYMBOLS Overrides the default cxxflags for enabling debug symbols # STRIPFLAGS Optionally change the flags given to the strip command +# PRECOMPILED_HEADER Header file to use as precompiled header +# PRECOMPILED_HEADER_EXCLUDE List of source files that should not use PCH SetupNativeCompilation = $(NamedParamsMacroTemplate) define SetupNativeCompilationBody @@ -556,8 +601,10 @@ define SetupNativeCompilationBody endif ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true) - $1_EXTRA_CFLAGS += $(CFLAGS_DEBUG_SYMBOLS) - $1_EXTRA_CXXFLAGS += $(CXXFLAGS_DEBUG_SYMBOLS) + $$(call SetIfEmpty, $1_CFLAGS_DEBUG_SYMBOLS, $(CFLAGS_DEBUG_SYMBOLS)) + $$(call SetIfEmpty, $1_CXXFLAGS_DEBUG_SYMBOLS, $(CXXFLAGS_DEBUG_SYMBOLS)) + $1_EXTRA_CFLAGS += $$($1_CFLAGS_DEBUG_SYMBOLS) + $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_DEBUG_SYMBOLS) endif ifneq (,$$($1_REORDER)) @@ -597,17 +644,23 @@ define SetupNativeCompilationBody endif ifeq (NONE, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NONE) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NONE) + $1_OPT_CFLAGS := $(C_O_FLAG_NONE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE) else ifeq (LOW, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NORM) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NORM) + $1_OPT_CFLAGS := $(C_O_FLAG_NORM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM) else ifeq (HIGH, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HI) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HI) + $1_OPT_CFLAGS := $(C_O_FLAG_HI) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI) else ifeq (HIGHEST, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HIGHEST) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HIGHEST) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST) + else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM) + else ifeq (SIZE, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_SIZE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE) else ifneq (, $$($1_OPTIMIZATION)) $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION)) endif @@ -618,11 +671,65 @@ define SetupNativeCompilationBody # lines for all object files in this setup. This includes at least all the # variables used in the call to add_native_source below. $1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ - $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_OPT_CFLAGS) $$($1_OPT_CXXFLAGS) \ $$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS) $1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps) + ifneq ($$($1_PRECOMPILED_HEADER), ) + ifeq ($(USE_PRECOMPILED_HEADER), 1) + ifeq ($(TOOLCHAIN_TYPE), microsoft) + $1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch + $1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp + $1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch.obj + + $$(eval $$(call add_native_source,$1,$$($1_GENERATED_PCH_SRC), \ + $$($1_OBJECT_DIR),,, \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_SYSROOT_CFLAGS) \ + -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \ + $$($1_CXX),,no_this_file)) + + $1_USE_PCH_FLAGS := \ + -Fp$$($1_PCH_FILE) -Yu$$(notdir $$($1_PRECOMPILED_HEADER)) + + $$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ) + + # Explicitly add the pch obj file first to ease comparing to old + # hotspot build. + $1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS) + + $$($1_GENERATED_PCH_SRC): + $(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@ + + else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), ) + ifeq ($(TOOLCHAIN_TYPE), gcc) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch + $1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled + else ifeq ($(TOOLCHAIN_TYPE), clang) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch + $1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE) + endif + $1_PCH_DEP := $$($1_PCH_FILE).d + $1_PCH_DEP_TARGETS := $$($1_PCH_FILE).d.targets + + -include $$($1_PCH_DEP) + -include $$($1_PCH_DEP_TARGETS) + + $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) + $$(call LogInfo, Generating precompiled header) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, \ + $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ + $$($1_OPT_CFLAGS) \ + -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP) $$< -o $$@) + $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEP) > $$($1_PCH_DEP_TARGETS) + + $$($1_ALL_OBJS): $$($1_PCH_FILE) + + endif + endif + endif + # Now call add_native_source for each source file we are going to compile. $$(foreach p,$$($1_SRCS), \ $$(eval $$(call add_native_source,$1,$$p,$$($1_OBJECT_DIR), \ diff --git a/make/jprt.properties b/make/jprt.properties index 943f15b5be5..40a75b1140f 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -129,9 +129,15 @@ jprt.build.flavor.optimized.target=jprt_bundle jprt.build.flavor.optimizedOpen.target=jprt_bundle jprt.build.flavor.slowdebug.target=jprt_bundle -# Use these configure args to define debug level +# Use these configure args to define debug level or provide specific +# configuration details not covered by Jib profiles. jprt.slowdebug.build.configure.args= jprt.fastdebug.build.configure.args=--disable-precompiled-headers +# Don't disable precompiled headers on windows. It's simply too slow. +jprt.windows_i586.fastdebug.build.configure.args= +jprt.windows_x64.fastdebug.build.configure.args= +jprt.windows_i586.fastdebugOpen.build.configure.args= +jprt.windows_x64.fastdebugOpen.build.configure.args= jprt.product.build.configure.args= jprt.optimized.build.configure.args=--with-debug-level=optimized jprt.slowdebugOpen.build.configure.args=${jprt.slowdebug.build.configure.args} From 87d68625afddda5556bf5c9bcb274002fb34bb38 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 8 Apr 2016 13:14:23 +0200 Subject: [PATCH 112/167] 8152666: The new Hotspot Build System Co-authored-by: Magnus Ihse Bursie Co-authored-by: Ingemar Aberg Reviewed-by: ihse, dcubed, erikj --- hotspot/make/Makefile | 18 +- hotspot/make/aix/makefiles/trace.make | 10 +- hotspot/make/bsd/makefiles/trace.make | 10 +- hotspot/make/linux/makefiles/gcc.make | 4 +- hotspot/make/linux/makefiles/trace.make | 10 +- hotspot/make/linux/makefiles/zero.make | 5 + hotspot/make/solaris/makefiles/dtrace.make | 2 +- hotspot/make/solaris/makefiles/trace.make | 10 +- hotspot/make/windows/makefiles/debug.make | 6 +- hotspot/make/windows/makefiles/fastdebug.make | 6 +- hotspot/make/windows/makefiles/product.make | 7 +- hotspot/make/windows/makefiles/trace.make | 6 + hotspot/make/windows/makefiles/vm.make | 4 +- hotspot/makefiles/BuildHotspot.gmk | 54 ++++ hotspot/makefiles/Dist.gmk | 239 +++++++++++++++++ hotspot/makefiles/HotspotCommon.gmk | 45 ++++ hotspot/makefiles/gensrc/GenerateSources.gmk | 75 ++++++ hotspot/makefiles/gensrc/GensrcAdlc.gmk | 192 ++++++++++++++ hotspot/makefiles/gensrc/GensrcDtrace.gmk | 56 ++++ hotspot/makefiles/gensrc/GensrcJvmti.gmk | 174 +++++++++++++ hotspot/makefiles/ide/CreateVSProject.gmk | 153 +++++++++++ .../makefiles/lib/CompileDtracePostJvm.gmk | 217 ++++++++++++++++ hotspot/makefiles/lib/CompileDtracePreJvm.gmk | 36 +++ hotspot/makefiles/lib/CompileJvm.gmk | 242 ++++++++++++++++++ hotspot/makefiles/lib/CompileLibjsig.gmk | 106 ++++++++ hotspot/makefiles/lib/CompileLibraries.gmk | 42 +++ hotspot/makefiles/lib/JvmFeatures.gmk | 144 +++++++++++ hotspot/makefiles/lib/JvmMapfile.gmk | 172 +++++++++++++ hotspot/makefiles/lib/JvmOverrideFiles.gmk | 168 ++++++++++++ .../mapfiles/libjsig/mapfile-vers-solaris | 38 +++ .../makefiles/mapfiles/libjvm_db/mapfile-vers | 38 +++ .../mapfiles/libjvm_dtrace/mapfile-vers | 37 +++ hotspot/makefiles/symbols/symbols-aix | 27 ++ hotspot/makefiles/symbols/symbols-aix-debug | 26 ++ hotspot/makefiles/symbols/symbols-linux | 27 ++ hotspot/makefiles/symbols/symbols-macosx | 24 ++ hotspot/makefiles/symbols/symbols-shared | 35 +++ hotspot/makefiles/symbols/symbols-solaris | 25 ++ .../symbols/symbols-solaris-dtrace-compiler1 | 34 +++ .../symbols/symbols-solaris-dtrace-compiler2 | 36 +++ hotspot/makefiles/symbols/symbols-unix | 195 ++++++++++++++ 41 files changed, 2714 insertions(+), 41 deletions(-) create mode 100644 hotspot/makefiles/BuildHotspot.gmk create mode 100644 hotspot/makefiles/Dist.gmk create mode 100644 hotspot/makefiles/HotspotCommon.gmk create mode 100644 hotspot/makefiles/gensrc/GenerateSources.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcAdlc.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcDtrace.gmk create mode 100644 hotspot/makefiles/gensrc/GensrcJvmti.gmk create mode 100644 hotspot/makefiles/ide/CreateVSProject.gmk create mode 100644 hotspot/makefiles/lib/CompileDtracePostJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileDtracePreJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileJvm.gmk create mode 100644 hotspot/makefiles/lib/CompileLibjsig.gmk create mode 100644 hotspot/makefiles/lib/CompileLibraries.gmk create mode 100644 hotspot/makefiles/lib/JvmFeatures.gmk create mode 100644 hotspot/makefiles/lib/JvmMapfile.gmk create mode 100644 hotspot/makefiles/lib/JvmOverrideFiles.gmk create mode 100644 hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris create mode 100644 hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers create mode 100644 hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers create mode 100644 hotspot/makefiles/symbols/symbols-aix create mode 100644 hotspot/makefiles/symbols/symbols-aix-debug create mode 100644 hotspot/makefiles/symbols/symbols-linux create mode 100644 hotspot/makefiles/symbols/symbols-macosx create mode 100644 hotspot/makefiles/symbols/symbols-shared create mode 100644 hotspot/makefiles/symbols/symbols-solaris create mode 100644 hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 create mode 100644 hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 create mode 100644 hotspot/makefiles/symbols/symbols-unix diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 4312c797579..db2b96e25e0 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -237,19 +237,21 @@ else $(MAKE_ARGS) $(VM_TARGET) endif +# NOTE: Changes in this file was just to facilitate comparison when +# developing the new build, and should not be integrated. generic_buildcore: $(HOTSPOT_SCRIPT) -ifeq ($(HS_ARCH),ppc) - ifeq ($(ARCH_DATA_MODEL),64) +#ifeq ($(HS_ARCH),ppc) +# ifeq ($(ARCH_DATA_MODEL),64) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) - else - @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" -endif +# else +# @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" +# endif +#else +# @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" +#endif generic_buildzero: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index f4f9e7f8e6c..f17e75e1f4f 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index af46df58ce0..37df4425f50 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index a2e5c6c03b6..75dcaeb2c34 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -221,7 +221,7 @@ ifeq ($(USE_CLANG),) ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" # GCC < 4.3 WARNING_FLAGS += -Wconversion - endif + endif ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1" # GCC >= 4.8 # This flag is only known since GCC 4.3. Gcc 4.8 contains a fix so that with templates no @@ -260,7 +260,7 @@ endif OPT_CFLAGS = $(OPT_CFLAGS/$(OPT_CFLAGS_DEFAULT)) $(OPT_EXTRAS) -# Variable tracking size limit exceeded for VMStructs::init() +# Variable tracking size limit exceeded for VMStructs::init() ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "1" # GCC >= 4.3 # Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file. diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 09cb921094e..2209716d35b 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/zero.make b/hotspot/make/linux/makefiles/zero.make index 0270711f5cb..622710f4dfa 100644 --- a/hotspot/make/linux/makefiles/zero.make +++ b/hotspot/make/linux/makefiles/zero.make @@ -30,3 +30,8 @@ TYPE = ZERO # Install libjvm.so, etc in in server directory. VM_SUBDIR = server + +# Disable trace for zero builds +# NOTE: This is used for simple comparison with the new build system, and +# should not be merged into mainline with build-infra. +INCLUDE_TRACE := false diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 376732d0e6b..2c65059a213 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -270,7 +270,7 @@ $(DTRACE.o): $(DTRACE).d $(DTraced_Files) @echo $(LOG_INFO) Compiling $(DTRACE).d $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ - $(DTraced_Files) ||\ + $(sort $(DTraced_Files)) ||\ STATUS=$$?;\ if [ x"$$STATUS" = x"1" ]; then \ if [ x`uname -r` = x"5.10" -a \ diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ed7046295b3..effe34061ce 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make index f2ecd269887..3ad45627467 100644 --- a/hotspot/make/windows/makefiles/debug.make +++ b/hotspot/make/windows/makefiles/debug.make @@ -48,10 +48,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-debug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make index cbcfd5abb04..ea6fc41a42a 100644 --- a/hotspot/make/windows/makefiles/fastdebug.make +++ b/hotspot/make/windows/makefiles/fastdebug.make @@ -47,10 +47,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-fastdebug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make index cd3a4e70bc5..09e750acc07 100644 --- a/hotspot/make/windows/makefiles/product.make +++ b/hotspot/make/windows/makefiles/product.make @@ -51,10 +51,11 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING) # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) + !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/trace.make b/hotspot/make/windows/makefiles/trace.make index eecc890663f..d52391386d0 100644 --- a/hotspot/make/windows/makefiles/trace.make +++ b/hotspot/make/windows/makefiles/trace.make @@ -41,6 +41,12 @@ HAS_ALT_SRC = true !endif !endif +!ifndef OPENJDK +!if EXISTS($(TraceAltSrcDir)) +HAS_ALT_SRC = true +!endif +!endif + TraceGeneratedNames = \ traceEventClasses.hpp \ traceEventIds.hpp \ diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index fd42111866b..a1391a04413 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -305,8 +305,10 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi # This guy should remain a single colon rule because # otherwise we can't specify the output filename. +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. {$(COMMONSRC)\os\windows\vm}.rc.res: - @$(RC) $(RC_FLAGS) /fo"$@" $< + $(RC) $(RC_FLAGS) /fo"$@" $< {$(COMMONSRC)\cpu\$(Platform_arch)\vm}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< diff --git a/hotspot/makefiles/BuildHotspot.gmk b/hotspot/makefiles/BuildHotspot.gmk new file mode 100644 index 00000000000..4ae7b84c387 --- /dev/null +++ b/hotspot/makefiles/BuildHotspot.gmk @@ -0,0 +1,54 @@ +# +# Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +VARIANT_TARGETS := $(foreach v, $(JVM_VARIANTS), variant-$v) +VARIANT_GENSRC_TARGETS := $(addsuffix -gensrc, $(VARIANT_TARGETS)) +VARIANT_LIBS_TARGETS := $(addsuffix -libs, $(VARIANT_TARGETS)) + +$(VARIANT_GENSRC_TARGETS): variant-%-gensrc: + $(call LogWarn, Building JVM variant '$*' with features '$(JVM_FEATURES_$*)') + +$(MAKE) -f gensrc/GenerateSources.gmk JVM_VARIANT=$* + +$(VARIANT_LIBS_TARGETS): variant-%-libs: variant-%-gensrc + +$(MAKE) -f lib/CompileLibraries.gmk JVM_VARIANT=$* + +$(VARIANT_TARGETS): variant-%: variant-%-gensrc variant-%-libs + +jsig: + +$(MAKE) -f lib/CompileLibjsig.gmk + +dist: $(VARIANT_TARGETS) jsig + +$(MAKE) -f Dist.gmk + +all: dist + +.PHONY: $(VARIANT_TARGETS) $(VARIANT_GENSRC_TARGETS) $(VARIANT_LIBS_TARGETS) \ + jsig dist all diff --git a/hotspot/makefiles/Dist.gmk b/hotspot/makefiles/Dist.gmk new file mode 100644 index 00000000000..bfe3daf2062 --- /dev/null +++ b/hotspot/makefiles/Dist.gmk @@ -0,0 +1,239 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +################################################################################ +# Copy the generated output into well-defined places in the dist directory. + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +$(eval $(call IncludeCustomExtension, hotspot, Dist.gmk)) + +DIST_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/dist + +# Unfortunately, all platforms have different target subdirs. +ifeq ($(OPENJDK_TARGET_OS), windows) + LIB_SUBDIR := bin +else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIB_SUBDIR := lib +else + LIB_SUBDIR := lib$(OPENJDK_TARGET_CPU_LIBDIR) +endif + +################################################################################ +# Functions to setup copying of files for variants + +# Support macro for SetupDistLibFile +define macosx_universalize + $(MKDIR) -p $(@D) + $(LIPO) -create -output $@ $< +endef + +################################################################################ +# Setup make rules to copy a native library and associated data. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# NAME -- The base name of the native library (e.g. 'jvm') +# VARIANT -- The variant to copy from +# VARIANT_TARGET_DIR -- The variant target sub dir, with trailing slash, optional +SetupDistLibFile = $(NamedParamsMacroTemplate) +define SetupDistLibFileBody + ifneq ($$($1_VARIANT), ) + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_VARIANT)/lib$$($1_NAME) + else + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/lib$$($1_NAME) + endif + $1_LIB_NAME := $(LIBRARY_PREFIX)$$($1_NAME) + $1_TARGET_DIR := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$$($1_VARIANT_TARGET_DIR) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # We must use the 'universalize' macro to run lipo on shared libraries, at + # least until JDK-8069540 is fixed. + $1_MACRO := macosx_universalize + endif + + # Copy the the native library. + $$(eval $$(call SetupCopyFiles, $1_COPY_LIB, \ + DEST := $$($1_TARGET_DIR), \ + MACRO := $$($1_MACRO), \ + FILES := $$(wildcard \ + $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX)), \ + )) + + TARGETS += $$($1_COPY_LIB) + + # Copy related data (debug symbols, static-build symbols file etc) + $$(eval $$(call SetupCopyFiles, $1_COPY_FILES, \ + DEST := $$($1_TARGET_DIR), \ + FILES := $$(wildcard \ + $$(addprefix $$($1_SRC_DIR)/$$($1_LIB_NAME), \ + .diz .debuginfo .pdb .map .symbols)), \ + )) + + TARGETS += $$($1_COPY_FILES) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # Debug symbols on macosx is a directory, not a single file, per library. + $1_DSYM_SRC := $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX).dSYM) + ifneq ($$(wildcard $$($1_DSYM_SRC)), ) + $$(eval $$(call SetupCopyFiles, $1_COPY_DSYM_DIR, \ + DEST := $$($1_TARGET_DIR), \ + SRC := $$($1_SRC_DIR), \ + FILES := $$(shell $(FIND) $$($1_DSYM_SRC) -type f), \ + )) + TARGETS += $$($1_COPY_DSYM_DIR) + endif + endif +endef + +################################################################################ +# Copy common files, which are independent on the jvm variant(s) being built. +# For files that were generated during the build, we assume all versions of +# these files are identical, and just pick one arbitrarily to use as source. + +ANY_JVM_VARIANT := $(firstword $(JVM_VARIANTS)) +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(ANY_JVM_VARIANT) + +### Copy platform-independent .h files +INCLUDE_FILES_SRC_DIR := $(HOTSPOT_TOPDIR)/src/share/vm +$(eval $(call SetupCopyFiles, COPY_INCLUDE, \ + SRC := $(INCLUDE_FILES_SRC_DIR), \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(INCLUDE_FILES_SRC_DIR)/prims/jni.h \ + $(INCLUDE_FILES_SRC_DIR)/code/jvmticmlr.h \ + $(INCLUDE_FILES_SRC_DIR)/services/jmm.h)) + +TARGETS += $(COPY_INCLUDE) + +### Copy jni_md.h + +# This might have been defined in a custom extension +ifeq ($(JNI_MD_H_SRC), ) + JNI_MD_H_SRC := $(HOTSPOT_TOPDIR)/src/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/jni_$(HOTSPOT_TARGET_CPU_ARCH).h +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: This should most likely be darwin, but the old hotspot build uses bsd + JNI_MD_SUBDIR := bsd +else ifeq ($(OPENJDK_TARGET_OS), windows) + JNI_MD_SUBDIR := win32 +else + JNI_MD_SUBDIR := $(OPENJDK_TARGET_OS) +endif + +# SetupCopyFiles is not used here since it's non-trivial to copy a single +# file with a different target name. +$(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h: $(JNI_MD_H_SRC) + $(call LogInfo, Copying hotspot/dist/include/$(JNI_MD_SUBDIR)/jni_md.h) + $(install-file) + +TARGETS += $(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h + +$(eval $(call SetupCopyFiles, COPY_JVMTI_H, \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h)) + +TARGETS += $(COPY_JVMTI_H) + +# NOTE: In the old build, this file was not copied on Windows. +ifneq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \ + DEST := $(DIST_OUTPUTDIR)/docs/platform/jvmti, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.html)) +endif + +TARGETS += $(COPY_JVMTI_HTML) + +ifeq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ + DEST := $(DIST_OUTPUTDIR)/lib, \ + FILES :=$(JVM_VARIANT_OUTPUTDIR)/libjvm/objs/jvm.lib)) + + TARGETS += $(COPY_JVM_LIB) +endif + +# Copy libjsig, if it exists +$(eval $(call SetupDistLibFile, DIST_jsig, \ + NAME := jsig, \ +)) + +################################################################################ +# Copy variant-specific files + +# Setup make rules to copy a single variant to dist. +# $1: The name of the variant +define SetupDistForVariant + ifneq ($$(filter client minimal, $1), ) + VARIANT_TARGET_DIR := $1 + else + # Use 'server' as default target directory name for all other variants. + VARIANT_TARGET_DIR := server + endif + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm, \ + NAME := jvm, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the dtrace libraries, if they exist + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_db, \ + NAME := jvm_db, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_dtrace, \ + NAME := jvm_dtrace, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the Xusage.txt file + $$(eval $$(call SetupCopyFiles, DIST_$(strip $1)_Xusage, \ + DEST := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$(strip $1), \ + FILES := $$(HOTSPOT_OUTPUTDIR)/variant-$(strip $1)/support/misc/Xusage.txt, \ + )) + + TARGETS += $$(DIST_$(strip $1)_Xusage) +endef + +$(foreach variant, $(JVM_VARIANTS), \ + $(eval $(call SetupDistForVariant, $(variant))) \ +) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/HotspotCommon.gmk b/hotspot/makefiles/HotspotCommon.gmk new file mode 100644 index 00000000000..1df3f4fa9b3 --- /dev/null +++ b/hotspot/makefiles/HotspotCommon.gmk @@ -0,0 +1,45 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +ifeq ($(JVM_VARIANT), ) + $(error This makefile must be called with JVM_VARIANT set) +endif + +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(JVM_VARIANT) +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_SUPPORT_DIR := $(JVM_VARIANT_OUTPUTDIR)/support + +DTRACE_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/dtrace + +################################################################################ + +# Test if a feature is available in the present build of JVM_VARIANT. Will return +# 'true' or 'false'. +# $1 - the feature to test for +check-jvm-feature = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_FEATURES), $1), \ + $(error Internal error: Invalid feature tested: $1)) \ + $(if $(filter $1, $(JVM_FEATURES_$(JVM_VARIANT))), true, false)) diff --git a/hotspot/makefiles/gensrc/GenerateSources.gmk b/hotspot/makefiles/gensrc/GenerateSources.gmk new file mode 100644 index 00000000000..b91f2d0c864 --- /dev/null +++ b/hotspot/makefiles/gensrc/GenerateSources.gmk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include NativeCompilation.gmk +include TextFileProcessing.gmk + +include HotspotCommon.gmk + +# The real work is done in these files + +include gensrc/GensrcAdlc.gmk +include gensrc/GensrcDtrace.gmk +include gensrc/GensrcJvmti.gmk + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GenerateSources.gmk)) + +# While technically the rules below are "gendata" which can be done in parallel +# with native compilation, let's keep it here for simplicity. + +# The Xusage.txt file needs to have platform specific path separator +$(eval $(call SetupTextFileProcessing, CREATE_XUSAGE, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/Xusage.txt, \ + OUTPUT_FILE := $(JVM_SUPPORT_DIR)/misc/Xusage.txt, \ + REPLACEMENTS := separated by ;> => separated by $(PATH_SEP)> ; , \ +)) + +TARGETS += $(CREATE_XUSAGE) + +# Setup the hotspot launcher script for developer use +$(eval $(call SetupTextFileProcessing, CREATE_HOTSPOT_LAUNCHER, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/make/hotspot.script, \ + OUTPUT_FILE := $(JVM_OUTPUTDIR)/hotspot, \ + REPLACEMENTS := \ + @@LIBARCH@@ => $(OPENJDK_TARGET_CPU_LEGACY_LIB) ; \ + @@JDK_IMPORT_PATH@@ => $(JDK_OUTPUTDIR) ; , \ +)) + +CHMOD_HOTSPOT_LAUNCHER := $(JVM_VARIANT_OUTPUTDIR)/libjvm/_hotspot-script-chmod.marker + +$(CHMOD_HOTSPOT_LAUNCHER): $(CREATE_HOTSPOT_LAUNCHER) + $(CHMOD) +x $< + $(TOUCH) $@ + +TARGETS += $(CREATE_HOTSPOT_LAUNCHER) $(CHMOD_HOTSPOT_LAUNCHER) + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/gensrc/GensrcAdlc.gmk b/hotspot/makefiles/gensrc/GensrcAdlc.gmk new file mode 100644 index 00000000000..eb58ac7737c --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcAdlc.gmk @@ -0,0 +1,192 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcAdlc.gmk)) + +ifeq ($(call check-jvm-feature, compiler2), true) + + ADLC_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/adlc + + ############################################################################## + # Build the ad compiler (the adlc build tool) + + # Flags depending on the build platform/tool chain + # NOTE: No optimization or debug flags set here + ifeq ($(OPENJDK_BUILD_OS), linux) + ADLC_CFLAGS := -fno-exceptions -DLINUX + else ifeq ($(OPENJDK_BUILD_OS), solaris) + ADLC_LDFLAGS := -m64 + ADLC_CFLAGS := -m64 + ADLC_CFLAGS_WARNINGS := +w + else ifeq ($(OPENJDK_BUILD_OS), aix) + # FIXME: Not implemented. These flags are likely, however + # ADLC_LDFLAGS := -q64 + # ADLC_CFLAGS := -qnortti -qnoeh -q64 + else ifeq ($(OPENJDK_BUILD_OS), windows) + ADLC_LDFLAGS := -nologo + ADLC_CFLAGS := -nologo -EHsc + # NOTE: The old build also have -D_CRT_SECURE_NO_DEPRECATE but it doesn't + # seem needed any more. + ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS + endif + + # NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to + # hurt. + ADLC_CFLAGS += -DASSERT + + ADLC_CFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE) + + ADLC_CFLAGS += -I$(HOTSPOT_TOPDIR)/src/share/vm + + $(eval $(call SetupNativeCompilation, BUILD_ADLC, \ + TOOLCHAIN := TOOLCHAIN_BUILD_LINK_CXX, \ + SRC := $(HOTSPOT_TOPDIR)/src/share/vm/adlc, \ + EXTRA_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/opto/opcodes.cpp, \ + CFLAGS := $(ADLC_CFLAGS) $(ADLC_CFLAGS_WARNINGS), \ + LDFLAGS := $(ADLC_LDFLAGS), \ + LIBS := $(ADLC_LIBS), \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc, \ + PROGRAM := adlc, \ + DEBUG_SYMBOLS := false, \ + DISABLED_WARNINGS_clang := parentheses tautological-compare, \ + DISABLED_WARNINGS_solstudio := notemsource, \ + )) + + ADLC_TOOL := $(BUILD_ADLC_TARGET) + + ############################################################################## + # Transform the ad source files into C++ source files using adlc + + # Setup flags for the adlc build tool (ADLCFLAGS). + ADLCFLAGS += -q -T + + # ADLC flags depending on target OS + ifeq ($(OPENJDK_TARGET_OS), linux) + ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1 + else ifeq ($(OPENJDK_TARGET_OS), solaris) + ADLCFLAGS += -DSOLARIS=1 -DSPARC_WORKS=1 + else ifeq ($(OPENJDK_TARGET_OS), aix) + # FIXME: Not implemented + else ifeq ($(OPENJDK_TARGET_OS), macosx) + ADLCFLAGS += -D_ALLBSD_SOURCE=1 -D_GNU_SOURCE=1 + endif + + ifneq ($(OPENJDK_TARGET_OS), windows) + # NOTE: Windows adlc flags was different in the old build. Is this really + # correct? + + # -g makes #line directives in the generated C++ files. + ADLCFLAGS += -g + + ADLCFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE)=1 + endif + + # This generates checks in the generated C++ files that _LP64 is correctly + # (un)defined when compiling them. + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + ADLCFLAGS += -D_LP64=1 + else + ADLCFLAGS += -U_LP64 + endif + + ############################################################################## + # Concatenate all ad source files into a single file, which will be fed to + # adlc. Also include a #line directive at the start of every included file + # (after the initial header block), stating the original source file name. + # + # Normally, debugging is done directly on the ad_*.cpp files, but the + # #line directives in those files will be pointing back to .ad. + + # AD_SRC_ROOTS might have been added to by a custom extension + AD_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + + AD_SRC_FILES := $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU).ad \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU_ARCH).ad \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \ + ))) + + SINGLE_AD_SRCFILE := $(ADLC_SUPPORT_DIR)/all-ad-src.ad + + INSERT_FILENAME_AWK_SCRIPT := \ + '{ \ + if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \ + if (need_lineno && $$0 !~ /\/\//) \ + { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \ + print \ + }' + + $(SINGLE_AD_SRCFILE): $(AD_SRC_FILES) + $(call LogInfo, Preprocessing adlc files $(^F)) + $(call MakeDir, $(@D)) + $(NAWK) $(INSERT_FILENAME_AWK_SCRIPT) $^ > $@ + + ############################################################################## + # Run the adlc tool on the single concatenated ad source file, and store the + # output in support/adlc for further processing. + ADLC_RUN_MARKER := $(ADLC_SUPPORT_DIR)/_adlc_run.marker + + $(ADLC_RUN_MARKER): $(BUILD_ADLC) $(SINGLE_AD_SRCFILE) + $(call LogInfo, Generating adlc files) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $(ADLC_SUPPORT_DIR)/adlc_run, \ + $(FIXPATH) $(ADLC_TOOL) $(ADLCFLAGS) $(SINGLE_AD_SRCFILE) \ + -c$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).cpp \ + -h$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).hpp \ + -a$(ADLC_SUPPORT_DIR)/dfa_$(HOTSPOT_TARGET_CPU).cpp \ + -v$(ADLC_SUPPORT_DIR)/adGlobals_$(HOTSPOT_TARGET_CPU).hpp) + $(TOUCH) $@ + + ############################################################################## + # Finally copy the generated files from support/adlc into gensrc/adfiles, + # and postprocess them by fixing dummy #line directives. + + ADLC_GENERATED_FILES := $(addprefix $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/, \ + ad_$(HOTSPOT_TARGET_CPU).cpp \ + ad_$(HOTSPOT_TARGET_CPU).hpp \ + ad_$(HOTSPOT_TARGET_CPU)_clone.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_expand.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_format.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_gen.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_misc.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_peephole.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_pipeline.cpp \ + adGlobals_$(HOTSPOT_TARGET_CPU).hpp \ + dfa_$(HOTSPOT_TARGET_CPU).cpp \ + ) + + $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/%: $(ADLC_RUN_MARKER) + $(call LogInfo, Postprocessing adlc file $*) + $(call MakeDir, $(@D)) + $(NAWK) \ + 'BEGIN { print "#line 1 \"$*\""; } \ + /^#line 999999$$/ {print "#line " (NR+1) " \"$*\""; next} \ + {print}' \ + < $(ADLC_SUPPORT_DIR)/$* > $@ + + TARGETS := $(ADLC_GENERATED_FILES) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcDtrace.gmk b/hotspot/makefiles/gensrc/GensrcDtrace.gmk new file mode 100644 index 00000000000..563f22112fb --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcDtrace.gmk @@ -0,0 +1,56 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +################################################################################ +# Gensrc support for dtrace. The files generated here are included by dtrace.hpp + +ifeq ($(call check-jvm-feature, dtrace), true) + + ifeq ($(OPENJDK_TARGET_OS), solaris) + DTRACE_FLAGS := -64 + DTRACE_CPP_FLAGS := -D_LP64 + else ifeq ($(OPENJDK_TARGET_OS), macosx) + DTRACE_CPP_FLAGS := -D_LP64 -x c + else ifeq ($(OPENJDK_TARGET_OS), linux) + DTRACE_CPP_FLAGS := -x c + endif + + DTRACE_SOURCE_DIR := $(HOTSPOT_TOPDIR)/src/os/posix/dtrace + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_GENSRC_DIR)/%.h: $(DTRACE_SOURCE_DIR)/%.d + $(call LogInfo, Generating dtrace header file $(@F)) + $(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR)) + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + # Process all .d files in DTRACE_SOURCE_DIR. They are: + # hotspot_jni.d hotspot.d hs_private.d + TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \ + $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d)) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcJvmti.gmk b/hotspot/makefiles/gensrc/GensrcJvmti.gmk new file mode 100644 index 00000000000..25f569dc119 --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcJvmti.gmk @@ -0,0 +1,174 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcJvmti.gmk)) + +################################################################################ +# Build tools needed for the JVMTI source code generation + +JVMTI_TOOLS_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_TOOLS_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/tools/jvmti + +$(eval $(call SetupJavaCompiler, GENERATE_OLDBYTECODE, \ + JAVAC := $(JAVAC), \ + FLAGS := $(DISABLE_WARNINGS), \ + SERVER_DIR := $(SJAVAC_SERVER_DIR), \ + SERVER_JVM := $(SJAVAC_SERVER_JAVA), \ + DISABLE_SJAVAC := true, \ +)) + +$(eval $(call SetupJavaCompilation, BUILD_JVMTI_TOOLS, \ + SETUP := GENERATE_OLDBYTECODE, \ + SRC := $(JVMTI_TOOLS_SRCDIR), \ + INCLUDE_FILES := jvmtiGen.java jvmtiEnvFill.java, \ + BIN := $(JVMTI_TOOLS_OUTPUTDIR), \ +)) + +TOOL_JVMTI_GEN := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiGen +TOOL_JVMTI_ENV_FILL := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiEnvFill + +################################################################################ +# Setup make rules for an xml transform for jvmti/trace file generation. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. This name is +# also used as the name of the output file. +# +# Remaining parameters are named arguments. These include: +# XML_FILE -- The input source file to use +# XSL_FILE -- The xsl file to use +# OUTPUT_DIR -- The directory to put the generated file in +# ARGS -- Additional arguments to the jvmtiGen tool +# DEPS -- Additional dependencies +SetupXslTransform = $(NamedParamsMacroTemplate) +define SetupXslTransformBody + $$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSL_FILE) $$($1_DEPS) $$(BUILD_JVMTI_TOOLS) + $$(call LogInfo, Generating $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS)) + # jvmtiGen does not return error code properly on fail. + # NOTE: We should really fix jvmtiGen.java instead. + test -f $$@ + + TARGETS += $$($1_OUTPUT_DIR)/$1 +endef + +################################################################################ +# Create JVMTI files in gensrc/jvmtifiles + +JVMTI_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles + +# Setup rule for generating a jvmti file +# +# $1 is generated source file name in $(JVMTI_OUTPUTDIR) +# $2 is XSL file to use in $(JVMTI_SRCDIR) +# $3 is optional extra arguments to jvmtiGen +define SetupJvmtiGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(JVMTI_SRCDIR)/jvmti.xml, \ + XSL_FILE := $$(JVMTI_SRCDIR)/$(strip $2), \ + OUTPUT_DIR := $$(JVMTI_OUTPUTDIR), \ + ARGS := $3, \ + DEPS := $$(JVMTI_SRCDIR)/jvmtiLib.xsl, \ + )) +endef + +$(eval $(call SetupJvmtiGeneration, jvmtiEnter.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnterTrace.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti -PARAM trace Trace)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnv.hpp, jvmtiHpp.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.h, jvmtiH.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.html, jvmti.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnvStub.cpp, jvmtiEnv.xsl)) + +JVMTI_BC_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/interpreter + +$(eval $(call SetupXslTransform, bytecodeInterpreterWithChecks.cpp, \ + XML_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xml, \ + XSL_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xsl, \ + OUTPUT_DIR := $(JVMTI_OUTPUTDIR), \ + DEPS := $(JVMTI_BC_SRCDIR)/bytecodeInterpreter.cpp, \ +)) + +# We need $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp (generated above) as input +$(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp: $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp $(BUILD_JVMTI_TOOLS) + $(call LogInfo, Generating $(@F)) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, $(TOOL_JVMTI_ENV_FILL) $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp) + # jvmtiEnvFill does not necessarily return an error code on failure. + # NOTE: We should really fix jvmtiEnvFill.java instead. + test -f $@ + +TARGETS += $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp + +################################################################################ +# Create trace files in gensrc/tracefiles + +TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles +TRACE_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/trace + +# Append directories to search (might have been set by custom extensions) +TRACE_SEARCH_DIRS += $(TRACE_SRCDIR) + +TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml + +# Changing these will trigger a rebuild of generated trace files. +TRACE_DEPS += \ + $(TRACE_XML) \ + $(TRACE_SRCDIR)/tracetypes.xml \ + $(TRACE_SRCDIR)/tracerelationdecls.xml \ + $(TRACE_SRCDIR)/traceevents.xml \ + $(TRACE_SRCDIR)/trace.dtd \ + $(TRACE_SRCDIR)/xinclude.mod \ + # + +# Setup rule for generating a trace file +# +# $1 is generated source file name in $(TRACE_OUTPUTDIR) +define SetupTraceGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(TRACE_XML), \ + XSL_FILE := $$(firstword $$(wildcard $$(addsuffix /$$(basename $1).xsl, $$(TRACE_SEARCH_DIRS)))), \ + OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \ + DEPS := $$(TRACE_DEPS), \ + )) +endef + +# Append files to generated (might have been set by custom extensions) +TRACE_GENSRC_FILES += \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp \ + # + +# Call SetupTraceGeneration for all trace gensrc files +$(foreach tracefile, $(TRACE_GENSRC_FILES), \ + $(eval $(call SetupTraceGeneration, $(tracefile))) \ +) diff --git a/hotspot/makefiles/ide/CreateVSProject.gmk b/hotspot/makefiles/ide/CreateVSProject.gmk new file mode 100644 index 00000000000..d804dcce9a8 --- /dev/null +++ b/hotspot/makefiles/ide/CreateVSProject.gmk @@ -0,0 +1,153 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include SetupJavaCompilers.gmk + +ifeq ($(OPENJDK_TARGET_OS), windows) + # The next part is a bit hacky. We include the CompileJvm.gmk to be + # able to extact flags, but we do not wish to execute the rules. + + # Use client as base for defines and includes + JVM_VARIANT=client + + include HotspotCommon.gmk + include lib/CompileJvm.gmk + + # Reset targets so we don't build libjvm. + TARGETS := + + # Helper macro to convert a unix path to a Windows path, suitable for + # inclusion in a command line. + FixPath = \ + $(strip $(subst \,\\,$(shell $(CYGPATH) -w $1))) + + JVM_DEFINES_client := $(patsubst -D%,%, $(filter -D%, $(JVM_CFLAGS))) + EXTRACTED_DEFINES_client := $(addprefix -define , $(JVM_DEFINES_client)) + + JVM_INCLUDES_client := $(patsubst -I%,%, $(filter -I%, $(JVM_CFLAGS))) + EXTRACTED_INCLUDES_client := $(foreach path, $(JVM_INCLUDES_client), -absoluteInclude $(call FixPath, $(path))) + + # Hand-code variant-specific arguments, based on the fact that we use + # client for general arguments. Not optimal but other solutions require + # major changes in ProjectCreator. + ADDITIONAL_VARIANT_ARGS := \ + -define_server COMPILER2 \ + -ignorePath_client adfiles \ + -ignorePath_client c2_ \ + -ignorePath_client runtime_ \ + -ignorePath_client libadt \ + -ignorePath_client opto \ + # + + IGNORED_PLATFORMS_ARGS := \ + -ignorePath aarch64 \ + -ignorePath aix \ + -ignorePath arm \ + -ignorePath bsd \ + -ignorePath linux \ + -ignorePath posix \ + -ignorePath ppc \ + -ignorePath shark \ + -ignorePath solaris \ + -ignorePath sparc \ + -ignorePath x86_32 \ + -ignorePath zero \ + # + + ################################################################################ + # Build the ProjectCreator java tool. + + TOOLS_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/support/tools_classes + + $(eval $(call SetupJavaCompilation, BUILD_PROJECT_CREATOR, \ + SETUP := GENERATE_OLDBYTECODE, \ + ADD_JAVAC_FLAGS := -Xlint:-auxiliaryclass, \ + SRC := $(HOTSPOT_TOPDIR)/makefiles/src/classes, \ + BIN := $(TOOLS_OUTPUTDIR), \ + )) + + TARGETS += $(BUILD_PROJECT_CREATOR) + + # Run the ProjectCreator tool + PROJECT_CREATOR_TOOL := $(JAVA_SMALL) -cp $(TOOLS_OUTPUTDIR) build.tools.projectcreator.ProjectCreator + + IDE_OUTPUTDIR := $(BUILD_OUTPUT)/ide/hotspot-visualstudio + + VCPROJ_FILE := $(IDE_OUTPUTDIR)/jvm.vcxproj + + PROJECT_CREATOR_CLASS := build.tools.projectcreator.WinGammaPlatformVC10 + + # We hard-code gensrc dir to server (since this includes adfiles) + PROJECT_CREATOR_ARGS := \ + -sourceBase $(call FixPath, $(HOTSPOT_TOPDIR)) \ + -startAt src \ + -relativeSrcInclude src \ + -hidePath .hg \ + -hidePath .jcheck \ + -hidePath jdk.hotspot.agent \ + -hidePath jdk.vm.ci \ + -hidePath jdk.jfr \ + -compiler VC10 \ + -jdkTargetRoot $(call FixPath, $(JDK_OUTPUTDIR)) \ + -platformName x64 \ + -buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \ + -buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \ + -makeBinary $(call FixPath, $(MAKE)) \ + -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \ + -absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + -absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + $(EXTRACTED_DEFINES_client) \ + $(EXTRACTED_INCLUDES_client) \ + $(ADDITIONAL_VARIANT_ARGS) \ + $(IGNORED_PLATFORMS_ARGS) \ + # + + VCPROJ_VARDEPS := $(PROJECT_CREATOR_CLASS) $(PROJECT_CREATOR_ARGS) + VCPROJ_VARDEPS_FILE := $(call DependOnVariable, VCPROJ_VARDEPS, \ + $(VCPROJ_FILE).vardeps) + + $(VCPROJ_FILE): $(BUILD_PROJECT_CREATOR) $(VCPROJ_VARDEPS_FILE) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, \ + $(PROJECT_CREATOR_TOOL) $(PROJECT_CREATOR_CLASS) \ + $(PROJECT_CREATOR_ARGS) -projectFileName $(call FixPath, $@)) \ + $(LOG_INFO) + + TARGETS += $(VCPROJ_FILE) + + all: $(TARGETS) + +else + all: + $(info Hotspot Visual Studio generation only supported on Windows) +endif + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileDtracePostJvm.gmk b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk new file mode 100644 index 00000000000..127460a562e --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk @@ -0,0 +1,217 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +################################################################################ +# Support for dtrace integration with libjvm, and stand-alone dtrace library +# compilation. + +ifeq ($(call check-jvm-feature, dtrace), true) + ############################################################################## + + ifeq ($(OPENJDK_TARGET_OS), solaris) + ############################################################################ + # Integrate with libjvm. Here we generate three object files which are + # linked with libjvm.so. This step is complicated from a dependency + # perspective, since it needs the rest of the compiled object files from the + # libjvm compilation, but the output is object files that are to be included + # when linking libjvm.so. So this generation must happen as a part of the + # libjvm compilation. + + # First we need to generate the dtraceGenOffsets tool. When run, this will + # produce more header files and a C++ file. + + # Note that generateJvmOffsets.cpp must be compiled as if it were a file + # in the libjvm.so, using JVM_CFLAGS as setup in CompileJvm.gmk. Otherwise + # this would preferrably have been done as a part of GensrcDtrace.gmk. + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ + SRC := $(HOTSPOT_TOPDIR)/src/os/$(OPENJDK_TARGET_OS)/dtrace, \ + INCLUDE_FILES := generateJvmOffsets.cpp generateJvmOffsetsMain.c, \ + CC := $(BUILD_CXX), \ + CXX := $(BUILD_CXX), \ + LDEXE := $(BUILD_CXX), \ + generateJvmOffsets.cpp_CXXFLAGS := $(JVM_CFLAGS) -mt -xnolib -norunpath, \ + generateJvmOffsetsMain.c_CFLAGS := -library=%none -mt -m64 -norunpath -z nodefs, \ + LDFLAGS := -m64, \ + LIBS := -lc, \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ + PROGRAM := dtraceGenOffsets, \ + )) + + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET) + + # Argument 1: Output filename + # Argument 2: dtrace-gen-offset tool command line option + define SetupDtraceOffsetsGeneration + $1: $$(BUILD_DTRACE_GEN_OFFSETS) + $$(call LogInfo, Generating dtrace $2 file $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@) + + TARGETS += $1 + endef + + JVM_OFFSETS_H := $(DTRACE_SUPPORT_DIR)/JvmOffsets.h + JVM_OFFSETS_CPP := $(DTRACE_SUPPORT_DIR)/JvmOffsets.cpp + JVM_OFFSETS_INDEX_H := $(DTRACE_SUPPORT_DIR)/JvmOffsetsIndex.h + + # Run the dtrace-gen-offset tool to generate these three files. + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table)) + + ############################################################################ + # Compile JVM_OFFSETS_OBJ which is linked with libjvm.so. + + # JvmOffsets.cpp is compiled without the common JVM_CFLAGS. Otherwise, the + # natural way would have been to included this source code in BUILD_LIBJVM. + JVM_OFFSETS_CFLAGS := -m64 + ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_OFFSETS_CFLAGS += -xarch=sparc + endif + + $(JVM_OFFSETS_OBJ): $(JVM_OFFSETS_CPP) $(JVM_OFFSETS_H) + $(call LogInfo, Compiling dtrace file JvmOffsets.cpp (for libjvm.so)) + $(call ExecuteWithLog, $@, $(CXX) -c -I$( $@ + + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + ciEnv.o \ + classLoadingService.o \ + compileBroker.o \ + hashtable.o \ + instanceKlass.o \ + java.o \ + jni.o \ + jvm.o \ + memoryManager.o \ + nmethod.o \ + objectMonitor.o \ + runtimeService.o \ + sharedRuntime.o \ + synchronizer.o \ + thread.o \ + unsafe.o \ + vmThread.o \ + vmGCOperations.o \ + ) + + ifeq ($(call check-jvm-feature, all-gcs), true) + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + vmCMSOperations.o \ + vmPSOperations.o \ + ) + endif + + DTRACE_FLAGS := -64 -G + DTRACE_CPP_FLAGS := -D_LP64 + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.d $(DTRACE_INSTRUMENTED_OBJS) + $(call LogInfo, Generating $(@F) from $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \ + -s $(DTRACE_SUPPORT_DIR)/$(@F).d $(sort $(DTRACE_INSTRUMENTED_OBJS))) + + ############################################################################ + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so. + + # Unfortunately dtrace generates incorrect types for some symbols in + # dtrace_jhelper.o, resulting in "warning: symbol X has differing types" + # This is tracked in JDK-6890703. + $(DTRACE_JHELPER_OBJ): $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace/jhelper.d \ + $(JVM_OFFSETS_INDEX_H) + $(call LogInfo, Running dtrace for $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + # $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \ + # -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + ############################################################################ + # Build the stand-alone dtrace libraries + + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace + + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ + LIBRARY := jvm_dtrace, \ + OUTPUT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := jvm_dtrace.c, \ + CFLAGS := -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := $(LIBDL) -lc -lthread -ldoor, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_dtrace/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db + + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by + # the old build. + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ + LIBRARY := jvm_db, \ + OUTPUT_DIR := $(LIBJVM_DB_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := libjvm_db.c, \ + CFLAGS := -I$(JVM_VARIANT_OUTPUTDIR)/gensrc -I$(DTRACE_SUPPORT_DIR) \ + -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := -lc, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_db/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + # We need the generated JvmOffsets.h before we can compile the libjvm_db source code. + $(BUILD_LIBJVM_DB_ALL_OBJS): $(JVM_OFFSETS_H) + + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB) + endif +endif diff --git a/hotspot/makefiles/lib/CompileDtracePreJvm.gmk b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk new file mode 100644 index 00000000000..20e3aa9be7d --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +ifeq ($(call check-jvm-feature, dtrace), true) + ifeq ($(OPENJDK_TARGET_OS), solaris) + # These files are are generated by CompileDtrace.gmk but consumed by + # CompileJvm.gmk + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o + JVM_OFFSETS_OBJ := $(JVM_OUTPUTDIR)/objs/JvmOffsets.o + + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ) $(JVM_OFFSETS_OBJ) + endif +endif diff --git a/hotspot/makefiles/lib/CompileJvm.gmk b/hotspot/makefiles/lib/CompileJvm.gmk new file mode 100644 index 00000000000..b6404cf74b1 --- /dev/null +++ b/hotspot/makefiles/lib/CompileJvm.gmk @@ -0,0 +1,242 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Include support files that will setup compiler flags due to the selected +# jvm feature set, and specific file overrides. +include lib/JvmFeatures.gmk +include lib/JvmOverrideFiles.gmk + +$(eval $(call IncludeCustomExtension, hotspot, lib/CompileJvm.gmk)) + +################################################################################ +# Setup compilation of the main Hotspot native library (libjvm). + +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_MAPFILE := $(JVM_OUTPUTDIR)/mapfile + +################################################################################ +# Platform independent setup + +# This variable may be added to by a custom extension +JVM_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + +JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \ + $d/share/vm \ + $d/os/$(HOTSPOT_TARGET_OS)/vm \ + $d/os/$(HOTSPOT_TARGET_OS_TYPE)/vm \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + ))) \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles \ + # + +JVM_CFLAGS_INCLUDES += \ + $(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \ + -I$(JVM_VARIANT_OUTPUTDIR)/gensrc \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/precompiled \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/prims \ + # + +JVM_CFLAGS_TARGET_DEFINES += \ + -DTARGET_OS_FAMILY_$(HOTSPOT_TARGET_OS) \ + -DTARGET_ARCH_MODEL_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_OS_ARCH_MODEL_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_OS_ARCH_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ + -D$(HOTSPOT_TARGET_CPU_DEFINE) \ + -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ + # + +ifeq ($(DEBUG_LEVEL), release) + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) + JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT + endif +else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT + ifeq ($(filter $(OPENJDK_TARGET_OS), windows aix), ) + # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. + JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS + endif +else ifeq ($(DEBUG_LEVEL), slowdebug) + # _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler + JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_ +endif + +JVM_CFLAGS += \ + $(JVM_CFLAGS_DEBUGLEVEL) \ + $(JVM_CFLAGS_TARGET_DEFINES) \ + $(JVM_CFLAGS_FEATURES) \ + $(JVM_CFLAGS_INCLUDES) \ + $(EXTRA_CFLAGS) \ + # + +JVM_LDFLAGS += \ + $(SHARED_LIBRARY_FLAGS) \ + $(JVM_LDFLAGS_FEATURES) \ + $(EXTRA_LDFLAGS) \ + # + +JVM_LIBS += \ + $(JVM_LIBS_FEATURES) \ + # + +# These files and directories are always excluded +JVM_EXCLUDE_FILES += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp args.cc +JVM_EXCLUDES += adlc + +# Needed by vm_version.cpp +ifeq ($(OPENJDK_TARGET_CPU), x86_64) + OPENJDK_TARGET_CPU_VM_VERSION := amd64 +else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + OPENJDK_TARGET_CPU_VM_VERSION := sparc +else + OPENJDK_TARGET_CPU_VM_VERSION := $(OPENJDK_TARGET_CPU) +endif + +CFLAGS_VM_VERSION := \ + $(VERSION_CFLAGS) \ + -DHOTSPOT_VERSION_STRING='"$(VERSION_STRING)"' \ + -DDEBUG_LEVEL='"$(DEBUG_LEVEL)"' \ + -DHOTSPOT_BUILD_USER='"$(USERNAME)"' \ + -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"' \ + -DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \ + # + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifeq ($(USE_PRECOMPILED_HEADER), 0) + JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + +################################################################################ +# Platform specific setup + +ifneq ($(filter $(OPENJDK_TARGET_OS), linux macosx windows), ) + JVM_PRECOMPILED_HEADER := $(HOTSPOT_TOPDIR)/src/share/vm/precompiled/precompiled.hpp +endif + +ifneq ($(filter $(OPENJDK_TARGET_OS), macosx aix solaris), ) + # On macosx, aix and solaris we have to link with the C++ compiler + JVM_TOOLCHAIN := TOOLCHAIN_LINK_CXX +else + JVM_TOOLCHAIN := TOOLCHAIN_DEFAULT +endif + +ifeq ($(OPENJDK_TARGET_CPU), x86) + JVM_EXCLUDE_PATTERNS += x86_64 +else ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_EXCLUDE_PATTERNS += x86_32 +endif + +# Inline assembly for solaris +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_x86/vm/solaris_x86_64.il + else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_sparc/vm/solaris_sparc.il + endif +endif + +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), false) + # NOTE: In the old build, we weirdly enough set -g/-g0 always, regardless + # of if debug symbols were needed. Without it, compilation fails on + # sparc! :-( + JVM_CFLAGS += -g0 + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + RC_DESC := 64-Bit$(SPACE) + endif + JVM_RCFLAGS += -D"HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(RC_DESC)$(JVM_VARIANT) VM" +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: The old build did not strip binaries on macosx. + JVM_STRIP_SYMBOLS := false +else + JVM_STRIP_SYMBOLS := true +endif + +JVM_OPTIMIZATION ?= HIGHEST_JVM + +################################################################################ +# Now set up the actual compilation of the main hotspot native library + +$(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ + TOOLCHAIN := $(JVM_TOOLCHAIN), \ + LIBRARY := jvm, \ + OUTPUT_DIR := $(JVM_OUTPUTDIR), \ + SRC := $(JVM_SRC_DIRS), \ + EXCLUDES := $(JVM_EXCLUDES), \ + EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \ + EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \ + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \ + CFLAGS := $(JVM_CFLAGS), \ + CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ + DISABLED_WARNINGS_clang := delete-non-virtual-dtor dynamic-class-memaccess \ + empty-body format logical-op-parentheses parentheses \ + parentheses-equality switch tautological-compare, \ + DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \ + 1540-1088 1500-010, \ + ASFLAGS := $(JVM_ASFLAGS), \ + LDFLAGS := $(JVM_LDFLAGS), \ + LIBS := $(JVM_LIBS), \ + OPTIMIZATION := $(JVM_OPTIMIZATION), \ + OBJECT_DIR := $(JVM_OUTPUTDIR)/objs, \ + MAPFILE := $(JVM_MAPFILE), \ + USE_MAPFILE_FOR_SYMBOLS := true, \ + STRIP_SYMBOLS := $(JVM_STRIP_SYMBOLS), \ + EMBED_MANIFEST := true, \ + RC_FLAGS := $(JVM_RCFLAGS), \ + VERSIONINFO_RESOURCE := $(HOTSPOT_TOPDIR)/src/os/windows/vm/version.rc, \ + PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \ + PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \ +)) + +# AIX warning explanation: +# 1500-010 : (W) WARNING in ...: Infinite loop. Program may not stop. +# There are several infinite loops in the vm, so better suppress. +# 1540-0198 : (W) The omitted keyword "private" is assumed for base class "...". +# 1540-0216 : (W) An expression of type .. cannot be converted to type .. +# In hotspot this fires for functionpointer to pointer conversions +# 1540-1088 : (W) The exception specification is being ignored. +# In hotspot this is caused by throw() in declaration of new() in nmethod.hpp. +# 1540-1090 : (I) The destructor of "..." might not be called. +# 1540-1639 : (I) The behavior of long type bit fields has changed ... + +# Include mapfile generation. It relies on BUILD_LIBJVM_ALL_OBJS which is only +# defined after the above call to BUILD_LIBJVM. Mapfile will be generated +# after all object files are built, but before the jvm library is linked. +include lib/JvmMapfile.gmk + +TARGETS += $(BUILD_LIBJVM) diff --git a/hotspot/makefiles/lib/CompileLibjsig.gmk b/hotspot/makefiles/lib/CompileLibjsig.gmk new file mode 100644 index 00000000000..ba9791cdef8 --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibjsig.gmk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +################################################################################ +# Create the libjsig.so shared library + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +ifneq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(STATIC_BUILD), false) + LIBJSIG_STRIP_SYMBOLS := true + ifeq ($(OPENJDK_TARGET_OS), linux) + LIBJSIG_CFLAGS := -fPIC -D_GNU_SOURCE -D_REENTRANT $(EXTRA_CFLAGS) + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) $(EXTRA_CFLAGS) + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + # Flags for other CPUs can be provided in EXTRA_CFLAGS + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + LIBJSIG_CPU_FLAGS := -m64 + else ifeq ($(OPENJDK_TARGET_CPU), x86) + LIBJSIG_CPU_FLAGS := -m32 -march=i586 + endif + + else ifeq ($(OPENJDK_TARGET_OS), solaris) + LIBJSIG_CFLAGS := -m64 -KPIC -mt + LIBJSIG_LDFLAGS := -m64 -mt -xnolib + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), aix) + LIBJSIG_CFLAGS := -q64 -D_GNU_SOURCE -D_REENTRANT -qpic=large + LIBJSIG_LDFLAGS := -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath -bernotok + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIBJSIG_CFLAGS := -m64 -D_GNU_SOURCE -pthread -mno-omit-leaf-frame-pointer -mstack-alignment=16 -fPIC + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) + # NOTE: This lib is not stripped on macosx in old build. Looks like a mistake. + LIBJSIG_STRIP_SYMBOLS := false + else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in CompileLibjsig.gmk) + endif + + LIBJSIG_SRC_FILE := $(HOTSPOT_TOPDIR)/src/os/$(HOTSPOT_TARGET_OS)/vm/jsig.c + LIBJSIG_MAPFILE := $(wildcard $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) + LIBJSIG_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/libjsig + + LIBJSIG_LDFLAGS += $(SHARED_LIBRARY_FLAGS) + + $(eval $(call SetupNativeCompilation, BUILD_LIBJSIG, \ + LIBRARY := jsig, \ + EXTRA_FILES := $(LIBJSIG_SRC_FILE), \ + OUTPUT_DIR := $(LIBJSIG_OUTPUTDIR), \ + LANG := C, \ + CFLAGS := $(LIBJSIG_CFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LDFLAGS := $(LIBJSIG_LDFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LIBS := $(LIBJSIG_LIBS), \ + MAPFILE := $(LIBJSIG_MAPFILE), \ + OBJECT_DIR := $(LIBJSIG_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := $(LIBJSIG_STRIP_SYMBOLS), \ + )) + + TARGETS += $(BUILD_LIBJSIG) + endif +endif + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileLibraries.gmk b/hotspot/makefiles/lib/CompileLibraries.gmk new file mode 100644 index 00000000000..7a7a1651194 --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibraries.gmk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +include HotspotCommon.gmk + +# The dtrace setup must be done both before and after CompileJvm.gmk, due to +# intricate dependencies. +include lib/CompileDtracePreJvm.gmk +include lib/CompileJvm.gmk +include lib/CompileDtracePostJvm.gmk + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/JvmFeatures.gmk b/hotspot/makefiles/lib/JvmFeatures.gmk new file mode 100644 index 00000000000..40a3247c9a7 --- /dev/null +++ b/hotspot/makefiles/lib/JvmFeatures.gmk @@ -0,0 +1,144 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmFeatures.gmk)) + +################################################################################ +# Setup CFLAGS and EXCLUDES for the libjvm compilation, depending on which +# jvm features are selected for this jvm variant. + +ifeq ($(call check-jvm-feature, compiler1), true) + JVM_CFLAGS_FEATURES += -DCOMPILER1 +else + JVM_EXCLUDE_PATTERNS += c1_ +endif + +ifeq ($(call check-jvm-feature, compiler2), true) + JVM_CFLAGS_FEATURES += -DCOMPILER2 + JVM_SRC_DIRS += $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles +else + JVM_EXCLUDES += opto libadt + JVM_EXCLUDE_FILES += bcEscapeAnalyzer.cpp ciTypeFlow.cpp + JVM_EXCLUDE_PATTERNS += c2_ runtime_ +endif + +ifeq ($(call check-jvm-feature, zero), true) + JVM_CFLAGS_FEATURES += -DZERO -DCC_INTERP -DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS) + JVM_LIBS_FEATURES += $(LIBFFI_LIBS) +endif + +ifeq ($(call check-jvm-feature, shark), true) + JVM_CFLAGS_FEATURES += -DSHARK $(LLVM_CFLAGS) + JVM_LDFLAGS_FEATURES += $(LLVM_LDFLAGS) + JVM_LIBS_FEATURES += $(LLVM_LIBS) +else + JVM_EXCLUDES += shark +endif + +ifeq ($(call check-jvm-feature, minimal), true) + JVM_CFLAGS_FEATURES += -DMINIMAL_JVM -DVMTYPE=\"Minimal\" +endif + +ifeq ($(call check-jvm-feature, dtrace), true) + JVM_CFLAGS_FEATURES += -DDTRACE_ENABLED +endif + +ifeq ($(call check-jvm-feature, static-build), true) + JVM_CFLAGS_FEATURES += -DSTATIC_BUILD=1 +endif + +ifneq ($(call check-jvm-feature, jvmti), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMTI=0 + JVM_EXCLUDE_FILES += jvmtiGetLoadedClasses.cpp jvmtiThreadState.cpp jvmtiExtensions.cpp \ + jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \ + jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \ + jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \ + jvmtiClassFileReconstituter.cpp +endif + +ifneq ($(call check-jvm-feature, jvmci), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMCI=0 + JVM_EXCLUDES += jvmci + JVM_EXCLUDE_FILES += jvmciCodeInstaller_$(HOTSPOT_TARGET_CPU_ARCH).cpp +endif + +ifneq ($(call check-jvm-feature, fprof), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_FPROF=0 + JVM_EXCLUDE_FILES += fprofiler.cpp +endif + +ifneq ($(call check-jvm-feature, vm-structs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_VM_STRUCTS=0 + JVM_EXCLUDE_FILES += vmStructs.cpp +endif + +ifneq ($(call check-jvm-feature, jni-check), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JNI_CHECK=0 + JVM_EXCLUDE_FILES += jniCheck.cpp +endif + +ifneq ($(call check-jvm-feature, services), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_SERVICES=0 + JVM_EXCLUDE_FILES += heapDumper.cpp heapInspection.cpp \ + attachListener_$(HOTSPOT_TARGET_OS).cpp attachListener.cpp +endif + +ifneq ($(call check-jvm-feature, management), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_MANAGEMENT=0 +endif + +ifneq ($(call check-jvm-feature, cds), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0 + JVM_EXCLUDE_FILES += \ + classListParser.cpp \ + classLoaderExt.cpp \ + filemap.cpp \ + metaspaceShared.cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU).cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU_ARCH).cpp \ + sharedClassUtil.cpp \ + sharedPathsMiscInfo.cpp \ + systemDictionaryShared.cpp \ + # +endif + +ifneq ($(call check-jvm-feature, all-gcs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_ALL_GCS=0 + JVM_EXCLUDE_PATTERNS += \ + cms/ g1/ parallel/ + JVM_EXCLUDE_FILES += \ + concurrentGCThread.cpp \ + plab.cpp + JVM_EXCLUDE_FILES += \ + g1MemoryPool.cpp \ + psMemoryPool.cpp +endif + +ifneq ($(call check-jvm-feature, nmt), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_NMT=0 + JVM_EXCLUDE_FILES += \ + memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \ + memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp +endif diff --git a/hotspot/makefiles/lib/JvmMapfile.gmk b/hotspot/makefiles/lib/JvmMapfile.gmk new file mode 100644 index 00000000000..9d7655b26ee --- /dev/null +++ b/hotspot/makefiles/lib/JvmMapfile.gmk @@ -0,0 +1,172 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmMapfile.gmk)) + +################################################################################ +# Combine a list of static symbols + +ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), windows-x86_64) + # On Windows x86_64, we should not have any symbols at all, since that + # results in duplicate warnings from the linker (JDK-8043491). + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-shared +endif + +ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-unix +endif + +ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS) +endif + +ifneq ($(findstring debug, $(DEBUG_LEVEL)), ) + ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(call check-jvm-feature, dtrace), true) + # Additional mapfiles that are only used when dtrace is enabled + ifeq ($(call check-jvm-feature, compiler2), true) + # This also covers the case of compiler1+compiler2. + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler2 + else ifeq ($(call check-jvm-feature, compiler1), true) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler1 + endif + endif +endif + +################################################################################ +# Create a dynamic list of symbols from the built object files. This is highly +# platform dependent. + +ifeq ($(OPENJDK_TARGET_OS), linux) + DUMP_SYMBOLS_CMD := $(NM) --defined-only *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^_ZN9Arguments17SharedArchivePathE$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + DUMP_SYMBOLS_CMD := $(NM) -p *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^__1c.*__vtbl_$$|^gHotSpotVM + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^__1cJArgumentsRSharedArchivePath_$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$2 == "U") next; \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # nm on macosx prints out "warning: nm: no name list" to stderr for + # files without symbols. Hide this, even at the expense of hiding real errors. + DUMP_SYMBOLS_CMD := $(NM) -Uj *.o 2> /dev/null + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +# NOTE: The script is from the old build. It is broken and finds no symbols. +# The script below might be what was intended, but it failes to link with tons +# of 'cannot export hidden symbol vtable for X'. +# '{ if ($$1 ~ /^__ZTV/ || $$1 ~ /^_gHotSpotVM/) print substr($$1, 2) }' +else ifeq ($(OPENJDK_TARGET_OS), aix) + # NOTE: The old build had the solution below. This should to be fixed in + # configure instead. + + # On AIX we have to prevent that we pick up the 'nm' version from the GNU binutils + # which may be installed under /opt/freeware/bin. So better use an absolute path here! + # NM=/usr/bin/nm + + DUMP_SYMBOLS_CMD := $(NM) -X64 -B -C *.o + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if (($$2="d" || $$2="D") && ($$3 ~ /^__vft/ || $$3 ~ /^gHotSpotVM/)) print $$3; \ + if ($$3 ~ /^UseSharedSpaces$$/) print $$3; \ + if ($$3 ~ /^SharedArchivePath__9Arguments$$/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), windows) + DUMP_SYMBOLS_CMD := $(DUMPBIN) -symbols *.obj + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$7 ~ /??_7.*@@6B@/ && $$7 !~ /type_info/) print $$7; \ + }' + +else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in JvmMapfile.gmk) +endif + +# A more correct solution would be to send BUILD_LIBJVM_ALL_OBJS instead of +# cd && *.o, but this will result in very long command lines, which is +# problematic on some platforms. +$(JVM_OUTPUTDIR)/symbols-objects: $(BUILD_LIBJVM_ALL_OBJS) + $(call LogInfo, Generating symbol list from object files) + $(CD) $(JVM_OUTPUTDIR)/objs && \ + $(DUMP_SYMBOLS_CMD) | $(NAWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@ + +SYMBOLS_SRC += $(JVM_OUTPUTDIR)/symbols-objects + +################################################################################ +# Now concatenate all symbol lists into a single file and remove comments. + +$(JVM_OUTPUTDIR)/symbols: $(SYMBOLS_SRC) + $(SED) -e '/^#/d' $^ > $@ + +################################################################################ +# Finally convert the symbol list into a platform-specific mapfile + +$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols + $(call LogInfo, Creating mapfile) + $(RM) $@ + ifeq ($(OPENJDK_TARGET_OS), macosx) + # On macosx, we need to add a leading underscore + $(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp + else ifeq ($(OPENJDK_TARGET_OS), windows) + # On windows, add an 'EXPORTS' header + $(ECHO) "EXPORTS" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp + else + # Assume standard linker script + $(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp + $(PRINTF) " local: \n *; \n }; \n" >> $@.tmp + endif + $(MV) $@.tmp $@ diff --git a/hotspot/makefiles/lib/JvmOverrideFiles.gmk b/hotspot/makefiles/lib/JvmOverrideFiles.gmk new file mode 100644 index 00000000000..1ffcb7455ce --- /dev/null +++ b/hotspot/makefiles/lib/JvmOverrideFiles.gmk @@ -0,0 +1,168 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmOverrideFiles.gmk)) + +################################################################################ +# This file contains explicit overrides of CFLAGS and/or precompiled header +# status for individual files on specific platforms. + +ifeq ($(TOOLCHAIN_TYPE), gcc) + BUILD_LIBJVM_vmStructs.cpp_CXXFLAGS := -fno-var-tracking-assignments -O0 +endif + +ifeq ($(OPENJDK_TARGET_OS), linux) + BUILD_LIBJVM_ostream.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64 + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + + ifeq ($(TOOLCHAIN_TYPE), clang) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + # + endif + endif + + ifeq ($(OPENJDK_TARGET_CPU), x86) + # Performance measurements show that by compiling GC related code, we could + # significantly reduce the GC pause time on 32 bit Linux/Unix platforms by + # compiling without the PIC flag (-fPIC on linux). + # See 6454213 for more details. + ALL_SRC := $(filter %.cpp, $(call CacheFind, $(HOTSPOT_TOPDIR)/src/share/vm)) + NONPIC_FILTER := $(addsuffix %, $(addprefix $(HOTSPOT_TOPDIR)/src/share/vm/, \ + memory oops gc)) + # Due to what looks like a bug in the old build implementation of this, add a + # couple of more files that were accidentally matched as substrings of GC related + # files. + NONPIC_SRC := $(filter $(NONPIC_FILTER), $(ALL_SRC)) globals.cpp location.cpp + # Declare variables for each source file that needs the pic flag like this: + # BUILD_JVM__CXXFLAGS := -fno-PIC + # This will get implicitly picked up by SetupNativeCompilation below. + $(foreach s, $(NONPIC_SRC), $(eval BUILD_LIBJVM_$(notdir $s)_CXXFLAGS := -fno-PIC)) + endif + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + ifneq ($(DEBUG_LEVEL), slowdebug) + # Workaround for a bug in dtrace. If ciEnv::post_compiled_method_load_event() + # is inlined, the resulting dtrace object file needs a reference to this + # function, whose symbol name is too long for dtrace. So disable inlining + # for this method for now. (fix this when dtrace bug 6258412 is fixed) + BUILD_LIBJVM_ciEnv.cpp_CXXFLAGS := \ + -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ + # dtrace cannot handle tail call optimization (6672627, 6693876) + BUILD_LIBJVM_jni.cpp_CXXFLAGS := -Qoption ube -O~yz + BUILD_LIBJVM_stubGenerator_$(HOTSPOT_TARGET_CPU).cpp_CXXFLAGS := -xspace + + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + # Temporary until SS10 C++ compiler is fixed + BUILD_LIBJVM_generateOptoStub.cpp_CXXFLAGS := -xO2 + # Temporary util SS12u1 C++ compiler is fixed + BUILD_LIBJVM_c1_LinearScan.cpp_CXXFLAGS := -xO2 + endif + endif + + # Need extra inlining to get oop_ps_push_contents functions to perform well enough. + ifeq ($(DEBUG_LEVEL),release) + BUILD_LIBJVM_psPromotionManager.cpp_CXXFLAGS := -W2,-Ainline:inc=1000 + endif + + ifeq ($(DEBUG_LEVEL), fastdebug) + # this hangs in iropt now (7113504) + BUILD_LIBJVM_compileBroker.cpp_CXXFLAGS := -xO2 + + # Frame size > 100k if we allow inlining via -g0! + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS := +d + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS := +d + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + # ube explodes on x86 + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS += -xO1 + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS += -xO1 + endif + + endif + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # The copied fdlibm routines in these files must not be optimized + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifeq ($(TOOLCHAIN_TYPE), clang) + # NOTE: The old build tested clang version to make sure this workaround + # for the clang bug was still needed. + BUILD_LIBJVM_loopTransform.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifneq ($(DEBUG_LEVEL), slowdebug) + BUILD_LIBJVM_unsafe.cpp_CXXFLAGS := -O1 + endif + + # The following files are compiled at various optimization + # levels due to optimization issues encountered at the + # default level. The Clang compiler issues a compile + # time error if there is an optimization level specification + # skew between the PCH file and the C++ file. Especially if the + # PCH file is compiled at a higher optimization level than + # the C++ file. One solution might be to prepare extra optimization + # level specific PCH files for the opt build and use them here, but + # it's probably not worth the effort as long as only a few files + # need this special handling. + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + loopTransform.cpp \ + unsafe.cpp \ + jvmciCompilerToVM.cpp \ + # + endif + +else ifeq ($(OPENJDK_TARGET_OS), aix) + BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -qnoinline + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + # Disable aggressive optimizations for functions in sharedRuntimeTrig.cpp + # and sharedRuntimeTrans.cpp on ppc64. + # -qstrict turns off the following optimizations: + # * Performing code motion and scheduling on computations such as loads + # and floating-point computations that may trigger an exception. + # * Relaxing conformance to IEEE rules. + # * Reassociating floating-point expressions. + # When using '-qstrict' there still remains one problem + # in javasoft.sqe.tests.api.java.lang.Math.sin5Tests when run in compile-all + # mode, so don't optimize sharedRuntimeTrig.cpp at all. + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + + # Disable ELF decoder on AIX (AIX uses XCOFF). + JVM_EXCLUDE_PATTERNS += elf + +else ifeq ($(OPENJDK_TARGET_OS), windows) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + bytecodeInterpreter.cpp \ + bytecodeInterpreterWithChecks.cpp \ + opcodes.cpp \ + os_windows.cpp \ + os_windows_x86.cpp \ + osThread_windows.cpp \ + # +endif diff --git a/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris new file mode 100644 index 00000000000..ddb46c050ec --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris @@ -0,0 +1,38 @@ +# +# Copyright (c) 2005, 2013, 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + JVM_begin_signal_setting; + JVM_end_signal_setting; + JVM_get_libjsig_version; + JVM_get_signal_action; + sigaction; + signal; + sigset; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers new file mode 100644 index 00000000000..9ee418d01a2 --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers @@ -0,0 +1,38 @@ +# + +# +# Copyright (c) 2005, 2008, 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Jagent_create; + Jagent_destroy; + Jframe_iter; + #Jget_vframe; + #Jlookup_by_regs; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers new file mode 100644 index 00000000000..f9aaa19ba9d --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers @@ -0,0 +1,37 @@ +# + +# +# Copyright (c) 2006, 2008, 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. +# +# + +# Define library interface for JVM-DTrace interface + +SUNWprivate_1.1 { + global: + jvm_attach; + jvm_get_last_error; + jvm_enable_dtprobes; + jvm_detach; + local: + *; +}; diff --git a/hotspot/makefiles/symbols/symbols-aix b/hotspot/makefiles/symbols/symbols-aix new file mode 100644 index 00000000000..0efd2dba97f --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-aix-debug b/hotspot/makefiles/symbols/symbols-aix-debug new file mode 100644 index 00000000000..10887ab2b61 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix-debug @@ -0,0 +1,26 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_AccessVMBooleanFlag +JVM_AccessVMIntFlag +JVM_VMBreakPoint diff --git a/hotspot/makefiles/symbols/symbols-linux b/hotspot/makefiles/symbols/symbols-linux new file mode 100644 index 00000000000..0efd2dba97f --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-linux @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-macosx b/hotspot/makefiles/symbols/symbols-macosx new file mode 100644 index 00000000000..d0243562b67 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-macosx @@ -0,0 +1,24 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_bsd_signal diff --git a/hotspot/makefiles/symbols/symbols-shared b/hotspot/makefiles/symbols/symbols-shared new file mode 100644 index 00000000000..5d26d1028c7 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-shared @@ -0,0 +1,35 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +AsyncGetCallTrace +jio_fprintf +jio_printf +jio_snprintf +jio_vfprintf +jio_vsnprintf +JNI_CreateJavaVM +JNI_GetCreatedJavaVMs +JNI_GetDefaultJavaVMInitArgs +JVM_FindClassFromBootLoader +JVM_GetVersionInfo +JVM_InitAgentProperties diff --git a/hotspot/makefiles/symbols/symbols-solaris b/hotspot/makefiles/symbols/symbols-solaris new file mode 100644 index 00000000000..bc6124f83a3 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris @@ -0,0 +1,25 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_handle_solaris_signal +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 new file mode 100644 index 00000000000..4ce7d8e30b2 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 new file mode 100644 index 00000000000..306345e5c29 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ +__1cNExceptionBlobG__vtbl_ +__1cQUncommonTrapBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-unix b/hotspot/makefiles/symbols/symbols-unix new file mode 100644 index 00000000000..5d876710e65 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-unix @@ -0,0 +1,195 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +JVM_ActiveProcessorCount +JVM_ArrayCopy +JVM_AssertionStatusDirectives +JVM_CallStackWalk +JVM_ClassDepth +JVM_ClassLoaderDepth +JVM_Clone +JVM_ConstantPoolGetClassAt +JVM_ConstantPoolGetClassAtIfLoaded +JVM_ConstantPoolGetClassRefIndexAt +JVM_ConstantPoolGetDoubleAt +JVM_ConstantPoolGetFieldAt +JVM_ConstantPoolGetFieldAtIfLoaded +JVM_ConstantPoolGetFloatAt +JVM_ConstantPoolGetIntAt +JVM_ConstantPoolGetLongAt +JVM_ConstantPoolGetMemberRefInfoAt +JVM_ConstantPoolGetMethodAt +JVM_ConstantPoolGetMethodAtIfLoaded +JVM_ConstantPoolGetNameAndTypeRefIndexAt +JVM_ConstantPoolGetNameAndTypeRefInfoAt +JVM_ConstantPoolGetSize +JVM_ConstantPoolGetStringAt +JVM_ConstantPoolGetTagAt +JVM_ConstantPoolGetUTF8At +JVM_CountStackFrames +JVM_CurrentClassLoader +JVM_CurrentLoadedClass +JVM_CurrentThread +JVM_CurrentTimeMillis +JVM_DefineClass +JVM_DefineClassWithSource +JVM_DesiredAssertionStatus +JVM_DoPrivileged +JVM_DumpAllStacks +JVM_DumpThreads +JVM_FillInStackTrace +JVM_FillStackFrames +JVM_FindClassFromCaller +JVM_FindClassFromClass +JVM_FindLibraryEntry +JVM_FindLoadedClass +JVM_FindPrimitiveClass +JVM_FindSignal +JVM_FreeMemory +JVM_GC +JVM_GetAllThreads +JVM_GetArrayElement +JVM_GetArrayLength +JVM_GetCallerClass +JVM_GetClassAccessFlags +JVM_GetClassAnnotations +JVM_GetClassConstantPool +JVM_GetClassContext +JVM_GetClassCPEntriesCount +JVM_GetClassCPTypes +JVM_GetClassDeclaredConstructors +JVM_GetClassDeclaredFields +JVM_GetClassDeclaredMethods +JVM_GetClassFieldsCount +JVM_GetClassInterfaces +JVM_GetClassMethodsCount +JVM_GetClassModifiers +JVM_GetClassName +JVM_GetClassNameUTF +JVM_GetClassSignature +JVM_GetClassSigners +JVM_GetClassTypeAnnotations +JVM_GetCPClassNameUTF +JVM_GetCPFieldClassNameUTF +JVM_GetCPFieldModifiers +JVM_GetCPFieldNameUTF +JVM_GetCPFieldSignatureUTF +JVM_GetCPMethodClassNameUTF +JVM_GetCPMethodModifiers +JVM_GetCPMethodNameUTF +JVM_GetCPMethodSignatureUTF +JVM_GetDeclaredClasses +JVM_GetDeclaringClass +JVM_GetEnclosingMethodInfo +JVM_GetFieldIxModifiers +JVM_GetFieldTypeAnnotations +JVM_GetInheritedAccessControlContext +JVM_GetInterfaceVersion +JVM_GetManagement +JVM_GetMethodIxArgsSize +JVM_GetMethodIxByteCode +JVM_GetMethodIxByteCodeLength +JVM_GetMethodIxExceptionIndexes +JVM_GetMethodIxExceptionsCount +JVM_GetMethodIxExceptionTableEntry +JVM_GetMethodIxExceptionTableLength +JVM_GetMethodIxLocalsCount +JVM_GetMethodIxMaxStack +JVM_GetMethodIxModifiers +JVM_GetMethodIxNameUTF +JVM_GetMethodIxSignatureUTF +JVM_GetMethodParameters +JVM_GetMethodTypeAnnotations +JVM_GetNanoTimeAdjustment +JVM_GetPrimitiveArrayElement +JVM_GetProtectionDomain +JVM_GetSimpleBinaryName +JVM_GetStackAccessControlContext +JVM_GetStackTraceElements +JVM_GetSystemPackage +JVM_GetSystemPackages +JVM_GetTemporaryDirectory +JVM_GetVmArguments +JVM_Halt +JVM_HoldsLock +JVM_IHashCode +JVM_InitProperties +JVM_InternString +JVM_Interrupt +JVM_InvokeMethod +JVM_IsArrayClass +JVM_IsConstructorIx +JVM_IsInterface +JVM_IsInterrupted +JVM_IsPrimitiveClass +JVM_IsSameClassPackage +JVM_IsSupportedJNIVersion +JVM_IsThreadAlive +JVM_IsVMGeneratedMethodIx +JVM_LatestUserDefinedLoader +JVM_LoadLibrary +JVM_MaxMemory +JVM_MaxObjectInspectionAge +JVM_MonitorNotify +JVM_MonitorNotifyAll +JVM_MonitorWait +JVM_MoreStackWalk +JVM_NanoTime +JVM_NativePath +JVM_NewArray +JVM_NewInstanceFromConstructor +JVM_NewMultiArray +JVM_RaiseSignal +JVM_RawMonitorCreate +JVM_RawMonitorDestroy +JVM_RawMonitorEnter +JVM_RawMonitorExit +JVM_RegisterSignal +JVM_ReleaseUTF +JVM_ResumeThread +JVM_SetArrayElement +JVM_SetClassSigners +JVM_SetMethodInfo +JVM_SetNativeThreadName +JVM_SetPrimitiveArrayElement +JVM_SetThreadPriority +JVM_Sleep +JVM_StartThread +JVM_StopThread +JVM_SupportsCX8 +JVM_SuspendThread +JVM_TotalMemory +JVM_UnloadLibrary +JVM_Yield + +# Module related API's +JVM_AddModuleExports +JVM_AddModuleExportsToAll +JVM_AddModuleExportsToAllUnnamed +JVM_AddModulePackage +JVM_AddReadsModule +JVM_CanReadModule +JVM_DefineModule +JVM_IsExportedToModule +JVM_SetBootLoaderUnnamedModule +JVM_GetModuleByPackageName From e1a8c2d19748b50038ca5eacc4b631f3254c546c Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Fri, 8 Apr 2016 15:36:34 +0200 Subject: [PATCH 113/167] 8153731: Increase max tag combinations for UL expression (config) Reviewed-by: stefank, mlarsson --- hotspot/src/share/vm/logging/log.cpp | 9 +++++++++ hotspot/src/share/vm/logging/logTagLevelExpression.hpp | 7 +++++-- hotspot/src/share/vm/logging/logTagSet.hpp | 4 ++++ hotspot/src/share/vm/utilities/internalVMTests.cpp | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index e37d83a7cc9..6621b0325a3 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -32,6 +32,8 @@ #include "logging/log.hpp" #include "logging/logConfiguration.hpp" #include "logging/logOutput.hpp" +#include "logging/logTagLevelExpression.hpp" +#include "logging/logTagSet.hpp" #include "logging/logStream.inline.hpp" #include "memory/resourceArea.hpp" @@ -44,6 +46,13 @@ #define assert_char_not_in(c, s) \ assert(strchr(s, c) == NULL, "Expected '%s' to *not* contain character '%c'", s, c) +void Test_log_tag_combinations_limit() { + assert(LogTagLevelExpression::MaxCombinations > LogTagSet::ntagsets(), + "Combination limit (" SIZE_FORMAT ") not sufficient " + "for configuring all available tag sets (" SIZE_FORMAT ")", + LogTagLevelExpression::MaxCombinations, LogTagSet::ntagsets()); +} + class TestLogFile { private: char file_name[256]; diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index 1eb27f07517..9a0d7c9cd79 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -36,9 +36,12 @@ class LogTagSet; // Class used to temporary encode a 'what'-expression during log configuration. // Consists of a combination of tags and levels, e.g. "tag1+tag2=level1,tag3*=level2". class LogTagLevelExpression : public StackObj { - friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + public: + static const size_t MaxCombinations = 256; + private: - static const size_t MaxCombinations = 32; + friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + static const char* DefaultExpressionString; size_t _ntags, _ncombinations; diff --git a/hotspot/src/share/vm/logging/logTagSet.hpp b/hotspot/src/share/vm/logging/logTagSet.hpp index 7b193fc9751..60080700d79 100644 --- a/hotspot/src/share/vm/logging/logTagSet.hpp +++ b/hotspot/src/share/vm/logging/logTagSet.hpp @@ -64,6 +64,10 @@ class LogTagSet VALUE_OBJ_CLASS_SPEC { return _list; } + static size_t ntagsets() { + return _ntagsets; + } + LogTagSet* next() { return _next; } diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 9b3df11e27b..63bd284920d 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -67,6 +67,7 @@ void InternalVMTests::run() { run_unit_test(Test_linked_list); run_unit_test(TestChunkedList_test); run_unit_test(JSON_test); + run_unit_test(Test_log_tag_combinations_limit); run_unit_test(Test_logtarget); run_unit_test(Test_logstream); run_unit_test(Test_loghandle); From e9a1251fb36b9d08bf7ae7a2c4ceea730d0eddf2 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 8 Apr 2016 19:39:32 -0400 Subject: [PATCH 114/167] 8033735: make Throwable.backtrace visible to Class.getDeclaredField again Removed old hack to workaround an old crash. Reviewed-by: hseigel, twisti, mchung --- hotspot/src/share/vm/prims/jvm.cpp | 14 ---- .../ThrowableIntrospectionSegfault.java | 80 +++++++++++++++++++ 2 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 7665065c9df..7fc617e819f 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1818,9 +1818,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, // Ensure class is linked k->link_class(CHECK_NULL); - // 4496456 We need to filter out java.lang.Throwable.backtrace - bool skip_backtrace = false; - // Allocate result int num_fields; @@ -1831,11 +1828,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } } else { num_fields = k->java_fields_count(); - - if (k() == SystemDictionary::Throwable_klass()) { - num_fields--; - skip_backtrace = true; - } } objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); @@ -1844,12 +1836,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, int out_idx = 0; fieldDescriptor fd; for (JavaFieldStream fs(k); !fs.done(); fs.next()) { - if (skip_backtrace) { - // 4496456 skip java.lang.Throwable.backtrace - int offset = fs.offset(); - if (offset == java_lang_Throwable::get_backtrace_offset()) continue; - } - if (!publicOnly || fs.access_flags().is_public()) { fd.reinitialize(k(), fs.index()); oop field = Reflection::new_field(&fd, CHECK_NULL); diff --git a/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java new file mode 100644 index 00000000000..fd4be6c88e1 --- /dev/null +++ b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8033735 + * @summary check backtrace field introspection + * @library /testlibrary + * @run main ThrowableIntrospectionSegfault + */ + +import java.lang.reflect.*; + +public class ThrowableIntrospectionSegfault { + public static void main(java.lang.String[] unused) { + // Construct a throwable object. + Throwable throwable = new Throwable(); + throwable.fillInStackTrace(); + + // Retrieve a reflection handle to the private backtrace field. + Class class1 = throwable.getClass(); + Field field; + try { + field = class1.getDeclaredField("backtrace"); + } + catch (NoSuchFieldException e) { + System.err.println("Can't retrieve field handle Throwable.backtrace: " + e.toString()); + return; + } + field.setAccessible(true); + + // Retrieve the value of the backtrace field. + Object backtrace; + try { + backtrace = field.get(throwable); + } + catch (IllegalAccessException e) { + System.err.println( "Can't retrieve field value for Throwable.backtrace: " + e.toString()); + return; + } + + try { + + // Retrieve the class of throwable.backtrace[0][0]. + Class class2 = ((Object[]) ((Object[]) backtrace)[2])[0].getClass(); + + // Segfault occurs while executing this line, to retrieve the name of + // this class. + String class2Name = class2.getName(); + + System.err.println("class2Name=" + class2Name); + return; // pass! Passes if it doesn't crash. + } catch (ClassCastException e) { + // Passes if it doesn't crash. Also if the backtrace changes this test might get + // ClassCastException and that's ok too. + System.out.println("Catch exception " + e); + return; // pass! Passes if it doesn't crash. + } + } +} From 78a7d2c16985a2f8273b0902ad83aa134795770b Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Sat, 9 Apr 2016 12:15:13 +0300 Subject: [PATCH 115/167] 8152679: DeadlockDetectionTest.java fails due to expected output missing Detect OS X and bailout Reviewed-by: sspitsyn, tbell --- hotspot/test/serviceability/sa/DeadlockDetectionTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java index aff1aaf156a..23ce96f6399 100644 --- a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java +++ b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java @@ -80,6 +80,12 @@ public class DeadlockDetectionTest { return; } + if (Platform.isOSX()) { + // Coredump stackwalking is not implemented for Darwin + System.out.println("This test is not expected to work on OS X. Skipping"); + return; + } + if (!LingeredApp.isLastModifiedWorking()) { // Exact behaviour of the test depends on operating system and the test nature, From 7b27547030710dbd8b6cf1e5002201e61be7f937 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sun, 10 Apr 2016 21:34:47 -0400 Subject: [PATCH 116/167] 8151322: Implement os::set_native_thread_name() on Solaris Reviewed-by: sla, kbarrett, gziemski --- hotspot/src/os/solaris/vm/os_solaris.cpp | 19 +++++++++++++++++-- hotspot/src/os/solaris/vm/os_solaris.hpp | 5 ++++- .../share/vm/utilities/globalDefinitions.hpp | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 68f4a58c30a..6a10ba59434 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -161,6 +161,7 @@ address os::Solaris::handler_end; // end pc of thr_sighndlrinfo address os::Solaris::_main_stack_base = NULL; // 4352906 workaround +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL; // "default" initializers for missing libc APIs extern "C" { @@ -441,8 +442,15 @@ static bool assign_distribution(processorid_t* id_array, } void os::set_native_thread_name(const char *name) { - // Not yet implemented. - return; + if (Solaris::_pthread_setname_np != NULL) { + // Only the first 31 bytes of 'name' are processed by pthread_setname_np + // but we explicitly copy into a size-limited buffer to avoid any + // possible overflow. + char buf[32]; + snprintf(buf, sizeof(buf), "%s", name); + buf[sizeof(buf) - 1] = '\0'; + Solaris::_pthread_setname_np(pthread_self(), buf); + } } bool os::distribute_processes(uint length, uint* distribution) { @@ -4410,6 +4418,13 @@ void os::init(void) { // the minimum of what the OS supports (thr_min_stack()), and // enough to allow the thread to get to user bytecode execution. Solaris::min_stack_allowed = MAX2(thr_min_stack(), Solaris::min_stack_allowed); + + // retrieve entry point for pthread_setname_np + void * handle = dlopen("libc.so.1", RTLD_LAZY); + if (handle != NULL) { + Solaris::_pthread_setname_np = + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np"); + } } // To install functions for atexit system call diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 777e63c8f75..12f72247168 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,9 @@ class Solaris { static int _SIGasync; // user-overridable ASYNC_SIGNAL static void set_SIGasync(int newsig) { _SIGasync = newsig; } + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*); + static pthread_setname_np_func_t _pthread_setname_np; + public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3fa2c942f13..5a080626ada 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -328,7 +328,7 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) { // so far from the middle of the road that it is likely to be problematic in // many C++ compilers. // -#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value))) +#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast(value)) #define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((address_word)(func_ptr))) // Unsigned byte types for os and stream.hpp From 3a4f4362a6411e01320281dd8e8b2727d52c29d4 Mon Sep 17 00:00:00 2001 From: Cheleswer Sahu Date: Mon, 11 Apr 2016 12:50:08 +0000 Subject: [PATCH 117/167] 8153319: new test serviceability/tmtools/jstack/JstackThreadTest.java fails Reviewed-by: dsamersoff, lmesnik --- .../tmtools/jstack/JstackThreadTest.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java index b1e3ed3f2a8..6ca81885814 100644 --- a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java +++ b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java @@ -25,6 +25,8 @@ import java.util.Arrays; import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.ProcessTools; +import utils.Utils; +import java.util.concurrent.CountDownLatch; /* * @test JstackThreadTest @@ -32,23 +34,22 @@ import jdk.test.lib.ProcessTools; * @summary jstack doesn't close quotation marks properly with threads' name greater than 1996 characters * @library /testlibrary * @build jdk.test.lib.* - * @ignore 8153319 * @run main JstackThreadTest */ public class JstackThreadTest { static class NamedThread extends Thread { - NamedThread(String name) { + CountDownLatch latch; + NamedThread(String name, CountDownLatch latch) { + this.latch = latch; setName(name); + } @Override public void run() { - try { - Thread.sleep(2000); - } catch(Exception e){ - e.printStackTrace(); - } - } + latch.countDown(); + Utils.sleep(); } + } public static void main(String[] args) throws Exception { StringBuilder sb = new StringBuilder(); @@ -60,8 +61,11 @@ public class JstackThreadTest { } private static void testWithName(String name) throws Exception { + //parent thread countDown latch + CountDownLatch latch = new CountDownLatch(1); // Start a thread with a long thread name - NamedThread thread = new NamedThread(name); + NamedThread thread = new NamedThread(name, latch); + thread.setDaemon(true); thread.start(); ProcessBuilder processBuilder = new ProcessBuilder(); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstack"); @@ -69,6 +73,8 @@ public class JstackThreadTest { launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); + // Ensuring that Jstack will always run after NamedThread + latch.await(); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); System.out.println(output.getOutput()); output.shouldContain("\""+ name + "\""); From ac0824cbad6dd19d14f1b1c54c856c6ad5033154 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 11 Apr 2016 11:33:52 -0400 Subject: [PATCH 118/167] 8152468: PrintMiscellaneous in constantPool should use classresolve logging Some instances of PrintMiscellaneous have ben replaced by classresolve logging. Reviewed-by: coleenp, rprotacio --- hotspot/src/share/vm/oops/constantPool.cpp | 27 ++++++++++--------- .../runtime/logging/ClassResolutionTest.java | 4 ++- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 75a2bf970da..996f5a50eef 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -283,8 +283,9 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM // logging for classresolve tag. - trace_class_resolution(this_cp, k); - + if (log_is_enabled(Debug, classresolve)){ + trace_class_resolution(this_cp, k); + } this_cp->klass_at_put(which, k()); entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); @@ -340,9 +341,7 @@ Method* ConstantPool::method_at_if_loaded(const constantPoolHandle& cpool, int cache_index = decode_cpcache_index(which, true); if (!(cache_index >= 0 && cache_index < cpool->cache()->length())) { // FIXME: should be an assert - if (PrintMiscellaneous && (Verbose||WizardMode)) { - tty->print_cr("bad operand %d in:", which); cpool->print(); - } + log_debug(classresolve)("bad operand %d in:", which); cpool->print(); return NULL; } ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); @@ -672,10 +671,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in 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_cp->method_handle_index_at(index), - callee_index, name->as_C_string(), signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", + 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_cp, callee_index, true, CHECK_NULL); callee = KlassHandle(THREAD, k); @@ -694,10 +694,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in case JVM_CONSTANT_MethodType: { Symbol* signature = this_cp->method_type_signature_at(index); - if (PrintMiscellaneous) - tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s", - index, this_cp->method_type_index_at(index), - signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodType [%d/%d] %s", + index, this_cp->method_type_index_at(index), + signature->as_C_string()); + } KlassHandle klass(THREAD, this_cp->pool_holder()); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); diff --git a/hotspot/test/runtime/logging/ClassResolutionTest.java b/hotspot/test/runtime/logging/ClassResolutionTest.java index 3c8d6dd7f09..700fc77cb29 100644 --- a/hotspot/test/runtime/logging/ClassResolutionTest.java +++ b/hotspot/test/runtime/logging/ClassResolutionTest.java @@ -51,7 +51,8 @@ public class ClassResolutionTest { }; public static void main(String... args) throws Exception { - Thing1Handler.getThingNumber(); + int x = Thing1Handler.getThingNumber(); + System.out.println("ThingNumber: "+Integer.toString(x)); } } @@ -62,6 +63,7 @@ public class ClassResolutionTest { ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); + o.shouldContain("[classresolve] resolve JVM_CONSTANT_MethodHandle"); // (2) classresolve should turn off. pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug", From cf540ad2aff07c4df7bcd3cce2d9be2f1673e3d7 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Mon, 11 Apr 2016 16:10:41 -0400 Subject: [PATCH 119/167] 8145704: Make test for classinit logging more robust 8145704: Make test for classinit logging more robust. Reviewed-by: hseigel, gtriantafill --- .../test/runtime/logging/ClassInitializationTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hotspot/test/runtime/logging/ClassInitializationTest.java b/hotspot/test/runtime/logging/ClassInitializationTest.java index f465ab5775d..a95cc489a3e 100644 --- a/hotspot/test/runtime/logging/ClassInitializationTest.java +++ b/hotspot/test/runtime/logging/ClassInitializationTest.java @@ -62,6 +62,16 @@ public class ClassInitializationTest { out.shouldContain("[Initialized").shouldContain("without side effects]"); out.shouldHaveExitValue(0); } + + // (3) classinit should turn off. + pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=off", + "-Xverify:all", + "-Xmx64m", + "BadMap50"); + out = new OutputAnalyzer(pb.start()); + out.shouldNotContain("[classinit]"); + out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); + } public static class InnerClass { public static void main(String[] args) throws Exception { From 71bcff35cfb9c6cc5d0c36742b14ffdf2a4adb7e Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 120/167] 8153742: Move Thread::current() to thread.hpp Reviewed-by: coleenp, jmasa --- hotspot/src/share/vm/interpreter/abstractInterpreter.hpp | 2 +- hotspot/src/share/vm/interpreter/interpreterRuntime.hpp | 2 +- hotspot/src/share/vm/memory/resourceArea.hpp | 2 +- hotspot/src/share/vm/runtime/javaCalls.hpp | 2 +- hotspot/src/share/vm/runtime/vmThread.hpp | 2 +- hotspot/src/share/vm/utilities/preserveException.hpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index db31ac83400..2c527a8f893 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -28,7 +28,7 @@ #include "asm/macroAssembler.hpp" #include "code/stubs.hpp" #include "interpreter/bytecodes.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" #include "utilities/top.hpp" diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 2039adba2a0..dd4f797b0c7 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -31,7 +31,7 @@ #include "oops/method.hpp" #include "runtime/frame.inline.hpp" #include "runtime/signature.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "utilities/top.hpp" // The InterpreterRuntime is called by the interpreter for everything diff --git a/hotspot/src/share/vm/memory/resourceArea.hpp b/hotspot/src/share/vm/memory/resourceArea.hpp index 65ae36a1646..89ad7457314 100644 --- a/hotspot/src/share/vm/memory/resourceArea.hpp +++ b/hotspot/src/share/vm/memory/resourceArea.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_MEMORY_RESOURCEAREA_HPP #include "memory/allocation.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // The resource area holds temporary data structures in the VM. // The actual allocation areas are thread local. Typical usage: diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index 543e58f0dde..0d885686de8 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -29,7 +29,7 @@ #include "oops/method.hpp" #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" #ifdef TARGET_ARCH_x86 # include "jniTypes_x86.hpp" diff --git a/hotspot/src/share/vm/runtime/vmThread.hpp b/hotspot/src/share/vm/runtime/vmThread.hpp index 43147e53c36..692fbdd164d 100644 --- a/hotspot/src/share/vm/runtime/vmThread.hpp +++ b/hotspot/src/share/vm/runtime/vmThread.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_RUNTIME_VMTHREAD_HPP #include "runtime/perfData.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" // diff --git a/hotspot/src/share/vm/utilities/preserveException.hpp b/hotspot/src/share/vm/utilities/preserveException.hpp index 58f92a876ab..09b3664ef9a 100644 --- a/hotspot/src/share/vm/utilities/preserveException.hpp +++ b/hotspot/src/share/vm/utilities/preserveException.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_UTILITIES_PRESERVEEXCEPTION_HPP #include "runtime/handles.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // This file provides more support for exception handling; see also exceptions.hpp class PreserveExceptionMark { From 2ca745d47ad2450d1cce2b0d3fbd6444dd844cb3 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 121/167] 8152639: ResourceMark missing in reportFreeListStatistics Reviewed-by: pliden, sjohanss --- .../src/share/vm/gc/cms/compactibleFreeListSpace.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index c048f08b4a1..ad651723aef 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -32,6 +32,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/spaceDecorator.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -505,10 +506,13 @@ void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const return; } log.debug("%s", title); - _dictionary->report_statistics(log.debug_stream()); + + LogStream out(log.debug()); + _dictionary->report_statistics(&out); + if (log.is_trace()) { - ResourceMark rm; - reportIndexedFreeListStatistics(log.trace_stream()); + LogStream trace_out(log.trace()); + reportIndexedFreeListStatistics(&trace_out); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); From 388236cc3d9cd233a087e1b57706100026fba93c Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 122/167] 8152962: CMSCollector::shouldConcurrentCollect incorrectly logs against the debug stream Reviewed-by: brutisso, sjohanss --- .../gc/cms/concurrentMarkSweepGeneration.cpp | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 1e7a4991dd3..9e67c9b39e3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -425,7 +425,7 @@ void CMSStats::print_on(outputStream *st) const { st->print(",cms_consumption_rate=%g,time_until_full=%g", cms_consumption_rate(), time_until_cms_gen_full()); } - st->print(" "); + st->cr(); } #endif // #ifndef PRODUCT @@ -1108,8 +1108,10 @@ bool ConcurrentMarkSweepGeneration::should_collect(bool full, } bool CMSCollector::shouldConcurrentCollect() { + LogTarget(Trace, gc) log; + if (_full_gc_requested) { - log_trace(gc)("CMSCollector: collect because of explicit gc request (or GCLocker)"); + log.print("CMSCollector: collect because of explicit gc request (or GCLocker)"); return true; } @@ -1117,21 +1119,22 @@ bool CMSCollector::shouldConcurrentCollect() { // ------------------------------------------------------------------ // Print out lots of information which affects the initiation of // a collection. - Log(gc) log; - if (log.is_trace() && stats().valid()) { - log.trace("CMSCollector shouldConcurrentCollect: "); - ResourceMark rm; - stats().print_on(log.debug_stream()); - log.trace("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); - log.trace("free=" SIZE_FORMAT, _cmsGen->free()); - log.trace("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); - log.trace("promotion_rate=%g", stats().promotion_rate()); - log.trace("cms_allocation_rate=%g", stats().cms_allocation_rate()); - log.trace("occupancy=%3.7f", _cmsGen->occupancy()); - log.trace("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); - log.trace("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); - log.trace("cms_time_since_end=%3.7f", stats().cms_time_since_end()); - log.trace("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); + if (log.is_enabled() && stats().valid()) { + log.print("CMSCollector shouldConcurrentCollect: "); + + LogStream out(log); + stats().print_on(&out); + + log.print("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); + log.print("free=" SIZE_FORMAT, _cmsGen->free()); + log.print("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); + log.print("promotion_rate=%g", stats().promotion_rate()); + log.print("cms_allocation_rate=%g", stats().cms_allocation_rate()); + log.print("occupancy=%3.7f", _cmsGen->occupancy()); + log.print("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); + log.print("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); + log.print("cms_time_since_end=%3.7f", stats().cms_time_since_end()); + log.print("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); } // ------------------------------------------------------------------ @@ -1149,8 +1152,8 @@ bool CMSCollector::shouldConcurrentCollect() { // this branch will not fire after the first successful CMS // collection because the stats should then be valid. if (_cmsGen->occupancy() >= _bootstrap_occupancy) { - log_trace(gc)(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", - _cmsGen->occupancy(), _bootstrap_occupancy); + log.print(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", + _cmsGen->occupancy(), _bootstrap_occupancy); return true; } } @@ -1162,7 +1165,7 @@ bool CMSCollector::shouldConcurrentCollect() { // XXX We need to make sure that the gen expansion // criterion dovetails well with this. XXX NEED TO FIX THIS if (_cmsGen->should_concurrent_collect()) { - log_trace(gc)("CMS old gen initiated"); + log.print("CMS old gen initiated"); return true; } @@ -1173,12 +1176,12 @@ bool CMSCollector::shouldConcurrentCollect() { assert(gch->collector_policy()->is_generation_policy(), "You may want to check the correctness of the following"); if (gch->incremental_collection_will_fail(true /* consult_young */)) { - log_trace(gc)("CMSCollector: collect because incremental collection will fail "); + log.print("CMSCollector: collect because incremental collection will fail "); return true; } if (MetaspaceGC::should_concurrent_collect()) { - log_trace(gc)("CMSCollector: collect for metadata allocation "); + log.print("CMSCollector: collect for metadata allocation "); return true; } @@ -1193,10 +1196,10 @@ bool CMSCollector::shouldConcurrentCollect() { // as we want to be able to trigger the first CMS cycle as well) if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) { if (stats().valid()) { - log_trace(gc)("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", - stats().cms_time_since_begin()); + log.print("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", + stats().cms_time_since_begin()); } else { - log_trace(gc)("CMSCollector: collect because of trigger interval (first collection)"); + log.print("CMSCollector: collect because of trigger interval (first collection)"); } return true; } From 0f89b2e137de3ed8b52bfa5e5b5c0b10656b268c Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 123/167] 8153583: Make OutputAnalyzer.reportDiagnosticSummary public Reviewed-by: brutisso, sjohanss --- .../testlibrary/jdk/test/lib/OutputAnalyzer.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java index 37f0209b288..15f6f53157b 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java +++ b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java @@ -378,14 +378,14 @@ public final class OutputAnalyzer { * - exit code * Note: the command line is printed by the ProcessTools */ - private void reportDiagnosticSummary() { - String msg = - " stdout: [" + stdout + "];\n" + - " stderr: [" + stderr + "]\n" + - " exitValue = " + getExitValue() + "\n"; + public void reportDiagnosticSummary() { + String msg = + " stdout: [" + stdout + "];\n" + + " stderr: [" + stderr + "]\n" + + " exitValue = " + getExitValue() + "\n"; - System.err.println(msg); - } + System.err.println(msg); + } /** From dab21ebd4d19c571f5436431da57590c53446756 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 124/167] 8153658: Redundant memory copy in LogStreamNoResourceMark Reviewed-by: kbarrett, jmasa --- hotspot/src/share/vm/logging/logStream.inline.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/logging/logStream.inline.hpp b/hotspot/src/share/vm/logging/logStream.inline.hpp index b1bff8b53bd..5be4754438d 100644 --- a/hotspot/src/share/vm/logging/logStream.inline.hpp +++ b/hotspot/src/share/vm/logging/logStream.inline.hpp @@ -33,7 +33,8 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); - _tagset->write(_level, "%s", _current_line.as_string()); + _current_line.write("\0", 1); + _tagset->write(_level, "%s", _current_line.base()); _current_line.reset(); } else { _current_line.write(s, len); From 320005909801f9484191c1e1daafef511e548efa Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 11 Apr 2016 08:51:53 +0200 Subject: [PATCH 125/167] 8153659: Create a CHeap backed LogStream class Reviewed-by: brutisso, mlarsson --- hotspot/src/share/vm/logging/log.cpp | 21 ++++ hotspot/src/share/vm/logging/logHandle.hpp | 4 +- hotspot/src/share/vm/logging/logStream.cpp | 2 +- hotspot/src/share/vm/logging/logStream.hpp | 95 +++++++++++++++++-- .../src/share/vm/logging/logStream.inline.hpp | 55 +---------- 5 files changed, 113 insertions(+), 64 deletions(-) diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 6c6566b386e..e37d83a7cc9 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -361,11 +361,32 @@ static void Test_logstream_no_rm() { Test_logstream_helper(stream); } +static void Test_logstreamcheap_log() { + Log(gc) log; + LogStreamCHeap stream(log.debug()); + + Test_logstream_helper(&stream); +} + +static void Test_logstreamcheap_logtarget() { + LogTarget(Debug, gc) log; + LogStreamCHeap stream(log); + + Test_logstream_helper(&stream); +} + void Test_logstream() { + // Test LogStreams with embedded ResourceMark. Test_logstream_log(); Test_logstream_logtarget(); Test_logstream_logstreamhandle(); + + // Test LogStreams without embedded ResourceMark. Test_logstream_no_rm(); + + // Test LogStreams backed by CHeap memory. + Test_logstreamcheap_log(); + Test_logstreamcheap_logtarget(); } void Test_loghandle_on() { diff --git a/hotspot/src/share/vm/logging/logHandle.hpp b/hotspot/src/share/vm/logging/logHandle.hpp index 1f62d96e6f9..41d20609a73 100644 --- a/hotspot/src/share/vm/logging/logHandle.hpp +++ b/hotspot/src/share/vm/logging/logHandle.hpp @@ -67,13 +67,13 @@ public: // This can be used to pass a Log instance as a parameter without // polluting the surrounding API with template functions. class LogTargetHandle { - friend class LogStream; - private: const LogLevelType _level; LogTagSet* _tagset; public: + LogTargetHandle(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} + template LogTargetHandle(const LogTargetImpl& type_carrier) : _level(level), diff --git a/hotspot/src/share/vm/logging/logStream.cpp b/hotspot/src/share/vm/logging/logStream.cpp index b68dca7f056..5c980a7b2ce 100644 --- a/hotspot/src/share/vm/logging/logStream.cpp +++ b/hotspot/src/share/vm/logging/logStream.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "logging/log.hpp" -#include "logging/logStream.hpp" +#include "logging/logStream.inline.hpp" // Create a log stream without an embedded ResourceMark. // The function is placed here to be called out-of-line in log.hpp. diff --git a/hotspot/src/share/vm/logging/logStream.hpp b/hotspot/src/share/vm/logging/logStream.hpp index 38ba83ab3ee..6e7a28ac5d2 100644 --- a/hotspot/src/share/vm/logging/logStream.hpp +++ b/hotspot/src/share/vm/logging/logStream.hpp @@ -26,23 +26,100 @@ #define SHARE_VM_LOGGING_LOGSTREAM_HPP #include "logging/log.hpp" +#include "logging/logHandle.hpp" +#include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -// An output stream that logs to the logging framework. -// Requires a ResourceMark on the stack. -class LogStreamNoResourceMark : public outputStream { -private: - stringStream _current_line; - LogLevelType _level; - LogTagSet* _tagset; +// The base class of an output stream that logs to the logging framework. +template +class LogStreamBase : public outputStream { + streamClass _current_line; + LogTargetHandle _log_handle; public: - LogStreamNoResourceMark(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} - ~LogStreamNoResourceMark() { + // Constructor to support creation from a LogTarget instance. + // + // LogTarget(Debug, gc) log; + // LogStreamBase(log) stream; + template + LogStreamBase(const LogTargetImpl& type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. + // + // LogStreamBase stream(log.debug()); + // or + // LogStreamBase stream((LogTargetImpl*)NULL); + template + LogStreamBase(const LogTargetImpl* type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from a LogTargetHandle. + // + // LogTarget(Debug, gc) log; + // LogTargetHandle(log) handle; + // LogStreamBase stream(handle); + LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {} + + // Constructor to support creation from a log level and tagset. + // + // LogStreamBase(level, tageset); + LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {} + + ~LogStreamBase() { guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?"); } +public: void write(const char* s, size_t len); }; +// A stringStream with an embedded ResourceMark. +class stringStreamWithResourceMark : outputStream { + private: + // The stringStream Resource allocate in the constructor, + // so the order of the fields is important. + ResourceMark _embedded_resource_mark; + stringStream _stream; + + public: + stringStreamWithResourceMark(size_t initial_bufsize = 256) : + _embedded_resource_mark(), + _stream(initial_bufsize) {} + + virtual void write(const char* c, size_t len) { _stream.write(c, len); } + size_t size() { return _stream.size(); } + const char* base() { return _stream.base(); } + void reset() { _stream.reset(); } + char* as_string() { return _stream.as_string(); } +}; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in Resource memory. +// The caller is required to have a ResourceMark on the stack. +typedef LogStreamBase LogStreamNoResourceMark; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in CHeap memory. +typedef LogStreamBase LogStreamCHeap; + +// An output stream that logs to the logging framework, and embeds a ResourceMark. +// +// The backing buffer is allocated in Resource memory. +// The class is intended to be stack allocated. +// The class provides its own ResourceMark, +// so care needs to be taken when nested ResourceMarks are used. +typedef LogStreamBase LogStream; + +// Support creation of a LogStream without having to provide a LogTarget pointer. +#define LogStreamHandle(level, ...) LogStreamTemplate + +template +class LogStreamTemplate : public LogStream { +public: + LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} +}; + #endif // SHARE_VM_LOGGING_LOGSTREAM_HPP diff --git a/hotspot/src/share/vm/logging/logStream.inline.hpp b/hotspot/src/share/vm/logging/logStream.inline.hpp index 5be4754438d..5660a5616bb 100644 --- a/hotspot/src/share/vm/logging/logStream.inline.hpp +++ b/hotspot/src/share/vm/logging/logStream.inline.hpp @@ -30,11 +30,12 @@ #include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -inline void LogStreamNoResourceMark::write(const char* s, size_t len) { +template +inline void LogStreamBase::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); _current_line.write("\0", 1); - _tagset->write(_level, "%s", _current_line.base()); + _log_handle.print("%s", _current_line.base()); _current_line.reset(); } else { _current_line.write(s, len); @@ -42,54 +43,4 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) { update_position(s, len); } -// An output stream that logs to the logging framework, and embeds a ResourceMark. -// -// The class is intended to be stack allocated. -// Care needs to be taken when nested ResourceMarks are used. -class LogStream : public outputStream { -private: - ResourceMark _embedded_resource_mark; - LogStreamNoResourceMark _stream; - -public: - // Constructor to support creation from a LogTarget instance. - // - // LogTarget(Debug, gc) log; - // LogStream(log) stream; - template - LogStream(const LogTargetImpl& type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. - // - // LogStream stream(log.debug()); - // LogStream stream((LogTargetImpl*)NULL); - template - LogStream(const LogTargetImpl* type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from a LogTargetHandle. - // - // LogTarget(Debug, gc) log; - // LogTargetHandle(log) handle; - // LogStream stream(handle); - LogStream(LogTargetHandle handle) : - _embedded_resource_mark(), - _stream(handle._level, handle._tagset) {} - - // Override of outputStream::write. - void write(const char* s, size_t len) { _stream.write(s, len); } -}; - -// Support creation of a LogStream without having to provide a LogTarget pointer. -#define LogStreamHandle(level, ...) LogStreamTemplate - -template -class LogStreamTemplate : public LogStream { -public: - LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} -}; - #endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP From 1afb9e94277c9399488d57996e7f17f3a8aa1c75 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 11 Apr 2016 09:45:03 +0200 Subject: [PATCH 126/167] 8153845: UL log write method missing essential assert Reviewed-by: mlarsson, brutisso --- hotspot/src/share/vm/logging/logTagSet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/src/share/vm/logging/logTagSet.cpp b/hotspot/src/share/vm/logging/logTagSet.cpp index db675a26854..96aae628857 100644 --- a/hotspot/src/share/vm/logging/logTagSet.cpp +++ b/hotspot/src/share/vm/logging/logTagSet.cpp @@ -98,6 +98,7 @@ void LogTagSet::write(LogLevelType level, const char* fmt, ...) { const size_t vwrite_buffer_size = 512; void LogTagSet::vwrite(LogLevelType level, const char* fmt, va_list args) { + assert(level >= LogLevel::First && level <= LogLevel::Last, "Log level:%d is incorrect", level); char buf[vwrite_buffer_size]; va_list saved_args; // For re-format on buf overflow. va_copy(saved_args, args); From 19cd9b20e8b929cbb502ce520a644e64665102cd Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Mon, 11 Apr 2016 09:49:10 +0200 Subject: [PATCH 127/167] 8153843: G1CardLiveDataHelper incorrectly sets next_live_bytes on dead humongous regions Reviewed-by: drwhite, tschatzl --- hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp | 10 ++++++++-- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 14 +++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp index 009179150a9..0a2ed25a29b 100644 --- a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp @@ -206,8 +206,14 @@ public: return 0; } if (hr->is_humongous()) { - mark_card_bitmap_range(start, hr->top()); - return pointer_delta(hr->top(), start, 1); + HeapRegion* start_region = hr->humongous_start_region(); + if (mark_bitmap->isMarked(start_region->bottom())) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } else { + // Humongous start object was actually dead. + return 0; + } } assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2980eecdc0e..0f33720d7ca 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2946,13 +2946,17 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { : rset->is_empty(); } - bool is_typeArray_region(HeapRegion* region) const { - return oop(region->bottom())->is_typeArray(); - } - bool humongous_region_is_candidate(G1CollectedHeap* heap, HeapRegion* region) const { assert(region->is_starts_humongous(), "Must start a humongous object"); + oop obj = oop(region->bottom()); + + // Dead objects cannot be eager reclaim candidates. Due to class + // unloading it is unsafe to query their classes so we return early. + if (heap->is_obj_dead(obj, region)) { + return false; + } + // Candidate selection must satisfy the following constraints // while concurrent marking is in progress: // @@ -2989,7 +2993,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { // important use case for eager reclaim, and this special handling // may reduce needed headroom. - return is_typeArray_region(region) && is_remset_small(region); + return obj->is_typeArray() && is_remset_small(region); } public: From 8b2f63bd2b054550cc0305f0593e20c79d86a48e Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Mon, 11 Apr 2016 12:22:09 +0200 Subject: [PATCH 128/167] 8146879: Add option for handling existing log files in UL Reviewed-by: dsamersoff, gziemski, rehn --- hotspot/src/os/bsd/vm/os_bsd.cpp | 22 +++ hotspot/src/os/linux/vm/os_linux.cpp | 15 ++ hotspot/src/os/posix/vm/os_posix.cpp | 4 + hotspot/src/os/solaris/vm/os_solaris.cpp | 13 ++ hotspot/src/os/windows/vm/os_windows.cpp | 16 ++ hotspot/src/share/vm/logging/log.cpp | 142 +++++++++++++++++ .../src/share/vm/logging/logConfiguration.cpp | 2 +- .../src/share/vm/logging/logFileOutput.cpp | 143 ++++++++++++++++-- .../src/share/vm/logging/logFileOutput.hpp | 17 ++- .../share/vm/logging/logFileStreamOutput.hpp | 4 +- hotspot/src/share/vm/logging/logOutput.hpp | 2 +- hotspot/src/share/vm/runtime/os.hpp | 3 + .../share/vm/utilities/internalVMTests.cpp | 3 + .../logging/TestLogRotation.java | 6 +- .../logging/TestQuotedLogOutputs.java | 2 +- 15 files changed, 368 insertions(+), 26 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index ce3f6e005fd..78def166e58 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3732,6 +3732,28 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); +#ifdef __APPLE__ + return st.st_mtimespec; +#else + return st.st_mtim; +#endif +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} + + bool os::check_heap(bool force) { return true; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 228ac835ffb..4889870e8f4 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -6008,7 +6008,22 @@ bool os::start_debugging(char *buf, int buflen) { return yes; } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtim; +} +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} /////////////// Unit tests /////////////// diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 6d683eec706..1c6efe5b513 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -181,6 +181,10 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return vsnprintf(buf, len, fmt, args); } +int os::fileno(FILE* fp) { + return ::fileno(fp); +} + void os::Posix::print_load_average(outputStream* st) { st->print("load average:"); double loadavg[3]; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 6a10ba59434..1d68dcc7721 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1827,6 +1827,19 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + static bool _print_ascii_file(const char* filename, outputStream* st) { int fd = ::open(filename, O_RDONLY); if (fd == -1) { diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 72da7bae97b..fa401527ed7 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1594,6 +1594,19 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return ret; } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + void os::print_os_info_brief(outputStream* st) { os::print_os_info(st); } @@ -4589,6 +4602,9 @@ int os::ftruncate(int fd, jlong length) { return 0; } +int os::fileno(FILE* fp) { + return _fileno(fp); +} // This code is a copy of JDK's sysSync // from src/windows/hpi/src/sys_api_md.c diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 6621b0325a3..cdef6d8a7ab 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -31,6 +31,7 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logFileOutput.hpp" #include "logging/logOutput.hpp" #include "logging/logTagLevelExpression.hpp" #include "logging/logTagSet.hpp" @@ -138,6 +139,131 @@ void Test_configure_stdout() { assert_str_eq("all=off", stdoutput->config_string()); } +static size_t number_of_lines_with_substring_in_file(const char* filename, + const char* substr) { + ResourceMark rm; + size_t ret = 0; + FILE* fp = fopen(filename, "r"); + assert(fp != NULL, "error opening file %s: %s", filename, strerror(errno)); + + int buflen = 512; + char* buf = NEW_RESOURCE_ARRAY(char, buflen); + long pos = 0; + + while (fgets(buf, buflen, fp) != NULL) { + if (buf[strlen(buf) - 1] != '\n' && !feof(fp)) { + // retry with a larger buffer + buf = REALLOC_RESOURCE_ARRAY(char, buf, buflen, buflen * 2); + buflen *= 2; + // rewind to beginning of line + fseek(fp, pos, SEEK_SET); + continue; + } + pos = ftell(fp); + if (strstr(buf, substr) != NULL) { + ret++; + } + } + + fclose(fp); + return ret; +} + +static bool file_exists(const char* filename) { + struct stat st; + return os::stat(filename, &st) == 0; +} + +static void delete_file(const char* filename) { + if (!file_exists(filename)) { + return; + } + int ret = remove(filename); + assert(ret == 0, "failed to remove file '%s': %s", filename, strerror(errno)); +} + +static void create_directory(const char* name) { + assert(!file_exists(name), "can't create directory: %s already exists", name); + bool failed; +#ifdef _WINDOWS + failed = !CreateDirectory(name, NULL); +#else + failed = mkdir(name, 0777); +#endif + assert(!failed, "failed to create directory %s", name); +} + +static const char* ExpectedLine = "a (hopefully) unique log line for testing"; + +static void init_file(const char* filename, const char* options = "") { + LogConfiguration::parse_log_arguments(filename, "logging=trace", "", options, + Log(logging)::error_stream()); + log_debug(logging)("%s", ExpectedLine); + LogConfiguration::parse_log_arguments(filename, "all=off", "", "", + Log(logging)::error_stream()); +} + +void Test_log_file_startup_rotation() { + ResourceMark rm; + const size_t rotations = 5; + const char* filename = "start-rotate-test"; + char* rotated_file[rotations]; + for (size_t i = 0; i < rotations; i++) { + size_t len = strlen(filename) + 3; + rotated_file[i] = NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(rotated_file[i], len, "%s." SIZE_FORMAT, filename, i); + delete_file(rotated_file[i]); + }; + + delete_file(filename); + init_file(filename); + assert(file_exists(filename), + "configured logging to file '%s' but file was not found", filename); + + // Initialize the same file a bunch more times to trigger rotations + for (size_t i = 0; i < rotations; i++) { + init_file(filename); + assert(file_exists(rotated_file[i]), "existing file was not rotated"); + } + + // Remove a file and expect its slot to be re-used + delete_file(rotated_file[1]); + init_file(filename); + assert(file_exists(rotated_file[1]), "log file not properly rotated"); + + // Clean up after test + delete_file(filename); + for (size_t i = 0; i < rotations; i++) { + delete_file(rotated_file[i]); + } +} + +void Test_log_file_startup_truncation() { + ResourceMark rm; + const char* filename = "start-truncate-test"; + const char* archived_filename = "start-truncate-test.0"; + + delete_file(filename); + delete_file(archived_filename); + + // Use the same log file twice and expect it to be overwritten/truncated + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + assert(!file_exists(archived_filename), + "existing log file %s was not properly truncated when filecount was 0", + filename); + + // Verify that the file was really truncated and not just appended + assert(number_of_lines_with_substring_in_file(filename, ExpectedLine) == 1, + "log file %s appended rather than truncated", filename); + + delete_file(filename); + delete_file(archived_filename); +} + static int Test_logconfiguration_subscribe_triggered = 0; static void Test_logconfiguration_subscribe_helper() { @@ -741,4 +867,20 @@ void Test_log_gctracetime() { Test_log_gctracetime_no_heap_no_cause(); } +void Test_invalid_log_file() { + ResourceMark rm; + stringStream ss; + const char* target_name = "tmplogdir"; + + // Attempt to log to a directory (existing log not a regular file) + create_directory(target_name); + LogFileOutput bad_file("tmplogdir"); + assert(bad_file.initialize("", &ss) == false, "file was initialized " + "when there was an existing directory with the same name"); + assert(strstr(ss.as_string(), "tmplogdir is not a regular file") != NULL, + "missing expected error message, received msg: %s", ss.as_string()); + ss.reset(); + remove(target_name); +} + #endif // PRODUCT diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 67b63b782d9..6f9f7bb2a27 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -145,7 +145,7 @@ LogOutput* LogConfiguration::new_output(char* name, const char* options, outputS return NULL; } - bool success = output->initialize(options); + bool success = output->initialize(options, errstream); if (!success) { errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options); delete output; diff --git a/hotspot/src/share/vm/logging/logFileOutput.cpp b/hotspot/src/share/vm/logging/logFileOutput.cpp index 4084d5d2ce1..7f41bd995fb 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.cpp +++ b/hotspot/src/share/vm/logging/logFileOutput.cpp @@ -41,8 +41,9 @@ char LogFileOutput::_vm_start_time_str[StartTimeBufferSize]; LogFileOutput::LogFileOutput(const char* name) : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)), - _file_name(NULL), _archive_name(NULL), _archive_name_len(0), _current_size(0), - _rotate_size(0), _current_file(1), _file_count(0), _rotation_semaphore(1) { + _file_name(NULL), _archive_name(NULL), _archive_name_len(0), + _rotate_size(DefaultFileSize), _file_count(DefaultFileCount), + _current_size(0), _current_file(0), _rotation_semaphore(1) { _file_name = make_file_name(name, _pid_str, _vm_start_time_str); } @@ -59,9 +60,6 @@ void LogFileOutput::set_file_name_parameters(jlong vm_start_time) { LogFileOutput::~LogFileOutput() { if (_stream != NULL) { - if (_archive_name != NULL) { - archive(); - } if (fclose(_stream) != 0) { jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n", _file_name, os::strerror(errno)); @@ -72,7 +70,7 @@ LogFileOutput::~LogFileOutput() { os::free(const_cast(_name)); } -size_t LogFileOutput::parse_value(const char* value_str) { +static size_t parse_value(const char* value_str) { char* end; unsigned long long value = strtoull(value_str, &end, 10); if (!isdigit(*value_str) || end != value_str + strlen(value_str) || value >= SIZE_MAX) { @@ -81,7 +79,80 @@ size_t LogFileOutput::parse_value(const char* value_str) { return value; } -bool LogFileOutput::configure_rotation(const char* options) { +static bool file_exists(const char* filename) { + struct stat dummy_stat; + return os::stat(filename, &dummy_stat) == 0; +} + +static uint number_of_digits(uint number) { + return number < 10 ? 1 : (number < 100 ? 2 : 3); +} + +static bool is_regular_file(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + if (ret != 0) { + return false; + } +#ifdef _WINDOWS + return (st.st_mode & S_IFMT) == _S_IFREG; +#else + return S_ISREG(st.st_mode); +#endif +} + +// Try to find the next number that should be used for file rotation. +// Return UINT_MAX on error. +static uint next_file_number(const char* filename, + uint number_of_digits, + uint filecount, + outputStream* errstream) { + bool found = false; + uint next_num = 0; + + // len is filename + dot + digits + null char + size_t len = strlen(filename) + number_of_digits + 2; + char* archive_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + char* oldest_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + + for (uint i = 0; i < filecount; i++) { + int ret = jio_snprintf(archive_name, len, "%s.%0*u", + filename, number_of_digits, i); + assert(ret > 0 && static_cast(ret) == len - 1, + "incorrect buffer length calculation"); + + if (file_exists(archive_name) && !is_regular_file(archive_name)) { + // We've encountered something that's not a regular file among the + // possible file rotation targets. Fail immediately to prevent + // problems later. + errstream->print_cr("Possible rotation target file '%s' already exists " + "but is not a regular file.", archive_name); + next_num = UINT_MAX; + break; + } + + // Stop looking if we find an unused file name + if (!file_exists(archive_name)) { + next_num = i; + found = true; + break; + } + + // Keep track of oldest existing log file + if (!found + || os::compare_file_modified_times(oldest_name, archive_name) > 0) { + strcpy(oldest_name, archive_name); + next_num = i; + found = true; + } + } + + FREE_C_HEAP_ARRAY(char, oldest_name); + FREE_C_HEAP_ARRAY(char, archive_name); + return next_num; +} + +bool LogFileOutput::parse_options(const char* options, outputStream* errstream) { if (options == NULL || strlen(options) == 0) { return true; } @@ -107,22 +178,25 @@ bool LogFileOutput::configure_rotation(const char* options) { if (strcmp(FileCountOptionKey, key) == 0) { size_t value = parse_value(value_str); - if (value == SIZE_MAX || value >= UINT_MAX) { + if (value > MaxRotationFileCount) { + errstream->print_cr("Invalid option: %s must be in range [0, %u]", + FileCountOptionKey, + MaxRotationFileCount); success = false; break; } _file_count = static_cast(value); - _file_count_max_digits = static_cast(log10(static_cast(_file_count)) + 1); - _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; - _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); } else if (strcmp(FileSizeOptionKey, key) == 0) { size_t value = parse_value(value_str); if (value == SIZE_MAX || value > SIZE_MAX / K) { + errstream->print_cr("Invalid option: %s must be in range [0, " + SIZE_FORMAT "]", FileSizeOptionKey, SIZE_MAX / K); success = false; break; } _rotate_size = value * K; } else { + errstream->print_cr("Invalid option '%s' for log file output.", key); success = false; break; } @@ -133,15 +207,54 @@ bool LogFileOutput::configure_rotation(const char* options) { return success; } -bool LogFileOutput::initialize(const char* options) { - if (!configure_rotation(options)) { +bool LogFileOutput::initialize(const char* options, outputStream* errstream) { + if (!parse_options(options, errstream)) { return false; } + + if (_file_count > 0) { + // compute digits with filecount - 1 since numbers will start from 0 + _file_count_max_digits = number_of_digits(_file_count - 1); + _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; + _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); + } + + log_trace(logging)("Initializing logging to file '%s' (filecount: %u" + ", filesize: " SIZE_FORMAT " KiB).", + _file_name, _file_count, _rotate_size / K); + + if (_file_count > 0 && file_exists(_file_name)) { + if (!is_regular_file(_file_name)) { + errstream->print_cr("Unable to log to file %s with log file rotation: " + "%s is not a regular file", + _file_name, _file_name); + return false; + } + _current_file = next_file_number(_file_name, + _file_count_max_digits, + _file_count, + errstream); + if (_current_file == UINT_MAX) { + return false; + } + log_trace(logging)("Existing log file found, saving it as '%s.%0*u'", + _file_name, _file_count_max_digits, _current_file); + archive(); + increment_file_count(); + } + _stream = fopen(_file_name, FileOpenMode); if (_stream == NULL) { - log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, os::strerror(errno)); + errstream->print_cr("Error opening log file '%s': %s", + _file_name, strerror(errno)); return false; } + + if (_file_count == 0 && is_regular_file(_file_name)) { + log_trace(logging)("Truncating log file"); + os::ftruncate(os::fileno(_stream), 0); + } + return true; } @@ -210,7 +323,7 @@ void LogFileOutput::rotate() { // Reset accumulated size, increase current file counter, and check for file count wrap-around. _current_size = 0; - _current_file = (_current_file >= _file_count ? 1 : _current_file + 1); + increment_file_count(); } char* LogFileOutput::make_file_name(const char* file_name, diff --git a/hotspot/src/share/vm/logging/logFileOutput.hpp b/hotspot/src/share/vm/logging/logFileOutput.hpp index 935a176a5e3..adfd3722cef 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileOutput.hpp @@ -39,8 +39,11 @@ class LogFileOutput : public LogFileStreamOutput { static const char* PidFilenamePlaceholder; static const char* TimestampFilenamePlaceholder; static const char* TimestampFormat; + static const size_t DefaultFileCount = 5; + static const size_t DefaultFileSize = 20 * M; static const size_t StartTimeBufferSize = 20; - static const size_t PidBufferSize = 21; + static const size_t PidBufferSize = 21; + static const uint MaxRotationFileCount = 1000; static char _pid_str[PidBufferSize]; static char _vm_start_time_str[StartTimeBufferSize]; @@ -61,18 +64,24 @@ class LogFileOutput : public LogFileStreamOutput { void archive(); void rotate(); - bool configure_rotation(const char* options); + bool parse_options(const char* options, outputStream* errstream); char *make_file_name(const char* file_name, const char* pid_string, const char* timestamp_string); - static size_t parse_value(const char* value_str); bool should_rotate() { return _file_count > 0 && _rotate_size > 0 && _current_size >= _rotate_size; } + void increment_file_count() { + _current_file++; + if (_current_file == _file_count) { + _current_file = 0; + } + } + public: LogFileOutput(const char *name); virtual ~LogFileOutput(); - virtual bool initialize(const char* options); + virtual bool initialize(const char* options, outputStream* errstream); virtual int write(const LogDecorations& decorations, const char* msg); virtual void force_rotate(); diff --git a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp index 9c4ddf7b9c5..a4c739cfcfa 100644 --- a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp @@ -53,7 +53,7 @@ class LogStdoutOutput : public LogFileStreamOutput { LogStdoutOutput() : LogFileStreamOutput(stdout) { set_config_string("all=off"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: @@ -69,7 +69,7 @@ class LogStderrOutput : public LogFileStreamOutput { LogStderrOutput() : LogFileStreamOutput(stderr) { set_config_string("all=warning"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: diff --git a/hotspot/src/share/vm/logging/logOutput.hpp b/hotspot/src/share/vm/logging/logOutput.hpp index 1ca598c357f..5f06f388efd 100644 --- a/hotspot/src/share/vm/logging/logOutput.hpp +++ b/hotspot/src/share/vm/logging/logOutput.hpp @@ -82,7 +82,7 @@ class LogOutput : public CHeapObj { } virtual const char* name() const = 0; - virtual bool initialize(const char* options) = 0; + virtual bool initialize(const char* options, outputStream* errstream) = 0; virtual int write(const LogDecorations &decorations, const char* msg) = 0; }; diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index fcc9728f296..f8ee8918e8d 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -521,6 +521,9 @@ class os: AllStatic { static int ftruncate(int fd, jlong length); static int fsync(int fd); static int available(int fd, jlong *bytes); + static int fileno(FILE* fp); + + static int compare_file_modified_times(const char* file1, const char* file2); //File i/o operations diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 63bd284920d..985885c2edd 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -78,6 +78,9 @@ void InternalVMTests::run() { run_unit_test(Test_log_prefix); run_unit_test(Test_log_big); run_unit_test(Test_logtagset_duplicates); + run_unit_test(Test_log_file_startup_rotation); + run_unit_test(Test_log_file_startup_truncation); + run_unit_test(Test_invalid_log_file); run_unit_test(DirectivesParser_test); run_unit_test(Test_TempNewSymbol); #if INCLUDE_VM_STRUCTS diff --git a/hotspot/test/serviceability/logging/TestLogRotation.java b/hotspot/test/serviceability/logging/TestLogRotation.java index cd056dec1fe..025a9847a27 100644 --- a/hotspot/test/serviceability/logging/TestLogRotation.java +++ b/hotspot/test/serviceability/logging/TestLogRotation.java @@ -102,8 +102,10 @@ public class TestLogRotation { smallFilesNumber++; } } - if (logs.length != numberOfFiles) { - throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles); + // Expect one more log file since the number-of-files doesn't include the active log file + int expectedNumberOfFiles = numberOfFiles + 1; + if (logs.length != expectedNumberOfFiles) { + throw new Error("There are " + logs.length + " logs instead of the expected " + expectedNumberOfFiles); } if (smallFilesNumber > 1) { throw new Error("There should maximum one log with size < " + logFileSizeK + "K"); diff --git a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java index be2e76d9c51..39789ea01df 100644 --- a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java +++ b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java @@ -101,7 +101,7 @@ public class TestQuotedLogOutputs { output.shouldHaveExitValue(1); // Ensure error message was logged output.shouldMatch("([Mm]issing terminating quote)" - + "|(Could not open log file '')" + + "|(Error opening log file '')" + "|(Output name can not be partially quoted)"); } } From cf254af2fb7bf25ddd9cd9ed25b5619b94e5b6e4 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 12 Apr 2016 07:17:44 +0200 Subject: [PATCH 129/167] 8152491: Convert TracePageSizes to use UL Reviewed-by: sjohanss, pliden --- hotspot/src/os/windows/vm/os_windows.cpp | 14 +-- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 24 ++-- .../share/vm/gc/parallel/generationSizer.cpp | 15 --- .../share/vm/gc/parallel/generationSizer.hpp | 2 - .../share/vm/gc/parallel/parMarkBitMap.cpp | 2 +- .../vm/gc/parallel/parallelScavengeHeap.cpp | 6 +- .../vm/gc/parallel/psParallelCompact.cpp | 2 +- .../share/vm/gc/shared/cardTableModRefBS.cpp | 2 +- .../share/vm/gc/shared/genCollectedHeap.cpp | 8 ++ hotspot/src/share/vm/logging/logTag.hpp | 1 + hotspot/src/share/vm/runtime/globals.hpp | 3 - hotspot/src/share/vm/runtime/os.cpp | 71 ++++++++--- hotspot/src/share/vm/runtime/os.hpp | 20 ++-- .../share/vm/utilities/globalDefinitions.cpp | 110 +++++++++++++----- .../share/vm/utilities/globalDefinitions.hpp | 30 +++++ .../share/vm/utilities/internalVMTests.cpp | 2 +- .../gc/g1/TestLargePageUseForAuxMemory.java | 54 +++++++-- 17 files changed, 255 insertions(+), 111 deletions(-) diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 53e4528c0cc..72da7bae97b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -3006,9 +3006,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, } #ifdef ASSERT if (should_inject_error) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving pages individually failed."); - } + log_develop_debug(pagesize)("Reserving pages individually failed."); } #endif return NULL; @@ -3192,9 +3190,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) // 2) NUMA Interleaving is enabled, in which case we use a different node for each page if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages individually."); - } + log_debug(pagesize)("Reserving large pages individually."); + char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError); if (p_buf == NULL) { // give an appropriate warning message @@ -3211,9 +3208,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, return p_buf; } else { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages in a single large chunk."); - } + log_debug(pagesize)("Reserving large pages in a single large chunk."); + // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; char * res = (char *)VirtualAlloc(addr, bytes, flag, prot); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2861baf232d..03c406e4bad 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1829,10 +1829,14 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des HeapRegion::GrainBytes, translation_factor, mtGC); - if (TracePageSizes) { - tty->print_cr("G1 '%s': pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT " size=" SIZE_FORMAT " alignment=" SIZE_FORMAT " reqsize=" SIZE_FORMAT, - description, preferred_page_size, p2i(rs.base()), rs.size(), rs.alignment(), size); - } + + os::trace_page_sizes_for_requested_size(description, + size, + preferred_page_size, + rs.alignment(), + rs.base(), + rs.size()); + return result; } @@ -1906,26 +1910,28 @@ jint G1CollectedHeap::initialize() { HeapRegion::GrainBytes, 1, mtJavaHeap); - os::trace_page_sizes("G1 Heap", collector_policy()->min_heap_byte_size(), - max_byte_size, page_size, + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + max_byte_size, + page_size, heap_rs.base(), heap_rs.size()); heap_storage->set_mapping_changed_listener(&_listener); // Create storage for the BOT, card table, card counts table (hot card cache) and the bitmaps. G1RegionToSpaceMapper* bot_storage = - create_aux_memory_mapper("Block offset table", + create_aux_memory_mapper("Block Offset Table", G1BlockOffsetTable::compute_size(g1_rs.size() / HeapWordSize), G1BlockOffsetTable::heap_map_factor()); ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize)); G1RegionToSpaceMapper* cardtable_storage = - create_aux_memory_mapper("Card table", + create_aux_memory_mapper("Card Table", G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize), G1SATBCardTableLoggingModRefBS::heap_map_factor()); G1RegionToSpaceMapper* card_counts_storage = - create_aux_memory_mapper("Card counts table", + create_aux_memory_mapper("Card Counts Table", G1CardCounts::compute_size(g1_rs.size() / HeapWordSize), G1CardCounts::heap_map_factor()); diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp index 03067d9bdae..565bb31043f 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp @@ -26,18 +26,6 @@ #include "gc/parallel/generationSizer.hpp" #include "gc/shared/collectorPolicy.hpp" -void GenerationSizer::trace_gen_sizes(const char* const str) { - if (TracePageSizes) { - tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT, - str, - _min_old_size / K, _max_old_size / K, - _min_young_size / K, _max_young_size / K, - _max_heap_byte_size / K); - } -} - void GenerationSizer::initialize_alignments() { _space_alignment = _gen_alignment = default_gen_alignment(); _heap_alignment = compute_heap_alignment(); @@ -60,7 +48,6 @@ void GenerationSizer::initialize_flags() { } void GenerationSizer::initialize_size_info() { - trace_gen_sizes("ps heap raw"); const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8); const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages); @@ -76,6 +63,4 @@ void GenerationSizer::initialize_size_info() { initialize_flags(); } GenCollectorPolicy::initialize_size_info(); - - trace_gen_sizes("ps heap rnd"); } diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp index 9db480f0bb7..539629b1c96 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp @@ -33,8 +33,6 @@ class GenerationSizer : public GenCollectorPolicy { private: - void trace_gen_sizes(const char* const str); - // The alignment used for boundary between young gen and old gen static size_t default_gen_alignment() { return 64 * K * HeapWordSize; } diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp index 569ff9ecbb1..76241d92692 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp @@ -49,7 +49,7 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz, + os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp index eb4b07f0410..89f384cb6a8 100644 --- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp @@ -60,8 +60,10 @@ jint ParallelScavengeHeap::initialize() { ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment()); - os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(), - heap_size, generation_alignment(), + os::trace_page_sizes("Heap", + _collector_policy->min_heap_byte_size(), + heap_size, + generation_alignment(), heap_rs.base(), heap_rs.size()); diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index a309ccd0c7d..6b145d17c00 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -426,7 +426,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par compact", raw_bytes, raw_bytes, page_sz, rs.base(), + os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp index e40cc62ca47..9053dedba0f 100644 --- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp @@ -93,7 +93,7 @@ void CardTableModRefBS::initialize() { MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC); - os::trace_page_sizes("card table", _guard_index + 1, _guard_index + 1, + os::trace_page_sizes("Card Table", _guard_index + 1, _guard_index + 1, _page_size, heap_rs.base(), heap_rs.size()); if (!heap_rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for the " diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 7f76efbcd10..c60e3a02092 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -167,6 +167,14 @@ char* GenCollectedHeap::allocate(size_t alignment, SIZE_FORMAT, total_reserved, alignment); *heap_rs = Universe::reserve_heap(total_reserved, alignment); + + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + total_reserved, + alignment, + heap_rs->base(), + heap_rs->size()); + return heap_rs->base(); } diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 5e4fcc6a142..ede507df242 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -70,6 +70,7 @@ LOG_TAG(monitorinflation) \ LOG_TAG(monitormismatch) \ LOG_TAG(os) \ + LOG_TAG(pagesize) \ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 67c8321b0ed..fe2d2e615f0 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -685,9 +685,6 @@ public: "Use large page memory in metaspace. " \ "Only used if UseLargePages is enabled.") \ \ - develop(bool, TracePageSizes, false, \ - "Trace page size selection and usage") \ - \ product(bool, UseNUMA, false, \ "Use NUMA if available") \ \ diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 1644e43eb0e..ec103436269 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -33,6 +33,7 @@ #include "gc/shared/vmGCOperations.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #ifdef ASSERT #include "memory/guardedMemory.hpp" @@ -1494,31 +1495,63 @@ const char* os::errno_name(int e) { return errno_to_string(e, true); } -#ifndef PRODUCT -void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) -{ - if (TracePageSizes) { - tty->print("%s: ", str); +void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) { + LogTarget(Info, pagesize) log; + if (log.is_enabled()) { + LogStreamCHeap out(log); + + out.print("%s: ", str); for (int i = 0; i < count; ++i) { - tty->print(" " SIZE_FORMAT, page_sizes[i]); + out.print(" " SIZE_FORMAT, page_sizes[i]); } - tty->cr(); + out.cr(); } } -void os::trace_page_sizes(const char* str, const size_t region_min_size, - const size_t region_max_size, const size_t page_size, - const char* base, const size_t size) -{ - if (TracePageSizes) { - tty->print_cr("%s: min=" SIZE_FORMAT " max=" SIZE_FORMAT - " pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT - " size=" SIZE_FORMAT, - str, region_min_size, region_max_size, - page_size, p2i(base), size); - } +#define trace_page_size_params(size) byte_size_in_exact_unit(size), exact_unit_for_byte_size(size) + +void os::trace_page_sizes(const char* str, + const size_t region_min_size, + const size_t region_max_size, + const size_t page_size, + const char* base, + const size_t size) { + + log_info(pagesize)("%s: " + " min=" SIZE_FORMAT "%s" + " max=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(region_min_size), + trace_page_size_params(region_max_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(size)); } -#endif // #ifndef PRODUCT + +void os::trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size) { + + log_info(pagesize)("%s:" + " req_size=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " alignment=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(requested_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(alignment), + trace_page_size_params(size)); +} + // This is the working definition of a server class machine: // >= 2 physical CPU's and >=2GB of memory, with some fuzz diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 04b19698cf3..fcc9728f296 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -286,18 +286,24 @@ class os: AllStatic { return _page_sizes[0]; } - // Methods for tracing page sizes returned by the above method; enabled by - // TracePageSizes. The region_{min,max}_size parameters should be the values + // Methods for tracing page sizes returned by the above method. + // The region_{min,max}_size parameters should be the values // passed to page_size_for_region() and page_size should be the result of that // call. The (optional) base and size parameters should come from the // ReservedSpace base() and size() methods. - static void trace_page_sizes(const char* str, const size_t* page_sizes, - int count) PRODUCT_RETURN; - static void trace_page_sizes(const char* str, const size_t region_min_size, + static void trace_page_sizes(const char* str, const size_t* page_sizes, int count); + static void trace_page_sizes(const char* str, + const size_t region_min_size, const size_t region_max_size, const size_t page_size, - const char* base = NULL, - const size_t size = 0) PRODUCT_RETURN; + const char* base, + const size_t size); + static void trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size); static int vm_allocation_granularity(); static char* reserve_memory(size_t bytes, char* addr = 0, diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 98abb71dbe1..0a653abcbe9 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -374,39 +374,89 @@ STATIC_ASSERT(left_n_bits(1|2) == (intptr_t) LP64_ONLY(0xE000000000000000) NOT_L #ifndef PRODUCT // For unit testing only -class GlobalDefinitions { +class TestGlobalDefinitions { +private: + + static void test_clamp_address_in_page() { + intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; + const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); + + for (int i = 0; i < num_page_sizes; i++) { + intptr_t page_size = page_sizes[i]; + + address a_page = (address)(10*page_size); + + // Check that address within page is returned as is + assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); + assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); + + // Check that address above page returns start of next page + assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); + + // Check that address below page returns start of page + assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); + } + } + + static void test_exact_unit_for_byte_size() { + assert(strcmp(exact_unit_for_byte_size(0), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + K), "K") == 0, "incorrect"); +#ifdef LP64 + assert(strcmp(exact_unit_for_byte_size(G - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G), "G") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M + K), "K") == 0, "incorrect"); +#endif + } + + static void test_byte_size_in_exact_unit() { + assert(byte_size_in_exact_unit(0) == 0, "incorrect"); + assert(byte_size_in_exact_unit(1) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K - 1) == K - 1, "incorrect"); + assert(byte_size_in_exact_unit(K) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K + 1) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(M - 1) == M - 1, "incorrect"); + assert(byte_size_in_exact_unit(M) == 1, "incorrect"); + assert(byte_size_in_exact_unit(M + 1) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(M + K) == K + 1, "incorrect"); +#ifdef LP64 + assert(byte_size_in_exact_unit(G - 1) == G - 1, "incorrect"); + assert(byte_size_in_exact_unit(G) == 1, "incorrect"); + assert(byte_size_in_exact_unit(G + 1) == G + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + K) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M + K) == M + K + 1, "incorrect"); +#endif + } + + static void test_exact_units() { + test_exact_unit_for_byte_size(); + test_byte_size_in_exact_unit(); + } + public: - static void test_globals(); + static void test() { + test_clamp_address_in_page(); + test_exact_units(); + } }; -void GlobalDefinitions::test_globals() { - intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; - const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); - - for (int i = 0; i < num_page_sizes; i++) { - intptr_t page_size = page_sizes[i]; - - address a_page = (address)(10*page_size); - - // Check that address within page is returned as is - assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); - assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); - - // Check that address above page returns start of next page - assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); - - // Check that address below page returns start of page - assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); - } -} - -void GlobalDefinitions_test() { - GlobalDefinitions::test_globals(); +void TestGlobalDefinitions_test() { + TestGlobalDefinitions::test(); } #endif // PRODUCT diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 5a080626ada..3c04e2a0f54 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -243,6 +243,36 @@ inline T byte_size_in_proper_unit(T s) { } } +inline const char* exact_unit_for_byte_size(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return "G"; + } +#endif + if (s >= M && (s % M) == 0) { + return "M"; + } + if (s >= K && (s % K) == 0) { + return "K"; + } + return "B"; +} + +inline size_t byte_size_in_exact_unit(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return s / G; + } +#endif + if (s >= M && (s % M) == 0) { + return s / M; + } + if (s >= K && (s % K) == 0) { + return s / K; + } + return s; +} + //---------------------------------------------------------------------------------------------------- // VM type definitions diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 4adaf307425..9b3df11e27b 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -50,7 +50,7 @@ void InternalVMTests::run() { run_unit_test(TestMetaspaceAux_test); run_unit_test(TestMetachunk_test); run_unit_test(TestVirtualSpaceNode_test); - run_unit_test(GlobalDefinitions_test); + run_unit_test(TestGlobalDefinitions_test); run_unit_test(GCTimer_test); run_unit_test(arrayOopDesc_test); run_unit_test(CollectedHeap_test); diff --git a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java index 03d214d19ec..28f1b166a4d 100644 --- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java +++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java @@ -36,6 +36,8 @@ */ import java.lang.Math; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import jdk.test.lib.*; import jdk.test.lib.Asserts; @@ -47,14 +49,29 @@ public class TestLargePageUseForAuxMemory { static long smallPageSize; static long allocGranularity; + static void checkSize(OutputAnalyzer output, long expectedSize, String pattern) { + String pageSizeStr = output.firstMatch(pattern, 1); + + if (pageSizeStr == null) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got 'null' expected: " + expectedSize); + } + + long size = parseMemoryString(pageSizeStr); + if (size != expectedSize) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got " + size + " expected: " + expectedSize); + } + } + static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Block offset table': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Card counts table': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Block Offset Table: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Card Counts Table: .*page_size=([^ ]+)"); } static void checkBitmaps(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Prev Bitmap': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Next Bitmap': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Prev Bitmap: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Next Bitmap: .*page_size=([^ ]+)"); } static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception { @@ -66,7 +83,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:+UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -82,7 +99,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:-UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -108,11 +125,6 @@ public class TestLargePageUseForAuxMemory { } public static void main(String[] args) throws Exception { - if (!Platform.isDebugBuild()) { - System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option."); - return; - } - // Size that a single card covers. final int cardSize = 512; WhiteBox wb = WhiteBox.getWhiteBox(); @@ -159,4 +171,24 @@ public class TestLargePageUseForAuxMemory { testVM("case5: only bitmap uses large pages (extra slack)", heapSizeForBitmapUsingLargePages + heapSizeDiffForBitmap, false, true); testVM("case6: nothing uses large pages (barely not)", heapSizeForBitmapUsingLargePages - heapSizeDiffForBitmap, false, false); } + + public static long parseMemoryString(String value) { + long multiplier = 1; + + if (value.endsWith("B")) { + multiplier = 1; + } else if (value.endsWith("K")) { + multiplier = 1024; + } else if (value.endsWith("M")) { + multiplier = 1024 * 1024; + } else if (value.endsWith("G")) { + multiplier = 1024 * 1024 * 1024; + } else { + throw new IllegalArgumentException("Expected memory string '" + value + "'to end with either of: B, K, M, G"); + } + + long longValue = Long.parseUnsignedLong(value.substring(0, value.length() - 1)); + + return longValue * multiplier; + } } From f78228b2eeeacf2db6873ab93bd1523e79d00aa5 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Tue, 12 Apr 2016 09:53:43 +0200 Subject: [PATCH 130/167] 8153967: Remove top.hpp Reviewed-by: coleenp, jwilhelm --- hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp | 1 - hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp | 1 - .../src/cpu/aarch64/vm/nativeInst_aarch64.hpp | 1 - .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 1 - hotspot/src/cpu/ppc/vm/debug_ppc.cpp | 1 - hotspot/src/cpu/ppc/vm/frame_ppc.hpp | 1 - hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp | 1 - hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 1 - hotspot/src/cpu/sparc/vm/debug_sparc.cpp | 1 - hotspot/src/cpu/sparc/vm/frame_sparc.hpp | 1 - hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp | 1 - .../src/cpu/sparc/vm/stubGenerator_sparc.cpp | 1 - hotspot/src/cpu/x86/vm/debug_x86.cpp | 1 - hotspot/src/cpu/x86/vm/frame_x86.hpp | 1 - hotspot/src/cpu/x86/vm/nativeInst_x86.hpp | 1 - .../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 1 - .../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 1 - hotspot/src/cpu/zero/vm/debug_zero.cpp | 1 - hotspot/src/cpu/zero/vm/frame_zero.hpp | 1 - hotspot/src/cpu/zero/vm/nativeInst_zero.hpp | 1 - .../src/cpu/zero/vm/stubGenerator_zero.cpp | 1 - hotspot/src/share/vm/asm/assembler.hpp | 1 - hotspot/src/share/vm/asm/register.hpp | 3 +- hotspot/src/share/vm/c1/c1_LIRAssembler.hpp | 1 - hotspot/src/share/vm/ci/ciFlags.hpp | 1 + .../share/vm/classfile/classFileStream.hpp | 3 +- hotspot/src/share/vm/code/relocInfo.hpp | 3 +- hotspot/src/share/vm/code/vmreg.hpp | 3 +- .../vm/gc/parallel/psAdaptiveSizePolicy.cpp | 1 - .../vm/interpreter/abstractInterpreter.hpp | 1 - .../share/vm/interpreter/bytecodeTracer.hpp | 1 + .../src/share/vm/interpreter/bytecodes.hpp | 3 +- .../vm/interpreter/interpreterRuntime.hpp | 1 - .../src/share/vm/interpreter/linkResolver.hpp | 1 - hotspot/src/share/vm/memory/iterator.hpp | 3 +- hotspot/src/share/vm/oops/oop.hpp | 1 - hotspot/src/share/vm/oops/symbol.hpp | 3 +- .../src/share/vm/precompiled/precompiled.hpp | 1 - hotspot/src/share/vm/prims/jvm.cpp | 1 - hotspot/src/share/vm/prims/nativeLookup.hpp | 2 +- hotspot/src/share/vm/runtime/arguments.hpp | 1 - hotspot/src/share/vm/runtime/basicLock.hpp | 1 - hotspot/src/share/vm/runtime/frame.hpp | 1 - hotspot/src/share/vm/runtime/globals.cpp | 1 - .../share/vm/runtime/globals_extension.hpp | 14 ++++- hotspot/src/share/vm/runtime/init.hpp | 2 +- .../src/share/vm/runtime/interfaceSupport.hpp | 1 - hotspot/src/share/vm/runtime/jniHandles.hpp | 2 +- hotspot/src/share/vm/runtime/os.hpp | 1 - hotspot/src/share/vm/runtime/osThread.hpp | 1 - hotspot/src/share/vm/runtime/signature.hpp | 1 - hotspot/src/share/vm/runtime/stackValue.hpp | 1 - hotspot/src/share/vm/runtime/stubRoutines.hpp | 1 - hotspot/src/share/vm/runtime/synchronizer.hpp | 2 - hotspot/src/share/vm/runtime/task.hpp | 3 +- hotspot/src/share/vm/runtime/thread.hpp | 1 - .../share/vm/runtime/threadLocalStorage.hpp | 2 +- .../src/share/vm/runtime/vm_operations.hpp | 1 - .../src/share/vm/utilities/accessFlags.hpp | 3 +- hotspot/src/share/vm/utilities/bitMap.hpp | 1 - .../src/share/vm/utilities/constantTag.cpp | 1 + .../src/share/vm/utilities/constantTag.hpp | 2 +- hotspot/src/share/vm/utilities/debug.cpp | 1 - hotspot/src/share/vm/utilities/events.hpp | 1 - hotspot/src/share/vm/utilities/exceptions.hpp | 1 - .../share/vm/utilities/globalDefinitions.cpp | 1 - .../src/share/vm/utilities/growableArray.hpp | 1 - hotspot/src/share/vm/utilities/ostream.cpp | 1 - hotspot/src/share/vm/utilities/pair.hpp | 1 - .../src/share/vm/utilities/resourceHash.hpp | 1 - hotspot/src/share/vm/utilities/top.hpp | 52 ------------------- hotspot/src/share/vm/utilities/utf8.hpp | 1 - hotspot/src/share/vm/utilities/vmError.cpp | 1 - 73 files changed, 38 insertions(+), 123 deletions(-) delete mode 100644 hotspot/src/share/vm/utilities/top.hpp diff --git a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp index 107f6085474..72fc4d7df63 100644 --- a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp index d267036974e..4332abce9f4 100644 --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp @@ -27,7 +27,6 @@ #define CPU_AARCH64_VM_FRAME_AARCH64_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp index d83017c1770..a3a6d6a1302 100644 --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index d618c0351f7..b0787ddf4a9 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -39,7 +39,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp index 5427a1e4644..ff92dd4e50d 100644 --- a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp index 8115a20640e..6f8f0296f83 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -27,7 +27,6 @@ #define CPU_PPC_VM_FRAME_PPC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // C frame layout on PPC-64. // diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index 586dcaa9380..99aa11c4b20 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -31,7 +31,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 0f6c6f77fdb..2eba3edacef 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -37,7 +37,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" -#include "utilities/top.hpp" #include "runtime/thread.inline.hpp" #define __ _masm-> diff --git a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp index 8be1072fc65..9f3f40ada7c 100644 --- a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp @@ -29,7 +29,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" #ifndef PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index 5de8ad4bf1d..cd91f52fd17 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -26,7 +26,6 @@ #define CPU_SPARC_VM_FRAME_SPARC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index a5f04a8f5b9..d0582f34265 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interface for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 98d82ee07e5..db2c5eefac8 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -37,7 +37,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/debug_x86.cpp b/hotspot/src/cpu/x86/vm/debug_x86.cpp index b128439ef23..0bde483a789 100644 --- a/hotspot/src/cpu/x86/vm/debug_x86.cpp +++ b/hotspot/src/cpu/x86/vm/debug_x86.cpp @@ -29,6 +29,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.hpp b/hotspot/src/cpu/x86/vm/frame_x86.hpp index 6c85be06a81..b10f9ce37e6 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp @@ -26,7 +26,6 @@ #define CPU_X86_VM_FRAME_X86_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp index 6c527d49991..1bb1c6c8aff 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 756c032861e..0f11b9c0371 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 882969c5695..d51f3a696a0 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/zero/vm/debug_zero.cpp b/hotspot/src/cpu/zero/vm/debug_zero.cpp index 19d00e33cdc..24580fecf5f 100644 --- a/hotspot/src/cpu/zero/vm/debug_zero.cpp +++ b/hotspot/src/cpu/zero/vm/debug_zero.cpp @@ -30,7 +30,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) { ShouldNotCallThis(); diff --git a/hotspot/src/cpu/zero/vm/frame_zero.hpp b/hotspot/src/cpu/zero/vm/frame_zero.hpp index 56f0a1716b0..2f1c931c690 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp @@ -27,7 +27,6 @@ #define CPU_ZERO_VM_FRAME_ZERO_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame on the Zero stack. diff --git a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp index 559bde79ab6..8b60b358f5e 100644 --- a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp +++ b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp index 9d999a8c805..bdaec67cd73 100644 --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp @@ -40,7 +40,6 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "stack_zero.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index 40bd5d379e0..2ef9d993721 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -33,7 +33,6 @@ #include "runtime/vm_version.hpp" #include "utilities/debug.hpp" #include "utilities/growableArray.hpp" -#include "utilities/top.hpp" // This file contains platform-independent assembler declarations. diff --git a/hotspot/src/share/vm/asm/register.hpp b/hotspot/src/share/vm/asm/register.hpp index 5e43cfa68fd..e258e867c1d 100644 --- a/hotspot/src/share/vm/asm/register.hpp +++ b/hotspot/src/share/vm/asm/register.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_ASM_REGISTER_HPP #define SHARE_VM_ASM_REGISTER_HPP -#include "utilities/top.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" // Use AbstractRegister as shortcut class AbstractRegisterImpl; diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 8c2c97ece41..42e6f6642d3 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -28,7 +28,6 @@ #include "c1/c1_CodeStubs.hpp" #include "ci/ciMethodData.hpp" #include "oops/methodData.hpp" -#include "utilities/top.hpp" class Compilation; class ScopeValue; diff --git a/hotspot/src/share/vm/ci/ciFlags.hpp b/hotspot/src/share/vm/ci/ciFlags.hpp index 60d5632f4bb..783064253c1 100644 --- a/hotspot/src/share/vm/ci/ciFlags.hpp +++ b/hotspot/src/share/vm/ci/ciFlags.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" #include "prims/jvm.h" #include "utilities/accessFlags.hpp" +#include "utilities/ostream.hpp" // ciFlags // diff --git a/hotspot/src/share/vm/classfile/classFileStream.hpp b/hotspot/src/share/vm/classfile/classFileStream.hpp index 2d69de74b3a..90ae4e9d34a 100644 --- a/hotspot/src/share/vm/classfile/classFileStream.hpp +++ b/hotspot/src/share/vm/classfile/classFileStream.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP #define SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP +#include "memory/allocation.hpp" #include "utilities/bytes.hpp" -#include "utilities/top.hpp" +#include "utilities/exceptions.hpp" // Input stream for reading .class file // diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index b399c093759..86a454c153f 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.hpp @@ -26,8 +26,9 @@ #define SHARE_VM_CODE_RELOCINFO_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" +#include "runtime/os.hpp" +class Metadata; class NativeMovConstReg; // Types in this file: diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index fb9228c3ee9..e6bc343c07d 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -28,10 +28,9 @@ #include "asm/register.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" - +#include "utilities/ostream.hpp" #ifdef COMPILER2 #include "opto/adlcVMDeps.hpp" -#include "utilities/ostream.hpp" #endif //------------------------------VMReg------------------------------------------ diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp index 4506ed67ee3..c8554287512 100644 --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp @@ -32,7 +32,6 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" -#include "utilities/top.hpp" #include diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 2c527a8f893..8ec0db7e0de 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -30,7 +30,6 @@ #include "interpreter/bytecodes.hpp" #include "runtime/thread.hpp" #include "runtime/vmThread.hpp" -#include "utilities/top.hpp" // This file contains the platform-independent parts // of the abstract interpreter and the abstract interpreter generator. diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp index 06d2a1d8899..dff27c66022 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_INTERPRETER_BYTECODETRACER_HPP #include "memory/allocation.hpp" +#include "utilities/ostream.hpp" // The BytecodeTracer is a helper class used by the interpreter for run-time // bytecode tracing. If bytecode tracing is turned on, trace() will be called diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 20990d64b9e..4f52e7b4a1a 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -26,11 +26,12 @@ #define SHARE_VM_INTERPRETER_BYTECODES_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Bytecodes specifies all bytecodes used in the VM and // provides utility functions to get bytecode attributes. +class Method; + // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/interpreter/Bytecodes.java class Bytecodes: AllStatic { public: diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index dd4f797b0c7..d8ef297e21d 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -32,7 +32,6 @@ #include "runtime/frame.inline.hpp" #include "runtime/signature.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" // The InterpreterRuntime is called by the interpreter for everything // that cannot/should not be dealt with in assembly and needs C support. diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index a197070dadd..4dae8111e18 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_INTERPRETER_LINKRESOLVER_HPP #include "oops/method.hpp" -#include "utilities/top.hpp" // All the necessary definitions for run-time link resolution. diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp index 6d7d9d4fece..3a36dc6d5f5 100644 --- a/hotspot/src/share/vm/memory/iterator.hpp +++ b/hotspot/src/share/vm/memory/iterator.hpp @@ -27,7 +27,7 @@ #include "memory/allocation.hpp" #include "memory/memRegion.hpp" -#include "utilities/top.hpp" +#include "oops/oopsHierarchy.hpp" class CodeBlob; class nmethod; @@ -35,6 +35,7 @@ class ReferenceProcessor; class DataLayout; class KlassClosure; class ClassLoaderData; +class Symbol; // The following classes are C++ `closures` for iterating over objects, roots and spaces diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index d154f966568..23d73067178 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -30,7 +30,6 @@ #include "memory/memRegion.hpp" #include "oops/metadata.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe // the format of Java objects so the fields can be accessed from C++. diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index f4241d3ad8d..b2d71d51335 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_OOPS_SYMBOL_HPP #define SHARE_VM_OOPS_SYMBOL_HPP -#include "utilities/utf8.hpp" #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "utilities/exceptions.hpp" +#include "utilities/utf8.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index f3e0fea113f..81bd00eaaf8 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -242,7 +242,6 @@ # include "utilities/ostream.hpp" # include "utilities/preserveException.hpp" # include "utilities/sizes.hpp" -# include "utilities/top.hpp" # include "utilities/utf8.hpp" #ifdef COMPILER2 # include "libadt/dict.hpp" diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 0619af4f9fd..85e2c9ebb83 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -79,7 +79,6 @@ #include "utilities/events.hpp" #include "utilities/histogram.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/utf8.hpp" #if INCLUDE_CDS #include "classfile/sharedClassUtil.hpp" diff --git a/hotspot/src/share/vm/prims/nativeLookup.hpp b/hotspot/src/share/vm/prims/nativeLookup.hpp index d1cfcb9259a..3afc5039eb2 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.hpp +++ b/hotspot/src/share/vm/prims/nativeLookup.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_PRIMS_NATIVELOOKUP_HPP #define SHARE_VM_PRIMS_NATIVELOOKUP_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" // NativeLookup provides an interface for finding DLL entry points for // Java native functions. diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 1dc3135aff6..328a9d71872 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -31,7 +31,6 @@ #include "runtime/os.hpp" #include "runtime/perfData.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" // Arguments parses the command line and recognizes options diff --git a/hotspot/src/share/vm/runtime/basicLock.hpp b/hotspot/src/share/vm/runtime/basicLock.hpp index cc4e37eed52..f47c5add571 100644 --- a/hotspot/src/share/vm/runtime/basicLock.hpp +++ b/hotspot/src/share/vm/runtime/basicLock.hpp @@ -27,7 +27,6 @@ #include "oops/markOop.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class BasicLock VALUE_OBJ_CLASS_SPEC { friend class VMStructs; diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index cbd63cd20b2..0bb1d875071 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -29,7 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/monitorChunk.hpp" #include "runtime/registerMap.hpp" -#include "utilities/top.hpp" #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 1728da3e857..7e752adac01 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -35,7 +35,6 @@ #include "trace/tracing.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1_globals.hpp" #endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 45830e56623..b550f236042 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -27,7 +27,19 @@ #include "runtime/globals.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS +#include "gc/g1/g1_globals.hpp" +#endif +#if INCLUDE_JVMCI +#include "jvmci/jvmci_globals.hpp" +#endif +#ifdef COMPILER1 +#include "c1/c1_globals.hpp" +#endif +#ifdef COMPILER2 +#include "opto/c2_globals.hpp" +#endif // Construct enum of Flag_ constants. diff --git a/hotspot/src/share/vm/runtime/init.hpp b/hotspot/src/share/vm/runtime/init.hpp index fd9fdf6f64a..77158f5a937 100644 --- a/hotspot/src/share/vm/runtime/init.hpp +++ b/hotspot/src/share/vm/runtime/init.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_INIT_HPP #define SHARE_VM_RUNTIME_INIT_HPP -#include "utilities/top.hpp" +#include "utilities/globalDefinitions.hpp" // init_globals replaces C++ global objects so we can use the standard linker // to link Delta (which is at least twice as fast as using the GNU C++ linker). diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 8dbc6be317c..de3ef8f648b 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -35,7 +35,6 @@ #include "runtime/vmThread.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/preserveException.hpp" -#include "utilities/top.hpp" // Wrapper for all entry points to the virtual machine. // The HandleMarkCleaner is a faster version of HandleMark. diff --git a/hotspot/src/share/vm/runtime/jniHandles.hpp b/hotspot/src/share/vm/runtime/jniHandles.hpp index 1503a3696b6..ce37d940d7c 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.hpp +++ b/hotspot/src/share/vm/runtime/jniHandles.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_RUNTIME_JNIHANDLES_HPP #define SHARE_VM_RUNTIME_JNIHANDLES_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class JNIHandleBlock; diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index fcc9728f296..edd15f04a7e 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -28,7 +28,6 @@ #include "jvmtifiles/jvmti.h" #include "runtime/extendedPC.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" # include diff --git a/hotspot/src/share/vm/runtime/osThread.hpp b/hotspot/src/share/vm/runtime/osThread.hpp index 29912bd5187..16cc2e8055e 100644 --- a/hotspot/src/share/vm/runtime/osThread.hpp +++ b/hotspot/src/share/vm/runtime/osThread.hpp @@ -29,7 +29,6 @@ #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" #include "runtime/objectMonitor.hpp" -#include "utilities/top.hpp" // The OSThread class holds OS-specific thread information. It is equivalent // to the sys_thread_t structure of the classic JVM implementation. diff --git a/hotspot/src/share/vm/runtime/signature.hpp b/hotspot/src/share/vm/runtime/signature.hpp index 46e36e9f532..3e0bb829cfc 100644 --- a/hotspot/src/share/vm/runtime/signature.hpp +++ b/hotspot/src/share/vm/runtime/signature.hpp @@ -27,7 +27,6 @@ #include "memory/allocation.hpp" #include "oops/method.hpp" -#include "utilities/top.hpp" // SignatureIterators iterate over a Java signature (or parts of it). // (Syntax according to: "The Java Virtual Machine Specification" by diff --git a/hotspot/src/share/vm/runtime/stackValue.hpp b/hotspot/src/share/vm/runtime/stackValue.hpp index a7698f50b74..569ef58f89a 100644 --- a/hotspot/src/share/vm/runtime/stackValue.hpp +++ b/hotspot/src/share/vm/runtime/stackValue.hpp @@ -27,7 +27,6 @@ #include "code/location.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class StackValue : public ResourceObj { private: diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 38fe86e631b..55cd9934bd0 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -30,7 +30,6 @@ #include "runtime/frame.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/stubCodeGenerator.hpp" -#include "utilities/top.hpp" // StubRoutines provides entry points to assembly routines used by // compiled code and the run-time system. Platform-specific entry diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index ab3d145842c..777317b927c 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -29,8 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/handles.hpp" #include "runtime/perfData.hpp" -#include "utilities/top.hpp" - class ObjectMonitor; diff --git a/hotspot/src/share/vm/runtime/task.hpp b/hotspot/src/share/vm/runtime/task.hpp index c7181089ee2..b3e5f927aee 100644 --- a/hotspot/src/share/vm/runtime/task.hpp +++ b/hotspot/src/share/vm/runtime/task.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_RUNTIME_TASK_HPP #define SHARE_VM_RUNTIME_TASK_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" +#include "runtime/timer.hpp" // A PeriodicTask has the sole purpose of executing its task // function with regular intervals. diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 4f993ab8fa1..0d54deec3ef 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -46,7 +46,6 @@ #include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/satbMarkQueue.hpp" diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp index 016e1fc1196..fbd370ed867 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP #define SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" // forward-decl as we can't have an include cycle class Thread; diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 22626d2c2a8..2807768339f 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "code/codeCache.hpp" // The following classes are used for operations diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp index 8e9219fe8bc..d9c1685e2b9 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.hpp +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_UTILITIES_ACCESSFLAGS_HPP #define SHARE_VM_UTILITIES_ACCESSFLAGS_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" // AccessFlags is an abstraction over Java access flags. diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index b925d66442f..b41cc12062e 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_BITMAP_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Forward decl; class BitMapClosure; diff --git a/hotspot/src/share/vm/utilities/constantTag.cpp b/hotspot/src/share/vm/utilities/constantTag.cpp index 1495a42e624..187bb5ed200 100644 --- a/hotspot/src/share/vm/utilities/constantTag.cpp +++ b/hotspot/src/share/vm/utilities/constantTag.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "utilities/constantTag.hpp" +#include "utilities/ostream.hpp" #ifndef PRODUCT diff --git a/hotspot/src/share/vm/utilities/constantTag.hpp b/hotspot/src/share/vm/utilities/constantTag.hpp index ae99d570693..c083848c0bd 100644 --- a/hotspot/src/share/vm/utilities/constantTag.hpp +++ b/hotspot/src/share/vm/utilities/constantTag.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_UTILITIES_CONSTANTTAG_HPP #define SHARE_VM_UTILITIES_CONSTANTTAG_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" // constant tags in Java .class files diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index f6fd336bca8..ad1e9e43a78 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -52,7 +52,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" #if INCLUDE_TRACE diff --git a/hotspot/src/share/vm/utilities/events.hpp b/hotspot/src/share/vm/utilities/events.hpp index 5b65fcc1a6f..3ff1e52a1b4 100644 --- a/hotspot/src/share/vm/utilities/events.hpp +++ b/hotspot/src/share/vm/utilities/events.hpp @@ -28,7 +28,6 @@ #include "memory/allocation.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // Events and EventMark provide interfaces to log events taking place in the vm. diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index cdfa0bdf817..e7aaf800237 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -47,7 +47,6 @@ // Forward declarations to be independent of the include structure. -// This allows us to have exceptions.hpp included in top.hpp. class Thread; class Handle; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 0a653abcbe9..7f69396d84d 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // Basic error support diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp index a2780fecca5..fccbad3645f 100644 --- a/hotspot/src/share/vm/utilities/growableArray.hpp +++ b/hotspot/src/share/vm/utilities/growableArray.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.inline.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // A growable array. diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 0f1057ed1ce..e9cc5fc2f08 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -31,7 +31,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #include "utilities/xmlstream.hpp" extern "C" void jio_print(const char* s); // Declarationtion of jvm method diff --git a/hotspot/src/share/vm/utilities/pair.hpp b/hotspot/src/share/vm/utilities/pair.hpp index d0bb5d65c4b..7c901539c56 100644 --- a/hotspot/src/share/vm/utilities/pair.hpp +++ b/hotspot/src/share/vm/utilities/pair.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_PAIR_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template class Pair : public ALLOC_BASE { diff --git a/hotspot/src/share/vm/utilities/resourceHash.hpp b/hotspot/src/share/vm/utilities/resourceHash.hpp index 82c1219b465..bfd0a1f2d94 100644 --- a/hotspot/src/share/vm/utilities/resourceHash.hpp +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template struct ResourceHashtableFns { typedef unsigned (*hash_fn)(K const&); diff --git a/hotspot/src/share/vm/utilities/top.hpp b/hotspot/src/share/vm/utilities/top.hpp deleted file mode 100644 index de26d52bc02..00000000000 --- a/hotspot/src/share/vm/utilities/top.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 - * 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. - * - */ - -#ifndef SHARE_VM_UTILITIES_TOP_HPP -#define SHARE_VM_UTILITIES_TOP_HPP - -#include "oops/oopsHierarchy.hpp" -#include "runtime/globals.hpp" -#include "utilities/debug.hpp" -#include "utilities/exceptions.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" -#include "utilities/ostream.hpp" -#include "utilities/sizes.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1_globals.hpp" -#endif // INCLUDE_ALL_GCS -#ifdef COMPILER1 -#include "c1/c1_globals.hpp" -#endif -#ifdef COMPILER2 -#include "opto/c2_globals.hpp" -#endif -#if INCLUDE_JVMCI -#include "jvmci/jvmci_globals.hpp" -#endif - -// THIS FILE IS INTESIONALLY LEFT EMPTY -// IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB - -#endif // SHARE_VM_UTILITIES_TOP_HPP diff --git a/hotspot/src/share/vm/utilities/utf8.hpp b/hotspot/src/share/vm/utilities/utf8.hpp index 1a30cb456fc..34deeb953f7 100644 --- a/hotspot/src/share/vm/utilities/utf8.hpp +++ b/hotspot/src/share/vm/utilities/utf8.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_UTF8_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Low-level interface for UTF8 strings diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 0f128c1f286..4ca94f391a4 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -43,7 +43,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/errorReporter.hpp" #include "utilities/events.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // List of environment variables that should be reported in error log file. From 89282b0c72136010754d64ed1278f4656883b7fa Mon Sep 17 00:00:00 2001 From: Mikael Gerdin Date: Tue, 12 Apr 2016 14:03:31 +0200 Subject: [PATCH 131/167] 8153834: G1 Card table verification fails due to concurrent region cleanup Reviewed-by: ehelin, tschatzl --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 03c406e4bad..2980eecdc0e 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4824,6 +4824,9 @@ void G1CollectedHeap::cleanUpCardTable() { workers()->run_task(&cleanup_task); #ifndef PRODUCT + // Need to synchronize with concurrent cleanup since it needs to + // finish its card table clearing before we can verify. + wait_while_free_regions_coming(); _verifier->verify_card_table_cleanup(); #endif } From 8423e2c392543ba5f4d0bc8266cefa8966f2f46c Mon Sep 17 00:00:00 2001 From: Derek White Date: Tue, 12 Apr 2016 14:46:02 -0400 Subject: [PATCH 132/167] 8149405: OOM Error running java/lang/invoke/MethodHandlesTest.java on windows-x86 Add missing ResourceMarks to release memory more quickly. Reviewed-by: jmasa, kbarrett --- hotspot/src/share/vm/oops/methodData.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index d5f5d6ad454..85f7c9b6098 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1729,6 +1729,7 @@ void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { } void MethodData::clean_method_data(BoolObjectClosure* is_alive) { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1745,6 +1746,7 @@ void MethodData::clean_method_data(BoolObjectClosure* is_alive) { } void MethodData::clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1758,6 +1760,7 @@ void MethodData::clean_weak_method_links() { #ifdef ASSERT void MethodData::verify_clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { From 7e7ae63929c0fe629d2443bcd1bbd9892cea029c Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 13 Apr 2016 11:13:14 +0200 Subject: [PATCH 133/167] 8154087: Fix AIX and Linux/ppc64le after the integration of the new hotspot build Reviewed-by: erikj, goetz --- hotspot/makefiles/gensrc/GensrcAdlc.gmk | 7 +++---- hotspot/src/os/aix/vm/perfMemory_aix.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/hotspot/makefiles/gensrc/GensrcAdlc.gmk b/hotspot/makefiles/gensrc/GensrcAdlc.gmk index eb58ac7737c..a33d42db206 100644 --- a/hotspot/makefiles/gensrc/GensrcAdlc.gmk +++ b/hotspot/makefiles/gensrc/GensrcAdlc.gmk @@ -41,9 +41,8 @@ ifeq ($(call check-jvm-feature, compiler2), true) ADLC_CFLAGS := -m64 ADLC_CFLAGS_WARNINGS := +w else ifeq ($(OPENJDK_BUILD_OS), aix) - # FIXME: Not implemented. These flags are likely, however - # ADLC_LDFLAGS := -q64 - # ADLC_CFLAGS := -qnortti -qnoeh -q64 + ADLC_LDFLAGS := -q64 + ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX else ifeq ($(OPENJDK_BUILD_OS), windows) ADLC_LDFLAGS := -nologo ADLC_CFLAGS := -nologo -EHsc @@ -89,7 +88,7 @@ ifeq ($(call check-jvm-feature, compiler2), true) else ifeq ($(OPENJDK_TARGET_OS), solaris) ADLCFLAGS += -DSOLARIS=1 -DSPARC_WORKS=1 else ifeq ($(OPENJDK_TARGET_OS), aix) - # FIXME: Not implemented + ADLCFLAGS += -DAIX=1 else ifeq ($(OPENJDK_TARGET_OS), macosx) ADLCFLAGS += -D_ALLBSD_SOURCE=1 -D_GNU_SOURCE=1 endif diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index e9621012b7b..62212be7175 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -956,7 +956,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { #ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); #else - open_o_nofollow(filename, oflags); + result = open_o_nofollow(filename, oflags); #endif if (result == OS_ERR) { From bf3b2fe3608c363bed0e1aa1cefd9d31a73b668e Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 13 Apr 2016 11:13:14 +0200 Subject: [PATCH 134/167] 8154087: Fix AIX and Linux/ppc64le after the integration of the new hotspot build Reviewed-by: erikj, goetz --- common/autoconf/flags.m4 | 25 +++++------ common/autoconf/generated-configure.sh | 60 +++++++++++++++----------- common/autoconf/platform.m4 | 4 ++ 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 5e9fc128843..7789f01450e 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -929,20 +929,21 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], elif test "x$OPENJDK_$1_CPU" = xppc64; then if test "x$OPENJDK_$1_OS" = xlinux; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_$1_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_$1_OS" = xaix; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index d97c4b4ebc7..632dd15d1b0 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -5056,7 +5056,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1460103573 +DATE_WHEN_GENERATED=1460538705 ############################################################################### # @@ -15448,6 +15448,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_TARGET_CPU=sparc elif test "x$OPENJDK_TARGET_CPU" = xppc64; then HOTSPOT_TARGET_CPU=ppc_64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU=ppc_64 fi @@ -15466,6 +15468,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_TARGET_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_TARGET_CPU" = xppc64; then HOTSPOT_TARGET_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_TARGET_CPU" = xsparc; then @@ -15600,6 +15604,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_BUILD_CPU=sparc elif test "x$OPENJDK_BUILD_CPU" = xppc64; then HOTSPOT_BUILD_CPU=ppc_64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU=ppc_64 fi @@ -15618,6 +15624,8 @@ $as_echo "$COMPILE_TYPE" >&6; } HOTSPOT_BUILD_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_BUILD_CPU" = xppc64; then HOTSPOT_BUILD_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_BUILD_CPU" = xsparc; then @@ -49834,20 +49842,21 @@ $as_echo "$supports" >&6; } elif test "x$OPENJDK_TARGET_CPU" = xppc64; then if test "x$OPENJDK_TARGET_OS" = xlinux; then JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_TARGET_OS" = xaix; then JVM_CFLAGS="$JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then @@ -50610,20 +50619,21 @@ $as_echo "$supports" >&6; } elif test "x$OPENJDK_BUILD_CPU" = xppc64; then if test "x$OPENJDK_BUILD_OS" = xlinux; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" - if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xbig; then - # fixes `relocation truncated to fit' error for gcc 4.1. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" - # Use ppc64 instructions, but schedule for power5 - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" - else - # Little endian machine uses ELFv2 ABI. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" - # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" - fi + # fixes `relocation truncated to fit' error for gcc 4.1. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" elif test "x$OPENJDK_BUILD_OS" = xaix; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qarch=ppc64" - fi + fi + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi fi if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 587f80dbcd5..deaf22ed169 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -405,6 +405,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU=sparc elif test "x$OPENJDK_$1_CPU" = xppc64; then HOTSPOT_$1_CPU=ppc_64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU=ppc_64 fi AC_SUBST(HOTSPOT_$1_CPU) @@ -423,6 +425,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU_DEFINE=AARCH64 elif test "x$OPENJDK_$1_CPU" = xppc64; then HOTSPOT_$1_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU_DEFINE=PPC64 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then From 23da19a7903106b21f133b30a56107d98a158d4f Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Wed, 13 Apr 2016 19:55:40 +0400 Subject: [PATCH 135/167] 8153755: Improve test: stress/gc/TestStressRSetCoarsening.java Reviewed-by: tschatzl, kzhaldyb --- .../stress/gc/TestStressRSetCoarsening.java | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/stress/gc/TestStressRSetCoarsening.java index 10ac597facc..bf3cd499e13 100644 --- a/hotspot/test/stress/gc/TestStressRSetCoarsening.java +++ b/hotspot/test/stress/gc/TestStressRSetCoarsening.java @@ -38,29 +38,29 @@ import sun.hotspot.WhiteBox; * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 1 0 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=8m TestStressRSetCoarsening 1 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=32m TestStressRSetCoarsening 42 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 2 0 300 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 500 0 1800 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 10 10 1800 */ /** @@ -179,7 +179,13 @@ public class TestStressRSetCoarsening { // sizeOf(Object[N]) ~= (N+4)*refSize // ==> // N = regionSize / K / refSize - 4; - N = (int) ((regionSize / K) / refSize) - 5; + int n = (int) ((regionSize / K) / refSize) - 5; // best guess + long objSize = WB.getObjectSize(new Object[n]); + while (K*objSize > regionSize) { // adjust to avoid OOME + n = n - 1; + objSize = WB.getObjectSize(new Object[n]); + } + N = n; /* * -------------- @@ -202,8 +208,9 @@ public class TestStressRSetCoarsening { System.out.println("%% Objects"); System.out.println("%% N (array length) : " + N); System.out.println("%% K (objects in regions): " + K); + System.out.println("%% Object size : " + objSize + + " (sizeOf(new Object[" + N + "])"); System.out.println("%% Reference size : " + refSize); - System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); storage = new Object[regionCount * K][]; for (int i = 0; i < storage.length; i++) { From 8e63a10779d6c0d91479045785bdcb0dd3dfa577 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 13 Apr 2016 12:57:31 -0400 Subject: [PATCH 136/167] 8148772: VM crash in nsk/jvmti/RedefineClasses/StressRedefine: assert failed: Corrupted constant pool 8151546: nsk/jvmti/RedefineClasses/StressRedefine fails in hs nightly ConstantPool::resolve_constant_at_impl() isn't thread safe for MethodHandleInError and MethodTypeInError and Constant pool merging is not thread safe for source_file_name. Reviewed-by: sspitsyn, dcubed --- .../share/vm/classfile/javaClasses.inline.hpp | 23 ++++++------- hotspot/src/share/vm/oops/constantPool.cpp | 32 ++++++++--------- hotspot/src/share/vm/oops/constantPool.hpp | 34 ++++--------------- .../share/vm/prims/jvmtiRedefineClasses.cpp | 8 ++++- 4 files changed, 40 insertions(+), 57 deletions(-) diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp index 1aba5b8f8c1..180bc5b40a4 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp @@ -222,20 +222,17 @@ inline int Backtrace::get_line_number(const methodHandle& method, int bci) { return line_number; } -/* - * Returns the source file name of a given InstanceKlass and version - */ inline Symbol* Backtrace::get_source_file_name(InstanceKlass* holder, int version) { - // Find the specific ik version that contains this source_file_name_index - // via the previous versions list, but use the current version's - // constant pool to look it up. The previous version's index has been - // merged for the current constant pool. - InstanceKlass* ik = holder->get_klass_version(version); - // This version has been cleaned up. - if (ik == NULL) return NULL; - int source_file_name_index = ik->source_file_name_index(); - return (source_file_name_index == 0) ? - (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index); + // RedefineClasses() currently permits redefine operations to + // happen in parallel using a "last one wins" philosophy. That + // spec laxness allows the constant pool entry associated with + // the source_file_name_index for any older constant pool version + // to be unstable so we shouldn't try to use it. + if (holder->constants()->version() != version) { + return NULL; + } else { + return holder->source_file_name(); + } } #endif // SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 996f5a50eef..708c2f77d86 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -395,7 +395,7 @@ int ConstantPool::impl_name_and_type_ref_index_at(int which, bool uncached) { int i = which; if (!uncached && cache() != NULL) { if (ConstantPool::is_invokedynamic_index(which)) { - // Invokedynamic index is index into resolved_references + // Invokedynamic index is index into the constant pool cache int pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index); assert(tag_at(pool_index).is_name_and_type(), ""); @@ -965,8 +965,8 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodType: { - int k1 = method_type_index_at_error_ok(index1); - int k2 = cp2->method_type_index_at_error_ok(index2); + int k1 = method_type_index_at(index1); + int k2 = cp2->method_type_index_at(index2); bool match = compare_entry_to(k1, cp2, k2, CHECK_false); if (match) { return true; @@ -975,11 +975,11 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodHandle: { - int k1 = method_handle_ref_kind_at_error_ok(index1); - int k2 = cp2->method_handle_ref_kind_at_error_ok(index2); + int k1 = method_handle_ref_kind_at(index1); + int k2 = cp2->method_handle_ref_kind_at(index2); if (k1 == k2) { - int i1 = method_handle_index_at_error_ok(index1); - int i2 = cp2->method_handle_index_at_error_ok(index2); + int i1 = method_handle_index_at(index1); + int i2 = cp2->method_handle_index_at(index2); bool match = compare_entry_to(i1, cp2, i2, CHECK_false); if (match) { return true; @@ -1311,15 +1311,15 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { - jint k = from_cp->method_type_index_at_error_ok(from_i); + jint k = from_cp->method_type_index_at(from_i); to_cp->method_type_index_at_put(to_i, k); } break; case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { - int k1 = from_cp->method_handle_ref_kind_at_error_ok(from_i); - int k2 = from_cp->method_handle_index_at_error_ok(from_i); + int k1 = from_cp->method_handle_ref_kind_at(from_i); + int k2 = from_cp->method_handle_index_at(from_i); to_cp->method_handle_index_at_put(to_i, k1, k2); } break; @@ -1755,8 +1755,8 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { *bytes = JVM_CONSTANT_MethodHandle; - int kind = method_handle_ref_kind_at_error_ok(idx); - idx1 = method_handle_index_at_error_ok(idx); + int kind = method_handle_ref_kind_at(idx); + idx1 = method_handle_index_at(idx); *(bytes+1) = (unsigned char) kind; Bytes::put_Java_u2((address) (bytes+2), idx1); DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1)); @@ -1765,7 +1765,7 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { *bytes = JVM_CONSTANT_MethodType; - idx1 = method_type_index_at_error_ok(idx); + idx1 = method_type_index_at(idx); Bytes::put_Java_u2((address) (bytes+1), idx1); DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1)); break; @@ -1953,12 +1953,12 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) { break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodHandleInError : - st->print("ref_kind=%d", method_handle_ref_kind_at_error_ok(index)); - st->print(" ref_index=%d", method_handle_index_at_error_ok(index)); + st->print("ref_kind=%d", method_handle_ref_kind_at(index)); + st->print(" ref_index=%d", method_handle_index_at(index)); break; case JVM_CONSTANT_MethodType : case JVM_CONSTANT_MethodTypeInError : - st->print("signature_index=%d", method_type_index_at_error_ok(index)); + st->print("signature_index=%d", method_type_index_at(index)); break; case JVM_CONSTANT_InvokeDynamic : { diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 9ed795cb303..75bca62917b 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -460,40 +460,20 @@ class ConstantPool : public Metadata { return *int_at_addr(which); } - private: - int method_handle_ref_kind_at(int which, bool error_ok) { + int method_handle_ref_kind_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits } - int method_handle_index_at(int which, bool error_ok) { + int method_handle_index_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits } - int method_type_index_at(int which, bool error_ok) { - assert(tag_at(which).is_method_type() || - (error_ok && tag_at(which).is_method_type_in_error()), "Corrupted constant pool"); - return *int_at_addr(which); - } - public: - int method_handle_ref_kind_at(int which) { - return method_handle_ref_kind_at(which, false); - } - int method_handle_ref_kind_at_error_ok(int which) { - return method_handle_ref_kind_at(which, true); - } - int method_handle_index_at(int which) { - return method_handle_index_at(which, false); - } - int method_handle_index_at_error_ok(int which) { - return method_handle_index_at(which, true); - } int method_type_index_at(int which) { - return method_type_index_at(which, false); - } - int method_type_index_at_error_ok(int which) { - return method_type_index_at(which, true); + assert(tag_at(which).is_method_type() || + tag_at(which).is_method_type_in_error(), "Corrupted constant pool"); + return *int_at_addr(which); } // Derived queries: diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 3410d9566c9..c6737e73617 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1443,8 +1443,9 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } - // Update the version number of the constant pool + // Update the version number of the constant pools (may keep scratch_cp) merge_cp->increment_and_save_version(old_cp->version()); + scratch_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; @@ -3911,6 +3912,11 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, method->set_constants(scratch_class->constants()); } + // NOTE: this doesn't work because you can redefine the same class in two + // threads, each getting their own constant pool data appended to the + // original constant pool. In order for the new methods to work when they + // become old methods, they need to keep their updated copy of the constant pool. + { // walk all previous versions of the klass InstanceKlass *ik = (InstanceKlass *)the_class(); From f474e970ba7fef84ed16ed7d5215ff940fff71b8 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Wed, 13 Apr 2016 15:53:46 -0500 Subject: [PATCH 137/167] 8153039: Command line processing should use mtCommand or mtArguments rather than mtInternal for NMT Added mtArguments and replaced argument related usages of mtInternal with the new flag. Reviewed-by: coleenp, gtriantafill --- hotspot/src/share/vm/memory/allocation.hpp | 5 +- hotspot/src/share/vm/runtime/arguments.cpp | 56 +++++++++---------- hotspot/src/share/vm/runtime/arguments.hpp | 16 +++--- .../runtime/commandLineFlagConstraintList.cpp | 2 +- .../runtime/commandLineFlagConstraintList.hpp | 2 +- .../vm/runtime/commandLineFlagRangeList.cpp | 2 +- .../vm/runtime/commandLineFlagRangeList.hpp | 2 +- hotspot/src/share/vm/runtime/globals.cpp | 4 +- hotspot/src/share/vm/services/nmtCommon.cpp | 1 + 9 files changed, 46 insertions(+), 44 deletions(-) diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 2705c6d8994..ec0e53977d6 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -143,8 +143,9 @@ enum MemoryType { mtTest = 0x0D, // Test type for verifying NMT mtTracing = 0x0E, // memory used for Tracing mtLogging = 0x0F, // memory for logging - mtNone = 0x10, // undefined - mt_number_of_types = 0x11 // number of memory types (mtDontTrack + mtArguments = 0x10, // memory for argument processing + mtNone = 0x11, // undefined + mt_number_of_types = 0x12 // number of memory types (mtDontTrack // is not included as validate type) }; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d85c6a9fc3e..0ffe91cfb7e 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -698,7 +698,7 @@ char* ArgumentBootClassPath::combined_path() { assert(total_len > 0, "empty sysclasspath not allowed"); // Copy the _items to a single string. - char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal); + char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments); char* cp_tmp = cp; for (i = 0; i < _bcp_nitems; ++i) { if (_items[i] != NULL) { @@ -719,7 +719,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe assert(str != NULL, "just checking"); if (path == NULL) { size_t len = strlen(str) + 1; - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); memcpy(cp, str, len); // copy the trailing null } else { const char separator = *os::path_separator(); @@ -728,7 +728,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe size_t len = old_len + str_len + 2; if (prepend) { - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); char* cp_tmp = cp; memcpy(cp_tmp, str, str_len); cp_tmp += str_len; @@ -736,7 +736,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null FREE_C_HEAP_ARRAY(char, path); } else { - cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtInternal); + cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments); char* cp_tmp = cp + old_len; *cp_tmp = separator; memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null @@ -758,7 +758,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) /* Scan the directory for jars/zips, appending them to path. */ struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; const char* ext = name + strlen(name) - 4; @@ -766,7 +766,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) (os::file_name_strcmp(ext, ".jar") == 0 || os::file_name_strcmp(ext, ".zip") == 0); if (isJarOrZip) { - char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal); + char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments); sprintf(jarpath, "%s%s%s", directory, dir_sep, name); path = add_to_path(path, jarpath, false); FREE_C_HEAP_ARRAY(char, jarpath); @@ -943,7 +943,7 @@ static bool append_to_string_flag(const char* name, const char* new_value, Flag: } else if (new_len == 0) { value = old_value; } else { - char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal); + char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtArguments); // each new setting adds another LINE to the switch: sprintf(buf, "%s\n%s", old_value, new_value); value = buf; @@ -1134,9 +1134,9 @@ void Arguments::add_string(char*** bldarray, int* count, const char* arg) { // expand the array and add arg to the last element if (*bldarray == NULL) { - *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtInternal); + *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtArguments); } else { - *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal); + *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtArguments); } (*bldarray)[*count] = os::strdup_check_oom(arg); *count = new_count; @@ -1400,7 +1400,7 @@ bool Arguments::add_property(const char* prop) { // property have a value, thus extract it and save to the // allocated string size_t key_len = eq - prop; - char* tmp_key = AllocateHeap(key_len + 1, mtInternal); + char* tmp_key = AllocateHeap(key_len + 1, mtArguments); strncpy(tmp_key, prop, key_len); tmp_key[key_len] = '\0'; @@ -1422,7 +1422,7 @@ bool Arguments::add_property(const char* prop) { } else { if (strcmp(key, "sun.java.command") == 0) { char *old_java_command = _java_command; - _java_command = os::strdup_check_oom(value, mtInternal); + _java_command = os::strdup_check_oom(value, mtArguments); if (old_java_command != NULL) { os::free(old_java_command); } @@ -1430,7 +1430,7 @@ bool Arguments::add_property(const char* prop) { const char* old_java_vendor_url_bug = _java_vendor_url_bug; // save it in _java_vendor_url_bug, so JVM fatal error handler can access // its value without going through the property list or making a Java call. - _java_vendor_url_bug = os::strdup_check_oom(value, mtInternal); + _java_vendor_url_bug = os::strdup_check_oom(value, mtArguments); if (old_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) { assert(old_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL"); os::free((void *)old_java_vendor_url_bug); @@ -1458,7 +1458,7 @@ bool Arguments::append_to_addmods_property(const char* module_name) { if (old_value != NULL) { buf_len += strlen(old_value) + 1; } - char* new_value = AllocateHeap(buf_len, mtInternal); + char* new_value = AllocateHeap(buf_len, mtArguments); if (new_value == NULL) { return false; } @@ -2852,13 +2852,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if (tail != NULL) { const char* pos = strchr(tail, ':'); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { size_t len2 = strlen(pos+1) + 1; // options start after ':'. Final zero must be copied. - options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2); + options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtArguments), pos+1, len2); } #if !INCLUDE_JVMTI if (strcmp(name, "jdwp") == 0) { @@ -2875,12 +2875,12 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if(tail != NULL) { const char* pos = strchr(tail, '='); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { - options = os::strdup_check_oom(pos + 1, mtInternal); + options = os::strdup_check_oom(pos + 1, mtArguments); } #if !INCLUDE_JVMTI if (valid_jdwp_agent(name, is_absolute_path)) { @@ -2899,7 +2899,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_ERR; #else if (tail != NULL) { - char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail); + char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail); add_init_agent("instrument", options, false); // java agents need module java.instrument. Also -addmods ALL-SYSTEM because // the java agent is in the unmamed module of the application class loader @@ -3201,7 +3201,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, size_t len = strlen(patch_dirs[x]); if (len != 0) { // Ignore empty strings. len += 11; // file_sep + "java.base" + null terminator. - char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal); + char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments); jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep); // See if Xpatch module path exists. @@ -3507,7 +3507,7 @@ void Arguments::fix_appclasspath() { src ++; } - char* copy = os::strdup_check_oom(src, mtInternal); + char* copy = os::strdup_check_oom(src, mtArguments); // trim all trailing empty paths for (char* tail = copy + strlen(copy) - 1; tail >= copy && *tail == separator; tail--) { @@ -3531,7 +3531,7 @@ static bool has_jar_files(const char* directory) { if (dir == NULL) return false; struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); bool hasJarFile = false; while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; @@ -3557,7 +3557,7 @@ static int check_non_empty_dirs(const char* path) { } path = end; } else { - char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal); + char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtArguments); memcpy(dirpath, path, tmp_end - path); dirpath[tmp_end - path] = '\0'; if (has_jar_files(dirpath)) { @@ -3729,7 +3729,7 @@ class ScopedVMInitArgs : public StackObj { jint set_args(GrowableArray* options) { _is_set = true; JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL( - JavaVMOption, options->length(), mtInternal); + JavaVMOption, options->length(), mtArguments); if (options_arr == NULL) { return JNI_ENOMEM; } @@ -3784,7 +3784,7 @@ class ScopedVMInitArgs : public StackObj { assert(vm_options_file_pos != -1, "vm_options_file_pos should be set"); int length = args->nOptions + args_to_insert->nOptions - 1; - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(length, true); // Construct new option array for (int i = 0; i < args->nOptions; i++) { if (i == vm_options_file_pos) { @@ -3861,7 +3861,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v // '+ 1' for NULL termination even with max bytes size_t bytes_alloc = stbuf.st_size + 1; - char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtInternal); + char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtArguments); if (NULL == buf) { jio_fprintf(defaultStream::error_stream(), "Could not allocate read buffer for options file parse\n"); @@ -3898,7 +3898,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v } jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args) { - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(2, true); // Construct option array + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(2, true); // Construct option array // some pointers to help with parsing char *buffer_end = buffer + buf_len; @@ -4002,13 +4002,13 @@ static char* get_shared_archive_path() { size_t jvm_path_len = strlen(jvm_path); size_t file_sep_len = strlen(os::file_separator()); const size_t len = jvm_path_len + file_sep_len + 20; - shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal); + shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); if (shared_archive_path != NULL) { jio_snprintf(shared_archive_path, len, "%s%sclasses.jsa", jvm_path, os::file_separator()); } } else { - shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtInternal); + shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); } return shared_archive_path; } diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 328a9d71872..4df23a5b485 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -47,7 +47,7 @@ class ArgumentBootClassPath; // PathString is used as the underlying value container for a // SystemProperty and for the string that represents the system // boot class path, Arguments::_system_boot_class_path. -class PathString : public CHeapObj { +class PathString : public CHeapObj { protected: char* _value; public: @@ -57,7 +57,7 @@ class PathString : public CHeapObj { if (_value != NULL) { FreeHeap(_value); } - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); assert(_value != NULL, "Unable to allocate space for new path value"); if (_value != NULL) { strcpy(_value, value); @@ -76,7 +76,7 @@ class PathString : public CHeapObj { if (_value != NULL) { len += strlen(_value); } - sp = AllocateHeap(len+2, mtInternal); + sp = AllocateHeap(len+2, mtArguments); assert(sp != NULL, "Unable to allocate space for new append path value"); if (sp != NULL) { if (_value != NULL) { @@ -97,7 +97,7 @@ class PathString : public CHeapObj { if (value == NULL) { _value = NULL; } else { - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); strcpy(_value, value); } } @@ -143,7 +143,7 @@ class SystemProperty : public PathString { if (key == NULL) { _key = NULL; } else { - _key = AllocateHeap(strlen(key)+1, mtInternal); + _key = AllocateHeap(strlen(key)+1, mtArguments); strcpy(_key, key); } _next = NULL; @@ -154,7 +154,7 @@ class SystemProperty : public PathString { // For use by -agentlib, -agentpath and -Xrun -class AgentLibrary : public CHeapObj { +class AgentLibrary : public CHeapObj { friend class AgentLibraryList; public: // Is this library valid or not. Don't rely on os_lib == NULL as statically @@ -189,12 +189,12 @@ public: // Constructor AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) { - _name = AllocateHeap(strlen(name)+1, mtInternal); + _name = AllocateHeap(strlen(name)+1, mtArguments); strcpy(_name, name); if (options == NULL) { _options = NULL; } else { - _options = AllocateHeap(strlen(options)+1, mtInternal); + _options = AllocateHeap(strlen(options)+1, mtArguments); strcpy(_options, options); } _is_absolute_path = is_absolute_path; diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp index 2e0139c39e5..c79a48c9700 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp @@ -226,7 +226,7 @@ CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_valida // Check the ranges of all flags that have them or print them out and exit if requested void CommandLineFlagConstraintList::init(void) { - _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); + _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp index 5affa729c34..e7df3e9d551 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp @@ -48,7 +48,7 @@ typedef Flag::Error (*CommandLineFlagConstraintFunc_uint64_t)(uint64_t value, bo typedef Flag::Error (*CommandLineFlagConstraintFunc_size_t)(size_t value, bool verbose); typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(double value, bool verbose); -class CommandLineFlagConstraint : public CHeapObj { +class CommandLineFlagConstraint : public CHeapObj { public: // During VM initialization, constraint validation will be done order of ConstraintType. enum ConstraintType { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp index 2af4847d67a..89acace33f7 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp @@ -292,7 +292,7 @@ GrowableArray* CommandLineFlagRangeList::_ranges = NULL; // Check the ranges of all flags that have them void CommandLineFlagRangeList::init(void) { - _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_RANGES_SIZE, true); + _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_RANGES_SIZE, true); emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, EMIT_RANGE_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp index 4b2c1ea7caa..bc299d4f2a5 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp @@ -44,7 +44,7 @@ public: static void print(bool verbose, const char* msg, ...); }; -class CommandLineFlagRange : public CHeapObj { +class CommandLineFlagRange : public CHeapObj { private: const char* _name; public: diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 7e752adac01..ef98dd77f94 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -1292,7 +1292,7 @@ void CommandLineFlags::printSetFlags(outputStream* out) { const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } @@ -1326,7 +1326,7 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } diff --git a/hotspot/src/share/vm/services/nmtCommon.cpp b/hotspot/src/share/vm/services/nmtCommon.cpp index cffce8c7099..8633bbe301e 100644 --- a/hotspot/src/share/vm/services/nmtCommon.cpp +++ b/hotspot/src/share/vm/services/nmtCommon.cpp @@ -41,6 +41,7 @@ const char* NMTUtil::_memory_type_names[] = { "Test", "Tracing", "Logging", + "Arguments", "Unknown" }; From 1326ae31c82f077dedde31d2a0ee8579a8e3c62e Mon Sep 17 00:00:00 2001 From: Derek White Date: Wed, 13 Apr 2016 17:00:54 -0400 Subject: [PATCH 138/167] 8152905: hs_err file is missing gc threads List the GC threads in the hs_err file in the "Other Threads" section Reviewed-by: dcubed, coleenp --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 5 +- .../src/share/vm/gc/g1/g1ConcurrentMark.cpp | 4 + .../src/share/vm/gc/g1/g1ConcurrentMark.hpp | 1 + hotspot/src/share/vm/runtime/thread.cpp | 81 +++++++++++-------- hotspot/src/share/vm/runtime/thread.hpp | 2 + 5 files changed, 56 insertions(+), 37 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 0f33720d7ca..75342af7fd5 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2742,7 +2742,7 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { _cmThread->print_on(st); st->cr(); _cm->print_worker_threads_on(st); - _cg1r->print_worker_threads_on(st); + _cg1r->print_worker_threads_on(st); // also prints the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::print_worker_threads_on(st); } @@ -2751,7 +2751,8 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { workers()->threads_do(tc); tc->do_thread(_cmThread); - _cg1r->threads_do(tc); + _cm->threads_do(tc); + _cg1r->threads_do(tc); // also iterates over the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::threads_do(tc); } diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 526387c018e..b36583e9822 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -2112,6 +2112,10 @@ void G1ConcurrentMark::print_worker_threads_on(outputStream* st) const { _parallel_workers->print_worker_threads_on(st); } +void G1ConcurrentMark::threads_do(ThreadClosure* tc) const { + _parallel_workers->threads_do(tc); +} + void G1ConcurrentMark::print_on_error(outputStream* st) const { st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, p2i(_prevMarkBitMap), p2i(_nextMarkBitMap)); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 36fb602de82..3b077d97a8a 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -621,6 +621,7 @@ public: void print_summary_info(); void print_worker_threads_on(outputStream* st) const; + void threads_do(ThreadClosure* tc) const; void print_on_error(outputStream* st) const; diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 1e56369bc3e..0a9ce34352d 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -818,13 +818,17 @@ void Thread::print_on(outputStream* st) const { // Thread::print_on_error() is called by fatal error handler. Don't use // any lock or allocate memory. void Thread::print_on_error(outputStream* st, char* buf, int buflen) const { - if (is_VM_thread()) st->print("VMThread"); - else if (is_Compiler_thread()) st->print("CompilerThread"); - else if (is_Java_thread()) st->print("JavaThread"); - else if (is_GC_task_thread()) st->print("GCTaskThread"); - else if (is_Watcher_thread()) st->print("WatcherThread"); - else if (is_ConcurrentGC_thread()) st->print("ConcurrentGCThread"); - else st->print("Thread"); + assert(!(is_Compiler_thread() || is_Java_thread()), "Can't call name() here if it allocates"); + + if (is_VM_thread()) { st->print("VMThread"); } + else if (is_GC_task_thread()) { st->print("GCTaskThread"); } + else if (is_Watcher_thread()) { st->print("WatcherThread"); } + else if (is_ConcurrentGC_thread()) { st->print("ConcurrentGCThread"); } + else { st->print("Thread"); } + + if (is_Named_thread()) { + st->print(" \"%s\"", name()); + } st->print(" [stack: " PTR_FORMAT "," PTR_FORMAT "]", p2i(stack_end()), p2i(stack_base())); @@ -4498,6 +4502,36 @@ void Threads::print_on(outputStream* st, bool print_stacks, st->flush(); } +void Threads::print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) { + if (this_thread != NULL) { + bool is_current = (current == this_thread); + *found_current = *found_current || is_current; + st->print("%s", is_current ? "=>" : " "); + + st->print(PTR_FORMAT, p2i(this_thread)); + st->print(" "); + this_thread->print_on_error(st, buf, buflen); + st->cr(); + } +} + +class PrintOnErrorClosure : public ThreadClosure { + outputStream* _st; + Thread* _current; + char* _buf; + int _buflen; + bool* _found_current; + public: + PrintOnErrorClosure(outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) : + _st(st), _current(current), _buf(buf), _buflen(buflen), _found_current(found_current) {} + + virtual void do_thread(Thread* thread) { + Threads::print_on_error(thread, _st, _current, _buf, _buflen, _found_current); + } +}; + // Threads::print_on_error() is called by fatal error handler. It's possible // that VM is not at safepoint and/or current thread is inside signal handler. // Don't print stack trace, as the stack may not be walkable. Don't allocate @@ -4507,40 +4541,17 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, bool found_current = false; st->print_cr("Java Threads: ( => current thread )"); ALL_JAVA_THREADS(thread) { - bool is_current = (current == thread); - found_current = found_current || is_current; - - st->print("%s", is_current ? "=>" : " "); - - st->print(PTR_FORMAT, p2i(thread)); - st->print(" "); - thread->print_on_error(st, buf, buflen); - st->cr(); + print_on_error(thread, st, current, buf, buflen, &found_current); } st->cr(); st->print_cr("Other Threads:"); - if (VMThread::vm_thread()) { - bool is_current = (current == VMThread::vm_thread()); - found_current = found_current || is_current; - st->print("%s", current == VMThread::vm_thread() ? "=>" : " "); + print_on_error(VMThread::vm_thread(), st, current, buf, buflen, &found_current); + print_on_error(WatcherThread::watcher_thread(), st, current, buf, buflen, &found_current); - st->print(PTR_FORMAT, p2i(VMThread::vm_thread())); - st->print(" "); - VMThread::vm_thread()->print_on_error(st, buf, buflen); - st->cr(); - } - WatcherThread* wt = WatcherThread::watcher_thread(); - if (wt != NULL) { - bool is_current = (current == wt); - found_current = found_current || is_current; - st->print("%s", is_current ? "=>" : " "); + PrintOnErrorClosure print_closure(st, current, buf, buflen, &found_current); + Universe::heap()->gc_threads_do(&print_closure); - st->print(PTR_FORMAT, p2i(wt)); - st->print(" "); - wt->print_on_error(st, buf, buflen); - st->cr(); - } if (!found_current) { st->cr(); st->print("=>" PTR_FORMAT " (exited) ", p2i(current)); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 0d54deec3ef..f5d7ac5b74d 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -2156,6 +2156,8 @@ class Threads: AllStatic { print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */); } static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen); + static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current); static void print_threads_compiling(outputStream* st, char* buf, int buflen); // Get Java threads that are waiting to enter a monitor. If doLock From a9e64aa5727667d690bc051047117b760bbe9d54 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 14 Apr 2016 08:30:15 +0200 Subject: [PATCH 139/167] 8154051: Change G1YoungGenSizer to use UL log_warning instead of warning Reviewed-by: brutisso, mgerdin --- hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp index cf7866770d5..e049f4da639 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp @@ -25,12 +25,13 @@ #include "precompiled.hpp" #include "gc/g1/g1YoungGenSizer.hpp" #include "gc/g1/heapRegion.hpp" +#include "logging/log.hpp" G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true), _min_desired_young_length(0), _max_desired_young_length(0) { if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { - warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); + log_warning(gc, ergo)("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { _sizer_kind = SizerNewRatio; _adaptive_size = false; @@ -40,9 +41,9 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size( if (NewSize > MaxNewSize) { if (FLAG_IS_CMDLINE(MaxNewSize)) { - warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " - "A new max generation size of " SIZE_FORMAT "k will be used.", - NewSize/K, MaxNewSize/K, NewSize/K); + log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " + "A new max generation size of " SIZE_FORMAT "k will be used.", + NewSize/K, MaxNewSize/K, NewSize/K); } MaxNewSize = NewSize; } From e79c2a2d8b8d7da1f677bc2164e114bfe2ecacc2 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 14 Apr 2016 08:30:37 +0200 Subject: [PATCH 140/167] 8153745: Avoid spawning G1ParPreserveCMReferentsTask when there is no work to be done Reviewed-by: brutisso, jmasa, tschatzl --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 25 ++++++++++++------- .../share/vm/gc/shared/referenceProcessor.cpp | 9 +++++++ .../share/vm/gc/shared/referenceProcessor.hpp | 3 +++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 75342af7fd5..3a775d5bca1 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4452,7 +4452,6 @@ void G1CollectedHeap::process_weak_jni_handles() { } void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { - double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4473,16 +4472,24 @@ void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_ // objects discovered by the STW ref processor in case one of these // referents points to another object which is also referenced by an // object discovered by the STW ref processor. + double preserve_cm_referents_time = 0.0; - uint no_of_gc_workers = workers()->active_workers(); + // To avoid spawning task when there is no work to do, check that + // a concurrent cycle is active and that some references have been + // discovered. + if (concurrent_mark()->cmThread()->during_cycle() && + ref_processor_cm()->has_discovered_references()) { + double preserve_cm_referents_start = os::elapsedTime(); + uint no_of_gc_workers = workers()->active_workers(); + G1ParPreserveCMReferentsTask keep_cm_referents(this, + per_thread_states, + no_of_gc_workers, + _task_queues); + workers()->run_task(&keep_cm_referents); + preserve_cm_referents_time = os::elapsedTime() - preserve_cm_referents_start; + } - G1ParPreserveCMReferentsTask keep_cm_referents(this, - per_thread_states, - no_of_gc_workers, - _task_queues); - workers()->run_task(&keep_cm_referents); - - g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms(preserve_cm_referents_time * 1000.0); } // Weak Reference processing during an evacuation pause (part 1). diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 22ed7b25d81..2200e7620a4 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -1090,6 +1090,15 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { return true; } +bool ReferenceProcessor::has_discovered_references() { + for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + if (!_discovered_refs[i].is_empty()) { + return true; + } + } + return false; +} + // Preclean the discovered references by removing those // whose referents are alive, and by marking from those that // are not active. These lists can be handled here diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp index 125f55bde72..c5d0f5f8321 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp @@ -412,6 +412,9 @@ class ReferenceProcessor : public CHeapObj { // Discover a Reference object, using appropriate discovery criteria bool discover_reference(oop obj, ReferenceType rt); + // Has discovered references that need handling + bool has_discovered_references(); + // Process references found during GC (called by the garbage collector) ReferenceProcessorStats process_discovered_references(BoolObjectClosure* is_alive, From 3bb96580fbb3fe61fb3b43ab7fb132681462a039 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 14 Apr 2016 11:17:34 +0200 Subject: [PATCH 141/167] 8073321: assert(q > prev_q) failed: we should be moving forward through memory Reviewed-by: jmasa, mgerdin --- .../vm/gc/cms/compactibleFreeListSpace.hpp | 2 + hotspot/src/share/vm/gc/shared/space.cpp | 16 - hotspot/src/share/vm/gc/shared/space.hpp | 16 +- .../src/share/vm/gc/shared/space.inline.hpp | 347 ++++++++++-------- 4 files changed, 194 insertions(+), 187 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index 92a2764afd0..d8f8e89b684 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -82,6 +82,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { template friend void CompactibleSpace::scan_and_compact(SpaceType* space); template + friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); + template friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp); // "Size" of chunks of work (executed during parallel remark phases diff --git a/hotspot/src/share/vm/gc/shared/space.cpp b/hotspot/src/share/vm/gc/shared/space.cpp index 5a020b1f74f..c207dcd74b5 100644 --- a/hotspot/src/share/vm/gc/shared/space.cpp +++ b/hotspot/src/share/vm/gc/shared/space.cpp @@ -411,22 +411,6 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, return compact_top; } - -bool CompactibleSpace::insert_deadspace(size_t& allowed_deadspace_words, - HeapWord* q, size_t deadlength) { - if (allowed_deadspace_words >= deadlength) { - allowed_deadspace_words -= deadlength; - CollectedHeap::fill_with_object(q, deadlength); - oop(q)->set_mark(oop(q)->mark()->set_marked()); - assert((int) deadlength == oop(q)->size(), "bad filler object size"); - // Recall that we required "q == compaction_top". - return true; - } else { - allowed_deadspace_words = 0; - return false; - } -} - void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { scan_and_forward(this, cp); } diff --git a/hotspot/src/share/vm/gc/shared/space.hpp b/hotspot/src/share/vm/gc/shared/space.hpp index 465dca90eb6..05eb3e1f27c 100644 --- a/hotspot/src/share/vm/gc/shared/space.hpp +++ b/hotspot/src/share/vm/gc/shared/space.hpp @@ -362,6 +362,12 @@ private: inline size_t obj_size(const HeapWord* addr) const; + template + static inline void verify_up_to_first_dead(SpaceType* space) NOT_DEBUG_RETURN; + + template + static inline void clear_empty_region(SpaceType* space); + public: CompactibleSpace() : _compaction_top(NULL), _next_compaction_space(NULL) {} @@ -455,16 +461,6 @@ protected: return end(); } - // Requires "allowed_deadspace_words > 0", that "q" is the start of a - // free block of the given "word_len", and that "q", were it an object, - // would not move if forwarded. If the size allows, fill the free - // block with an object, to prevent excessive compaction. Returns "true" - // iff the free region was made deadspace, and modifies - // "allowed_deadspace_words" to reflect the number of available deadspace - // words remaining after this operation. - bool insert_deadspace(size_t& allowed_deadspace_words, HeapWord* q, - size_t word_len); - // Below are template functions for scan_and_* algorithms (avoiding virtual calls). // The space argument should be a subclass of CompactibleSpace, implementing // scan_limit(), scanned_block_is_obj(), and scanned_block_size(), diff --git a/hotspot/src/share/vm/gc/shared/space.inline.hpp b/hotspot/src/share/vm/gc/shared/space.inline.hpp index 24cfb6213e8..3943a6da5dc 100644 --- a/hotspot/src/share/vm/gc/shared/space.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/space.inline.hpp @@ -31,6 +31,7 @@ #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "memory/universe.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" @@ -75,11 +76,61 @@ size_t CompactibleSpace::obj_size(const HeapWord* addr) const { return oop(addr)->size(); } +class DeadSpacer : StackObj { + size_t _allowed_deadspace_words; + bool _active; + CompactibleSpace* _space; + +public: + DeadSpacer(CompactibleSpace* space) : _space(space), _allowed_deadspace_words(0) { + size_t ratio = _space->allowed_dead_ratio(); + _active = ratio > 0; + + if (_active) { + assert(!UseG1GC, "G1 should not be using dead space"); + + // We allow some amount of garbage towards the bottom of the space, so + // we don't start compacting before there is a significant gain to be made. + // Occasionally, we want to ensure a full compaction, which is determined + // by the MarkSweepAlwaysCompactCount parameter. + if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { + _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; + } else { + _active = false; + } + } + } + + + bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { + if (!_active) { + return false; + } + + size_t dead_length = pointer_delta(dead_end, dead_start); + if (_allowed_deadspace_words >= dead_length) { + _allowed_deadspace_words -= dead_length; + CollectedHeap::fill_with_object(dead_start, dead_length); + oop obj = oop(dead_start); + obj->set_mark(obj->mark()->set_marked()); + + assert(dead_length == (size_t)obj->size(), "bad filler object size"); + log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", + p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); + + return true; + } else { + _active = false; + return false; + } + } + +}; + template inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { // Compute the new addresses for the live objects and store it in the mark // Used by universe::mark_sweep_phase2() - HeapWord* compact_top; // This is where we are currently compacting to. // We're sure to be here before any objects are compacted into this // space, so this is a good time to initialize this: @@ -90,89 +141,73 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c assert(cp->threshold == NULL, "just checking"); assert(cp->gen->first_compaction_space() == space, "just checking"); cp->space = cp->gen->first_compaction_space(); - compact_top = cp->space->bottom(); - cp->space->set_compaction_top(compact_top); cp->threshold = cp->space->initialize_threshold(); - } else { - compact_top = cp->space->compaction_top(); + cp->space->set_compaction_top(cp->space->bottom()); } - // We allow some amount of garbage towards the bottom of the space, so - // we don't start compacting before there is a significant gain to be made. - // Occasionally, we want to ensure a full compaction, which is determined - // by the MarkSweepAlwaysCompactCount parameter. - uint invocations = MarkSweep::total_invocations(); - bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); + HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to. - size_t allowed_deadspace = 0; - if (skip_dead) { - const size_t ratio = space->allowed_dead_ratio(); - allowed_deadspace = (space->capacity() * ratio / 100) / HeapWordSize; - } + DeadSpacer dead_spacer(space); - HeapWord* q = space->bottom(); - HeapWord* t = space->scan_limit(); - - HeapWord* end_of_live= q; // One byte beyond the last byte of the last - // live object. - HeapWord* first_dead = space->end(); // The first dead object. + HeapWord* end_of_live = space->bottom(); // One byte beyond the last byte of the last live object. + HeapWord* first_dead = NULL; // The first dead object. const intx interval = PrefetchScanIntervalInBytes; - while (q < t) { - assert(!space->scanned_block_is_obj(q) || - oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || - oop(q)->mark()->has_bias_pattern(), + HeapWord* cur_obj = space->bottom(); + HeapWord* scan_limit = space->scan_limit(); + + while (cur_obj < scan_limit) { + assert(!space->scanned_block_is_obj(cur_obj) || + oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() || + oop(cur_obj)->mark()->has_bias_pattern(), "these are the only valid states during a mark sweep"); - if (space->scanned_block_is_obj(q) && oop(q)->is_gc_marked()) { - // prefetch beyond q - Prefetch::write(q, interval); - size_t size = space->scanned_block_size(q); - compact_top = cp->space->forward(oop(q), size, cp, compact_top); - q += size; - end_of_live = q; + if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) { + // prefetch beyond cur_obj + Prefetch::write(cur_obj, interval); + size_t size = space->scanned_block_size(cur_obj); + compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); + cur_obj += size; + end_of_live = cur_obj; } else { // run over all the contiguous dead objects - HeapWord* end = q; + HeapWord* end = cur_obj; do { // prefetch beyond end Prefetch::write(end, interval); end += space->scanned_block_size(end); - } while (end < t && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); + } while (end < scan_limit && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); // see if we might want to pretend this object is alive so that // we don't have to compact quite as often. - if (allowed_deadspace > 0 && q == compact_top) { - size_t sz = pointer_delta(end, q); - if (space->insert_deadspace(allowed_deadspace, q, sz)) { - compact_top = cp->space->forward(oop(q), sz, cp, compact_top); - q = end; - end_of_live = end; - continue; + if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { + oop obj = oop(cur_obj); + compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); + end_of_live = end; + } else { + // otherwise, it really is a free region. + + // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. + *(HeapWord**)cur_obj = end; + + // see if this is the first dead region. + if (first_dead == NULL) { + first_dead = cur_obj; } } - // otherwise, it really is a free region. - - // q is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. - (*(HeapWord**)q) = end; - - // see if this is the first dead region. - if (q < first_dead) { - first_dead = q; - } - // move on to the next object - q = end; + cur_obj = end; } } - assert(q == t, "just checking"); + assert(cur_obj == scan_limit, "just checking"); space->_end_of_live = end_of_live; - if (end_of_live < first_dead) { - first_dead = end_of_live; + if (first_dead != NULL) { + space->_first_dead = first_dead; + } else { + space->_first_dead = end_of_live; } - space->_first_dead = first_dead; // save the compaction_top of the compaction space. cp->space->set_compaction_top(compact_top); @@ -183,127 +218,58 @@ inline void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space) { // adjust all the interior pointers to point at the new locations of objects // Used by MarkSweep::mark_sweep_phase3() - HeapWord* q = space->bottom(); - HeapWord* t = space->_end_of_live; // Established by "prepare_for_compaction". + HeapWord* cur_obj = space->bottom(); + HeapWord* const end_of_live = space->_end_of_live; // Established by "scan_and_forward". + HeapWord* const first_dead = space->_first_dead; // Established by "scan_and_forward". - assert(space->_first_dead <= space->_end_of_live, "Stands to reason, no?"); - - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - // we have a chunk of the space which hasn't moved and we've - // reinitialized the mark word during the previous pass, so we can't - // use is_gc_marked for the traversal. - HeapWord* end = space->_first_dead; - - while (q < end) { - // I originally tried to conjoin "block_start(q) == q" to the - // assertion below, but that doesn't work, because you can't - // accurately traverse previous objects to get to the current one - // after their pointers have been - // updated, until the actual compaction is done. dld, 4/00 - assert(space->block_is_obj(q), "should be at block boundaries, and should be looking at objs"); - - // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); - size = space->adjust_obj_size(size); - - q += size; - } - - if (space->_first_dead == t) { - q = t; - } else { - // The first dead object is no longer an object. At that memory address, - // there is a pointer to the first live object that the previous phase found. - q = *((HeapWord**)(space->_first_dead)); - } - } + assert(first_dead <= end_of_live, "Stands to reason, no?"); const intx interval = PrefetchScanIntervalInBytes; - debug_only(HeapWord* prev_q = NULL); - while (q < t) { - // prefetch beyond q - Prefetch::write(q, interval); - if (oop(q)->is_gc_marked()) { - // q is alive + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + Prefetch::write(cur_obj, interval); + if (cur_obj < first_dead || oop(cur_obj)->is_gc_marked()) { + // cur_obj is alive // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); + size_t size = MarkSweep::adjust_pointers(oop(cur_obj)); size = space->adjust_obj_size(size); - debug_only(prev_q = q); - q += size; + debug_only(prev_obj = cur_obj); + cur_obj += size; } else { - debug_only(prev_q = q); - // q is not a live object, instead it points at the next live object - q = *(HeapWord**)q; - assert(q > prev_q, "we should be moving forward through memory, q: " PTR_FORMAT ", prev_q: " PTR_FORMAT, p2i(q), p2i(prev_q)); + debug_only(prev_obj = cur_obj); + // cur_obj is not a live object, instead it points at the next live object + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory, cur_obj: " PTR_FORMAT ", prev_obj: " PTR_FORMAT, p2i(cur_obj), p2i(prev_obj)); } } - assert(q == t, "just checking"); + assert(cur_obj == end_of_live, "just checking"); } +#ifdef ASSERT template -inline void CompactibleSpace::scan_and_compact(SpaceType* space) { - // Copy all live objects to their new location - // Used by MarkSweep::mark_sweep_phase4() +inline void CompactibleSpace::verify_up_to_first_dead(SpaceType* space) { + HeapWord* cur_obj = space->bottom(); - HeapWord* q = space->bottom(); - HeapWord* const t = space->_end_of_live; - debug_only(HeapWord* prev_q = NULL); + if (cur_obj < space->_end_of_live && space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // we have a chunk of the space which hasn't moved and we've reinitialized + // the mark word during the previous pass, so we can't use is_gc_marked for + // the traversal. + HeapWord* prev_obj = NULL; - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - #ifdef ASSERT // Debug only - // we have a chunk of the space which hasn't moved and we've reinitialized - // the mark word during the previous pass, so we can't use is_gc_marked for - // the traversal. - HeapWord* const end = space->_first_dead; - - while (q < end) { - size_t size = space->obj_size(q); - assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); - prev_q = q; - q += size; - } - #endif - - if (space->_first_dead == t) { - q = t; - } else { - // $$$ Funky - q = (HeapWord*) oop(space->_first_dead)->mark()->decode_pointer(); - } - } - - const intx scan_interval = PrefetchScanIntervalInBytes; - const intx copy_interval = PrefetchCopyIntervalInBytes; - while (q < t) { - if (!oop(q)->is_gc_marked()) { - // mark is pointer to next marked oop - debug_only(prev_q = q); - q = (HeapWord*) oop(q)->mark()->decode_pointer(); - assert(q > prev_q, "we should be moving forward through memory"); - } else { - // prefetch beyond q - Prefetch::read(q, scan_interval); - - // size and destination - size_t size = space->obj_size(q); - HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); - - // prefetch beyond compaction_top - Prefetch::write(compaction_top, copy_interval); - - // copy object and reinit its mark - assert(q != compaction_top, "everything in this pass should be moving"); - Copy::aligned_conjoint_words(q, compaction_top, size); - oop(compaction_top)->init_mark(); - assert(oop(compaction_top)->klass() != NULL, "should have a class"); - - debug_only(prev_q = q); - q += size; - } + while (cur_obj < space->_first_dead) { + size_t size = space->obj_size(cur_obj); + assert(!oop(cur_obj)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); + prev_obj = cur_obj; + cur_obj += size; + } } +} +#endif +template +inline void CompactibleSpace::clear_empty_region(SpaceType* space) { // Let's remember if we were empty before we did the compaction. bool was_empty = space->used_region().is_empty(); // Reset space after compaction is complete @@ -320,6 +286,65 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { } } +template +inline void CompactibleSpace::scan_and_compact(SpaceType* space) { + // Copy all live objects to their new location + // Used by MarkSweep::mark_sweep_phase4() + + verify_up_to_first_dead(space); + + HeapWord* const end_of_live = space->_end_of_live; + + assert(space->_first_dead <= end_of_live, "Invariant. _first_dead: " PTR_FORMAT " <= end_of_live: " PTR_FORMAT, p2i(space->_first_dead), p2i(end_of_live)); + if (space->_first_dead == end_of_live && !oop(space->bottom())->is_gc_marked()) { + // Nothing to compact. The space is either empty or all live object should be left in place. + clear_empty_region(space); + return; + } + + const intx scan_interval = PrefetchScanIntervalInBytes; + const intx copy_interval = PrefetchCopyIntervalInBytes; + + assert(space->bottom() < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(space->bottom()), p2i(end_of_live)); + HeapWord* cur_obj = space->bottom(); + if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // All object before _first_dead can be skipped. They should not be moved. + // A pointer to the first live object is stored at the memory location for _first_dead. + cur_obj = *(HeapWord**)(space->_first_dead); + } + + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + if (!oop(cur_obj)->is_gc_marked()) { + debug_only(prev_obj = cur_obj); + // The first word of the dead object contains a pointer to the next live object or end of space. + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory"); + } else { + // prefetch beyond q + Prefetch::read(cur_obj, scan_interval); + + // size and destination + size_t size = space->obj_size(cur_obj); + HeapWord* compaction_top = (HeapWord*)oop(cur_obj)->forwardee(); + + // prefetch beyond compaction_top + Prefetch::write(compaction_top, copy_interval); + + // copy object and reinit its mark + assert(cur_obj != compaction_top, "everything in this pass should be moving"); + Copy::aligned_conjoint_words(cur_obj, compaction_top, size); + oop(compaction_top)->init_mark(); + assert(oop(compaction_top)->klass() != NULL, "should have a class"); + + debug_only(prev_obj = cur_obj); + cur_obj += size; + } + } + + clear_empty_region(space); +} + size_t ContiguousSpace::scanned_block_size(const HeapWord* addr) const { return oop(addr)->size(); } From e13ecd97b08dcb07ae1f8232a9fab2920379f815 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 14 Apr 2016 11:55:28 +0200 Subject: [PATCH 142/167] 8154064: JVMTI trace event crashes Reviewed-by: sla, stefank --- hotspot/src/share/vm/prims/jvmtiExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 20de3f979cb..edaea323658 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2260,7 +2260,7 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) { EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s", JvmtiTrace::safe_get_thread_name(thread), - object==NULL? "NULL" : java_lang_Class::as_Klass(object)->external_name())); + object==NULL? "NULL" : object->klass()->external_name())); JvmtiVMObjectAllocEventMark jem(thread, h()); JvmtiJavaThreadEventTransition jet(thread); From 8c6cc265f69f61c9a260520d8e1c591c76c27adc Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 14 Apr 2016 15:45:38 +0300 Subject: [PATCH 143/167] 8153222: [TESTBUG] Move tests in stress/gc to gc/stress Reviewed-by: dfazunen, jwilhelm --- hotspot/test/TEST.groups | 3 ++- hotspot/test/{stress/gc => gc/stress}/TestGCOld.java | 0 .../{stress/gc => gc/stress}/TestMultiThreadStressRSet.java | 0 .../{stress/gc => gc/stress}/TestStressIHOPMultiThread.java | 0 .../{stress/gc => gc/stress}/TestStressRSetCoarsening.java | 0 5 files changed, 2 insertions(+), 1 deletion(-) rename hotspot/test/{stress/gc => gc/stress}/TestGCOld.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestMultiThreadStressRSet.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestStressIHOPMultiThread.java (100%) rename hotspot/test/{stress/gc => gc/stress}/TestStressRSetCoarsening.java (100%) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 5705527c728..18dc949a024 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -338,6 +338,7 @@ hotspot_fast_gc_2 = \ sanity/ExecuteInternalVMTests.java \ gc/ \ -gc/g1/ \ + -gc/stress \ -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \ -gc/cms/TestMBeanCMS.java \ -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -346,7 +347,7 @@ hotspot_fast_gc_closed = \ sanity/ExecuteInternalVMTests.java hotspot_fast_gc_gcold = \ - stress/gc/TestGCOld.java + gc/stress/TestGCOld.java hotspot_fast_runtime = \ runtime/ \ diff --git a/hotspot/test/stress/gc/TestGCOld.java b/hotspot/test/gc/stress/TestGCOld.java similarity index 100% rename from hotspot/test/stress/gc/TestGCOld.java rename to hotspot/test/gc/stress/TestGCOld.java diff --git a/hotspot/test/stress/gc/TestMultiThreadStressRSet.java b/hotspot/test/gc/stress/TestMultiThreadStressRSet.java similarity index 100% rename from hotspot/test/stress/gc/TestMultiThreadStressRSet.java rename to hotspot/test/gc/stress/TestMultiThreadStressRSet.java diff --git a/hotspot/test/stress/gc/TestStressIHOPMultiThread.java b/hotspot/test/gc/stress/TestStressIHOPMultiThread.java similarity index 100% rename from hotspot/test/stress/gc/TestStressIHOPMultiThread.java rename to hotspot/test/gc/stress/TestStressIHOPMultiThread.java diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/gc/stress/TestStressRSetCoarsening.java similarity index 100% rename from hotspot/test/stress/gc/TestStressRSetCoarsening.java rename to hotspot/test/gc/stress/TestStressRSetCoarsening.java From acd52761a2d4edc68f4961a49dbdde3b1a2c4415 Mon Sep 17 00:00:00 2001 From: Rachel Protacio Date: Thu, 14 Apr 2016 09:46:03 -0400 Subject: [PATCH 144/167] 8152845: Improve PackageEntry and ModuleEntry print methods for future logging Changed print methods for PackageEntry and ModuleEntry to take an outputStream Reviewed-by: lfoltan, hseigel, coleenp --- .../src/share/vm/classfile/moduleEntry.cpp | 29 +++++++++---------- .../src/share/vm/classfile/moduleEntry.hpp | 5 ++-- .../src/share/vm/classfile/packageEntry.cpp | 23 +++++++-------- .../src/share/vm/classfile/packageEntry.hpp | 5 ++-- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index e86ed6acabf..3386dc43c1e 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -36,6 +36,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" ModuleEntry* ModuleEntryTable::_javabase_module = NULL; @@ -359,31 +360,29 @@ void ModuleEntryTable::patch_javabase_entries(Handle module_handle) { java_lang_Class::set_fixup_module_field_list(NULL); } -#ifndef PRODUCT -void ModuleEntryTable::print() { - tty->print_cr("Module Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void ModuleEntryTable::print(outputStream* st) { + st->print_cr("Module Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (ModuleEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void ModuleEntry::print() { +void ModuleEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, - p2i(this), - name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), - p2i(module()), - loader()->loader_name(), - version() != NULL ? version()->as_C_string() : "NULL", - location() != NULL ? location()->as_C_string() : "NULL", - BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); + st->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, + p2i(this), + name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), + p2i(module()), + loader()->loader_name(), + version() != NULL ? version()->as_C_string() : "NULL", + location() != NULL ? location()->as_C_string() : "NULL", + BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); } -#endif void ModuleEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp index d67251c1869..87accbeab41 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.hpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp @@ -33,6 +33,7 @@ #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" #define UNNAMED_MODULE "Unnamed Module" @@ -141,7 +142,7 @@ public: void purge_reads(); void delete_reads(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -223,7 +224,7 @@ public: static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location); static void patch_javabase_entries(Handle module_handle); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp index b3117d483c1..ec6d4d08428 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.cpp +++ b/hotspot/src/share/vm/classfile/packageEntry.cpp @@ -32,6 +32,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" // Return true if this package is exported to m. bool PackageEntry::is_qexported_to(ModuleEntry* m) const { @@ -265,28 +266,26 @@ void PackageEntryTable::purge_all_package_exports() { } } -#ifndef PRODUCT -void PackageEntryTable::print() { - tty->print_cr("Package Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void PackageEntryTable::print(outputStream* st) { + st->print_cr("Package Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (PackageEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void PackageEntry::print() { +void PackageEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " - INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, - p2i(this), name()->as_C_string(), - (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), - _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); + st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " + INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, + p2i(this), name()->as_C_string(), + (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), + _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); } -#endif void PackageEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp index 368609c21b6..00b7b9d160f 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.hpp +++ b/hotspot/src/share/vm/classfile/packageEntry.hpp @@ -29,6 +29,7 @@ #include "oops/symbol.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" // A PackageEntry basically represents a Java package. It contains: // - Symbol* containing the package's name. @@ -144,7 +145,7 @@ public: void purge_qualified_exports(); void delete_qualified_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -195,7 +196,7 @@ public: // purge dead weak references out of exported list void purge_all_package_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; From 33aa33f03a83d5fd09dee99d89397a7b572b2cd5 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 18 Apr 2016 13:42:52 -0400 Subject: [PATCH 145/167] 8154268: [TESTBUG] Compilation of ExportAllUnnamed.java failed, missing @modules Add missing @modules and @build tags Reviewed-by: ctornqvi, lfoltan, gtriantafill --- .../test/runtime/modules/AccessCheck/ExportAllUnnamed.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java index cb09a5315d6..a75fda9668f 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java @@ -28,11 +28,12 @@ * @summary Test if package p2 in module m2 is exported to all unnamed, * then class p1.c1 in an unnamed module can read p2.c2 in module m2. * @library /testlibrary /test/lib + * @modules java.base/jdk.internal.module * @compile myloaders/MySameClassLoader.java * @compile p2/c2.java * @compile p1/c1.java - * @compile -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED ExportAllUnnamed.java - * @run main/othervm -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED -Xbootclasspath/a:. ExportAllUnnamed + * @build ExportAllUnnamed + * @run main/othervm -Xbootclasspath/a:. ExportAllUnnamed */ import static jdk.test.lib.Asserts.*; From 3079c942b60af576b0293cf26e755403b230e5f3 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 18 Apr 2016 14:52:31 -0400 Subject: [PATCH 146/167] 8133051: Concurrent refinement threads may be activated and deactivated at random Establish min threshold step; earlier primary refinement thread activation. Reviewed-by: tschatzl, drwhite, mgerdin, jmasa --- .../src/share/vm/gc/g1/concurrentG1Refine.cpp | 301 ++++++++++++++---- .../src/share/vm/gc/g1/concurrentG1Refine.hpp | 32 +- .../vm/gc/g1/concurrentG1RefineThread.cpp | 34 +- .../vm/gc/g1/concurrentG1RefineThread.hpp | 12 +- hotspot/src/share/vm/gc/g1/g1_globals.hpp | 16 +- hotspot/src/share/vm/logging/logPrefix.hpp | 1 + hotspot/src/share/vm/runtime/arguments.cpp | 4 +- .../share/vm/utilities/globalDefinitions.hpp | 11 +- .../TestG1ConcRefinementThreads.java | 8 +- 9 files changed, 302 insertions(+), 117 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index 3a4d5ede251..e67c8932a8b 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -29,42 +29,174 @@ #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1Predictions.hpp" #include "runtime/java.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/pair.hpp" +#include -ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictor) : - _threads(NULL), - _sample_thread(NULL), - _predictor_sigma(predictor->sigma()), - _hot_card_cache(g1h) -{ - // Ergonomically select initial concurrent refinement parameters - if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); +// Arbitrary but large limits, to simplify some of the zone calculations. +// The general idea is to allow expressions like +// MIN2(x OP y, max_XXX_zone) +// without needing to check for overflow in "x OP y", because the +// ranges for x and y have been restricted. +STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)); +const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort); +const size_t max_green_zone = max_yellow_zone / 2; +const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue. +STATIC_ASSERT(max_yellow_zone <= max_red_zone); + +// Range check assertions for green zone values. +#define assert_zone_constraints_g(green) \ + do { \ + size_t azc_g_green = (green); \ + assert(azc_g_green <= max_green_zone, \ + "green exceeds max: " SIZE_FORMAT, azc_g_green); \ + } while (0) + +// Range check assertions for green and yellow zone values. +#define assert_zone_constraints_gy(green, yellow) \ + do { \ + size_t azc_gy_green = (green); \ + size_t azc_gy_yellow = (yellow); \ + assert_zone_constraints_g(azc_gy_green); \ + assert(azc_gy_yellow <= max_yellow_zone, \ + "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \ + assert(azc_gy_green <= azc_gy_yellow, \ + "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \ + azc_gy_green, azc_gy_yellow); \ + } while (0) + +// Range check assertions for green, yellow, and red zone values. +#define assert_zone_constraints_gyr(green, yellow, red) \ + do { \ + size_t azc_gyr_green = (green); \ + size_t azc_gyr_yellow = (yellow); \ + size_t azc_gyr_red = (red); \ + assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \ + assert(azc_gyr_red <= max_red_zone, \ + "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \ + assert(azc_gyr_yellow <= azc_gyr_red, \ + "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \ + azc_gyr_yellow, azc_gyr_red); \ + } while (0) + +// Logging tag sequence for refinement control updates. +#define CTRL_TAGS gc, ergo, refine + +// For logging zone values, ensuring consistency of level and tags. +#define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__) + +// Package for pair of refinement thread activation and deactivation +// thresholds. The activation and deactivation levels are resp. the first +// and second values of the pair. +typedef Pair Thresholds; +inline size_t activation_level(const Thresholds& t) { return t.first; } +inline size_t deactivation_level(const Thresholds& t) { return t.second; } + +static Thresholds calc_thresholds(size_t green_zone, + size_t yellow_zone, + uint worker_i) { + double yellow_size = yellow_zone - green_zone; + double step = yellow_size / ConcurrentG1Refine::thread_num(); + if (worker_i == 0) { + // Potentially activate worker 0 more aggressively, to keep + // available buffers near green_zone value. When yellow_size is + // large we don't want to allow a full step to accumulate before + // doing any processing, as that might lead to significantly more + // than green_zone buffers to be processed by update_rs. + step = MIN2(step, ParallelGCThreads / 2.0); } - set_green_zone(G1ConcRefinementGreenZone); - - if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); - } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); - - if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); - } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); - + size_t activate_offset = static_cast(ceil(step * (worker_i + 1))); + size_t deactivate_offset = static_cast(floor(step * worker_i)); + return Thresholds(green_zone + activate_offset, + green_zone + deactivate_offset); } -ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { - G1CollectorPolicy* policy = g1h->g1_policy(); - ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, &policy->predictor()); +ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size) : + _threads(NULL), + _sample_thread(NULL), + _n_worker_threads(thread_num()), + _green_zone(green_zone), + _yellow_zone(yellow_zone), + _red_zone(red_zone), + _min_yellow_zone_size(min_yellow_zone_size), + _hot_card_cache(g1h) +{ + assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone); +} + +static size_t calc_min_yellow_zone_size() { + size_t step = G1ConcRefinementThresholdStep; + uint n_workers = ConcurrentG1Refine::thread_num(); + if ((max_yellow_zone / step) < n_workers) { + return max_yellow_zone; + } else { + return step * n_workers; + } +} + +static size_t calc_init_green_zone() { + size_t green = G1ConcRefinementGreenZone; + if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { + green = ParallelGCThreads; + } + return MIN2(green, max_green_zone); +} + +static size_t calc_init_yellow_zone(size_t green, size_t min_size) { + size_t config = G1ConcRefinementYellowZone; + size_t size = 0; + if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { + size = green * 2; + } else if (green < config) { + size = config - green; + } + size = MAX2(size, min_size); + size = MIN2(size, max_yellow_zone); + return MIN2(green + size, max_yellow_zone); +} + +static size_t calc_init_red_zone(size_t green, size_t yellow) { + size_t size = yellow - green; + if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { + size_t config = G1ConcRefinementRedZone; + if (yellow < config) { + size = MAX2(size, config - yellow); + } + } + return MIN2(yellow + size, max_red_zone); +} + +ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, + CardTableEntryClosure* refine_closure, + jint* ecode) { + size_t min_yellow_zone_size = calc_min_yellow_zone_size(); + size_t green_zone = calc_init_green_zone(); + size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size); + size_t red_zone = calc_init_red_zone(green_zone, yellow_zone); + + LOG_ZONES("Initial Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT ", " + "min yellow size: " SIZE_FORMAT, + green_zone, yellow_zone, red_zone, min_yellow_zone_size); + + ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, + green_zone, + yellow_zone, + red_zone, + min_yellow_zone_size); + if (cg1r == NULL) { *ecode = JNI_ENOMEM; vm_shutdown_during_initialization("Could not create ConcurrentG1Refine"); return NULL; } - cg1r->_n_worker_threads = thread_num(); - - cg1r->reset_threshold_step(); cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC); if (cg1r->_threads == NULL) { @@ -77,7 +209,15 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn ConcurrentG1RefineThread *next = NULL; for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) { - ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i); + Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i); + ConcurrentG1RefineThread* t = + new ConcurrentG1RefineThread(cg1r, + next, + refine_closure, + worker_id_offset, + i, + activation_level(thresholds), + deactivation_level(thresholds)); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { *ecode = JNI_ENOMEM; @@ -101,14 +241,6 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn return cg1r; } -void ConcurrentG1Refine::reset_threshold_step() { - if (FLAG_IS_DEFAULT(G1ConcRefinementThresholdStep)) { - _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1); - } else { - _thread_threshold_step = G1ConcRefinementThresholdStep; - } -} - void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) { _hot_card_cache.initialize(card_counts_storage); } @@ -120,10 +252,11 @@ void ConcurrentG1Refine::stop() { _sample_thread->stop(); } -void ConcurrentG1Refine::reinitialize_threads() { - reset_threshold_step(); +void ConcurrentG1Refine::update_thread_thresholds() { for (uint i = 0; i < _n_worker_threads; i++) { - _threads[i]->initialize(); + Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i); + _threads[i]->update_thresholds(activation_level(thresholds), + deactivation_level(thresholds)); } } @@ -142,7 +275,7 @@ void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { } void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { - for (uint i = 0; i < worker_thread_num(); i++) { + for (uint i = 0; i < _n_worker_threads; i++) { tc->do_thread(_threads[i]); } } @@ -160,34 +293,80 @@ void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { st->cr(); } +static size_t calc_new_green_zone(size_t green, + double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + // Adjust green zone based on whether we're meeting the time goal. + // Limit to max_green_zone. + const double inc_k = 1.1, dec_k = 0.9; + if (update_rs_time > goal_ms) { + if (green > 0) { + green = static_cast(green * dec_k); + } + } else if (update_rs_time < goal_ms && + update_rs_processed_buffers > green) { + green = static_cast(MAX2(green * inc_k, green + 1.0)); + green = MIN2(green, max_green_zone); + } + return green; +} + +static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) { + size_t size = green * 2; + size = MAX2(size, min_yellow_size); + return MIN2(green + size, max_yellow_zone); +} + +static size_t calc_new_red_zone(size_t green, size_t yellow) { + return MIN2(yellow + (yellow - green), max_red_zone); +} + +void ConcurrentG1Refine::update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + log_trace( CTRL_TAGS )("Updating Refinement Zones: " + "update_rs time: %.3fms, " + "update_rs buffers: " SIZE_FORMAT ", " + "update_rs goal time: %.3fms", + update_rs_time, + update_rs_processed_buffers, + goal_ms); + + _green_zone = calc_new_green_zone(_green_zone, + update_rs_time, + update_rs_processed_buffers, + goal_ms); + _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); + _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); + + assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone); + LOG_ZONES("Updated Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT, + _green_zone, _yellow_zone, _red_zone); +} + void ConcurrentG1Refine::adjust(double update_rs_time, - double update_rs_processed_buffers, + size_t update_rs_processed_buffers, double goal_ms) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); if (G1UseAdaptiveConcRefinement) { - const int k_gy = 3, k_gr = 6; - const double inc_k = 1.1, dec_k = 0.9; + update_zones(update_rs_time, update_rs_processed_buffers, goal_ms); + update_thread_thresholds(); - size_t g = green_zone(); - if (update_rs_time > goal_ms) { - g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. - } else { - if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (size_t)MAX2(g * inc_k, g + 1.0); - } - } - // Change the refinement threads params - set_green_zone(g); - set_yellow_zone(g * k_gy); - set_red_zone(g * k_gr); - reinitialize_threads(); - - size_t processing_threshold_delta = MAX2(green_zone() * _predictor_sigma, 1); - size_t processing_threshold = MIN2(green_zone() + processing_threshold_delta, - yellow_zone()); // Change the barrier params - dcqs.set_process_completed_threshold((int)processing_threshold); + if (_n_worker_threads == 0) { + // Disable dcqs notification when there are no threads to notify. + dcqs.set_process_completed_threshold(INT_MAX); + } else { + // Worker 0 is the primary; wakeup is via dcqs notification. + STATIC_ASSERT(max_yellow_zone <= INT_MAX); + size_t activate = _threads[0]->activation_threshold(); + dcqs.set_process_completed_threshold((int)activate); + } dcqs.set_max_completed_queue((int)red_zone()); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index 3161f62f2b2..098d49e801d 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -65,18 +65,24 @@ class ConcurrentG1Refine: public CHeapObj { size_t _green_zone; size_t _yellow_zone; size_t _red_zone; - - size_t _thread_threshold_step; - - double _predictor_sigma; + size_t _min_yellow_zone_size; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; - // Reset the threshold step value based of the current zone boundaries. - void reset_threshold_step(); + ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size); - ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictions); + // Update green/yellow/red zone values based on how well goals are being met. + void update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms); + + // Update thread thresholds to account for updated zone values. + void update_thread_thresholds(); public: ~ConcurrentG1Refine(); @@ -88,9 +94,7 @@ class ConcurrentG1Refine: public CHeapObj { void init(G1RegionToSpaceMapper* card_counts_storage); void stop(); - void adjust(double update_rs_time, double update_rs_processed_buffers, double goal_ms); - - void reinitialize_threads(); + void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms); // Iterate over all concurrent refinement threads void threads_do(ThreadClosure *tc); @@ -105,18 +109,10 @@ class ConcurrentG1Refine: public CHeapObj { void print_worker_threads_on(outputStream* st) const; - void set_green_zone(size_t x) { _green_zone = x; } - void set_yellow_zone(size_t x) { _yellow_zone = x; } - void set_red_zone(size_t x) { _red_zone = x; } - size_t green_zone() const { return _green_zone; } size_t yellow_zone() const { return _yellow_zone; } size_t red_zone() const { return _red_zone; } - uint worker_thread_num() const { return _n_worker_threads; } - - size_t thread_threshold_step() const { return _thread_threshold_step; } - G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } static bool hot_card_cache_enabled() { return G1HotCardCache::default_use_cache(); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index 78bea91e71b..8f9ebfbfb68 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -36,7 +36,8 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id) : + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate) : ConcurrentGCThread(), _refine_closure(refine_closure), _worker_id_offset(worker_id_offset), @@ -45,7 +46,9 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex _next(next), _monitor(NULL), _cg1r(cg1r), - _vtime_accum(0.0) + _vtime_accum(0.0), + _activation_threshold(activate), + _deactivation_threshold(deactivate) { // Each thread has its own monitor. The i-th thread is responsible for signaling @@ -58,21 +61,17 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex } else { _monitor = DirtyCardQ_CBL_mon; } - initialize(); // set name set_name("G1 Refine#%d", worker_id); create_and_start(); } -void ConcurrentG1RefineThread::initialize() { - // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); - // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = - MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), - cg1r()->green_zone()); +void ConcurrentG1RefineThread::update_thresholds(size_t activate, + size_t deactivate) { + assert(deactivate < activate, "precondition"); + _activation_threshold = activate; + _deactivation_threshold = deactivate; } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -118,9 +117,10 @@ void ConcurrentG1RefineThread::run_service() { break; } + size_t buffers_processed = 0; DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _threshold, dcqs.completed_buffers_num()); + _worker_id, _activation_threshold, dcqs.completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; @@ -139,7 +139,9 @@ void ConcurrentG1RefineThread::run_service() { } // Check if we need to activate the next thread. - if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { + if ((_next != NULL) && + !_next->is_active() && + (curr_buffer_num > _next->_activation_threshold)) { _next->activate(); } @@ -150,14 +152,16 @@ void ConcurrentG1RefineThread::run_service() { false /* during_pause */)) { break; // Deactivate, number of buffers fell below threshold. } + ++buffers_processed; } } deactivate(); log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT - ", current: " SIZE_FORMAT, + ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, _worker_id, _deactivation_threshold, - dcqs.completed_buffers_num()); + dcqs.completed_buffers_num(), + buffers_processed); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index 9f325599cfc..902d77cb9f6 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -53,10 +53,8 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - size_t _thread_threshold_step; - // This thread activation threshold - size_t _threshold; - // This thread deactivation threshold + // This thread's activation/deactivation thresholds + size_t _activation_threshold; size_t _deactivation_threshold; void wait_for_completed_buffers(); @@ -75,9 +73,11 @@ public: // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id); + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate); - void initialize(); + void update_thresholds(size_t activate, size_t deactivate); + size_t activation_threshold() const { return _activation_threshold; } // Total virtual time so far. double vtime_accum() { return _vtime_accum; } diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index f015e4e9ee1..ce8d96ea3ec 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -112,8 +112,7 @@ product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ - "Will be selected ergonomically by default. Zero will disable " \ - "concurrent processing.") \ + "Will be selected ergonomically by default.") \ range(0, max_intx) \ \ product(size_t, G1ConcRefinementGreenZone, 0, \ @@ -127,11 +126,12 @@ "specified number of milliseconds to do miscellaneous work.") \ range(0, max_jint) \ \ - product(size_t, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 2, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ - "Will be selected ergonomically by default.") \ - range(0, SIZE_MAX) \ + "The actual step size will be selected ergonomically by " \ + "default, with this value used to determine a lower bound.") \ + range(1, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ @@ -201,9 +201,9 @@ range(0, 32*M) \ constraint(G1HeapRegionSizeConstraintFunc,AfterMemoryInit) \ \ - product(uintx, G1ConcRefinementThreads, 0, \ - "If non-0 is the number of parallel rem set update threads, " \ - "otherwise the value is determined ergonomically.") \ + product(uint, G1ConcRefinementThreads, 0, \ + "The number of parallel rem set update threads. " \ + "Will be set ergonomically by default.") \ range(0, (max_jint-1)/wordSize) \ \ develop(bool, G1VerifyCTCleanup, false, \ diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 48d342d1ba8..8d2ae12adf3 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -55,6 +55,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);) LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, cset)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, ihop)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, refine)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, freelist)) \ diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 0ffe91cfb7e..7fa2ea8a7ad 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2095,8 +2095,8 @@ void Arguments::set_g1_gc_flags() { } #if INCLUDE_ALL_GCS - if (G1ConcRefinementThreads == 0) { - FLAG_SET_DEFAULT(G1ConcRefinementThreads, ParallelGCThreads); + if (FLAG_IS_DEFAULT(G1ConcRefinementThreads)) { + FLAG_SET_ERGO(uint, G1ConcRefinementThreads, ParallelGCThreads); } #endif diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3c04e2a0f54..85186c1ffab 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -199,9 +199,6 @@ const size_t M = K*K; const size_t G = M*K; const size_t HWperKB = K / sizeof(HeapWord); -const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint -const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint - // Constants for converting from a base unit to milli-base units. For // example from seconds to milliseconds and microseconds @@ -381,6 +378,14 @@ typedef jshort s2; typedef jint s4; typedef jlong s8; +const jbyte min_jbyte = -(1 << 7); // smallest jbyte +const jbyte max_jbyte = (1 << 7) - 1; // largest jbyte +const jshort min_jshort = -(1 << 15); // smallest jshort +const jshort max_jshort = (1 << 15) - 1; // largest jshort + +const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint +const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint + //---------------------------------------------------------------------------------------------------- // JVM spec restrictions diff --git a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java index 0a470191560..25b8e34414a 100644 --- a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java +++ b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java @@ -38,7 +38,7 @@ import java.util.regex.*; public class TestG1ConcRefinementThreads { - static final int AUTO_SELECT_THREADS_COUNT = 0; + static final int AUTO_SELECT_THREADS_COUNT = -1; static final int PASSED_THREADS_COUNT = 11; public static void main(String args[]) throws Exception { @@ -49,8 +49,8 @@ public class TestG1ConcRefinementThreads { // zero setting case runG1ConcRefinementThreadsTest( - new String[]{"-XX:G1ConcRefinementThreads=0"}, // automatically selected - AUTO_SELECT_THREADS_COUNT /* set to zero */); + new String[]{"-XX:G1ConcRefinementThreads=0"}, + 0); // non-zero sestting case runG1ConcRefinementThreadsTest( @@ -77,7 +77,7 @@ public class TestG1ConcRefinementThreads { private static void checkG1ConcRefinementThreadsConsistency(String output, int expectedValue) { int actualValue = getIntValue("G1ConcRefinementThreads", output); - if (expectedValue == 0) { + if (expectedValue == AUTO_SELECT_THREADS_COUNT) { // If expectedValue is automatically selected, set it same as ParallelGCThreads. expectedValue = getIntValue("ParallelGCThreads", output); } From 5acf187999317e172bc783dbb8ed6b87aaae1447 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 18 Apr 2016 14:11:16 -0700 Subject: [PATCH 147/167] 8145468: update java.lang APIs with new deprecations Reviewed-by: lancea, alanb --- make/CompileJavaModules.gmk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index c4275f863e3..4ce9cca25bf 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -98,7 +98,8 @@ java.datatransfer_COPY := flavormap.properties ################################################################################ -java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' +java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \ + '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties From ebb86eaa4f6da5ab0985b8ad4c8981fa43c494eb Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 19 Apr 2016 14:34:43 +0100 Subject: [PATCH 148/167] 8148863: Remove sun.misc.ManagedLocalsThread from corba Reviewed-by: alanb, coffeys, msheppar --- .../classes/com/sun/corba/se/impl/corba/RequestImpl.java | 2 +- .../classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java | 3 ++- .../share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java | 3 ++- .../classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java | 2 +- .../sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java | 3 ++- .../share/classes/com/sun/corba/se/impl/orb/ORBImpl.java | 2 +- .../sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java | 4 ++-- .../classes/com/sun/corba/se/impl/transport/SelectorImpl.java | 4 ++-- corba/src/java.corba/share/classes/module-info.java | 2 -- 9 files changed, 13 insertions(+), 12 deletions(-) diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java index 3c357f61c38..69b58393d95 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java @@ -255,7 +255,7 @@ public class RequestImpl public synchronized void send_deferred() { AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "Async-Request-Invoker-Thread", 0, false).start(); } public synchronized boolean poll_response() diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java index d9dceac7ba8..a9ae337883e 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java @@ -751,12 +751,13 @@ public class Util implements javax.rmi.CORBA.UtilDelegate } } -class KeepAlive extends sun.misc.ManagedLocalsThread +class KeepAlive extends Thread { boolean quit = false; public KeepAlive () { + super(null, null, "Servant-KeepAlive-Thread", 0, false); setDaemon(false); } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java index 546914d623d..3205a5c24be 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java @@ -516,7 +516,7 @@ public class POAImpl extends ObjectAdapterBase implements POA // Converted from anonymous class to local class // so that we can call performDestroy() directly. - static class DestroyThread extends sun.misc.ManagedLocalsThread { + static class DestroyThread extends Thread { private boolean wait ; private boolean etherealize ; private boolean debug ; @@ -524,6 +524,7 @@ public class POAImpl extends ObjectAdapterBase implements POA public DestroyThread( boolean etherealize, boolean debug ) { + super(null, null, "POA-Destroy-Thread", 0, false); this.etherealize = etherealize ; this.debug = debug ; } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java index 22610dda9ba..eb51310fcd3 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java @@ -357,7 +357,7 @@ public class POAManagerImpl extends org.omg.CORBA.LocalObject implements if (wait_for_completion) deactivator.run() ; else { - Thread thr = new sun.misc.ManagedLocalsThread(deactivator) ; + Thread thr = new Thread(null, deactivator, "POA-Deactivator-Thread", 0, false) ; thr.start() ; } } finally { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java index 9e9fce8a47d..1a8badc0930 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java @@ -302,7 +302,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { throw new WrongPolicy(); } - class Etherealizer extends sun.misc.ManagedLocalsThread { + class Etherealizer extends Thread { private POAPolicyMediatorImpl_R_USM mediator ; private ActiveObjectMap.Key key ; private AOMEntry entry ; @@ -314,6 +314,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { ActiveObjectMap.Key key, AOMEntry entry, Servant servant, boolean debug ) { + super(null, null, "PAO-Etherealizer-Thread", 0, false); this.mediator = mediator ; this.key = key ; this.entry = entry; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java index 82da35a7921..007e6b8dc28 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java @@ -691,7 +691,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB for (int i = 0; i < req.length; i++) { AsynchInvoke invokeObject = new AsynchInvoke( this, (com.sun.corba.se.impl.corba.RequestImpl)req[i], true); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "ORB-Request-Thread", 0, false).start(); } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java index 9a0e56afc4f..7f3ad89869c 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java @@ -459,7 +459,7 @@ public class ThreadPoolImpl implements ThreadPool } - private class WorkerThread extends sun.misc.ManagedLocalsThread implements Closeable + private class WorkerThread extends Thread implements Closeable { private Work currentWork; private int threadId = 0; // unique id for the thread @@ -469,7 +469,7 @@ public class ThreadPoolImpl implements ThreadPool private StringBuffer workerThreadName = new StringBuffer(); WorkerThread(ThreadGroup tg, String threadPoolName) { - super(tg, "Idle"); + super(tg, null, "Idle", 0, false); this.threadId = ThreadPoolImpl.getUniqueThreadId(); this.threadPoolName = threadPoolName; setName(composeWorkerThreadName(threadPoolName, "Idle")); diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index 016fd945abf..ac87ef9c932 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -61,7 +61,7 @@ import com.sun.corba.se.impl.orbutil.ORBUtility; */ class SelectorImpl extends - sun.misc.ManagedLocalsThread + Thread implements com.sun.corba.se.pept.transport.Selector { @@ -79,6 +79,7 @@ class SelectorImpl public SelectorImpl(ORB orb) { + super(null, null, "ORB-Selector-Thread", 0, false); this.orb = orb; selector = null; selectorStarted = false; @@ -277,7 +278,6 @@ class SelectorImpl public void run() { - setName("SelectorThread"); while (!closed) { try { int n = 0; diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java index 25f79def5cb..23da4b785a9 100644 --- a/corba/src/java.corba/share/classes/module-info.java +++ b/corba/src/java.corba/share/classes/module-info.java @@ -29,8 +29,6 @@ module java.corba { requires java.logging; requires java.naming; requires java.transaction; - // 8148863 - requires jdk.unsupported; exports javax.activity; exports javax.rmi; From d03b60789684f8a9e96b47c89b05b3c2e639c26a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Tue, 19 Apr 2016 23:01:06 -0700 Subject: [PATCH 149/167] 8153781: Issue in XMLScanner: EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET when skipping large DOCTYPE section with CRLF at wrong place Reviewed-by: joehw --- .../internal/impl/XML11EntityScanner.java | 25 +++--- .../internal/impl/XMLDTDScannerImpl.java | 55 +++++++----- .../impl/XMLDocumentFragmentScannerImpl.java | 14 +-- .../internal/impl/XMLDocumentScannerImpl.java | 17 ++-- .../internal/impl/XMLEntityScanner.java | 61 +++++++------ .../xerces/internal/impl/XMLScanner.java | 14 +-- .../internal/impl/msg/XMLMessages.properties | 1 + .../impl/msg/XMLMessages_de.properties | 1 + .../impl/msg/XMLMessages_es.properties | 1 + .../impl/msg/XMLMessages_fr.properties | 1 + .../impl/msg/XMLMessages_it.properties | 1 + .../xerces/internal/util/HTTPInputSource.java | 30 +++---- .../javax/xml/jaxp/unittest/TEST.properties | 3 +- .../XMLEventReaderTest/Bug6668115Test.java | 3 +- .../stream/XMLEventReaderTest/Bug8153781.java | 90 +++++++++++++++++++ 15 files changed, 210 insertions(+), 107 deletions(-) create mode 100644 jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java index a425067224c..8e1eaef54e1 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,7 +25,6 @@ import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLString; @@ -815,7 +815,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -960,7 +960,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.startPosition = 0; @@ -1397,7 +1397,7 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged) { @@ -1446,8 +1446,9 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; - entityChanged = load(1, true, true); + entityChanged = load(1, true, false); if (!entityChanged) { // the load change the position to be 1, // need to restore it when entity not changed diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java index 4daa5f0e333..d695936f67d 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,17 +20,17 @@ */ package com.sun.org.apache.xerces.internal.impl; -import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; -import java.io.EOFException; -import java.io.IOException; +import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; - +import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; +import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; - +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; @@ -41,11 +42,9 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.impl.Constants; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; +import java.io.EOFException; +import java.io.IOException; /** * This class is responsible for scanning the declarations found @@ -387,15 +386,25 @@ implements XMLDTDScanner, XMLComponent, XMLEntityHandler { */ @Override public boolean skipDTD(boolean supportDTD) throws IOException { - if (!supportDTD) { - fStringBuffer.clear(); - if (!fEntityScanner.scanData("]", fStringBuffer)) { - fEntityScanner.fCurrentEntity.position--; - } + if (supportDTD) + return false; - return true; + fStringBuffer.clear(); + while (fEntityScanner.scanData("]", fStringBuffer)) { + int c = fEntityScanner.peekChar(); + if (c != -1) { + if (XMLChar.isHighSurrogate(c)) { + scanSurrogates(fStringBuffer); + } + if (isInvalidLiteral(c)) { + reportFatalError("InvalidCharInDTD", + new Object[] { Integer.toHexString(c) }); + fEntityScanner.scanChar(); + } + } } - return false; + fEntityScanner.fCurrentEntity.position--; + return true; } // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index e31e838c8e8..c817111e067 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +19,6 @@ * limitations under the License. */ - package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.XMLBufferListener; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index 7f1bbf10226..235d27ba5d8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; @@ -1106,8 +1106,7 @@ public class XMLDocumentScannerImpl if (!moreToScan) { // end doctype declaration if (!fEntityScanner.skipChar(']')) { - reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET", - null); + reportFatalError("DoctypedeclNotClosed", new Object[]{fDoctypeName}); } fEntityScanner.skipSpaces(); if (!fEntityScanner.skipChar('>')) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index 1c0eca636a8..b7922312371 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,8 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - - import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; import com.sun.org.apache.xerces.internal.impl.io.UCSReader; import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; @@ -44,8 +43,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.ArrayList; import java.util.Locale; -import java.util.Vector; /** * Implements the entity scanner methods. @@ -58,11 +57,10 @@ import java.util.Vector; */ public class XMLEntityScanner implements XMLLocator { - - protected Entity.ScannedEntity fCurrentEntity = null ; + protected Entity.ScannedEntity fCurrentEntity = null; protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE; - protected XMLEntityManager fEntityManager ; + protected XMLEntityManager fEntityManager; /** Security manager. */ protected XMLSecurityManager fSecurityManager = null; @@ -72,8 +70,9 @@ public class XMLEntityScanner implements XMLLocator { /** Debug switching readers for encodings. */ private static final boolean DEBUG_ENCODINGS = false; + /** Listeners which should know when load is being called */ - private Vector listeners = new Vector(); + private ArrayList listeners = new ArrayList<>(); private static final boolean [] VALID_NAMES = new boolean[127]; @@ -140,9 +139,11 @@ public class XMLEntityScanner implements XMLLocator { VALID_NAMES[58]=true; VALID_NAMES[95]=true; } - // SAPJVM: Remember, that the XML version has explicitly been set, + + // Remember, that the XML version has explicitly been set, // so that XMLStreamReader.getVersion() can find that out. - boolean xmlVersionSetExplicitly = false; + protected boolean xmlVersionSetExplicitly = false; + // // Constructors // @@ -257,7 +258,7 @@ public class XMLEntityScanner implements XMLLocator { * @param xmlVersion the XML version of the current entity */ public final void setXMLVersion(String xmlVersion) { - xmlVersionSetExplicitly = true; // SAPJVM + xmlVersionSetExplicitly = true; fCurrentEntity.xmlVersion = xmlVersion; } // setXMLVersion(String) @@ -546,8 +547,7 @@ public class XMLEntityScanner implements XMLLocator { // scan character int c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\n' || - (c == '\r' && isExternal)) { + if (c == '\n' || (c == '\r' && isExternal)) { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { @@ -953,7 +953,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1105,7 +1105,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1256,8 +1256,8 @@ public class XMLEntityScanner implements XMLLocator { *

    * Note: The characters are consumed. *

    - * Note: This assumes that the length of the delimiter - * and that the delimiter contains at least one character. + * Note: This assumes that the delimiter contains at + * least one character. *

    * Note: This method does not guarantee to return * the longest run of character data. This method may return before @@ -1436,7 +1436,7 @@ public class XMLEntityScanner implements XMLLocator { } while (!done); return !done; - } // scanData(String,XMLString) + } // scanData(String, XMLStringBuffer) /** * Skips a character appearing immediately on the input. @@ -1558,7 +1558,7 @@ public class XMLEntityScanner implements XMLLocator { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged){ @@ -1727,8 +1727,7 @@ public class XMLEntityScanner implements XMLLocator { final int length = s.length; //first make sure that required capacity is avaible if(arrangeCapacity(length, false)){ - int beforeSkip = fCurrentEntity.position ; - int afterSkip = fCurrentEntity.position + length ; + int beforeSkip = fCurrentEntity.position; if(DEBUG_SKIP_STRING){ System.out.println("skipString,length = " + new String(s) + "," + length); @@ -2107,8 +2106,9 @@ public class XMLEntityScanner implements XMLLocator { * is being changed. */ public void registerListener(XMLBufferListener listener) { - if(!listeners.contains(listener)) + if (!listeners.contains(listener)) { listeners.add(listener); + } } /** @@ -2116,9 +2116,8 @@ public class XMLEntityScanner implements XMLLocator { * @param loadPos Starting position from which new data is being loaded into scanner buffer. */ public void invokeListeners(int loadPos){ - for(int i=0;i''. + DoctypedeclNotClosed = The document type declaration for root element type \"{0}\" must be closed with '']''. PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index c82bc5b80d0..55c9d3a3c92 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Leerstelle nach "" enden. + DoctypedeclNotClosed = Dokumenttypdeklaration f\u00FCr Root-Elementtyp "{0}" muss mit "]" abgeschlossen werden. PEReferenceWithinMarkup = Parameterentit\u00E4tsreferenz "%{0};" darf nicht in Markup in der internen Teilmenge der DTD vorkommen. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Die Markup-Deklarationen, die in der Dokumenttypdeklaration enthalten sind bzw. auf die von der Dokumenttypdeklaration verwiesen wird, m\u00FCssen ordnungsgem\u00E4\u00DF formatiert sein. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties index 1243b215cec..51491f84075 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Es necesario un espacio en blanco despu\u00E9s de "''. + DoctypedeclNotClosed = La declaraci\u00F3n de tipo de documento para el tipo de elemento ra\u00EDz "{0}" debe cerrar en '']''. PEReferenceWithinMarkup = La referencia de entidad del par\u00E1metro "%{0};" no puede producirse en el marcador en el subconjunto interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Las declaraciones de marcador que se incluyen o a las que apunta la declaraci\u00F3n de tipo de documento deben tener el formato correcto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties index 5a2b76c13b7..2be672257f3 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Un espace est obligatoire apr\u00E8s "''. + DoctypedeclNotClosed = La d\u00E9claration de type de document pour le type d''\u00E9l\u00E9ment racine "{0}" doit se conclure par '']''. PEReferenceWithinMarkup = La r\u00E9f\u00E9rence d''entit\u00E9 de param\u00E8tre "%{0};" ne peut pas survenir dans le balisage du sous-ensemble interne de la DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Les d\u00E9clarations de balisage contenues dans la d\u00E9claration de type de document ou sur lesquelles pointe cette derni\u00E8re doivent avoir un format correct. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties index 1f8ec89276a..aa229f49bf2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = \u00C8 richiesto uno spazio dopo "''. + DoctypedeclNotClosed = La dichiarazione del tipo di documento per il tipo di elemento radice "{0}" deve chiudere con '']''. PEReferenceWithinMarkup = Il riferimento di entit\u00E0 di parametro "%{0};" non pu\u00F2 essere presente nel markup del set secondario interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Le dichiarazioni di markup contenute o indicate dalla dichiarazione del tipo di documento devono avere un formato corretto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java index bdd0750d0fa..c9bbed93511 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java @@ -1,15 +1,16 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. */ + /* - * Copyright 2004,2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,17 +18,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.util; -import java.io.InputStream; -import java.io.Reader; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; +import java.io.InputStream; +import java.io.Reader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** * This class represents an input source for an XML resource diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties index 93da2fdba82..b6e235b5124 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties +++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties @@ -4,5 +4,6 @@ TestNG.dirs = . lib.dirs = /javax/xml/jaxp/libs # Declare module dependency -modules=java.xml/com.sun.org.apache.xerces.internal.jaxp \ +modules=java.xml/com.sun.org.apache.xerces.internal.impl \ + java.xml/com.sun.org.apache.xerces.internal.jaxp \ java.xml/com.sun.org.apache.xml.internal.serialize diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java index c56e7569c3c..188d003621a 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java @@ -28,7 +28,6 @@ import java.io.File; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.events.XMLEvent; import org.testng.Assert; import org.testng.annotations.Test; @@ -74,7 +73,7 @@ public class Bug6668115Test { er.nextTag(); er.nextTag(); - XMLEvent event = er.peek(); + er.peek(); System.out.println(er.getElementText()); er.nextTag(); System.out.println(er.getElementText()); diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java new file mode 100644 index 00000000000..f973b3bf33d --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package stream.XMLEventReaderTest; + +import java.io.StringReader; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; + +/* + * @bug 8153781 + * @summary Test if method skipDTD of class XMLDTDScannerImpl will correctly skip the DTD section, + * even if a call to XMLEntityScanner.scanData for skipping to the closing ']' returns true. + */ +public class Bug8153781 { + public static int DOCTYPE_SECTION_LENGTH = XMLEntityManager.DEFAULT_BUFFER_SIZE * 2; + public static int DOCUMENT_LENGTH = DOCTYPE_SECTION_LENGTH + 4096; + + public String createXMLDocument(int doctypeoffset) { + StringBuilder xmlcontentbuilder = new StringBuilder(DOCUMENT_LENGTH); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append(" \r\n"); + xmlcontentbuilder.append(" ]\r\n"); + xmlcontentbuilder.append(">\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + System.out.println("Document length:" + xmlcontentbuilder.length()); + return xmlcontentbuilder.toString(); + } + + public void runReader(XMLInputFactory factory, int offset) throws XMLStreamException { + StringReader stringReader = new StringReader(createXMLDocument(offset)); + XMLEventReader reader = factory.createXMLEventReader(stringReader); + + while (reader.hasNext()) { + XMLEvent event = reader.nextEvent(); + System.out.println("Event Type: " + event.getEventType()); + } + } + + @Test + public void test() { + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + for (int i = 0; i < 3; i++) { + runReader(factory, i); + } + } catch (XMLStreamException xe) { + xe.printStackTrace(); + Assert.fail(xe.getMessage()); + } + } +} From 4b1ef0a20be4c6444aea5b8f281135cc7a6a5595 Mon Sep 17 00:00:00 2001 From: Frank Yuan Date: Tue, 19 Apr 2016 23:56:52 -0700 Subject: [PATCH 150/167] 8078820: Test deploying a XML parser as a module Reviewed-by: joehw, alanb --- .../jaxp/libs/jdk/testlibrary/Asserts.java | 566 +++++++++++++++++ .../libs/jdk/testlibrary/CompilerUtils.java | 81 +++ .../libs/jdk/testlibrary/JDKToolFinder.java | 111 ++++ .../libs/jdk/testlibrary/JDKToolLauncher.java | 136 ++++ .../libs/jdk/testlibrary/OutputAnalyzer.java | 576 +++++++++++++++++ .../libs/jdk/testlibrary/OutputBuffer.java | 113 ++++ .../jaxp/libs/jdk/testlibrary/Platform.java | 213 +++++++ .../libs/jdk/testlibrary/ProcessTools.java | 579 ++++++++++++++++++ .../xml/jaxp/libs/jdk/testlibrary/README.txt | 1 + .../libs/jdk/testlibrary/StreamPumper.java | 204 ++++++ .../xml/jaxp/libs/jdk/testlibrary/Utils.java | 365 +++++++++++ .../BasicModularXMLParserTest.java | 120 ++++ .../LayerModularXMLParserTest.java | 187 ++++++ .../src/test/module-info.java | 27 + .../src/test/test/XMLFactoryHelper.java | 55 ++ .../ServiceProviderTest/src/unnamed/Main.java | 107 ++++ .../src/xmlprovider1/module-info.java | 34 + .../xp1/DocumentBuilderFactoryImpl.java | 57 ++ .../xp1/SAXParserFactoryImpl.java | 53 ++ .../xmlprovider1/xp1/SchemaFactoryImpl.java | 77 +++ .../xp1/TransformerFactoryImpl.java | 97 +++ .../xmlprovider1/xp1/XMLInputFactoryImpl.java | 166 +++++ .../xp1/XMLOutputFactoryImpl.java | 94 +++ .../xmlprovider1/xp1/XPathFactoryImpl.java | 65 ++ .../src/xmlprovider2/module-info.java | 29 + .../xmlprovider2/xp2/DatatypeFactoryImpl.java | 73 +++ .../xmlprovider2/xp2/XMLEventFactoryImpl.java | 180 ++++++ .../javax/xml/jaxp/module/TEST.properties | 5 + 28 files changed, 4371 insertions(+) create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java create mode 100644 jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java create mode 100644 jaxp/test/javax/xml/jaxp/module/TEST.properties diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java new file mode 100644 index 00000000000..594b12e3ede --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.Objects; + +/** + * Asserts that can be used for verifying assumptions in tests. + * + * An assertion will throw a {@link RuntimeException} if the assertion isn't true. + * All the asserts can be imported into a test by using a static import: + * + *

    + * {@code
    + * import static jdk.testlibrary.Asserts.*;
    + * }
    + *
    + * Always provide a message describing the assumption if the line number of the
    + * failing assertion isn't enough to understand why the assumption failed. For
    + * example, if the assertion is in a loop or in a method that is called
    + * multiple times, then the line number won't provide enough context to
    + * understand the failure.
    + * 
    + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Asserts { + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable) + */ + public static > void assertLT(T lhs, T rhs) { + assertLessThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLT(T lhs, T rhs, String msg) { + assertLessThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLessThan(T lhs, T rhs) { + assertLessThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static >void assertLessThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) < 0)) { + msg = Objects.toString(msg, "assertLessThan") + + ": expected that " + Objects.toString(lhs) + + " < " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable) + */ + public static > void assertLTE(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLTE(T lhs, T rhs, String msg) { + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLessThanOrEqual(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertLessThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) <= 0)) { + msg = Objects.toString(msg, "assertLessThanOrEqual") + + ": expected that " + Objects.toString(lhs) + + " <= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object) + */ + public static void assertEQ(Object lhs, Object rhs) { + assertEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEQ(Object lhs, Object rhs, String msg) { + assertEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEquals(Object lhs, Object rhs) { + assertEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertEquals(Object lhs, Object rhs, String msg) { + if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) { + msg = Objects.toString(msg, "assertEquals") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertSame(Object, Object, String) + */ + public static void assertSame(Object lhs, Object rhs) { + assertSame(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is the same as {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertSame(Object lhs, Object rhs, String msg) { + if (lhs != rhs) { + msg = Objects.toString(msg, "assertSame") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable) + */ + public static > void assertGTE(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGTE(T lhs, T rhs, String msg) { + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) >= 0)) { + msg = Objects.toString(msg, "assertGreaterThanOrEqual") + + ": expected " + Objects.toString(lhs) + + " >= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThan(Comparable, Comparable) + */ + public static > void assertGT(T lhs, T rhs) { + assertGreaterThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGT(T lhs, T rhs, String msg) { + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGreaterThan(T lhs, T rhs) { + assertGreaterThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) > 0)) { + msg = Objects.toString(msg, "assertGreaterThan") + + ": expected " + Objects.toString(lhs) + + " > " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object) + */ + public static void assertNE(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNE(Object lhs, Object rhs, String msg) { + assertNotEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertNotEquals(Object, Object, String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNotEquals(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is not equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotEquals(Object lhs, Object rhs, String msg) { + if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) { + msg = Objects.toString(msg, "assertNotEquals") + + ": expected " + Objects.toString(lhs) + + " to not equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertNull(Object, String)} with a default message. + * + * @param o The reference assumed to be null. + * @see #assertNull(Object, String) + */ + public static void assertNull(Object o) { + assertNull(o, null); + } + + /** + * Asserts that {@code o} is null. + * + * @param o The reference assumed to be null. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNull(Object o, String msg) { + assertEquals(o, null, msg); + } + + /** + * Calls {@link #assertNotNull(Object, String)} with a default message. + * + * @param o The reference assumed not to be null, + * @see #assertNotNull(Object, String) + */ + public static void assertNotNull(Object o) { + assertNotNull(o, null); + } + + /** + * Asserts that {@code o} is not null. + * + * @param o The reference assumed not to be null, + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotNull(Object o, String msg) { + assertNotEquals(o, null, msg); + } + + /** + * Calls {@link #assertFalse(boolean, String)} with a default message. + * + * @param value The value assumed to be false. + * @see #assertFalse(boolean, String) + */ + public static void assertFalse(boolean value) { + assertFalse(value, null); + } + + /** + * Asserts that {@code value} is {@code false}. + * + * @param value The value assumed to be false. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertFalse(boolean value, String msg) { + if (value) { + msg = Objects.toString(msg, "assertFalse") + + ": expected false, was true"; + fail(msg); + } + } + + /** + * Calls {@link #assertTrue(boolean, String)} with a default message. + * + * @param value The value assumed to be true. + * @see #assertTrue(boolean, String) + */ + public static void assertTrue(boolean value) { + assertTrue(value, null); + } + + /** + * Asserts that {@code value} is {@code true}. + * + * @param value The value assumed to be true. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertTrue(boolean value, String msg) { + if (!value) { + msg = Objects.toString(msg, "assertTrue") + + ": expected true, was false"; + fail(msg); + } + } + + private static > int compare(T lhs, T rhs, String msg) { + if (lhs == null || rhs == null) { + fail(lhs, rhs, msg + ": values must be non-null:", ","); + } + return lhs.compareTo(rhs); + } + + /** + * Returns a string formatted with a message and expected and actual values. + * @param lhs the actual value + * @param rhs the expected value + * @param message the actual value + * @param relation the asserted relationship between lhs and rhs + * @return a formatted string + */ + public static String format(Object lhs, Object rhs, String message, String relation) { + StringBuilder sb = new StringBuilder(80); + if (message != null) { + sb.append(message); + sb.append(' '); + } + sb.append("<"); + sb.append(Objects.toString(lhs)); + sb.append("> "); + sb.append(Objects.toString(relation, ",")); + sb.append(" <"); + sb.append(Objects.toString(rhs)); + sb.append(">"); + return sb.toString(); + } + + /** + * Fail reports a failure with message fail. + * + * @throws RuntimeException always + */ + public static void fail() { + fail("fail"); + } + + /** + * Fail reports a failure with a message. + * @param message for the failure + * @throws RuntimeException always + */ + public static void fail(String message) { + throw new RuntimeException(message); + } + + /** + * Fail reports a failure with a formatted message. + * + * @param lhs the actual value + * @param rhs the expected value + * @param message to be format before the expected and actual values + * @param relation the asserted relationship between lhs and rhs + * @throws RuntimeException always + */ + public static void fail(Object lhs, Object rhs, String message, String relation) { + throw new RuntimeException(format(lhs, rhs, message, relation)); + } + + /** + * Fail reports a failure with a message and a cause. + * @param message to be format before the expected and actual values + * @param cause the exception that caused this failure + * @throws RuntimeException always + */ + public static void fail(String message, Throwable cause) { + throw new RuntimeException(message, cause); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java new file mode 100644 index 00000000000..afabfd7cc52 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +package jdk.testlibrary; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + */ + +public final class CompilerUtils { + private CompilerUtils() { } + + /** + * Compile all the java sources in {@code /**} to + * {@code /**}. The destination directory will be created if + * it doesn't exist. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @return true if the compilation is successful + * + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + */ + public static boolean compile(Path source, Path destination, String ... options) + throws IOException + { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List sources + = Files.find(source, Integer.MAX_VALUE, + (file, attrs) -> (file.toString().endsWith(".java"))) + .collect(Collectors.toList()); + + Files.createDirectories(destination); + jfm.setLocation(StandardLocation.CLASS_PATH, Collections.EMPTY_LIST); + jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, + Arrays.asList(destination)); + + List opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromPaths(sources)); + + return task.call(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java new file mode 100644 index 00000000000..c4815229eb7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java new file mode 100644 index 00000000000..777e8cf5336 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following + * code run {@code jmap -heap} against a process with GC logging turned on for + * the {@code jmap} process: + * + *
    + * {@code
    + * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
    + *                                       .addVMArg("-Xlog:gc*=debug")
    + *                                       .addToolArg("-heap")
    + *                                       .addToolArg(pid);
    + * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
    + * Process p = pb.start();
    + * }
    + * 
    + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class JDKToolLauncher { + private final String executable; + private final List vmArgs = new ArrayList(); + private final List toolArgs = new ArrayList(); + + private JDKToolLauncher(String tool, boolean useCompilerJDK) { + if (useCompilerJDK) { + executable = JDKToolFinder.getJDKTool(tool); + } else { + executable = JDKToolFinder.getTestJDKTool(tool); + } + vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); + } + + /** + * Creates a new JDKToolLauncher for the specified tool. Using tools path + * from the compiler JDK. + * + * @param tool + * The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool, true); + } + + /** + * Creates a new JDKToolLauncher for the specified tool in the Tested JDK. + * + * @param tool + * The name of the tool + * + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher createUsingTestJDK(String tool) { + return new JDKToolLauncher(tool, false); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg + * The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add(arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg + * The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List command = new ArrayList(); + command.add(executable); + // Add -J in front of all vmArgs + for (String arg : vmArgs) { + command.add("-J" + arg); + } + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java new file mode 100644 index 00000000000..839c3228294 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import static jdk.testlibrary.Asserts.*; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class for verifying output and exit value from a {@code Process}. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + * + */ +@Deprecated +public final class OutputAnalyzer { + private final OutputBuffer output; + private final String stdout; + private final String stderr; + private final int exitValue; // useless now. output contains exit value. + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process. + *

    + * OutputAnalyzer should never be instantiated directly - + * use {@linkplain ProcessTools#executeProcess(ProcessBuilder)} instead + * + * @param process + * Process to analyze + * @throws IOException + * If an I/O error occurs. + */ + OutputAnalyzer(Process process) throws IOException { + output = new OutputBuffer(process); + exitValue = -1; + this.stdout = null; + this.stderr = null; + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output. + * + * @param buf + * String buffer to analyze + */ + OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout + * stdout buffer to analyze + * @param stderr + * stderr buffer to analyze + */ + OutputAnalyzer(String stdout, String stderr) { + this.output = null; + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the + * string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer shouldContain(String expectedString) { + if (!getStdout().contains(expectedString) + && !getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stdoutShouldContain(String expectedString) { + if (!getStdout().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stderrShouldContain(String expectedString) { + if (!getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * contain the string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer shouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout: '" + + matcher.group() + "' \n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr: '" + + matcher.group() + "' \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr \n"); + } + return this; + } + + /** + * Get the captured group of the first string matching the pattern. stderr + * is searched before stdout. + * + * @param pattern + * The multi-line pattern to match + * @param group + * The group to capture + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern, int group) { + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. stderr is searched before + * stdout. + * + * @param pattern + * The multi-line pattern to match + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern) { + return firstMatch(pattern, 0); + } + + /** + * Verify the exit value of the process + * + * @param expectedExitValue + * Expected exit value from process + * @throws RuntimeException + * If the exit value from the process did not match the expected + * value + */ + public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Expected to get exit value of [" + + expectedExitValue + "]\n"); + } + return this; + } + + /** + * Report summary that will help to diagnose the problem Currently includes: + * - standard input produced by the process under test - standard output - + * exit code Note: the command line is printed by the ProcessTools + */ + private OutputAnalyzer reportDiagnosticSummary() { + String msg = " stdout: [" + getStdout() + "];\n" + " stderr: [" + getStderr() + + "]\n" + " exitValue = " + getExitValue() + "\n"; + + System.err.println(msg); + return this; + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return getStdout() + getStderr(); + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return output == null ? stdout : output.getStdout(); + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return output == null ? stderr : output.getStderr(); + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return output == null ? exitValue : output.getExitValue(); + } + + + /** + * Print the stdout buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer outputTo(PrintStream out) { + out.println(getStdout()); + return this; + } + + /** + * Print the stderr buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer errorTo(PrintStream out) { + out.println(getStderr()); + return this; + } + + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by system property 'line.separator'. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + List l = new ArrayList<>(); + String[] a = buffer.split(Utils.NEW_LINE); + for (String string : a) { + l.add(string); + } + return l; + } + + /** + * Check if there is a line matching {@code pattern} and return its index + * + * @param pattern Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String pattern) { + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).matches(pattern)) { + return i; + } + } + return -1; + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #stdoutShouldMatchByLine(String, String, String) + */ + public int stdoutShouldMatchByLine(String pattern) { + return stdoutShouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int shouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getOutput(), from, to, pattern); + } + + /** + * Verify that the stdout contents of output buffer matches the + * {@code pattern} line by line. The whole stdout could be matched or + * just a subset of it. + * + * @param from + * The line from where stdout will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where stdout will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int stdoutShouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getStdout(), from, to, pattern); + } + + private int shouldMatchByLine(String buffer, String from, String to, String pattern) { + List lines = asLines(buffer); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + int matchedCount = 0; + for (String line : subList) { + assertTrue(line.matches(pattern), + "The line '" + line + "' does not match pattern '" + pattern + "'"); + matchedCount++; + } + + return matchedCount; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java new file mode 100644 index 00000000000..c8a5d7aab12 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +class OutputBuffer { + private static class OutputBufferException extends RuntimeException { + private static final long serialVersionUID = 8528687792643129571L; + + public OutputBufferException(Throwable cause) { + super(cause); + } + } + + private final Process p; + private final Future outTask; + private final Future errTask; + private final ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + + /** + * Create an OutputBuffer, a class for storing and managing stdout and + * stderr results separately + * + * @param stdout + * stdout result + * @param stderr + * stderr result + */ + OutputBuffer(Process p) { + this.p = p; + StreamPumper outPumper = new StreamPumper(p.getInputStream(), + stdoutBuffer); + StreamPumper errPumper = new StreamPumper(p.getErrorStream(), + stderrBuffer); + + outTask = outPumper.process(); + errTask = errPumper.process(); + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + try { + outTask.get(); + return stdoutBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + try { + errTask.get(); + return stderrBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + public int getExitValue() { + try { + return p.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java new file mode 100644 index 00000000000..523e6e6a074 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; +import java.util.regex.Pattern; +import java.io.RandomAccessFile; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Platform { + private static final String osName = System.getProperty("os.name"); + private static final String dataModel = System.getProperty("sun.arch.data.model"); + private static final String vmVersion = System.getProperty("java.vm.version"); + private static final String jdkDebug = System.getProperty("jdk.debug"); + private static final String osArch = System.getProperty("os.arch"); + private static final String vmName = System.getProperty("java.vm.name"); + private static final String userName = System.getProperty("user.name"); + private static final String compiler = System.getProperty("sun.management.compiler"); + + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } + + public static boolean isGraal() { + return vmName.endsWith(" Graal VM"); + } + + public static boolean isMinimal() { + return vmName.endsWith(" Minimal VM"); + } + + public static boolean isEmbedded() { + return vmName.contains("Embedded"); + } + + public static boolean isTieredSupported() { + return compiler.contains("Tiered Compilers"); + } + + + public static boolean is32bit() { + return dataModel.equals("32"); + } + + public static boolean is64bit() { + return dataModel.equals("64"); + } + + public static boolean isAix() { + return isOs("aix"); + } + + public static boolean isLinux() { + return isOs("linux"); + } + + public static boolean isOSX() { + return isOs("mac"); + } + + public static boolean isSolaris() { + return isOs("sunos"); + } + + public static boolean isWindows() { + return isOs("win"); + } + + private static boolean isOs(String osname) { + return osName.toLowerCase().startsWith(osname.toLowerCase()); + } + + public static String getOsName() { + return osName; + } + + public static boolean isDebugBuild() { + return (jdkDebug.toLowerCase().contains("debug")); + } + + public static String getVMVersion() { + return vmVersion; + } + + // Returns true for sparc and sparcv9. + public static boolean isSparc() { + return isArch("sparc.*"); + } + + public static boolean isARM() { + return isArch("arm.*"); + } + + public static boolean isPPC() { + return isArch("ppc.*"); + } + + public static boolean isX86() { + // On Linux it's 'i386', Windows 'x86' without '_64' suffix. + return isArch("(i386)|(x86(?!_64))"); + } + + public static boolean isX64() { + // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' + return isArch("(amd64)|(x86_64)"); + } + + private static boolean isArch(String archnameRE) { + return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE) + .matcher(osArch) + .matches(); + } + + public static String getOsArch() { + return osArch; + } + + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. + */ + public static boolean shouldSAAttach() + throws IOException { + + if (isAix()) { + return false; // SA not implemented. + } else if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". + */ + public static boolean canPtraceAttachLinux() + throws IOException { + + // SELinux deny_ptrace: + try(RandomAccessFile file = new RandomAccessFile("/sys/fs/selinux/booleans/deny_ptrace", "r")) { + if (file.readByte() != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // YAMA enhanced security ptrace_scope: + // 0 - a process can PTRACE_ATTACH to any other process running under the same uid + // 1 - restricted ptrace: a process must be a children of the inferior or user is root + // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root + // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH + + try(RandomAccessFile file = new RandomAccessFile("/proc/sys/kernel/yama/ptrace_scope", "r")) { + byte yama_scope = file.readByte(); + if (yama_scope == '3') { + return false; + } + + if (!userName.equals("root") && yama_scope != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + public static boolean canAttachOSX() { + return userName.equals("root"); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java new file mode 100644 index 00000000000..35cffc1c994 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; +import java.util.function.Consumer; +import java.util.stream.Collectors; + + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class ProcessTools { + private static final class LineForwarder extends StreamPumper.LinePump { + private final PrintStream ps; + private final String prefix; + LineForwarder(String prefix, PrintStream os) { + this.ps = os; + this.prefix = prefix; + } + @Override + protected void processLine(String line) { + ps.println("[" + prefix + "] " + line); + } + } + + private ProcessTools() { + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + * @param name The process name + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder) + throws IOException { + return startProcess(name, processBuilder, (Consumer)null); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    It is possible to monitor the in-streams via the provided {@code consumer} + * @param name The process name + * @param consumer {@linkplain Consumer} instance to process the in-streams + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + Consumer consumer) + throws IOException { + try { + return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS); + } catch (InterruptedException | TimeoutException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT + *

    + * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, null, linePredicate, timeout, unit); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT and monitor the + * in-streams via the provided {@linkplain Consumer} + *

    + * @param name The process name + * @param processBuilder The process builder + * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Consumer lineConsumer, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" "))); + Process p = processBuilder.start(); + StreamPumper stdout = new StreamPumper(p.getInputStream()); + StreamPumper stderr = new StreamPumper(p.getErrorStream()); + + stdout.addPump(new LineForwarder(name, System.out)); + stderr.addPump(new LineForwarder(name, System.err)); + if (lineConsumer != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + lineConsumer.accept(line); + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } + + + CountDownLatch latch = new CountDownLatch(1); + if (linePredicate != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + if (latch.getCount() > 0 && linePredicate.test(line)) { + latch.countDown(); + } + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } else { + latch.countDown(); + } + final Future stdoutTask = stdout.process(); + final Future stderrTask = stderr.process(); + + try { + if (timeout > -1) { + if (timeout == 0) { + latch.await(); + } else { + if (!latch.await(Utils.adjustTimeout(timeout), unit)) { + throw new TimeoutException(); + } + } + } + } catch (TimeoutException | InterruptedException e) { + System.err.println("Failed to start a process (thread dump follows)"); + for(Map.Entry s : Thread.getAllStackTraces().entrySet()) { + printStack(s.getKey(), s.getValue()); + } + + if (p.isAlive()) { + p.destroyForcibly(); + } + + stdoutTask.cancel(true); + stderrTask.cancel(true); + throw e; + } + + return new ProcessImpl(p, stdoutTask, stderrTask); + } + + /** + *

    Starts a process from its builder.

    + * The default redirects of STDOUT and STDERR are started + *

    + * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT. The warm-up will + * wait indefinitely. + *

    + * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static long getProcessId() { + return ProcessHandle.current().getPid(); + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are + * none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) + throws Exception { + return createJavaProcessBuilder(false, command); + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts + * to the java arguments. + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + + if (addTestVmAndJavaOptions) { + // -cp is needed to make sure the same classpath is used whether the test is + // run in AgentVM mode or OtherVM mode. It was added to the hotspot version + // of this API as part of 8077608. However, for the jdk version it is only + // added when addTestVmAndJavaOptions is true in order to minimize + // disruption to existing JDK tests, which have yet to be tested with -cp + // being added. At some point -cp should always be added to be consistent + // with what the hotspot version does. + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + Collections.addAll(args, Utils.getTestJavaOpts()); + } + + Collections.addAll(args, command); + + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String cmd : args) + cmdLine.append(cmd).append(' '); + System.out.println("Command line: [" + cmdLine.toString() + "]"); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + } + + private static void printStack(Thread t, StackTraceElement[] stack) { + System.out.println("\t" + t + + " stack: (length = " + stack.length + ")"); + if (t != null) { + for (StackTraceElement stack1 : stack) { + System.out.println("\t" + stack1); + } + System.out.println(); + } + } + + /** + * Executes a test java process, waits for it to finish and returns the process output. + * The default options from jtreg, test.vm.opts and test.java.opts, are added. + * The java from the test.jdk is used to execute the command. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * + * The java process will have exited before this method returns. + * + * @param cmds User specifed arguments. + * @return The output from the process. + */ + public static OutputAnalyzer executeTestJava(String... options) throws Exception { + ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(options)); + return executeProcess(pb); + } + + /** + * @deprecated Use executeTestJava instead + */ + public static OutputAnalyzer executeTestJvm(String... options) throws Exception { + return executeTestJava(options); + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) + throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = pb.start(); + if (input != null) { + try (OutputStream os = p.getOutputStream(); + PrintStream ps = new PrintStream(os)) { + ps.print(input); + ps.flush(); + } + } + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The output from the process. + */ + public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + return executeProcess(new ProcessBuilder(cmds)); + } + + /** + * Used to log command line, stdout, stderr and exit code from an executed process. + * @param pb The executed process. + * @param output The output from the process. + */ + public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) { + String stderr = output == null ? "null" : output.getStderr(); + String stdout = output == null ? "null" : output.getStdout(); + String exitValue = output == null ? "null": Integer.toString(output.getExitValue()); + StringBuilder logMsg = new StringBuilder(); + final String nl = System.getProperty("line.separator"); + logMsg.append("--- ProcessLog ---" + nl); + logMsg.append("cmd: " + getCommandLine(pb) + nl); + logMsg.append("exitvalue: " + exitValue + nl); + logMsg.append("stderr: " + stderr + nl); + logMsg.append("stdout: " + stdout + nl); + + return logMsg.toString(); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + if (pb == null) { + return "null"; + } + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString().trim(); + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout, and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(String... cmds) + throws Throwable { + String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout and returns the process output. + * + * The process will have exited before this method returns. + * + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(ProcessBuilder pb) + throws Throwable { + String cmdLine = pb.command().stream().collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + private static class ProcessImpl extends Process { + + private final Process p; + private final Future stdoutTask; + private final Future stderrTask; + + public ProcessImpl(Process p, Future stdoutTask, Future stderrTask) { + this.p = p; + this.stdoutTask = stdoutTask; + this.stderrTask = stderrTask; + } + + @Override + public OutputStream getOutputStream() { + return p.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return p.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return p.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + int rslt = p.waitFor(); + waitForStreams(); + return rslt; + } + + @Override + public int exitValue() { + return p.exitValue(); + } + + @Override + public void destroy() { + p.destroy(); + } + + @Override + public long getPid() { + return p.getPid(); + } + + @Override + public boolean isAlive() { + return p.isAlive(); + } + + @Override + public Process destroyForcibly() { + return p.destroyForcibly(); + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + boolean rslt = p.waitFor(timeout, unit); + if (rslt) { + waitForStreams(); + } + return rslt; + } + + private void waitForStreams() throws InterruptedException { + try { + stdoutTask.get(); + } catch (ExecutionException e) { + } + try { + stderrTask.get(); + } catch (ExecutionException e) { + } + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt new file mode 100644 index 00000000000..c4fd572cd04 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt @@ -0,0 +1 @@ +These files are copies of the corresponding files in test/lib/testlibrary/ from jdk repo. diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java new file mode 100644 index 00000000000..2f3c205db3c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + /** + * Pump will be called by the StreamPumper to process the incoming data + */ + abstract public static class Pump { + abstract void register(StreamPumper d); + } + + /** + * OutputStream -> Pump adapter + */ + final public static class StreamPump extends Pump { + private final OutputStream out; + public StreamPump(OutputStream out) { + this.out = out; + } + + @Override + void register(StreamPumper sp) { + sp.addOutputStream(out); + } + } + + /** + * Used to process the incoming data line-by-line + */ + abstract public static class LinePump extends Pump { + @Override + final void register(StreamPumper sp) { + sp.addLineProcessor(this); + } + + abstract protected void processLine(String line); + } + + private final InputStream in; + private final Set outStreams = new HashSet<>(); + private final Set linePumps = new HashSet<>(); + + private final AtomicBoolean processing = new AtomicBoolean(false); + private final FutureTask processingTask = new FutureTask<>(this, null); + + public StreamPumper(InputStream in) { + this.in = in; + } + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in + * The stream to read from. + * @param out + * The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this(in); + this.addOutputStream(out); + } + + /** + * Implements Thread.run(). Continuously read from {@code in} and write to + * {@code out} until {@code in} has reached end of stream. Abort on + * interruption. Abort on IOExceptions. + */ + @Override + public void run() { + try (BufferedInputStream is = new BufferedInputStream(in)) { + ByteArrayOutputStream lineBos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + int linelen = 0; + + while ((len = is.read(buf)) > 0 && !Thread.interrupted()) { + for(OutputStream out : outStreams) { + out.write(buf, 0, len); + } + if (!linePumps.isEmpty()) { + int i = 0; + int lastcrlf = -1; + while (i < len) { + if (buf[i] == '\n' || buf[i] == '\r') { + int bufLinelen = i - lastcrlf - 1; + if (bufLinelen > 0) { + lineBos.write(buf, lastcrlf + 1, bufLinelen); + } + linelen += bufLinelen; + + if (linelen > 0) { + lineBos.flush(); + final String line = lineBos.toString(); + linePumps.stream().forEach((lp) -> { + lp.processLine(line); + }); + lineBos.reset(); + linelen = 0; + } + lastcrlf = i; + } + + i++; + } + if (lastcrlf == -1) { + lineBos.write(buf, 0, len); + linelen += len; + } else if (lastcrlf < len - 1) { + lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1); + linelen += len - lastcrlf - 1; + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + for(OutputStream out : outStreams) { + try { + out.flush(); + } catch (IOException e) {} + } + try { + in.close(); + } catch (IOException e) {} + } + } + + final void addOutputStream(OutputStream out) { + outStreams.add(out); + } + + final void addLineProcessor(LinePump lp) { + linePumps.add(lp); + } + + final public StreamPumper addPump(Pump ... pump) { + if (processing.get()) { + throw new IllegalStateException("Can not modify pumper while " + + "processing is in progress"); + } + for(Pump p : pump) { + p.register(this); + } + return this; + } + + final public Future process() { + if (!processing.compareAndSet(false, true)) { + throw new IllegalStateException("Can not re-run the processing"); + } + Thread t = new Thread(new Runnable() { + @Override + public void run() { + processingTask.run(); + } + }); + t.setDaemon(true); + t.start(); + + return processingTask; + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java new file mode 100644 index 00000000000..c76339107c8 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2013, 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. + */ + +package jdk.testlibrary; + +import static jdk.testlibrary.Asserts.assertTrue; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import java.util.function.Function; + +/** + * Common library for various test helper functions. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class Utils { + + /** + * Returns the sequence used by operating system to separate lines. + */ + public static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Returns the value of 'test.vm.opts'system property. + */ + public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim(); + + /** + * Returns the value of 'test.java.opts'system property. + */ + public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + + /** + * Returns the value of 'test.timeout.factor' system property + * converted to {@code double}. + */ + public static final double TIMEOUT_FACTOR; + static { + String toFactor = System.getProperty("test.timeout.factor", "1.0"); + TIMEOUT_FACTOR = Double.parseDouble(toFactor); + } + + /** + * Returns the value of JTREG default test timeout in milliseconds + * converted to {@code long}. + */ + public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + + private Utils() { + // Private constructor to prevent class instantiation + } + + /** + * Returns the list of VM options. + * + * @return List of VM options + */ + public static List getVmOptions() { + return Arrays.asList(safeSplitString(VM_OPTIONS)); + } + + /** + * Returns the list of VM options with -J prefix. + * + * @return The list of VM options with -J prefix + */ + public static List getForwardVmOptions() { + String[] opts = safeSplitString(VM_OPTIONS); + for (int i = 0; i < opts.length; i++) { + opts[i] = "-J" + opts[i]; + } + return Arrays.asList(opts); + } + + /** + * Returns the default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @return An array of options, or an empty array if no opptions. + */ + public static String[] getTestJavaOpts() { + List opts = new ArrayList(); + Collections.addAll(opts, safeSplitString(VM_OPTIONS)); + Collections.addAll(opts, safeSplitString(JAVA_OPTIONS)); + return opts.toArray(new String[0]); + } + + /** + * Combines given arguments with default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts + * @return The combination of JTReg test java options and user args. + */ + public static String[] addTestJavaOpts(String... userArgs) { + List opts = new ArrayList(); + Collections.addAll(opts, getTestJavaOpts()); + Collections.addAll(opts, userArgs); + return opts.toArray(new String[0]); + } + + /** + * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". + * Removes any options matching: -XX:(+/-)Use*GC + * Used when a test need to set its own GC version. Then any + * GC specified by the framework must first be removed. + * @return A copy of given opts with all GC options removed. + */ + private static final Pattern useGcPattern = Pattern.compile( + "(?:\\-XX\\:[\\+\\-]Use.+GC)" + + "|(?:\\-Xconcgc)"); + public static List removeGcOpts(List opts) { + List optsWithoutGC = new ArrayList(); + for (String opt : opts) { + if (useGcPattern.matcher(opt).matches()) { + System.out.println("removeGcOpts: removed " + opt); + } else { + optsWithoutGC.add(opt); + } + } + return optsWithoutGC; + } + + /** + * Splits a string by white space. + * Works like String.split(), but returns an empty array + * if the string is null or empty. + */ + private static String[] safeSplitString(String s) { + if (s == null || s.trim().isEmpty()) { + return new String[] {}; + } + return s.trim().split("\\s+"); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString(); + } + + /** + * Returns the free port on the local host. + * The function will spin until a valid port number is found. + * + * @return The port number + * @throws InterruptedException if any thread has interrupted the current thread + * @throws IOException if an I/O error occurs when opening the socket + */ + public static int getFreePort() throws InterruptedException, IOException { + int port = -1; + + while (port <= 0) { + Thread.sleep(100); + + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(0); + port = serverSocket.getLocalPort(); + } finally { + serverSocket.close(); + } + } + + return port; + } + + /** + * Returns the name of the local host. + * + * @return The host name + * @throws UnknownHostException if IP address of a host could not be determined + */ + public static String getHostname() throws UnknownHostException { + InetAddress inetAddress = InetAddress.getLocalHost(); + String hostName = inetAddress.getHostName(); + + assertTrue((hostName != null && !hostName.isEmpty()), + "Cannot get hostname"); + + return hostName; + } + + /** + * Uses "jcmd -l" to search for a jvm pid. This function will wait + * forever (until jtreg timeout) for the pid to be found. + * @param key Regular expression to search for + * @return The found pid. + */ + public static int waitForJvmPid(String key) throws Throwable { + final long iterationSleepMillis = 250; + System.out.println("waitForJvmPid: Waiting for key '" + key + "'"); + System.out.flush(); + while (true) { + int pid = tryFindJvmPid(key); + if (pid >= 0) { + return pid; + } + Thread.sleep(iterationSleepMillis); + } + } + + /** + * Searches for a jvm pid in the output from "jcmd -l". + * + * Example output from jcmd is: + * 12498 sun.tools.jcmd.JCmd -l + * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar + * + * @param key A regular expression to search for. + * @return The found pid, or -1 if Enot found. + * @throws Exception If multiple matching jvms are found. + */ + public static int tryFindJvmPid(String key) throws Throwable { + OutputAnalyzer output = null; + try { + JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd"); + jcmdLauncher.addToolArg("-l"); + output = ProcessTools.executeProcess(jcmdLauncher.getCommand()); + output.shouldHaveExitValue(0); + + // Search for a line starting with numbers (pid), follwed by the key. + Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n"); + Matcher matcher = pattern.matcher(output.getStdout()); + + int pid = -1; + if (matcher.find()) { + pid = Integer.parseInt(matcher.group(1)); + System.out.println("findJvmPid.pid: " + pid); + if (matcher.find()) { + throw new Exception("Found multiple JVM pids for key: " + key); + } + } + return pid; + } catch (Throwable t) { + System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t)); + throw t; + } + } + + /** + * Adjusts the provided timeout value for the TIMEOUT_FACTOR + * @param tOut the timeout value to be adjusted + * @return The timeout value adjusted for the value of "test.timeout.factor" + * system property + */ + public static long adjustTimeout(long tOut) { + return Math.round(tOut * Utils.TIMEOUT_FACTOR); + } + + /** + * Wait for condition to be true + * + * @param condition, a condition to wait for + */ + public static final void waitForCondition(BooleanSupplier condition) { + waitForCondition(condition, -1L, 100L); + } + + /** + * Wait until timeout for condition to be true + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true + * specifying -1 will wait forever + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout) { + return waitForCondition(condition, timeout, 100L); + } + + /** + * Wait until timeout for condition to be true for specified time + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true, + * specifying -1 will wait forever + * @param sleepTime a time to sleep value in milliseconds + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout, long sleepTime) { + long startTime = System.currentTimeMillis(); + while (!(condition.getAsBoolean() || (timeout != -1L + && ((System.currentTimeMillis() - startTime) > timeout)))) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } + return condition.getAsBoolean(); + } + + /** + * Interface same as java.lang.Runnable but with + * method {@code run()} able to throw any Throwable. + */ + public static interface ThrowingRunnable { + void run() throws Throwable; + } + + /** + * Filters out an exception that may be thrown by the given + * test according to the given filter. + * + * @param test - method that is invoked and checked for exception. + * @param filter - function that checks if the thrown exception matches + * criteria given in the filter's implementation. + * @return - exception that matches the filter if it has been thrown or + * {@code null} otherwise. + * @throws Throwable - if test has thrown an exception that does not + * match the filter. + */ + public static Throwable filterException(ThrowingRunnable test, + Function filter) throws Throwable { + try { + test.run(); + } catch (Throwable t) { + if (filter.apply(t)) { + return t; + } else { + throw t; + } + } + return null; + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java new file mode 100644 index 00000000000..c3403f9d1d0 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static jdk.testlibrary.ProcessTools.executeTestJava; +import jdk.testlibrary.CompilerUtils; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng BasicModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib can instantiate the following interfaces + * with customized provider module on boot layer + * + * javax.xml.datatype.DatatypeFactory + * javax.xml.parsers.DocumentBuilderFactory + * javax.xml.parsers.SAXParserFactory + * javax.xml.stream.XMLEventFactory + * javax.xml.stream.XMLInputFactory + * javax.xml.stream.XMLOutputFactory + * javax.xml.transform.TransformerFactory + * javax.xml.validation.SchemaFactory + * javax.xml.xpath.XPathFactory + */ + +@Test +public class BasicModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + private static final Path CLASSES_DIR = Paths.get("classes"); + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("unnamed"), CLASSES_DIR)); + } + + /* + * test the default JAXP implementation + */ + public void testDefault() throws Exception { + int exitValue + = executeTestJava("-cp", CLASSES_DIR.toString(), + "Main") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading one provider module + */ + public void testWithOneProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading both provider modules + */ + public void testWithTwoProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString() + File.pathSeparator + MOD_DIR2.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1", "xmlprovider2") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java new file mode 100644 index 00000000000..45f24001278 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.module.ModuleFinder.empty; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.lang.ClassLoader; +import java.lang.String; +import java.lang.System; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.reflect.Layer; +import java.lang.reflect.Method; +import java.lang.reflect.Module; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import jdk.testlibrary.CompilerUtils; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng LayerModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib works with layer and TCCL + */ + +@Test +public class LayerModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + + /* + * services provided by provider1 + */ + private static final String[] services1 = { "javax.xml.parsers.DocumentBuilderFactory", + "javax.xml.parsers.SAXParserFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + + /* + * services provided by provider2 + */ + private static final String[] services2 = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.stream.XMLEventFactory" }; + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR1.resolve("test"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR2.resolve("test"))); + } + + /* + * layer 1 is created on top of boot layer, layer1 includes module provider1. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the other services are loaded from boot layer + */ + public void testOneLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + ClassLoader cl1 = layer1.findLoader("test"); + + Method m = cl1.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, Layer.boot()); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1 and provider2. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayerWithDuplicate() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1, MOD_DIR2); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java new file mode 100644 index 00000000000..9a1caa4e1f9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module test { + requires java.xml; + exports test; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java new file mode 100644 index 00000000000..6dfaec5cedf --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.Class; +import java.lang.String; +import java.lang.System; +import java.util.Iterator; +import java.util.ServiceLoader; + +public class XMLFactoryHelper { + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + public static Object instantiateXMLService(String serviceName) throws Exception { + ClassLoader backup = Thread.currentThread().getContextClassLoader(); + try { + // set thread context class loader to module class loader + Thread.currentThread().setContextClassLoader(XMLFactoryHelper.class.getClassLoader()); + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } finally { + Thread.currentThread().setContextClassLoader(backup); + } + + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java new file mode 100644 index 00000000000..cb0a37e916b --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.reflect.Layer; +import java.lang.reflect.Module; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +public class Main { + /* + * @param args, the names of provider modules, which have been loaded + */ + public static void main(String[] args) throws Exception { + Module xml = Layer.boot().findModule("java.xml").get(); + + Set allServices = new HashSet<>(Arrays.asList(expectedAllServices)); + if (!allServices.equals(xml.getDescriptor().uses())) + throw new AssertionError("Expect xml module uses: " + allServices + " But actually uses: " + + xml.getDescriptor().uses()); + + long violationCount = Stream.of(args) + .map(xmlProviderName -> Layer.boot().findModule(xmlProviderName).get()) + .mapToLong( + // services provided by the implementation in provider module + provider -> provider.getDescriptor().provides().keySet().stream() + .filter(serviceName -> { + allServices.remove(serviceName); // remove service provided by + // customized module from allServices + return !belongToModule(serviceName, instantiateXMLService(serviceName), provider); + }).count()) + .sum(); + + // the remaining services should be provided by the default implementation + violationCount += allServices.stream() + .filter(serviceName -> !belongToModule(serviceName, instantiateXMLService(serviceName), xml)) + .count(); + + if (violationCount > 0) + throw new AssertionError(violationCount + " services are not provided by expected module"); + } + + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + private static Object instantiateXMLService(String serviceName) { + try { + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } catch (Exception e) { + e.printStackTrace(System.err); + throw new RuntimeException(e); + } + } + + /* + * verify which module provides the xml factory + */ + private static boolean belongToModule(String factoryName, Object factory, Module expected) { + Module actual = factory.getClass().getModule(); + if (!actual.equals(expected)) { + System.err.println("Expect " + factoryName + " is provided by " + expected + + ", but actual implementation " + factory.getClass() + " is provided by " + actual); + return false; + } else { + System.out.println(factory.getClass() + " is provided by " + expected); + return true; + } + } + + /* + * This list equals the declarations in java.xml module-info.java + */ + private static final String[] expectedAllServices = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.parsers.DocumentBuilderFactory", "javax.xml.parsers.SAXParserFactory", + "javax.xml.stream.XMLEventFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java new file mode 100644 index 00000000000..5a5b1b01447 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module xmlprovider1 { + requires java.xml; + + provides javax.xml.parsers.DocumentBuilderFactory with xp1.DocumentBuilderFactoryImpl; + provides javax.xml.parsers.SAXParserFactory with xp1.SAXParserFactoryImpl; + provides javax.xml.stream.XMLInputFactory with xp1.XMLInputFactoryImpl; + provides javax.xml.stream.XMLOutputFactory with xp1.XMLOutputFactoryImpl; + provides javax.xml.transform.TransformerFactory with xp1.TransformerFactoryImpl; + provides javax.xml.validation.SchemaFactory with xp1.SchemaFactoryImpl; + provides javax.xml.xpath.XPathFactory with xp1.XPathFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java new file mode 100644 index 00000000000..7e302b9630c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { + + @Override + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + return null; + } + + @Override + public void setAttribute(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java new file mode 100644 index 00000000000..5d4ce0602f3 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +public class SAXParserFactoryImpl extends SAXParserFactory { + + @Override + public SAXParser newSAXParser() throws ParserConfigurationException, SAXException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException, + SAXNotRecognizedException, SAXNotSupportedException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java new file mode 100644 index 00000000000..ca0cb3be8c7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; + +public class SchemaFactoryImpl extends SchemaFactory { + + @Override + public boolean isSchemaLanguageSupported(String schemaLanguage) { + // must be true, otherwise JAXP library will deny this impl + if (schemaLanguage.equals(W3C_XML_SCHEMA_NS_URI)) + return true; + else + return false; + } + + @Override + public void setErrorHandler(ErrorHandler errorHandler) { + + } + + @Override + public ErrorHandler getErrorHandler() { + return null; + } + + @Override + public void setResourceResolver(LSResourceResolver resourceResolver) { + + } + + @Override + public LSResourceResolver getResourceResolver() { + return null; + } + + @Override + public Schema newSchema(Source[] schemas) throws SAXException { + return null; + } + + @Override + public Schema newSchema() throws SAXException { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java new file mode 100644 index 00000000000..0feabb6b21f --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; + +public class TransformerFactoryImpl extends TransformerFactory { + + @Override + public Transformer newTransformer(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Transformer newTransformer() throws TransformerConfigurationException { + return null; + } + + @Override + public Templates newTemplates(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Source getAssociatedStylesheet(Source source, String media, String title, String charset) + throws TransformerConfigurationException { + return null; + } + + @Override + public void setURIResolver(URIResolver resolver) { + + } + + @Override + public URIResolver getURIResolver() { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws TransformerConfigurationException { + + } + + @Override + public boolean getFeature(String name) { + return false; + } + + @Override + public void setAttribute(String name, Object value) { + + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public void setErrorListener(ErrorListener listener) { + + } + + @Override + public ErrorListener getErrorListener() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java new file mode 100644 index 00000000000..de4f6cbe075 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import java.io.InputStream; +import java.io.Reader; + +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; + +public class XMLInputFactoryImpl extends XMLInputFactory { + + @Override + public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, InputStream stream) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream, String encoding) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLResolver getXMLResolver() { + return null; + } + + @Override + public void setXMLResolver(XMLResolver resolver) { + + } + + @Override + public XMLReporter getXMLReporter() { + return null; + } + + @Override + public void setXMLReporter(XMLReporter reporter) { + + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + + @Override + public void setEventAllocator(XMLEventAllocator allocator) { + + } + + @Override + public XMLEventAllocator getEventAllocator() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java new file mode 100644 index 00000000000..7042ca1af60 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; + +public class XMLOutputFactoryImpl extends XMLOutputFactory { + + @Override + public XMLStreamWriter createXMLStreamWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java new file mode 100644 index 00000000000..bf5aa7aa20e --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp1; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathVariableResolver; + +public class XPathFactoryImpl extends XPathFactory { + + @Override + public boolean isObjectModelSupported(String objectModel) { + // must be true, otherwise JAXP library will deny this impl + return true; + } + + @Override + public void setFeature(String name, boolean value) throws XPathFactoryConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws XPathFactoryConfigurationException { + return false; + } + + @Override + public void setXPathVariableResolver(XPathVariableResolver resolver) { + + } + + @Override + public void setXPathFunctionResolver(XPathFunctionResolver resolver) { + + } + + @Override + public XPath newXPath() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java new file mode 100644 index 00000000000..d55645e58e9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +module xmlprovider2 { + requires java.xml; + + provides javax.xml.datatype.DatatypeFactory with xp2.DatatypeFactoryImpl; + provides javax.xml.stream.XMLEventFactory with xp2.XMLEventFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java new file mode 100644 index 00000000000..e4a38886dcc --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp2; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; + +public class DatatypeFactoryImpl extends DatatypeFactory { + + @Override + public Duration newDuration(String lexicalRepresentation) { + return null; + } + + @Override + public Duration newDuration(long durationInMilliSeconds) { + return null; + } + + @Override + public Duration newDuration(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, + BigInteger hours, BigInteger minutes, BigDecimal seconds) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar() { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int month, int day, int hour, + int minute, int second, BigDecimal fractionalSecond, int timezone) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java new file mode 100644 index 00000000000..e4e89c8383b --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package xp2; + +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.Comment; +import javax.xml.stream.events.DTD; +import javax.xml.stream.events.EndDocument; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.EntityDeclaration; +import javax.xml.stream.events.EntityReference; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.ProcessingInstruction; +import javax.xml.stream.events.StartDocument; +import javax.xml.stream.events.StartElement; + +public class XMLEventFactoryImpl extends XMLEventFactory { + + @Override + public void setLocation(Location location) { + + } + + @Override + public Attribute createAttribute(String prefix, String namespaceURI, String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(QName name, String value) { + return null; + } + + @Override + public Namespace createNamespace(String namespaceURI) { + return null; + } + + @Override + public Namespace createNamespace(String prefix, String namespaceUri) { + return null; + } + + @Override + public StartElement createStartElement(QName name, Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces, NamespaceContext context) { + return null; + } + + @Override + public EndElement createEndElement(QName name, Iterator namespaces) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName, + Iterator namespaces) { + return null; + } + + @Override + public Characters createCharacters(String content) { + return null; + } + + @Override + public Characters createCData(String content) { + return null; + } + + @Override + public Characters createSpace(String content) { + return null; + } + + @Override + public Characters createIgnorableSpace(String content) { + return null; + } + + @Override + public StartDocument createStartDocument() { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version, boolean standalone) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding) { + return null; + } + + @Override + public EndDocument createEndDocument() { + return null; + } + + @Override + public EntityReference createEntityReference(String name, EntityDeclaration declaration) { + return null; + } + + @Override + public Comment createComment(String text) { + return null; + } + + @Override + public ProcessingInstruction createProcessingInstruction(String target, String data) { + return null; + } + + @Override + public DTD createDTD(String dtd) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/TEST.properties b/jaxp/test/javax/xml/jaxp/module/TEST.properties new file mode 100644 index 00000000000..85a3ae5f5c7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/TEST.properties @@ -0,0 +1,5 @@ +# Tests that must run in othervm mode +othervm.dirs= . + +# Declare module dependency +modules=java.xml From 1d0549f73ee2a3ea57234c3da05507b8ef22f4b5 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:03 -0700 Subject: [PATCH 151/167] Added tag jdk-9+115 for changeset 4fbd14764fa7 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index e13ddc6f1e0..06edc4a1f53 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -357,3 +357,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 03543a758cd5890f2266e4b9678378a925dde22a jdk-9+112 55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113 1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114 +09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115 From 9fe8b397dd0cbb96e395e8e5a65115ce4a0bf27d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:05 -0700 Subject: [PATCH 152/167] Added tag jdk-9+115 for changeset 5daa5fbad3ce --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index df49fd73654..dd25acb220b 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -357,3 +357,4 @@ b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 780d0620add32bf545471cf65038c9ac6d9c036d jdk-9+112 cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114 +7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115 From 4fff4771e0f3d61201adaba003ac602ba3d66fd6 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:06 -0700 Subject: [PATCH 153/167] Added tag jdk-9+115 for changeset a936b4e01afb --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 472e5185290..11405727ce0 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -517,3 +517,4 @@ c558850fac5750d8ca98a45180121980f57cdd28 jdk-9+111 76582e8dc9e6374e4f99ab797c8d364b6e9449b4 jdk-9+112 c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 +88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115 From 2c681d330ed0750bf357c8ba6afae5accb279f4d Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:09 -0700 Subject: [PATCH 154/167] Added tag jdk-9+115 for changeset 04a4a89d81b9 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 99d74713f24..07b1b9985f7 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -357,3 +357,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 36326537f929d20cc5885b93939f90c0efcc4681 jdk-9+112 28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113 147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114 +1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115 From ae0df303d1080640613cfb775148828aff5b03dc Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:17 -0700 Subject: [PATCH 155/167] Added tag jdk-9+115 for changeset e9c85d2b1fcc --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 5d1fa7fb250..78e30d77611 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -348,3 +348,4 @@ cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 c261f8440c5578b34596e6b0419a81aec431a884 jdk-9+112 a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113 ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114 +295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115 From 2ee49b78fe6ac31d4fb992adaad702333d85c2a9 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Fri, 22 Apr 2016 10:46:08 +0200 Subject: [PATCH 156/167] 8154867: PPC64: Better byte behavior Reviewed-by: goetz --- .../src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp | 5 +- hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp | 40 +++++++++++++ hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp | 2 + .../vm/templateInterpreterGenerator_ppc.cpp | 12 +++- .../src/cpu/ppc/vm/templateTable_ppc_64.cpp | 60 +++++++++++++++++-- 5 files changed, 111 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index cba04106f8c..0d1cb4711bd 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -360,7 +360,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -407,7 +407,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark. post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 9c7128da0b4..cedc1e08c1c 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -169,6 +169,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state, Register Rsc case ltos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: lwz(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); @@ -294,6 +295,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -309,6 +311,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -749,6 +752,43 @@ void InterpreterMacroAssembler::merge_frames(Register Rsender_sp, Register retur stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP } +void InterpreterMacroAssembler::narrow(Register result) { + Register ret_type = R11_scratch1; + ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); + lbz(ret_type, in_bytes(ConstMethod::result_type_offset()), R11_scratch1); + + Label notBool, notByte, notChar, done; + + // common case first + cmpwi(CCR0, ret_type, T_INT); + beq(CCR0, done); + + cmpwi(CCR0, ret_type, T_BOOLEAN); + bne(CCR0, notBool); + andi(result, result, 0x1); + b(done); + + bind(notBool); + cmpwi(CCR0, ret_type, T_BYTE); + bne(CCR0, notByte); + extsb(result, result); + b(done); + + bind(notByte); + cmpwi(CCR0, ret_type, T_CHAR); + bne(CCR0, notChar); + andi(result, result, 0xffff); + b(done); + + bind(notChar); + // cmpwi(CCR0, ret_type, T_SHORT); // all that's left + // bne(CCR0, done); + extsh(result, result); + + // Nothing to do for T_INT + bind(done); +} + // Remove activation. // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp index 8a75af011bd..05bd3aa0bdd 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -140,6 +140,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cpool_and_tags(Register Rcpool, Register Rtags); void is_a(Label& L); + void narrow(Register result); + // Java Call Helpers void call_from_interpreter(Register Rtarget_method, Register Rret_addr, Register Rscratch1, Register Rscratch2); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 8979e213acf..3602c646192 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -655,6 +655,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -701,6 +702,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -2092,12 +2094,14 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state // Copied from TemplateTable::_return. // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2157,6 +2161,10 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) { bname = "trace_code_btos {"; tsize = 2; break; + case ztos: + bname = "trace_code_ztos {"; + tsize = 2; + break; case ctos: bname = "trace_code_ctos {"; tsize = 2; diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index c59e7b4b38b..6b8f658ff09 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -170,6 +170,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg switch (new_bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -981,9 +982,21 @@ void TemplateTable::bastore() { Rarray = R12_scratch2, Rscratch = R3_ARG1; __ pop_i(Rindex); + __ pop_ptr(Rarray); // tos: val - // Rarray: array ptr (popped by index_check) - __ index_check(Rarray, Rindex, 0, Rscratch, Rarray); + + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(Rscratch, Rarray); + __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); + int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); + __ testbitdi(CCR0, R0, Rscratch, diffbit); + Label L_skip; + __ bfalse(CCR0, L_skip); + __ andi(R17_tos, R17_tos, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + + __ index_check_without_pop(Rarray, Rindex, 0, Rscratch, Rarray); __ stb(R17_tos, arrayOopDesc::base_offset_in_bytes(T_BYTE), Rarray); } @@ -2108,12 +2121,16 @@ void TemplateTable::_return(TosState state) { __ remove_activation(state, /* throw_monitor_exception */ true); // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2518,6 +2535,21 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ beq(CCR6, Lacquire); // Volatile? __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. + // __ bind(Lztos); (same code as btos) + __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ lbzx(R17_tos, Rclass_or_obj, Roffset); + __ extsb(R17_tos, R17_tos); + __ push(ztos); + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, Rbc, Rscratch); + } + __ beq(CCR6, Lacquire); // Volatile? + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. // __ bind(Lctos); __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2618,6 +2650,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ push_ptr(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ push_i(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_lputfield: __ push_l(); offs+=2*Interpreter::stackElementSize; break; @@ -2658,6 +2691,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ pop_ptr(); break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ pop_i(); break; case Bytecodes::_fast_lputfield: __ pop_l(); break; @@ -2824,6 +2858,21 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. + // __ bind(Lztos); + __ release(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ pop(ztos); + if (!is_static) { pop_and_check_object(Rclass_or_obj); } // Kills R11_scratch1. + __ andi(R17_tos, R17_tos, 0x1); + __ stbx(R17_tos, Rclass_or_obj, Roffset); + if (!is_static) { patch_bytecode(Bytecodes::_fast_zputfield, Rbc, Rscratch, true, byte_no); } + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + __ beq(CR_is_vol, Lvolatile); // Volatile? + } + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. // __ bind(Lctos); __ release(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2949,6 +2998,9 @@ void TemplateTable::fast_storefield(TosState state) { __ stdx(R17_tos, Rclass_or_obj, Roffset); break; + case Bytecodes::_fast_zputfield: + __ andi(R17_tos, R17_tos, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ stbx(R17_tos, Rclass_or_obj, Roffset); break; From f2c59f97ce65dd3c7eb879bfaa085e2ec8799e76 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Fri, 22 Apr 2016 10:48:12 +0200 Subject: [PATCH 157/167] 8154326: bash >(...) construct causes race conditions Reviewed-by: tbell, ihse --- make/InitSupport.gmk | 2 +- make/common/MakeBase.gmk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 493591ebbec..cee30522d33 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -331,7 +331,7 @@ else # $(HAS_SPEC)=true BUILD_LOG := $(OUTPUT_ROOT)/build.log BUILD_TRACE_LOG := $(OUTPUT_ROOT)/build-trace-time.log - BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) + BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait # Sanity check the spec file, so it matches this source code define CheckSpecSanity diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 6f1f00b99d5..f159b8fca63 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -706,10 +706,10 @@ endif ExecuteWithLog = \ $(call LogCmdlines, Exececuting: [$(strip $2)]) \ $(call WriteFile, $2, $(strip $1).cmdline) \ - ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ + ( ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ ( exitcode=$(DOLLAR)? && \ $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).log && \ - exit $(DOLLAR)exitcode ) ) + exit $(DOLLAR)exitcode ) ) && wait ) ################################################################################ # Find lib dir for module From 911f4b1664c6b7f6d2c2208c8f3ae052ea170aa7 Mon Sep 17 00:00:00 2001 From: Nadeesh TV Date: Mon, 25 Apr 2016 09:37:43 +0000 Subject: [PATCH 158/167] 8031085: DateTimeFormatter won't parse dates with custom format "yyyyMMddHHmmssSSS" Changed the FractionPrinterParser to subclass of NumberPrinterParser to make it participate in adjacent value parsing Reviewed-by: rriggs, scolebourne --- .../time/format/DateTimeFormatterBuilder.java | 81 ++++++++++++++++--- .../format/TCKDateTimeFormatterBuilder.java | 18 ++++- 2 files changed, 85 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index e8ca3f1e99f..a36d1b5e142 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -667,8 +667,11 @@ public final class DateTimeFormatterBuilder { * No rounding occurs due to the maximum width - digits are simply dropped. *

    * When parsing in strict mode, the number of parsed digits must be between - * the minimum and maximum width. When parsing in lenient mode, the minimum - * width is considered to be zero and the maximum is nine. + * the minimum and maximum width. In strict mode, if the minimum and maximum widths + * are equal and there is no decimal point then the parser will + * participate in adjacent value parsing, see + * {@link appendValue(java.time.temporal.TemporalField, int)}. When parsing in lenient mode, + * the minimum width is considered to be zero and the maximum is nine. *

    * If the value cannot be obtained then an exception will be thrown. * If the value is negative an exception will be thrown. @@ -687,7 +690,12 @@ public final class DateTimeFormatterBuilder { */ public DateTimeFormatterBuilder appendFraction( TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { - appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + if (minWidth == maxWidth && decimalPoint == false) { + // adjacent parsing + appendValue(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } else { + appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } return this; } @@ -2925,11 +2933,8 @@ public final class DateTimeFormatterBuilder { /** * Prints and parses a numeric date-time field with optional padding. */ - static final class FractionPrinterParser implements DateTimePrinterParser { - private final TemporalField field; - private final int minWidth; - private final int maxWidth; - private final boolean decimalPoint; + static final class FractionPrinterParser extends NumberPrinterParser { + private final boolean decimalPoint; /** * Constructor. @@ -2940,6 +2945,7 @@ public final class DateTimeFormatterBuilder { * @param decimalPoint whether to output the localized decimal point symbol */ FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { + this(field, minWidth, maxWidth, decimalPoint, 0); Objects.requireNonNull(field, "field"); if (field.range().isFixed() == false) { throw new IllegalArgumentException("Field must have a fixed set of values: " + field); @@ -2954,12 +2960,61 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " + maxWidth + " < " + minWidth); } - this.field = field; - this.minWidth = minWidth; - this.maxWidth = maxWidth; + } + + /** + * Constructor. + * + * @param field the field to output, not null + * @param minWidth the minimum width to output, from 0 to 9 + * @param maxWidth the maximum width to output, from 0 to 9 + * @param decimalPoint whether to output the localized decimal point symbol + * @param subsequentWidth the subsequentWidth for this instance + */ + FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; } + /** + * Returns a new instance with fixed width flag set. + * + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withFixedWidth() { + if (subsequentWidth == -1) { + return this; + } + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, -1); + } + + /** + * Returns a new instance with an updated subsequent width. + * + * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withSubsequentWidth(int subsequentWidth) { + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, this.subsequentWidth + subsequentWidth); + } + + /** + * For FractionPrinterPrinterParser, the width is fixed if context is sttrict, + * minWidth equal to maxWidth and decimalpoint is absent. + * @param context the context + * @return if the field is fixed width + * @see DateTimeFormatterBuilder#appendValueFraction(java.time.temporal.TemporalField, int, int, boolean) + */ + @Override + boolean isFixedWidth(DateTimeParseContext context) { + if (context.isStrict() && minWidth == maxWidth && decimalPoint == false) { + return true; + } + return false; + } + @Override public boolean format(DateTimePrintContext context, StringBuilder buf) { Long value = context.getValue(field); @@ -2992,8 +3047,8 @@ public final class DateTimeFormatterBuilder { @Override public int parse(DateTimeParseContext context, CharSequence text, int position) { - int effectiveMin = (context.isStrict() ? minWidth : 0); - int effectiveMax = (context.isStrict() ? maxWidth : 9); + int effectiveMin = (context.isStrict() || isFixedWidth(context) ? minWidth : 0); + int effectiveMax = (context.isStrict() || isFixedWidth(context) ? maxWidth : 9); int length = text.length(); if (position == length) { // valid if whole field is optional, invalid if minimum width diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 2fde35b5e2c..14d7e0359d4 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -71,6 +71,7 @@ import static org.testng.Assert.assertEquals; import java.text.ParsePosition; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.YearMonth; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -930,7 +931,7 @@ public class TCKDateTimeFormatterBuilder { @Test public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { - // succeeds because hour/min are fixed width + // succeeds because hour, min and fraction of seconds are fixed width DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); ParsePosition pp = new ParsePosition(0); TemporalAccessor parsed = f.parseUnresolved("1230", pp); @@ -940,6 +941,21 @@ public class TCKDateTimeFormatterBuilder { assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); } + @DataProvider(name="adjacentFractionParseData") + Object[][] data_adjacent_fraction_parse() { + return new Object[][] { + {"20130812214600025", "yyyyMMddHHmmssSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25000000)}, + {"201308122146000256", "yyyyMMddHHmmssSSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25600000)}, + }; + } + + @Test(dataProvider = "adjacentFractionParseData") + public void test_adjacent_fraction(String input, String pattern, LocalDateTime expected) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern); + LocalDateTime actual = LocalDateTime.parse(input, dtf); + assertEquals(actual, expected); + } + @DataProvider(name="lenientOffsetParseData") Object[][] data_lenient_offset_parse() { return new Object[][] { From f4d962e735d90915da9095586b29f2bf671b92e8 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 159/167] 8147426: Missing definition for JIMAGE_NOT_FOUND Reviewed-by: hseigel, alanb --- jdk/src/java.base/share/native/libjimage/jimage.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp index d215e30c2ab..f3371204ec7 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.hpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp @@ -37,11 +37,13 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes +// Resource was not found +#define JIMAGE_NOT_FOUND (0) // The image file is not prefixed with 0xCAFEDADA #define JIMAGE_BAD_MAGIC (-1) // The image file does not have a compatible (translatable) version From 5013b6458071350c568b81cd57bf4ed25b4839ae Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 160/167] 8147634: Need a JImage API that given a JImageLocationRef returns class name Reviewed-by: hseigel --- jdk/make/lib/CoreLibraries.gmk | 2 +- jdk/make/mapfiles/libjimage/mapfile-vers | 1 + .../share/native/libjimage/jimage.cpp | 25 ++++++++++++++++++- .../share/native/libjimage/jimage.hpp | 17 +++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index e4a24e47904..3cb135253ea 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -267,7 +267,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ -export:JIMAGE_PackageToModule \ -export:JIMAGE_FindResource -export:JIMAGE_GetResource \ - -export:JIMAGE_ResourceIterator, \ + -export:JIMAGE_ResourceIterator -export:JIMAGE_ResourcePath, \ LIBS_unix := -ljvm -ldl $(LIBCXX), \ LIBS_solaris := -lc, \ LIBS_macosx := -lc++, \ diff --git a/jdk/make/mapfiles/libjimage/mapfile-vers b/jdk/make/mapfiles/libjimage/mapfile-vers index 48eac21b53a..a4de5f82f3c 100644 --- a/jdk/make/mapfiles/libjimage/mapfile-vers +++ b/jdk/make/mapfiles/libjimage/mapfile-vers @@ -34,6 +34,7 @@ SUNWprivate_1.1 { JIMAGE_FindResource; JIMAGE_GetResource; JIMAGE_ResourceIterator; + JIMAGE_ResourcePath; local: *; }; diff --git a/jdk/src/java.base/share/native/libjimage/jimage.cpp b/jdk/src/java.base/share/native/libjimage/jimage.cpp index 4816a173be9..0c12facbc4d 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.cpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp @@ -207,7 +207,30 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* image, if (!(*visitor)(image, module, "9", parent, base, extension, arg)) { break; } - } } +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max) { + ImageFileReader* imageFile = (ImageFileReader*) image; + + u4 offset = (u4) locationRef; + if (offset >= imageFile->locations_size()) { + return false; + } + + ImageLocation location(imageFile->get_location_offset_data(offset)); + imageFile->location_path(location, path, max); + + return true; +} diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp index f3371204ec7..637f1689e49 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.hpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp @@ -186,3 +186,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + From 80b4b623c7b292ca84e8795f37a0f26f37ad8f13 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 161/167] 8082537: jimage should print usage when started with no args Reviewed-by: alanb --- .../jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 44a6bcc4ce3..105e8f61b44 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -152,6 +152,11 @@ class JImageTask { setLog(new PrintWriter(System.out)); } + if (args.length == 0) { + log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + return EXIT_ABNORMAL; + } + try { List unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { From 58b1ba941edb7bbc991194e2d4b660e0f49964b3 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 162/167] 8153930: Compiler crashed (intermittently) Reviewed-by: redestad, alanb --- .../jdk/internal/jimage/ImageReader.java | 829 ++++++++++-------- .../jdk/internal/jrtfs/JrtFileSystem.java | 12 +- .../jdk/internal/jrtfs/SystemImage.java | 4 +- 3 files changed, 479 insertions(+), 366 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index 41a51b88acf..2c78ea9e5d5 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -25,6 +25,7 @@ package jdk.internal.jimage; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -36,8 +37,11 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; /** @@ -47,80 +51,486 @@ import java.util.function.Consumer; * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -public class ImageReader extends BasicImageReader { +public final class ImageReader implements AutoCloseable { + private SharedImageReader reader; - private static final int SIZE_OF_OFFSET = 4; - - // Map of files opened as LITTLE_ENDIAN - private static final HashMap OPEN_LE_FILES - = new HashMap<>(); - - // Map of files opened as BIG_ENDIAN - private static final HashMap OPEN_BE_FILES - = new HashMap<>(); - - private int openCount; - - // attributes of the .jimage file. jimage file does not contain - // attributes for the individual resources (yet). We use attributes - // of the jimage file itself (creation, modification, access times). - // Iniitalized lazily, see {@link #imageFileAttributes()}. - private BasicFileAttributes imageFileAttributes; - - // directory management implementation - private final HashMap nodes; - private volatile Directory rootDir; - - private Directory packagesDir; - private Directory modulesDir; - - private ImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { - super(imagePath, byteOrder); - this.nodes = new HashMap<>(); + private ImageReader(SharedImageReader reader) { + this.reader = reader; } public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { - HashMap openFiles = getOpenFilesMap(byteOrder); - ImageReader reader; - synchronized (openFiles) { - reader = openFiles.get(imagePath); - if (reader == null) { - reader = new ImageReader(imagePath, byteOrder); - ImageReader existingReader = openFiles.putIfAbsent(imagePath, reader); - assert (existingReader == null); - } - reader.openCount++; - } - return reader; + return SharedImageReader.open(imagePath, byteOrder); } - private static HashMap getOpenFilesMap(ByteOrder byteOrder) { - return (byteOrder == ByteOrder.BIG_ENDIAN) ? OPEN_BE_FILES : OPEN_LE_FILES; - } - - /** - * Opens the given file path as an image file, returning an {@code ImageReader}. - */ public static ImageReader open(Path imagePath) throws IOException { return open(imagePath, ByteOrder.nativeOrder()); } - private boolean canClose() { - HashMap openFiles = getOpenFilesMap(this.getByteOrder()); - synchronized (openFiles) { - if (--this.openCount == 0) { - return openFiles.remove(this.getName(), this); - } - } - return false; - } - @Override public void close() throws IOException { - if (canClose()) { - super.close(); - clearNodes(); - } + if (reader == null) { + throw new IOException("image file already closed"); + } + + reader.close(this); + reader = null; + } + + // directory management interface + public Directory getRootDirectory() throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getRootDirectory(); + } + + public Node findNode(String name) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.findNode(name); + } + + public byte[] getResource(Node node) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(node); + } + + public byte[] getResource(Resource rs) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(rs); + } + + public ImageHeader getHeader() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getHeader(); + } + + public static void releaseByteBuffer(ByteBuffer buffer) { + BasicImageReader.releaseByteBuffer(buffer); + } + + public String getName() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getName() ; + } + + public ByteOrder getByteOrder() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getByteOrder(); + } + + public Path getImagePath() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getImagePath(); + } + + public ImageStringsReader getStrings() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getStrings(); + } + + public ImageLocation findLocation(String mn, String rn) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(mn, rn); + } + + public ImageLocation findLocation(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(name); + } + + public String[] getEntryNames() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getEntryNames(); + } + + public long[] getAttributes(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getAttributes(offset); + } + + public String getString(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getString(offset); + } + + public byte[] getResource(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(name); + } + + public byte[] getResource(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(loc); + } + + public ByteBuffer getResourceBuffer(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceBuffer(loc); + } + + public InputStream getResourceStream(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceStream(loc); + } + + private final static class SharedImageReader extends BasicImageReader { + static final int SIZE_OF_OFFSET = Integer.BYTES; + + static final Map OPEN_FILES = new HashMap<>(); + + // List of openers for this shared image. + final Set openers; + + // attributes of the .jimage file. jimage file does not contain + // attributes for the individual resources (yet). We use attributes + // of the jimage file itself (creation, modification, access times). + // Iniitalized lazily, see {@link #imageFileAttributes()}. + BasicFileAttributes imageFileAttributes; + + // directory management implementation + final HashMap nodes; + volatile Directory rootDir; + + Directory packagesDir; + Directory modulesDir; + + private SharedImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { + super(imagePath, byteOrder); + this.openers = new HashSet<>(); + this.nodes = new HashMap<>(); + } + + public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + synchronized (OPEN_FILES) { + SharedImageReader reader = OPEN_FILES.get(imagePath); + + if (reader == null) { + // Will fail with an IOException if wrong byteOrder. + reader = new SharedImageReader(imagePath, byteOrder); + OPEN_FILES.put(imagePath, reader); + } else if (reader.getByteOrder() != byteOrder) { + throw new IOException("\"" + reader.getName() + "\" is not an image file"); + } + + ImageReader image = new ImageReader(reader); + reader.openers.add(image); + + return image; + } + } + + public void close(ImageReader image) throws IOException { + synchronized (OPEN_FILES) { + if (!openers.remove(image)) { + throw new IOException("image file already closed"); + } + + if (openers.isEmpty()) { + close(); + nodes.clear(); + rootDir = null; + + if (!OPEN_FILES.remove(this.getImagePath(), this)) { + throw new IOException("image file not found in open list"); + } + } + } + } + + void addOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + openers.add(reader); + } + } + + boolean removeOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + return openers.remove(reader); + } + } + + // directory management interface + Directory getRootDirectory() { + return buildRootDirectory(); + } + + /** + * Lazily build a node from a name. + */ + synchronized Node buildNode(String name) { + Node n; + boolean isPackages = name.startsWith("/packages"); + boolean isModules = !isPackages && name.startsWith("/modules"); + + if (!(isModules || isPackages)) { + return null; + } + + ImageLocation loc = findLocation(name); + + if (loc != null) { // A sub tree node + if (isPackages) { + n = handlePackages(name, loc); + } else { // modules sub tree + n = handleModulesSubTree(name, loc); + } + } else { // Asking for a resource? /modules/java.base/java/lang/Object.class + if (isModules) { + n = handleResource(name); + } else { + // Possibly ask for /packages/java.lang/java.base + // although /packages/java.base not created + n = handleModuleLink(name); + } + } + return n; + } + + synchronized Directory buildRootDirectory() { + Directory root = rootDir; // volatile read + if (root != null) { + return root; + } + + root = newDirectory(null, "/"); + root.setIsRootDir(); + + // /packages dir + packagesDir = newDirectory(root, "/packages"); + packagesDir.setIsPackagesDir(); + + // /modules dir + modulesDir = newDirectory(root, "/modules"); + modulesDir.setIsModulesDir(); + + root.setCompleted(true); + return rootDir = root; + } + + /** + * To visit sub tree resources. + */ + interface LocationVisitor { + void visit(ImageLocation loc); + } + + void visitLocation(ImageLocation loc, LocationVisitor visitor) { + byte[] offsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(offsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { + int offset = intBuffer.get(i); + ImageLocation pkgLoc = getLocation(offset); + visitor.visit(pkgLoc); + } + } + + void visitPackageLocation(ImageLocation loc) { + // Retrieve package name + String pkgName = getBaseExt(loc); + // Content is array of offsets in Strings table + byte[] stringsOffsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + // For each module, create a link node. + for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { + // skip empty state, useless. + intBuffer.get(i); + i++; + int offset = intBuffer.get(i); + String moduleName = getString(offset); + Node targetNode = findNode("/modules/" + moduleName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); + } + } + } + + Node handlePackages(String name, ImageLocation loc) { + long size = loc.getUncompressedSize(); + Node n = null; + // Only possiblities are /packages, /packages/package/module + if (name.equals("/packages")) { + visitLocation(loc, (childloc) -> { + findNode(childloc.getFullName()); + }); + packagesDir.setCompleted(true); + n = packagesDir; + } else { + if (size != 0) { // children are offsets to module in StringsTable + String pkgName = getBaseExt(loc); + Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); + visitPackageLocation(loc); + pkgDir.setCompleted(true); + n = pkgDir; + } else { // Link to module + String pkgName = loc.getParent(); + String modName = getBaseExt(loc); + Node targetNode = findNode("/modules/" + modName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); + n = linkNode; + } + } + } + return n; + } + + // Asking for /packages/package/module although + // /packages// not yet created, need to create it + // prior to return the link to module node. + Node handleModuleLink(String name) { + // eg: unresolved /packages/package/module + // Build /packages/package node + Node ret = null; + String radical = "/packages/"; + String path = name; + if (path.startsWith(radical)) { + int start = radical.length(); + int pkgEnd = path.indexOf('/', start); + if (pkgEnd != -1) { + String pkg = path.substring(start, pkgEnd); + String pkgPath = radical + pkg; + Node n = findNode(pkgPath); + // If not found means that this is a symbolic link such as: + // /packages/java.util/java.base/java/util/Vector.class + // and will be done by a retry of the filesystem + for (Node child : n.getChildren()) { + if (child.name.equals(name)) { + ret = child; + break; + } + } + } + } + return ret; + } + + Node handleModulesSubTree(String name, ImageLocation loc) { + Node n; + assert (name.equals(loc.getFullName())); + Directory dir = makeDirectories(name); + visitLocation(loc, (childloc) -> { + String path = childloc.getFullName(); + if (path.startsWith("/modules")) { // a package + makeDirectories(path); + } else { // a resource + makeDirectories(childloc.buildName(true, true, false)); + newResource(dir, childloc); + } + }); + dir.setCompleted(true); + n = dir; + return n; + } + + Node handleResource(String name) { + Node n = null; + String locationPath = name.substring("/modules".length()); + ImageLocation resourceLoc = findLocation(locationPath); + if (resourceLoc != null) { + Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); + Resource res = newResource(dir, resourceLoc); + n = res; + } + return n; + } + + String getBaseExt(ImageLocation loc) { + String base = loc.getBase(); + String ext = loc.getExtension(); + if (ext != null && !ext.isEmpty()) { + base = base + "." + ext; + } + return base; + } + + synchronized Node findNode(String name) { + buildRootDirectory(); + Node n = nodes.get(name); + if (n == null || !n.isCompleted()) { + n = buildNode(name); + } + return n; + } + + /** + * Returns the file attributes of the image file. + */ + BasicFileAttributes imageFileAttributes() { + BasicFileAttributes attrs = imageFileAttributes; + if (attrs == null) { + try { + Path file = getImagePath(); + attrs = Files.readAttributes(file, BasicFileAttributes.class); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + imageFileAttributes = attrs; + } + return attrs; + } + + Directory newDirectory(Directory parent, String name) { + Directory dir = Directory.create(parent, name, imageFileAttributes()); + nodes.put(dir.getName(), dir); + return dir; + } + + Resource newResource(Directory parent, ImageLocation loc) { + Resource res = Resource.create(parent, loc, imageFileAttributes()); + nodes.put(res.getName(), res); + return res; + } + + LinkNode newLinkNode(Directory dir, String name, Node link) { + LinkNode linkNode = LinkNode.create(dir, name, link); + nodes.put(linkNode.getName(), linkNode); + return linkNode; + } + + Directory makeDirectories(String parent) { + Directory last = rootDir; + for (int offset = parent.indexOf('/', 1); + offset != -1; + offset = parent.indexOf('/', offset + 1)) { + String dir = parent.substring(0, offset); + last = makeDirectory(dir, last); + } + return makeDirectory(parent, last); + + } + + Directory makeDirectory(String dir, Directory last) { + Directory nextDir = (Directory) nodes.get(dir); + if (nextDir == null) { + nextDir = newDirectory(last, dir); + } + return nextDir; + } + + byte[] getResource(Node node) throws IOException { + if (node.isResource()) { + return super.getResource(node.getLocation()); + } + throw new IOException("Not a resource: " + node); + } + + byte[] getResource(Resource rs) throws IOException { + return super.getResource(rs.getLocation()); + } } // jimage file does not store directory structure. We build nodes @@ -389,7 +799,7 @@ public class ImageReader extends BasicImageReader { @Override public Node resolveLink(boolean recursive) { - return recursive && (link instanceof LinkNode)? ((LinkNode)link).resolveLink(true) : link; + return (recursive && link instanceof LinkNode) ? ((LinkNode)link).resolveLink(true) : link; } @Override @@ -397,297 +807,4 @@ public class ImageReader extends BasicImageReader { return true; } } - - // directory management interface - public Directory getRootDirectory() { - return buildRootDirectory(); - } - - /** - * To visit sub tree resources. - */ - interface LocationVisitor { - - void visit(ImageLocation loc); - } - - /** - * Lazily build a node from a name. - */ - private Node buildNode(String name) { - Node n; - boolean isPackages = name.startsWith("/packages"); - boolean isModules = !isPackages && name.startsWith("/modules"); - - if (!(isModules || isPackages)) { - return null; - } - - ImageLocation loc = findLocation(name); - - if (loc != null) { // A sub tree node - if (isPackages) { - n = handlePackages(name, loc); - } else { // modules sub tree - n = handleModulesSubTree(name, loc); - } - } else { // Asking for a resource? /modules/java.base/java/lang/Object.class - if (isModules) { - n = handleResource(name); - } else { - // Possibly ask for /packages/java.lang/java.base - // although /packages/java.base not created - n = handleModuleLink(name); - } - } - return n; - } - - private void visitLocation(ImageLocation loc, LocationVisitor visitor) { - byte[] offsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(offsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { - int offset = intBuffer.get(i); - ImageLocation pkgLoc = getLocation(offset); - visitor.visit(pkgLoc); - } - } - - private void visitPackageLocation(ImageLocation loc) { - // Retrieve package name - String pkgName = getBaseExt(loc); - // Content is array of offsets in Strings table - byte[] stringsOffsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - // For each module, create a link node. - for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { - // skip empty state, useless. - intBuffer.get(i); - i++; - int offset = intBuffer.get(i); - String moduleName = getString(offset); - Node targetNode = findNode("/modules/" + moduleName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); - } - } - } - - private Node handlePackages(String name, ImageLocation loc) { - long size = loc.getUncompressedSize(); - Node n = null; - // Only possiblities are /packages, /packages/package/module - if (name.equals("/packages")) { - visitLocation(loc, (childloc) -> { - findNode(childloc.getFullName()); - }); - packagesDir.setCompleted(true); - n = packagesDir; - } else { - if (size != 0) { // children are offsets to module in StringsTable - String pkgName = getBaseExt(loc); - Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); - visitPackageLocation(loc); - pkgDir.setCompleted(true); - n = pkgDir; - } else { // Link to module - String pkgName = loc.getParent(); - String modName = getBaseExt(loc); - Node targetNode = findNode("/modules/" + modName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); - n = linkNode; - } - } - } - return n; - } - - // Asking for /packages/package/module although - // /packages// not yet created, need to create it - // prior to return the link to module node. - private Node handleModuleLink(String name) { - // eg: unresolved /packages/package/module - // Build /packages/package node - Node ret = null; - String radical = "/packages/"; - String path = name; - if (path.startsWith(radical)) { - int start = radical.length(); - int pkgEnd = path.indexOf('/', start); - if (pkgEnd != -1) { - String pkg = path.substring(start, pkgEnd); - String pkgPath = radical + pkg; - Node n = findNode(pkgPath); - // If not found means that this is a symbolic link such as: - // /packages/java.util/java.base/java/util/Vector.class - // and will be done by a retry of the filesystem - for (Node child : n.getChildren()) { - if (child.name.equals(name)) { - ret = child; - break; - } - } - } - } - return ret; - } - - private Node handleModulesSubTree(String name, ImageLocation loc) { - Node n; - assert (name.equals(loc.getFullName())); - Directory dir = makeDirectories(name); - visitLocation(loc, (childloc) -> { - String path = childloc.getFullName(); - if (path.startsWith("/modules")) { // a package - makeDirectories(path); - } else { // a resource - makeDirectories(childloc.buildName(true, true, false)); - newResource(dir, childloc); - } - }); - dir.setCompleted(true); - n = dir; - return n; - } - - private Node handleResource(String name) { - Node n = null; - String locationPath = name.substring("/modules".length()); - ImageLocation resourceLoc = findLocation(locationPath); - if (resourceLoc != null) { - Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); - Resource res = newResource(dir, resourceLoc); - n = res; - } - return n; - } - - private String getBaseExt(ImageLocation loc) { - String base = loc.getBase(); - String ext = loc.getExtension(); - if (ext != null && !ext.isEmpty()) { - base = base + "." + ext; - } - return base; - } - - public synchronized Node findNode(String name) { - buildRootDirectory(); - Node n = nodes.get(name); - if (n == null || !n.isCompleted()) { - n = buildNode(name); - } - return n; - } - - private synchronized void clearNodes() { - nodes.clear(); - rootDir = null; - } - - /** - * Returns the file attributes of the image file. - */ - private BasicFileAttributes imageFileAttributes() { - BasicFileAttributes attrs = imageFileAttributes; - if (attrs == null) { - try { - Path file = getImagePath(); - attrs = Files.readAttributes(file, BasicFileAttributes.class); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - imageFileAttributes = attrs; - } - return attrs; - } - - private Directory buildRootDirectory() { - Directory root = rootDir; // volatile read - if (root != null) { - return root; - } - - synchronized (this) { - root = rootDir; - if (root != null) { - return root; - } - - // FIXME no time information per resource in jimage file (yet?) - // we use file attributes of jimage itself. - // root directory - root = newDirectory(null, "/"); - root.setIsRootDir(); - - // /packages dir - packagesDir = newDirectory(root, "/packages"); - packagesDir.setIsPackagesDir(); - - // /modules dir - modulesDir = newDirectory(root, "/modules"); - modulesDir.setIsModulesDir(); - - root.setCompleted(true); - return rootDir = root; - } - } - - private Directory newDirectory(Directory parent, String name) { - Directory dir = Directory.create(parent, name, imageFileAttributes()); - nodes.put(dir.getName(), dir); - return dir; - } - - private Resource newResource(Directory parent, ImageLocation loc) { - Resource res = Resource.create(parent, loc, imageFileAttributes()); - nodes.put(res.getName(), res); - return res; - } - - private LinkNode newLinkNode(Directory dir, String name, Node link) { - LinkNode linkNode = LinkNode.create(dir, name, link); - nodes.put(linkNode.getName(), linkNode); - return linkNode; - } - - private Directory makeDirectories(String parent) { - Directory last = rootDir; - for (int offset = parent.indexOf('/', 1); - offset != -1; - offset = parent.indexOf('/', offset + 1)) { - String dir = parent.substring(0, offset); - last = makeDirectory(dir, last); - } - return makeDirectory(parent, last); - - } - - private Directory makeDirectory(String dir, Directory last) { - Directory nextDir = (Directory) nodes.get(dir); - if (nextDir == null) { - nextDir = newDirectory(last, dir); - } - return nextDir; - } - - public byte[] getResource(Node node) throws IOException { - if (node.isResource()) { - return super.getResource(node.getLocation()); - } - throw new IOException("Not a resource: " + node); - } - - public byte[] getResource(Resource rs) throws IOException { - return super.getResource(rs.getLocation()); - } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java index d5984095e99..5f0433b9d3b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java @@ -299,13 +299,9 @@ class JrtFileSystem extends FileSystem { } // clean up this file system - called from finalize and close - void cleanup() throws IOException { - if (!isOpen) { - return; - } - synchronized (this) { + synchronized void cleanup() throws IOException { + if (isOpen) { isOpen = false; - // close image reader and null out image.close(); image = null; } @@ -461,8 +457,8 @@ class JrtFileSystem extends FileSystem { private Node lookup(String path) { try { return image.findNode(path); - } catch (RuntimeException re) { - throw new InvalidPathException(path, re.toString()); + } catch (RuntimeException | IOException ex) { + throw new InvalidPathException(path, ex.toString()); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java index 7b155feba88..2da0d6ed452 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java @@ -49,7 +49,7 @@ import jdk.internal.jimage.ImageReader.Node; */ abstract class SystemImage { - abstract Node findNode(String path); + abstract Node findNode(String path) throws IOException; abstract byte[] getResource(Node node) throws IOException; abstract void close() throws IOException; @@ -60,7 +60,7 @@ abstract class SystemImage { image.getRootDirectory(); return new SystemImage() { @Override - Node findNode(String path) { + Node findNode(String path) throws IOException { return image.findNode(path); } @Override From c20a95b52d5e32ad7fb9cde3e755f271f76cef9c Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 163/167] 8154090: Remove support for jimage recreate Reviewed-by: alanb --- .../jdk/tools/jimage/ExtractedImage.java | 78 ------------------- .../classes/jdk/tools/jimage/JImageTask.java | 43 ++-------- .../tools/jimage/resources/jimage.properties | 23 ++---- jdk/test/tools/jimage/JImageTest.java | 49 ------------ jdk/test/tools/jimage/JImageToolTest.java | 4 - jdk/test/tools/lib/tests/JImageGenerator.java | 4 - 6 files changed, 12 insertions(+), 189 deletions(-) delete mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java deleted file mode 100644 index 7090f768eb0..00000000000 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.tools.jimage; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Consumer; -import jdk.tools.jlink.internal.ImageFileCreator; -import jdk.tools.jlink.internal.Archive; -import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.DirArchive; -/** - * - * Support for extracted image. - */ -public final class ExtractedImage { - - private Set archives = new HashSet<>(); - private final ImagePluginStack plugins; - - ExtractedImage(Path dirPath, ImagePluginStack plugins, PrintWriter log, - boolean verbose) throws IOException { - if (!Files.isDirectory(dirPath)) { - throw new IOException("Not a directory"); - } - Consumer cons = (String t) -> { - if (verbose) { - log.println(t); - } - }; - this.plugins = plugins; - Files.walk(dirPath, 1).forEach((p) -> { - if (!dirPath.equals(p)) { - if (Files.isDirectory(p)) { - Archive a = new DirArchive(p, cons); - archives.add(a); - } - } - }); - archives = Collections.unmodifiableSet(archives); - } - - void recreateJImage(Path path) throws IOException { - ImageFileCreator.recreateJimage(path, archives, plugins); - } - - private static String getPathName(Path path) { - return path.toString().replace(File.separatorChar, '/'); - } -} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 105e8f61b44..26acec228bb 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -32,7 +32,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.file.Files; -import java.nio.file.Path; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; import java.util.LinkedList; @@ -44,8 +43,6 @@ import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION; import static jdk.internal.jimage.ImageHeader.MINOR_VERSION; import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.ImageResourcesTree; -import jdk.tools.jlink.internal.ImagePluginConfiguration; -import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.TaskHelper; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE; @@ -97,7 +94,6 @@ class JImageTask { EXTRACT, INFO, LIST, - RECREATE, SET, VERIFY }; @@ -160,18 +156,20 @@ class JImageTask { try { List unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { - options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + try { + options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + } catch (IllegalArgumentException ex) { + throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0)); + } for(int i = 1; i < unhandled.size(); i++) { options.jimages.add(new File(unhandled.get(i))); } + } else { + throw taskHelper.newBadArgs("err.not.a.task", ""); } if (options.help) { optionsHelper.showHelp(PROGNAME); } - if(optionsHelper.listPlugins()) { - optionsHelper.listPlugins(true); - return EXIT_OK; - } if (options.version || options.fullVersion) { taskHelper.showVersion(options.fullVersion); } @@ -191,30 +189,6 @@ class JImageTask { } } - private void recreate() throws Exception, BadArgs { - File directory = new File(options.directory); - if (!directory.isDirectory()) { - throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath()); - } - Path dirPath = directory.toPath(); - if (options.jimages.isEmpty()) { - throw taskHelper.newBadArgs("err.jimage.not.specified"); - } else if (options.jimages.size() != 1) { - throw taskHelper.newBadArgs("err.only.one.jimage"); - } - - Path jimage = options.jimages.get(0).toPath(); - - if (jimage.toFile().createNewFile()) { - ImagePluginStack pc = ImagePluginConfiguration.parseConfiguration(taskHelper. - getPluginsConfig(null, false)); - ExtractedImage img = new ExtractedImage(dirPath, pc, log, options.verbose); - img.recreateJImage(jimage); - } else { - throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName()); - } - } - private void title(File file, BasicImageReader reader) { log.println("jimage: " + file.getName()); } @@ -379,9 +353,6 @@ class JImageTask { case LIST: iterate(this::listTitle, this::list); break; - case RECREATE: - recreate(); - break; case SET: iterate(this::set, null); break; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 857d52b005a..99d2d4706d5 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -1,30 +1,25 @@ main.usage.summary=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ use --help for a list of possible options main.usage=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ \n\ \ extract - Extract all jimage entries into separate files into the directory\n\ \ specified by --dir= (default='.')\n\ \ info - Prints information specified in the jimage header.\n\ \ list - Prints the names of all the entries in the jimage. When used with\n\ \ --verbose will also print entry attributes ex. size and offset.\n\ -\ recreate - Reconstructs a jimage from an extracted directory (--dir)\n\ \ set - sets the value of specific jimage header entries\n\ \ verify - Reports errors on any .class entries that don't verify as classes.\n\ \n\ Possible options include: -main.extended.help=\ -jimage recreate is extensible by the main of plugins. Following plugins have been discovered \ -thanks to ServiceLoader and can be used when re-creating a jimage. - error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract/recreate +\ --dir Target directory for extract main.opt.flags=\ \ --flags=value Set the jimage flags to value @@ -38,14 +33,8 @@ main.opt.verbose=\ main.opt.version=\ \ --version Version information -main.opt.configuration=\ -\ --configuration Path to properties file containing defaults\ -\ options for recreate - main.command.files=\ \ @ Read options from file - -err.cannot.create.dir=cannot create directory: {0} err.cannot.read.file=cannot read file: {0} err.cannot.update.file=cannot update file: {0} err.file.not.found=cannot find file: {0} @@ -53,12 +42,10 @@ err.file.error=cannot access file: {0} err.flags.not.int=--flags value not integer: {0} err.internal.error=internal error: {0} {1} {2} err.invalid.arg.for.option=invalid argument for option: {0} -err.invalid.task=task must be extract|recreate|info|list|verify: {0} -err.jimage.already.exists=jimage already exists: {0} -err.jimage.not.specified=no jimage specified +err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} -err.only.one.jimage=only one jimage should be specified +err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} diff --git a/jdk/test/tools/jimage/JImageTest.java b/jdk/test/tools/jimage/JImageTest.java index be1e784c070..fa2c08b08dd 100644 --- a/jdk/test/tools/jimage/JImageTest.java +++ b/jdk/test/tools/jimage/JImageTest.java @@ -110,54 +110,5 @@ public class JImageTest { .dir(helper.createNewExtractedDir("modules")) .image(image.resolve("lib").resolve("modules")) .extract().assertSuccess(); - - Path recreatedImage = JImageGenerator.getJImageTask() - .dir(extractedDir) - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage, bootClasses, Collections.emptyList()); - - // Check replacing the boot image by recreated one - Path destFile = image.resolve("lib").resolve("modules"); - Files.copy(recreatedImage, destFile, REPLACE_EXISTING); - JImageValidator validator = new JImageValidator(module, Collections.emptyList(), - image.toFile(), Collections.emptyList(), Collections.emptyList()); - validator.validate(); - - Path recreatedImage2 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress").option("2") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage2, bootClasses, Collections.emptyList()); - - Path recreatedImage3 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--strip-debug") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage3, bootClasses, Collections.emptyList()); - - Path recreatedImage4 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - List unexpectedPaths = new ArrayList<>(); - unexpectedPaths.add(".jcov"); - unexpectedPaths.add("/META-INF/"); - JImageValidator.validate(recreatedImage4, bootClasses, unexpectedPaths); - - Path recreatedImage5 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress") - .option("2") - .option("--strip-debug") - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage5, bootClasses, unexpectedPaths); } } diff --git a/jdk/test/tools/jimage/JImageToolTest.java b/jdk/test/tools/jimage/JImageToolTest.java index 18f22f12fb1..48195c4c1da 100644 --- a/jdk/test/tools/jimage/JImageToolTest.java +++ b/jdk/test/tools/jimage/JImageToolTest.java @@ -63,11 +63,7 @@ public class JImageToolTest { String jimage = jimagePath.toAbsolutePath().toString(); String bootimage = modulesimagePath.toAbsolutePath().toString(); String extractDir = Paths.get(".", "extract").toAbsolutePath().toString(); - String recreateImage = Paths.get(".", "recreate").toAbsolutePath().toString(); - String relativeRecreateImage = Paths.get(".", "recreate2").toString(); jimage("extract", "--dir", extractDir, bootimage); - jimage("recreate", "--dir", extractDir, recreateImage); - jimage("recreate", "--dir", extractDir, relativeRecreateImage); System.out.println("Test successful"); } else { System.out.println("Test skipped, not an images build"); diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index 77366aafb13..c75164b69cc 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -553,10 +553,6 @@ public class JImageGenerator { public Result extract() { return cmd("extract", dir); } - - public Result recreate() { - return cmd("recreate", image); - } } public static class JLinkTask { From d83717b035492c9ec6ca3a1092ba721a4c492e25 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 164/167] 8069079: jimage extract / list to organize classes by modules Reviewed-by: alanb, mchung --- .../classes/jdk/tools/jimage/JImageTask.java | 86 +++++++++++++------ .../tools/jimage/resources/jimage.properties | 1 + 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 26acec228bb..b8a2d58c7fc 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -189,25 +189,19 @@ class JImageTask { } } - private void title(File file, BasicImageReader reader) { - log.println("jimage: " + file.getName()); - } - private void listTitle(File file, BasicImageReader reader) { - title(file, reader); - - if (options.verbose) { - log.print(pad("Offset", OFFSET_WIDTH + 1)); - log.print(pad("Size", SIZE_WIDTH + 1)); - log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1)); - log.println(" Entry"); - } + log.println("jimage: " + file); } private interface JImageAction { public void apply(File file, BasicImageReader reader) throws IOException, BadArgs; } + private interface ModuleAction { + public void apply(BasicImageReader reader, + String oldModule, String newModule) throws IOException, BadArgs; + } + private interface ResourceAction { public void apply(BasicImageReader reader, String name, ImageLocation location) throws IOException, BadArgs; @@ -233,23 +227,32 @@ class JImageTask { } } - private static final int NUMBER_WIDTH = 12; - private static final int OFFSET_WIDTH = NUMBER_WIDTH; - private static final int SIZE_WIDTH = NUMBER_WIDTH; - private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH; + private static final int OFFSET_WIDTH = 12; + private static final int SIZE_WIDTH = 10; + private static final int COMPRESSEDSIZE_WIDTH = 10; - private void print(String entry, ImageLocation location) { + private String trimModule(String name) { + int offset = name.indexOf('/', 1); + + if (offset != -1 && offset + 1 < name.length()) { + return name.substring(offset + 1); + } + + return name; + } + + private void print(String name, ImageLocation location) { log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " "); log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " "); log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " "); - log.println(entry); + log.println(trimModule(name)); } - private void print(BasicImageReader reader, String entry) { + private void print(BasicImageReader reader, String name) { if (options.verbose) { - print(entry, reader.findLocation(entry)); + print(name, reader.findLocation(name)); } else { - log.println(entry); + log.println(" " + trimModule(name)); } } @@ -268,6 +271,18 @@ class JImageTask { log.println(" Index Size: " + header.getIndexSize()); } + private void listModule(BasicImageReader reader, String oldModule, String newModule) { + log.println(); + log.println("Module: " + newModule); + + if (options.verbose) { + log.print(pad("Offset", OFFSET_WIDTH) + " "); + log.print(pad("Size", SIZE_WIDTH) + " "); + log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH) + " "); + log.println("Entry"); + } + } + private void list(BasicImageReader reader, String name, ImageLocation location) { print(reader, name); } @@ -317,7 +332,12 @@ class JImageTask { } private void iterate(JImageAction jimageAction, + ModuleAction moduleAction, ResourceAction resourceAction) throws IOException, BadArgs { + if (options.jimages.isEmpty()) { + throw taskHelper.newBadArgs("err.no.jimage"); + } + for (File file : options.jimages) { if (!file.exists() || !file.isFile()) { throw taskHelper.newBadArgs("err.not.a.jimage", file.getName()); @@ -330,9 +350,23 @@ class JImageTask { if (resourceAction != null) { String[] entryNames = reader.getEntryNames(); + String oldModule = ""; for (String name : entryNames) { if (!ImageResourcesTree.isTreeInfoResource(name)) { + if (moduleAction != null) { + int offset = name.indexOf('/', 1); + + String newModule = offset != -1 ? + name.substring(1, offset) : + ""; + + if (!oldModule.equals(newModule)) { + moduleAction.apply(reader, oldModule, newModule); + oldModule = newModule; + } + } + ImageLocation location = reader.findLocation(name); resourceAction.apply(reader, name, location); } @@ -345,19 +379,19 @@ class JImageTask { private boolean run() throws Exception, BadArgs { switch (options.task) { case EXTRACT: - iterate(null, this::extract); + iterate(null, null, this::extract); break; case INFO: - iterate(this::info, null); + iterate(this::info, null, null); break; case LIST: - iterate(this::listTitle, this::list); + iterate(this::listTitle, this::listModule, this::list); break; case SET: - iterate(this::set, null); + iterate(this::set, null, null); break; case VERIFY: - iterate(this::title, this::verify); + iterate(this::listTitle, null, this::verify); break; default: throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 99d2d4706d5..ef94fd376c6 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -46,6 +46,7 @@ err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} +err.no.jimage=no jimage provided err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} From 7057b40f4859efe2af4fcb48b9c9636ce8d6682e Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:56 -0300 Subject: [PATCH 165/167] 8154179: BasicImageReader activating ImageBufferCache when not used Reviewed-by: redestad --- .../share/classes/jdk/internal/jimage/BasicImageReader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java index 4c70a9b1547..9b21fb6c1be 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java @@ -183,7 +183,9 @@ public class BasicImageReader implements AutoCloseable { } public static void releaseByteBuffer(ByteBuffer buffer) { - ImageBufferCache.releaseBuffer(buffer); + if (!MAP_ALL) { + ImageBufferCache.releaseBuffer(buffer); + } } public String getName() { From c95df8b9fe59a9af82f316853dc9fee0dd9deab7 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:59:07 -0300 Subject: [PATCH 166/167] 8147426: Missing definition for JIMAGE_NOT_FOUND Reviewed-by: hseigel, alanb --- hotspot/src/share/vm/classfile/jimage.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp index e538ac805f8..480d01bc149 100644 --- a/hotspot/src/share/vm/classfile/jimage.hpp +++ b/hotspot/src/share/vm/classfile/jimage.hpp @@ -30,7 +30,7 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes @@ -113,7 +113,8 @@ typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* p * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); */ extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage, const char* module_name, const char* version, const char* name, @@ -134,7 +135,8 @@ typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); * char* buffer = new char[size]; * (*JImageGetResource)(image, location, buffer, size); */ @@ -154,7 +156,8 @@ typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef locati * required. All strings are utf-8, zero byte terminated.file. * * Ex. - * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) { + * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, + * const char* package, const char* name, const char* extension, void* arg) { * if (strcmp(extension, “class”) == 0) { * char path[JIMAGE_MAX_PATH]; * Thread* THREAD = Thread::current(); From ce076f3ab97f97e0a6e2027deb666a4b9409e1c6 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:59:43 -0300 Subject: [PATCH 167/167] 8147634: Need a JImage API that given a JImageLocationRef returns class name Reviewed-by: hseigel --- hotspot/src/share/vm/classfile/classLoader.cpp | 15 +++++++++------ hotspot/src/share/vm/classfile/jimage.hpp | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index a8a86765970..19b0f460a9d 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -98,12 +98,13 @@ static Crc32_t Crc32 = NULL; // Entry points for jimage.dll for loading jimage file entries -static JImageOpen_t JImageOpen = NULL; -static JImageClose_t JImageClose = NULL; -static JImagePackageToModule_t JImagePackageToModule = NULL; -static JImageFindResource_t JImageFindResource = NULL; -static JImageGetResource_t JImageGetResource = NULL; -static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImageOpen_t JImageOpen = NULL; +static JImageClose_t JImageClose = NULL; +static JImagePackageToModule_t JImagePackageToModule = NULL; +static JImageFindResource_t JImageFindResource = NULL; +static JImageGetResource_t JImageGetResource = NULL; +static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImage_ResourcePath_t JImageResourcePath = NULL; // Globals @@ -925,6 +926,8 @@ void ClassLoader::load_jimage_library() { guarantee(JImageGetResource != NULL, "function JIMAGE_GetResource not found"); JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, os::dll_lookup(handle, "JIMAGE_ResourceIterator")); guarantee(JImageResourceIterator != NULL, "function JIMAGE_ResourceIterator not found"); + JImageResourcePath = CAST_TO_FN_PTR(JImage_ResourcePath_t, os::dll_lookup(handle, "JIMAGE_ResourcePath")); + guarantee(JImageResourcePath != NULL, "function JIMAGE_ResourcePath not found"); } jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp index 480d01bc149..f34ba6efde9 100644 --- a/hotspot/src/share/vm/classfile/jimage.hpp +++ b/hotspot/src/share/vm/classfile/jimage.hpp @@ -179,3 +179,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); +