From 200784d505dd98444c48c9ccb7f2e4df36dcbb6a Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Oct 2015 18:13:34 -0400 Subject: [PATCH 001/225] 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 46cb32012acde827d2924895083a4cfada9864db Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 7 Jan 2016 13:59:49 -0500 Subject: [PATCH 002/225] 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 9105842337913b9b8e5922b1195efe050459b194 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 8 Feb 2016 12:54:57 +0000 Subject: [PATCH 003/225] 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 004/225] 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 005/225] 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 006/225] 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 007/225] 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 d9e44503b4843911e00cd3a79c3dd04f7b5c0405 Mon Sep 17 00:00:00 2001 From: Nadeesh TV Date: Fri, 22 Apr 2016 05:46:54 +0000 Subject: [PATCH 008/225] 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 009/225] 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 010/225] 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 011/225] 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 012/225] 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 013/225] 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 014/225] 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 015/225] 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 016/225] 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 017/225] 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 018/225] 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 019/225] 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 4b662bba26d584ae0a3d0a536d817aa50104504f Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 18 Apr 2016 21:07:50 +0200 Subject: [PATCH 020/225] 8036952: copyright issues in jdk9/dev/langtools files Updated copyright notices. Reviewed-by: jjg, jlahoda --- .../com/sun/tools/javac/file/FSInfo.java | 24 +++++++++++++++++++ langtools/test/tools/javac/6520152/T.java | 23 ++++++++++++++++++ .../test/tools/javac/6520152/T6520152.java | 23 ++++++++++++++++++ .../test/tools/javac/6521805/T6521805e.out | 2 +- .../test/tools/javac/6521805/p/Outer.java | 2 ++ langtools/test/tools/javac/6521805/p/Sub.java | 2 ++ langtools/test/tools/javac/6547131/T.java | 23 ++++++++++++++++++ .../test/tools/javac/6589361/T6589361.java | 23 ++++++++++++++++++ .../tools/javac/6668794/badSource/Test.java | 2 +- .../typeAnnotations/referenceinfos/Test.java | 22 +++++++++++++++++ .../tools/javac/api/6731573/Erroneous.java | 2 ++ langtools/test/tools/javac/flow/T8062747.java | 23 ++++++++++++++++++ .../jvm/6397652/com/test/Test$Test$Test.java | 23 ++++++++++++++++++ .../javac/jvm/6397652/com/test/Test$Test.java | 23 ++++++++++++++++++ .../lambda/badMemberRefBytecode/Main.java | 24 +++++++++++++++++++ .../lambda/badMemberRefBytecode/Use.java | 23 ++++++++++++++++++ .../javac/lambda/lambdaExecution/TBlock.java | 23 ++++++++++++++++++ .../test/tools/javac/policy/test3/A.java | 2 ++ .../tools/javac/synthesize/src/Double.java | 23 ++++++++++++++++++ .../tools/javac/synthesize/src/Float.java | 23 ++++++++++++++++++ .../javac/warnings/6594914/Auxiliary.java | 2 ++ .../warnings/6594914/ExplicitCompilation.out | 2 +- .../warnings/6594914/ImplicitCompilation.out | 2 +- langtools/test/tools/javap/4111861/A.java | 23 ++++++++++++++++++ 24 files changed, 360 insertions(+), 4 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java index 974f28fe5ce..fea4ef7a60a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2008, 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 com.sun.tools.javac.file; diff --git a/langtools/test/tools/javac/6520152/T.java b/langtools/test/tools/javac/6520152/T.java index 8a46b8f5735..8443a4dc50e 100644 --- a/langtools/test/tools/javac/6520152/T.java +++ b/langtools/test/tools/javac/6520152/T.java @@ -1,3 +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. + */ + import java.io.Serializable; public class T { diff --git a/langtools/test/tools/javac/6520152/T6520152.java b/langtools/test/tools/javac/6520152/T6520152.java index bdb15990296..c7cbf31eb95 100644 --- a/langtools/test/tools/javac/6520152/T6520152.java +++ b/langtools/test/tools/javac/6520152/T6520152.java @@ -1,3 +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. + */ + /** * @test * @bug 6520152 diff --git a/langtools/test/tools/javac/6521805/T6521805e.out b/langtools/test/tools/javac/6521805/T6521805e.out index 04c71cd8821..31b628ce2d6 100644 --- a/langtools/test/tools/javac/6521805/T6521805e.out +++ b/langtools/test/tools/javac/6521805/T6521805e.out @@ -1,2 +1,2 @@ -Sub.java:8:11: compiler.err.synthetic.name.conflict: this$0, p.Inner +Sub.java:10:11: compiler.err.synthetic.name.conflict: this$0, p.Inner 1 error diff --git a/langtools/test/tools/javac/6521805/p/Outer.java b/langtools/test/tools/javac/6521805/p/Outer.java index 3dd1de56b78..8a92158426b 100644 --- a/langtools/test/tools/javac/6521805/p/Outer.java +++ b/langtools/test/tools/javac/6521805/p/Outer.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + package p; class Outer { diff --git a/langtools/test/tools/javac/6521805/p/Sub.java b/langtools/test/tools/javac/6521805/p/Sub.java index 7a9f78896e3..a6d00c76a6d 100644 --- a/langtools/test/tools/javac/6521805/p/Sub.java +++ b/langtools/test/tools/javac/6521805/p/Sub.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + package p; class Inner extends Outer.Super { diff --git a/langtools/test/tools/javac/6547131/T.java b/langtools/test/tools/javac/6547131/T.java index 76d8a5b344f..5acf9b2ae63 100644 --- a/langtools/test/tools/javac/6547131/T.java +++ b/langtools/test/tools/javac/6547131/T.java @@ -1,3 +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. + */ + /** * @test * @bug 6547131 diff --git a/langtools/test/tools/javac/6589361/T6589361.java b/langtools/test/tools/javac/6589361/T6589361.java index 4d405e41d21..5a69bc5ec99 100644 --- a/langtools/test/tools/javac/6589361/T6589361.java +++ b/langtools/test/tools/javac/6589361/T6589361.java @@ -1,3 +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. + */ + /** * @test * @bug 6589361 diff --git a/langtools/test/tools/javac/6668794/badSource/Test.java b/langtools/test/tools/javac/6668794/badSource/Test.java index 162493e5ab1..c683bbe7f48 100644 --- a/langtools/test/tools/javac/6668794/badSource/Test.java +++ b/langtools/test/tools/javac/6668794/badSource/Test.java @@ -1,5 +1,5 @@ /* - * @test /nodynamiccopyight/ + * @test /nodynamiccopyright/ * @bug 6668794 6668796 * @summary javac puts localized text in raw diagnostics * bad diagnostic "bad class file" given for source files diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java index b6cb1cae604..811bbbf454b 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Test.java @@ -1,3 +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. + */ import java.util.*; import java.lang.annotation.*; diff --git a/langtools/test/tools/javac/api/6731573/Erroneous.java b/langtools/test/tools/javac/api/6731573/Erroneous.java index 7902f871c95..4bc66258016 100644 --- a/langtools/test/tools/javac/api/6731573/Erroneous.java +++ b/langtools/test/tools/javac/api/6731573/Erroneous.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + class A { boolean b; boolean b; diff --git a/langtools/test/tools/javac/flow/T8062747.java b/langtools/test/tools/javac/flow/T8062747.java index 857474216d5..8d2cfd17abc 100644 --- a/langtools/test/tools/javac/flow/T8062747.java +++ b/langtools/test/tools/javac/flow/T8062747.java @@ -1,3 +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. + */ + /** * @test * @bug 8062747 diff --git a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java index 83a81213721..6be3c7d93ac 100644 --- a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java +++ b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test$Test.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2006, 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 com.test; public class Test$Test$Test { diff --git a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java index d15532570b1..f439128a987 100644 --- a/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java +++ b/langtools/test/tools/javac/jvm/6397652/com/test/Test$Test.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2006, 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 com.test; public class Test$Test { diff --git a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java index 4c834cf3741..a188c4a74af 100644 --- a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java +++ b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Main.java @@ -1,3 +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. + */ + import java.util.Collections; public class Main { @@ -6,4 +29,5 @@ public class Main { Collections.sort(null, String::compareTo); } + } diff --git a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java index bb5a77a06ef..fa89e8118b1 100644 --- a/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java +++ b/langtools/test/tools/javac/lambda/badMemberRefBytecode/Use.java @@ -1,3 +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. + */ + public class Use { private Main m; } diff --git a/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java b/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java index 329eaf25de1..48d56c9f403 100644 --- a/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java +++ b/langtools/test/tools/javac/lambda/lambdaExecution/TBlock.java @@ -1,3 +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. + */ + /** * Performs operations upon an input object which may modify that object and/or * external state (other objects). diff --git a/langtools/test/tools/javac/policy/test3/A.java b/langtools/test/tools/javac/policy/test3/A.java index b21c7713860..c1f4c63bf88 100644 --- a/langtools/test/tools/javac/policy/test3/A.java +++ b/langtools/test/tools/javac/policy/test3/A.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + class A { void m1() { System.err.println("hello"); diff --git a/langtools/test/tools/javac/synthesize/src/Double.java b/langtools/test/tools/javac/synthesize/src/Double.java index 7ae620e85c8..b4cf0392933 100644 --- a/langtools/test/tools/javac/synthesize/src/Double.java +++ b/langtools/test/tools/javac/synthesize/src/Double.java @@ -1,3 +1,26 @@ +/* + * 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 + * 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 java.lang; public class Double extends Number diff --git a/langtools/test/tools/javac/synthesize/src/Float.java b/langtools/test/tools/javac/synthesize/src/Float.java index afbef38bebc..4b2fb18d5a6 100644 --- a/langtools/test/tools/javac/synthesize/src/Float.java +++ b/langtools/test/tools/javac/synthesize/src/Float.java @@ -1,3 +1,26 @@ +/* + * 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 + * 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 java.lang; public class Float extends Number diff --git a/langtools/test/tools/javac/warnings/6594914/Auxiliary.java b/langtools/test/tools/javac/warnings/6594914/Auxiliary.java index e9c881643e2..19157042e8e 100644 --- a/langtools/test/tools/javac/warnings/6594914/Auxiliary.java +++ b/langtools/test/tools/javac/warnings/6594914/Auxiliary.java @@ -1,3 +1,5 @@ +/* /nodynamiccopyright/ */ + import java.io.StringBufferInputStream; public class Auxiliary { diff --git a/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out b/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out index 3dff7922cf7..abb4822197b 100644 --- a/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out +++ b/langtools/test/tools/javac/warnings/6594914/ExplicitCompilation.out @@ -1,2 +1,2 @@ -Auxiliary.java:1:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io +Auxiliary.java:3:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io 1 warning diff --git a/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out b/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out index 3dff7922cf7..abb4822197b 100644 --- a/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out +++ b/langtools/test/tools/javac/warnings/6594914/ImplicitCompilation.out @@ -1,2 +1,2 @@ -Auxiliary.java:1:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io +Auxiliary.java:3:15: compiler.warn.has.been.deprecated: java.io.StringBufferInputStream, java.io 1 warning diff --git a/langtools/test/tools/javap/4111861/A.java b/langtools/test/tools/javap/4111861/A.java index 32cc86a8f07..3abd02c6b8a 100644 --- a/langtools/test/tools/javap/4111861/A.java +++ b/langtools/test/tools/javap/4111861/A.java @@ -1,3 +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. + */ + class A { public static final int i = 42; public static final boolean b = true; From 9691505077918e937d7315a606e8ebf1648bec60 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 18 Apr 2016 22:25:50 +0200 Subject: [PATCH 021/225] 7152104: javac should not warn about missing serialVersionUID for anonymous inner classes Javac no longer issues warnings for missing serialVersionUID in anonymous classes. Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/Attr.java | 9 ++--- langtools/test/tools/javac/T6554097.java | 21 ++++++----- langtools/test/tools/javac/T6554097.out | 22 +++++++++--- .../javac/diags/examples/AnonymousClass.java | 13 ++++--- .../test/tools/javac/positions/T6253161.java | 36 ------------------- .../test/tools/javac/positions/T6253161.out | 2 -- .../test/tools/javac/positions/T6253161a.java | 28 --------------- .../test/tools/javac/positions/T6253161a.out | 2 -- .../tools/javac/{ => serial}/SerialWarn.java | 0 .../tools/javac/{ => serial}/SerialWarn.out | 0 .../tools/javac/serial/SerialWarnAnon.java | 15 ++++++++ 11 files changed, 57 insertions(+), 91 deletions(-) delete mode 100644 langtools/test/tools/javac/positions/T6253161.java delete mode 100644 langtools/test/tools/javac/positions/T6253161.out delete mode 100644 langtools/test/tools/javac/positions/T6253161a.java delete mode 100644 langtools/test/tools/javac/positions/T6253161a.out rename langtools/test/tools/javac/{ => serial}/SerialWarn.java (100%) rename langtools/test/tools/javac/{ => serial}/SerialWarn.out (100%) create mode 100644 langtools/test/tools/javac/serial/SerialWarnAnon.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index ccbe70acfbd..1fd1d379a74 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -4491,10 +4491,11 @@ public class Attr extends JCTree.Visitor { chk.checkNonCyclicElements(tree); // Check for proper use of serialVersionUID - if (env.info.lint.isEnabled(LintCategory.SERIAL) && - isSerializable(c.type) && - (c.flags() & Flags.ENUM) == 0 && - checkForSerial(c)) { + if (env.info.lint.isEnabled(LintCategory.SERIAL) + && isSerializable(c.type) + && (c.flags() & Flags.ENUM) == 0 + && !c.isAnonymous() + && checkForSerial(c)) { checkSerialVersionUID(tree, c); } if (allowTypeAnnos) { diff --git a/langtools/test/tools/javac/T6554097.java b/langtools/test/tools/javac/T6554097.java index 4deb2e9b5a8..076517c7140 100644 --- a/langtools/test/tools/javac/T6554097.java +++ b/langtools/test/tools/javac/T6554097.java @@ -3,24 +3,27 @@ * @bug 6554097 * @summary "final" confuses at-SuppressWarnings * @compile T6554097.java - * @compile/fail/ref=T6554097.out -XDrawDiagnostics -Werror -Xlint:serial T6554097.java + * @compile/fail/ref=T6554097.out -XDrawDiagnostics -Werror -Xlint:rawtypes T6554097.java */ +import java.util.ArrayList; + class T6554097 { - @SuppressWarnings("serial") final Throwable[] v1 = { new Throwable() {} }; - @SuppressWarnings("serial") Throwable[] v2 = { new Throwable() {} }; + + @SuppressWarnings("unchecked") final ArrayList[] v1 = { new ArrayList() {} }; + @SuppressWarnings("unchecked") ArrayList[] v2 = { new ArrayList() {} }; public static void m1() throws Throwable { - @SuppressWarnings("serial") final Throwable[] v3 = { new Throwable() {} }; - @SuppressWarnings("serial") Throwable[] v4 = { new Throwable() {} }; + @SuppressWarnings("unchecked") final ArrayList[] v3 = { new ArrayList() {} }; + @SuppressWarnings("unchecked") ArrayList[] v4 = { new ArrayList() {} }; } - final Throwable[] v5 = { new Throwable() {} }; - Throwable[] v6 = { new Throwable() {} }; + final ArrayList[] v5 = { new ArrayList() {} }; + ArrayList[] v6 = { new ArrayList() {} }; public static void m2() throws Throwable { - final Throwable[] v7 = { new Throwable() {} }; - Throwable[] v8 = { new Throwable() {} }; + final ArrayList[] v7 = { new ArrayList() {} }; + ArrayList[] v8 = { new ArrayList() {} }; } } diff --git a/langtools/test/tools/javac/T6554097.out b/langtools/test/tools/javac/T6554097.out index aecbd999cf5..14db8a54b81 100644 --- a/langtools/test/tools/javac/T6554097.out +++ b/langtools/test/tools/javac/T6554097.out @@ -1,7 +1,19 @@ -T6554097.java:18:46: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$5 -T6554097.java:19:46: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$6 -T6554097.java:22:50: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$7 -T6554097.java:23:54: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6554097$8 +T6554097.java:13:42: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:13:65: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:14:42: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:14:65: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:17:50: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:17:73: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:18:50: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:18:73: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:21:11: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:21:34: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:22:11: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:22:34: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:25:15: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:25:38: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:26:15: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList +T6554097.java:26:38: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList - compiler.err.warnings.and.werror 1 error -4 warnings +16 warnings diff --git a/langtools/test/tools/javac/diags/examples/AnonymousClass.java b/langtools/test/tools/javac/diags/examples/AnonymousClass.java index 771d888ddbc..d5e3858f13a 100644 --- a/langtools/test/tools/javac/diags/examples/AnonymousClass.java +++ b/langtools/test/tools/javac/diags/examples/AnonymousClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,12 +22,15 @@ */ // key: compiler.misc.anonymous.class -// key: compiler.warn.missing.SVUID -// options: -Xlint:serial +// key: compiler.err.prob.found.req +// key: compiler.misc.inconvertible.types +// options: -Xlint:rawtypes // run: simple +import java.util.ArrayList; + class AnonymousClass { - Exception m() { - return new Exception() { }; + Object m() { + return (ArrayList) new ArrayList() { }; } } diff --git a/langtools/test/tools/javac/positions/T6253161.java b/langtools/test/tools/javac/positions/T6253161.java deleted file mode 100644 index 5824a457707..00000000000 --- a/langtools/test/tools/javac/positions/T6253161.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6253161 - * @summary Compiler will fail to find the correct location of serial warnings for anonymous inner classes - * @author Seetharama Avadhanam - * @compile -Xlint:serial -XDdev T6253161.java - * @compile/ref=T6253161.out -Xlint:serial -XDdev -XDrawDiagnostics T6253161.java - */ -import java.util.List; -import java.util.ArrayList; - -public class T6253161 { - @SuppressWarnings("unchecked") - public void anonymousMethod(){ - List list = new ArrayList(){ - static final long serialVersionUID = 1; - List list = new ArrayList(); - public List getMyList(){ - final List floatList = new ArrayList(){ - List integerList = new ArrayList(); - public List getMyList(){ - for(int i=0;i<10;i++) - integerList.add((int)((Float.parseFloat(i+""))+(1.11F))); - return (List)(Object)integerList; - } - public void testMethods(){ - //... - } - }.getMyList(); - for(int i=0;i<10;i++) - list.add((Float)(floatList.get(i)) * 11.232F * i); - return list; - } - }.getMyList(); - } -} diff --git a/langtools/test/tools/javac/positions/T6253161.out b/langtools/test/tools/javac/positions/T6253161.out deleted file mode 100644 index d5d2e5162e8..00000000000 --- a/langtools/test/tools/javac/positions/T6253161.out +++ /dev/null @@ -1,2 +0,0 @@ -T6253161.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161$1$1 -1 warning diff --git a/langtools/test/tools/javac/positions/T6253161a.java b/langtools/test/tools/javac/positions/T6253161a.java deleted file mode 100644 index 1adfd72f8a9..00000000000 --- a/langtools/test/tools/javac/positions/T6253161a.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6253161 - * @summary Compiler will fail to find the correct location of serial warnings for anonymous inner classes - * @author Seetharama Avadhanam - * @compile -Xlint:serial -XDdev T6253161a.java - * @compile/ref=T6253161a.out -Xlint:serial -XDdev -XDrawDiagnostics T6253161a.java - */ -import java.util.List; -import java.util.ArrayList; - -public class T6253161a { - @SuppressWarnings("unchecked") - public void anonymousMethod(){ - List list = new ArrayList(){ - static final long serialVersionUID = 1; - List list = new ArrayList(); - public List getMyList(){ - final List floatList = new ArrayList(){ - // Blank .... - }; - for(int i=0;i<10;i++) - list.add((Float)(floatList.get(i)) * 11.232F * i); - return list; - } - }.getMyList(); - } -} diff --git a/langtools/test/tools/javac/positions/T6253161a.out b/langtools/test/tools/javac/positions/T6253161a.out deleted file mode 100644 index e5ba714cb51..00000000000 --- a/langtools/test/tools/javac/positions/T6253161a.out +++ /dev/null @@ -1,2 +0,0 @@ -T6253161a.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161a$1$1 -1 warning diff --git a/langtools/test/tools/javac/SerialWarn.java b/langtools/test/tools/javac/serial/SerialWarn.java similarity index 100% rename from langtools/test/tools/javac/SerialWarn.java rename to langtools/test/tools/javac/serial/SerialWarn.java diff --git a/langtools/test/tools/javac/SerialWarn.out b/langtools/test/tools/javac/serial/SerialWarn.out similarity index 100% rename from langtools/test/tools/javac/SerialWarn.out rename to langtools/test/tools/javac/serial/SerialWarn.out diff --git a/langtools/test/tools/javac/serial/SerialWarnAnon.java b/langtools/test/tools/javac/serial/SerialWarnAnon.java new file mode 100644 index 00000000000..2e6def59519 --- /dev/null +++ b/langtools/test/tools/javac/serial/SerialWarnAnon.java @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7152104 + * @summary Make sure no warning is emitted for anonymous classes + * without serialVersionUID + * @compile SerialWarn.java + * @compile -Werror -XDrawDiagnostics -Xlint:serial SerialWarnAnon.java + */ + +class SerialWarnAnon { + interface SerialWarnAnonInterface extends java.io.Serializable { } + Object m() { + return new SerialWarnAnonInterface() { }; + } +} From 2d863bcd37bcbd06e39559add140e9d2cde73f5e Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 18 Apr 2016 14:04:09 -0700 Subject: [PATCH 022/225] 8145468: update java.lang APIs with new deprecations Reviewed-by: mcimadamore --- .../com/sun/tools/javac/comp/ConstFold.java | 50 +++++++++---------- .../com/sun/tools/javac/jvm/ClassReader.java | 6 +-- .../classes/com/sun/tools/javac/jvm/Gen.java | 2 +- .../sun/tools/javac/parser/JavacParser.java | 2 +- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java index be33a96ffc6..3436c18ceaf 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ConstFold.java @@ -125,15 +125,15 @@ strictfp class ConstFold { return syms.booleanType.constType(b2i(intValue(od) >= 0)); case lneg: // unary - - return syms.longType.constType(new Long(-longValue(od))); + return syms.longType.constType(Long.valueOf(-longValue(od))); case lxor: // ~ - return syms.longType.constType(new Long(~longValue(od))); + return syms.longType.constType(Long.valueOf(~longValue(od))); case fneg: // unary - - return syms.floatType.constType(new Float(-floatValue(od))); + return syms.floatType.constType(Float.valueOf(-floatValue(od))); case dneg: // ~ - return syms.doubleType.constType(new Double(-doubleValue(od))); + return syms.doubleType.constType(Double.valueOf(-doubleValue(od))); default: return null; @@ -216,37 +216,37 @@ strictfp class ConstFold { case ladd: return syms.longType.constType( - new Long(longValue(l) + longValue(r))); + Long.valueOf(longValue(l) + longValue(r))); case lsub: return syms.longType.constType( - new Long(longValue(l) - longValue(r))); + Long.valueOf(longValue(l) - longValue(r))); case lmul: return syms.longType.constType( - new Long(longValue(l) * longValue(r))); + Long.valueOf(longValue(l) * longValue(r))); case ldiv: return syms.longType.constType( - new Long(longValue(l) / longValue(r))); + Long.valueOf(longValue(l) / longValue(r))); case lmod: return syms.longType.constType( - new Long(longValue(l) % longValue(r))); + Long.valueOf(longValue(l) % longValue(r))); case land: return syms.longType.constType( - new Long(longValue(l) & longValue(r))); + Long.valueOf(longValue(l) & longValue(r))); case lor: return syms.longType.constType( - new Long(longValue(l) | longValue(r))); + Long.valueOf(longValue(l) | longValue(r))); case lxor: return syms.longType.constType( - new Long(longValue(l) ^ longValue(r))); + Long.valueOf(longValue(l) ^ longValue(r))); case lshl: case lshll: return syms.longType.constType( - new Long(longValue(l) << intValue(r))); + Long.valueOf(longValue(l) << intValue(r))); case lshr: case lshrl: return syms.longType.constType( - new Long(longValue(l) >> intValue(r))); + Long.valueOf(longValue(l) >> intValue(r))); case lushr: return syms.longType.constType( - new Long(longValue(l) >>> intValue(r))); + Long.valueOf(longValue(l) >>> intValue(r))); case lcmp: if (longValue(l) < longValue(r)) return syms.intType.constType(minusOne); @@ -256,19 +256,19 @@ strictfp class ConstFold { return syms.intType.constType(zero); case fadd: return syms.floatType.constType( - new Float(floatValue(l) + floatValue(r))); + Float.valueOf(floatValue(l) + floatValue(r))); case fsub: return syms.floatType.constType( - new Float(floatValue(l) - floatValue(r))); + Float.valueOf(floatValue(l) - floatValue(r))); case fmul: return syms.floatType.constType( - new Float(floatValue(l) * floatValue(r))); + Float.valueOf(floatValue(l) * floatValue(r))); case fdiv: return syms.floatType.constType( - new Float(floatValue(l) / floatValue(r))); + Float.valueOf(floatValue(l) / floatValue(r))); case fmod: return syms.floatType.constType( - new Float(floatValue(l) % floatValue(r))); + Float.valueOf(floatValue(l) % floatValue(r))); case fcmpg: case fcmpl: if (floatValue(l) < floatValue(r)) return syms.intType.constType(minusOne); @@ -282,19 +282,19 @@ strictfp class ConstFold { return syms.intType.constType(minusOne); case dadd: return syms.doubleType.constType( - new Double(doubleValue(l) + doubleValue(r))); + Double.valueOf(doubleValue(l) + doubleValue(r))); case dsub: return syms.doubleType.constType( - new Double(doubleValue(l) - doubleValue(r))); + Double.valueOf(doubleValue(l) - doubleValue(r))); case dmul: return syms.doubleType.constType( - new Double(doubleValue(l) * doubleValue(r))); + Double.valueOf(doubleValue(l) * doubleValue(r))); case ddiv: return syms.doubleType.constType( - new Double(doubleValue(l) / doubleValue(r))); + Double.valueOf(doubleValue(l) / doubleValue(r))); case dmod: return syms.doubleType.constType( - new Double(doubleValue(l) % doubleValue(r))); + Double.valueOf(doubleValue(l) % doubleValue(r))); case dcmpg: case dcmpl: if (doubleValue(l) < doubleValue(r)) return syms.intType.constType(minusOne); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 9806e85f959..12c46059519 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -457,13 +457,13 @@ public class ClassReader { poolObj[i] = getInt(index + 1); break; case CONSTANT_Float: - poolObj[i] = new Float(getFloat(index + 1)); + poolObj[i] = Float.valueOf(getFloat(index + 1)); break; case CONSTANT_Long: - poolObj[i] = new Long(getLong(index + 1)); + poolObj[i] = Long.valueOf(getLong(index + 1)); break; case CONSTANT_Double: - poolObj[i] = new Double(getDouble(index + 1)); + poolObj[i] = Double.valueOf(getDouble(index + 1)); break; case CONSTANT_MethodHandle: skipBytes(4); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index b551b61e8d9..5de84f0ab59 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -203,7 +203,7 @@ public class Gen extends JCTree.Visitor { */ void emitMinusOne(int tc) { if (tc == LONGcode) { - items.makeImmediateItem(syms.longType, new Long(-1)).load(); + items.makeImmediateItem(syms.longType, Long.valueOf(-1)).load(); } else { code.emitop0(iconst_m1); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index c0b69a9c86e..e6e3b839e25 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -686,7 +686,7 @@ public class JavacParser implements Parser { try { t = F.at(pos).Literal( TypeTag.LONG, - new Long(Convert.string2long(strval(prefix), token.radix()))); + Long.valueOf(Convert.string2long(strval(prefix), token.radix()))); } catch (NumberFormatException ex) { error(token.pos, "int.number.too.large", strval(prefix)); } From 8f62cdc8a03baaacac556edde84a7a01ba58cd62 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 18 Apr 2016 18:41:38 -0700 Subject: [PATCH 023/225] 8154504: javac tests fail after JDK API is deprecated Reviewed-by: darcy --- langtools/test/tools/javac/CaptureInSubtype.java | 2 +- langtools/test/tools/javac/OverrideChecks/T4721069.java | 2 +- langtools/test/tools/javac/generics/Nonlinear.java | 2 +- langtools/test/tools/javac/generics/odersky/BadTest4.java | 2 +- langtools/test/tools/javac/lambda/8074381/T8074381a.java | 2 ++ langtools/test/tools/javac/lambda/8074381/T8074381a.out | 4 ++-- langtools/test/tools/javac/lambda/TargetType27.java | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/langtools/test/tools/javac/CaptureInSubtype.java b/langtools/test/tools/javac/CaptureInSubtype.java index 41d5a3b0b1b..3b73e20a6dd 100644 --- a/langtools/test/tools/javac/CaptureInSubtype.java +++ b/langtools/test/tools/javac/CaptureInSubtype.java @@ -33,7 +33,7 @@ public class CaptureInSubtype { public static class ShowFlaw extends SuperOfShowFlaw { - static Flaw fn = new Flaw(new Integer(3)); + static Flaw fn = new Flaw(Integer.valueOf(3)); Flaw m(){return fn;} } diff --git a/langtools/test/tools/javac/OverrideChecks/T4721069.java b/langtools/test/tools/javac/OverrideChecks/T4721069.java index 18259f791d4..ea8f4da567d 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4721069.java +++ b/langtools/test/tools/javac/OverrideChecks/T4721069.java @@ -12,7 +12,7 @@ interface I { static class T { static void f(I i) { if (i == null) { - Integer x = new Integer(2); + Integer x = Integer.valueOf(2); } else { I x = i; x.getClass(); diff --git a/langtools/test/tools/javac/generics/Nonlinear.java b/langtools/test/tools/javac/generics/Nonlinear.java index f952d74c300..36004a07907 100644 --- a/langtools/test/tools/javac/generics/Nonlinear.java +++ b/langtools/test/tools/javac/generics/Nonlinear.java @@ -22,7 +22,7 @@ public class Nonlinear { // the program. public static void main (String [] args) { - Integer x = new Integer (5); + Integer x = Integer.valueOf(5); String y = castit (x); System.out.println (y); } diff --git a/langtools/test/tools/javac/generics/odersky/BadTest4.java b/langtools/test/tools/javac/generics/odersky/BadTest4.java index 1ad3e576b0c..516318d8147 100644 --- a/langtools/test/tools/javac/generics/odersky/BadTest4.java +++ b/langtools/test/tools/javac/generics/odersky/BadTest4.java @@ -30,7 +30,7 @@ class BadTest4 { static Cell makeCell(A x) { return new Cell(x); } static A id(A x) { return x; } - static Integer i = new Integer(1); + static Integer i = Integer.valueOf(1); static Number n = i; public static void main(String[] args) { diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.java b/langtools/test/tools/javac/lambda/8074381/T8074381a.java index 7b7b9dd6cc2..d11944d3926 100644 --- a/langtools/test/tools/javac/lambda/8074381/T8074381a.java +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java @@ -13,6 +13,7 @@ class T8074381a { boolean m(String s); } + @SuppressWarnings("deprecation") void testRaw() { Sub s1 = c -> true; Sub s2 = Boolean::new; @@ -22,6 +23,7 @@ class T8074381a { }; } + @SuppressWarnings("deprecation") void testNonRaw() { Sub s1 = c -> true; Sub s2 = Boolean::new; diff --git a/langtools/test/tools/javac/lambda/8074381/T8074381a.out b/langtools/test/tools/javac/lambda/8074381/T8074381a.out index f7ba487c586..d969c59a919 100644 --- a/langtools/test/tools/javac/lambda/8074381/T8074381a.out +++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out @@ -1,4 +1,4 @@ -T8074381a.java:17:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) T8074381a.java:18:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) -T8074381a.java:19:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup +T8074381a.java:19:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub) +T8074381a.java:20:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup 3 errors diff --git a/langtools/test/tools/javac/lambda/TargetType27.java b/langtools/test/tools/javac/lambda/TargetType27.java index 762a4ab8bef..dcb76901c7e 100644 --- a/langtools/test/tools/javac/lambda/TargetType27.java +++ b/langtools/test/tools/javac/lambda/TargetType27.java @@ -15,6 +15,6 @@ class TargetType27 { F m(F f) { return null; } void test() { - m((String s1) -> (String s2) -> new Integer(1)); + m((String s1) -> (String s2) -> Integer.valueOf(1)); } } From 28ed819ae90b622f2eedaaceb41a798a8c6af080 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 18 Apr 2016 19:14:50 -0700 Subject: [PATCH 024/225] 8154500: fix handling of jdk.launcher.patch.* in tests Reviewed-by: ksrini --- .../javadoc/tool/6964914/TestStdDoclet.java | 19 +++++++++++++----- .../javadoc/tool/6964914/TestUserDoclet.java | 19 ++++++++++++++---- .../tools/javadoc/6964914/TestStdDoclet.java | 19 +++++++++++++----- .../tools/javadoc/6964914/TestUserDoclet.java | 20 ++++++++++++++----- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java index 3fff0e1252d..3803a5241e9 100644 --- a/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.java +++ b/langtools/test/jdk/javadoc/tool/6964914/TestStdDoclet.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 @@ -28,6 +28,7 @@ */ import java.io.*; +import java.util.*; /** * Dummy javadoc comment. @@ -54,13 +55,21 @@ public class TestStdDoclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestStdDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-classpath", ".", // insulates us from ambient classpath "-Xdoclint:none", "-package", - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java index cec6d274d24..02c6ec882b3 100644 --- a/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java +++ b/langtools/test/jdk/javadoc/tool/6964914/TestUserDoclet.java @@ -30,7 +30,10 @@ import java.io.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -63,12 +66,20 @@ public class TestUserDoclet implements Doclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestUserDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-doclet", thisClassName, "-docletpath", testClasses.getPath(), - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java b/langtools/test/tools/javadoc/6964914/TestStdDoclet.java index d30ae8322ff..2ab14c0124c 100644 --- a/langtools/test/tools/javadoc/6964914/TestStdDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestStdDoclet.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 @@ -28,6 +28,7 @@ */ import java.io.*; +import java.util.*; /** * Dummy javadoc comment. @@ -54,13 +55,21 @@ public class TestStdDoclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestStdDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-classpath", ".", // insulates us from ambient classpath "-Xdoclint:none", "-package", - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); diff --git a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java b/langtools/test/tools/javadoc/6964914/TestUserDoclet.java index a09847073b2..7cb2041cfe6 100644 --- a/langtools/test/tools/javadoc/6964914/TestUserDoclet.java +++ b/langtools/test/tools/javadoc/6964914/TestUserDoclet.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 @@ -29,6 +29,8 @@ */ import java.io.*; +import java.util.*; + import com.sun.javadoc.Doclet; import com.sun.javadoc.RootDoc; @@ -55,12 +57,20 @@ public class TestUserDoclet extends Doclet { // run javadoc in separate process to ensure doclet executed under // normal user conditions w.r.t. classloader String thisClassName = TestUserDoclet.class.getName(); - Process p = new ProcessBuilder() - .command(javadoc.getPath(), - "-J-Xpatch:" + System.getProperty("jdk.launcher.patch.0", ""), + List cmdArgs = new ArrayList<>(); + cmdArgs.add(javadoc.getPath()); + int i = 0; + String prop; + while ((prop = System.getProperty("jdk.launcher.patch." + (i++))) != null) { + cmdArgs.add("-J-Xpatch:" + prop); + } + cmdArgs.addAll(Arrays.asList( "-doclet", thisClassName, "-docletpath", testClasses.getPath(), - new File(testSrc, thisClassName + ".java").getPath()) + new File(testSrc, thisClassName + ".java").getPath() + )); + Process p = new ProcessBuilder() + .command(cmdArgs) .redirectErrorStream(true) .start(); From d6521300a0ff2896edd2e63113f9e740d855a71a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 19 Apr 2016 14:16:39 +0200 Subject: [PATCH 025/225] 7020499: Project Coin: improvements to try-with-resources desugaring Avoid unnecessary check for resource nullness if the resource is known to be non-null; put resource closing code in a method that is shared by multiple try-with-resources. Reviewed-by: darcy, mcimadamore, vromero --- .../com/sun/tools/javac/comp/Lower.java | 105 +++++++++++- .../TryWithResources/TwrAvoidNullCheck.java | 125 ++++++++++++++ .../javac/TryWithResources/TwrClose.java | 140 ++++++++++++++++ .../TryWithResources/TwrShareCloseCode.java | 158 ++++++++++++++++++ .../referenceinfos/ResourceVariable.java | 14 +- .../tools/javac/flow/tests/TestCaseTry.java | 10 +- 6 files changed, 533 insertions(+), 19 deletions(-) create mode 100644 langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrClose.java create mode 100644 langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index 197cff5c3be..0bb1d96a7fb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -86,6 +86,7 @@ public class Lower extends TreeTranslator { private final TypeEnvs typeEnvs; private final Name dollarAssertionsDisabled; private final Name classDollar; + private final Name dollarCloseResource; private final Types types; private final boolean debugLower; private final PkgInfo pkginfoOpt; @@ -109,6 +110,8 @@ public class Lower extends TreeTranslator { fromString(target.syntheticNameChar() + "assertionsDisabled"); classDollar = names. fromString("class" + target.syntheticNameChar()); + dollarCloseResource = names. + fromString(target.syntheticNameChar() + "closeResource"); types = Types.instance(context); Options options = Options.instance(context); @@ -1648,9 +1651,11 @@ public class Lower extends TreeTranslator { ListBuffer stats = new ListBuffer<>(); JCTree resource = resources.head; JCExpression expr = null; + boolean resourceNonNull; if (resource instanceof JCVariableDecl) { JCVariableDecl var = (JCVariableDecl) resource; expr = make.Ident(var.sym).setType(resource.type); + resourceNonNull = var.init != null && TreeInfo.skipParens(var.init).hasTag(NEWCLASS); stats.add(var); } else { Assert.check(resource instanceof JCExpression); @@ -1665,6 +1670,7 @@ public class Lower extends TreeTranslator { JCVariableDecl syntheticTwrVarDecl = make.VarDef(syntheticTwrVar, (JCExpression)resource); expr = (JCExpression)make.Ident(syntheticTwrVar); + resourceNonNull = TreeInfo.skipParens(resource).hasTag(NEWCLASS); stats.add(syntheticTwrVarDecl); } @@ -1694,7 +1700,7 @@ public class Lower extends TreeTranslator { int oldPos = make.pos; make.at(TreeInfo.endPos(block)); - JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr); + JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr, resourceNonNull); make.at(oldPos); JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, finallyCanCompleteNormally, depth + 1), @@ -1706,7 +1712,96 @@ public class Lower extends TreeTranslator { return newBlock; } - private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) { + /**If the estimated number of copies the close resource code in a single class is above this + * threshold, generate and use a method for the close resource code, leading to smaller code. + * As generating a method has overhead on its own, generating the method for cases below the + * threshold could lead to an increase in code size. + */ + public static final int USE_CLOSE_RESOURCE_METHOD_THRESHOLD = 4; + + private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource, + boolean resourceNonNull) { + MethodSymbol closeResource = (MethodSymbol)lookupSynthetic(dollarCloseResource, + currentClass.members()); + + if (closeResource == null && shouldUseCloseResourceMethod()) { + closeResource = new MethodSymbol( + PRIVATE | STATIC | SYNTHETIC, + dollarCloseResource, + new MethodType( + List.of(syms.throwableType, syms.autoCloseableType), + syms.voidType, + List.nil(), + syms.methodClass), + currentClass); + enterSynthetic(resource.pos(), closeResource, currentClass.members()); + + JCMethodDecl md = make.MethodDef(closeResource, null); + List params = md.getParameters(); + md.body = make.Block(0, List.of(makeTwrCloseStatement(params.get(0).sym, + make.Ident(params.get(1))))); + + JCClassDecl currentClassDecl = classDef(currentClass); + currentClassDecl.defs = currentClassDecl.defs.prepend(md); + } + + JCStatement closeStatement; + + if (closeResource != null) { + //$closeResource(#primaryException, #resource) + closeStatement = make.Exec(make.Apply(List.nil(), + make.Ident(closeResource), + List.of(make.Ident(primaryException), + resource) + ).setType(syms.voidType)); + } else { + closeStatement = makeTwrCloseStatement(primaryException, resource); + } + + JCStatement finallyStatement; + + if (resourceNonNull) { + finallyStatement = closeStatement; + } else { + // if (#resource != null) { $closeResource(...); } + finallyStatement = make.If(makeNonNullCheck(resource), + closeStatement, + null); + } + + return make.Block(0L, + List.of(finallyStatement)); + } + //where: + private boolean shouldUseCloseResourceMethod() { + class TryFinder extends TreeScanner { + int closeCount; + @Override + public void visitTry(JCTry tree) { + boolean empty = tree.body.stats.isEmpty(); + + for (JCTree r : tree.resources) { + closeCount += empty ? 1 : 2; + empty = false; //with multiple resources, only the innermost try can be empty. + } + super.visitTry(tree); + } + @Override + public void scan(JCTree tree) { + if (useCloseResourceMethod()) + return; + super.scan(tree); + } + boolean useCloseResourceMethod() { + return closeCount >= USE_CLOSE_RESOURCE_METHOD_THRESHOLD; + } + } + TryFinder tryFinder = new TryFinder(); + tryFinder.scan(classDef(currentClass)); + return tryFinder.useCloseResourceMethod(); + } + + private JCStatement makeTwrCloseStatement(Symbol primaryException, JCExpression resource) { // primaryException.addSuppressed(catchException); VarSymbol catchException = new VarSymbol(SYNTHETIC, make.paramName(2), @@ -1731,11 +1826,7 @@ public class Lower extends TreeTranslator { tryTree, makeResourceCloseInvocation(resource)); - // if (#resource != null) { if (primaryException ... } - return make.Block(0L, - List.of(make.If(makeNonNullCheck(resource), - closeIfStatement, - null))); + return closeIfStatement; } private JCStatement makeResourceCloseInvocation(JCExpression resource) { diff --git a/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java b/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.java new file mode 100644 index 00000000000..f095b92b571 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAvoidNullCheck.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. + */ + +/* + * @test + * @bug 7020499 + * @summary Verify that try-with-resources desugaring is not generating unnecessary null checks + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask TwrAvoidNullCheck + * @run main TwrAvoidNullCheck + */ + +import java.io.IOException; +import java.util.Arrays; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.Lower; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBinary; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import com.sun.tools.javac.util.List; + +import toolbox.ToolBox; + +public class TwrAvoidNullCheck { + public static void main(String... args) throws IOException { + new TwrAvoidNullCheck().run(); + } + void run() throws IOException { + run("new Test()", false); + run("null", true); + run("System.getProperty(\"test\") != null ? new Test() : null", true); + } + void run(String resourceSpecification, boolean expected) throws IOException { + String template = "public class Test implements AutoCloseable {\n" + + " void t() {\n" + + " try (Test resource = RESOURCE) { }\n" + + " }\n" + + " public void close() { }\n" + + "}\n"; + String code = template.replace("RESOURCE", resourceSpecification); + Context ctx = new Context(); + DumpLower.preRegister(ctx); + Iterable files = Arrays.asList(new ToolBox.JavaSource(code)); + JavacTask task = JavacTool.create().getTask(null, null, null, null, null, files, ctx); + task.call(); + + boolean hasNullCheck = ((DumpLower) DumpLower.instance(ctx)).hasNullCheck; + + if (hasNullCheck != expected) { + throw new IllegalStateException("expected: " + expected + + "; actual: " + hasNullCheck + + "; code: " + code); + } + } + + static class DumpLower extends Lower { + + public static void preRegister(Context ctx) { + ctx.put(lowerKey, new Factory() { + @Override + public Lower make(Context c) { + return new DumpLower(c); + } + }); + } + + public DumpLower(Context context) { + super(context); + } + + boolean hasNullCheck; + + @Override + public List translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + List result = super.translateTopLevelClass(env, cdef, make); + + new TreeScanner() { + @Override + public void visitBinary(JCBinary tree) { + hasNullCheck |= tree.operator.getSimpleName().contentEquals("!=") && + "resource".equals(String.valueOf(TreeInfo.name(tree.lhs))) && + TreeInfo.isNull(tree.rhs); + super.visitBinary(tree); + } + }.scan(result); + + return result; + } + + } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrClose.java b/langtools/test/tools/javac/TryWithResources/TwrClose.java new file mode 100644 index 00000000000..504a05bd5b4 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrClose.java @@ -0,0 +1,140 @@ +/* + * 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 7020499 + * @summary Verify that the close resource code works properly in all cases + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox TwrClose + * @run main TwrClose + */ + +import javax.tools.JavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.tools.javac.comp.Lower; + +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class TwrClose { + + public static void main(String... args) throws Exception { + for (int i = 1; i < Lower.USE_CLOSE_RESOURCE_METHOD_THRESHOLD * 2; i++) { + new TwrClose().compile(i); + } + } + + ToolBox tb = new ToolBox(); + JavaFileManager fm = ToolProvider.getSystemJavaCompiler() + .getStandardFileManager(null, null, null); + + void compile(int trysCount) throws Exception { + StringBuilder testInvocations = new StringBuilder(); + StringBuilder testMethods = new StringBuilder(); + + for (int i = 0; i < trysCount; i++) { + testInvocations.append(TEST_INVOCATIONS_TEMPLATE.replace("#N", Integer.toString(i))); + testMethods.append(TEST_METHOD_TEMPLATE.replace("#N", Integer.toString(i))); + } + + String sourceCode = FILE_TEMPLATE.replace("#TEST_INVOCATIONS", testInvocations.toString()) + .replace("#TEST_METHODS", testMethods.toString()); + + System.err.println("analyzing:"); + System.err.println(sourceCode); + + try (ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager()) { + new JavacTask(tb).fileManager(mfm) + .sources(sourceCode) + .run() + .writeAll(); + ClassLoader cl = new ClassLoader(TwrClose.class.getClassLoader()) { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] data = mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, name); + if (data != null) { + return defineClass(name, data, 0, data.length); + } + return super.findClass(name); + } + }; + + ((Runnable) cl.loadClass("Test").newInstance()).run(); + } + } + + final String TEST_INVOCATIONS_TEMPLATE = + " test#N(false, false, Arrays.asList(\"close\"));\n" + + " test#N(false, true, Arrays.asList(\"close\", \"close-exception\"));\n" + + " test#N(true, false, Arrays.asList(\"close\", \"inTwr\"));\n" + + " test#N(true, true, Arrays.asList(\"close\", \"inTwr\", \"close-exception\"));\n"; + + final String TEST_METHOD_TEMPLATE = + " private void test#N(boolean failInTwr, boolean failOnClose,\n" + + " List expectedMessages) {\n" + + " List messages = new ArrayList<>();\n" + + " try {\n" + + " try (CloseableImpl c = new CloseableImpl(messages, failOnClose)) {\n" + + " if (failInTwr)\n" + + " throw new IllegalStateException(\"inTwr\");\n" + + " }\n" + + " } catch (IllegalStateException ex) {\n" + + " messages.add(ex.getMessage());\n" + + " for (Throwable t : ex.getSuppressed()) {\n" + + " messages.add(t.getMessage());\n" + + " }\n" + + " }\n" + + " if (!expectedMessages.equals(messages))\n" + + " throw new AssertionError(\"Expected and actual messages differ; expectedMessages=\" +\n" + + " expectedMessages + \"; actual=\" + messages);\n" + + " }\n"; + + final String FILE_TEMPLATE = + "import java.util.*;\n" + + "public class Test implements Runnable {\n" + + " public void run() {\n" + + "#TEST_INVOCATIONS" + + " }\n" + + "#TEST_METHODS" + + " static class CloseableImpl implements AutoCloseable {\n" + + " private final List messages;\n" + + " private final boolean failOnClose;\n" + + " public CloseableImpl(List messages, boolean failOnClose) {\n" + + " this.messages = messages;\n" + + " this.failOnClose = failOnClose;\n" + + " }\n" + + " @Override\n" + + " public void close() {\n" + + " messages.add(\"close\");\n" + + " if (failOnClose)\n" + + " throw new IllegalStateException(\"close-exception\");\n" + + " }\n" + + " }\n" + + "}\n"; +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java b/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java new file mode 100644 index 00000000000..0d6ff045ef7 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrShareCloseCode.java @@ -0,0 +1,158 @@ +/* + * 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 7020499 + * @summary Verify that the code that closes the resources is shared by among try-with-resources + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox TwrShareCloseCode + * @run main TwrShareCloseCode + */ + +import java.io.IOException; +import java.util.Arrays; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.Lower; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import com.sun.tools.javac.util.List; + +import toolbox.ToolBox; + +public class TwrShareCloseCode { + public static void main(String... args) throws IOException { + new TwrShareCloseCode().run(); + } + + void run() throws IOException { + run("try (Test t1 = new Test()) { }", true); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }", true); + run("try (Test t1 = new Test();\n" + + " Test t2 = new Test()) { }", true); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }", true); + run("try (Test t1 = new Test();\n" + + " Test t2 = new Test();\n" + + " Test t3 = new Test()) { }", false); + run("try (Test t1 = new Test()) { }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }\n" + + "try (Test t4 = new Test()) { }", false); + + run("try (Test t1 = new Test()) { i++; }", true); + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { i++; }", false); + + run("try (Test t1 = new Test(); Test t2 = new Test()) { i++; }", false); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { }", true); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { }\n" + + "try (Test t3 = new Test()) { }", false); + + run("try (Test t1 = new Test()) { i++; }\n" + + "try (Test t2 = new Test()) { i++; }\n" + + "try (Test t3 = new Test()) { }", false); + } + void run(String trySpec, boolean expected) throws IOException { + String template = "public class Test implements AutoCloseable {\n" + + " void t(int i) {\n" + + " TRY\n" + + " }\n" + + " public void close() { }\n" + + "}\n"; + String code = template.replace("TRY", trySpec); + Context ctx = new Context(); + DumpLower.preRegister(ctx); + Iterable files = Arrays.asList(new ToolBox.JavaSource(code)); + JavacTask task = JavacTool.create().getTask(null, null, null, null, null, files, ctx); + task.call(); + boolean actual = ((DumpLower) DumpLower.instance(ctx)).closeSeen; + + if (expected != actual) { + throw new IllegalStateException("expected: " + expected + "; actual: " + actual + "; code:\n" + code); + } + } + + static class DumpLower extends Lower { + + public static void preRegister(Context ctx) { + ctx.put(lowerKey, new Factory() { + @Override + public Lower make(Context c) { + return new DumpLower(c); + } + }); + } + + public DumpLower(Context context) { + super(context); + } + + boolean closeSeen; + + @Override + public List translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + List result = super.translateTopLevelClass(env, cdef, make); + + new TreeScanner() { + @Override + public void visitMethodDef(JCMethodDecl tree) { + if (!tree.name.contentEquals("t")) + return; + + super.visitMethodDef(tree); + } + + @Override + public void visitApply(JCMethodInvocation tree) { + closeSeen |= TreeInfo.symbol(tree.meth).name.contentEquals("close"); + super.visitApply(tree); + } + }.scan(result); + + return result; + } + + } +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java index 266a3e8a592..b65535badf5 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/ResourceVariable.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 @@ -36,9 +36,9 @@ import static java.lang.System.lineSeparator; public class ResourceVariable { @TADescription(annotation = "TA", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {118}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {106}, lvarIndex = {1}) @TADescription(annotation = "TB", type = RESOURCE_VARIABLE, - lvarOffset = {22}, lvarLength = {35}, lvarIndex = {3}) + lvarOffset = {22}, lvarLength = {31}, lvarIndex = {3}) public String testResourceVariable() { return "public void f() throws IOException {" + lineSeparator() + @@ -49,7 +49,7 @@ public class ResourceVariable { } @TADescription(annotation = "RTAs", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {30}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {26}, lvarIndex = {1}) public String testRepeatedAnnotation1() { return "public void f() throws IOException {" + lineSeparator() + @@ -58,7 +58,7 @@ public class ResourceVariable { } @TADescription(annotation = "RTAs", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {30}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {26}, lvarIndex = {1}) public String testRepeatedAnnotation2() { return "public void f() throws IOException {" + lineSeparator() + @@ -67,9 +67,9 @@ public class ResourceVariable { } @TADescription(annotation = "TA", type = RESOURCE_VARIABLE, - lvarOffset = {10}, lvarLength = {118}, lvarIndex = {1}) + lvarOffset = {10}, lvarLength = {106}, lvarIndex = {1}) @TADescription(annotation = "TB", type = RESOURCE_VARIABLE, - lvarOffset = {22}, lvarLength = {35}, lvarIndex = {3}) + lvarOffset = {22}, lvarLength = {31}, lvarIndex = {3}) public String testSeveralVariablesInTryWithResources() { return "public void f() throws IOException {" + lineSeparator() + diff --git a/langtools/test/tools/javac/flow/tests/TestCaseTry.java b/langtools/test/tools/javac/flow/tests/TestCaseTry.java index b3a3762bd20..dbc1f2b9d74 100644 --- a/langtools/test/tools/javac/flow/tests/TestCaseTry.java +++ b/langtools/test/tools/javac/flow/tests/TestCaseTry.java @@ -52,9 +52,9 @@ public class TestCaseTry { o = ""; } - @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=38) - @AliveRange(varName="o", bytecodeStart=103, bytecodeLength=3) - @AliveRange(varName="o", bytecodeStart=110, bytecodeLength=1) + @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=13) + @AliveRange(varName="o", bytecodeStart=53, bytecodeLength=3) + @AliveRange(varName="o", bytecodeStart=60, bytecodeLength=1) void m3() { Object o; try (BufferedReader br = @@ -65,8 +65,8 @@ public class TestCaseTry { o = ""; } - @AliveRange(varName="o", bytecodeStart=12, bytecodeLength=96) - @AliveRange(varName="o", bytecodeStart=112, bytecodeLength=1) + @AliveRange(varName="o", bytecodeStart=12, bytecodeLength=46) + @AliveRange(varName="o", bytecodeStart=62, bytecodeLength=1) void m4() { String o; try (BufferedReader br = From 6921adecb8cb37b162181cd9665a34436c8b781c Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 20 Apr 2016 08:30:30 -0700 Subject: [PATCH 026/225] 8154445: JShell: Drop residual use of addReads from jshell Reviewed-by: alanb, ksrini --- .../share/classes/jdk/internal/jshell/remote/RemoteAgent.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java index 1a0cec3444f..f7d8e4a186d 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java @@ -113,7 +113,6 @@ class RemoteAgent { } Method doitMethod; try { - this.getClass().getModule().addReads(klass.getModule()); this.getClass().getModule().addExports(RemoteResolutionException.class.getPackage().getName(), klass.getModule()); doitMethod = klass.getDeclaredMethod(DOIT_METHOD_NAME, new Class[0]); doitMethod.setAccessible(true); @@ -184,7 +183,6 @@ class RemoteAgent { break; } try { - this.getClass().getModule().addReads(klass.getModule()); Field var = klass.getDeclaredField(varname); var.setAccessible(true); Object res = var.get(null); From ecfc09db1610dd4e7bb52e45d1fe82d6fa4e3768 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 20 Apr 2016 08:35:44 -0700 Subject: [PATCH 027/225] 8153551: jshell tool: no longer a mechanism to see current feedback modes Reviewed-by: jlahoda --- .../classes/jdk/internal/jshell/tool/Feedback.java | 11 ++++++++--- langtools/test/jdk/jshell/ToolFormatTest.java | 8 +++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java index 8ebf1216611..958116c6987 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -606,6 +606,7 @@ class Feedback { fluffmsg("jshell.msg.feedback.mode", mode.name); } else { fluffmsg("jshell.msg.see", "/help /set feedback"); + printFeedbackModes(); } return valid; } @@ -671,13 +672,17 @@ class Feedback { } else { errorat("jshell.err.feedback.ambiguous.mode", umode); } - fluffmsg("jshell.msg.feedback.mode.following"); - modeMap.keySet().stream() - .forEach(mk -> fluff(" %s", mk)); + printFeedbackModes(); return null; } } + void printFeedbackModes() { + fluffmsg("jshell.msg.feedback.mode.following"); + modeMap.keySet().stream() + .forEach(mk -> fluff(" %s", mk)); + } + // Test if the format string is correctly final String nextFormat() { String format = at.next(); diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java index 6d61fba4671..f4758f8a876 100644 --- a/langtools/test/jdk/jshell/ToolFormatTest.java +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8148316 8148317 8151755 8152246 + * @bug 8148316 8148317 8151755 8152246 8153551 * @summary Tests for output customization * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -155,6 +155,12 @@ public class ToolFormatTest extends ReplToolTesting { } } + public void testShowFeedbackModes() { + test( + (a) -> assertCommandOutputContains(a, "/set feedback", "normal") + ); + } + public void testSetNewModeQuiet() { try { test( From 25c9be01d56ca788a421ec2cd9bfa7cd2e5b31ce Mon Sep 17 00:00:00 2001 From: Oleg Barbashov Date: Wed, 20 Apr 2016 17:17:56 -0700 Subject: [PATCH 028/225] 8151777: Add "@index" tag to the sampleapi generator Reviewed-by: ksrini, bpatel --- .../sampleapi/lib/sampleapi/SampleApi.java | 5 ++- .../generator/DocCommentGenerator.java | 43 +++++++++++++++---- .../sampleapi/generator/PackageGenerator.java | 4 +- .../sampleapi/lib/sampleapi/SampleApi.java | 5 ++- .../generator/DocCommentGenerator.java | 43 +++++++++++++++---- .../sampleapi/generator/PackageGenerator.java | 4 +- 6 files changed, 80 insertions(+), 24 deletions(-) diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java index 7b72cf0ba81..536787bcc26 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/SampleApi.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 @@ -53,5 +53,8 @@ public class SampleApi { public Fault(String msg) { super(msg); } + public Fault(String msg, Throwable th) { + super(msg, th); + } } } diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java index 691cd90eafe..b3ca960fe4e 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/DocCommentGenerator.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,6 +32,8 @@ import javax.lang.model.element.Modifier; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; +import java.util.HashMap; +import java.util.Map; class DocCommentGenerator { @@ -99,14 +101,25 @@ class DocCommentGenerator { LITERAL("@literal", "Use < and > brackets instead of < and > escapes."), CODE("@code", "(i) -> new Abc((i > 0) ? (i << 1) : 0)"), LINK("@link", ""), - VALUE("@value", ""); + VALUE("@value", ""), + INDEX("@index", "", true); String tagName; String tagValue; + boolean counted; + Map counters; InlineTag(String tagName, String tagValue) { + this(tagName, tagValue, false); + } + + InlineTag(String tagName, String tagValue, boolean counted) { this.tagName = tagName; this.tagValue = tagValue; + this.counted = counted; + if (counted) { + counters = new HashMap<>(); + } } public String toString() { @@ -114,9 +127,14 @@ class DocCommentGenerator { } public String value(String value) { + String name = ((tagValue.length() != 0) ? " " + tagValue : "") + + ((value.length() != 0) ? " " + value : ""); + if (counted && !counters.containsKey(name)) { + counters.put(name, 0); + } return "{" + tagName - + ((tagValue.length() != 0) ? " " + tagValue : "") - + ((value.length() != 0) ? " " + value : "") + + name + + (counted ? "_" + counters.put(name, counters.get(name) + 1) : "") + "}"; } } @@ -179,7 +197,8 @@ class DocCommentGenerator { // public String getPackageComment() { - return Text.LOREMIPSUM + return InlineTag.INDEX.value("PackageCommentLabel") + " " + + Text.LOREMIPSUM + "\n

    " + Text.LIEUROPANLINGUES + "\n" + Text.CODE + "\n" + LinkTag.nextLink() @@ -192,7 +211,9 @@ class DocCommentGenerator { static int serialValIdx = 0; public String getBaseComment(JCClassDecl baseDecl, boolean toplevel) { - String buildComment = Text.LIEUROPANLINGUES + "\n"; + String buildComment = InlineTag.INDEX.value("BaseCommentLabel") + " "; + + buildComment += Text.LIEUROPANLINGUES + "\n"; buildComment += "

    It is possible to see inlined code:\n" + InlineTag.CODE @@ -237,8 +258,9 @@ class DocCommentGenerator { } public String getConstComment() { - String buildComment = Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; + String buildComment = InlineTag.INDEX.value("ConstCommentLabel") + " "; + buildComment += Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; buildComment += LinkTag.nextLink() + "\n"; buildComment += LinkTag.nextSee() + "\n"; buildComment += Tag.SINCE + "\n"; @@ -249,8 +271,9 @@ class DocCommentGenerator { public String getFieldComment(JCClassDecl baseDecl, JCVariableDecl varDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; + String buildComment = InlineTag.INDEX.value("FieldCommentLabel") + " "; + buildComment += Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; Set mods = varDecl.getModifiers().getFlags(); String varName = varDecl.getName().toString(); @@ -299,7 +322,9 @@ class DocCommentGenerator { public String getMethodComment(JCClassDecl baseDecl, JCMethodDecl methodDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; + String buildComment = InlineTag.INDEX.value("MethodCommentLabel") + " "; + + buildComment += Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; buildComment += "

    " + LinkTag.nextLink() + "\n"; diff --git a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java index 05e5524fc0d..8e7ed7c1d4c 100644 --- a/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.java +++ b/langtools/test/jdk/javadoc/tool/sampleapi/lib/sampleapi/generator/PackageGenerator.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 @@ -125,7 +125,7 @@ public class PackageGenerator { processTopLevel((Element)node); } } catch (ParserConfigurationException | SAXException | IOException e) { - throw new Fault("Error parsing dataset " + dsName); + throw new Fault("Error parsing dataset " + dsName, e); } fx = false; diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java index 7b72cf0ba81..536787bcc26 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/SampleApi.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 @@ -53,5 +53,8 @@ public class SampleApi { public Fault(String msg) { super(msg); } + public Fault(String msg, Throwable th) { + super(msg, th); + } } } diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java index 691cd90eafe..b3ca960fe4e 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/DocCommentGenerator.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,6 +32,8 @@ import javax.lang.model.element.Modifier; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; +import java.util.HashMap; +import java.util.Map; class DocCommentGenerator { @@ -99,14 +101,25 @@ class DocCommentGenerator { LITERAL("@literal", "Use < and > brackets instead of < and > escapes."), CODE("@code", "(i) -> new Abc((i > 0) ? (i << 1) : 0)"), LINK("@link", ""), - VALUE("@value", ""); + VALUE("@value", ""), + INDEX("@index", "", true); String tagName; String tagValue; + boolean counted; + Map counters; InlineTag(String tagName, String tagValue) { + this(tagName, tagValue, false); + } + + InlineTag(String tagName, String tagValue, boolean counted) { this.tagName = tagName; this.tagValue = tagValue; + this.counted = counted; + if (counted) { + counters = new HashMap<>(); + } } public String toString() { @@ -114,9 +127,14 @@ class DocCommentGenerator { } public String value(String value) { + String name = ((tagValue.length() != 0) ? " " + tagValue : "") + + ((value.length() != 0) ? " " + value : ""); + if (counted && !counters.containsKey(name)) { + counters.put(name, 0); + } return "{" + tagName - + ((tagValue.length() != 0) ? " " + tagValue : "") - + ((value.length() != 0) ? " " + value : "") + + name + + (counted ? "_" + counters.put(name, counters.get(name) + 1) : "") + "}"; } } @@ -179,7 +197,8 @@ class DocCommentGenerator { // public String getPackageComment() { - return Text.LOREMIPSUM + return InlineTag.INDEX.value("PackageCommentLabel") + " " + + Text.LOREMIPSUM + "\n

    " + Text.LIEUROPANLINGUES + "\n" + Text.CODE + "\n" + LinkTag.nextLink() @@ -192,7 +211,9 @@ class DocCommentGenerator { static int serialValIdx = 0; public String getBaseComment(JCClassDecl baseDecl, boolean toplevel) { - String buildComment = Text.LIEUROPANLINGUES + "\n"; + String buildComment = InlineTag.INDEX.value("BaseCommentLabel") + " "; + + buildComment += Text.LIEUROPANLINGUES + "\n"; buildComment += "

    It is possible to see inlined code:\n" + InlineTag.CODE @@ -237,8 +258,9 @@ class DocCommentGenerator { } public String getConstComment() { - String buildComment = Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; + String buildComment = InlineTag.INDEX.value("ConstCommentLabel") + " "; + buildComment += Text.NOWISTHETIME + " " + Text.BROWNFOX + "\n"; buildComment += LinkTag.nextLink() + "\n"; buildComment += LinkTag.nextSee() + "\n"; buildComment += Tag.SINCE + "\n"; @@ -249,8 +271,9 @@ class DocCommentGenerator { public String getFieldComment(JCClassDecl baseDecl, JCVariableDecl varDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; + String buildComment = InlineTag.INDEX.value("FieldCommentLabel") + " "; + buildComment += Text.BROWNFOX + "

    " + Text.NOWISTHETIME + "\n"; Set mods = varDecl.getModifiers().getFlags(); String varName = varDecl.getName().toString(); @@ -299,7 +322,9 @@ class DocCommentGenerator { public String getMethodComment(JCClassDecl baseDecl, JCMethodDecl methodDecl, boolean isFxStyle) { - String buildComment = Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; + String buildComment = InlineTag.INDEX.value("MethodCommentLabel") + " "; + + buildComment += Text.BROWNFOX + "\n

    " + Text.THISPANGRAM + "\n"; buildComment += "

    " + LinkTag.nextLink() + "\n"; diff --git a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java index 05e5524fc0d..8e7ed7c1d4c 100644 --- a/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.java +++ b/langtools/test/tools/javadoc/sampleapi/lib/sampleapi/generator/PackageGenerator.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 @@ -125,7 +125,7 @@ public class PackageGenerator { processTopLevel((Element)node); } } catch (ParserConfigurationException | SAXException | IOException e) { - throw new Fault("Error parsing dataset " + dsName); + throw new Fault("Error parsing dataset " + dsName, e); } fx = false; From c413f5eb4419bdf83ddcfc672a4230e42a0e36fa Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:16 -0700 Subject: [PATCH 029/225] Added tag jdk-9+115 for changeset c36230ee15d9 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 8032358a539..e8881f37c97 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -357,3 +357,4 @@ f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 3d4117c36559b344a73f786d39cc7626b4d8e2c0 jdk-9+112 4e87682893e662421af10a62d29ae822ce0fea04 jdk-9+113 cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114 +31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115 From e85033c628f607fee4e9365938534ab56cedbfd3 Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Tue, 22 Mar 2016 13:14:12 +0100 Subject: [PATCH 030/225] 8048146: sjavac uses unexpected exit code of -1 Changed exit codes for sjavac Reviewed-by: jlahoda --- .../sun/tools/sjavac/CompileJavaPackages.java | 7 ++--- .../sun/tools/sjavac/client/ClientMain.java | 8 +++-- .../sun/tools/sjavac/client/SjavacClient.java | 25 +++++++++------- .../tools/sjavac/comp/CompilationService.java | 21 +++++++++----- .../sun/tools/sjavac/comp/PooledSjavac.java | 3 +- .../com/sun/tools/sjavac/comp/SjavacImpl.java | 29 ++++++++++--------- .../sjavac/server/CompilationSubResult.java | 16 +++++----- .../tools/sjavac/server/IdleResetSjavac.java | 6 ++-- .../tools/sjavac/server/RequestHandler.java | 5 ++-- .../sun/tools/sjavac/server/ServerMain.java | 6 ++-- .../com/sun/tools/sjavac/server/Sjavac.java | 8 ++--- .../sun/tools/sjavac/server/SjavacServer.java | 6 ++-- langtools/test/tools/sjavac/HiddenFiles.java | 3 +- langtools/test/tools/sjavac/IdleShutdown.java | 6 ++-- .../tools/sjavac/IncludeExcludePatterns.java | 3 +- .../test/tools/sjavac/PooledExecution.java | 8 ++--- 16 files changed, 84 insertions(+), 76 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java index f6ac5d2ad44..18a079dad9d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java @@ -26,8 +26,6 @@ package com.sun.tools.sjavac; import java.io.File; -import java.io.IOException; -import java.io.Writer; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -42,9 +40,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.regex.Pattern; -import java.util.stream.Stream; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; @@ -283,7 +280,7 @@ public class CompileJavaPackages implements Transformer { } // Check the return values. - if (subResult.returnCode != 0) { + if (subResult.result != Result.OK) { rc = false; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java index 54c1e51952f..5ba63fed8d5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java @@ -28,6 +28,8 @@ package com.sun.tools.sjavac.client; import java.io.OutputStreamWriter; import java.io.Writer; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.AutoFlushWriter; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -58,7 +60,7 @@ public class ClientMain { options = Options.parseArgs(args); } catch (IllegalArgumentException e) { Log.error(e.getMessage()); - return -1; + return Result.CMDERR.exitCode; } Log.setLogLevel(options.getLogLevel()); @@ -73,13 +75,13 @@ public class ClientMain { Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); // Perform compilation - int rc = sjavac.compile(args); + Result result = sjavac.compile(args); // If sjavac is running in the foreground we should shut it down at this point if (!useServer) { sjavac.shutdown(); } - return rc; + return result.exitCode; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index 37fb47890c2..570530d7028 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -26,23 +26,20 @@ package com.sun.tools.sjavac.client; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.io.PrintStream; import java.io.PrintWriter; import java.io.Reader; -import java.io.Writer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Scanner; -import java.util.stream.Stream; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.options.OptionHelper; @@ -116,8 +113,8 @@ public class SjavacClient implements Sjavac { } @Override - public int compile(String[] args) { - int result = -1; + public Result compile(String[] args) { + Result result = null; try (Socket socket = tryConnect()) { PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); @@ -150,22 +147,28 @@ public class SjavacClient implements Sjavac { } if (type.equals(SjavacServer.LINE_TYPE_RC)) { - result = Integer.parseInt(content); + result = Main.Result.valueOf(content); } } } catch (PortFileInaccessibleException e) { Log.error("Port file inaccessible."); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } catch (IOException ioe) { Log.error("IOException caught during compilation: " + ioe.getMessage()); Log.debug(ioe); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Restore interrupt Log.error("Compilation interrupted."); Log.debug(ie); - result = CompilationSubResult.ERROR_FATAL; + result = Result.ERROR; } + + if (result == null) { + // No LINE_TYPE_RC was found. + result = Result.ERROR; + } + return result; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java index 0eb4f7e2358..bf55947827c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java @@ -42,6 +42,8 @@ import javax.tools.ToolProvider; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Dependencies; import com.sun.tools.javac.util.ListBuffer; @@ -80,7 +82,7 @@ public class CompilationService { Dependencies.GraphDependencies.preRegister(context); // Now setup the actual compilation - CompilationSubResult compilationResult = new CompilationSubResult(0); + CompilationSubResult compilationResult = new CompilationSubResult(Result.OK); // First deal with explicit source files on cmdline and in at file ListBuffer explicitJFOs = new ListBuffer<>(); @@ -97,7 +99,7 @@ public class CompilationService { // Create a log to capture compiler output StringWriter stderrLog = new StringWriter(); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + Result result; PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs); @@ -120,20 +122,23 @@ public class CompilationService { task.addTaskListener(pubApiCollector); task.addTaskListener(papVerifier); logJavacInvocation(args); - rc = task.doCall(); - Log.debug("javac returned with code " + rc); + result = task.doCall(); + Log.debug("javac result: " + result); sfm.flush(); + } else { + result = Result.ERROR; } } catch (Exception e) { Log.error(Util.getStackTrace(e)); stderrLog.append(Util.getStackTrace(e)); - rc = com.sun.tools.javac.main.Main.Result.ERROR; + result = Result.ERROR; } compilationResult.packageArtifacts = sfm.getPackageArtifacts(); - if (papVerifier.errorsDiscovered()) - rc = com.sun.tools.javac.main.Main.Result.ERROR; + if (papVerifier.errorsDiscovered()) { + result = Result.ERROR; + } compilationResult.packageDependencies = depsCollector.getDependencies(false); compilationResult.packageCpDependencies = depsCollector.getDependencies(true); @@ -141,7 +146,7 @@ public class CompilationService { compilationResult.packagePubapis = pubApiCollector.getPubApis(true); compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); compilationResult.stderr = stderrLog.toString(); - compilationResult.returnCode = rc.exitCode; + compilationResult.result = result; return compilationResult; } catch (IOException e) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java index 82be0ae3b16..f84d52d5296 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java @@ -25,6 +25,7 @@ package com.sun.tools.sjavac.comp; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.server.Sjavac; @@ -54,7 +55,7 @@ public class PooledSjavac implements Sjavac { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { Log log = Log.get(); try { return pool.submit(() -> { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index 4c39a70f779..3553fcf9075 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -41,6 +41,7 @@ import java.util.stream.Stream; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Context; import com.sun.tools.sjavac.JavacState; import com.sun.tools.sjavac.Log; @@ -69,36 +70,36 @@ import javax.tools.JavaFileManager; public class SjavacImpl implements Sjavac { @Override - public int compile(String[] args) { + public Result compile(String[] args) { Options options; try { options = Options.parseArgs(args); } catch (IllegalArgumentException e) { Log.error(e.getMessage()); - return RC_FATAL; + return Result.CMDERR; } if (!validateOptions(options)) - return RC_FATAL; + return Result.CMDERR; if (srcDstOverlap(options.getSources(), options.getDestDir())) { - return RC_FATAL; + return Result.CMDERR; } if (!createIfMissing(options.getDestDir())) - return RC_FATAL; + return Result.ERROR; Path stateDir = options.getStateDir(); if (stateDir != null && !createIfMissing(options.getStateDir())) - return RC_FATAL; + return Result.ERROR; Path gensrc = options.getGenSrcDir(); if (gensrc != null && !createIfMissing(gensrc)) - return RC_FATAL; + return Result.ERROR; Path hdrdir = options.getHeaderDir(); if (hdrdir != null && !createIfMissing(hdrdir)) - return RC_FATAL; + return Result.ERROR; if (stateDir == null) { // Prepare context. Direct logging to our byte array stream. @@ -113,7 +114,7 @@ public class SjavacImpl implements Sjavac { .filter(arg -> !arg.startsWith(Option.SERVER.arg)) .toArray(String[]::new); // Compile - Main.Result result = new Main("javac", printWriter).compile(passThroughArgs, context); + Result result = new Main("javac", printWriter).compile(passThroughArgs, context); // Process compiler output (which is always errors) printWriter.flush(); @@ -128,7 +129,7 @@ public class SjavacImpl implements Sjavac { throw new UncheckedIOException(es); } } - return result.exitCode; + return result; } else { // Load the prev build state database. @@ -166,7 +167,7 @@ public class SjavacImpl implements Sjavac { if (sources.isEmpty()) { Log.error("Found nothing to compile!"); - return RC_FATAL; + return Result.ERROR; } @@ -292,15 +293,15 @@ public class SjavacImpl implements Sjavac { javac_state.removeSuperfluousArtifacts(recently_compiled); } - return rc[0] ? RC_OK : RC_FATAL; + return rc[0] ? Result.OK : Result.ERROR; } catch (ProblemException e) { // For instance make file list mismatch. Log.error(e.getMessage()); Log.debug(e); - return RC_FATAL; + return Result.ERROR; } catch (Exception e) { Log.error(e); - return RC_FATAL; + return Result.ERROR; } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java index 1b96379b79d..5a60aa2bef7 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.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 @@ -31,6 +31,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.pubapi.PubApi; /** @@ -44,10 +45,7 @@ public class CompilationSubResult implements Serializable { static final long serialVersionUID = 46739181113L; - // Return code constants - public final static int ERROR_FATAL = -1; - - public int returnCode; + public Result result; public Map> packageArtifacts = new HashMap<>(); public Map>> packageDependencies = new HashMap<>(); public Map>> packageCpDependencies = new HashMap<>(); @@ -56,11 +54,11 @@ public class CompilationSubResult implements Serializable { public String stdout = ""; public String stderr = ""; - public CompilationSubResult(int returnCode) { - this.returnCode = returnCode; + public CompilationSubResult(Result result) { + this.result = result; } - public void setReturnCode(int returnCode) { - this.returnCode = returnCode; + public void setResult(Result result) { + this.result = result; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java index 8b7d17b0c0c..724c5062d5d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java @@ -25,11 +25,9 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; import java.util.Timer; import java.util.TimerTask; @@ -66,7 +64,7 @@ public class IdleResetSjavac implements Sjavac { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { startCall(); try { return delegate.compile(args); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java index 62ba3b995a9..e26a5c77766 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java @@ -25,6 +25,7 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -100,10 +101,10 @@ public class RequestHandler extends Thread { checkInternalErrorLog(); // Perform compilation - int rc = sjavac.compile(args); + Main.Result rc = sjavac.compile(args); // Send return code back to client - out.println(LINE_TYPE_RC + ":" + rc); + out.println(LINE_TYPE_RC + ":" + rc.name()); // Check for internal errors again. checkInternalErrorLog(); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java index 6690c3ece70..39c22966e22 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java @@ -32,6 +32,8 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.Thread.UncaughtExceptionHandler; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Log.Level; import com.sun.tools.sjavac.server.log.LazyInitFileLog; @@ -75,7 +77,7 @@ public class ServerMain { // Any options other than --startserver? if (args.length > 1) { Log.error("When spawning a background server, only a single --startserver argument is allowed."); - return 1; + return Result.CMDERR.exitCode; } int exitCode; @@ -84,7 +86,7 @@ public class ServerMain { exitCode = server.startServer(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(); - exitCode = -1; + exitCode = Result.ERROR.exitCode; } return exitCode; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java index 91063c5a809..dd3c43db74d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.javac.main.Main.Result; + import java.io.Writer; @@ -38,10 +40,6 @@ import java.io.Writer; * deletion without notice. */ public interface Sjavac { - - final static int RC_FATAL = -1; - final static int RC_OK = 0; - - int compile(String[] args); + Result compile(String[] args); void shutdown(); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java index 16450295afe..d7dcc203ade 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java @@ -40,6 +40,8 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.client.PortFileInaccessibleException; @@ -167,7 +169,7 @@ public class SjavacServer implements Terminable { if (portFile.containsPortInfo()) { Log.debug("Javac server not started because portfile exists!"); portFile.unlock(); - return -1; + return Result.ERROR.exitCode; } // .-----------. .--------. .------. @@ -221,7 +223,7 @@ public class SjavacServer implements Terminable { // Shut down sjavac.shutdown(); - return 0; + return Result.OK.exitCode; } @Override diff --git a/langtools/test/tools/sjavac/HiddenFiles.java b/langtools/test/tools/sjavac/HiddenFiles.java index f6a7c7ba91d..237146af29b 100644 --- a/langtools/test/tools/sjavac/HiddenFiles.java +++ b/langtools/test/tools/sjavac/HiddenFiles.java @@ -36,6 +36,7 @@ * @run main Wrapper HiddenFiles */ +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.server.Sjavac; @@ -62,6 +63,6 @@ public class HiddenFiles extends SjavacBase { "-d", BIN.toString(), "--state-dir=" + STATE_DIR); - Assert.check(rc == Sjavac.RC_FATAL, "Compilation succeeded unexpectedly."); + Assert.check(rc == Result.ERROR.exitCode, "Compilation succeeded unexpectedly."); } } diff --git a/langtools/test/tools/sjavac/IdleShutdown.java b/langtools/test/tools/sjavac/IdleShutdown.java index 7178d6c89e5..334f03149c2 100644 --- a/langtools/test/tools/sjavac/IdleShutdown.java +++ b/langtools/test/tools/sjavac/IdleShutdown.java @@ -29,9 +29,9 @@ * @build Wrapper * @run main Wrapper IdleShutdown */ -import java.io.Writer; import java.util.concurrent.atomic.AtomicLong; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.server.IdleResetSjavac; import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.Terminable; @@ -103,13 +103,13 @@ public class IdleShutdown { public void shutdown() { } @Override - public int compile(String[] args) { + public Result compile(String[] args) { // Attempt to trigger idle timeout during a call by sleeping try { Thread.sleep(TIMEOUT_MS + 1000); } catch (InterruptedException e) { } - return 0; + return Result.OK; } } } diff --git a/langtools/test/tools/sjavac/IncludeExcludePatterns.java b/langtools/test/tools/sjavac/IncludeExcludePatterns.java index 41b02a3ddbe..6e38aadc218 100644 --- a/langtools/test/tools/sjavac/IncludeExcludePatterns.java +++ b/langtools/test/tools/sjavac/IncludeExcludePatterns.java @@ -33,6 +33,7 @@ * @run main Wrapper IncludeExcludePatterns */ +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.server.Sjavac; @@ -131,7 +132,7 @@ public class IncludeExcludePatterns extends SjavacBase { int rc = compile((Object[]) args.split(" ")); // Compilation should always pass in these tests - Assert.check(rc == Sjavac.RC_OK, "Compilation failed unexpectedly."); + Assert.check(rc == Result.OK.exitCode, "Compilation failed unexpectedly."); // The resulting .class files should correspond to the visible source files Set result = allFilesInDir(BIN); diff --git a/langtools/test/tools/sjavac/PooledExecution.java b/langtools/test/tools/sjavac/PooledExecution.java index ccd4265fee2..bfa24b4fdcd 100644 --- a/langtools/test/tools/sjavac/PooledExecution.java +++ b/langtools/test/tools/sjavac/PooledExecution.java @@ -30,12 +30,10 @@ * @build Wrapper * @run main Wrapper PooledExecution */ -import java.io.PrintWriter; -import java.io.Writer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; -import com.sun.tools.sjavac.Log; +import com.sun.tools.javac.main.Main.Result; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.server.Sjavac; @@ -111,7 +109,7 @@ public class PooledExecution { AtomicInteger activeRequests = new AtomicInteger(0); @Override - public int compile(String[] args) { + public Result compile(String[] args) { leftToStart.countDown(); int numActiveRequests = activeRequests.incrementAndGet(); System.out.printf("Left to start: %2d / Currently active: %2d%n", @@ -125,7 +123,7 @@ public class PooledExecution { } activeRequests.decrementAndGet(); System.out.println("Task completed"); - return 0; + return Result.OK; } @Override From b51a55a78cb36b057e1ee217f2b634a9773fbb5c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 6 Apr 2016 10:50:19 +0300 Subject: [PATCH 031/225] 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 032/225] 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 033/225] 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 034/225] 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 035/225] 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 036/225] 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 037/225] 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 038/225] 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 039/225] 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 040/225] 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 041/225] 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 042/225] 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 043/225] 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 044/225] 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 045/225] 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 046/225] 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 047/225] 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 048/225] 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 049/225] 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 050/225] 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 051/225] 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 052/225] 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 053/225] 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 054/225] 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 055/225] 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 056/225] 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 057/225] 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 058/225] 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 059/225] 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 060/225] 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 061/225] 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 062/225] 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 063/225] 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 064/225] 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 065/225] 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 066/225] 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 067/225] 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 068/225] 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 069/225] 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 070/225] 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 071/225] 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 072/225] 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 073/225] 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 074/225] 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 75a63ccb0d1b976e474f29e5ca2fe11cfcd83c76 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 13 Apr 2016 17:04:02 +0530 Subject: [PATCH 075/225] 8147841: [macosx] Updating TrayIcons popup menu does not work on Mac OS X Reviewed-by: serb, ssadetsky --- .../classes/sun/lwawt/macosx/CTrayIcon.java | 21 +- .../UpdatePopupMenu/UpdatePopupMenu.java | 233 ++++++++++++++++++ 2 files changed, 249 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java index 2d82a2eb1c1..abd092b8be9 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java @@ -98,15 +98,26 @@ public class CTrayIcon extends CFRetainedResource implements TrayIconPeer { private native long nativeCreate(); //invocation from the AWTTrayIcon.m - public long getPopupMenuModel(){ - if(popup == null) { - PopupMenu popupMenu = target.getPopupMenu(); - if (popupMenu != null) { - popup = popupMenu; + public long getPopupMenuModel() { + PopupMenu newPopup = target.getPopupMenu(); + + if (popup == newPopup) { + if (popup == null) { + return 0L; + } + } else { + if (newPopup != null) { + if (popup != null) { + popup.removeNotify(); + popup = newPopup; + } else { + popup = newPopup; + } } else { return 0L; } } + return checkAndCreatePopupPeer().getModel(); } diff --git a/jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java b/jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java new file mode 100644 index 00000000000..b19dd209f78 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java @@ -0,0 +1,233 @@ +/* + * 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 8147841 + @summary Updating Tray Icon popup menu does not update menu items on Mac OS X + @run main/manual UpdatePopupMenu + */ + +import java.awt.SystemTray; +import java.awt.TrayIcon; +import java.awt.PopupMenu; +import java.awt.MenuItem; +import java.awt.Image; +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.awt.RenderingHints; +import java.awt.AWTException; +import java.awt.Button; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class UpdatePopupMenu implements ActionListener { + + private static final int imageSize = 32; + private static final int imageInset = 4; + private static GridBagLayout layout; + private static Panel mainControlPanel; + private static Panel resultButtonPanel; + private static TextArea instructionTextArea; + private static Button passButton; + private static Button failButton; + private static Frame mainFrame; + private static Thread mainThread = null; + private static boolean testPassed = false; + private static boolean isInterrupted = false; + private static final int testTimeOut = 300000; + + private Image createSystemTrayIconImage() { + final BufferedImage trayImage = new BufferedImage( + imageSize, + imageSize, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D imageGraphics = (Graphics2D) trayImage.getGraphics(); + + imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + imageGraphics.setColor(new Color(255, 255, 255, 0)); + imageGraphics.fillRect(0, 0, trayImage.getWidth(), + trayImage.getHeight()); + + imageGraphics.setColor(Color.green); + + int imageWidth = trayImage.getWidth() - 2 * imageInset; + int imageHeight = trayImage.getHeight() - 2 * imageInset; + + imageGraphics.fillOval(imageInset, imageInset, imageWidth, imageHeight); + imageGraphics.setColor(Color.darkGray); + imageGraphics.drawOval(imageInset, imageInset, imageWidth, imageHeight); + + return trayImage; + } + + private PopupMenu createPopupMenu(final TrayIcon trayIcon, + final int menuCount) { + + final PopupMenu trayIconPopupMenu = new PopupMenu(); + + for (int i = 1; i <= menuCount; ++i) { + final MenuItem popupMenuItem = new MenuItem("MenuItem_" + i); + + popupMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent ae) { + trayIcon.setPopupMenu(createPopupMenu(trayIcon, + menuCount + 1)); + } + }); + + trayIconPopupMenu.add(popupMenuItem); + } + + return trayIconPopupMenu; + } + + private void createSystemTrayIcons() { + + final TrayIcon trayIcon = new TrayIcon(createSystemTrayIconImage()); + trayIcon.setImageAutoSize(true); + trayIcon.setToolTip("Update Popup Menu items"); + + try { + trayIcon.setPopupMenu(createPopupMenu(trayIcon, 2)); + SystemTray.getSystemTray().add(trayIcon); + + } catch (AWTException ex) { + throw new RuntimeException("System Tray cration failed"); + } + } + + private void createInstructionUI() { + mainFrame = new Frame("Updating TrayIcon Popup Menu Item Test"); + layout = new GridBagLayout(); + mainControlPanel = new Panel(layout); + resultButtonPanel = new Panel(layout); + + GridBagConstraints gbc = new GridBagConstraints(); + String instructions + = "INSTRUCTIONS:" + + "\n 1. Click on the System Tray Icon" + + "\n 2. Click on any of the displayed Menu items" + + "\n 3. Repeat step 1 and count the number of items in the " + + "Menu" + + "\n 4. The number of items in the Menu should increase by 1" + + "\n 5. Repeating steps 1, 2 and 3 should not break 4th step" + + "\n 6. Click Fail if the 4th step is broken, Otherwise " + + "click Pass "; + + instructionTextArea = new TextArea(); + instructionTextArea.setText(instructions); + instructionTextArea.setEnabled(false); + instructionTextArea.setBackground(Color.white); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(instructionTextArea, gbc); + + passButton = new Button("Pass"); + passButton.setName("Pass"); + passButton.addActionListener(this); + + failButton = new Button("Fail"); + failButton.setName("Fail"); + failButton.addActionListener(this); + + gbc.gridx = 0; + gbc.gridy = 0; + resultButtonPanel.add(passButton, gbc); + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); + gbc.gridx = 0; + gbc.gridy = 1; + mainControlPanel.add(resultButtonPanel, gbc); + + mainFrame.add(mainControlPanel); + mainFrame.pack(); + mainFrame.setVisible(true); + } + + @Override + public void actionPerformed(ActionEvent ae) { + if (ae.getSource() instanceof Button) { + Button btn = (Button) ae.getSource(); + switch (btn.getName()) { + case "Pass": + testPassed = true; + isInterrupted = true; + mainThread.interrupt(); + break; + + case "Fail": + testPassed = false; + isInterrupted = true; + mainThread.interrupt(); + break; + } + } + } + + private static void cleanUp() { + mainFrame.dispose(); + } + + public static void main(final String[] args) throws Exception { + if (SystemTray.isSupported()) { + + UpdatePopupMenu updatePopupMenu = new UpdatePopupMenu(); + updatePopupMenu.createInstructionUI(); + updatePopupMenu.createSystemTrayIcons(); + + mainThread = Thread.currentThread(); + try { + mainThread.sleep(testTimeOut); + } catch (InterruptedException ex) { + if (!testPassed) { + throw new RuntimeException("Updating TrayIcon popup menu" + + " items FAILED"); + } + } finally { + cleanUp(); + } + + if (!isInterrupted) { + throw new RuntimeException("Test Timed out after " + + testTimeOut / 1000 + " seconds"); + } + + } else { + System.out.println("System Tray is not supported on this platform"); + } + } +} From 23da19a7903106b21f133b30a56107d98a158d4f Mon Sep 17 00:00:00 2001 From: Dmitry Fazunenko Date: Wed, 13 Apr 2016 19:55:40 +0400 Subject: [PATCH 076/225] 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 077/225] 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 078/225] 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 079/225] 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 080/225] 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 081/225] 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 082/225] 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 083/225] 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 b7b4dfdc09a0bcdcef9491753f79d7819b424fc8 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 14 Apr 2016 13:07:35 +0300 Subject: [PATCH 084/225] 8146035: Windows - With LCD antialiasing, some glyphs are not rendered correctly Reviewed-by: serb, prr --- .../windows/native/libfontmanager/lcdglyph.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c b/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c index 05f4aae9d82..d940e8cb468 100644 --- a/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c +++ b/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c @@ -157,6 +157,9 @@ JNIEXPORT jboolean JNICALL if (hBitmap != 0) { \ DeleteObject(hBitmap); \ } \ + if (tmpBitmap != 0) { \ + DeleteObject(tmpBitmap); \ + } \ if (dibImage != NULL) { \ free(dibImage); \ } \ @@ -196,6 +199,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows int bmWidth, bmHeight; int x, y; HBITMAP hBitmap = NULL, hOrigBM; + HBITMAP tmpBitmap = NULL; int gamma, orient; HWND hWnd = NULL; @@ -250,6 +254,12 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows } oldFont = SelectObject(hMemoryDC, hFont); + tmpBitmap = CreateCompatibleBitmap(hDesktopDC, 1, 1); + if (tmpBitmap == NULL) { + FREE_AND_RETURN; + } + hOrigBM = (HBITMAP)SelectObject(hMemoryDC, tmpBitmap); + memset(&textMetric, 0, sizeof(TEXTMETRIC)); err = GetTextMetrics(hMemoryDC, &textMetric); if (err == 0) { @@ -334,7 +344,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows if (hBitmap == NULL) { FREE_AND_RETURN; } - hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap); + SelectObject(hMemoryDC, hBitmap); /* Fill in black */ rect.left = 0; @@ -478,6 +488,7 @@ Java_sun_font_FileFontStrike__1getGlyphImageFromWindows ReleaseDC(hWnd, hDesktopDC); DeleteObject(hMemoryDC); DeleteObject(hBitmap); + DeleteObject(tmpBitmap); return ptr_to_jlong(glyphInfo); } From 8c6cc265f69f61c9a260520d8e1c591c76c27adc Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Thu, 14 Apr 2016 15:45:38 +0300 Subject: [PATCH 085/225] 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 086/225] 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 26e64bbd263d7ba37c5f0766104115c1248f65f1 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Thu, 14 Apr 2016 20:32:50 +0300 Subject: [PATCH 087/225] 8153351: GTK Menu's have no border Reviewed-by: alexsch, serb --- .../sun/java/swing/plaf/gtk/GTKPainter.java | 41 +++++++++++++++---- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 15 +++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index ad61aca85f1..ecd319a337f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.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 @@ -576,12 +576,11 @@ class GTKPainter extends SynthPainter { ShadowType.OUT, "menu", x, y, w, h); GTKStyle style = (GTKStyle)context.getStyle(); - int xThickness = style.getXThickness(); - int yThickness = style.getYThickness(); + Insets insets = style.getInsets(context, null); ENGINE.paintBackground(g, context, id, gtkState, - style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND), - x + xThickness, y + yThickness, - w - xThickness - xThickness, h - yThickness - yThickness); + style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND), + x + insets.left, y + insets.top, w - insets.left - insets.right, + h - insets.top - insets.bottom); ENGINE.finishPainting(); } } @@ -640,6 +639,34 @@ class GTKPainter extends SynthPainter { int state = context.getComponentState(); JComponent c = context.getComponent(); + GTKStyle style = (GTKStyle) context.getStyle(); + String detail; + // wide-separators are painted using box not line + if (style.getClassSpecificBoolValue(context, + "wide-separators", false)) { + Insets insets = c.getInsets(); + x += insets.left; + y += insets.top; + if (orientation == JSeparator.HORIZONTAL) { + w -= (insets.left + insets.right); + detail = "hseparator"; + } else { + h -= (insets.top + insets.bottom); + detail = "vseparator"; + } + synchronized (UNIXToolkit.GTK_LOCK) { + if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state, + detail, orientation)) { + ENGINE.startPainting(g, x, y, w, h, id, state, + detail, orientation); + ENGINE.paintBox(g, context, id, state, + ShadowType.ETCHED_OUT, detail, x, y, w, h); + ENGINE.finishPainting(); + } + } + return; + } + /* * Note: In theory, the style's x/y thickness values would determine * the width of the separator content. In practice, however, some @@ -650,7 +677,6 @@ class GTKPainter extends SynthPainter { * the w/h values below too much, so that the full thickness of the * rendered line will be captured by our image caching code. */ - String detail; if (c instanceof JToolBar.Separator) { /* * GTK renders toolbar separators differently in that an @@ -678,7 +704,6 @@ class GTKPainter extends SynthPainter { float pct = 0.2f; JToolBar.Separator sep = (JToolBar.Separator)c; Dimension size = sep.getSeparatorSize(); - GTKStyle style = (GTKStyle)context.getStyle(); if (orientation == JSeparator.HORIZONTAL) { x += (int)(w * pct); w -= (int)(w * pct * 2); diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index 4fa44c758e5..fe54752cef6 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -776,6 +776,15 @@ class GTKStyle extends SynthStyle implements GTKConstants { } else if (key == "Separator.thickness") { JSeparator sep = (JSeparator)context.getComponent(); + if (getClassSpecificBoolValue(context, "wide-separators", false)) { + if (sep.getOrientation() == JSeparator.HORIZONTAL) { + return getClassSpecificIntValue(context, + "separator-height", 0); + } else { + return getClassSpecificIntValue(context, + "separator-width", 0); + } + } if (sep.getOrientation() == JSeparator.HORIZONTAL) { return getYThickness(); } else { @@ -783,6 +792,12 @@ class GTKStyle extends SynthStyle implements GTKConstants { } } else if (key == "ToolBar.separatorSize") { + if (getClassSpecificBoolValue(context, "wide-separators", false)) { + return new DimensionUIResource( + getClassSpecificIntValue(context, "separator-width", 2), + getClassSpecificIntValue(context, "separator-height", 2) + ); + } int size = getClassSpecificIntValue(WidgetType.TOOL_BAR, "space-size", 12); return new DimensionUIResource(size, size); From 524efbad7966199bd1c55d9ac3198209dfa7a115 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 14 Apr 2016 12:36:14 -0700 Subject: [PATCH 088/225] 8134986: Incorrect use of ConcurrentHashMap.contains in SunFontManager.java Reviewed-by: serb, jgodinez --- jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 19200c8282b..6ac092ed32e 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -1843,7 +1843,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { private PhysicalFont registerFontFile(String file) { if (new File(file).isAbsolute() && - !registeredFonts.contains(file)) { + !registeredFonts.containsKey(file)) { int fontFormat = FONTFORMAT_NONE; int fontRank = Font2D.UNKNOWN_RANK; if (ttFilter.accept(null, file)) { From 0d5a231133543ae73bbeeed1acc029a76200b5a9 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 15 Apr 2016 11:45:11 +0530 Subject: [PATCH 089/225] 6921664: The number of copies and the job name are not passed to a 3rd party PrintService Reviewed-by: prr, jdv --- .../classes/sun/print/RasterPrinterJob.java | 2 + .../awt/print/PrinterJob/DummyPrintTest.java | 247 ++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index b5d8f0daa8f..638e01488e6 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -1388,6 +1388,8 @@ public abstract class RasterPrinterJob extends PrinterJob { Doc doc = new PageableDoc(getPageable()); if (attributes == null) { attributes = new HashPrintRequestAttributeSet(); + attributes.add(new Copies(getCopies())); + attributes.add(new JobName(getJobName(), null)); } try { job.print(doc, attributes); diff --git a/jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java b/jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java new file mode 100644 index 00000000000..43881d5ca9f --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java @@ -0,0 +1,247 @@ +/* + * 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 6921664 + * @summary Verifies number of copies and the job name are passed to a + * 3rd party PrintService. + * @run main DummyPrintTest + */ +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 java.util.HashSet; +import java.util.Set; +import javax.print.Doc; +import javax.print.DocFlavor; +import javax.print.DocPrintJob; +import javax.print.PrintException; +import javax.print.PrintService; +import javax.print.PrintServiceLookup; +import javax.print.ServiceUIFactory; +import javax.print.attribute.Attribute; +import javax.print.attribute.AttributeSet; +import javax.print.attribute.HashPrintJobAttributeSet; +import javax.print.attribute.HashPrintServiceAttributeSet; +import javax.print.attribute.PrintJobAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.PrintServiceAttribute; +import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.PrinterName; +import javax.print.attribute.standard.PrinterState; +import javax.print.event.PrintJobAttributeListener; +import javax.print.event.PrintJobListener; +import javax.print.event.PrintServiceAttributeListener; + + +public class DummyPrintTest { + + public static void main(String[] args) throws Exception { + // register custom print service implementation + String printerName = "myDummyPrintService"; + PrintServiceLookup.registerService(new DummyPrintService(printerName)); + // calling third party print logic + thirdPartyPrintLogic(printerName); + } + + static void thirdPartyPrintLogic(String printerName) throws Exception { + PrinterJob printerjob = PrinterJob.getPrinterJob(); + printerjob.setCopies(2); + printerjob.setJobName("myJobName"); + printerjob.setPrintable(new DummyPrintable()); + for (PrintService printService : PrinterJob.lookupPrintServices()) { + System.out.println("check printer name of service " + printService); + if (printerName.equals(printService.getName())) { + System.out.println("correct printer service do print..."); + printerjob.setPrintService(printService); + printerjob.print(); + break; + } + } + } +} + +class DummyPrintService implements PrintService { + private final String _name; + private final Set _supportedFlavors; + private final PrintServiceAttributeSet _printServiceAttributeSet; + + public DummyPrintService(String name) { + _name = name; + _supportedFlavors = new HashSet(); + _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE); + _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE); + _printServiceAttributeSet = new HashPrintServiceAttributeSet(); + _printServiceAttributeSet.add(new PrinterName(name, null)); + _printServiceAttributeSet.add(PrinterState.IDLE); + } + + @Override + public String toString() { + return "Dummy Printer : " + getName(); + } + + @Override + public String getName() { + return _name; + } + + @Override + public DocPrintJob createPrintJob() { + return new DummyDocPrintJob(this); + } + + @Override + public boolean isDocFlavorSupported(DocFlavor flavor) { + return _supportedFlavors.contains(flavor); + } + + @Override + public T getAttribute(Class category) { + return category.cast(_printServiceAttributeSet.get(category)); + } + + @Override + public PrintServiceAttributeSet getAttributes() { + return _printServiceAttributeSet; + } + + @Override + public DocFlavor[] getSupportedDocFlavors() { + return _supportedFlavors.toArray(new DocFlavor[_supportedFlavors.size()]); + } + + @Override + public Object getDefaultAttributeValue(Class category) { + return null; + } + + @Override + public ServiceUIFactory getServiceUIFactory() { + return null; + } + + @Override + public Class[] getSupportedAttributeCategories() { + return null; + } + + @Override + public Object getSupportedAttributeValues(Class category, + DocFlavor flavor, AttributeSet attributes) { + return null; + } + + @Override + public AttributeSet getUnsupportedAttributes(DocFlavor flavor, + AttributeSet attributes) { + return null; + } + + @Override + public boolean isAttributeCategorySupported(Class category) { + return false; + } + + @Override + public boolean isAttributeValueSupported(Attribute attrval, + DocFlavor flavor, + AttributeSet attributes) { + return false; + } + + @Override + public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener) { + } + + @Override + public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener) { + } +} + +class DummyDocPrintJob implements DocPrintJob { + private static int _counter; + private final PrintService _printService; + private final PrintJobAttributeSet _printJobAttributeSet; + + public DummyDocPrintJob(PrintService printService) { + _counter++; + _printService = printService; + _printJobAttributeSet = new HashPrintJobAttributeSet(); + } + + @Override + public PrintService getPrintService() { + return _printService; + } + + @Override + public PrintJobAttributeSet getAttributes() { + return _printJobAttributeSet; + } + + @Override + public void addPrintJobAttributeListener(PrintJobAttributeListener listener, + PrintJobAttributeSet printJobAttributeSet) { + } + + @Override + public void removePrintJobAttributeListener(PrintJobAttributeListener listener) { + } + + @Override + public void addPrintJobListener(PrintJobListener listener) { + } + + @Override + public void removePrintJobListener(PrintJobListener listener) { + } + + @Override + public void print(Doc doc, + PrintRequestAttributeSet printRequestAttributeSet) + throws PrintException { + System.out.println("job name: " + printRequestAttributeSet.get(JobName.class)); + System.out.println("copies: " + printRequestAttributeSet.get(Copies.class)); + if(printRequestAttributeSet.get(JobName.class) == null || + printRequestAttributeSet.get(Copies.class) == null) { + throw new RuntimeException("Copies and JobName is not passed correctly"); + } + } +} + +class DummyPrintable implements Printable { + @Override + public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) + throws PrinterException { + if (pageIndex == 0) { + return Printable.PAGE_EXISTS; + } else { + return Printable.NO_SUCH_PAGE; + } + } +} From 13ab7793b822ea6966227cc4c02f827126f4bd85 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 15 Apr 2016 11:48:08 +0530 Subject: [PATCH 090/225] 6801613: Cross-platform pageDialog and printDialog top margin entry broken Reviewed-by: prr, jdv --- .../classes/sun/print/ServiceDialog.java | 4 +- .../PrinterJob/PageDialogMarginTest.java | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java diff --git a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java index f4694100cd2..615304c75f4 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java @@ -1422,13 +1422,13 @@ public class ServiceDialog extends JDialog implements ActionListener { topMargin.addActionListener(this); topMargin.getAccessibleContext().setAccessibleName( getMsg("label.topmargin")); - topMargin = new JFormattedTextField(nf); + bottomMargin = new JFormattedTextField(nf); bottomMargin.addFocusListener(this); bottomMargin.addActionListener(this); bottomMargin.getAccessibleContext().setAccessibleName( getMsg("label.bottommargin")); - topMargin = new JFormattedTextField(nf); + c.gridwidth = GridBagConstraints.RELATIVE; lblLeft = new JLabel(getMsg("label.leftmargin") + " " + unitsMsg, JLabel.LEADING); diff --git a/jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java b/jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java new file mode 100644 index 00000000000..3efc1125049 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java @@ -0,0 +1,92 @@ +/* + * 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 6801613 + * @summary Verifies if cross-platform pageDialog and printDialog top margin + * entry is working + * @run main/manual PageDialogMarginTest + */ +import java.awt.Component; +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.MediaPrintableArea; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +public class PageDialogMarginTest { + + public static void main(String args[]) throws Exception { + String[] instructions + = { + "Page Dialog will be shown.", + "Change top(in) margin value from 1.0 to 2.0", + "Then select OK." + }; + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog((Component) null, + instructions, "Instructions", + JOptionPane.INFORMATION_MESSAGE); + }); + PrinterJob pj = PrinterJob.getPrinterJob(); + try { + HashPrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + PageFormat pf; + pf = pj.pageDialog(aset); + double left = pf.getImageableX(); + double top = pf.getImageableY(); + System.out.println("pageDialog - left/top from pageFormat: " + left / 72 + + " " + top / 72); + System.out.println("pageDialog - left/top from attribute set: " + + getPrintableXFromASet(aset) + " " + + getPrintableYFromASet(aset)); + if (top / 72 != 2.0f || getPrintableYFromASet(aset) != 2.0f) { + throw new RuntimeException("Top margin value not updated"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + static double getPrintableXFromASet(PrintRequestAttributeSet aset) { + try { + return ((MediaPrintableArea) aset.get( + MediaPrintableArea.class)).getX(MediaPrintableArea.INCH); + } catch (Exception e) { + return -1.0; + } + } + + static double getPrintableYFromASet(PrintRequestAttributeSet aset) { + try { + return ((MediaPrintableArea) aset.get( + MediaPrintableArea.class)).getY(MediaPrintableArea.INCH); + } catch (Exception e) { + return -1.0; + } + } + +} From d22bbd1a01922ed98db276879db908235e9fe036 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 15 Apr 2016 11:52:23 +0530 Subject: [PATCH 091/225] 8154057: [macosx] getPrintJob doesn't throw NPE if Frame is null AND type is COMMON Reviewed-by: prr, jdv --- .../macosx/classes/sun/lwawt/LWToolkit.java | 4 ++ jdk/test/java/awt/PrintJob/NullFrameTest.java | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 jdk/test/java/awt/PrintJob/NullFrameTest.java 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 b7262a5a402..daa02981c27 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java @@ -404,6 +404,10 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { public final PrintJob getPrintJob(Frame frame, String doctitle, JobAttributes jobAttributes, PageAttributes pageAttributes) { + if (frame == null) { + throw new NullPointerException("frame must not be null"); + } + if (GraphicsEnvironment.isHeadless()) { throw new IllegalArgumentException(); } diff --git a/jdk/test/java/awt/PrintJob/NullFrameTest.java b/jdk/test/java/awt/PrintJob/NullFrameTest.java new file mode 100644 index 00000000000..a6de7e5b7fc --- /dev/null +++ b/jdk/test/java/awt/PrintJob/NullFrameTest.java @@ -0,0 +1,48 @@ +/* + * 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 8154057 + * @summary getPrintJob doesn't throw NPE if frame is null + * @run main NullFrameTest + */ +import java.awt.JobAttributes; +import java.awt.Toolkit; + +public class NullFrameTest { + public static void main(String[] args) { + JobAttributes ja = new JobAttributes(); + ja.setDialog(JobAttributes.DialogType.COMMON); + boolean npeThrown = false; + try { + Toolkit.getDefaultToolkit().getPrintJob(null, + "test Printing", ja, null); + } catch (NullPointerException ex) { + npeThrown = true; + } + if (!npeThrown) { + throw + new RuntimeException("getPrintJob didn't throw NPE for null Frame"); + } + } +} From eca0d89af65e2c9291da6880f1a5d7c610996eaf Mon Sep 17 00:00:00 2001 From: Abdul Kolarkunnu Date: Fri, 15 Apr 2016 12:00:37 +0530 Subject: [PATCH 092/225] 8025430: [TEST_BUG] javax/swing/JEditorPane/5076514/bug5076514.java failed since jdk8b108 Reviewed-by: serb, psadhukhan --- .../swing/JEditorPane/5076514/bug5076514.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java diff --git a/jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java b/jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java new file mode 100644 index 00000000000..fc411722def --- /dev/null +++ b/jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java @@ -0,0 +1,58 @@ +/* + * 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 5076514 8025430 + @summary Tests if SecurityManager.checkPermission() + used for clipboard access with permission 'accessClipboard' + @run main bug5076514 +*/ + +import java.security.Permission; +import javax.swing.JEditorPane; + +public class bug5076514 { + private final static String ACCESS_CLIPBOARD = "accessClipboard"; + private static boolean isCheckPermissionCalled = false; + + public static void main(String[] args) { + System.setSecurityManager(new MySecurityManager()); + JEditorPane editor = new JEditorPane(); + editor.copy(); + if (!isCheckPermissionCalled) { + throw new RuntimeException("JEditorPane's clipboard operations " + + "didn't call SecurityManager.checkPermission() with " + + "permission 'accessClipboard' when there is a security" + + " manager installed"); + } + } + + private static class MySecurityManager extends SecurityManager { + @Override + public void checkPermission(Permission perm) { + if (ACCESS_CLIPBOARD.equals(perm.getName())) { + isCheckPermissionCalled = true; + } + } + } +} From 40685b42712164d01e4ac7a59da0a91260e6e806 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 15 Apr 2016 09:46:31 +0300 Subject: [PATCH 093/225] 8080395: consider making sun.awt.CausedFocusEvent functionality public Reviewed-by: alexsch, prr --- .../classes/sun/lwawt/LWComponentPeer.java | 6 +- .../sun/lwawt/LWLightweightFramePeer.java | 6 +- .../classes/sun/lwawt/LWWindowPeer.java | 10 +- .../classes/sun/lwawt/PlatformWindow.java | 6 +- .../classes/sun/lwawt/macosx/CFileDialog.java | 4 +- .../lwawt/macosx/CPlatformEmbeddedFrame.java | 9 +- .../sun/lwawt/macosx/CPlatformLWWindow.java | 6 +- .../sun/lwawt/macosx/CPlatformWindow.java | 6 +- .../macosx/CViewPlatformEmbeddedFrame.java | 4 +- .../share/classes/java/awt/Component.java | 31 ++- .../share/classes/java/awt/Container.java | 5 +- .../java/awt/DefaultKeyboardFocusManager.java | 27 +-- .../java/awt/KeyboardFocusManager.java | 49 ++-- .../share/classes/java/awt/Window.java | 5 +- .../classes/java/awt/event/FocusEvent.java | 184 ++++++++++++-- .../classes/java/awt/peer/ComponentPeer.java | 6 +- .../share/classes/javax/swing/JComponent.java | 4 +- .../share/classes/sun/awt/AWTAccessor.java | 7 +- .../classes/sun/awt/CausedFocusEvent.java | 112 ++++++--- .../sun/awt/KeyboardFocusManagerPeerImpl.java | 16 +- .../classes/sun/awt/NullComponentPeer.java | 6 +- .../sun/awt/RequestFocusController.java | 5 +- .../classes/sun/awt/X11/XComponentPeer.java | 6 +- .../classes/sun/awt/X11/XEmbedCanvasPeer.java | 13 +- .../sun/awt/X11/XEmbedChildProxyPeer.java | 4 +- .../awt/X11/XKeyboardFocusManagerPeer.java | 6 +- .../classes/sun/awt/X11/XTextAreaPeer.java | 9 +- .../classes/sun/awt/X11/XTextFieldPeer.java | 9 +- .../sun/awt/windows/WComponentPeer.java | 7 +- .../sun/awt/windows/WFileDialogPeer.java | 6 +- .../windows/WKeyboardFocusManagerPeer.java | 6 +- .../sun/awt/windows/WPrintDialogPeer.java | 6 +- .../classes/sun/awt/windows/WWindowPeer.java | 6 +- .../java/awt/Focus/Cause/FocusCauseTest.java | 224 ++++++++++++++++++ 34 files changed, 617 insertions(+), 199 deletions(-) create mode 100644 jdk/test/java/awt/Focus/Cause/FocusCauseTest.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java index d0a3f65ed58..a024da398b5 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, 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 @@ -903,7 +903,7 @@ public abstract class LWComponentPeer @Override public boolean requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary + @@ -1278,7 +1278,7 @@ public abstract class LWComponentPeer assert (e.getSource() == target); if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) { - LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT); + LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT); } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java index 4491b7c9c05..8205956b649 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -31,8 +31,8 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; import java.awt.dnd.DropTarget; +import java.awt.event.FocusEvent; -import sun.awt.CausedFocusEvent; import sun.awt.LightweightFrame; import sun.swing.JLightweightFrame; import sun.swing.SwingAccessor; @@ -60,7 +60,7 @@ public class LWLightweightFramePeer extends LWWindowPeer { } @Override - public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + public boolean requestWindowFocus(FocusEvent.Cause cause) { if (!focusAllowedFor()) { return false; } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index fabc2a21ba1..820dc1af2a0 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.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 @@ -256,14 +256,14 @@ public class LWWindowPeer if (!getTarget().isAutoRequestFocus()) { return; } else { - requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION); + requestWindowFocus(FocusEvent.Cause.ACTIVATION); } // Focus the owner in case this window is focused. } else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) { // Transfer focus to the owner. LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this); if (owner != null) { - owner.requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION); + owner.requestWindowFocus(FocusEvent.Cause.ACTIVATION); } } } @@ -848,7 +848,7 @@ public class LWWindowPeer // 2. An active but not focused owner frame/dialog is clicked. // The mouse event then will trigger a focus request "in window" to the component, so the window // should gain focus before. - requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT); + requestWindowFocus(FocusEvent.Cause.MOUSE_EVENT); mouseDownTarget[targetIdx] = targetPeer; } else if (id == MouseEvent.MOUSE_DRAGGED) { @@ -1199,7 +1199,7 @@ public class LWWindowPeer * Requests platform to set native focus on a frame/dialog. * In case of a simple window, triggers appropriate java focus change. */ - public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + public boolean requestWindowFocus(FocusEvent.Cause cause) { if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { focusLog.fine("requesting native focus to " + this); } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java index 06bc5f48a83..81134ef48c4 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.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 @@ -26,8 +26,8 @@ package sun.lwawt; import java.awt.*; +import java.awt.event.FocusEvent; -import sun.awt.CausedFocusEvent; import sun.java2d.SurfaceData; // TODO Is it worth to generify this interface, like that: @@ -114,7 +114,7 @@ public interface PlatformWindow { public void updateFocusableWindowState(); - public boolean rejectFocusRequest(CausedFocusEvent.Cause cause); + public boolean rejectFocusRequest(FocusEvent.Cause cause); public boolean requestWindowFocus(); 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 34651baba70..e232541c4e3 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 @@ -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 @@ -26,6 +26,7 @@ package sun.lwawt.macosx; import java.awt.*; +import java.awt.event.FocusEvent.Cause; import java.awt.peer.*; import java.awt.BufferCapabilities.FlipContents; import java.awt.event.*; @@ -34,7 +35,6 @@ import java.security.AccessController; import java.util.List; import java.io.*; -import sun.awt.CausedFocusEvent.Cause; import sun.awt.AWTAccessor; import sun.java2d.pipe.Region; import sun.security.action.GetBooleanAction; diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index f6ab6bbb4ad..b2e7466b817 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.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 @@ -26,7 +26,8 @@ package sun.lwawt.macosx; import java.awt.*; -import sun.awt.CausedFocusEvent; +import java.awt.event.FocusEvent; + import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLLayer; import sun.lwawt.LWWindowPeer; @@ -133,9 +134,9 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { public void updateFocusableWindowState() {} @Override - public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + public boolean rejectFocusRequest(FocusEvent.Cause cause) { // Cross-app activation requests are not allowed. - if (cause != CausedFocusEvent.Cause.MOUSE_EVENT && + if (cause != FocusEvent.Cause.MOUSE_EVENT && !target.isParentWindowActive()) { focusLogger.fine("the embedder is inactive, so the request is rejected"); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java index 0d9f9744c41..71bb436dff3 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.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 @@ -37,7 +37,7 @@ import java.awt.Rectangle; import java.awt.Window; import sun.awt.CGraphicsDevice; import sun.awt.CGraphicsEnvironment; -import sun.awt.CausedFocusEvent; +import java.awt.event.FocusEvent; import sun.awt.LightweightFrame; import sun.java2d.SurfaceData; import sun.lwawt.LWLightweightFramePeer; @@ -134,7 +134,7 @@ public class CPlatformLWWindow extends CPlatformWindow { } @Override - public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + public boolean rejectFocusRequest(FocusEvent.Cause cause) { return false; } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index a9214b45ba7..835f01a5eca 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.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 @@ -706,9 +706,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo } @Override - public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) { + public boolean rejectFocusRequest(FocusEvent.Cause cause) { // Cross-app activation requests are not allowed. - if (cause != CausedFocusEvent.Cause.MOUSE_EVENT && + if (cause != FocusEvent.Cause.MOUSE_EVENT && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) { focusLogger.fine("the app is inactive, so the request is rejected"); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java index 1c11789713f..e577f286a91 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.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 @@ -33,7 +33,7 @@ import java.awt.Insets; import java.awt.MenuBar; import java.awt.Point; import java.awt.Window; -import sun.awt.CausedFocusEvent.Cause; +import java.awt.event.FocusEvent.Cause; import sun.java2d.SurfaceData; import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java index a01b9065c36..b2b51e08559 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Component.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, 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 @@ -68,7 +68,6 @@ import sun.awt.AWTAccessor; import sun.awt.ConstrainableGraphics; import sun.awt.SubRegionShowable; import sun.awt.SunToolkit; -import sun.awt.CausedFocusEvent; import sun.awt.EmbeddedFrame; import sun.awt.dnd.SunDropTargetEvent; import sun.awt.im.CompositionArea; @@ -878,7 +877,7 @@ public abstract class Component implements ImageObserver, MenuContainer, { comp.setGraphicsConfiguration(gc); } - public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) { + public boolean requestFocus(Component comp, FocusEvent.Cause cause) { return comp.requestFocus(cause); } public boolean canBeFocusOwner(Component comp) { @@ -7538,7 +7537,7 @@ public abstract class Component implements ImageObserver, MenuContainer, requestFocusHelper(false, true); } - boolean requestFocus(CausedFocusEvent.Cause cause) { + boolean requestFocus(FocusEvent.Cause cause) { return requestFocusHelper(false, true, cause); } @@ -7605,7 +7604,7 @@ public abstract class Component implements ImageObserver, MenuContainer, return requestFocusHelper(temporary, true); } - boolean requestFocus(boolean temporary, CausedFocusEvent.Cause cause) { + boolean requestFocus(boolean temporary, FocusEvent.Cause cause) { return requestFocusHelper(temporary, true, cause); } /** @@ -7656,7 +7655,7 @@ public abstract class Component implements ImageObserver, MenuContainer, return requestFocusHelper(false, false); } - boolean requestFocusInWindow(CausedFocusEvent.Cause cause) { + boolean requestFocusInWindow(FocusEvent.Cause cause) { return requestFocusHelper(false, false, cause); } @@ -7721,18 +7720,18 @@ public abstract class Component implements ImageObserver, MenuContainer, return requestFocusHelper(temporary, false); } - boolean requestFocusInWindow(boolean temporary, CausedFocusEvent.Cause cause) { + boolean requestFocusInWindow(boolean temporary, FocusEvent.Cause cause) { return requestFocusHelper(temporary, false, cause); } final boolean requestFocusHelper(boolean temporary, boolean focusedWindowChangeAllowed) { - return requestFocusHelper(temporary, focusedWindowChangeAllowed, CausedFocusEvent.Cause.UNKNOWN); + return requestFocusHelper(temporary, focusedWindowChangeAllowed, FocusEvent.Cause.UNKNOWN); } final boolean requestFocusHelper(boolean temporary, boolean focusedWindowChangeAllowed, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { // 1) Check if the event being dispatched is a system-generated mouse event. AWTEvent currentEvent = EventQueue.getCurrentEvent(); @@ -7820,7 +7819,7 @@ public abstract class Component implements ImageObserver, MenuContainer, private boolean isRequestFocusAccepted(boolean temporary, boolean focusedWindowChangeAllowed, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { if (!isFocusable() || !isVisible()) { if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) { @@ -7867,7 +7866,7 @@ public abstract class Component implements ImageObserver, MenuContainer, return true; } - if (CausedFocusEvent.Cause.ACTIVATION == cause) { + if (FocusEvent.Cause.ACTIVATION == cause) { // we shouldn't call RequestFocusController in case we are // in activation. We do request focus on component which // has got temporary focus lost and then on component which is @@ -7899,7 +7898,7 @@ public abstract class Component implements ImageObserver, MenuContainer, private static class DummyRequestFocusController implements RequestFocusController { public boolean acceptRequestFocus(Component from, Component to, boolean temporary, boolean focusedWindowChangeAllowed, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { return true; } @@ -7983,7 +7982,7 @@ public abstract class Component implements ImageObserver, MenuContainer, Component toFocus = getNextFocusCandidate(); boolean res = false; if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) { - res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD); + res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_FORWARD); } if (clearOnFailure && !res) { if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { @@ -8063,7 +8062,7 @@ public abstract class Component implements ImageObserver, MenuContainer, toFocus = policy.getDefaultComponent(rootAncestor); } if (toFocus != null) { - res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); + res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_BACKWARD); } } if (clearOnFailure && !res) { @@ -8108,7 +8107,7 @@ public abstract class Component implements ImageObserver, MenuContainer, KeyboardFocusManager.getCurrentKeyboardFocusManager(). setGlobalCurrentFocusCycleRootPriv(fcr); - rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP); + rootAncestor.requestFocus(FocusEvent.Cause.TRAVERSAL_UP); } else { Window window = getContainingWindow(); @@ -8118,7 +8117,7 @@ public abstract class Component implements ImageObserver, MenuContainer, if (toFocus != null) { KeyboardFocusManager.getCurrentKeyboardFocusManager(). setGlobalCurrentFocusCycleRootPriv(window); - toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP); + toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_UP); } } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/Container.java b/jdk/src/java.desktop/share/classes/java/awt/Container.java index a16c2f55d97..04e3f1e89bd 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Container.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, 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 @@ -55,7 +55,6 @@ import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.AWTAccessor; -import sun.awt.CausedFocusEvent; import sun.awt.PeerEvent; import sun.awt.SunToolkit; @@ -3515,7 +3514,7 @@ public class Container extends Component { Component toFocus = getFocusTraversalPolicy(). getDefaultComponent(this); if (toFocus != null) { - toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN); + toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_DOWN); } } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java index b6f1bcfbe4e..ad23e21655a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.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 @@ -40,7 +40,6 @@ import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.AWTAccessor; -import sun.awt.CausedFocusEvent; import sun.awt.TimedWindowEvent; /** @@ -165,13 +164,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { boolean clearOnFailure) { if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() && - toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK)) + toFocus.requestFocus(false, FocusEvent.Cause.ROLLBACK)) { return true; } else { Component nextFocus = toFocus.getNextFocusCandidate(); if (nextFocus != null && nextFocus != vetoedComponent && - nextFocus.requestFocusInWindow(CausedFocusEvent.Cause.ROLLBACK)) + nextFocus.requestFocusInWindow(FocusEvent.Cause.ROLLBACK)) { return true; } else if (clearOnFailure) { @@ -431,13 +430,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { tempLost, toFocus); } if (tempLost != null) { - tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION); + tempLost.requestFocusInWindow(FocusEvent.Cause.ACTIVATION); } if (toFocus != null && toFocus != tempLost) { // If there is a component which requested focus when this window // was inactive it expects to receive focus after activation. - toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION); + toFocus.requestFocusInWindow(FocusEvent.Cause.ACTIVATION); } } @@ -490,8 +489,6 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { case FocusEvent.FOCUS_GAINED: { FocusEvent fe = (FocusEvent)e; - CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ? - ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN; Component oldFocusOwner = getGlobalFocusOwner(); Component newFocusOwner = fe.getComponent(); if (oldFocusOwner == newFocusOwner) { @@ -509,10 +506,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { if (oldFocusOwner != null) { boolean isEventDispatched = sendMessage(oldFocusOwner, - new CausedFocusEvent(oldFocusOwner, + new FocusEvent(oldFocusOwner, FocusEvent.FOCUS_LOST, fe.isTemporary(), - newFocusOwner, cause)); + newFocusOwner, fe.getCause())); // Failed to dispatch, clear by ourselves if (!isEventDispatched) { setGlobalFocusOwner(null); @@ -552,7 +549,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { // Refuse focus on a disabled component if the focus event // isn't of UNKNOWN reason (i.e. not a result of a direct request // but traversal, activation or system generated). - (newFocusOwner.isEnabled() || cause.equals(CausedFocusEvent.Cause.UNKNOWN)))) + (newFocusOwner.isEnabled() || fe.getCause().equals(FocusEvent.Cause.UNKNOWN)))) { // we should not accept focus on such component, so reject it. dequeueKeyEvents(-1, newFocusOwner); @@ -601,10 +598,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { Component realOppositeComponent = this.realOppositeComponentWR.get(); if (realOppositeComponent != null && realOppositeComponent != fe.getOppositeComponent()) { - fe = new CausedFocusEvent(newFocusOwner, + fe = new FocusEvent(newFocusOwner, FocusEvent.FOCUS_GAINED, fe.isTemporary(), - realOppositeComponent, cause); + realOppositeComponent, fe.getCause()); ((AWTEvent) fe).isPosted = true; } return typeAheadAssertions(newFocusOwner, fe); @@ -729,10 +726,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { oppositeComp = oppositeWindow; } sendMessage(currentFocusOwner, - new CausedFocusEvent(currentFocusOwner, + new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, true, - oppositeComp, CausedFocusEvent.Cause.ACTIVATION)); + oppositeComp, FocusEvent.Cause.ACTIVATION)); } setGlobalFocusedWindow(null); diff --git a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java index 6b7d779a7db..aa9d64367a4 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.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 @@ -57,7 +57,6 @@ import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.SunToolkit; -import sun.awt.CausedFocusEvent; import sun.awt.KeyboardFocusManagerPeerProvider; import sun.awt.AWTAccessor; @@ -124,7 +123,7 @@ public abstract class KeyboardFocusManager boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { return KeyboardFocusManager.shouldNativelyFocusHeavyweight( heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause); @@ -2164,9 +2163,9 @@ public abstract class KeyboardFocusManager private static final class LightweightFocusRequest { final Component component; final boolean temporary; - final CausedFocusEvent.Cause cause; + final FocusEvent.Cause cause; - LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) { + LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) { this.component = component; this.temporary = temporary; this.cause = cause; @@ -2190,7 +2189,7 @@ public abstract class KeyboardFocusManager } HeavyweightFocusRequest(Component heavyweight, Component descendant, - boolean temporary, CausedFocusEvent.Cause cause) { + boolean temporary, FocusEvent.Cause cause) { if (log.isLoggable(PlatformLogger.Level.FINE)) { if (heavyweight == null) { log.fine("Assertion (heavyweight != null) failed"); @@ -2202,7 +2201,7 @@ public abstract class KeyboardFocusManager addLightweightRequest(descendant, temporary, cause); } boolean addLightweightRequest(Component descendant, - boolean temporary, CausedFocusEvent.Cause cause) { + boolean temporary, FocusEvent.Cause cause) { if (log.isLoggable(PlatformLogger.Level.FINE)) { if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) { log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed"); @@ -2314,7 +2313,7 @@ public abstract class KeyboardFocusManager hwFocusRequest = new HeavyweightFocusRequest(heavyweight, descendant, - temporary, CausedFocusEvent.Cause.UNKNOWN); + temporary, FocusEvent.Cause.UNKNOWN); heavyweightRequests.add(hwFocusRequest); if (currentFocusOwner != null) { @@ -2379,7 +2378,7 @@ public abstract class KeyboardFocusManager */ static int shouldNativelyFocusHeavyweight (Component heavyweight, Component descendant, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) + boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause) { if (log.isLoggable(PlatformLogger.Level.FINE)) { if (heavyweight == null) { @@ -2445,7 +2444,7 @@ public abstract class KeyboardFocusManager if (currentFocusOwner != null) { FocusEvent currentFocusOwnerEvent = - new CausedFocusEvent(currentFocusOwner, + new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, temporary, descendant, cause); // Fix 5028014. Rolled out. @@ -2454,7 +2453,7 @@ public abstract class KeyboardFocusManager currentFocusOwnerEvent); } FocusEvent newFocusOwnerEvent = - new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED, + new FocusEvent(descendant, FocusEvent.FOCUS_GAINED, temporary, currentFocusOwner, cause); // Fix 5028014. Rolled out. // SunToolkit.postPriorityEvent(newFocusOwnerEvent); @@ -2670,13 +2669,13 @@ public abstract class KeyboardFocusManager * lw requests. */ if (currentFocusOwner != null) { - currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner, + currentFocusOwnerEvent = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, lwFocusRequest.temporary, lwFocusRequest.component, lwFocusRequest.cause); } FocusEvent newFocusOwnerEvent = - new CausedFocusEvent(lwFocusRequest.component, + new FocusEvent(lwFocusRequest.component, FocusEvent.FOCUS_GAINED, lwFocusRequest.temporary, currentFocusOwner == null ? lastFocusOwner : currentFocusOwner, @@ -2726,8 +2725,8 @@ public abstract class KeyboardFocusManager { temporary = true; } - return new CausedFocusEvent(source, fe.getID(), temporary, opposite, - CausedFocusEvent.Cause.NATIVE_SYSTEM); + return new FocusEvent(source, fe.getID(), temporary, opposite, + FocusEvent.Cause.UNEXPECTED); } } @@ -2802,7 +2801,7 @@ public abstract class KeyboardFocusManager // 'opposite' will be fixed by // DefaultKeyboardFocusManager.realOppositeComponent - return new CausedFocusEvent(newSource, + return new FocusEvent(newSource, FocusEvent.FOCUS_GAINED, temporary, opposite, lwFocusRequest.cause); } @@ -2815,8 +2814,8 @@ public abstract class KeyboardFocusManager // If it arrives as the result of activation we should skip it // This event will not have appropriate request record and // on arrival there will be already some focus owner set. - return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false, - null, CausedFocusEvent.Cause.ACTIVATION); + return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false, + null, FocusEvent.Cause.ACTIVATION); } return retargetUnexpectedFocusEvent(fe); @@ -2839,9 +2838,9 @@ public abstract class KeyboardFocusManager if (currentFocusOwner != null) { // Call to KeyboardFocusManager.clearGlobalFocusOwner() heavyweightRequests.removeFirst(); - return new CausedFocusEvent(currentFocusOwner, + return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, false, null, - CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER); + FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER); } // Otherwise, fall through to failure case below @@ -2850,9 +2849,9 @@ public abstract class KeyboardFocusManager { // Focus leaving application if (currentFocusOwner != null) { - return new CausedFocusEvent(currentFocusOwner, + return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, - true, null, CausedFocusEvent.Cause.ACTIVATION); + true, null, FocusEvent.Cause.ACTIVATION); } else { return fe; } @@ -2878,15 +2877,15 @@ public abstract class KeyboardFocusManager ? true : lwFocusRequest.temporary; - return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, + return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, temporary, lwFocusRequest.component, lwFocusRequest.cause); } else if (focusedWindowChanged(opposite, currentFocusOwner)) { // If top-level changed there might be no focus request in a list // But we know the opposite, we now it is temporary - dispatch the event. if (!fe.isTemporary() && currentFocusOwner != null) { // Create copy of the event with only difference in temporary parameter. - fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, - true, opposite, CausedFocusEvent.Cause.ACTIVATION); + fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, + true, opposite, FocusEvent.Cause.ACTIVATION); } return fe; } diff --git a/jdk/src/java.desktop/share/classes/java/awt/Window.java b/jdk/src/java.desktop/share/classes/java/awt/Window.java index 5894ad303b7..71fc98009b3 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Window.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, 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 @@ -52,7 +52,6 @@ import javax.accessibility.*; import sun.awt.AWTAccessor; import sun.awt.AWTPermissions; import sun.awt.AppContext; -import sun.awt.CausedFocusEvent; import sun.awt.DebugSettings; import sun.awt.SunToolkit; import sun.awt.util.IdentityArrayList; @@ -2599,7 +2598,7 @@ public class Window extends Container implements Accessible { { Component toFocus = KeyboardFocusManager.getMostRecentFocusOwner(owner); - if (toFocus != null && toFocus.requestFocus(false, CausedFocusEvent.Cause.ACTIVATION)) { + if (toFocus != null && toFocus.requestFocus(false, FocusEvent.Cause.ACTIVATION)) { return; } } diff --git a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java index afef05edef0..c4483a4d927 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java +++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.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 @@ -26,6 +26,9 @@ package java.awt.event; import java.awt.Component; +import java.io.ObjectStreamException; + +import sun.awt.AWTAccessor; import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -51,6 +54,10 @@ import sun.awt.SunToolkit; * the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in * the event using the isTemporary() method. *

    + * Every {@code FocusEvent} records its cause - the reason why this event was + * generated. The cause is assigned during the focus event creation and may be + * retrieved by calling {@link #getCause}. + *

    * An unspecified behavior will be caused if the {@code id} parameter * of any particular {@code FocusEvent} instance is not * in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}. @@ -65,6 +72,61 @@ import sun.awt.SunToolkit; */ public class FocusEvent extends ComponentEvent { + /** + * This enum represents the cause of a {@code FocusEvent}- the reason why it + * occurred. Possible reasons include mouse events, keyboard focus + * traversal, window activation. + * If no cause is provided then the reason is {@code UNKNOWN}. + * + * @since 9 + */ + public enum Cause { + /** + * The default value. + */ + UNKNOWN, + /** + * An activating mouse event. + */ + MOUSE_EVENT, + /** + * A focus traversal action with unspecified direction. + */ + TRAVERSAL, + /** + * An up-cycle focus traversal action. + */ + TRAVERSAL_UP, + /** + * A down-cycle focus traversal action. + */ + TRAVERSAL_DOWN, + /** + * A forward focus traversal action. + */ + TRAVERSAL_FORWARD, + /** + * A backward focus traversal action. + */ + TRAVERSAL_BACKWARD, + /** + * Restoring focus after a focus request has been rejected. + */ + ROLLBACK, + /** + * A system action causing an unexpected focus change. + */ + UNEXPECTED, + /** + * An activation of a toplevel window. + */ + ACTIVATION, + /** + * Clearing global focus owner. + */ + CLEAR_GLOBAL_FOCUS_OWNER + } + /** * The first number in the range of ids used for focus events. */ @@ -85,6 +147,16 @@ public class FocusEvent extends ComponentEvent { */ public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS + /** + * A focus event has the reason why this event was generated. + * The cause is set during the focus event creation. + * + * @serial + * @see #getCause() + * @since 9 + */ + private final Cause cause; + /** * A focus event can have two different levels, permanent and temporary. * It will be set to true if some operation takes away the focus @@ -115,7 +187,8 @@ public class FocusEvent extends ComponentEvent { /** * Constructs a {@code FocusEvent} object with the - * specified temporary state and opposite {@code Component}. + * specified temporary state, opposite {@code Component} and the + * {@code Cause.UNKNOWN} cause. * The opposite {@code Component} is the other * {@code Component} involved in this focus change. * For a {@code FOCUS_GAINED} event, this is the @@ -142,13 +215,57 @@ public class FocusEvent extends ComponentEvent { * @see #getID() * @see #isTemporary() * @see #getOppositeComponent() + * @see Cause#UNKNOWN * @since 1.4 */ public FocusEvent(Component source, int id, boolean temporary, Component opposite) { + this(source, id, temporary, opposite, Cause.UNKNOWN); + } + + /** + * Constructs a {@code FocusEvent} object with the + * specified temporary state, opposite {@code Component} and the cause. + * The opposite {@code Component} is the other + * {@code Component} involved in this focus change. + * For a {@code FOCUS_GAINED} event, this is the + * {@code Component} that lost focus. For a + * {@code FOCUS_LOST} event, this is the {@code Component} + * that gained focus. If this focus change occurs with a native + * application, with a Java application in a different VM, + * or with no other {@code Component}, then the opposite + * {@code Component} is {@code null}. + *

    This method throws an + * {@code IllegalArgumentException} if {@code source} or {@code cause} + * is {@code null}. + * + * @param source The {@code Component} that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link FocusEvent} + * @param temporary Equals {@code true} if the focus change is temporary; + * {@code false} otherwise + * @param opposite The other Component involved in the focus change, + * or {@code null} + * @param cause The focus event cause. + * @throws IllegalArgumentException if {@code source} equals {@code null} + * or if {@code cause} equals {@code null} + * @see #getSource() + * @see #getID() + * @see #isTemporary() + * @see #getOppositeComponent() + * @see Cause + * @since 9 + */ + public FocusEvent(Component source, int id, boolean temporary, + Component opposite, Cause cause) { super(source, id); + if (cause == null) { + throw new IllegalArgumentException("null cause"); + } this.temporary = temporary; this.opposite = opposite; + this.cause = cause; } /** @@ -220,8 +337,8 @@ public class FocusEvent extends ComponentEvent { return (SunToolkit.targetToAppContext(opposite) == AppContext.getAppContext()) - ? opposite - : null; + ? opposite + : null; } /** @@ -233,17 +350,56 @@ public class FocusEvent extends ComponentEvent { public String paramString() { String typeStr; switch(id) { - case FOCUS_GAINED: - typeStr = "FOCUS_GAINED"; - break; - case FOCUS_LOST: - typeStr = "FOCUS_LOST"; - break; - default: - typeStr = "unknown type"; + case FOCUS_GAINED: + typeStr = "FOCUS_GAINED"; + break; + case FOCUS_LOST: + typeStr = "FOCUS_LOST"; + break; + default: + typeStr = "unknown type"; } return typeStr + (temporary ? ",temporary" : ",permanent") + - ",opposite=" + getOppositeComponent(); + ",opposite=" + getOppositeComponent() + ",cause=" + getCause(); } -} + /** + * Returns the event cause. + * + * @return one of {@link Cause} values + * @since 9 + */ + public final Cause getCause() { + return cause; + } + + /** + * Checks if this deserialized {@code FocusEvent} instance is compatible + * with the current specification which implies that focus event has + * non-null {@code cause} value. If the check fails a new {@code FocusEvent} + * instance is returned which {@code cause} field equals to + * {@link Cause#UNKNOWN} and its other fields have the same values as in + * this {@code FocusEvent} instance. + * + * @serial + * @see #cause + * @since 9 + */ + @SuppressWarnings("serial") + Object readResolve() throws ObjectStreamException { + if (cause != null) { + return this; + } + FocusEvent focusEvent = new FocusEvent(new Component(){}, getID(), + isTemporary(), getOppositeComponent()); + focusEvent.setSource(null); + focusEvent.consumed = consumed; + + AWTAccessor.AWTEventAccessor accessor = + AWTAccessor.getAWTEventAccessor(); + accessor.setBData(focusEvent, accessor.getBData(this)); + return focusEvent; + } + + +} \ No newline at end of file diff --git a/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java b/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java index 2ac37efb7d1..40890c784e8 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, 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 @@ -27,12 +27,12 @@ package java.awt.peer; import java.awt.*; import java.awt.event.PaintEvent; +import java.awt.event.FocusEvent.Cause; import java.awt.image.ColorModel; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.awt.image.VolatileImage; -import sun.awt.CausedFocusEvent; import sun.java2d.pipe.Region; @@ -343,7 +343,7 @@ public interface ComponentPeer { */ boolean requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause); + Cause cause); /** * Returns {@code true} when the component takes part in the focus diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java index 883e0c0cf7c..dd64b77df1d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.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 @@ -3558,7 +3558,7 @@ public abstract class JComponent extends Container implements Serializable, new sun.awt.RequestFocusController() { public boolean acceptRequestFocus(Component from, Component to, boolean temporary, boolean focusedWindowChangeAllowed, - sun.awt.CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { if ((to == null) || !(to instanceof JComponent)) { return true; diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index 7d67cd6ae47..796b7ab5d79 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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,6 +29,7 @@ import jdk.internal.misc.Unsafe; import javax.accessibility.AccessibleContext; import java.awt.*; +import java.awt.event.FocusEvent.Cause; import java.awt.dnd.DragSourceContext; import java.awt.dnd.DropTargetContext; import java.awt.dnd.peer.DragSourceContextPeer; @@ -104,7 +105,7 @@ public final class AWTAccessor { /* * Requests focus to the component. */ - boolean requestFocus(Component comp, CausedFocusEvent.Cause cause); + boolean requestFocus(Component comp, Cause cause); /* * Determines if the component can gain focus. */ @@ -438,7 +439,7 @@ public final class AWTAccessor { boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause); + Cause cause); /** * Delivers focus for the lightweight descendant of the heavyweight * synchronously. diff --git a/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java b/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java index 985b416cffc..638a63f549d 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, 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 @@ -27,17 +27,18 @@ package sun.awt; import java.awt.event.FocusEvent; import java.awt.Component; +import java.io.ObjectStreamException; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; /** - * This class represents FocusEvents with a known "cause" - reason why this event happened. It can - * be mouse press, traversal, activation, and so on - all causes are described as Cause enum. The - * event with the cause can be constructed in two ways - explicitly through constructor of - * CausedFocusEvent class or implicitly, by calling appropriate requestFocusXXX method with "cause" - * parameter. The default cause is UNKNOWN. + * This class exists for deserialization compatibility only. */ -@SuppressWarnings("serial") -public class CausedFocusEvent extends FocusEvent { - public enum Cause { +class CausedFocusEvent extends FocusEvent { + private static final long serialVersionUID = -3647309088427840738L; + + private enum Cause { UNKNOWN, MOUSE_EVENT, TRAVERSAL, @@ -51,39 +52,82 @@ public class CausedFocusEvent extends FocusEvent { NATIVE_SYSTEM, ACTIVATION, CLEAR_GLOBAL_FOCUS_OWNER, - RETARGETED + RETARGETED; }; + @SuppressWarnings("serial") + private static final Component dummy = new Component(){}; + private final Cause cause; - public Cause getCause() { - return cause; - } - - public String toString() { - return "java.awt.FocusEvent[" + super.paramString() + ",cause=" + cause + "] on " + getSource(); - } - - public CausedFocusEvent(Component source, int id, boolean temporary, + private CausedFocusEvent(Component source, int id, boolean temporary, Component opposite, Cause cause) { super(source, id, temporary, opposite); - if (cause == null) { - cause = Cause.UNKNOWN; - } - this.cause = cause; + throw new IllegalStateException(); } - /** - * Retargets the original focus event to the new target. If the - * original focus event is CausedFocusEvent, it remains such and - * cause is copied. Otherwise, new CausedFocusEvent is created, - * with cause as RETARGETED. - * @return retargeted event, or null if e is null - */ - public static FocusEvent retarget(FocusEvent e, Component newSource) { - if (e == null) return null; + Object readResolve() throws ObjectStreamException { + FocusEvent.Cause newCause; + switch (cause) { + case UNKNOWN: + newCause = FocusEvent.Cause.UNKNOWN; + break; + case MOUSE_EVENT: + newCause = FocusEvent.Cause.MOUSE_EVENT; + break; + case TRAVERSAL: + newCause = FocusEvent.Cause.TRAVERSAL; + break; + case TRAVERSAL_UP: + newCause = FocusEvent.Cause.TRAVERSAL_UP; + break; + case TRAVERSAL_DOWN: + newCause = FocusEvent.Cause.TRAVERSAL_DOWN; + break; + case TRAVERSAL_FORWARD: + newCause = FocusEvent.Cause.TRAVERSAL_FORWARD; + break; + case TRAVERSAL_BACKWARD: + newCause = FocusEvent.Cause.TRAVERSAL_BACKWARD; + break; + case ROLLBACK: + newCause = FocusEvent.Cause.ROLLBACK; + break; + case NATIVE_SYSTEM: + newCause = FocusEvent.Cause.UNEXPECTED; + break; + case ACTIVATION: + newCause = FocusEvent.Cause.ACTIVATION; + break; + case CLEAR_GLOBAL_FOCUS_OWNER: + newCause = FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER; + break; + default: + newCause = FocusEvent.Cause.UNKNOWN; + } - return new CausedFocusEvent(newSource, e.getID(), e.isTemporary(), e.getOppositeComponent(), - (e instanceof CausedFocusEvent) ? ((CausedFocusEvent)e).getCause() : Cause.RETARGETED); + FocusEvent focusEvent = new FocusEvent(dummy, getID(), isTemporary(), + getOppositeComponent(), newCause); + focusEvent.setSource(null); + try { + final Field consumedField = FocusEvent.class.getField("consumed"); + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Object run() { + consumedField.setAccessible(true); + try { + consumedField.set(focusEvent, consumed); + } catch (IllegalAccessException e) { + } + return null; + } + }); + } catch (NoSuchFieldException e) { + } + + AWTAccessor.AWTEventAccessor accessor = + AWTAccessor.getAWTEventAccessor(); + accessor.setBData(focusEvent, accessor.getBData(this)); + return focusEvent; } } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java index 11b54c807c4..b82f1833177 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.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 @@ -60,8 +60,8 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag focusLog.fine("Clearing global focus owner " + focusOwner); } if (focusOwner != null) { - FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null, - CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER); + FocusEvent fl = new FocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null, + FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER); SunToolkit.postPriorityEvent(fl); } } @@ -110,7 +110,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause, + FocusEvent.Cause cause, Component currentFocusOwner) // provided by the descendant peers { if (lightweightChild == null) { @@ -122,7 +122,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag currentOwner = null; } if (currentOwner != null) { - FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST, + FocusEvent fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST, false, lightweightChild, cause); if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { @@ -131,7 +131,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl); } - FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, + FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, false, currentOwner, cause); if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { @@ -142,7 +142,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag } // WARNING: Don't call it on the Toolkit thread. - public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) { + public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) { return AWTAccessor.getComponentAccessor().requestFocus(target, cause); } @@ -152,7 +152,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { return KfmAccessor.instance.shouldNativelyFocusHeavyweight( heavyweight, descendant, temporary, focusedWindowChangeAllowed, diff --git a/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java b/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java index d44e8ca2535..f95df58145f 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, 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 @@ -37,7 +37,7 @@ import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Insets; -import java.awt.MenuBar; +import java.awt.event.FocusEvent.Cause; import java.awt.Point; import java.awt.Event; import java.awt.event.PaintEvent; @@ -178,7 +178,7 @@ public class NullComponentPeer implements LightweightPeer, public boolean requestFocus (Component lightweightChild, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) { + boolean focusedWindowChangeAllowed, long time, Cause cause) { return false; } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java b/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java index a0b9a3ee12b..29c94c6ab1b 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -25,10 +25,11 @@ package sun.awt; import java.awt.Component; +import java.awt.event.FocusEvent.Cause; public interface RequestFocusController { public boolean acceptRequestFocus(Component from, Component to, boolean temporary, boolean focusedWindowChangeAllowed, - CausedFocusEvent.Cause cause); + Cause cause); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java index 82715e73ff2..c65a7c79f96 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.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 @@ -287,7 +287,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget @SuppressWarnings("deprecation") public final boolean requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { if (XKeyboardFocusManagerPeer. processSynchronousLightweightTransfer(target, lightweightChild, temporary, @@ -527,7 +527,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget // WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS); // parentWindow.dispatchEvent(wfg); // } - XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT); + XKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT); } break; } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java index 9370b8cdae4..e81ff91575c 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, 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 @@ -430,13 +430,10 @@ public class XEmbedCanvasPeer extends XCanvasPeer implements WindowFocusListener if (isXEmbedActive()) { xembedLog.fine("Forwarding FOCUS_GAINED"); int flavor = XEMBED_FOCUS_CURRENT; - if (e instanceof CausedFocusEvent) { - CausedFocusEvent ce = (CausedFocusEvent)e; - if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) { - flavor = XEMBED_FOCUS_FIRST; - } else if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) { - flavor = XEMBED_FOCUS_LAST; - } + if (e.getCause() == FocusEvent.Cause.TRAVERSAL_FORWARD) { + flavor = XEMBED_FOCUS_FIRST; + } else if (e.getCause() == FocusEvent.Cause.TRAVERSAL_BACKWARD) { + flavor = XEMBED_FOCUS_LAST; } xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, flavor, 0, 0); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java index 6bb38b54f24..d8fe392fe2c 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.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 @@ -195,7 +195,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { int result = XKeyboardFocusManagerPeer .shouldNativelyFocusHeavyweight(proxy, lightweightChild, diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java index dde0b87d64c..2ec736feb29 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, 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 @@ -28,7 +28,7 @@ import java.awt.Component; import java.awt.Window; import sun.awt.AWTAccessor; -import sun.awt.CausedFocusEvent; +import java.awt.event.FocusEvent; import sun.awt.KeyboardFocusManagerPeerImpl; import sun.util.logging.PlatformLogger; @@ -101,7 +101,7 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild, target, diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java index 9efe70b17c4..5d769203159 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.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 @@ -59,7 +59,6 @@ import javax.swing.text.JTextComponent; import javax.swing.plaf.BorderUIResource; import java.awt.im.InputMethodRequests; -import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; import sun.awt.SunToolkit; @@ -945,14 +944,16 @@ final class XTextAreaPeer extends XComponentPeer implements TextAreaPeer { void forwardFocusGained( FocusEvent e) { isFocused = true; - FocusEvent fe = CausedFocusEvent.retarget(e, this); + FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(), + e.getOppositeComponent(), e.getCause()); super.processFocusEvent(fe); } void forwardFocusLost( FocusEvent e) { isFocused = false; - FocusEvent fe = CausedFocusEvent.retarget(e, this); + FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(), + e.getOppositeComponent(), e.getCause()); super.processFocusEvent(fe); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java index 9df078e9d1f..42730dce98f 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.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 @@ -54,7 +54,6 @@ import java.awt.im.InputMethodRequests; import sun.util.logging.PlatformLogger; -import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; final class XTextFieldPeer extends XComponentPeer implements TextFieldPeer { @@ -618,13 +617,15 @@ final class XTextFieldPeer extends XComponentPeer implements TextFieldPeer { void forwardFocusGained( FocusEvent e) { isFocused = true; - FocusEvent fe = CausedFocusEvent.retarget(e, this); + FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(), + e.getOppositeComponent(), e.getCause()); super.processFocusEvent(fe); } void forwardFocusLost( FocusEvent e) { isFocused = false; - FocusEvent fe = CausedFocusEvent.retarget(e, this); + FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(), + e.getOppositeComponent(), e.getCause()); super.processFocusEvent(fe); } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java index 51e16b0a1f1..f07857b80b4 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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,6 @@ import java.awt.*; import java.awt.peer.*; import java.awt.image.VolatileImage; import sun.awt.RepaintArea; -import sun.awt.CausedFocusEvent; import sun.awt.image.SunVolatileImage; import sun.awt.image.ToolkitImage; import java.awt.image.BufferedImage; @@ -321,7 +320,7 @@ public abstract class WComponentPeer extends WObjectPeer WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target)) { WKeyboardFocusManagerPeer.requestFocusFor((Component)target, - CausedFocusEvent.Cause.MOUSE_EVENT); + FocusEvent.Cause.MOUSE_EVENT); } break; } @@ -687,7 +686,7 @@ public abstract class WComponentPeer extends WObjectPeer @Override public boolean requestFocus(Component lightweightChild, boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + FocusEvent.Cause cause) { if (WKeyboardFocusManagerPeer. processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, 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 383254b815a..40c995def1d 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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 @@ -25,6 +25,7 @@ package sun.awt.windows; import java.awt.*; +import java.awt.event.FocusEvent.Cause; import java.awt.dnd.DropTarget; import java.awt.peer.*; import java.io.File; @@ -34,7 +35,6 @@ import java.security.PrivilegedAction; import java.util.ResourceBundle; import java.util.MissingResourceException; import java.util.Vector; -import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @@ -282,7 +282,7 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @Override public boolean requestFocus (Component lightweightChild, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) + boolean focusedWindowChangeAllowed, long time, Cause cause) { return false; } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java index a475328881a..f11409d4aca 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 java.awt.peer.ComponentPeer; import sun.awt.AWTAccessor; import sun.awt.AWTAccessor.ComponentAccessor; import sun.awt.KeyboardFocusManagerPeerImpl; -import sun.awt.CausedFocusEvent; +import java.awt.event.FocusEvent.Cause; final class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { static native void setNativeFocusOwner(ComponentPeer peer); @@ -75,7 +75,7 @@ final class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { boolean temporary, boolean focusedWindowChangeAllowed, long time, - CausedFocusEvent.Cause cause) + Cause cause) { // TODO: do something to eliminate this forwarding return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild, 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 a80e7dd6d13..d4ae0eb491e 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 @@ -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 @@ -26,11 +26,11 @@ package sun.awt.windows; import java.awt.*; +import java.awt.event.FocusEvent.Cause; import java.awt.peer.DialogPeer; import java.awt.peer.ComponentPeer; import java.awt.dnd.DropTarget; import java.util.Vector; -import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; class WPrintDialogPeer extends WWindowPeer implements DialogPeer { @@ -153,7 +153,7 @@ class WPrintDialogPeer extends WWindowPeer implements DialogPeer { @Override public boolean requestFocus (Component lightweightChild, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) + boolean focusedWindowChangeAllowed, long time, Cause cause) { return false; diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index 12885ad2a61..2e8e81262d4 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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 @@ -300,11 +300,11 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, return getNativeWindowSize(); } - public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + public boolean requestWindowFocus(FocusEvent.Cause cause) { if (!focusAllowedFor()) { return false; } - return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT); + return requestWindowFocus(cause == FocusEvent.Cause.MOUSE_EVENT); } private native boolean requestWindowFocus(boolean isMouseEventCause); diff --git a/jdk/test/java/awt/Focus/Cause/FocusCauseTest.java b/jdk/test/java/awt/Focus/Cause/FocusCauseTest.java new file mode 100644 index 00000000000..129c3b6dd24 --- /dev/null +++ b/jdk/test/java/awt/Focus/Cause/FocusCauseTest.java @@ -0,0 +1,224 @@ +/* + * 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 8080395 + @summary consider making sun.awt.CausedFocusEvent functionality public + @run main FocusCauseTest +*/ + + +import java.awt.*; +import java.awt.event.FocusEvent.Cause; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.RuntimeException; +import java.util.Arrays; + +public class FocusCauseTest { + + private static Cause[] causes1 = {Cause.ACTIVATION, + Cause.UNKNOWN, Cause.UNKNOWN, Cause.TRAVERSAL_FORWARD, + Cause.TRAVERSAL_FORWARD, Cause.TRAVERSAL_BACKWARD, + Cause.TRAVERSAL_BACKWARD, Cause.TRAVERSAL_UP, + Cause.TRAVERSAL_DOWN, Cause.CLEAR_GLOBAL_FOCUS_OWNER}; + private static Cause[] causes2 = new Cause[10]; + private static int cnt; + + static byte[] data = + {-84, -19, 0, 5, 115, 114, 0, 24, 115, 117, 110, 46, 97, 119, + 116, 46, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118, + 101, 110, 116, -51, 98, 39, -75, 86, 52, 107, 30, 2, 0, 1, 76, 0, 5, + 99, 97, 117, 115, 101, 116, 0, 32, 76, 115, 117, 110, 47, 97, 119, + 116, 47, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118, + 101, 110, 116, 36, 67, 97, 117, 115, 101, 59, 120, 114, 0, 25, 106, + 97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46, 70, + 111, 99, 117, 115, 69, 118, 101, 110, 116, 7, 68, -65, 75, 55, -113, + 98, -52, 2, 0, 1, 90, 0, 9, 116, 101, 109, 112, 111, 114, 97, 114, + 121, 120, 114, 0, 29, 106, 97, 118, 97, 46, 97, 119, 116, 46, 101, + 118, 101, 110, 116, 46, 67, 111, 109, 112, 111, 110, 101, 110, 116, + 69, 118, 101, 110, 116, 112, 109, -6, -107, 79, -87, -38, 69, 2, 0, + 0, 120, 114, 0, 17, 106, 97, 118, 97, 46, 97, 119, 116, 46, 65, 87, + 84, 69, 118, 101, 110, 116, -26, -85, 45, -31, 24, -33, -118, -61, + 2, 0, 3, 90, 0, 8, 99, 111, 110, 115, 117, 109, 101, 100, 73, 0, 2, + 105, 100, 91, 0, 5, 98, 100, 97, 116, 97, 116, 0, 2, 91, 66, 120, + 114, 0, 21, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 69, 118, + 101, 110, 116, 79, 98, 106, 101, 99, 116, 76, -115, 9, 78, 24, 109, + 125, -88, 2, 0, 0, 120, 112, 0, 0, 0, 3, -20, 112, 0, 126, 114, 0, + 30, 115, 117, 110, 46, 97, 119, 116, 46, 67, 97, 117, 115, 101, 100, + 70, 111, 99, 117, 115, 69, 118, 101, 110, 116, 36, 67, 97, 117, 115, + 101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 120, 114, 0, 14, 106, 97, + 118, 97, 46, 108, 97, 110, 103, 46, 69, 110, 117, 109, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 120, 112, 116, 0}; + + static byte[] dataOld = + {-84, -19, 0, 5, 115, 114, 0, 25, 106, 97, 118, 97, 46, 97, 119, + 116, 46, 101, 118, 101, 110, 116, 46, 70, 111, 99, 117, 115, 69, + 118, 101, 110, 116, 7, 68, -65, 75, 55, -113, 98, -52, 2, 0, 1, 90, + 0, 9, 116, 101, 109, 112, 111, 114, 97, 114, 121, 120, 114, 0, 29, + 106, 97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46, + 67, 111, 109, 112, 111, 110, 101, 110, 116, 69, 118, 101, 110, 116, + 112, 109, -6, -107, 79, -87, -38, 69, 2, 0, 0, 120, 114, 0, 17, 106, + 97, 118, 97, 46, 97, 119, 116, 46, 65, 87, 84, 69, 118, 101, 110, + 116, -26, -85, 45, -31, 24, -33, -118, -61, 2, 0, 3, 90, 0, 8, 99, + 111, 110, 115, 117, 109, 101, 100, 73, 0, 2, 105, 100, 91, 0, 5, 98, + 100, 97, 116, 97, 116, 0, 2, 91, 66, 120, 114, 0, 21, 106, 97, 118, + 97, 46, 117, 116, 105, 108, 46, 69, 118, 101, 110, 116, 79, 98, 106, + 101, 99, 116, 76, -115, 9, 78, 24, 109, 125, -88, 2, 0, 0, 120, 112, + 0, 0, 0, 0, 100, 112, 0}; + + static String[] causesIn = {"UNKNOWN", "MOUSE_EVENT", "TRAVERSAL", + "TRAVERSAL_UP", "TRAVERSAL_DOWN", "TRAVERSAL_FORWARD", + "TRAVERSAL_BACKWARD", "MANUAL_REQUEST", "AUTOMATIC_TRAVERSE" + ,"ROLLBACK", "NATIVE_SYSTEM", "ACTIVATION", + "CLEAR_GLOBAL_FOCUS_OWNER", "RETARGETED"}; + + static FocusEvent.Cause[] causesOut = {FocusEvent.Cause.UNKNOWN, + FocusEvent.Cause.MOUSE_EVENT, + FocusEvent.Cause.TRAVERSAL, FocusEvent.Cause.TRAVERSAL_UP, + FocusEvent.Cause.TRAVERSAL_DOWN, FocusEvent.Cause.TRAVERSAL_FORWARD, + FocusEvent.Cause.TRAVERSAL_BACKWARD, FocusEvent.Cause.UNKNOWN, + FocusEvent.Cause.UNKNOWN, FocusEvent.Cause.ROLLBACK, + FocusEvent.Cause.UNEXPECTED, FocusEvent.Cause.ACTIVATION, + FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER, FocusEvent.Cause.UNKNOWN + }; + + public static void main(String[] args) throws Exception { + testCauses(); + testNullCause(); + testCausedFocusEventDeserialization(); + testFocusEventDeserialization(); + System.out.println("ok"); + } + + private static void testNullCause() { + try { + new FocusEvent(new Frame(), FocusEvent.FOCUS_GAINED, true, + null, null); + throw new RuntimeException("Exception is not thrown when the " + + "cause is null"); + } catch (IllegalArgumentException e) { + } + } + + private static void testCauses() throws Exception { + cnt = 0; + Frame frame = new Frame(); + TextField comp1 = new TextField(); + comp1.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + System.out.println(e.getCause()); + causes2[cnt++] = e.getCause(); + } + + @Override + public void focusLost(FocusEvent e) { + System.out.println(e.getCause()); + causes2[cnt++] = e.getCause(); + } + }); + TextField comp2 = new TextField(); + comp2.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + System.out.println(e.getCause()); + causes2[cnt++] = e.getCause(); + } + + @Override + public void focusLost(FocusEvent e) { + System.out.println(e.getCause()); + causes2[cnt++] = e.getCause(); + } + }); + frame.add(comp1, BorderLayout.NORTH); + frame.add(comp2, BorderLayout.SOUTH); + frame.setVisible(true); + + Robot robot = new Robot(); + robot.delay(200); + robot.waitForIdle(); + comp2.requestFocus(); + robot.waitForIdle(); + comp2.transferFocus(); + robot.waitForIdle(); + comp1.transferFocusBackward(); + robot.waitForIdle(); + comp2.transferFocusUpCycle(); + robot.waitForIdle(); + frame.transferFocusDownCycle(); + robot.waitForIdle(); + frame.dispose(); + robot.waitForIdle(); + if (!Arrays.equals(causes1, causes2)) { + throw new RuntimeException("wrong cause " + causes2); + } + } + + private static void testCausedFocusEventDeserialization() throws + Exception { + for (int i = 0; i < causesIn.length; i++) { + final String causeIn = causesIn[i]; + ObjectInputStream oi = new ObjectInputStream(new InputStream() { + int cnt = 0; + @Override + public int read() throws IOException { + if(cnt < data.length) { + return data[cnt++]; + } else if(cnt == data.length){ + cnt++; + return causeIn.length(); + } else if(cnt - data.length - 1 < causeIn.length()) { + return causeIn.getBytes()[cnt++ - data.length - 1]; + } + return -1; + } + }); + FocusEvent ev = (FocusEvent) oi.readObject(); + System.out.println(ev); + if(ev.getCause() != causesOut[i]) { + throw new RuntimeException("Wrong cause read :" +ev.getCause()); + } + } + } + + private static void testFocusEventDeserialization() throws + Exception { + ObjectInputStream oi = new ObjectInputStream( + new ByteArrayInputStream(dataOld)); + FocusEvent ev = (FocusEvent)oi.readObject(); + if(ev.getCause() != FocusEvent.Cause.UNKNOWN) { + throw new RuntimeException("Wrong cause in deserialized FocusEvent " + + ev.getCause()); + } + } + +} From dc0aed8917af20d28df38590998d116ab6b6070d Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 15 Apr 2016 09:54:27 +0300 Subject: [PATCH 094/225] 8153276: [TEST_BUG] javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java Reviewed-by: alexsch, yan --- .../ShellFolderQueries/ShellFolderQueriesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java index 0892b5e2090..3cd85f21823 100644 --- a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java +++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java @@ -30,7 +30,6 @@ * @run main ShellFolderQueriesTest */ -import sun.awt.OSInfo; import javax.swing.filechooser.FileSystemView; import java.io.File; @@ -50,7 +49,8 @@ public class ShellFolderQueriesTest { static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save"; public static void main(String[] args) throws Exception { - if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + if(System.getProperty("os.name").toLowerCase().contains("windows")) { + System.out.println("Windows detected: will run shortcut test"); testGet(); testLink(); } else { From 3029b6b065f7d455225cb65ca23f33a74858da4e Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 15 Apr 2016 09:59:36 +0300 Subject: [PATCH 095/225] 8145787: [TEST_BUG][PIT] javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java fails with CannotUndoException Reviewed-by: alexsch, serb --- .../AbstractDocumentUndoConcurrentTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java b/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java index 30c48df47f8..a425f5a0fe0 100644 --- a/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java +++ b/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.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 @@ -104,8 +104,12 @@ public class AbstractDocumentUndoConcurrentTest { e.printStackTrace(); } for (int i = 0; i < 1000; i++) { - undoManager.undoOrRedo(); - undoManager.undo(); + if(undoManager.canUndoOrRedo()) { + undoManager.undoOrRedo(); + } + if(undoManager.canUndo()) { + undoManager.undo(); + } } System.out.println("t3 done"); } From d20efa360f420a46c3057c15ea7cfd392cbedaa5 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 15 Apr 2016 11:39:31 +0200 Subject: [PATCH 096/225] 8154283: Check for clash between package and class not working when package in a different module Looking for any visible package when checking for package-class clash Reviewed-by: jjg --- .../com/sun/tools/javac/code/Symtab.java | 2 +- .../com/sun/tools/javac/comp/MemberEnter.java | 4 -- .../test/tools/javac/modules/EdgeCases.java | 37 ++++++++++++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java index db9d1bbfda6..2d1c87d3272 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java @@ -698,7 +698,7 @@ public class Symtab { */ public boolean packageExists(ModuleSymbol msym, Name fullname) { Assert.checkNonNull(msym); - return enterPackage(msym, fullname).exists(); + return lookupPackage(msym, fullname).exists(); } /** Make a package, given its fully qualified name. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 48ebd8e74ca..8db5f0899e0 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -53,10 +53,6 @@ import static com.sun.tools.javac.code.TypeTag.TYPEVAR; public class MemberEnter extends JCTree.Visitor { protected static final Context.Key memberEnterKey = new Context.Key<>(); - /** A switch to determine whether we check for package/class conflicts - */ - final static boolean checkClash = true; - private final Enter enter; private final Log log; private final Check chk; diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java index c85f364f3c8..4c80bd4f7b4 100644 --- a/langtools/test/tools/javac/modules/EdgeCases.java +++ b/langtools/test/tools/javac/modules/EdgeCases.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154283 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules @@ -57,7 +58,6 @@ import com.sun.tools.javac.code.Symbol.ModuleSymbol; import toolbox.JarTask; import toolbox.JavacTask; import toolbox.Task; -import toolbox.ToolBox; public class EdgeCases extends ModuleTestBase { @@ -269,4 +269,39 @@ public class EdgeCases extends ModuleTestBase { } + @Test + void testClassPackageClash(Path base) throws Exception { + Path src = base.resolve("src"); + Path src_m1 = src.resolve("m1"); + tb.writeJavaFiles(src_m1, + "module m1 { exports test.m1; }", + "package test.m1;\n" + + "public class Test {}\n"); + Path src_m2 = src.resolve("m2"); + tb.writeJavaFiles(src_m2, + "module m2 { requires m1; }", + "package test;\n" + + "public class m1 {}\n"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List log = new JavacTask(tb) + .options("-modulesourcepath", src.toString(), + "-XDrawDiagnostics") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "m1.java:2:8: compiler.err.clash.with.pkg.of.same.name: kindname.class, test.m1", + "1 error" + ); + + if (!expected.equals(log)) { + throw new IllegalStateException(log.toString()); + } + } + } From 65bd7fafd82cf9cc64dd028edb55cb93df2f9a6d Mon Sep 17 00:00:00 2001 From: Ajit Ghaisas Date: Fri, 15 Apr 2016 15:50:45 +0530 Subject: [PATCH 097/225] 8049069: JButton incorrect behaviour on button release Reviewed-by: serb, alexsch --- .../classes/javax/swing/SwingUtilities.java | 44 ++++++- .../JButton/PressedButtonRightClickTest.java | 112 ++++++++++++++++++ 2 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index 6a48eb423a3..9900c9b7e0e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -845,6 +845,38 @@ public class SwingUtilities implements SwingConstants return result; } + /** + * Check whether MouseEvent contains speficied mouse button or + * mouse button down mask based on MouseEvent ID. + * + * @param anEvent a MouseEvent object + * @param mouseButton mouse button type + * @param mouseButtonDownMask mouse button down mask event modifier + * + * @return true if the anEvent contains speficied mouseButton or + * mouseButtonDownMask based on MouseEvent ID. + */ + private static boolean checkMouseButton(MouseEvent anEvent, + int mouseButton, + int mouseButtonDownMask) + { + switch (anEvent.getID()) { + case MouseEvent.MOUSE_PRESSED: + case MouseEvent.MOUSE_RELEASED: + case MouseEvent.MOUSE_CLICKED: + return (anEvent.getButton() == mouseButton); + + case MouseEvent.MOUSE_ENTERED: + case MouseEvent.MOUSE_EXITED: + case MouseEvent.MOUSE_DRAGGED: + return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0); + + default: + return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0 || + anEvent.getButton() == mouseButton); + } + } + /** * Returns true if the mouse event specifies the left mouse button. * @@ -852,8 +884,8 @@ public class SwingUtilities implements SwingConstants * @return true if the left mouse button was active */ public static boolean isLeftMouseButton(MouseEvent anEvent) { - return ((anEvent.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0 || - anEvent.getButton() == MouseEvent.BUTTON1); + return checkMouseButton(anEvent, MouseEvent.BUTTON1, + InputEvent.BUTTON1_DOWN_MASK); } /** @@ -863,8 +895,8 @@ public class SwingUtilities implements SwingConstants * @return true if the middle mouse button was active */ public static boolean isMiddleMouseButton(MouseEvent anEvent) { - return ((anEvent.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0 || - anEvent.getButton() == MouseEvent.BUTTON2); + return checkMouseButton(anEvent, MouseEvent.BUTTON2, + InputEvent.BUTTON2_DOWN_MASK); } /** @@ -874,8 +906,8 @@ public class SwingUtilities implements SwingConstants * @return true if the right mouse button was active */ public static boolean isRightMouseButton(MouseEvent anEvent) { - return ((anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 || - anEvent.getButton() == MouseEvent.BUTTON3); + return checkMouseButton(anEvent, MouseEvent.BUTTON3, + InputEvent.BUTTON3_DOWN_MASK); } /** diff --git a/jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java b/jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java new file mode 100644 index 00000000000..c4cddc71f18 --- /dev/null +++ b/jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java @@ -0,0 +1,112 @@ +/* + * 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.AWTException; +import java.awt.BorderLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 8049069 + * @summary Tests whether right mouse click releases a pressed JButton + */ + +public class PressedButtonRightClickTest { + + private static Robot testRobot; + private static JFrame myFrame; + private static JButton myButton; + + public static void main(String[] args) throws Throwable { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + constructTestUI(); + } + }); + + try { + testRobot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Exception in Robot creation"); + } + + testRobot.waitForIdle(); + + // Method performing auto test operation + test(); + + disposeTestUI(); + } + + private static void test() { + Point loc = myFrame.getLocationOnScreen(); + + testRobot.mouseMove((loc.x + 100), (loc.y + 100)); + + // Press the left mouse button + testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + myButton.setText("Left button pressed"); + testRobot.delay(1000); + + // Press the right mouse button + testRobot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + myButton.setText("Left button pressed + Right button pressed"); + testRobot.delay(1000); + + // Release the right mouse button + testRobot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + myButton.setText("Right button released"); + testRobot.delay(1000); + + // Test whether the button is still pressed + if (myButton.getModel().isPressed() == false) { + disposeTestUI(); + throw new RuntimeException("Test Failed!"); + } + } + + private static void disposeTestUI() { + myFrame.setVisible(false); + myFrame.dispose(); + } + + public static void constructTestUI() { + myFrame = new JFrame(); + myFrame.setLayout(new BorderLayout()); + myButton = new JButton("Whatever"); + myFrame.add(myButton, BorderLayout.CENTER); + myFrame.setSize(400, 300); + myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + myFrame.setVisible(true); + } +} + From b4712438319af7ae4fa5dbd49720782bec51b595 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Fri, 15 Apr 2016 19:15:12 +0400 Subject: [PATCH 098/225] 8132791: No access to SynthContext.getContext() Reviewed-by: serb, ssadetsky --- .../swing/plaf/synth/SynthArrowButton.java | 1 - .../javax/swing/plaf/synth/SynthBorder.java | 1 - .../javax/swing/plaf/synth/SynthButtonUI.java | 9 ---- .../swing/plaf/synth/SynthColorChooserUI.java | 5 --- .../swing/plaf/synth/SynthComboBoxUI.java | 4 -- .../javax/swing/plaf/synth/SynthContext.java | 42 +++++-------------- .../swing/plaf/synth/SynthDefaultLookup.java | 1 - .../swing/plaf/synth/SynthDesktopIconUI.java | 4 -- .../swing/plaf/synth/SynthDesktopPaneUI.java | 4 -- .../swing/plaf/synth/SynthEditorPaneUI.java | 3 -- .../synth/SynthInternalFrameTitlePane.java | 6 --- .../plaf/synth/SynthInternalFrameUI.java | 4 -- .../javax/swing/plaf/synth/SynthLabelUI.java | 8 ---- .../javax/swing/plaf/synth/SynthListUI.java | 3 -- .../swing/plaf/synth/SynthLookAndFeel.java | 1 - .../swing/plaf/synth/SynthMenuBarUI.java | 4 -- .../swing/plaf/synth/SynthMenuItemUI.java | 9 ---- .../javax/swing/plaf/synth/SynthMenuUI.java | 9 ---- .../swing/plaf/synth/SynthOptionPaneUI.java | 6 --- .../javax/swing/plaf/synth/SynthPanelUI.java | 4 -- .../swing/plaf/synth/SynthPopupMenuUI.java | 4 -- .../swing/plaf/synth/SynthProgressBarUI.java | 5 --- .../swing/plaf/synth/SynthRootPaneUI.java | 4 -- .../swing/plaf/synth/SynthScrollBarUI.java | 11 ----- .../swing/plaf/synth/SynthScrollPaneUI.java | 5 --- .../swing/plaf/synth/SynthSeparatorUI.java | 5 --- .../javax/swing/plaf/synth/SynthSliderUI.java | 16 ------- .../swing/plaf/synth/SynthSpinnerUI.java | 4 -- .../plaf/synth/SynthSplitPaneDivider.java | 1 - .../swing/plaf/synth/SynthSplitPaneUI.java | 7 ---- .../swing/plaf/synth/SynthTabbedPaneUI.java | 16 ------- .../swing/plaf/synth/SynthTableHeaderUI.java | 4 -- .../javax/swing/plaf/synth/SynthTableUI.java | 4 -- .../swing/plaf/synth/SynthTextAreaUI.java | 3 -- .../swing/plaf/synth/SynthTextFieldUI.java | 3 -- .../swing/plaf/synth/SynthToolBarUI.java | 13 ------ .../swing/plaf/synth/SynthToolTipUI.java | 5 --- .../javax/swing/plaf/synth/SynthTreeUI.java | 11 ----- .../swing/plaf/synth/SynthViewportUI.java | 4 -- 39 files changed, 11 insertions(+), 242 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java index e4766bb12c4..71a136f0d63 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java @@ -139,7 +139,6 @@ class SynthArrowButton extends JButton implements SwingConstants, UIResource { } } - context.dispose(); return dim; } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java index 8dcbd6ff36c..57a868c7b3a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java @@ -61,7 +61,6 @@ class SynthBorder extends AbstractBorder implements UIResource { return; } ui.paintBorder(context, g, x, y, width, height); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java index a85cf146849..379bcd9a10a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java @@ -105,7 +105,6 @@ public class SynthButtonUI extends BasicButtonUI implements } } - context.dispose(); } /** @@ -125,7 +124,6 @@ public class SynthButtonUI extends BasicButtonUI implements SynthContext context = getContext(b, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -226,7 +224,6 @@ public class SynthButtonUI extends BasicButtonUI implements else { baseline = textRect.y + fm.getAscent(); } - context.dispose(); return baseline; } @@ -253,7 +250,6 @@ public class SynthButtonUI extends BasicButtonUI implements SynthLookAndFeel.update(context, g); paintBackground(context, g, c); paint(context, g); - context.dispose(); } /** @@ -270,7 +266,6 @@ public class SynthButtonUI extends BasicButtonUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -321,7 +316,6 @@ public class SynthButtonUI extends BasicButtonUI implements protected Icon getDefaultIcon(AbstractButton b) { SynthContext context = getContext(b); Icon icon = context.getStyle().getIcon(context, getPropertyPrefix() + "icon"); - context.dispose(); return icon; } @@ -473,7 +467,6 @@ public class SynthButtonUI extends BasicButtonUI implements b.getVerticalTextPosition(), b.getIconTextGap(), b.getDisplayedMnemonicIndex()); - ss.dispose(); return size; } @@ -494,7 +487,6 @@ public class SynthButtonUI extends BasicButtonUI implements b.getVerticalTextPosition(), b.getIconTextGap(), b.getDisplayedMnemonicIndex()); - ss.dispose(); return size; } @@ -516,7 +508,6 @@ public class SynthButtonUI extends BasicButtonUI implements b.getVerticalTextPosition(), b.getIconTextGap(), b.getDisplayedMnemonicIndex()); - ss.dispose(); return size; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java index 72ab2b09a16..4f67bd86d3e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java @@ -65,7 +65,6 @@ public class SynthColorChooserUI extends BasicColorChooserUI implements SynthContext context = getContext(chooser, ENABLED); AbstractColorChooserPanel[] panels = (AbstractColorChooserPanel[]) context.getStyle().get(context, "ColorChooser.panels"); - context.dispose(); if (panels == null) { panels = ColorChooserComponentFactory.getDefaultChooserPanels(); @@ -85,7 +84,6 @@ public class SynthColorChooserUI extends BasicColorChooserUI implements private void updateStyle(JComponent c) { SynthContext context = getContext(c, ENABLED); style = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -96,7 +94,6 @@ public class SynthColorChooserUI extends BasicColorChooserUI implements SynthContext context = getContext(chooser, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; super.uninstallDefaults(); } @@ -155,7 +152,6 @@ public class SynthColorChooserUI extends BasicColorChooserUI implements context.getPainter().paintColorChooserBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -172,7 +168,6 @@ public class SynthColorChooserUI extends BasicColorChooserUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java index 8734d55806d..42ddb3b230a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java @@ -144,7 +144,6 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements forceOpaque = style.getBoolean(context, "ComboBox.forceOpaque", false); } - context.dispose(); if(listBox != null) { SynthLookAndFeel.updateStyles(listBox); @@ -182,7 +181,6 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements SynthContext context = getContext(comboBox, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -323,7 +321,6 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements context.getPainter().paintComboBoxBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -340,7 +337,6 @@ public class SynthComboBoxUI extends BasicComboBoxUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java index 64b6e536f79..164dc0c265f 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java @@ -24,8 +24,6 @@ */ package javax.swing.plaf.synth; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; import javax.swing.JComponent; /** @@ -40,7 +38,6 @@ import javax.swing.JComponent; * @author Scott Violet */ public class SynthContext { - private static final Queue queue = new ConcurrentLinkedQueue<>(); private JComponent component; private Region region; @@ -54,19 +51,15 @@ public class SynthContext { static SynthContext getContext(JComponent component, Region region, SynthStyle style, int state) { - SynthContext context = queue.poll(); - if (context == null) { - context = new SynthContext(); - } - context.reset(component, region, style, state); + SynthContext context = new SynthContext(); + context.component = component; + context.region = region; + context.style = style; + context.state = state; return context; } - static void releaseContext(SynthContext context) { - queue.offer(context); - } - - SynthContext() { + private SynthContext() { } /** @@ -86,7 +79,11 @@ public class SynthContext { throw new NullPointerException( "You must supply a non-null component, region and style"); } - reset(component, region, style, state); + + this.component = component; + this.region = region; + this.style = style; + this.state = state; } @@ -146,23 +143,6 @@ public class SynthContext { return state; } - /** - * Resets the state of the Context. - */ - void reset(JComponent component, Region region, SynthStyle style, - int state) { - this.component = component; - this.region = region; - this.style = style; - this.state = state; - } - - void dispose() { - this.component = null; - this.style = null; - releaseContext(this); - } - /** * Convenience method to get the Painter from the current SynthStyle. * This will NEVER return null. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java index 0e5a6478aef..ba1927bb948 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java @@ -41,7 +41,6 @@ class SynthDefaultLookup extends DefaultLookup { } SynthContext context = ((SynthUI)ui).getContext(c); Object value = context.getStyle().get(context, key); - context.dispose(); return value; } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java index 8da1fe0cf3b..e5463beca23 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java @@ -121,7 +121,6 @@ public class SynthDesktopIconUI extends BasicDesktopIconUI private void updateStyle(JComponent c) { SynthContext context = getContext(c, ENABLED); style = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -131,7 +130,6 @@ public class SynthDesktopIconUI extends BasicDesktopIconUI protected void uninstallDefaults() { SynthContext context = getContext(desktopIcon, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -171,7 +169,6 @@ public class SynthDesktopIconUI extends BasicDesktopIconUI context.getPainter().paintDesktopIconBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -188,7 +185,6 @@ public class SynthDesktopIconUI extends BasicDesktopIconUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java index f7b370eb35b..9702fa980ff 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java @@ -119,7 +119,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements uninstallKeyboardActions(); installKeyboardActions(); } - context.dispose(); } /** @@ -143,7 +142,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements SynthContext context = getContext(desktop, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; if (taskBar != null) { @@ -460,7 +458,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements context.getPainter().paintDesktopPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -477,7 +474,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java index 69489197d6a..ffaeece02fb 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java @@ -83,7 +83,6 @@ public class SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI { c.putClientProperty("caretAspectRatio", null); style.uninstallDefaults(context); - context.dispose(); style = null; Object clientProperty = @@ -127,7 +126,6 @@ public class SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI { installKeyboardActions(); } } - context.dispose(); } /** @@ -165,7 +163,6 @@ public class SynthEditorPaneUI extends BasicEditorPaneUI implements SynthUI { SynthLookAndFeel.update(context, g); paintBackground(context, g, c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java index 92ad059085d..a7413a5577d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java @@ -138,7 +138,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane } } } - context.dispose(); } protected void installDefaults() { @@ -149,7 +148,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane protected void uninstallDefaults() { SynthContext context = getContext(this, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; JInternalFrame.JDesktopIcon di = frame.getDesktopIcon(); if(di != null && di.getComponentPopupMenu() == systemPopupMenu) { @@ -235,7 +233,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane context.getPainter().paintInternalFrameTitlePaneBackground(context, g, 0, 0, getWidth(), getHeight()); paint(context, g); - context.dispose(); } protected void paint(SynthContext context, Graphics g) { @@ -321,7 +318,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane SynthContext context = getContext(this); LayoutManager lm = (LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout"); - context.dispose(); return (lm != null) ? lm : new SynthTitlePaneLayout(); } @@ -362,7 +358,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane Image.SCALE_SMOOTH)); } } - context.dispose(); menuButton.setIcon(frameIcon); } @@ -433,7 +428,6 @@ class SynthInternalFrameTitlePane extends BasicInternalFrameTitlePane Insets insets = getInsets(); height += insets.top + insets.bottom; width += insets.left + insets.right; - context.dispose(); return new Dimension(width, height); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java index 8ed25333234..a11e7549d5d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java @@ -118,7 +118,6 @@ public class SynthInternalFrameUI extends BasicInternalFrameUI installKeyboardActions(); } } - context.dispose(); } /** @@ -128,7 +127,6 @@ public class SynthInternalFrameUI extends BasicInternalFrameUI protected void uninstallDefaults() { SynthContext context = getContext(frame, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; if(frame.getLayout() == internalFrameLayout) { frame.setLayout(null); @@ -216,7 +214,6 @@ public class SynthInternalFrameUI extends BasicInternalFrameUI context.getPainter().paintInternalFrameBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -233,7 +230,6 @@ public class SynthInternalFrameUI extends BasicInternalFrameUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java index 22e57e5e4a8..4d5b900a931 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java @@ -67,7 +67,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { void updateStyle(JLabel c) { SynthContext context = getContext(c, ENABLED); style = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -78,7 +77,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { SynthContext context = getContext(c, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -150,7 +148,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { else { baseline = textRect.y + fm.getAscent(); } - context.dispose(); return baseline; } @@ -174,7 +171,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { context.getPainter().paintLabelBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -191,7 +187,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -242,7 +237,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { label.getVerticalTextPosition(), label.getIconTextGap(), label.getDisplayedMnemonicIndex()); - context.dispose(); return size; } @@ -263,7 +257,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { label.getVerticalTextPosition(), label.getIconTextGap(), label.getDisplayedMnemonicIndex()); - context.dispose(); return size; } @@ -284,7 +277,6 @@ public class SynthLabelUI extends BasicLabelUI implements SynthUI { label.getVerticalTextPosition(), label.getIconTextGap(), label.getDisplayedMnemonicIndex()); - context.dispose(); return size; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java index 121ddb5cb81..b7e96f611e9 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java @@ -75,7 +75,6 @@ public class SynthListUI extends BasicListUI SynthLookAndFeel.update(context, g); context.getPainter().paintListBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); - context.dispose(); paint(g, c); } @@ -162,7 +161,6 @@ public class SynthListUI extends BasicListUI installKeyboardActions(); } } - context.dispose(); } /** @@ -175,7 +173,6 @@ public class SynthListUI extends BasicListUI SynthContext context = getContext(list, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java index 3998b354ccb..74b0cd2e006 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java @@ -976,7 +976,6 @@ public class SynthLookAndFeel extends BasicLookAndFeel { if (currBG != null && !currBG.equals(lastBG)) { comp.repaint(); } - context.dispose(); } } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java index 1f096646495..77c7a819074 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java @@ -83,7 +83,6 @@ public class SynthMenuBarUI extends BasicMenuBarUI installKeyboardActions(); } } - context.dispose(); } /** @@ -94,7 +93,6 @@ public class SynthMenuBarUI extends BasicMenuBarUI SynthContext context = getContext(menuBar, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -143,7 +141,6 @@ public class SynthMenuBarUI extends BasicMenuBarUI context.getPainter().paintMenuBarBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -160,7 +157,6 @@ public class SynthMenuBarUI extends BasicMenuBarUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java index 956f76f1fb3..9e07c376675 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java @@ -124,13 +124,11 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements installKeyboardActions(); } } - context.dispose(); SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR, ENABLED); accStyle = SynthLookAndFeel.updateStyle(accContext, this); - accContext.dispose(); } /** @@ -140,13 +138,11 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements protected void uninstallDefaults() { SynthContext context = getContext(menuItem, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; SynthContext accContext = getContext(menuItem, Region.MENU_ITEM_ACCELERATOR, ENABLED); accStyle.uninstallDefaults(accContext); - accContext.dispose(); accStyle = null; super.uninstallDefaults(); @@ -218,8 +214,6 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements defaultTextIconGap, acceleratorDelimiter, MenuItemLayoutHelper.useCheckAndArrow(menuItem), getPropertyPrefix()); - context.dispose(); - accContext.dispose(); return value; } @@ -243,7 +237,6 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements SynthLookAndFeel.update(context, g); paintBackground(context, g, c); paint(context, g); - context.dispose(); } /** @@ -260,7 +253,6 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -280,7 +272,6 @@ public class SynthMenuItemUI extends BasicMenuItemUI implements Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon"); SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon, acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix()); - accContext.dispose(); } void paintBackground(SynthContext context, Graphics g, JComponent c) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java index 7bb66a25c93..be1bd34cab1 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java @@ -110,13 +110,11 @@ public class SynthMenuUI extends BasicMenuUI installKeyboardActions(); } } - context.dispose(); SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR, ENABLED); accStyle = SynthLookAndFeel.updateStyle(accContext, this); - accContext.dispose(); } /** @@ -140,13 +138,11 @@ public class SynthMenuUI extends BasicMenuUI protected void uninstallDefaults() { SynthContext context = getContext(menuItem, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; SynthContext accContext = getContext(menuItem, Region.MENU_ITEM_ACCELERATOR, ENABLED); accStyle.uninstallDefaults(accContext); - accContext.dispose(); accStyle = null; super.uninstallDefaults(); @@ -218,8 +214,6 @@ public class SynthMenuUI extends BasicMenuUI defaultTextIconGap, acceleratorDelimiter, MenuItemLayoutHelper.useCheckAndArrow(menuItem), getPropertyPrefix()); - context.dispose(); - accContext.dispose(); return value; } @@ -243,7 +237,6 @@ public class SynthMenuUI extends BasicMenuUI context.getPainter().paintMenuBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -260,7 +253,6 @@ public class SynthMenuUI extends BasicMenuUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -279,7 +271,6 @@ public class SynthMenuUI extends BasicMenuUI Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon"); SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon, acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix()); - accContext.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java index de6f2a7135e..b09ed3a7709 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java @@ -88,7 +88,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements installKeyboardActions(); } } - context.dispose(); } /** @@ -99,7 +98,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements SynthContext context = getContext(optionPane, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -125,7 +123,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements SynthContext context = getContext(optionPane, ENABLED); optionPane.add(Box.createVerticalStrut(context.getStyle(). getInt(context, "OptionPane.separatorPadding", 6))); - context.dispose(); } optionPane.add(createButtonArea()); optionPane.applyComponentOrientation(optionPane.getComponentOrientation()); @@ -167,7 +164,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements context.getPainter().paintOptionPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -184,7 +180,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -259,7 +254,6 @@ public class SynthOptionPaneUI extends BasicOptionPaneUI implements SynthContext context = getContext(optionPane, ENABLED); cons.anchor = context.getStyle().getInt(context, "OptionPane.messageAnchor", GridBagConstraints.CENTER); - context.dispose(); cons.insets = new Insets(0,0,3,0); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java index 73f37ff530b..a9b91b79099 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java @@ -108,14 +108,12 @@ public class SynthPanelUI extends BasicPanelUI SynthContext context = getContext(p, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } private void updateStyle(JPanel c) { SynthContext context = getContext(c, ENABLED); style = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -154,7 +152,6 @@ public class SynthPanelUI extends BasicPanelUI context.getPainter().paintPanelBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -171,7 +168,6 @@ public class SynthPanelUI extends BasicPanelUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java index cbb09f29212..d3f1e25f7ae 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java @@ -77,7 +77,6 @@ public class SynthPopupMenuUI extends BasicPopupMenuUI installKeyboardActions(); } } - context.dispose(); } /** @@ -97,7 +96,6 @@ public class SynthPopupMenuUI extends BasicPopupMenuUI SynthContext context = getContext(popupMenu, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; if (popupMenu.getLayout() instanceof UIResource) { @@ -150,7 +148,6 @@ public class SynthPopupMenuUI extends BasicPopupMenuUI context.getPainter().paintPopupMenuBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -167,7 +164,6 @@ public class SynthPopupMenuUI extends BasicPopupMenuUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java index f38fea87fb6..743366f4112 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java @@ -118,7 +118,6 @@ public class SynthProgressBarUI extends BasicProgressBarUI } minBarSize = (Dimension)style.get(context, "ProgressBar.minBarSize"); glowWidth = style.getInt(context, "ProgressBar.glowWidth", 0); - context.dispose(); } /** @@ -129,7 +128,6 @@ public class SynthProgressBarUI extends BasicProgressBarUI SynthContext context = getContext(progressBar, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -160,7 +158,6 @@ public class SynthProgressBarUI extends BasicProgressBarUI SynthContext context = getContext(c); Font font = context.getStyle().getFont(context); FontMetrics metrics = progressBar.getFontMetrics(font); - context.dispose(); return (height - metrics.getAscent() - metrics.getDescent()) / 2 + metrics.getAscent(); } @@ -216,7 +213,6 @@ public class SynthProgressBarUI extends BasicProgressBarUI g, 0, 0, c.getWidth(), c.getHeight(), progressBar.getOrientation()); paint(context, g); - context.dispose(); } /** @@ -233,7 +229,6 @@ public class SynthProgressBarUI extends BasicProgressBarUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java index 1115fe35551..13244226ba3 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java @@ -67,7 +67,6 @@ public class SynthRootPaneUI extends BasicRootPaneUI implements SynthUI { SynthContext context = getContext(root, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -97,7 +96,6 @@ public class SynthRootPaneUI extends BasicRootPaneUI implements SynthUI { installKeyboardActions((JRootPane)c); } } - context.dispose(); } /** @@ -120,7 +118,6 @@ public class SynthRootPaneUI extends BasicRootPaneUI implements SynthUI { context.getPainter().paintRootPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -137,7 +134,6 @@ public class SynthRootPaneUI extends BasicRootPaneUI implements SynthUI { SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java index bf86f377412..b93196a9eab 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java @@ -129,15 +129,12 @@ public class SynthScrollBarUI extends BasicScrollBarUI installKeyboardActions(); } } - context.dispose(); context = getContext(c, Region.SCROLL_BAR_TRACK, ENABLED); trackStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); context = getContext(c, Region.SCROLL_BAR_THUMB, ENABLED); thumbStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -165,17 +162,14 @@ public class SynthScrollBarUI extends BasicScrollBarUI protected void uninstallDefaults(){ SynthContext context = getContext(scrollbar, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; context = getContext(scrollbar, Region.SCROLL_BAR_TRACK, ENABLED); trackStyle.uninstallDefaults(context); - context.dispose(); trackStyle = null; context = getContext(scrollbar, Region.SCROLL_BAR_THUMB, ENABLED); thumbStyle.uninstallDefaults(context); - context.dispose(); thumbStyle = null; super.uninstallDefaults(); @@ -222,7 +216,6 @@ public class SynthScrollBarUI extends BasicScrollBarUI SynthContext context = getContext(scrollbar); boolean value = style.getBoolean(context, "ScrollBar.allowsAbsolutePositioning", false); - context.dispose(); return value; } @@ -247,7 +240,6 @@ public class SynthScrollBarUI extends BasicScrollBarUI g, 0, 0, c.getWidth(), c.getHeight(), scrollbar.getOrientation()); paint(context, g); - context.dispose(); } /** @@ -264,7 +256,6 @@ public class SynthScrollBarUI extends BasicScrollBarUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -278,11 +269,9 @@ public class SynthScrollBarUI extends BasicScrollBarUI SynthContext subcontext = getContext(scrollbar, Region.SCROLL_BAR_TRACK); paintTrack(subcontext, g, getTrackBounds()); - subcontext.dispose(); subcontext = getContext(scrollbar, Region.SCROLL_BAR_THUMB); paintThumb(subcontext, g, getThumbBounds()); - subcontext.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java index 6b3e29602de..8e4601eb85e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java @@ -83,7 +83,6 @@ public class SynthScrollPaneUI extends BasicScrollPaneUI context.getPainter().paintScrollPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -100,7 +99,6 @@ public class SynthScrollPaneUI extends BasicScrollPaneUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -150,7 +148,6 @@ public class SynthScrollPaneUI extends BasicScrollPaneUI installKeyboardActions(c); } } - context.dispose(); } /** @@ -178,7 +175,6 @@ public class SynthScrollPaneUI extends BasicScrollPaneUI SynthContext context = getContext(c, ENABLED); style.uninstallDefaults(context); - context.dispose(); if (scrollpane.getViewportBorder() instanceof UIResource) { scrollpane.setViewportBorder(null); @@ -254,7 +250,6 @@ public class SynthScrollPaneUI extends BasicScrollPaneUI } context.getPainter().paintViewportBorder(context, g, x, y, width, height); - context.dispose(); } @Override diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java index a222a428080..b9de6433b47 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java @@ -106,7 +106,6 @@ public class SynthSeparatorUI extends SeparatorUI } } - context.dispose(); } /** @@ -120,7 +119,6 @@ public class SynthSeparatorUI extends SeparatorUI SynthContext context = getContext(c, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -168,7 +166,6 @@ public class SynthSeparatorUI extends SeparatorUI g, 0, 0, c.getWidth(), c.getHeight(), separator.getOrientation()); paint(context, g); - context.dispose(); } /** @@ -185,7 +182,6 @@ public class SynthSeparatorUI extends SeparatorUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -231,7 +227,6 @@ public class SynthSeparatorUI extends SeparatorUI size = new Dimension(insets.left + insets.right, insets.top + insets.bottom + thickness); } - context.dispose(); return size; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index 9c222e1a925..9118fb7569f 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -116,17 +116,14 @@ public class SynthSliderUI extends BasicSliderUI protected void uninstallDefaults(JSlider slider) { SynthContext context = getContext(slider, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; context = getContext(slider, Region.SLIDER_TRACK, ENABLED); sliderTrackStyle.uninstallDefaults(context); - context.dispose(); sliderTrackStyle = null; context = getContext(slider, Region.SLIDER_THUMB, ENABLED); sliderThumbStyle.uninstallDefaults(context); - context.dispose(); sliderThumbStyle = null; } @@ -190,17 +187,14 @@ public class SynthSliderUI extends BasicSliderUI installKeyboardActions(c); } } - context.dispose(); context = getContext(c, Region.SLIDER_TRACK, ENABLED); sliderTrackStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); context = getContext(c, Region.SLIDER_THUMB, ENABLED); sliderThumbStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -252,14 +246,12 @@ public class SynthSliderUI extends BasicSliderUI SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK); style.getInsets(trackContext, trackInsets); - trackContext.dispose(); if (slider.getOrientation() == JSlider.HORIZONTAL) { int valueHeight = 0; if (paintValue) { SynthContext context = getContext(slider); valueHeight = context.getStyle().getGraphicsUtils(context). getMaximumCharHeight(context); - context.dispose(); } int tickHeight = 0; if (slider.getPaintTicks()) { @@ -287,7 +279,6 @@ public class SynthSliderUI extends BasicSliderUI SynthContext context = getContext(slider); valueHeight = context.getStyle().getGraphicsUtils( context).getMaximumCharHeight(context); - context.dispose(); } int contentHeight = height - insetCache.top - insetCache.bottom; @@ -359,7 +350,6 @@ public class SynthSliderUI extends BasicSliderUI Insets trackInsets = new Insets(0, 0, 0, 0); SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK); style.getInsets(trackContext, trackInsets); - trackContext.dispose(); if (slider.getOrientation() == JSlider.HORIZONTAL) { // Calculate the height of all the subcomponents so we can center @@ -509,7 +499,6 @@ public class SynthSliderUI extends BasicSliderUI trackRect.x = startX + tickRect.width + trackInsets.left; } } - context.dispose(); lastSize = slider.getSize(); } @@ -715,7 +704,6 @@ public class SynthSliderUI extends BasicSliderUI insetCache = newInsets; calculateGeometry(); } - context.dispose(); } /** @@ -774,7 +762,6 @@ public class SynthSliderUI extends BasicSliderUI g, 0, 0, c.getWidth(), c.getHeight(), slider.getOrientation()); paint(context, g); - context.dispose(); } /** @@ -790,7 +777,6 @@ public class SynthSliderUI extends BasicSliderUI public void paint(Graphics g, JComponent c) { SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -835,13 +821,11 @@ public class SynthSliderUI extends BasicSliderUI if (slider.getPaintTrack() && clip.intersects(trackRect)) { SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK); paintTrack(subcontext, g, trackRect); - subcontext.dispose(); } if (clip.intersects(thumbRect)) { SynthContext subcontext = getContext(slider, Region.SLIDER_THUMB); paintThumb(subcontext, g, thumbRect); - subcontext.dispose(); } if (slider.getPaintTicks() && clip.intersects(tickRect)) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java index a1293dfdadd..2c430e03e82 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java @@ -131,7 +131,6 @@ public class SynthSpinnerUI extends BasicSpinnerUI installKeyboardActions(); } } - context.dispose(); } @@ -151,7 +150,6 @@ public class SynthSpinnerUI extends BasicSpinnerUI SynthContext context = getContext(spinner, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -301,7 +299,6 @@ public class SynthSpinnerUI extends BasicSpinnerUI context.getPainter().paintSpinnerBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } @@ -319,7 +316,6 @@ public class SynthSpinnerUI extends BasicSpinnerUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java index c3a203e5237..ab0c0954318 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java @@ -81,7 +81,6 @@ class SynthSplitPaneDivider extends BasicSplitPaneDivider { context.getPainter().paintSplitPaneDividerForeground(context, g, 0, 0, getWidth(), getHeight(), splitPane.getOrientation()); - context.dispose(); // super.paint(g2); for (int counter = 0; counter < getComponentCount(); counter++) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java index 667d6ded258..6c4a1d42901 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java @@ -121,7 +121,6 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI ENABLED); SynthStyle oldDividerStyle = dividerStyle; dividerStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); context = getContext(splitPane, ENABLED); SynthStyle oldStyle = style; @@ -160,7 +159,6 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI divider.setBasicSplitPaneUI(this); splitPane.add(divider, JSplitPane.DIVIDER); } - context.dispose(); } /** @@ -180,12 +178,10 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI SynthContext context = getContext(splitPane, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED); dividerStyle.uninstallDefaults(context); - context.dispose(); dividerStyle = null; super.uninstallDefaults(); @@ -287,7 +283,6 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI context.getPainter().paintSplitPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -304,7 +299,6 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -338,7 +332,6 @@ public class SynthSplitPaneUI extends BasicSplitPaneUI context.getPainter().paintSplitPaneDragDivider(context, g, x, y, w, h, splitPane.getOrientation()); g.setClip(oldClip); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java index 211e8a2c331..8e59afe9342 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java @@ -154,27 +154,17 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI installKeyboardActions(); } } - context.dispose(); - if (tabContext != null) { - tabContext.dispose(); - } tabContext = getContext(c, Region.TABBED_PANE_TAB, ENABLED); this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this); tabInsets = tabStyle.getInsets(tabContext, null); - if (tabAreaContext != null) { - tabAreaContext.dispose(); - } tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED); this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this); tabAreaInsets = tabAreaStyle.getInsets(tabAreaContext, null); - if (tabContentContext != null) { - tabContentContext.dispose(); - } tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED); this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext, this); @@ -207,21 +197,17 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI protected void uninstallDefaults() { SynthContext context = getContext(tabPane, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; tabStyle.uninstallDefaults(tabContext); - tabContext.dispose(); tabContext = null; tabStyle = null; tabAreaStyle.uninstallDefaults(tabAreaContext); - tabAreaContext.dispose(); tabAreaContext = null; tabAreaStyle = null; tabContentStyle.uninstallDefaults(tabContentContext); - tabContentContext.dispose(); tabContentContext = null; tabContentStyle = null; } @@ -374,7 +360,6 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI context.getPainter().paintTabbedPaneBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -424,7 +409,6 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java index 16272ffa819..39acd0e90ea 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java @@ -85,7 +85,6 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI installKeyboardActions(); } } - context.dispose(); } /** @@ -109,7 +108,6 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI SynthContext context = getContext(header, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -142,7 +140,6 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI context.getPainter().paintTableHeaderBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -159,7 +156,6 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java index 1e5f522416f..08ac1382015 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java @@ -189,7 +189,6 @@ public class SynthTableUI extends BasicTableUI installKeyboardActions(); } } - context.dispose(); } /** @@ -220,7 +219,6 @@ public class SynthTableUI extends BasicTableUI } SynthContext context = getContext(table, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -273,7 +271,6 @@ public class SynthTableUI extends BasicTableUI context.getPainter().paintTableBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -299,7 +296,6 @@ public class SynthTableUI extends BasicTableUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java index 33214dad926..affbb6f4ecd 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java @@ -88,7 +88,6 @@ public class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { getComponent().removeFocusListener(handler); style.uninstallDefaults(context); - context.dispose(); style = null; super.uninstallDefaults(); } @@ -107,7 +106,6 @@ public class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { installKeyboardActions(); } } - context.dispose(); } /** @@ -142,7 +140,6 @@ public class SynthTextAreaUI extends BasicTextAreaUI implements SynthUI { context.getPainter().paintTextAreaBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java index 6adb7538e88..cf0e83637ef 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java @@ -79,7 +79,6 @@ public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI { installKeyboardActions(); } } - context.dispose(); } static void updateStyle(JTextComponent comp, SynthContext context, @@ -179,7 +178,6 @@ public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI { SynthLookAndFeel.update(context, g); paintBackground(context, g, c); paint(context, g); - context.dispose(); } /** @@ -262,7 +260,6 @@ public class SynthTextFieldUI extends BasicTextFieldUI implements SynthUI { getComponent().removeFocusListener(handler); style.uninstallDefaults(context); - context.dispose(); style = null; super.uninstallDefaults(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java index a36117cda20..518c25da5a9 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java @@ -98,11 +98,9 @@ public class SynthToolBarUI extends BasicToolBarUI SynthContext context = getContext( c, Region.TOOL_BAR_CONTENT, null, ENABLED); contentStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, null, ENABLED); dragWindowStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); context = getContext(c, ENABLED); SynthStyle oldStyle = style; @@ -116,7 +114,6 @@ public class SynthToolBarUI extends BasicToolBarUI installKeyboardActions(); } } - context.dispose(); } /** @@ -127,7 +124,6 @@ public class SynthToolBarUI extends BasicToolBarUI SynthContext context = getContext(toolBar, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; handleIcon = null; @@ -135,13 +131,11 @@ public class SynthToolBarUI extends BasicToolBarUI context = getContext(toolBar, Region.TOOL_BAR_CONTENT, contentStyle, ENABLED); contentStyle.uninstallDefaults(context); - context.dispose(); contentStyle = null; context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW, dragWindowStyle, ENABLED); dragWindowStyle.uninstallDefaults(context); - context.dispose(); dragWindowStyle = null; toolBar.setLayout(null); @@ -215,7 +209,6 @@ public class SynthToolBarUI extends BasicToolBarUI g, 0, 0, c.getWidth(), c.getHeight(), toolBar.getOrientation()); paint(context, g); - context.dispose(); } /** @@ -232,7 +225,6 @@ public class SynthToolBarUI extends BasicToolBarUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -289,7 +281,6 @@ public class SynthToolBarUI extends BasicToolBarUI SynthContext subcontext = getContext( toolBar, Region.TOOL_BAR_CONTENT, contentStyle); paintContent(subcontext, g, contentRect); - subcontext.dispose(); } /** @@ -326,7 +317,6 @@ public class SynthToolBarUI extends BasicToolBarUI dragWindow.getOrientation()); context.getPainter().paintToolBarDragWindowBorder(context, g, 0, 0, w, h, dragWindow.getOrientation()); - context.dispose(); } // @@ -383,7 +373,6 @@ public class SynthToolBarUI extends BasicToolBarUI dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; - context.dispose(); return dim; } @@ -421,7 +410,6 @@ public class SynthToolBarUI extends BasicToolBarUI dim.width += insets.left + insets.right; dim.height += insets.top + insets.bottom; - context.dispose(); return dim; } @@ -543,7 +531,6 @@ public class SynthToolBarUI extends BasicToolBarUI } } } - context.dispose(); } private boolean isGlue(Component c) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java index dc42debba7d..b73d57ab3dd 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java @@ -68,7 +68,6 @@ public class SynthToolTipUI extends BasicToolTipUI private void updateStyle(JComponent c) { SynthContext context = getContext(c, ENABLED); style = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -78,7 +77,6 @@ public class SynthToolTipUI extends BasicToolTipUI protected void uninstallDefaults(JComponent c) { SynthContext context = getContext(c, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -139,7 +137,6 @@ public class SynthToolTipUI extends BasicToolTipUI context.getPainter().paintToolTipBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -165,7 +162,6 @@ public class SynthToolTipUI extends BasicToolTipUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -218,7 +214,6 @@ public class SynthToolTipUI extends BasicToolTipUI prefSize.height += fm.getHeight(); } } - context.dispose(); return prefSize; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java index 603540c6a58..08194e7e3cf 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java @@ -147,11 +147,9 @@ public class SynthTreeUI extends BasicTreeUI installKeyboardActions(); } } - context.dispose(); context = getContext(tree, Region.TREE_CELL, ENABLED); cellStyle = SynthLookAndFeel.updateStyle(context, this); - context.dispose(); } /** @@ -223,12 +221,10 @@ public class SynthTreeUI extends BasicTreeUI SynthContext context = getContext(tree, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; context = getContext(tree, Region.TREE_CELL, ENABLED); cellStyle.uninstallDefaults(context); - context.dispose(); cellStyle = null; @@ -266,7 +262,6 @@ public class SynthTreeUI extends BasicTreeUI context.getPainter().paintTreeBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -292,7 +287,6 @@ public class SynthTreeUI extends BasicTreeUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** @@ -425,7 +419,6 @@ public class SynthTreeUI extends BasicTreeUI row++; } } - cellContext.dispose(); paintDropLine(g); @@ -743,7 +736,6 @@ public class SynthTreeUI extends BasicTreeUI context.getPainter().paintTreeCellFocus(context, g, 0, 0, getWidth() - imageOffset, getHeight()); } - context.dispose(); } SynthLookAndFeel.resetSelectedUI(); } @@ -785,7 +777,6 @@ public class SynthTreeUI extends BasicTreeUI if (context == null) { context = getContext(tree); SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h); - context.dispose(); } else { SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h); @@ -797,7 +788,6 @@ public class SynthTreeUI extends BasicTreeUI if (context == null) { context = getContext(tree); width = SynthGraphicsUtils.getIconWidth(expandedIcon, context); - context.dispose(); } else { width = SynthGraphicsUtils.getIconWidth(expandedIcon, context); @@ -810,7 +800,6 @@ public class SynthTreeUI extends BasicTreeUI if (context == null) { context = getContext(tree); height = SynthGraphicsUtils.getIconHeight(expandedIcon, context); - context.dispose(); } else { height = SynthGraphicsUtils.getIconHeight(expandedIcon, context); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java index dc3e6c6e1a1..94483f983d8 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java @@ -99,7 +99,6 @@ public class SynthViewportUI extends ViewportUI newStyle.installDefaults(context); } this.style = newStyle; - context.dispose(); } /** @@ -128,7 +127,6 @@ public class SynthViewportUI extends ViewportUI protected void uninstallDefaults(JComponent c) { SynthContext context = getContext(c, ENABLED); style.uninstallDefaults(context); - context.dispose(); style = null; } @@ -168,7 +166,6 @@ public class SynthViewportUI extends ViewportUI context.getPainter().paintViewportBackground(context, g, 0, 0, c.getWidth(), c.getHeight()); paint(context, g); - context.dispose(); } /** @@ -202,7 +199,6 @@ public class SynthViewportUI extends ViewportUI SynthContext context = getContext(c); paint(context, g); - context.dispose(); } /** From cfa3376da92f7cc8db7e5b1bf705a53a2eaa4743 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 15 Apr 2016 10:25:11 -0700 Subject: [PATCH 099/225] 8154269: Remove unused or unnecessary Xm/Xt files and header includes Reviewed-by: serb, ssadetsky --- .../java.desktop/unix/native/common/awt/awt.h | 4 +- .../unix/native/common/awt/awt_p.h | 7 - .../unix/native/common/awt/extutil.h | 251 ------------- .../native/common/java2d/x11/X11SurfaceData.c | 3 +- .../native/common/java2d/x11/X11SurfaceData.h | 1 - .../unix/native/include/jawt_md.h | 1 - .../native/libawt_headless/awt/VDrawingArea.c | 344 ------------------ .../native/libawt_headless/awt/VDrawingArea.h | 36 -- .../libawt_headless/awt/VDrawingAreaP.h | 79 ---- .../native/libawt_xawt/awt/awt_InputMethod.c | 3 +- .../unix/native/libawt_xawt/awt/awt_Robot.c | 1 - .../unix/native/libawt_xawt/awt/awt_util.c | 1 - .../unix/native/libawt_xawt/xawt/XToolkit.c | 3 +- 13 files changed, 6 insertions(+), 728 deletions(-) delete mode 100644 jdk/src/java.desktop/unix/native/common/awt/extutil.h delete mode 100644 jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c delete mode 100644 jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h delete mode 100644 jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h diff --git a/jdk/src/java.desktop/unix/native/common/awt/awt.h b/jdk/src/java.desktop/unix/native/common/awt/awt.h index 0dacab98a40..18a6dee275b 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/awt.h +++ b/jdk/src/java.desktop/unix/native/common/awt/awt.h @@ -35,7 +35,9 @@ #include "debug_util.h" #if !defined(HEADLESS) && !defined(MACOSX) -#include +#include +#include +typedef char Boolean; #endif /* !HEADLESS && !MACOSX */ diff --git a/jdk/src/java.desktop/unix/native/common/awt/awt_p.h b/jdk/src/java.desktop/unix/native/common/awt/awt_p.h index d2d1d74922a..934838c44b1 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/awt_p.h +++ b/jdk/src/java.desktop/unix/native/common/awt/awt_p.h @@ -41,13 +41,6 @@ #include #include #ifndef HEADLESS -#include -#include -#include -#include -#include -#include -#include #include #endif /* !HEADLESS */ #include "awt.h" diff --git a/jdk/src/java.desktop/unix/native/common/awt/extutil.h b/jdk/src/java.desktop/unix/native/common/awt/extutil.h deleted file mode 100644 index ba9f75a7642..00000000000 --- a/jdk/src/java.desktop/unix/native/common/awt/extutil.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * 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 file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file: - * - * $Xorg: extutil.h,v 1.3 2000/08/18 04:05:45 coskrey Exp $ - * -Copyright 1989, 1998 The Open Group - -All Rights Reserved. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - * - * Author: Jim Fulton, MIT The Open Group - * - * Xlib Extension-Writing Utilities - * - * This package contains utilities for writing the client API for various - * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND - * ARE SUBJECT TO CHANGE! - */ -/* $XFree86: xc/include/extensions/extutil.h,v 1.5 2001/01/17 17:53:20 dawes Exp $ */ - -#if defined(__linux__) || defined(MACOSX) - -#ifndef _EXTUTIL_H_ -#define _EXTUTIL_H_ - -/* - * We need to keep a list of open displays since the Xlib display list isn't - * public. We also have to per-display info in a separate block since it isn't - * stored directly in the Display structure. - */ -typedef struct _XExtDisplayInfo { - struct _XExtDisplayInfo *next; /* keep a linked list */ - Display *display; /* which display this is */ - XExtCodes *codes; /* the extension protocol codes */ - XPointer data; /* extra data for extension to use */ -} XExtDisplayInfo; - -typedef struct _XExtensionInfo { - XExtDisplayInfo *head; /* start of list */ - XExtDisplayInfo *cur; /* most recently used */ - int ndisplays; /* number of displays */ -} XExtensionInfo; - -typedef struct _XExtensionHooks { - int (*create_gc)( -#if NeedNestedPrototypes - Display* /* display */, - GC /* gc */, - XExtCodes* /* codes */ -#endif -); - int (*copy_gc)( -#if NeedNestedPrototypes - Display* /* display */, - GC /* gc */, - XExtCodes* /* codes */ -#endif -); - int (*flush_gc)( -#if NeedNestedPrototypes - Display* /* display */, - GC /* gc */, - XExtCodes* /* codes */ -#endif -); - int (*free_gc)( -#if NeedNestedPrototypes - Display* /* display */, - GC /* gc */, - XExtCodes* /* codes */ -#endif -); - int (*create_font)( -#if NeedNestedPrototypes - Display* /* display */, - XFontStruct* /* fs */, - XExtCodes* /* codes */ -#endif -); - int (*free_font)( -#if NeedNestedPrototypes - Display* /* display */, - XFontStruct* /* fs */, - XExtCodes* /* codes */ -#endif -); - int (*close_display)( -#if NeedNestedPrototypes - Display* /* display */, - XExtCodes* /* codes */ -#endif -); - Bool (*wire_to_event)( -#if NeedNestedPrototypes - Display* /* display */, - XEvent* /* re */, - xEvent* /* event */ -#endif -); - Status (*event_to_wire)( -#if NeedNestedPrototypes - Display* /* display */, - XEvent* /* re */, - xEvent* /* event */ -#endif -); - int (*error)( -#if NeedNestedPrototypes - Display* /* display */, - xError* /* err */, - XExtCodes* /* codes */, - int* /* ret_code */ -#endif -); - char *(*error_string)( -#if NeedNestedPrototypes - Display* /* display */, - int /* code */, - XExtCodes* /* codes */, - char* /* buffer */, - int /* nbytes */ -#endif -); -} XExtensionHooks; - -extern XExtensionInfo *XextCreateExtension( -#if NeedFunctionPrototypes - void -#endif -); -extern void XextDestroyExtension( -#if NeedFunctionPrototypes - XExtensionInfo* /* info */ -#endif -); -extern XExtDisplayInfo *XextAddDisplay( -#if NeedFunctionPrototypes - XExtensionInfo* /* extinfo */, - Display* /* dpy */, - char* /* ext_name */, - XExtensionHooks* /* hooks */, - int /* nevents */, - XPointer /* data */ -#endif -); -extern int XextRemoveDisplay( -#if NeedFunctionPrototypes - XExtensionInfo* /* extinfo */, - Display* /* dpy */ -#endif -); -extern XExtDisplayInfo *XextFindDisplay( -#if NeedFunctionPrototypes - XExtensionInfo* /* extinfo */, - Display* /* dpy */ -#endif -); - -#define XextHasExtension(i) ((i) && ((i)->codes)) -#define XextCheckExtension(dpy,i,name,val) \ - if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; } -#define XextSimpleCheckExtension(dpy,i,name) \ - if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; } - - -/* - * helper macros to generate code that is common to all extensions; caller - * should prefix it with static if extension source is in one file; this - * could be a utility function, but have to stack 6 unused arguments for - * something that is called many, many times would be bad. - */ -#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \ -XExtDisplayInfo *proc (Display *dpy) \ -{ \ - XExtDisplayInfo *dpyinfo; \ - if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \ - if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \ - dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \ - return dpyinfo; \ -} - -#define XEXT_FIND_DISPLAY_PROTO(proc) \ - XExtDisplayInfo *proc(Display *dpy) - -#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \ -int proc (Display *dpy, XExtCodes *codes) \ -{ \ - return XextRemoveDisplay (extinfo, dpy); \ -} - -#define XEXT_CLOSE_DISPLAY_PROTO(proc) \ - int proc(Display *dpy, XExtCodes *codes) - -#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \ -char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \ -{ \ - code -= codes->first_error; \ - if (code >= 0 && code < nerr) { \ - char tmp[256]; \ - sprintf (tmp, "%s.%d", extname, code); \ - XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \ - return buf; \ - } \ - return (char *)0; \ -} - -#define XEXT_ERROR_STRING_PROTO(proc) \ - char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n) -#endif - -#endif /* __linux__ || MACOSX */ diff --git a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c index e6597a4723c..07c13f7b7e1 100644 --- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c +++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c @@ -270,7 +270,6 @@ Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd, xsdo->sdOps.Dispose = X11SD_Dispose; xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg; xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg; - xsdo->widget = NULL; if (peer != NULL) { xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j; if (hasException) { @@ -1087,7 +1086,7 @@ static int X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds, X11SDOps *xsdo) { - Position x1=0, y1=0, x2=0, y2=0; + short x1=0, y1=0, x2=0, y2=0; int tmpx, tmpy; Window tmpchild; diff --git a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h index 91ad4626a4c..9de747a70e0 100644 --- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h +++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h @@ -101,7 +101,6 @@ struct _X11SDOps { jboolean isPixmap; jobject peer; Drawable drawable; - Widget widget; GC javaGC; /* used for Java-level GC validation */ GC cachedGC; /* cached for use in X11SD_Unlock() */ jint depth; diff --git a/jdk/src/java.desktop/unix/native/include/jawt_md.h b/jdk/src/java.desktop/unix/native/include/jawt_md.h index b7c2ea749aa..2ba3a8e83cf 100644 --- a/jdk/src/java.desktop/unix/native/include/jawt_md.h +++ b/jdk/src/java.desktop/unix/native/include/jawt_md.h @@ -28,7 +28,6 @@ #include #include -#include #include "jawt.h" #ifdef __cplusplus diff --git a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c b/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c deleted file mode 100644 index 712d08409df..00000000000 --- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 1997, 2012, 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. - */ - -#ifndef HEADLESS - -#include -#include "VDrawingAreaP.h" - -#endif /* !HEADLESS */ - -#include -#include - -#ifdef __linux__ -/* XXX: Shouldn't be necessary. */ -#include "awt_p.h" -#endif /* __linux__ */ - - -/****************************************************************** - * - * Provides Canvas widget which allows the X11 visual to be - * changed (the Motif DrawingArea restricts the visual to that - * of the parent widget). - * - ******************************************************************/ - - -/****************************************************************** - * - * VDrawingArea Widget Resources - * - ******************************************************************/ - -#ifndef HEADLESS -#define Offset(x) (XtOffsetOf(VDrawingAreaRec, x)) -static XtResource resources[]= -{ - { XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*), - Offset(vdrawing_area.visual), XtRImmediate, CopyFromParent} -}; - - -static void Realize(); -static Boolean SetValues(); -static void Destroy (); - -static XmBaseClassExtRec baseClassExtRec = { - NULL, - NULLQUARK, - XmBaseClassExtVersion, - sizeof(XmBaseClassExtRec), - NULL, /* InitializePrehook */ - NULL, /* SetValuesPrehook */ - NULL, /* InitializePosthook */ - NULL, /* SetValuesPosthook */ - NULL, /* secondaryObjectClass */ - NULL, /* secondaryCreate */ - NULL, /* getSecRes data */ - { 0 }, /* fastSubclass flags */ - NULL, /* getValuesPrehook */ - NULL, /* getValuesPosthook */ - NULL, /* classPartInitPrehook */ - NULL, /* classPartInitPosthook*/ - NULL, /* ext_resources */ - NULL, /* compiled_ext_resources*/ - 0, /* num_ext_resources */ - FALSE, /* use_sub_resources */ - NULL, /* widgetNavigable */ - NULL, /* focusChange */ - NULL /* wrapper_data */ -}; - -VDrawingAreaClassRec vDrawingAreaClassRec = { -{ - /* Core class part */ - - /* superclass */ (WidgetClass)&xmDrawingAreaClassRec, - /* class_name */ "VDrawingArea", - /* widget_size */ sizeof(VDrawingAreaRec), - /* class_initialize */ NULL, - /* class_part_initialize*/ NULL, - /* class_inited */ FALSE, - /* initialize */ NULL, - /* initialize_hook */ NULL, - /* realize */ Realize, - /* actions */ NULL, - /* num_actions */ 0, - /* resources */ resources, - /* num_resources */ XtNumber(resources), - /* xrm_class */ NULLQUARK, - /* compress_motion */ FALSE, - /* compress_exposure */ FALSE, - /* compress_enterleave*/ FALSE, - /* visible_interest */ FALSE, - /* destroy */ Destroy, - /* resize */ XtInheritResize, - /* expose */ XtInheritExpose, - /* set_values */ SetValues, - /* set_values_hook */ NULL, - /* set_values_almost */ XtInheritSetValuesAlmost, - /* get_values_hook */ NULL, - /* accept_focus */ NULL, - /* version */ XtVersion, - /* callback_offsets */ NULL, - /* tm_table */ NULL, - /* query_geometry */ NULL, - /* display_accelerator */ NULL, - /* extension */ NULL - }, - - { /* composite_class fields */ - XtInheritGeometryManager, /* geometry_manager */ - XtInheritChangeManaged, /* change_managed */ - XtInheritInsertChild, /* insert_child */ - XtInheritDeleteChild, /* delete_child */ - NULL, /* extension */ - }, - - { /* constraint_class fields */ - NULL, /* resource list */ - 0, /* num resources */ - 0, /* constraint size */ - NULL, /* init proc */ - NULL, /* destroy proc */ - NULL, /* set values proc */ - NULL, /* extension */ - }, - - { /* manager_class fields */ - XtInheritTranslations, /* translations */ - NULL, /* syn_resources */ - 0, /* num_get_resources */ - NULL, /* syn_cont_resources */ - 0, /* num_get_cont_resources */ - XmInheritParentProcess, /* parent_process */ - NULL, /* extension */ - }, - - { /* drawingArea class */ - /* extension */ NULL - }, - - /* VDrawingArea class part */ - { - /* extension */ NULL - } -}; - -WidgetClass vDrawingAreaClass = (WidgetClass)&vDrawingAreaClassRec; - -static Boolean -SetValues(cw, rw, nw, args, num_args) - Widget cw; - Widget rw; - Widget nw; - ArgList args; - Cardinal *num_args; -{ - VDrawingAreaWidget current = (VDrawingAreaWidget)cw; - VDrawingAreaWidget new_w = (VDrawingAreaWidget)nw; - - if (new_w->vdrawing_area.visual != current->vdrawing_area.visual) { - new_w->vdrawing_area.visual = current->vdrawing_area.visual; -#ifdef DEBUG - fprintf(stdout, "VDrawingArea.SetValues: can't change visual from: visualID=%ld to visualID=%ld\n", - current->vdrawing_area.visual->visualid, - new_w->vdrawing_area.visual->visualid); -#endif - - } - - return (False); -} - -int -FindWindowInList (Window parentWindow, Window *colormap_windows, int count) -{ - int i; - - for (i = 0; i < count; i++) - if (colormap_windows [i] == parentWindow) - return i; - return -1; -} - -static void -Realize(w, value_mask, attributes) - Widget w; - XtValueMask *value_mask; - XSetWindowAttributes *attributes; -{ - Widget parent; - Status status; - Window *colormap_windows; - Window *new_colormap_windows; - int count; - int i; - VDrawingAreaWidget vd = (VDrawingAreaWidget)w; - -#ifdef DEBUG - fprintf(stdout, "VDrawingArea.Realize: visualID=%ld, depth=%d\n", - vd->vdrawing_area.visual->visualid, w->core.depth); -#endif - - /* 4328588: - * Since we have our own Realize() function, we don't execute the one for - * our super-super class, XmManager, and miss the code which checks that - * height and width != 0. I've added that here. -bchristi - */ - if (!XtWidth(w)) XtWidth(w) = 1 ; - if (!XtHeight(w)) XtHeight(w) = 1 ; - - w->core.window = XCreateWindow (XtDisplay (w), XtWindow (w->core.parent), - w->core.x, w->core.y, w->core.width, w->core.height, - 0, w->core.depth, InputOutput, - vd->vdrawing_area.visual, - *value_mask, attributes ); - - /* Need to add this window to the list of Colormap windows */ - parent = XtParent (w); - while ((parent != NULL) && (!(XtIsShell (parent)))) - parent = XtParent (parent); - if (parent == NULL) { - fprintf (stderr, "NO TopLevel widget?!\n"); - return; - } - - status = XGetWMColormapWindows (XtDisplay (w), XtWindow (parent), - &colormap_windows, &count); - - /* If status is zero, add this window and shell to the list - of colormap Windows */ - if (status == 0) { - new_colormap_windows = (Window *) calloc (2, sizeof (Window)); - new_colormap_windows [0] = XtWindow (w); - new_colormap_windows [1] = XtWindow (parent); - XSetWMColormapWindows (XtDisplay (w), XtWindow (parent), - new_colormap_windows, 2); - free (new_colormap_windows); - } else { - /* Check if parent is already in the list */ - int parent_entry = -1; - - if (count > 0) - parent_entry = FindWindowInList (XtWindow (parent), - colormap_windows, count); - if (parent_entry == -1) { /* Parent not in list */ - new_colormap_windows = (Window *) calloc (count + 2, - sizeof (Window)); - new_colormap_windows [0] = XtWindow (w); - new_colormap_windows [1] = XtWindow (parent); - for (i = 0; i < count; i++) - new_colormap_windows [i + 2] = colormap_windows [i]; - XSetWMColormapWindows (XtDisplay (w), XtWindow (parent), - new_colormap_windows, count + 2); - - } else { /* parent already in list, just add new window */ - new_colormap_windows = (Window *) calloc (count + 1, - sizeof (Window)); - new_colormap_windows [0] = XtWindow (w); - for (i = 0; i < count; i++) - new_colormap_windows [i + 1] = colormap_windows [i]; - XSetWMColormapWindows (XtDisplay (w), XtWindow (parent), - new_colormap_windows, count + 1); - } - free (new_colormap_windows); - XFree (colormap_windows); - } - - -} - -static void -Destroy(Widget widget) -{ - Status status; - Widget parent; - Window *colormap_windows; - Window *new_colormap_windows; - int count; - int listEntry; - int i; - int j; - - /* Need to get this window's parent shell first */ - parent = XtParent (widget); - while ((parent != NULL) && (!(XtIsShell (parent)))) - parent = XtParent (parent); - if (parent == NULL) { - fprintf (stderr, "NO TopLevel widget?!\n"); - return; - } - - status = XGetWMColormapWindows (XtDisplay (widget), XtWindow (parent), - &colormap_windows, &count); - - /* If status is zero, then there were no colormap windows for - the parent ?? */ - - if (status == 0) - return; - - /* Remove this window from the list of colormap windows */ - listEntry = FindWindowInList (XtWindow (widget), colormap_windows, - count); - - new_colormap_windows = (Window *) calloc (count - 1, sizeof (Window)); - j = 0; - for (i = 0; i < count; i++) { - if (i == listEntry) - continue; - new_colormap_windows [j] = colormap_windows [i]; - j++; - } - XSetWMColormapWindows (XtDisplay (widget), XtWindow (parent), - new_colormap_windows, count - 1); - free (new_colormap_windows); - XFree (colormap_windows); - -} -#endif /* !HEADLESS */ diff --git a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h b/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h deleted file mode 100644 index fe6b67ee530..00000000000 --- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 1997, 2001, 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. - */ - -#ifndef _VDrawingArea_h_ -#define _VDrawingArea_h_ - -#ifndef HEADLESS -extern WidgetClass vDrawingAreaClass; - -typedef struct _VDrawingAreaClassRec *VDrawingAreaWidgetClass; -typedef struct _VDrawingAreaRec *VDrawingAreaWidget; -#endif /* !HEADLESS */ - -#endif /* !_VDrawingArea_h_ */ diff --git a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h b/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h deleted file mode 100644 index 00864fc50cd..00000000000 --- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 1997, 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. - */ - -#ifndef _VDrawingAreaP_h_ -#define _VDrawingAreaP_h_ - -#include -#include "VDrawingArea.h" - - -/*************************************************************** - * VDrawingArea Widget Data Structures - * - * - **************************************************************/ - -/* Define part class structure */ -typedef struct _VDrawingAreaClass { - XtPointer extension; -} VDrawingAreaClassPart; - -/* Define the full class record */ -typedef struct _VDrawingAreaClassRec { - CoreClassPart core_class; - CompositeClassPart composite_class; - ConstraintClassPart constraint_class; - XmManagerClassPart manager_class; - XmDrawingAreaClassPart drawing_area_class; - VDrawingAreaClassPart vdrawingarea_class; -} VDrawingAreaClassRec; - -/* External definition for class record */ -extern VDrawingAreaClassRec vDrawingAreaClassRec; - -typedef struct { - Visual *visual; -} VDrawingAreaPart; - -/**************************************************************** - * - * Full instance record declaration - * - ****************************************************************/ - -typedef struct _VDrawingAreaRec -{ - CorePart core; - CompositePart composite; - ConstraintPart constraint; - XmManagerPart manager; - XmDrawingAreaPart drawing_area; - VDrawingAreaPart vdrawing_area; -} VDrawingAreaRec; - - - -#endif /* !_VDrawingAreaP_h_ */ diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c index 00d04814e86..e4388cd64a4 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -40,7 +40,6 @@ #define THROW_OUT_OF_MEMORY_ERROR() \ JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL) -#define SETARG(name, value) XtSetArg(args[argc], name, value); argc++ struct X11InputMethodIDs { jfieldID pData; @@ -590,7 +589,7 @@ static StatusWindow *createStatusWindow( char **mclr; int mccr = 0; char *dsr; - Pixel bg, fg, light, dim; + unsigned long bg, fg, light, dim; int x, y, off_x, off_y, xx, yy; unsigned int w, h, bw, depth; XGCValues values; diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c index c9172a6e5f6..b066844ca74 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c @@ -31,7 +31,6 @@ #include "awt_GraphicsEnv.h" #define XK_MISCELLANY #include -#include #include #include #include diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c index 261986f9ac0..d61c59b5915 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c @@ -29,7 +29,6 @@ #include "awt_p.h" #include "color.h" -#include #include #include #include diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c index 3b340914658..db32a22ec6c 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c @@ -354,7 +354,6 @@ JNIEXPORT void JNICALL Java_java_awt_Dialog_initIDs (JNIEnv *env, jclass cls) static void waitForEvents(JNIEnv *, jlong); static void awt_pipe_init(); -static void processOneEvent(XtInputMask iMask); static Boolean performPoll(JNIEnv *, jlong); static void wakeUp(); static void update_poll_timeout(int timeout_control); @@ -614,7 +613,7 @@ static uint32_t get_poll_timeout(jlong nextTaskTime) } /* get_poll_timeout() */ /* - * Waits for X/Xt events to appear on the pipe. Returns only when + * Waits for X events to appear on the pipe. Returns only when * it is likely (but not definite) that there are events waiting to * be processed. * From a7624a0967777411e2e99a85fc9eb2453700262e Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 16 Apr 2016 23:29:11 +0300 Subject: [PATCH 100/225] 8154016: [macosx] Some HiDPI code can be removed Reviewed-by: alexsch, prr --- .../macosx/classes/sun/lwawt/LWWindowPeer.java | 2 +- .../macosx/classes/sun/lwawt/PlatformWindow.java | 6 ------ .../classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java | 9 ++------- .../classes/sun/lwawt/macosx/CPlatformLWWindow.java | 6 ------ .../macosx/classes/sun/lwawt/macosx/CPlatformWindow.java | 6 ------ .../sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java | 6 ------ .../macosx/classes/sun/lwawt/macosx/CWarningWindow.java | 6 +++--- 7 files changed, 6 insertions(+), 35 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index 820dc1af2a0..658be0638bb 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -295,7 +295,7 @@ public class LWWindowPeer if (f == null) { f = DEFAULT_FONT; } - return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f)); + return new SunGraphics2D(getSurfaceData(), fg, bg, f); } @Override diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java index 81134ef48c4..0e3be9d81a1 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java @@ -130,12 +130,6 @@ public interface PlatformWindow { */ public void setSizeConstraints(int minW, int minH, int maxW, int maxH); - /** - * Transforms the given Graphics object according to the native - * implementation traits (insets, etc.). - */ - public Graphics transformGraphics(Graphics g); - /* * Installs the images for particular window. */ diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index b2e7466b817..d7c6d2903f6 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -31,7 +31,6 @@ import java.awt.event.FocusEvent; import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLLayer; import sun.lwawt.LWWindowPeer; -import sun.lwawt.LWWindowPeer.PeerType; import sun.lwawt.PlatformWindow; import sun.util.logging.PlatformLogger; @@ -40,7 +39,8 @@ import sun.util.logging.PlatformLogger; */ public class CPlatformEmbeddedFrame implements PlatformWindow { - private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformEmbeddedFrame"); + private static final PlatformLogger focusLogger = PlatformLogger.getLogger( + "sun.lwawt.macosx.focus.CPlatformEmbeddedFrame"); private CGLLayer windowLayer; private LWWindowPeer peer; @@ -161,11 +161,6 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { @Override public void setSizeConstraints(int minW, int minH, int maxW, int maxH) {} - @Override - public Graphics transformGraphics(Graphics g) { - return g; - } - @Override public void updateIconImages() {} diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java index 71bb436dff3..a056df5cc10 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java @@ -27,7 +27,6 @@ package sun.lwawt.macosx; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Insets; @@ -152,11 +151,6 @@ public class CPlatformLWWindow extends CPlatformWindow { public void updateFocusableWindowState() { } - @Override - public Graphics transformGraphics(Graphics g) { - return null; - } - @Override public void setAlwaysOnTop(boolean isAlwaysOnTop) { } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 835f01a5eca..f0d0a22b3bc 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -740,12 +740,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once } - @Override - public Graphics transformGraphics(Graphics g) { - // is this where we can inject a transform for HiDPI? - return g; - } - @Override public void setAlwaysOnTop(boolean isAlwaysOnTop) { setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java index e577f286a91..2312fbb94be 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java @@ -27,7 +27,6 @@ package sun.lwawt.macosx; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.Insets; import java.awt.MenuBar; @@ -170,11 +169,6 @@ public class CViewPlatformEmbeddedFrame implements PlatformWindow { public void setSizeConstraints(int minW, int minH, int maxW, int maxH) { } - @Override - public Graphics transformGraphics(Graphics g) { - return g; - } - @Override public void updateIconImages() { } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java index b2c36705a09..28a4b657e55 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.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 @@ -364,8 +364,8 @@ public final class CWarningWindow extends CPlatformWindow return null; } - return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText, - SystemColor.window, ownerWindow.getFont())); + return new SunGraphics2D(sd, SystemColor.windowText, SystemColor.window, + ownerWindow.getFont()); } From 0aee9fb36835dd255359debb5b7ae93331967888 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 16 Apr 2016 23:36:45 +0300 Subject: [PATCH 101/225] 8141544: The interface sun.swing.UIClientPropertyKey can be made public Reviewed-by: alexsch --- .../plaf/windows/AnimationController.java | 3 +- .../share/classes/javax/swing/JComponent.java | 2 - .../swing/UIClientPropertyKey.java | 17 +-- .../sun/swing/StringUIClientPropertyKey.java | 4 +- .../UIClientPropertyKeyTest.java | 113 ++++++++++++++++++ 5 files changed, 126 insertions(+), 13 deletions(-) rename jdk/src/java.desktop/share/classes/{sun => javax}/swing/UIClientPropertyKey.java (76%) create mode 100644 jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java index dab22fd293e..eb47262b29c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -37,7 +37,6 @@ import javax.swing.*; -import sun.swing.UIClientPropertyKey; import com.sun.java.swing.plaf.windows.TMSchema.State; import static com.sun.java.swing.plaf.windows.TMSchema.State.*; import com.sun.java.swing.plaf.windows.TMSchema.Part; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java index dd64b77df1d..56d1df019ba 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -36,7 +36,6 @@ import java.util.Set; import java.awt.*; import java.awt.event.*; -import java.awt.peer.LightweightPeer; import java.applet.Applet; @@ -57,7 +56,6 @@ import javax.accessibility.*; import sun.awt.AWTAccessor; import sun.awt.SunToolkit; import sun.swing.SwingUtilities2; -import sun.swing.UIClientPropertyKey; /** * The base class for all Swing components except top-level containers. diff --git a/jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java b/jdk/src/java.desktop/share/classes/javax/swing/UIClientPropertyKey.java similarity index 76% rename from jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java rename to jdk/src/java.desktop/share/classes/javax/swing/UIClientPropertyKey.java index 6ec361cbf45..8aa2bf393fc 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/UIClientPropertyKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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,18 +23,19 @@ * questions. */ -package sun.swing; +package javax.swing; /** - * This interface is used only for tagging keys for client properties - * for {@code JComponent} set by UI which needs to be cleared on {@literal L&F} + * This interface is used only for tagging keys for client properties for + * {@code JComponent} set by UI which needs to be cleared on {@literal L&F} * change and serialization. - * - * All such keys are removed from client properties in {@code - * JComponent.setUI()} method after uninstalling old UI and before - * intalling the new one. They are also removed prior to serialization. + *

    + * All such keys are removed from client properties in + * {@code JComponent.setUI()} method after uninstalling old UI and before + * installing the new one. They are also removed prior to serialization. * * @author Igor Kushnirskiy + * @since 9 */ public interface UIClientPropertyKey { } diff --git a/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java b/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java index ea4bb945b1c..7720d484467 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -25,6 +25,8 @@ package sun.swing; +import javax.swing.UIClientPropertyKey; + /** * An implementation of {@code UIClientPropertyKey} that wraps a {@code String}. * diff --git a/jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java b/jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java new file mode 100644 index 00000000000..499fa0cf3cd --- /dev/null +++ b/jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java @@ -0,0 +1,113 @@ +/* + * 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.EventQueue; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.UIClientPropertyKey; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/** + * @test + * @bug 8141544 + */ +public final class UIClientPropertyKeyTest { + + private static Object key = new UIClientPropertyKey() { + }; + + public static void main(final String[] args) throws Exception { + EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSetUI); + EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSerialization); + } + + /** + * UIClientPropertyKey should be removed after deserialization. + */ + private static void testSerialization() { + JComponent comp = new JButton(); + comp.putClientProperty("key1", "value1"); + comp.putClientProperty(key, "value2"); + + comp = serializeDeserialize(comp); + + validate(comp); + } + + /** + * UIClientPropertyKey should be removed on updateUI(). + */ + private static void testSetUI() { + JComponent comp = new JButton(); + comp.putClientProperty("key1", "value1"); + for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { + comp.putClientProperty(key, "value2"); + setLookAndFeel(laf); + SwingUtilities.updateComponentTreeUI(comp); + validate(comp); + } + } + + private static void validate(JComponent comp) { + Object value = comp.getClientProperty("key1"); + if (!value.equals("value1")) { + throw new RuntimeException("Incorrect value: " + value); + } + value = comp.getClientProperty(key); + if (value != null) { + throw new RuntimeException("Incorrect value: " + value); + } + } + + private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + System.out.println("LookAndFeel: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException | + UnsupportedLookAndFeelException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static JComponent serializeDeserialize(JComponent comp) { + try { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(comp); + out.close(); + return (JComponent) new ObjectInputStream(new ByteArrayInputStream( + byteOut.toByteArray())).readObject(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} From ea65ad3102de33a1f6daa63a402e30aa42a3f67a Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 16 Apr 2016 23:39:45 +0300 Subject: [PATCH 102/225] 7102282: TEST_BUG: sun/java2d/OpenGL/GradientPaints.java should be modified Reviewed-by: yan, psadhukhan --- jdk/test/sun/java2d/OpenGL/GradientPaints.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/test/sun/java2d/OpenGL/GradientPaints.java b/jdk/test/sun/java2d/OpenGL/GradientPaints.java index 009ca09bb81..7e8736a96f3 100644 --- a/jdk/test/sun/java2d/OpenGL/GradientPaints.java +++ b/jdk/test/sun/java2d/OpenGL/GradientPaints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 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 @@ -23,11 +23,11 @@ /* * @test - * @bug 6521533 6525997 + * @bug 6521533 6525997 7102282 * @summary Verifies that the OGL-accelerated codepaths for GradientPaint, * LinearGradientPaint, and RadialGradientPaint produce results that are * sufficiently close to those produced by the software codepaths. - * @run main/othervm -Dsun.java2d.opengl=True GradientPaints + * @run main/othervm -Dsun.java2d.uiScale=1 -Dsun.java2d.opengl=True GradientPaints * @author campbelc */ From 881e6672230e42d819f7e19b9058691d56aa5cfe Mon Sep 17 00:00:00 2001 From: Prem Balakrishnan Date: Mon, 18 Apr 2016 15:39:29 +0530 Subject: [PATCH 103/225] 8153056: 8152647(duplicate of 6439354) Manual Test always passes Reviewed-by: alexsch, psadhukhan --- .../LookAndFeel/6439354/TitledBorderTest.java | 164 +++++++++++------- 1 file changed, 97 insertions(+), 67 deletions(-) diff --git a/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java b/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java index f74a14d99ee..118283adf1f 100644 --- a/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java +++ b/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6439354 + * @bug 8153056 8152647 6439354 * @summary Verify TitleBorder appearance Color/Visibility for WLAF * @requires (os.family == "windows") * @run main/manual TitledBorderTest @@ -33,6 +33,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.concurrent.CountDownLatch; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; @@ -41,7 +42,26 @@ import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.UIManager; -public class TitledBorderTest implements ActionListener { +public class TitledBorderTest { + + public static void main(String args[]) throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + + TitledBorder test = new TitledBorder(latch); + Thread T1 = new Thread(test); + T1.start(); + + // wait for latch to complete + latch.await(); + + if (test.testResult == false) { + throw new RuntimeException("User Clicked Fail!" + + " TitledBorder Not Valid"); + } + } +} + +class TitledBorder implements Runnable { private static GridBagLayout layout; private static JPanel mainControlPanel; @@ -50,88 +70,98 @@ public class TitledBorderTest implements ActionListener { private static JButton passButton; private static JButton failButton; private static JFrame mainFrame; + private final CountDownLatch latch; + public boolean testResult = false; - public static void main(String[] args) throws Exception { - TitledBorderTest titledBorderTest = new TitledBorderTest(); + public TitledBorder(CountDownLatch latch) throws Exception { + this.latch = latch; } - public TitledBorderTest() throws Exception { - createUI(); + @Override + public void run() { + + try { + createUI(); + } catch (Exception ex) { + if (mainFrame != null) { + mainFrame.dispose(); + } + latch.countDown(); + throw new RuntimeException("createUI Failed: " + ex.getMessage()); + } + } public final void createUI() throws Exception { UIManager.setLookAndFeel("com.sun.java.swing.plaf." + "windows.WindowsLookAndFeel"); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + mainFrame = new JFrame("Window LAF TitledBorder Test"); + layout = new GridBagLayout(); + mainControlPanel = new JPanel(layout); + resultButtonPanel = new JPanel(layout); - SwingUtilities.invokeAndWait(() -> { + GridBagConstraints gbc = new GridBagConstraints(); + String instructions + = "INSTRUCTIONS:" + + "\n set Windows Theme to HighContrast#1." + + "\n (ControlPanel->Personalization->High Contrast#1)" + + "\n If Titled Border(Border Line) is visible then test" + + " passes else failed."; - mainFrame = new JFrame("Window LAF TitledBorder Test"); - layout = new GridBagLayout(); - mainControlPanel = new JPanel(layout); - resultButtonPanel = new JPanel(layout); + instructionTextArea = new JTextArea(); + instructionTextArea.setText(instructions); + instructionTextArea.setEnabled(false); + instructionTextArea.setDisabledTextColor(Color.black); + instructionTextArea.setBackground(Color.white); - GridBagConstraints gbc = new GridBagConstraints(); - String instructions - = "INSTRUCTIONS:" - + "\n set Windows Theme to HighContrast#1." - + "\n (ControlPanel->Personalization->High Contrast#1)" - + "\n If Titled Border(Border Line) is visible then test" - + " passes else failed."; + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(instructionTextArea, gbc); - instructionTextArea = new JTextArea(); - instructionTextArea.setText(instructions); - instructionTextArea.setEnabled(false); - instructionTextArea.setDisabledTextColor(Color.black); - instructionTextArea.setBackground(Color.white); + mainControlPanel.setBorder(BorderFactory. + createTitledBorder("Titled Border")); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.fill = GridBagConstraints.HORIZONTAL; - mainControlPanel.add(instructionTextArea, gbc); + passButton = new JButton("Pass"); + passButton.setActionCommand("Pass"); + passButton.addActionListener((ActionEvent e) -> { + System.out.println("Pass Button pressed!"); + testResult = true; + mainFrame.dispose(); + latch.countDown(); - mainControlPanel.setBorder(BorderFactory. - createTitledBorder("Titled Border")); + }); + failButton = new JButton("Fail"); + failButton.setActionCommand("Fail"); + failButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("Fail Button pressed!"); + testResult = false; + mainFrame.dispose(); + latch.countDown(); + } + }); + gbc.gridx = 0; + gbc.gridy = 0; + resultButtonPanel.add(passButton, gbc); + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); - passButton = new JButton("Pass"); - passButton.setActionCommand("Pass"); - passButton.addActionListener(TitledBorderTest.this); - failButton = new JButton("Fail"); - failButton.setActionCommand("Fail"); - failButton.addActionListener(TitledBorderTest.this); - gbc.gridx = 0; - gbc.gridy = 0; - resultButtonPanel.add(passButton, gbc); - gbc.gridx = 1; - gbc.gridy = 0; - resultButtonPanel.add(failButton, gbc); + gbc.gridx = 0; + gbc.gridy = 1; + mainControlPanel.add(resultButtonPanel, gbc); - gbc.gridx = 0; - gbc.gridy = 1; - mainControlPanel.add(resultButtonPanel, gbc); - - mainFrame.add(mainControlPanel); - mainFrame.pack(); - mainFrame.setVisible(true); - }); - } - - @Override - public void actionPerformed(ActionEvent evt) { - if (evt.getSource() instanceof JButton) { - JButton btn = (JButton) evt.getSource(); - cleanUp(); - switch (btn.getActionCommand()) { - case "Pass": - break; - case "Fail": - throw new AssertionError("User Clicked Fail!"); + mainFrame.add(mainControlPanel); + mainFrame.pack(); + mainFrame.setVisible(true); } - } - } + }); - private static void cleanUp() { - mainFrame.dispose(); } - } From 33aa33f03a83d5fd09dee99d89397a7b572b2cd5 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Mon, 18 Apr 2016 13:42:52 -0400 Subject: [PATCH 104/225] 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 105/225] 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 106/225] 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 108c188df5061703f06aab3b25637749a2583277 Mon Sep 17 00:00:00 2001 From: Ajit Ghaisas Date: Tue, 19 Apr 2016 13:00:00 +0530 Subject: [PATCH 107/225] 8031423: Test java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java fails by Timeout on Windows Reviewed-by: yan, arapte --- .../DisposeFrameOnDragTest.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java b/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java index 05cd0d51840..bfeb4bda85a 100644 --- a/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java +++ b/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -56,17 +56,24 @@ public class DisposeFrameOnDragTest { } }); - Util.waitForIdle(null); + Robot testRobot = null; try { - Point loc = textArea.getLocationOnScreen(); - Util.drag(new Robot(), - new Point((int) loc.x + 3, (int) loc.y + 3), - new Point((int) loc.x + 40, (int) loc.y + 40), - InputEvent.BUTTON1_MASK); - } catch (AWTException ex) { - throw new RuntimeException("Could not initiate a drag operation"); + testRobot = new Robot(); + } catch(AWTException ex) { + throw new RuntimeException("Error while creating Robot"); } - Util.waitForIdle(null); + + Util.waitForIdle(testRobot); + + Point loc = textArea.getLocationOnScreen(); + Util.drag(testRobot, + new Point((int) loc.x + 3, (int) loc.y + 3), + new Point((int) loc.x + 40, (int) loc.y + 40), + InputEvent.BUTTON1_MASK); + + Util.waitForIdle(testRobot); + + testRobot.delay(200); } private static void constructTestUI() { From ebb86eaa4f6da5ab0985b8ad4c8981fa43c494eb Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 19 Apr 2016 14:34:43 +0100 Subject: [PATCH 108/225] 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 8658335d619cb041b9b64ec2e7196ce0cb0a67fc Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 20 Apr 2016 10:59:23 +0530 Subject: [PATCH 109/225] 6197099: PrinterJob.getUserName() throws a security exception when user.name permission is not given Reviewed-by: prr, jdv --- .../classes/java/awt/print/PrinterJob.java | 2 + .../awt/print/PrinterJob/GetUserNameTest.java | 49 +++++++++++++++++++ .../print/PrinterJob/GetUserNameTest.policy | 28 +++++++++++ 3 files changed, 79 insertions(+) create mode 100644 jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java create mode 100644 jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy diff --git a/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java b/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java index 3044cd2413a..5a1cf128607 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java +++ b/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java @@ -577,6 +577,8 @@ public abstract class PrinterJob { /** * Gets the name of the printing user. * @return the name of the printing user + * @throws SecurityException if a security manager exists and + * PropertyPermission - user.name is not given in the policy file */ public abstract String getUserName(); diff --git a/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java new file mode 100644 index 00000000000..8e35a5f4204 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java @@ -0,0 +1,49 @@ +/* + * 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 6197099 + * @summary Verifies PrinterJob's getUserName() throws a security exception when + * username permission is not given + * @run main/othervm/java.security.policy=GetUserNameTest.policy GetUserNameTest + */ +import java.awt.print.PrinterJob; + +public class GetUserNameTest { + + public static void main(String args[]) { + System.setSecurityManager(new SecurityManager()); + PrinterJob pj = PrinterJob.getPrinterJob(); + boolean secExcpn = false; + try { + System.out.println(pj.getUserName()); + } catch (SecurityException ex) { + secExcpn = true; + System.out.println("SecurityException thrown as user.name permission " + + "not given"); + } + if (!secExcpn) { + throw new RuntimeException("SecurityException not thrown"); + } + } +} diff --git a/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy new file mode 100644 index 00000000000..b7b7d70df3d --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy @@ -0,0 +1,28 @@ +/* + * 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. + */ +grant { + permission java.lang.RuntimePermission "setSecurityManager"; + permission java.lang.RuntimePermission "createSecurityManager"; + permission java.lang.RuntimePermission "usePolicy"; + permission java.lang.RuntimePermission "queuePrintJob"; +}; From d03b60789684f8a9e96b47c89b05b3c2e639c26a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Tue, 19 Apr 2016 23:01:06 -0700 Subject: [PATCH 110/225] 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 111/225] 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 f69b5f55eb71737d3afe966f56e364e26b3bc1e7 Mon Sep 17 00:00:00 2001 From: Peter Brunet Date: Wed, 20 Apr 2016 12:23:38 -0500 Subject: [PATCH 112/225] 8076554: [macosx] Custom Swing text components need to allow standard accessibility Remove JTextComponent listeners; use property change listeners for caret/text Reviewed-by: prr, alexsch --- .../macosx/AccessibilityEventMonitor.java | 253 ++++++++++++++++++ .../classes/sun/lwawt/macosx/CAccessible.java | 47 ++-- 2 files changed, 271 insertions(+), 29 deletions(-) create mode 100644 jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java new file mode 100644 index 00000000000..c575590802b --- /dev/null +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java @@ -0,0 +1,253 @@ +/* + * 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 + * 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.lwawt.macosx; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; +import javax.swing.event.EventListenerList; + +/** + *

    {@code AccessibilityEventMonitor} implements a PropertyChange listener + * on every UI object that implements interface {@code Accessible} in the Java + * Virtual Machine. The events captured by these listeners are made available + * through listeners supported by {@code AccessibilityEventMonitor}. + * With this, all the individual events on each of the UI object + * instances are funneled into one set of PropertyChange listeners. + * + * This code is a subset of com.sun.java.accessibility.util.AccessibilityEventMonitor + * which resides in module jdk.accessibility. Due to modularization the code in + * this package, java.desktop, can not be dependent on code in jdk.accessibility. + */ + +class AccessibilityEventMonitor { + + /** + * The current list of registered {@link java.beans.PropertyChangeListener + * PropertyChangeListener} classes. + * + * @see #addPropertyChangeListener + */ + private static final EventListenerList listenerList = + new EventListenerList(); + + + /** + * The actual listener that is installed on the component instances. + * This listener calls the other registered listeners when an event + * occurs. By doing things this way, the actual number of listeners + * installed on a component instance is drastically reduced. + */ + private static final AccessibilityEventListener accessibilityListener = + new AccessibilityEventListener(); + + /** + * Adds the specified listener to receive all PropertyChange events on + * each UI object instance in the Java Virtual Machine as they occur. + *

    Note: This listener is automatically added to all component + * instances created after this method is called. In addition, it + * is only added to UI object instances that support this listener type. + * + * @param l the listener to add + * @param a the Accessible object to add the PropertyChangeListener to + */ + + static void addPropertyChangeListener(PropertyChangeListener l, Accessible a) { + if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) { + accessibilityListener.installListeners(a); + } + listenerList.add(PropertyChangeListener.class, l); + } + + /** + * AccessibilityEventListener is the class that does all the work for + * AccessibilityEventMonitor. It is not intended for use by any other + * class except AccessibilityEventMonitor. + */ + + private static class AccessibilityEventListener implements PropertyChangeListener { + + /** + * Installs PropertyChange listeners to the Accessible object, and its + * children (so long as the object isn't of TRANSIENT state). + * + * @param a the Accessible object to add listeners to + */ + private void installListeners(Accessible a) { + installListeners(a.getAccessibleContext()); + } + + /** + * Installs PropertyChange listeners to the AccessibleContext object, + * and its * children (so long as the object isn't of TRANSIENT state). + * + * @param ac the AccessibleContext to add listeners to + */ + private void installListeners(AccessibleContext ac) { + + if (ac != null) { + AccessibleStateSet states = ac.getAccessibleStateSet(); + if (!states.contains(AccessibleState.TRANSIENT)) { + ac.addPropertyChangeListener(this); + /* + * Don't add listeners to transient children. Components + * with transient children should return an AccessibleStateSet + * containing AccessibleState.MANAGES_DESCENDANTS. Components + * may not explicitly return the MANAGES_DESCENDANTS state. + * In this case, don't add listeners to the children of + * lists, tables and trees. + */ + AccessibleStateSet set = ac.getAccessibleStateSet(); + if (set.contains(AccessibleState.MANAGES_DESCENDANTS)) { + return; + } + AccessibleRole role = ac.getAccessibleRole(); + if ( role == AccessibleRole.LIST || + role == AccessibleRole.TREE ) { + return; + } + if (role == AccessibleRole.TABLE) { + // handle Oracle tables containing tables + Accessible child = ac.getAccessibleChild(0); + if (child != null) { + AccessibleContext ac2 = child.getAccessibleContext(); + if (ac2 != null) { + role = ac2.getAccessibleRole(); + if (role != null && role != AccessibleRole.TABLE) { + return; + } + } + } + } + int count = ac.getAccessibleChildrenCount(); + for (int i = 0; i < count; i++) { + Accessible child = ac.getAccessibleChild(i); + if (child != null) { + installListeners(child); + } + } + } + } + } + + /** + * Removes PropertyChange listeners for the given Accessible object, + * its children (so long as the object isn't of TRANSIENT state). + * + * @param a the Accessible object to remove listeners from + */ + private void removeListeners(Accessible a) { + removeListeners(a.getAccessibleContext()); + } + + /** + * Removes PropertyChange listeners for the given AccessibleContext + * object, its children (so long as the object isn't of TRANSIENT + * state). + * + * @param a the Accessible object to remove listeners from + */ + private void removeListeners(AccessibleContext ac) { + + if (ac != null) { + // Listeners are not added to transient components. + AccessibleStateSet states = ac.getAccessibleStateSet(); + if (!states.contains(AccessibleState.TRANSIENT)) { + ac.removePropertyChangeListener(this); + /* + * Listeners are not added to transient children. Components + * with transient children should return an AccessibleStateSet + * containing AccessibleState.MANAGES_DESCENDANTS. Components + * may not explicitly return the MANAGES_DESCENDANTS state. + * In this case, don't remove listeners from the children of + * lists, tables and trees. + */ + if (states.contains(AccessibleState.MANAGES_DESCENDANTS)) { + return; + } + AccessibleRole role = ac.getAccessibleRole(); + if ( role == AccessibleRole.LIST || + role == AccessibleRole.TABLE || + role == AccessibleRole.TREE ) { + return; + } + int count = ac.getAccessibleChildrenCount(); + for (int i = 0; i < count; i++) { + Accessible child = ac.getAccessibleChild(i); + if (child != null) { + removeListeners(child); + } + } + } + } + } + + @Override + public void propertyChange(PropertyChangeEvent e) { + // propogate the event + Object[] listeners = + AccessibilityEventMonitor.listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==PropertyChangeListener.class) { + ((PropertyChangeListener)listeners[i+1]).propertyChange(e); + } + } + + // handle childbirth/death + String name = e.getPropertyName(); + if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) { + Object oldValue = e.getOldValue(); + Object newValue = e.getNewValue(); + + if ((oldValue == null) ^ (newValue == null)) { // one null, not both + if (oldValue != null) { + // this Accessible is a child that's going away + if (oldValue instanceof Accessible) { + Accessible a = (Accessible) oldValue; + removeListeners(a.getAccessibleContext()); + } else if (oldValue instanceof AccessibleContext) { + removeListeners((AccessibleContext) oldValue); + } + } else if (newValue != null) { + // this Accessible is a child was just born + if (newValue instanceof Accessible) { + Accessible a = (Accessible) newValue; + installListeners(a.getAccessibleContext()); + } else if (newValue instanceof AccessibleContext) { + installListeners((AccessibleContext) newValue); + } + } + } else { + System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString()); + } + } + } + } +} diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java index c5611c4d453..20ce3551d94 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.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 @@ -26,20 +26,18 @@ package sun.lwawt.macosx; import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.lang.reflect.Field; import javax.accessibility.Accessible; import javax.accessibility.AccessibleContext; import javax.swing.JProgressBar; import javax.swing.JSlider; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.text.JTextComponent; +import sun.lwawt.macosx.CFRetainedResource; class CAccessible extends CFRetainedResource implements Accessible { static Field getNativeAXResourceField() { @@ -99,13 +97,10 @@ class CAccessible extends CFRetainedResource implements Accessible { return accessible.getAccessibleContext(); } - // currently only supports text components public void addNotificationListeners(Component c) { - if (c instanceof JTextComponent) { - JTextComponent tc = (JTextComponent) c; - AXTextChangeNotifier listener = new AXTextChangeNotifier(); - tc.getDocument().addDocumentListener(listener); - tc.addCaretListener(listener); + AXTextChangeNotifier listener = new AXTextChangeNotifier(); + if (c instanceof Accessible) { + AccessibilityEventMonitor.addPropertyChangeListener(listener, (Accessible)c); } if (c instanceof JProgressBar) { JProgressBar pb = (JProgressBar) c; @@ -117,29 +112,23 @@ class CAccessible extends CFRetainedResource implements Accessible { } - private class AXTextChangeNotifier implements DocumentListener, CaretListener { - @Override - public void changedUpdate(DocumentEvent e) { - if (ptr != 0) valueChanged(ptr); - } + private class AXTextChangeNotifier implements PropertyChangeListener { @Override - public void insertUpdate(DocumentEvent e) { - if (ptr != 0) valueChanged(ptr); - } - - @Override - public void removeUpdate(DocumentEvent e) { - if (ptr != 0) valueChanged(ptr); - } - - @Override - public void caretUpdate(CaretEvent e) { - if (ptr != 0) selectionChanged(ptr); + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + if ( ptr != 0 ) { + if (name.compareTo(AccessibleContext.ACCESSIBLE_CARET_PROPERTY) == 0) { + selectionChanged(ptr); + } else if (name.compareTo(AccessibleContext.ACCESSIBLE_TEXT_PROPERTY) == 0 ) { + valueChanged(ptr); + } + } } } private class AXProgressChangeNotifier implements ChangeListener { + @Override public void stateChanged(ChangeEvent e) { if (ptr != 0) valueChanged(ptr); } From c2f3c9f0db5bc8f64eb3f6757edf76b51dccd92f Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Thu, 21 Apr 2016 20:08:18 +0300 Subject: [PATCH 113/225] 8154762: [TEST] add some tests according to JDK-8132138 Reviewed-by: ssadetsky, serb --- .../beans/Introspector/BeanPropertyTest.java | 988 ++++++++++++++++++ 1 file changed, 988 insertions(+) create mode 100644 jdk/test/java/beans/Introspector/BeanPropertyTest.java diff --git a/jdk/test/java/beans/Introspector/BeanPropertyTest.java b/jdk/test/java/beans/Introspector/BeanPropertyTest.java new file mode 100644 index 00000000000..0344f378cc6 --- /dev/null +++ b/jdk/test/java/beans/Introspector/BeanPropertyTest.java @@ -0,0 +1,988 @@ +/* + * 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.beans.BeanInfo; +import java.beans.BeanProperty; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; + +import java.util.Arrays; + + +/** + * @test + * @bug 8132703 8132163 8132732 8132973 8154756 8132888 + * @summary Some check for BeanProperty annotation + * @author a.stepanov + * @run main BeanPropertyTest + */ + + +public class BeanPropertyTest { + + private final static String DESCRIPTION = "TEST"; + private final static boolean BOUND = true; + private final static boolean EXPERT = false; + private final static boolean HIDDEN = true; + private final static boolean PREFERRED = false; + private final static boolean REQUIRED = true; + private final static boolean UPDATE = false; + private final static String + V_NAME = "javax.swing.SwingConstants.TOP", + V_SHORT = "TOP", + V = Integer.toString(javax.swing.SwingConstants.TOP); + private final static int X = javax.swing.SwingConstants.TOP; + + private final static String DESCRIPTION_2 = "XYZ"; + + + // ---------- test cases ---------- + + public static class G01 { + + private final static String TESTCASE = "arbitrary getter name"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int get1() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class S01 { + + private final static String TESTCASE = "arbitrary setter name"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setXXXXX(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132703 + public static class G02 { + + private final static String TESTCASE = "arbitrary getter name"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int get() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132703 + public static class S02 { + + private final static String TESTCASE = "arbitrary setter name"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void set(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132703 + public static class G03 { + + private final static String TESTCASE = "arbitrary getter name"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int GetX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132703 + public static class S03 { + + private final static String TESTCASE = "arbitrary setter name"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void SetX(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132163 + public static class G04 { + + private final static String TESTCASE = "arbitrary getter return type"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public Object getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132163 + public static class S04 { + + private final static String TESTCASE = "arbitrary setter argument type"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(short v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G05 { + + private final static String TESTCASE = + "annotated getter + arbitrary setter argument type"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX() { return x; } + public void setX(short v) { x = v; } + + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132163 + public static class S05 { + + private final static String TESTCASE = + "annotated setter + arbitrary getter return type"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int v) { x = v; } + public Object getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G06 { + + private final static String TESTCASE = "indexed getter"; + + private final int x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX(int i) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + return x[i]; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class S06 { + + private final static String TESTCASE = "indexed setter"; + + private final int x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int i, int v) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + x[i] = v; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G07 { + + private final static String TESTCASE = + "indexed (annotated) + non-indexed getters"; + + private final int x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX(int i) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + return x[i]; + } + + public int[] getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class S07 { + + private final static String TESTCASE = + "indexed (annotated) + non-indexed setters"; + + private int x[] = new int[3]; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int i, int v) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + x[i] = v; + } + + public void setX(int a[]) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132732 + public static class G08 { + + private final static String TESTCASE = + "non-indexed (annotated) + indexed getters"; + + private final int x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int[] getX() { return x; } + + public int getX(int i) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + return x[i]; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132732 + public static class S08 { + + private final static String TESTCASE = + "non-indexed (annotated) + indexed setters"; + + private int x[] = new int[3]; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int a[]) { x = Arrays.copyOf(a, a.length); } + + public void setX(int i, int v) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + x[i] = v; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132732 + public static class G09 { + + private final static String TESTCASE = "two annotated getters"; + + private final int x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int[] getX() { return x; } + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public int getX(int i) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + return x[i]; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132732 + public static class S09 { + + private final static String TESTCASE = "two annotated setters"; + + private int x[] = new int[3]; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int a[]) { x = Arrays.copyOf(a, a.length); } + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public void setX(int i, int v) throws IndexOutOfBoundsException { + if (i < 0 || i >= x.length) { + throw new IndexOutOfBoundsException(); } + x[i] = v; + } + + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G10 { + + private final static String TESTCASE = + "getter + similarly named field"; + + public int prop, Prop, setProp, getProp; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getProp() { return X; } + public void setProp(int v) { prop = Prop = setProp = getProp = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class S10 { + + private final static String TESTCASE = + "setter + similarly named field"; + + public int prop, Prop, setProp, getProp; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getProp() { return x; } + public void setProp(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G11 { + + private final static String TESTCASE = + "getter + similarly named field of other type"; + + public Object prop, Prop, setProp, getProp; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getProp() { return X; } + public void setProp(int v) { prop = Prop = setProp = getProp = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class S11 { + + private final static String TESTCASE = + "setter + similarly named field of other type"; + + public String prop, Prop, setProp, getProp; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getProp() { return x; } + public void setProp(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132163 + public static class G12 { + + private final static String TESTCASE = + "getter having wrapper class return type"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public Integer getProp() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132163 + public static class S12 { + + private final static String TESTCASE = + "setter with wrapper class argument type"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(Integer v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class G13 { + + private final static String TESTCASE = + "getter + overloading methods"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX() { return x; } + public int getX(boolean arg) { return (arg ? x : 0); } + public int getX(int ... dummy) { return 0; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8154756 + public static class S13 { + + private final static String TESTCASE = + "setter + overloading methods"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int v) { x = v; } + public int setX() { return (x = X); } + public void setX(int ... dummy) {} + private void setX(Object ... dummy) {} + + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + + // JDK-8132888 + public static class G14 { + + private final static String TESTCASE = "non-public getter"; + + private final int x = X; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + int getX() { return x; } // getter is not public + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132888 + public static class S14 { + + private final static String TESTCASE = "non-public setter"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + void setX(int v) { x = v; } // setter is not public + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class getX { + + private final static String TESTCASE = + "class name coincides with getter name"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX() { return x; } + public void setX(int v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class setX { + + private final static String TESTCASE = + "class name coincides with setter name"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public void setX(int v) { x = v; } + public int getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + // JDK-8132973 + public static class GS { + + private final static String TESTCASE = + "both getter and setter are annotated"; + + private int x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public int getX() { return x; } + + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + public void setX(int v) { x = v; } + + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + + + + // ---------- checks ---------- + + private static boolean check(String what, boolean v, boolean ref) { + + boolean ok = (v == ref); + if (!ok) { System.out.println( + "invalid " + what + ": " + v + ", expected: " + ref); } + return ok; + } + + private static boolean checkInfo(BeanInfo i) { + + System.out.println("checking info..."); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals(DESCRIPTION); + if (!ok) { System.out.println("invalid description: " + descr + + ", expected: " + DESCRIPTION); } + + ok &= check("isBound", d.isBound(), BOUND); + ok &= check("isExpert", d.isExpert(), EXPERT); + ok &= check("isHidden", d.isHidden(), HIDDEN); + ok &= check("isPreferred", d.isPreferred(), PREFERRED); + ok &= check("required", (boolean) d.getValue("required"), REQUIRED); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), UPDATE); + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals == null) { + System.out.println("null enumerationValues"); + return false; + } + + boolean okVals = ( + (vals.length == 3) && + vals[0].toString().equals(V_SHORT) && + vals[1].toString().equals(V) && + vals[2].toString().equals(V_NAME)); + + if (!okVals) { System.out.println("invalid enumerationValues"); } + + return (ok && okVals); + } + + private static boolean checkAlternativeInfo(BeanInfo i) { + + System.out.println("checking alternative info..."); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals(DESCRIPTION_2); + if (!ok) { System.out.println("invalid alternative description: " + + descr + ", expected: " + DESCRIPTION_2); } + + ok &= check("isBound", d.isBound(), !BOUND); + ok &= check("isExpert", d.isExpert(), !EXPERT); + ok &= check("isHidden", d.isHidden(), !HIDDEN); + ok &= check("isPreferred", d.isPreferred(), !PREFERRED); + ok &= check("required", (boolean) d.getValue("required"), !REQUIRED); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), !UPDATE); + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals != null || vals.length > 0) { + System.out.println("non-null enumerationValues"); + return false; + } + + return ok; + } + + + private static boolean checkAlternative(Class c) { + return ( + c.equals(G09.class) || + c.equals(S09.class) || + c.equals(GS.class)); + } + + + // ---------- run test ---------- + + public static void main(String[] args) throws Exception { + + Class cases[] = { + + G01.class, S01.class, + // G02.class, S02.class, // TODO: please update after 8132703 fix + // G03.class, S03.class, // TODO: please update after 8132703 fix + // G04.class, S04.class, // TODO: please update after 8132163 fix + G05.class, // S05.class, // TODO: please update after 8132163 fix + G06.class, S06.class, + G07.class, S07.class, + // G08.class, S08.class, // TODO: please update after 8132732 fix + // G09.class, S09.class, // TODO: please update after 8132732 fix + G10.class, S10.class, + G11.class, S11.class, + // G12.class, S12.class, // TODO: please update after 8132163 fix + G13.class, // S13.class, // TODO: please update after 8154756 fix + // G14.class, S14.class, // TODO: please update after 8132888 fix or + // remove these cases if it is not an issue + // GS.class, // TODO: please update after 8132973 fix + getX.class, setX.class + }; + + boolean passed = true; + + for (Class c: cases) { + + java.lang.reflect.Field f = c.getDeclaredField("TESTCASE"); + f.setAccessible(true); + String descr = f.get(c).toString(); + + System.out.println("\n" + c.getSimpleName() + " (" + descr + "):"); + BeanInfo i; + try { i = Introspector.getBeanInfo(c, Object.class); } + catch (IntrospectionException e) { throw new RuntimeException(e); } + boolean ok = checkInfo(i); + if (checkAlternative(c)) { + ok |= checkAlternativeInfo(i); + } + System.out.println(ok ? "OK" : "NOK"); + passed = passed && ok; + } + + if (!passed) { throw new RuntimeException("test failed"); } + System.out.println("\ntest passed"); + } +} From 1d0549f73ee2a3ea57234c3da05507b8ef22f4b5 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:03 -0700 Subject: [PATCH 114/225] 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 115/225] 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 116/225] 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 117/225] 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 6e60b5bc3ef83efdc0143436c3131573ea922ca6 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 21 Apr 2016 12:57:10 -0700 Subject: [PATCH 118/225] Added tag jdk-9+115 for changeset c0f1d63d6486 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index c0e2ef494a3..7781746dc33 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -360,3 +360,4 @@ fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 21274e7937bae291658d68143aca0e3ee9296db0 jdk-9+112 e980062475c10d21137051045bf95ee229db9b27 jdk-9+113 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 +4ff86e5489e4c0513dadfa69def8601c110ca5cd 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 119/225] 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 6c7656678916ff3f5c9fc70efcbb69ce76801458 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 22 Apr 2016 01:59:35 +0300 Subject: [PATCH 120/225] 8154088: [macosx] SWT does not work on JDK 9 since b65 Reviewed-by: prr --- .../sun/lwawt/macosx/CViewEmbeddedFrame.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java index 095922047fe..5fbb825a342 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java @@ -87,23 +87,22 @@ public class CViewEmbeddedFrame extends EmbeddedFrame { } } - /* + /** * Initializes the embedded frame bounds and validates a component. - * Designed to be called from the main thread - * This method should be called once from the initialization of the SWT_AWT Bridge + * Designed to be called from the main thread. This method should be called + * once from the initialization of the SWT_AWT Bridge. */ - public void validateWithBounds(final int x, final int y, final int width, final int height) { + public void validateWithBounds(final int x, final int y, final int width, + final int height) { try { - final LWWindowPeer peer = AWTAccessor.getComponentAccessor() - .getPeer(this); - LWCToolkit.invokeAndWait(new Runnable() { - @Override - public void run() { - peer.setBoundsPrivate(0, 0, width, height); - validate(); - setVisible(true); - } + LWCToolkit.invokeAndWait(() -> { + final LWWindowPeer peer = AWTAccessor.getComponentAccessor() + .getPeer(this); + peer.setBoundsPrivate(0, 0, width, height); + validate(); + setVisible(true); }, this); - } catch (InvocationTargetException ex) {} + } catch (InvocationTargetException ex) { + } } } From 2ee49b78fe6ac31d4fb992adaad702333d85c2a9 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Fri, 22 Apr 2016 10:46:08 +0200 Subject: [PATCH 121/225] 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 122/225] 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 123/225] 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 080a341e800547fdcd7f6749ec3e0169c3da9efc Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Mon, 25 Apr 2016 15:37:31 +0300 Subject: [PATCH 124/225] 8145547: [AWT/Swing] Conditional support for GTK 3 on Linux Reviewed-by: prr, alexsch --- jdk/make/mapfiles/libawt_xawt/mapfile-vers | 1 + .../sun/java/swing/plaf/gtk/GTKEngine.java | 20 +- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 33 +- .../sun/java/swing/plaf/gtk/GTKPainter.java | 55 +- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 21 +- .../unix/classes/sun/awt/UNIXToolkit.java | 71 +- .../classes/sun/awt/X11/XDesktopPeer.java | 9 +- .../classes/sun/awt/X11/XTaskbarPeer.java | 9 +- .../unix/classes/sun/awt/X11/XToolkit.java | 3 +- .../unix/native/libawt_xawt/awt/awt_Robot.c | 72 +- .../native/libawt_xawt/awt/awt_UNIXToolkit.c | 92 +- .../native/libawt_xawt/awt/gtk2_interface.c | 405 ++- .../native/libawt_xawt/awt/gtk2_interface.h | 512 +-- .../native/libawt_xawt/awt/gtk3_interface.c | 2881 +++++++++++++++++ .../native/libawt_xawt/awt/gtk3_interface.h | 577 ++++ .../native/libawt_xawt/awt/gtk_interface.c | 158 + .../native/libawt_xawt/awt/gtk_interface.h | 560 ++++ .../awt/sun_awt_X11_GtkFileDialogPeer.c | 80 +- .../native/libawt_xawt/awt/swing_GTKEngine.c | 141 +- .../native/libawt_xawt/awt/swing_GTKStyle.c | 37 +- .../native/libawt_xawt/xawt/awt_Desktop.c | 14 +- .../native/libawt_xawt/xawt/awt_Taskbar.c | 35 +- .../native/libawt_xawt/xawt/awt_Taskbar.h | 2 +- .../native/libawt_xawt/xawt/gnome_interface.h | 4 +- 24 files changed, 4862 insertions(+), 930 deletions(-) create mode 100644 jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c create mode 100644 jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h create mode 100644 jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c create mode 100644 jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h diff --git a/jdk/make/mapfiles/libawt_xawt/mapfile-vers b/jdk/make/mapfiles/libawt_xawt/mapfile-vers index 2b18bd42e6f..b56fad43b4f 100644 --- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers +++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers @@ -179,6 +179,7 @@ SUNWprivate_1.1 { Java_sun_awt_UNIXToolkit_load_1gtk_1icon; Java_sun_awt_UNIXToolkit_nativeSync; Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl; + Java_sun_awt_UNIXToolkit_get_1gtk_1version; Java_java_awt_AWTEvent_initIDs; Java_java_awt_event_InputEvent_initIDs; Java_java_awt_event_KeyEvent_initIDs; diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index f52982a4461..940b0107a93 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.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 @@ -158,8 +158,8 @@ class GTKEngine { int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int synthState, int dir); private native void native_paint_slider( - int widgetType, int state, int shadowType, String detail, - int x, int y, int width, int height, int orientation); + int widgetType, int state, int shadowType, String detail, int x, + int y, int width, int height, int orientation, boolean hasFocus); private native void native_paint_vline( int widgetType, int state, String detail, int x, int y, int width, int height); @@ -491,6 +491,14 @@ class GTKEngine { int gtkState = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int synthState = context.getComponentState(); + Container parent = context.getComponent().getParent(); + if(GTKLookAndFeel.is3()) { + if (parent != null && parent.getParent() instanceof JComboBox) { + if (parent.getParent().hasFocus()) { + synthState |= SynthConstants.FOCUSED; + } + } + } int dir = getTextDirection(context); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail, @@ -498,13 +506,13 @@ class GTKEngine { } public void paintSlider(Graphics g, SynthContext context, - Region id, int state, ShadowType shadowType, String detail, - int x, int y, int w, int h, Orientation orientation) { + Region id, int state, ShadowType shadowType, String detail, int x, + int y, int w, int h, Orientation orientation, boolean hasFocus) { state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_slider(widget, state, shadowType.ordinal(), detail, - x - x0, y - y0, w, h, orientation.ordinal()); + x - x0, y - y0, w, h, orientation.ordinal(), hasFocus); } public void paintVline(Graphics g, SynthContext context, diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 199806d133a..f568f6a4bae 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.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 @@ -54,7 +54,8 @@ import sun.swing.SwingUtilities2; */ @SuppressWarnings("serial") // Superclass not serializable public class GTKLookAndFeel extends SynthLookAndFeel { - private static final boolean IS_22; + private static boolean IS_22; + private static boolean IS_3; /** * Whether or not text is drawn antialiased. This keys off the @@ -107,17 +108,6 @@ public class GTKLookAndFeel extends SynthLookAndFeel { private static String gtkThemeName = "Default"; static { - // Backup for specifying the version, this isn't currently documented. - // If you pass in anything but 2.2 you got the 2.0 colors/look. - String version = AccessController.doPrivileged( - new GetPropertyAction("swing.gtk.version")); - if (version != null) { - IS_22 = version.equals("2.2"); - } - else { - IS_22 = true; - } - String language = Locale.getDefault().getLanguage(); boolean cjkLocale = (Locale.CHINESE.getLanguage().equals(language) || @@ -158,6 +148,10 @@ public class GTKLookAndFeel extends SynthLookAndFeel { return IS_22; } + static boolean is3() { + return IS_3; + } + /** * Maps a swing constant to a GTK constant. */ @@ -1460,6 +1454,19 @@ public class GTKLookAndFeel extends SynthLookAndFeel { throw new InternalError("Unable to load native GTK libraries"); } + if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) { + String version = AccessController.doPrivileged( + new GetPropertyAction("jdk.gtk.version")); + if (version != null) { + IS_22 = version.equals("2.2"); + } else { + IS_22 = true; + } + } else if (UNIXToolkit.getGtkVersion() == + UNIXToolkit.GtkVersions.GTK3) { + IS_3 = true; + } + super.initialize(); inInitialize = true; loadStyles(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index ecd319a337f..a607d4c41d4 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -768,6 +768,15 @@ class GTKPainter extends SynthPainter { // The ubuntulooks engine paints slider troughs differently depending // on the current slider value and its component orientation. JSlider slider = (JSlider)context.getComponent(); + if (GTKLookAndFeel.is3()) { + if (slider.getOrientation() == JSlider.VERTICAL) { + y += 1; + h -= 2; + } else { + x += 1; + w -= 2; + } + } double value = slider.getValue(); double min = slider.getMinimum(); double max = slider.getMaximum(); @@ -801,15 +810,19 @@ class GTKPainter extends SynthPainter { Region id = context.getRegion(); int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); + boolean hasFocus = GTKLookAndFeel.is3() && + ((context.getComponentState() & SynthConstants.FOCUSED) != 0); synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) { + if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir, + hasFocus)) { Orientation orientation = (dir == JSlider.HORIZONTAL ? Orientation.HORIZONTAL : Orientation.VERTICAL); String detail = (dir == JSlider.HORIZONTAL ? "hscale" : "vscale"); ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir); ENGINE.paintSlider(g, context, id, gtkState, - ShadowType.OUT, detail, x, y, w, h, orientation); + ShadowType.OUT, detail, x, y, w, h, orientation, + hasFocus); ENGINE.finishPainting(); } } @@ -988,15 +1001,21 @@ class GTKPainter extends SynthPainter { int yThickness = style.getYThickness(); ENGINE.startPainting(g, x, y, w, h, id, state); + if (GTKLookAndFeel.is3()) { + ENGINE.paintBackground(g, context, id, gtkState, null, + x, y, w, h); + } ENGINE.paintShadow(g, context, id, gtkState, ShadowType.IN, "entry", x, y, w, h); - ENGINE.paintFlatBox(g, context, id, - gtkState, ShadowType.NONE, "entry_bg", - x + xThickness, - y + yThickness, - w - (2 * xThickness), - h - (2 * yThickness), - ColorType.TEXT_BACKGROUND); + if (!GTKLookAndFeel.is3()) { + ENGINE.paintFlatBox(g, context, id, + gtkState, ShadowType.NONE, "entry_bg", + x + xThickness, + y + yThickness, + w - (2 * xThickness), + h - (2 * yThickness), + ColorType.TEXT_BACKGROUND); + } if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) { if (!interiorFocus) { @@ -1007,14 +1026,14 @@ class GTKPainter extends SynthPainter { } else { if (containerParent instanceof JComboBox) { x += (focusSize + 2); - y += (focusSize + 1); - w -= (2 * focusSize + 1); - h -= (2 * focusSize + 2); + y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1); + w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1); + h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2); } else { - x += focusSize; - y += focusSize; - w -= 2 * focusSize; - h -= 2 * focusSize; + x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0); + y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 ); + w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); + h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); } } ENGINE.paintFocus(g, context, id, gtkState, @@ -1163,8 +1182,8 @@ class GTKPainter extends SynthPainter { Orientation orientation = (dir == JScrollBar.HORIZONTAL ? Orientation.HORIZONTAL : Orientation.VERTICAL); ENGINE.setRangeValue(context, id, value, min, max, visible); - ENGINE.paintSlider(g, context, id, gtkState, - ShadowType.OUT, "slider", x, y, w, h, orientation); + ENGINE.paintSlider(g, context, id, gtkState, ShadowType.OUT, + "slider", x, y, w, h, orientation, false); ENGINE.finishPainting(); } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index fe54752cef6..2c60551dd04 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.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 @@ -715,29 +715,33 @@ class GTKStyle extends SynthStyle implements GTKConstants { if (region == Region.COMBO_BOX || region == Region.DESKTOP_PANE || region == Region.DESKTOP_ICON || - region == Region.EDITOR_PANE || - region == Region.FORMATTED_TEXT_FIELD || region == Region.INTERNAL_FRAME || region == Region.LIST || region == Region.MENU_BAR || region == Region.PANEL || - region == Region.PASSWORD_FIELD || region == Region.POPUP_MENU || region == Region.PROGRESS_BAR || region == Region.ROOT_PANE || region == Region.SCROLL_PANE || - region == Region.SPINNER || region == Region.SPLIT_PANE_DIVIDER || region == Region.TABLE || region == Region.TEXT_AREA || - region == Region.TEXT_FIELD || - region == Region.TEXT_PANE || region == Region.TOOL_BAR_DRAG_WINDOW || region == Region.TOOL_TIP || region == Region.TREE || region == Region.VIEWPORT) { return true; } + if (!GTKLookAndFeel.is3()) { + if (region == Region.EDITOR_PANE || + region == Region.FORMATTED_TEXT_FIELD || + region == Region.PASSWORD_FIELD || + region == Region.SPINNER || + region == Region.TEXT_FIELD || + region == Region.TEXT_PANE) { + return true; + } + } Component c = context.getComponent(); String name = c.getName(); if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") { @@ -848,6 +852,8 @@ class GTKStyle extends SynthStyle implements GTKConstants { int focusPad = getClassSpecificIntValue(context, "focus-padding", 1); return indicatorSpacing + focusSize + focusPad; + } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) { + return true; } // Is it a stock icon ? @@ -1127,6 +1133,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { static { CLASS_SPECIFIC_MAP = new HashMap(); CLASS_SPECIFIC_MAP.put("Slider.thumbHeight", "slider-width"); + CLASS_SPECIFIC_MAP.put("Slider.thumbWidth", "slider-length"); CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border"); CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size"); CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size"); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index ecee8ade0bc..4e60992f314 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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,12 @@ import static java.awt.RenderingHints.*; import java.awt.color.ColorSpace; import java.awt.image.*; import java.security.AccessController; +import java.security.PrivilegedAction; + import sun.security.action.GetIntegerAction; import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection; import sun.java2d.opengl.OGLRenderQueue; +import sun.security.action.GetPropertyAction; public abstract class UNIXToolkit extends SunToolkit { @@ -42,6 +45,40 @@ public abstract class UNIXToolkit extends SunToolkit private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 }; private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000; + // Allowed GTK versions + public enum GtkVersions { + ANY(0), + GTK2(Constants.GTK2_MAJOR_NUMBER), + GTK3(Constants.GTK3_MAJOR_NUMBER); + + static class Constants { + static final int GTK2_MAJOR_NUMBER = 2; + static final int GTK3_MAJOR_NUMBER = 3; + } + + final int number; + + GtkVersions(int number) { + this.number = number; + } + + public static GtkVersions getVersion(int number) { + switch (number) { + case Constants.GTK2_MAJOR_NUMBER: + return GTK2; + case Constants.GTK3_MAJOR_NUMBER: + return GTK3; + default: + return ANY; + } + } + + // major GTK version number + public int getNumber() { + return number; + } + }; + private Boolean nativeGTKAvailable; private Boolean nativeGTKLoaded; private BufferedImage tmpImage = null; @@ -79,7 +116,7 @@ public abstract class UNIXToolkit extends SunToolkit return nativeGTKAvailable; } else { - boolean success = check_gtk(); + boolean success = check_gtk(getEnabledGtkVersion().getNumber()); nativeGTKAvailable = success; return success; } @@ -97,7 +134,8 @@ public abstract class UNIXToolkit extends SunToolkit public boolean loadGTK() { synchronized (GTK_LOCK) { if (nativeGTKLoaded == null) { - nativeGTKLoaded = load_gtk(); + nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(), + isGtkVerbose()); } } return nativeGTKLoaded; @@ -241,14 +279,15 @@ public abstract class UNIXToolkit extends SunToolkit tmpImage = new BufferedImage(colorModel, raster, false, null); } - private static native boolean check_gtk(); - private static native boolean load_gtk(); + private static native boolean check_gtk(int version); + private static native boolean load_gtk(int version, boolean verbose); private static native boolean unload_gtk(); private native boolean load_gtk_icon(String filename); private native boolean load_stock_icon(int widget_type, String stock_id, int iconSize, int textDirection, String detail); private native void nativeSync(); + private static native int get_gtk_version(); @Override public void sync() { @@ -338,4 +377,26 @@ public abstract class UNIXToolkit extends SunToolkit } return false; } + + public static GtkVersions getEnabledGtkVersion() { + String version = AccessController.doPrivileged( + new GetPropertyAction("jdk.gtk.version")); + if (version == null) { + return GtkVersions.ANY; + } else if (version.startsWith("2")) { + return GtkVersions.GTK2; + } else if("3".equals(version) ){ + return GtkVersions.GTK3; + } + return GtkVersions.ANY; + } + + public static GtkVersions getGtkVersion() { + return GtkVersions.getVersion(get_gtk_version()); + } + + public static boolean isGtkVerbose() { + return AccessController.doPrivileged((PrivilegedAction)() + -> Boolean.getBoolean("jdk.gtk.verbose")); + } } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java index 72a34cf85f8..b3d1c559442 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, 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 @@ -26,6 +26,8 @@ package sun.awt.X11; +import sun.awt.UNIXToolkit; + import java.io.File; import java.io.IOException; import java.net.MalformedURLException; @@ -57,7 +59,8 @@ public class XDesktopPeer implements DesktopPeer { XToolkit.awtLock(); try { if (!initExecuted) { - nativeLibraryLoaded = init(); + nativeLibraryLoaded = init(UNIXToolkit.getEnabledGtkVersion() + .ordinal(), UNIXToolkit.isGtkVerbose()); } } finally { initExecuted = true; @@ -123,5 +126,5 @@ public class XDesktopPeer implements DesktopPeer { } private native boolean gnome_url_show(byte[] url); - private static native boolean init(); + private static native boolean init(int gtkVersion, boolean verbose); } 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 fa23ae0b66e..58b9559652a 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,6 +29,8 @@ import java.awt.PopupMenu; import java.awt.Taskbar.Feature; import java.awt.peer.TaskbarPeer; import java.awt.event.ActionEvent; + +import sun.awt.UNIXToolkit; import java.security.AccessController; import sun.security.action.GetPropertyAction; @@ -45,7 +47,9 @@ final class XTaskbarPeer implements TaskbarPeer { if (!initExecuted) { String dname = AccessController.doPrivileged( new GetPropertyAction("java.desktop.appName", "")); - nativeLibraryLoaded = init(dname); + nativeLibraryLoaded = init(dname, + UNIXToolkit.getEnabledGtkVersion().ordinal(), + UNIXToolkit.isGtkVerbose()); if (nativeLibraryLoaded) { Thread t = new Thread(null, () -> { runloop(); }, "TaskBar", 0, false); @@ -147,7 +151,8 @@ final class XTaskbarPeer implements TaskbarPeer { } } - private static native boolean init(String name); + private static native boolean init(String name, int version, + boolean verbose); private static native void runloop(); 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 aa460f9f636..770244c964a 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 @@ -1144,7 +1144,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { public FileDialogPeer createFileDialog(FileDialog target) { FileDialogPeer peer = null; // The current GtkFileChooser is available from GTK+ 2.4 - if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) { + if (!getSunAwtDisableGtkFileDialogs() && + (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) { peer = new GtkFileDialogPeer(target); } else { peer = new XFileDialogPeer(target); diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c index b066844ca74..91ad2515a8a 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c @@ -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 @@ -44,7 +44,7 @@ #include "wsutils.h" #include "list.h" #include "multiVis.h" -#include "gtk2_interface.h" +#include "gtk_interface.h" #if defined(__linux__) || defined(MACOSX) #include @@ -263,70 +263,10 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, int index; if (isGtkSupported) { - GdkPixbuf *pixbuf; - (*fp_gdk_threads_enter)(); - GdkWindow *root = (*fp_gdk_get_default_root_window)(); - - pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, - x, y, 0, 0, width, height); - if (pixbuf && scale != 1) { - GdkPixbuf *scaledPixbuf; - x /= scale; - y /= scale; - width /= scale; - height /= scale; - dx /= scale; - dy /= scale; - scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height, - GDK_INTERP_BILINEAR); - (*fp_g_object_unref)(pixbuf); - pixbuf = scaledPixbuf; - } - - if (pixbuf) { - int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - - if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width - && (*fp_gdk_pixbuf_get_height)(pixbuf) == height - && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 - && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB - && nchan >= 3 - ) { - guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - - ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); - if (!ary) { - (*fp_g_object_unref)(pixbuf); - (*fp_gdk_threads_leave)(); - AWT_UNLOCK(); - return; - } - - for (_y = 0; _y < height; _y++) { - for (_x = 0; _x < width; _x++) { - p = pix + _y * stride + _x * nchan; - - index = (_y + dy) * jwidth + (_x + dx); - ary[index] = 0xff000000 - | (p[0] << 16) - | (p[1] << 8) - | (p[2]); - - } - } - (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); - if ((*env)->ExceptionCheck(env)) { - (*fp_g_object_unref)(pixbuf); - (*fp_gdk_threads_leave)(); - AWT_UNLOCK(); - return; - } - gtk_failed = FALSE; - } - (*fp_g_object_unref)(pixbuf); - } - (*fp_gdk_threads_leave)(); + gtk->gdk_threads_enter(); + gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width, + jwidth, height, dx, dy, scale); + gtk->gdk_threads_leave(); } if (gtk_failed) { diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c index c8b29f3bdcc..81e3423feec 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -34,7 +34,7 @@ #ifndef HEADLESS #include "awt.h" -#include "gtk2_interface.h" +#include "gtk_interface.h" #endif /* !HEADLESS */ @@ -45,13 +45,12 @@ static jmethodID icon_upcall_method = NULL; /* * Class: sun_awt_UNIXToolkit * Method: check_gtk - * Signature: ()Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL -Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass) -{ +Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) { #ifndef HEADLESS - return (jboolean)gtk2_check_version(); + return (jboolean)gtk_check_version(version); #else return JNI_FALSE; #endif /* !HEADLESS */ @@ -61,13 +60,13 @@ Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass) /* * Class: sun_awt_UNIXToolkit * Method: load_gtk - * Signature: ()Z + * Signature: (I)Z */ JNIEXPORT jboolean JNICALL -Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass) -{ +Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version, + jboolean verbose) { #ifndef HEADLESS - return (jboolean)gtk2_load(env); + return (jboolean)gtk_load(env, version, verbose); #else return JNI_FALSE; #endif /* !HEADLESS */ @@ -83,16 +82,14 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass) { #ifndef HEADLESS - return (jboolean)gtk2_unload(); + return (jboolean)gtk->unload(); #else return JNI_FALSE; #endif /* !HEADLESS */ } -jboolean _icon_upcall(JNIEnv *env, jobject this, GdkPixbuf *pixbuf) +jboolean init_method(JNIEnv *env, jobject this) { - jboolean result = JNI_FALSE; - if (this_class == NULL) { this_class = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, this)); @@ -100,33 +97,7 @@ jboolean _icon_upcall(JNIEnv *env, jobject this, GdkPixbuf *pixbuf) "loadIconCallback", "([BIIIIIZ)V"); CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE); } - - if (pixbuf != NULL) - { - guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - int width = (*fp_gdk_pixbuf_get_width)(pixbuf); - int height = (*fp_gdk_pixbuf_get_height)(pixbuf); - int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); - int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); - - /* Copy the data array into a Java structure so we can pass it back. */ - jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), - (jbyte *)pixbuf_data); - - /* Release the pixbuf. */ - (*fp_g_object_unref)(pixbuf); - - /* Call the callback method to create the image on the Java side. */ - (*env)->CallVoidMethod(env, this, icon_upcall_method, data, - width, height, row_stride, bps, channels, alpha); - result = JNI_TRUE; - } - return result; + return JNI_TRUE; } /* @@ -144,7 +115,6 @@ Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this, int len; char *filename_str = NULL; GError **error = NULL; - GdkPixbuf *pixbuf; if (filename == NULL) { @@ -158,13 +128,17 @@ Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this, JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError"); return JNI_FALSE; } + if (!init_method(env, this) ) { + return JNI_FALSE; + } (*env)->GetStringUTFRegion(env, filename, 0, len, filename_str); - pixbuf = (*fp_gdk_pixbuf_new_from_file)(filename_str, error); + jboolean result = gtk->get_file_icon_data(env, filename_str, error, + icon_upcall_method, this); /* Release the strings we've allocated. */ free(filename_str); - return _icon_upcall(env, this, pixbuf); + return result; #else /* HEADLESS */ return JNI_FALSE; #endif /* !HEADLESS */ @@ -186,7 +160,6 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, int len; char *stock_id_str = NULL; char *detail_str = NULL; - GdkPixbuf *pixbuf; if (stock_id == NULL) { @@ -215,8 +188,12 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, (*env)->GetStringUTFRegion(env, detail, 0, len, detail_str); } - pixbuf = gtk2_get_stock_icon(widget_type, stock_id_str, icon_size, - text_direction, detail_str); + if (!init_method(env, this) ) { + return JNI_FALSE; + } + jboolean result = gtk->get_icon_data(env, widget_type, stock_id_str, + icon_size, text_direction, detail_str, + icon_upcall_method, this); /* Release the strings we've allocated. */ free(stock_id_str); @@ -224,8 +201,7 @@ Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, { free(detail_str); } - - return _icon_upcall(env, this, pixbuf); + return result; #else /* HEADLESS */ return JNI_FALSE; #endif /* !HEADLESS */ @@ -279,11 +255,25 @@ Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv *env, jobject this, { char *ret; - ret = fp_gtk_check_version(major, minor, micro); + ret = gtk->gtk_check_version(major, minor, micro); if (ret == NULL) { return TRUE; } - free(ret); return FALSE; } + +/* + * Class: sun_awt_UNIXToolkit + * Method: get_gtk_version + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass) +{ +#ifndef HEADLESS + return gtk ? gtk->version : GTK_ANY; +#else + return GTK_ANY; +#endif /* !HEADLESS */ +} diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index ef58feccd9b..672a8414d8d 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -35,52 +35,18 @@ #include #include "awt.h" -#define GTK2_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0") -#define GTK2_LIB JNI_LIB_NAME("gtk-x11-2.0") #define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0") #define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0") -#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0) -#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1) -#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2) -#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3) -#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4) -#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5) -#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6) -#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7) -#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8) -#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9) -#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10) -#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11) -#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12) -#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13) -#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14) -#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15) -#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16) -#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17) -#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18) -#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19) -#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) - #define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) #define G_TYPE_FUNDAMENTAL_SHIFT (2) #define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define CONV_BUFFER_SIZE 128 #define NO_SYMBOL_EXCEPTION 1 -/* SynthConstants */ -const gint ENABLED = 1 << 0; -const gint MOUSE_OVER = 1 << 1; -const gint PRESSED = 1 << 2; -const gint DISABLED = 1 << 3; -const gint FOCUSED = 1 << 8; -const gint SELECTED = 1 << 9; -const gint DEFAULT = 1 << 10; - static void *gtk2_libhandle = NULL; static void *gthread_libhandle = NULL; @@ -105,54 +71,6 @@ static char convertionBuffer[CONV_BUFFER_SIZE]; static gboolean new_combo = TRUE; const char ENV_PREFIX[] = "GTK_MODULES="; -/*******************/ -enum GtkWidgetType -{ - _GTK_ARROW_TYPE, - _GTK_BUTTON_TYPE, - _GTK_CHECK_BUTTON_TYPE, - _GTK_CHECK_MENU_ITEM_TYPE, - _GTK_COLOR_SELECTION_DIALOG_TYPE, - _GTK_COMBO_BOX_TYPE, - _GTK_COMBO_BOX_ARROW_BUTTON_TYPE, - _GTK_COMBO_BOX_TEXT_FIELD_TYPE, - _GTK_CONTAINER_TYPE, - _GTK_ENTRY_TYPE, - _GTK_FRAME_TYPE, - _GTK_HANDLE_BOX_TYPE, - _GTK_HPANED_TYPE, - _GTK_HPROGRESS_BAR_TYPE, - _GTK_HSCALE_TYPE, - _GTK_HSCROLLBAR_TYPE, - _GTK_HSEPARATOR_TYPE, - _GTK_IMAGE_TYPE, - _GTK_MENU_TYPE, - _GTK_MENU_BAR_TYPE, - _GTK_MENU_ITEM_TYPE, - _GTK_NOTEBOOK_TYPE, - _GTK_LABEL_TYPE, - _GTK_RADIO_BUTTON_TYPE, - _GTK_RADIO_MENU_ITEM_TYPE, - _GTK_SCROLLED_WINDOW_TYPE, - _GTK_SEPARATOR_MENU_ITEM_TYPE, - _GTK_SEPARATOR_TOOL_ITEM_TYPE, - _GTK_SPIN_BUTTON_TYPE, - _GTK_TEXT_VIEW_TYPE, - _GTK_TOGGLE_BUTTON_TYPE, - _GTK_TOOLBAR_TYPE, - _GTK_TOOLTIP_TYPE, - _GTK_TREE_VIEW_TYPE, - _GTK_VIEWPORT_TYPE, - _GTK_VPANED_TYPE, - _GTK_VPROGRESS_BAR_TYPE, - _GTK_VSCALE_TYPE, - _GTK_VSCROLLBAR_TYPE, - _GTK_VSEPARATOR_TYPE, - _GTK_WINDOW_TYPE, - _GTK_DIALOG_TYPE, - _GTK_WIDGET_TYPE_SIZE -}; - static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; @@ -359,20 +277,6 @@ static void (*fp_gtk_widget_size_request)(GtkWidget *widget, static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); /* Method bodies */ -const char *getStrFor(JNIEnv *env, jstring val) -{ - int length = (*env)->GetStringLength(env, val); - if (length > CONV_BUFFER_SIZE-1) - { - length = CONV_BUFFER_SIZE-1; -#ifdef DEBUG - fprintf(stderr, "Note: Detail is too long: %d chars\n", length); -#endif /* DEBUG */ - } - - (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer); - return convertionBuffer; -} static void throw_exception(JNIEnv *env, const char* name, const char* message) { @@ -408,33 +312,34 @@ static void* dl_symbol_gthread(const char* name) return result; } -gboolean gtk2_check_version() +gboolean gtk2_check(const char* lib_name, int flags) { if (gtk2_libhandle != NULL) { /* We've already successfully opened the GTK libs, so return true. */ return TRUE; } else { void *lib = NULL; - gboolean result = FALSE; - lib = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); + lib = dlopen(lib_name, flags); + if (lib == NULL) { - lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL); - if (lib == NULL) { - return FALSE; - } + return FALSE; + } + + if (flags & RTLD_NOLOAD) { + return TRUE; } fp_gtk_check_version = dlsym(lib, "gtk_check_version"); /* Check for GTK 2.2+ */ if (!fp_gtk_check_version(2, 2, 0)) { - result = TRUE; + return TRUE; } // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065 // dlclose(lib); - return result; + return FALSE; } } @@ -450,7 +355,7 @@ do { \ } while(0); -void update_supported_actions(JNIEnv *env) { +static void update_supported_actions(JNIEnv *env) { GVfs * (*fp_g_vfs_get_default) (void); const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); const gchar * const * schemes = NULL; @@ -513,7 +418,7 @@ void update_supported_actions(JNIEnv *env) { /** * Functions for awt_Desktop.c */ -gboolean gtk2_show_uri_load(JNIEnv *env) { +static gboolean gtk2_show_uri_load(JNIEnv *env) { gboolean success = FALSE; dlerror(); const char *gtk_version = fp_gtk_check_version(2, 14, 0); @@ -547,7 +452,7 @@ gboolean gtk2_show_uri_load(JNIEnv *env) { /** * Functions for sun_awt_X11_GtkFileDialogPeer.c */ -void gtk2_file_chooser_load() +static void gtk2_file_chooser_load() { fp_gtk_file_chooser_get_filename = dl_symbol( "gtk_file_chooser_get_filename"); @@ -576,7 +481,7 @@ void gtk2_file_chooser_load() fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid"); } -gboolean gtk2_load(JNIEnv *env) +GtkApi* gtk2_load(JNIEnv *env, const char* lib_name) { gboolean result; int i; @@ -584,11 +489,9 @@ gboolean gtk2_load(JNIEnv *env) int (*io_handler)(); char *gtk_modules_env; - gtk2_libhandle = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); + gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); if (gtk2_libhandle == NULL) { - gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gtk2_libhandle == NULL) - return FALSE; + return FALSE; } gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); @@ -962,8 +865,12 @@ gboolean gtk2_load(JNIEnv *env) { gtk2_widgets[i] = NULL; } - - return result; + if (result) { + GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); + gtk2_init(gtk); + return gtk; + } + return NULL; } int gtk2_unload() @@ -1007,7 +914,7 @@ int gtk2_unload() /* Dispatch all pending events from the GTK event loop. * This is needed to catch theme change and update widgets' style. */ -void flush_gtk_event_loop() +static void flush_gtk_event_loop() { while( (*fp_g_main_context_iteration)(NULL, FALSE)); } @@ -1056,7 +963,7 @@ static void init_containers() * comparing results. This can be optimized by using subclassed pixmap and * doing the second drawing only if necessary. */ -void gtk2_init_painting(JNIEnv *env, gint width, gint height) +static void gtk2_init_painting(JNIEnv *env, gint width, gint height) { GdkGC *gc; GdkPixbuf *white, *black; @@ -1116,7 +1023,7 @@ void gtk2_init_painting(JNIEnv *env, gint width, gint height) * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and * java_awt_Transparency_TRANSLUCENT. */ -gint gtk2_copy_image(gint *dst, gint width, gint height) +static gint gtk2_copy_image(gint *dst, gint width, gint height) { gint i, j, r, g, b; guchar *white, *black; @@ -1778,7 +1685,7 @@ void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, x, y, w, h); } -void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gint synth_state, GtkTextDirection dir) @@ -1948,7 +1855,7 @@ void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, x, y, width, height, gap_side, gap_x, gap_width); } -void gtk2_paint_check(WidgetType widget_type, gint synth_state, +static void gtk2_paint_check(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); @@ -1965,7 +1872,7 @@ void gtk2_paint_check(WidgetType widget_type, gint synth_state, x, y, width, height); } -void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height) { @@ -1978,7 +1885,7 @@ void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, x, y, width, height); } -void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkExpanderStyle expander_style) { @@ -1991,7 +1898,7 @@ void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, x + width / 2, y + height / 2, expander_style); } -void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkPositionType gap_side) { @@ -2004,7 +1911,7 @@ void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, x, y, width, height, gap_side); } -void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gboolean has_focus) { @@ -2023,7 +1930,7 @@ void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, x, y, width, height); } -void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, const char *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2033,7 +1940,7 @@ void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, NULL, gtk2_widget, detail, x, y, width, height); } -void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, GtkOrientation orientation) { @@ -2046,7 +1953,7 @@ void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, x, y, width, height, orientation); } -void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2056,7 +1963,7 @@ void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, NULL, gtk2_widget, detail, x, x + width, y); } -void gtk2_paint_option(WidgetType widget_type, gint synth_state, +static void gtk2_paint_option(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); @@ -2073,7 +1980,7 @@ void gtk2_paint_option(WidgetType widget_type, gint synth_state, x, y, width, height); } -void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, gint x, gint y, gint width, gint height, gint synth_state, GtkTextDirection dir) @@ -2123,9 +2030,10 @@ void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); } -void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation) + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus) { gtk2_widget = gtk2_get_widget(widget_type); (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type, @@ -2136,7 +2044,7 @@ void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, x, y, width, height, orientation); } -void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, +static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, const gchar *detail, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2146,7 +2054,7 @@ void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, NULL, gtk2_widget, detail, y, y + height, x); } -void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, +static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, gint x, gint y, gint width, gint height) { gtk2_widget = gtk2_get_widget(widget_type); @@ -2156,7 +2064,7 @@ void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height); } -GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, +static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, GtkIconSize size, GtkTextDirection direction, const char *detail) { init_containers(); @@ -2166,8 +2074,52 @@ GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail); } +static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, + jmethodID icon_upcall_method, jobject this) { + if (!pixbuf) { + return JNI_FALSE; + } + guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + if (pixbuf_data) { + int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + int width = (*fp_gdk_pixbuf_get_width)(pixbuf); + int height = (*fp_gdk_pixbuf_get_height)(pixbuf); + int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); + int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); + + jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), + (jbyte *)pixbuf_data); + (*fp_g_object_unref)(pixbuf); + + /* Call the callback method to create the image on the Java side. */ + (*env)->CallVoidMethod(env, this, icon_upcall_method, data, + width, height, row_stride, bps, channels, alpha); + return JNI_TRUE; + } + return JNI_FALSE; +} + +static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); + return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size, + direction, detail); + return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + /*************************************************/ -gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) +static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2176,7 +2128,7 @@ gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) return style->xthickness; } -gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) +static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2186,12 +2138,12 @@ gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) } /*************************************************/ -guint8 recode_color(guint16 channel) +static guint8 recode_color(guint16 channel) { return (guint8)(channel>>8); } -gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, +static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, GtkStateType state_type, ColorType color_type) { gint result = 0; @@ -2243,19 +2195,19 @@ gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, } /*************************************************/ -jobject create_Boolean(JNIEnv *env, jboolean boolean_value); -jobject create_Integer(JNIEnv *env, jint int_value); -jobject create_Long(JNIEnv *env, jlong long_value); -jobject create_Float(JNIEnv *env, jfloat float_value); -jobject create_Double(JNIEnv *env, jdouble double_value); -jobject create_Character(JNIEnv *env, jchar char_value); -jobject create_Insets(JNIEnv *env, GtkBorder *border); +static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); +static jobject create_Integer(JNIEnv *env, jint int_value); +static jobject create_Long(JNIEnv *env, jlong long_value); +static jobject create_Float(JNIEnv *env, jfloat float_value); +static jobject create_Double(JNIEnv *env, jdouble double_value); +static jobject create_Character(JNIEnv *env, jchar char_value); +static jobject create_Insets(JNIEnv *env, GtkBorder *border); -jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey) +static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, + const char* key) { init_containers(); - const char* key = getStrFor(env, jkey); gtk2_widget = gtk2_get_widget(widget_type); GValue value; @@ -2376,7 +2328,7 @@ jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey) return NULL; } -void gtk2_set_range_value(WidgetType widget_type, jdouble value, +static void gtk2_set_range_value(WidgetType widget_type, jdouble value, jdouble min, jdouble max, jdouble visible) { GtkAdjustment *adj; @@ -2391,7 +2343,7 @@ void gtk2_set_range_value(WidgetType widget_type, jdouble value, } /*************************************************/ -jobject create_Object(JNIEnv *env, jmethodID *cid, +static jobject create_Object(JNIEnv *env, jmethodID *cid, const char* class_name, const char* signature, jvalue* value) @@ -2494,7 +2446,7 @@ jobject create_Insets(JNIEnv *env, GtkBorder *border) } /*********************************************/ -jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) +static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) { init_containers(); @@ -2513,7 +2465,7 @@ jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) } /***********************************************/ -jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { jobject result = NULL; gchar* strval = NULL; @@ -2525,21 +2477,21 @@ jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key return result; } -jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { gint intval = NULL; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Integer(env, intval); } -jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) +static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { gint intval = NULL; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Boolean(env, intval); } -jobject gtk2_get_setting(JNIEnv *env, Setting property) +static jobject gtk2_get_setting(JNIEnv *env, Setting property) { GtkSettings* settings = (*fp_gtk_settings_get_default)(); @@ -2557,3 +2509,148 @@ jobject gtk2_get_setting(JNIEnv *env, Setting property) return NULL; } + +static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x, + jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) { + GdkPixbuf *pixbuf; + jint *ary; + + GdkWindow *root = (*fp_gdk_get_default_root_window)(); + + pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y, + 0, 0, width, height); + if (pixbuf && scale != 1) { + GdkPixbuf *scaledPixbuf; + x /= scale; + y /= scale; + width /= scale; + height /= scale; + dx /= scale; + dy /= scale; + scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height, + GDK_INTERP_BILINEAR); + (*fp_g_object_unref)(pixbuf); + pixbuf = scaledPixbuf; + } + + if (pixbuf) { + int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + + if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width + && (*fp_gdk_pixbuf_get_height)(pixbuf) == height + && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 + && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB + && nchan >= 3 + ) { + guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + + ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); + if (ary) { + jint _x, _y; + int index; + for (_y = 0; _y < height; _y++) { + for (_x = 0; _x < width; _x++) { + p = pix + _y * stride + _x * nchan; + + index = (_y + dy) * jwidth + (_x + dx); + ary[index] = 0xff000000 + | (p[0] << 16) + | (p[1] << 8) + | (p[2]); + + } + } + (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); + } + } + (*fp_g_object_unref)(pixbuf); + } + return JNI_FALSE; +} + +static GdkWindow* gtk2_get_window(void *widget) { + return ((GtkWidget*)widget)->window; +} + +void gtk2_init(GtkApi* gtk) { + gtk->version = GTK_2; + + gtk->show_uri_load = >k2_show_uri_load; + gtk->unload = >k2_unload; + gtk->flush_event_loop = &flush_gtk_event_loop; + gtk->gtk_check_version = fp_gtk_check_version; + gtk->get_setting = >k2_get_setting; + + gtk->paint_arrow = >k2_paint_arrow; + gtk->paint_box = >k2_paint_box; + gtk->paint_box_gap = >k2_paint_box_gap; + gtk->paint_expander = >k2_paint_expander; + gtk->paint_extension = >k2_paint_extension; + gtk->paint_flat_box = >k2_paint_flat_box; + gtk->paint_focus = >k2_paint_focus; + gtk->paint_handle = >k2_paint_handle; + gtk->paint_hline = >k2_paint_hline; + gtk->paint_vline = >k2_paint_vline; + gtk->paint_option = >k2_paint_option; + gtk->paint_shadow = >k2_paint_shadow; + gtk->paint_slider = >k2_paint_slider; + gtk->paint_background = >k_paint_background; + gtk->paint_check = >k2_paint_check; + gtk->set_range_value = >k2_set_range_value; + + gtk->init_painting = >k2_init_painting; + gtk->copy_image = >k2_copy_image; + + gtk->get_xthickness = >k2_get_xthickness; + gtk->get_ythickness = >k2_get_ythickness; + gtk->get_color_for_state = >k2_get_color_for_state; + gtk->get_class_value = >k2_get_class_value; + + gtk->get_pango_font_name = >k2_get_pango_font_name; + gtk->get_icon_data = >k2_get_icon_data; + gtk->get_file_icon_data = >k2_get_file_icon_data; + gtk->gdk_threads_enter = fp_gdk_threads_enter; + gtk->gdk_threads_leave = fp_gdk_threads_leave; + gtk->gtk_show_uri = fp_gtk_show_uri; + gtk->get_drawable_data = >k2_get_drawable_data; + gtk->g_free = fp_g_free; + + gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; + gtk->gtk_widget_hide = fp_gtk_widget_hide; + gtk->gtk_main_quit = fp_gtk_main_quit; + gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; + gtk->gtk_file_chooser_set_current_folder = + fp_gtk_file_chooser_set_current_folder; + gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; + gtk->gtk_file_chooser_set_current_name = + fp_gtk_file_chooser_set_current_name; + gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; + gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; + gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; + gtk->gtk_file_filter_new = fp_gtk_file_filter_new; + gtk->gtk_file_chooser_set_do_overwrite_confirmation = + fp_gtk_file_chooser_set_do_overwrite_confirmation; + gtk->gtk_file_chooser_set_select_multiple = + fp_gtk_file_chooser_set_select_multiple; + gtk->gtk_file_chooser_get_current_folder = + fp_gtk_file_chooser_get_current_folder; + gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; + gtk->gtk_g_slist_length = fp_gtk_g_slist_length; + gtk->g_signal_connect_data = fp_g_signal_connect_data; + gtk->gtk_widget_show = fp_gtk_widget_show; + gtk->gtk_main = fp_gtk_main; + gtk->gtk_main_level = fp_gtk_main_level; + gtk->g_path_get_dirname = fp_g_path_get_dirname; + gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; + gtk->gtk_widget_destroy = fp_gtk_widget_destroy; + gtk->gtk_window_present = fp_gtk_window_present; + gtk->gtk_window_move = fp_gtk_window_move; + gtk->gtk_window_resize = fp_gtk_window_resize; + gtk->get_window = >k2_get_window; + + gtk->g_object_unref = fp_g_object_unref; + gtk->g_list_append = fp_g_list_append; + gtk->g_list_free = fp_g_list_free; + gtk->g_list_free_full = fp_g_list_free_full; +} diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h index c94749ecb51..b405e070f43 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h @@ -28,232 +28,11 @@ #include #include #include - -#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip) -#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type)) -#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ()) -#define GTK_FILE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser)) -#define fp_g_signal_connect(instance, detailed_signal, c_handler, data) \ - fp_g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0) -#define G_CALLBACK(f) ((GCallback) (f)) -#define G_TYPE_FUNDAMENTAL_SHIFT (2) -#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) -#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) -#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject)) -#define GTK_STOCK_CANCEL "gtk-cancel" -#define GTK_STOCK_SAVE "gtk-save" -#define GTK_STOCK_OPEN "gtk-open" -#define GDK_CURRENT_TIME 0L - -typedef enum _WidgetType -{ - BUTTON, /* GtkButton */ - CHECK_BOX, /* GtkCheckButton */ - CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */ - COLOR_CHOOSER, /* GtkColorSelectionDialog */ - COMBO_BOX, /* GtkComboBox */ - COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */ - COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */ - DESKTOP_ICON, /* GtkLabel */ - DESKTOP_PANE, /* GtkContainer */ - EDITOR_PANE, /* GtkTextView */ - FORMATTED_TEXT_FIELD, /* GtkEntry */ - HANDLE_BOX, /* GtkHandleBox */ - HPROGRESS_BAR, /* GtkProgressBar */ - HSCROLL_BAR, /* GtkHScrollbar */ - HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */ - HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */ - HSCROLL_BAR_TRACK, /* GtkHScrollbar */ - HSCROLL_BAR_THUMB, /* GtkHScrollbar */ - HSEPARATOR, /* GtkHSeparator */ - HSLIDER, /* GtkHScale */ - HSLIDER_TRACK, /* GtkHScale */ - HSLIDER_THUMB, /* GtkHScale */ - HSPLIT_PANE_DIVIDER, /* GtkHPaned */ - INTERNAL_FRAME, /* GtkWindow */ - INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */ - IMAGE, /* GtkImage */ - LABEL, /* GtkLabel */ - LIST, /* GtkTreeView */ - MENU, /* GtkMenu */ - MENU_BAR, /* GtkMenuBar */ - MENU_ITEM, /* GtkMenuItem */ - MENU_ITEM_ACCELERATOR, /* GtkLabel */ - OPTION_PANE, /* GtkMessageDialog */ - PANEL, /* GtkContainer */ - PASSWORD_FIELD, /* GtkEntry */ - POPUP_MENU, /* GtkMenu */ - POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */ - RADIO_BUTTON, /* GtkRadioButton */ - RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */ - ROOT_PANE, /* GtkContainer */ - SCROLL_PANE, /* GtkScrolledWindow */ - SPINNER, /* GtkSpinButton */ - SPINNER_ARROW_BUTTON, /* GtkSpinButton */ - SPINNER_TEXT_FIELD, /* GtkSpinButton */ - SPLIT_PANE, /* GtkPaned */ - TABBED_PANE, /* GtkNotebook */ - TABBED_PANE_TAB_AREA, /* GtkNotebook */ - TABBED_PANE_CONTENT, /* GtkNotebook */ - TABBED_PANE_TAB, /* GtkNotebook */ - TABLE, /* GtkTreeView */ - TABLE_HEADER, /* GtkButton */ - TEXT_AREA, /* GtkTextView */ - TEXT_FIELD, /* GtkEntry */ - TEXT_PANE, /* GtkTextView */ - TITLED_BORDER, /* GtkFrame */ - TOGGLE_BUTTON, /* GtkToggleButton */ - TOOL_BAR, /* GtkToolbar */ - TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */ - TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */ - TOOL_TIP, /* GtkWindow */ - TREE, /* GtkTreeView */ - TREE_CELL, /* GtkTreeView */ - VIEWPORT, /* GtkViewport */ - VPROGRESS_BAR, /* GtkProgressBar */ - VSCROLL_BAR, /* GtkVScrollbar */ - VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */ - VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */ - VSCROLL_BAR_TRACK, /* GtkVScrollbar */ - VSCROLL_BAR_THUMB, /* GtkVScrollbar */ - VSEPARATOR, /* GtkVSeparator */ - VSLIDER, /* GtkVScale */ - VSLIDER_TRACK, /* GtkVScale */ - VSLIDER_THUMB, /* GtkVScale */ - VSPLIT_PANE_DIVIDER, /* GtkVPaned */ - WIDGET_TYPE_SIZE -} WidgetType; - -typedef enum _ColorType -{ - FOREGROUND, - BACKGROUND, - TEXT_FOREGROUND, - TEXT_BACKGROUND, - FOCUS, - LIGHT, - DARK, - MID, - BLACK, - WHITE -} ColorType; - -typedef enum _Setting -{ - GTK_FONT_NAME, - GTK_ICON_SIZES, - GTK_CURSOR_BLINK, - GTK_CURSOR_BLINK_TIME -} Setting; - -/* GTK types, here to eliminate need for GTK headers at compile time */ - -#ifndef FALSE -#define FALSE (0) -#define TRUE (!FALSE) -#endif +#include "gtk_interface.h" #define GTK_HAS_FOCUS (1 << 12) #define GTK_HAS_DEFAULT (1 << 14) - -/* basic types */ -typedef char gchar; -typedef short gshort; -typedef int gint; -typedef long glong; -typedef float gfloat; -typedef double gdouble; -typedef void* gpointer; -typedef gint gboolean; - -typedef signed char gint8; -typedef signed short gint16; -typedef signed int gint32; - -typedef unsigned char guchar; -typedef unsigned char guint8; -typedef unsigned short gushort; -typedef unsigned short guint16; -typedef unsigned int guint; -typedef unsigned int guint32; -typedef unsigned int gsize; -typedef unsigned long gulong; - -typedef signed long long gint64; -typedef unsigned long long guint64; - -/* enumerated constants */ -typedef enum -{ - GTK_ARROW_UP, - GTK_ARROW_DOWN, - GTK_ARROW_LEFT, - GTK_ARROW_RIGHT -} GtkArrowType; - -typedef enum { - GDK_COLORSPACE_RGB -} GdkColorspace; - -typedef enum -{ - GTK_EXPANDER_COLLAPSED, - GTK_EXPANDER_SEMI_COLLAPSED, - GTK_EXPANDER_SEMI_EXPANDED, - GTK_EXPANDER_EXPANDED -} GtkExpanderStyle; - -typedef enum -{ - GTK_ICON_SIZE_INVALID, - GTK_ICON_SIZE_MENU, - GTK_ICON_SIZE_SMALL_TOOLBAR, - GTK_ICON_SIZE_LARGE_TOOLBAR, - GTK_ICON_SIZE_BUTTON, - GTK_ICON_SIZE_DND, - GTK_ICON_SIZE_DIALOG -} GtkIconSize; - -typedef enum -{ - GTK_ORIENTATION_HORIZONTAL, - GTK_ORIENTATION_VERTICAL -} GtkOrientation; - -typedef enum -{ - GTK_POS_LEFT, - GTK_POS_RIGHT, - GTK_POS_TOP, - GTK_POS_BOTTOM -} GtkPositionType; - -typedef enum -{ - GTK_SHADOW_NONE, - GTK_SHADOW_IN, - GTK_SHADOW_OUT, - GTK_SHADOW_ETCHED_IN, - GTK_SHADOW_ETCHED_OUT -} GtkShadowType; - -typedef enum -{ - GTK_STATE_NORMAL, - GTK_STATE_ACTIVE, - GTK_STATE_PRELIGHT, - GTK_STATE_SELECTED, - GTK_STATE_INSENSITIVE -} GtkStateType; - -typedef enum -{ - GTK_TEXT_DIR_NONE, - GTK_TEXT_DIR_LTR, - GTK_TEXT_DIR_RTL -} GtkTextDirection; - typedef enum { GTK_WINDOW_TOPLEVEL, @@ -270,41 +49,15 @@ typedef enum G_PARAM_PRIVATE = 1 << 5 } GParamFlags; -typedef enum { - GDK_INTERP_NEAREST, - GDK_INTERP_TILES, - GDK_INTERP_BILINEAR, - GDK_INTERP_HYPER -} GdkInterpType; - /* We define all structure pointers to be void* */ -typedef void GError; typedef void GMainContext; typedef void GVfs; -typedef struct _GSList GSList; -struct _GSList -{ - gpointer data; - GSList *next; -}; - -typedef struct _GList GList; - -struct _GList -{ - gpointer data; - GList *next; - GList *prev; -}; - typedef void GdkColormap; typedef void GdkDrawable; typedef void GdkGC; -typedef void GdkScreen; typedef void GdkPixbuf; typedef void GdkPixmap; -typedef void GdkWindow; typedef void GtkFixed; typedef void GtkMenuItem; @@ -364,7 +117,6 @@ typedef struct { * structures. This is a place where getting rid of gtk * headers may be dangerous. ******************************************************/ -typedef gulong GType; typedef struct { @@ -599,70 +351,9 @@ struct _GtkProgressBar guint ellipsize : 3; }; -typedef enum { - GTK_RESPONSE_NONE = -1, - GTK_RESPONSE_REJECT = -2, - GTK_RESPONSE_ACCEPT = -3, - GTK_RESPONSE_DELETE_EVENT = -4, - GTK_RESPONSE_OK = -5, - GTK_RESPONSE_CANCEL = -6, - GTK_RESPONSE_CLOSE = -7, - GTK_RESPONSE_YES = -8, - GTK_RESPONSE_NO = -9, - GTK_RESPONSE_APPLY = -10, - GTK_RESPONSE_HELP = -11 -} GtkResponseType; - -typedef struct _GtkWindow GtkWindow; - -typedef struct _GtkFileChooser GtkFileChooser; - -typedef enum { - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER -} GtkFileChooserAction; - -typedef struct _GtkFileFilter GtkFileFilter; - -typedef enum { - GTK_FILE_FILTER_FILENAME = 1 << 0, - GTK_FILE_FILTER_URI = 1 << 1, - GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, - GTK_FILE_FILTER_MIME_TYPE = 1 << 3 -} GtkFileFilterFlags; - -typedef struct { - GtkFileFilterFlags contains; - const gchar *filename; - const gchar *uri; - const gchar *display_name; - const gchar *mime_type; -} GtkFileFilterInfo; - -typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, - gpointer data); - -typedef void (*GDestroyNotify)(gpointer data); - -typedef void (*GCallback)(void); - -typedef struct _GClosure GClosure; - -typedef void (*GClosureNotify)(gpointer data, GClosure *closure); - -typedef enum { - G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1 -} GConnectFlags; typedef struct _GThreadFunctions GThreadFunctions; -/* - * Converts java.lang.String object to UTF-8 character string. - */ -const char *getStrFor(JNIEnv *env, jstring value); - /** * Returns : * NULL if the GLib library is compatible with the given version, or a string @@ -670,7 +361,7 @@ const char *getStrFor(JNIEnv *env, jstring value); * Please note that the glib_check_version() is available since 2.6, * so you should use GLIB_CHECK_VERSION macro instead. */ -gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, +static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, guint required_micro); /** @@ -680,193 +371,96 @@ gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, #define GLIB_CHECK_VERSION(major, minor, micro) \ (fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL) -/* - * Check whether the gtk2 library is available and meets the minimum - * version requirement. If the library is already loaded this method has no - * effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_check_version(); - /** * Returns : * NULL if the GTK+ library is compatible with the given version, or a string * describing the version mismatch. */ -gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, +static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, guint required_micro); -/* - * Load the gtk2 library. If the library is already loaded this method has no - * effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_load(JNIEnv *env); -/* - * Loads fp_gtk_show_uri function pointer. This initialization is - * separated because the function is required only - * for java.awt.Desktop API. The function relies on initialization in - * gtk2_load, so it must be invoked only after a successful gtk2_load - * invocation - */ -gboolean gtk2_show_uri_load(JNIEnv *env); +static void gtk2_init(GtkApi* gtk); -/* - * Unload the gtk2 library. If the library is already unloaded this method has - * no effect and returns success. - * Returns FALSE on failure and TRUE on success. - */ -gboolean gtk2_unload(); +static void (*fp_g_free)(gpointer mem); +static void (*fp_g_object_unref)(gpointer object); +static GdkWindow *(*fp_gdk_get_default_root_window) (void); -void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkArrowType arrow_type, gboolean fill); -void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir); -void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width); -void gtk2_paint_check(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height); -void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height, - GtkExpanderStyle expander_style); -void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side); -void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, gboolean has_focus); -void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, - const char *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_option(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir); -void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height); -void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, - gint x, gint y, gint width, gint height); +static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); +static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); +static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); +static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); +static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); -void gtk2_init_painting(JNIEnv *env, gint w, gint h); -gint gtk2_copy_image(gint *dest, gint width, gint height); - -gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type); -gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type); -gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, - GtkStateType state_type, ColorType color_type); -jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring key); - -GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, - GtkIconSize size, GtkTextDirection direction, const char *detail); -GdkPixbuf *gtk2_get_icon(const gchar *filename, gint size); -jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type); - -void flush_gtk_event_loop(); - -jobject gtk2_get_setting(JNIEnv *env, Setting property); - -void gtk2_set_range_value(WidgetType widget_type, jdouble value, - jdouble min, jdouble max, jdouble visible); - -void (*fp_g_free)(gpointer mem); -void (*fp_g_object_unref)(gpointer object); -GdkWindow *(*fp_gdk_get_default_root_window) (void); - -int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); -guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); -gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); -int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); -GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); -GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); - -GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, +static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y, int dest_x, int dest_y, int width, int height); -GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, +static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, int dest_width, int dest_heigh, GdkInterpType interp_type); -void (*fp_gtk_widget_destroy)(GtkWidget *widget); -void (*fp_gtk_window_present)(GtkWindow *window); -void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); -void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); +static void (*fp_gtk_widget_destroy)(void *widget); +static void (*fp_gtk_window_present)(GtkWindow *window); +static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); +static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); /** * Function Pointers for GtkFileChooser */ -gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); -void (*fp_gtk_widget_hide)(GtkWidget *widget); -void (*fp_gtk_main_quit)(void); -GtkWidget* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, +static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +static void (*fp_gtk_widget_hide)(void *widget); +static void (*fp_gtk_main_quit)(void); +static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); -gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, +static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename); -gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, +static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, const char *filename); -void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, +static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name); -void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, +static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); -void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, +static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -GType (*fp_gtk_file_chooser_get_type)(void); -GtkFileFilter* (*fp_gtk_file_filter_new)(void); -void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( +static GType (*fp_gtk_file_chooser_get_type)(void); +static GtkFileFilter* (*fp_gtk_file_filter_new)(void); +static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( GtkFileChooser *chooser, gboolean do_overwrite_confirmation); -void (*fp_gtk_file_chooser_set_select_multiple)( +static void (*fp_gtk_file_chooser_set_select_multiple)( GtkFileChooser *chooser, gboolean select_multiple); -gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); -GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -guint (*fp_gtk_g_slist_length)(GSList *list); -gulong (*fp_g_signal_connect_data)(gpointer instance, +static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); +static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static guint (*fp_gtk_g_slist_length)(GSList *list); +static gulong (*fp_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); -void (*fp_gtk_widget_show)(GtkWidget *widget); -void (*fp_gtk_main)(void); -guint (*fp_gtk_main_level)(void); -gchar* (*fp_g_path_get_dirname) (const gchar *file_name); -XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); +static void (*fp_gtk_widget_show)(void *widget); +static void (*fp_gtk_main)(void); +static guint (*fp_gtk_main_level)(void); +static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); +static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); - -GList* (*fp_g_list_append) (GList *list, gpointer data); -void (*fp_g_list_free) (GList *list); -void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); +static GList* (*fp_g_list_append) (GList *list, gpointer data); +static void (*fp_g_list_free) (GList *list); +static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); /** * This function is available for GLIB > 2.20, so it MUST be * called within GLIB_CHECK_VERSION(2, 20, 0) check. */ -gboolean (*fp_g_thread_get_initialized)(void); +static gboolean (*fp_g_thread_get_initialized)(void); -void (*fp_g_thread_init)(GThreadFunctions *vtable); -void (*fp_gdk_threads_init)(void); -void (*fp_gdk_threads_enter)(void); -void (*fp_gdk_threads_leave)(void); +static void (*fp_g_thread_init)(GThreadFunctions *vtable); +static void (*fp_gdk_threads_init)(void); +static void (*fp_gdk_threads_enter)(void); +static void (*fp_gdk_threads_leave)(void); -gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, +static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, guint32 timestamp, GError **error); #endif /* !_GTK2_INTERFACE_H */ diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c new file mode 100644 index 00000000000..385c8015046 --- /dev/null +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -0,0 +1,2881 @@ +/* + * 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 + * 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 +#include +#include +#include +#include +#include "gtk3_interface.h" +#include "java_awt_Transparency.h" +#include "sizecalc.h" +#include +#include +#include "awt.h" + +static void *gtk3_libhandle = NULL; + +static jmp_buf j; + +/* Widgets */ +static GtkWidget *gtk3_widget = NULL; +static GtkWidget *gtk3_window = NULL; +static GtkFixed *gtk3_fixed = NULL; +static GtkStyleProvider *gtk3_css = NULL; + +/* Paint system */ +static cairo_surface_t *surface = NULL; +static cairo_t *cr = NULL; + +static const char ENV_PREFIX[] = "GTK_MODULES="; + +static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE]; + +static void throw_exception(JNIEnv *env, const char* name, const char* message) +{ + jclass class = (*env)->FindClass(env, name); + + if (class != NULL) + (*env)->ThrowNew(env, class, message); + + (*env)->DeleteLocalRef(env, class); +} + +static void gtk3_add_state(GtkWidget *widget, GtkStateType state) { + GtkStateType old_state = fp_gtk_widget_get_state(widget); + fp_gtk_widget_set_state(widget, old_state | state); +} + +static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) { + GtkStateType old_state = fp_gtk_widget_get_state(widget); + fp_gtk_widget_set_state(widget, old_state & ~state); +} + +/* This is a workaround for the bug: + * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 + * (dlsym/dlopen clears dlerror state) + * This bug is specific to Linux, but there is no harm in + * applying this workaround on Solaris as well. + */ +static void* dl_symbol(const char* name) +{ + void* result = dlsym(gtk3_libhandle, name); + if (!result) + longjmp(j, NO_SYMBOL_EXCEPTION); + + return result; +} + +gboolean gtk3_check(const char* lib_name, int flags) +{ + if (gtk3_libhandle != NULL) { + /* We've already successfully opened the GTK libs, so return true. */ + return TRUE; + } else { + return dlopen(lib_name, flags) != NULL; + } +} + +#define ADD_SUPPORTED_ACTION(actionStr) \ +do { \ + jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \ + "Ljava/awt/Desktop$Action;"); \ + if (!(*env)->ExceptionCheck(env)) { \ + jobject action = (*env)->GetStaticObjectField(env, cls_action, \ + fld_action); \ + (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, \ + action); \ + } else { \ + (*env)->ExceptionClear(env); \ + } \ +} while(0); + + +static void update_supported_actions(JNIEnv *env) { + GVfs * (*fp_g_vfs_get_default) (void); + const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); + const gchar * const * schemes = NULL; + + jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); + CHECK_NULL(cls_action); + jclass cls_xDesktopPeer = (*env)-> + FindClass(env, "sun/awt/X11/XDesktopPeer"); + CHECK_NULL(cls_xDesktopPeer); + jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, + cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); + CHECK_NULL(fld_supportedActions); + jobject supportedActions = (*env)->GetStaticObjectField(env, + cls_xDesktopPeer, fld_supportedActions); + + jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); + CHECK_NULL(cls_arrayList); + jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", + "(Ljava/lang/Object;)Z"); + CHECK_NULL(mid_arrayListAdd); + jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, + "clear", "()V"); + CHECK_NULL(mid_arrayListClear); + + (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); + + ADD_SUPPORTED_ACTION("OPEN"); + + /** + * gtk_show_uri() documentation says: + * + * > you need to install gvfs to get support for uri schemes such as http:// + * > or ftp://, as only local files are handled by GIO itself. + * + * So OPEN action was safely added here. + * However, it looks like Solaris 11 have gvfs support only for 32-bit + * applications only by default. + */ + + fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); + fp_g_vfs_get_supported_uri_schemes = + dl_symbol("g_vfs_get_supported_uri_schemes"); + dlerror(); + + if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { + GVfs * vfs = fp_g_vfs_get_default(); + schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; + if (schemes) { + int i = 0; + while (schemes[i]) { + if (strcmp(schemes[i], "http") == 0) { + ADD_SUPPORTED_ACTION("BROWSE"); + ADD_SUPPORTED_ACTION("MAIL"); + break; + } + i++; + } + } + } else { +#ifdef DEBUG + fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); +#endif /* DEBUG */ + } + +} +/** + * Functions for awt_Desktop.c + */ +static gboolean gtk3_show_uri_load(JNIEnv *env) { + gboolean success = FALSE; + dlerror(); + fp_gtk_show_uri = dl_symbol("gtk_show_uri"); + const char *dlsym_error = dlerror(); + if (dlsym_error) { +#ifdef DEBUG + fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); +#endif /* DEBUG */ + } else if (fp_gtk_show_uri == NULL) { +#ifdef DEBUG + fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); +#endif /* DEBUG */ + } else { + update_supported_actions(env); + success = TRUE; + } + return success; +} + +/** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ +static void gtk3_file_chooser_load() +{ + fp_gtk_file_chooser_get_filename = dl_symbol( + "gtk_file_chooser_get_filename"); + fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); + fp_gtk_file_chooser_set_current_folder = dl_symbol( + "gtk_file_chooser_set_current_folder"); + fp_gtk_file_chooser_set_filename = dl_symbol( + "gtk_file_chooser_set_filename"); + fp_gtk_file_chooser_set_current_name = dl_symbol( + "gtk_file_chooser_set_current_name"); + fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); + fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); + fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); + fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); + fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( + "gtk_file_chooser_set_do_overwrite_confirmation"); + fp_gtk_file_chooser_set_select_multiple = dl_symbol( + "gtk_file_chooser_set_select_multiple"); + fp_gtk_file_chooser_get_current_folder = dl_symbol( + "gtk_file_chooser_get_current_folder"); + fp_gtk_file_chooser_get_filenames = dl_symbol( + "gtk_file_chooser_get_filenames"); + fp_gtk_g_slist_length = dl_symbol("g_slist_length"); + fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid"); +} + +static void empty() {} + +static gboolean gtk3_version_3_10 = TRUE; +static gboolean gtk3_version_3_14 = FALSE; + +GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) +{ + gboolean result; + int i; + int (*handler)(); + int (*io_handler)(); + char *gtk_modules_env; + gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); + if (gtk3_libhandle == NULL) { + return FALSE; + } + + if (setjmp(j) == 0) + { + fp_gtk_check_version = dl_symbol("gtk_check_version"); + + /* GLib */ + fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version"); + if (!fp_glib_check_version) { + dlerror(); + } + fp_g_free = dl_symbol("g_free"); + fp_g_object_unref = dl_symbol("g_object_unref"); + + fp_g_main_context_iteration = + dl_symbol("g_main_context_iteration"); + + fp_g_value_init = dl_symbol("g_value_init"); + fp_g_type_is_a = dl_symbol("g_type_is_a"); + fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); + fp_g_value_get_char = dl_symbol("g_value_get_char"); + fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); + fp_g_value_get_int = dl_symbol("g_value_get_int"); + fp_g_value_get_uint = dl_symbol("g_value_get_uint"); + fp_g_value_get_long = dl_symbol("g_value_get_long"); + fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); + fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); + fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); + fp_g_value_get_float = dl_symbol("g_value_get_float"); + fp_g_value_get_double = dl_symbol("g_value_get_double"); + fp_g_value_get_string = dl_symbol("g_value_get_string"); + fp_g_value_get_enum = dl_symbol("g_value_get_enum"); + fp_g_value_get_flags = dl_symbol("g_value_get_flags"); + fp_g_value_get_param = dl_symbol("g_value_get_param"); + fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); + fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); + + fp_g_object_get = dl_symbol("g_object_get"); + fp_g_object_set = dl_symbol("g_object_set"); + + fp_g_str_has_prefix = dl_symbol("g_str_has_prefix"); + fp_g_strsplit = dl_symbol("g_strsplit"); + fp_g_strfreev = dl_symbol("g_strfreev"); + + /* GDK */ + fp_gdk_get_default_root_window = + dl_symbol("gdk_get_default_root_window"); + + /* Pixbuf */ + fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); + fp_gdk_pixbuf_new_from_file = + dl_symbol("gdk_pixbuf_new_from_file"); + fp_gdk_pixbuf_get_from_drawable = + dl_symbol("gdk_pixbuf_get_from_window"); + fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); + fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); + fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); + fp_gdk_pixbuf_get_rowstride = + dl_symbol("gdk_pixbuf_get_rowstride"); + fp_gdk_pixbuf_get_has_alpha = + dl_symbol("gdk_pixbuf_get_has_alpha"); + fp_gdk_pixbuf_get_bits_per_sample = + dl_symbol("gdk_pixbuf_get_bits_per_sample"); + fp_gdk_pixbuf_get_n_channels = + dl_symbol("gdk_pixbuf_get_n_channels"); + fp_gdk_pixbuf_get_colorspace = + dl_symbol("gdk_pixbuf_get_colorspace"); + + fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create"); + fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy"); + fp_cairo_create = dl_symbol("cairo_create"); + fp_cairo_destroy = dl_symbol("cairo_destroy"); + fp_cairo_fill = dl_symbol("cairo_fill"); + fp_cairo_rectangle = dl_symbol("cairo_rectangle"); + fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb"); + fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba"); + fp_cairo_surface_flush = dl_symbol("cairo_surface_flush"); + fp_cairo_paint = dl_symbol("cairo_paint"); + fp_cairo_clip = dl_symbol("cairo_clip"); + fp_cairo_image_surface_get_data = + dl_symbol("cairo_image_surface_get_data"); + fp_cairo_image_surface_get_stride = + dl_symbol("cairo_image_surface_get_stride"); + + fp_gdk_pixbuf_get_from_surface = + dl_symbol("gdk_pixbuf_get_from_surface"); + + fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state"); + fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state"); + + fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus"); + fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation"); + fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent"); + fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window"); + + fp_gtk_widget_get_style_context = + dl_symbol("gtk_widget_get_style_context"); + fp_gtk_style_context_get_color = + dl_symbol("gtk_style_context_get_color"); + fp_gtk_style_context_get_background_color = + dl_symbol("gtk_style_context_get_background_color"); + fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags"); + fp_gtk_style_context_set_state = + dl_symbol("gtk_style_context_set_state"); + fp_gtk_style_context_add_class = + dl_symbol("gtk_style_context_add_class"); + fp_gtk_style_context_save = dl_symbol("gtk_style_context_save"); + fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore"); + fp_gtk_render_check = dl_symbol("gtk_render_check"); + fp_gtk_render_option = dl_symbol("gtk_render_option"); + fp_gtk_render_extension = dl_symbol("gtk_render_extension"); + fp_gtk_render_expander = dl_symbol("gtk_render_expander"); + fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap"); + fp_gtk_render_line = dl_symbol("gtk_render_line"); + fp_gtk_widget_render_icon_pixbuf = + dl_symbol("gtk_widget_render_icon_pixbuf"); + if (fp_gtk_check_version(3, 10, 0)) { + gtk3_version_3_10 = FALSE; + } else { + fp_gdk_window_create_similar_image_surface = + dl_symbol("gdk_window_create_similar_image_surface"); + } + gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0); + + fp_gdk_window_create_similar_surface = + dl_symbol("gdk_window_create_similar_surface"); + fp_gtk_settings_get_for_screen = + dl_symbol("gtk_settings_get_for_screen"); + fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen"); + fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named"); + fp_gtk_style_context_add_provider = + dl_symbol("gtk_style_context_add_provider"); + fp_gtk_render_frame = dl_symbol("gtk_render_frame"); + fp_gtk_render_focus = dl_symbol("gtk_render_focus"); + fp_gtk_render_handle = dl_symbol("gtk_render_handle"); + fp_gtk_render_arrow = dl_symbol("gtk_render_arrow"); + + fp_gtk_style_context_get_property = + dl_symbol("gtk_style_context_get_property"); + fp_gtk_scrolled_window_set_shadow_type = + dl_symbol("gtk_scrolled_window_set_shadow_type"); + fp_gtk_render_slider = dl_symbol("gtk_render_slider"); + fp_gtk_style_context_get_padding = + dl_symbol("gtk_style_context_get_padding"); + fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted"); + fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font"); + fp_gtk_widget_get_allocated_width = + dl_symbol("gtk_widget_get_allocated_width"); + fp_gtk_widget_get_allocated_height = + dl_symbol("gtk_widget_get_allocated_height"); + fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default"); + fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon"); + + fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower"); + fp_gtk_adjustment_set_page_increment = + dl_symbol("gtk_adjustment_set_page_increment"); + fp_gtk_adjustment_set_page_size = + dl_symbol("gtk_adjustment_set_page_size"); + fp_gtk_adjustment_set_step_increment = + dl_symbol("gtk_adjustment_set_step_increment"); + fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper"); + fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value"); + + fp_gtk_render_activity = dl_symbol("gtk_render_activity"); + fp_gtk_render_background = dl_symbol("gtk_render_background"); + fp_gtk_style_context_has_class = + dl_symbol("gtk_style_context_has_class"); + + fp_gtk_style_context_set_junction_sides = + dl_symbol("gtk_style_context_set_junction_sides"); + fp_gtk_style_context_add_region = + dl_symbol("gtk_style_context_add_region"); + + fp_gtk_init_check = dl_symbol("gtk_init_check"); + + /* GTK widgets */ + fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); + fp_gtk_button_new = dl_symbol("gtk_button_new"); + fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); + fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); + fp_gtk_check_menu_item_new = + dl_symbol("gtk_check_menu_item_new"); + fp_gtk_color_selection_dialog_new = + dl_symbol("gtk_color_selection_dialog_new"); + fp_gtk_entry_new = dl_symbol("gtk_entry_new"); + fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); + fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); + fp_gtk_image_new = dl_symbol("gtk_image_new"); + fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); + fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); + fp_gtk_scale_new = dl_symbol("gtk_scale_new"); + fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); + fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); + fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); + fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); + fp_gtk_label_new = dl_symbol("gtk_label_new"); + fp_gtk_menu_new = dl_symbol("gtk_menu_new"); + fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); + fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); + fp_gtk_menu_item_set_submenu = + dl_symbol("gtk_menu_item_set_submenu"); + fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); + fp_gtk_progress_bar_new = + dl_symbol("gtk_progress_bar_new"); + fp_gtk_progress_bar_set_orientation = + dl_symbol("gtk_orientable_set_orientation"); + fp_gtk_radio_button_new = + dl_symbol("gtk_radio_button_new"); + fp_gtk_radio_menu_item_new = + dl_symbol("gtk_radio_menu_item_new"); + fp_gtk_scrolled_window_new = + dl_symbol("gtk_scrolled_window_new"); + fp_gtk_separator_menu_item_new = + dl_symbol("gtk_separator_menu_item_new"); + fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); + fp_gtk_toggle_button_new = + dl_symbol("gtk_toggle_button_new"); + fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); + fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); + fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); + fp_gtk_window_new = dl_symbol("gtk_window_new"); + fp_gtk_window_present = dl_symbol("gtk_window_present"); + fp_gtk_window_move = dl_symbol("gtk_window_move"); + fp_gtk_window_resize = dl_symbol("gtk_window_resize"); + + fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); + fp_gtk_frame_new = dl_symbol("gtk_frame_new"); + + fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); + fp_gtk_container_add = dl_symbol("gtk_container_add"); + fp_gtk_menu_shell_append = + dl_symbol("gtk_menu_shell_append"); + fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); + fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); + fp_gtk_widget_render_icon = + dl_symbol("gtk_widget_render_icon"); + fp_gtk_widget_set_name = + dl_symbol("gtk_widget_set_name"); + fp_gtk_widget_set_parent = + dl_symbol("gtk_widget_set_parent"); + fp_gtk_widget_set_direction = + dl_symbol("gtk_widget_set_direction"); + fp_gtk_widget_style_get = + dl_symbol("gtk_widget_style_get"); + fp_gtk_widget_class_install_style_property = + dl_symbol("gtk_widget_class_install_style_property"); + fp_gtk_widget_class_find_style_property = + dl_symbol("gtk_widget_class_find_style_property"); + fp_gtk_widget_style_get_property = + dl_symbol("gtk_widget_style_get_property"); + fp_pango_font_description_to_string = + dl_symbol("pango_font_description_to_string"); + fp_gtk_settings_get_default = + dl_symbol("gtk_settings_get_default"); + fp_gtk_widget_get_settings = + dl_symbol("gtk_widget_get_settings"); + fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); + fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); + fp_gtk_widget_size_request = + dl_symbol("gtk_widget_size_request"); + fp_gtk_range_get_adjustment = + dl_symbol("gtk_range_get_adjustment"); + + fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); + fp_gtk_main_quit = dl_symbol("gtk_main_quit"); + fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); + fp_gtk_widget_show = dl_symbol("gtk_widget_show"); + fp_gtk_main = dl_symbol("gtk_main"); + + fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); + + fp_gdk_threads_enter = ∅ + fp_gdk_threads_leave = ∅ + + /** + * Functions for sun_awt_X11_GtkFileDialogPeer.c + */ + gtk3_file_chooser_load(); + + fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new"); + fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle, + "gtk_combo_box_new_with_entry"); + fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle, + "gtk_separator_tool_item_new"); + + fp_g_list_append = dl_symbol("g_list_append"); + fp_g_list_free = dl_symbol("g_list_free"); + fp_g_list_free_full = dl_symbol("g_list_free_full"); + } + /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION + * Otherwise we can check the return value of setjmp method. + */ + else + { + dlclose(gtk3_libhandle); + gtk3_libhandle = NULL; + + return NULL; + } + + /* + * Strip the AT-SPI GTK_MODULEs if present + */ + gtk_modules_env = getenv ("GTK_MODULES"); + if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") || + gtk_modules_env && strstr (gtk_modules_env, "gail")) + { + /* the new env will be smaller than the old one */ + gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, + sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); + + if (new_env != NULL ) + { + /* careful, strtok modifies its args */ + gchar *tmp_env = strdup (gtk_modules_env); + strcpy(new_env, ENV_PREFIX); + + /* strip out 'atk-bridge' and 'gail' */ + size_t PREFIX_LENGTH = strlen(ENV_PREFIX); + while (s = strtok(tmp_env, ":")) + { + if ((!strstr (s, "atk-bridge")) && (!strstr (s, "gail"))) + { + if (strlen (new_env) > PREFIX_LENGTH) { + new_env = strcat (new_env, ":"); + } + new_env = strcat(new_env, s); + } + if (tmp_env) + { + free (tmp_env); + tmp_env = NULL; /* next call to strtok arg1==NULL */ + } + } + putenv (new_env); + free (new_env); + free (tmp_env); + } + } + /* + * GTK should be initialized with gtk_init_check() before use. + * + * gtk_init_check installs its own error handlers. It is critical that + * we preserve error handler set from AWT. Otherwise we'll crash on + * BadMatch errors which we would normally ignore. The IO error handler + * is preserved here, too, just for consistency. + */ + AWT_LOCK(); + handler = XSetErrorHandler(NULL); + io_handler = XSetIOErrorHandler(NULL); + result = (*fp_gtk_init_check)(NULL, NULL); + XSetErrorHandler(handler); + XSetIOErrorHandler(io_handler); + AWT_UNLOCK(); + /* Initialize widget array. */ + for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) + { + gtk3_widgets[i] = NULL; + } + if (result) { + GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); + gtk3_init(gtk); + return gtk; + } + return NULL; +} + +static int gtk3_unload() +{ + int i; + char *gtk3_error; + + if (!gtk3_libhandle) + return TRUE; + + /* Release painting objects */ + if (surface != NULL) { + fp_cairo_destroy(cr); + fp_cairo_surface_destroy(surface); + surface = NULL; + } + + if (gtk3_window != NULL) { + /* Destroying toplevel widget will destroy all contained widgets */ + (*fp_gtk_widget_destroy)(gtk3_window); + + /* Unset some static data so they get reinitialized on next load */ + gtk3_window = NULL; + } + + dlerror(); + dlclose(gtk3_libhandle); + if ((gtk3_error = dlerror()) != NULL) + { + return FALSE; + } + return TRUE; +} + +/* Dispatch all pending events from the GTK event loop. + * This is needed to catch theme change and update widgets' style. + */ +static void flush_gtk_event_loop() +{ + while((*fp_g_main_context_iteration)(NULL)); +} + +/* + * Initialize components of containment hierarchy. This creates a GtkFixed + * inside a GtkWindow. All widgets get realized. + */ +static void init_containers() +{ + if (gtk3_window == NULL) + { + gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); + (*fp_gtk_container_add)((GtkContainer*)gtk3_window, + (GtkWidget *)gtk3_fixed); + (*fp_gtk_widget_realize)(gtk3_window); + (*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed); + + GtkSettings* settings = fp_gtk_settings_get_for_screen( + fp_gtk_widget_get_screen(gtk3_window)); + gchar* strval = NULL; + fp_g_object_get(settings, "gtk-theme-name", &strval, NULL); + gtk3_css = fp_gtk_css_provider_get_named(strval, NULL); + } +} + +/* + * Ensure everything is ready for drawing an element of the specified width + * and height. + * + * We should somehow handle translucent images. GTK can draw to X Drawables + * only, which don't support alpha. When we retrieve the image back from + * the server, translucency information is lost. There're several ways to + * work around this: + * 1) Subclass GdkPixmap and cache translucent objects on client side. This + * requires us to implement parts of X server drawing logic on client side. + * Many X requests can potentially be "translucent"; e.g. XDrawLine with + * fill=tile and a translucent tile is a "translucent" operation, whereas + * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some + * do) intermix transparent and opaque operations which makes caching even + * more problematic. + * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support + * for it (as of version 2.6). Also even in JDS 3 Xorg does not support + * these visuals by default, which makes optimizing for them pointless. + * We can consider doing this at a later point when ARGB visuals become more + * popular. + * 3') GTK has plans to use Cairo as its graphical backend (presumably in + * 2.8), and Cairo supports alpha. With it we could also get rid of the + * unnecessary round trip to server and do all the drawing on client side. + * 4) For now we draw to two different pixmaps and restore alpha channel by + * comparing results. This can be optimized by using subclassed pixmap and +*/ +static void gtk3_init_painting(JNIEnv *env, gint width, gint height) +{ + init_containers(); + + if (cr) { + fp_cairo_destroy(cr); + } + + if (surface != NULL) { + /* free old stuff */ + fp_cairo_surface_destroy(surface); + + } + + if (gtk3_version_3_10) { + surface = fp_gdk_window_create_similar_image_surface( + fp_gtk_widget_get_window(gtk3_window), + CAIRO_FORMAT_ARGB32, width, height, 1); + } else { + surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + width, height); + } + + cr = fp_cairo_create(surface); +} + +/* + * Restore image from white and black pixmaps and copy it into destination + * buffer. This method compares two pixbufs taken from white and black + * pixmaps and decodes color and alpha components. Pixbufs are RGB without + * alpha, destination buffer is ABGR. + * + * The return value is the transparency type of the resulting image, either + * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and + * java_awt_Transparency_TRANSLUCENT. + */ +static gint gtk3_copy_image(gint *dst, gint width, gint height) +{ + gint i, j, r, g, b; + guchar *data; + gint stride, padding; + + fp_cairo_surface_flush(surface); + data = (*fp_cairo_image_surface_get_data)(surface); + stride = (*fp_cairo_image_surface_get_stride)(surface); + padding = stride - width * 4; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + int r = *data++; + int g = *data++; + int b = *data++; + int a = *data++; + *dst++ = (a << 24 | b << 16 | g << 8 | r); + } + data += padding; + } + return java_awt_Transparency_TRANSLUCENT; +} + +static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir) +{ + /* + * Some engines (inexplicably) look at the direction of the widget's + * parent, so we need to set the direction of both the widget and its + * parent. + */ + (*fp_gtk_widget_set_direction)(widget, dir); + GtkWidget* parent = fp_gtk_widget_get_parent(widget); + if (parent != NULL) { + fp_gtk_widget_set_direction(parent, dir); + } +} + +/* GTK state_type filter */ +static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) +{ + GtkStateType result = GTK_STATE_NORMAL; + + if ((synth_state & DISABLED) != 0) { + result = GTK_STATE_INSENSITIVE; + } else if ((synth_state & PRESSED) != 0) { + result = GTK_STATE_ACTIVE; + } else if ((synth_state & MOUSE_OVER) != 0) { + result = GTK_STATE_PRELIGHT; + } + return result; +} + +static GtkStateFlags get_gtk_state_flags(gint synth_state) +{ + GtkStateFlags flags = 0; + + if ((synth_state & DISABLED) != 0) { + flags |= GTK_STATE_FLAG_INSENSITIVE; + } + if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) { + flags |= GTK_STATE_FLAG_ACTIVE; + } + if ((synth_state & MOUSE_OVER) != 0) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + if ((synth_state & FOCUSED) != 0) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + return flags; +} + +static GtkStateFlags get_gtk_flags(GtkStateType state_type) { + GtkStateFlags flags = 0; + switch (state_type) + { + case GTK_STATE_PRELIGHT: + flags |= GTK_STATE_FLAG_PRELIGHT; + break; + case GTK_STATE_SELECTED: + flags |= GTK_STATE_FLAG_SELECTED; + break; + case GTK_STATE_INSENSITIVE: + flags |= GTK_STATE_FLAG_INSENSITIVE; + break; + case GTK_STATE_ACTIVE: + flags |= GTK_STATE_FLAG_ACTIVE; + break; + case GTK_STATE_FOCUSED: + flags |= GTK_STATE_FLAG_FOCUSED; + break; + default: + break; + } + return flags; +} + +/* GTK shadow_type filter */ +static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, + gint synth_state) +{ + GtkShadowType result = GTK_SHADOW_OUT; + + if ((synth_state & SELECTED) != 0) { + result = GTK_SHADOW_IN; + } + return result; +} + + +static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type, + GtkShadowType shadow_type) +{ + GtkWidget *arrow = NULL; + if (NULL == gtk3_widgets[_GTK_ARROW_TYPE]) + { + gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, + shadow_type); + (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, + gtk3_widgets[_GTK_ARROW_TYPE]); + (*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]); + } + arrow = gtk3_widgets[_GTK_ARROW_TYPE]; + + (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); + return arrow; +} + +static GtkAdjustment* create_adjustment() +{ + return (GtkAdjustment *) + (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); +} + +/** + * Returns a pointer to the cached native widget for the specified widget + * type. + */ +static GtkWidget *gtk3_get_widget(WidgetType widget_type) +{ + gboolean init_result = FALSE; + GtkWidget *result = NULL; + switch (widget_type) + { + case BUTTON: + case TABLE_HEADER: + if (init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); + } + result = gtk3_widgets[_GTK_BUTTON_TYPE]; + break; + case CHECK_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] = + (*fp_gtk_check_button_new)(); + } + result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]; + break; + case CHECK_BOX_MENU_ITEM: + if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = + (*fp_gtk_check_menu_item_new)(); + } + result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; + break; + /************************************************************ + * Creation a dedicated color chooser is dangerous because + * it deadlocks the EDT + ************************************************************/ +/* case COLOR_CHOOSER: + if (init_result = + (NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) + { + gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = + (*fp_gtk_color_selection_dialog_new)(NULL); + } + result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; + break;*/ + case COMBO_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE])) + { + gtk3_widgets[_GTK_COMBO_BOX_TYPE] = + (*fp_gtk_combo_box_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_TYPE]; + break; + case COMBO_BOX_ARROW_BUTTON: + if (init_result = + (NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = + (*fp_gtk_toggle_button_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; + break; + case COMBO_BOX_TEXT_FIELD: + if (init_result = + (NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE])) + { + result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = + (*fp_gtk_entry_new)(); + } + result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; + break; + case DESKTOP_ICON: + case INTERNAL_FRAME_TITLE_PANE: + case LABEL: + if (init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE])) + { + gtk3_widgets[_GTK_LABEL_TYPE] = + (*fp_gtk_label_new)(NULL); + } + result = gtk3_widgets[_GTK_LABEL_TYPE]; + break; + case DESKTOP_PANE: + case PANEL: + case ROOT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE])) + { + /* There is no constructor for a container type. I've + * chosen GtkFixed container since it has a default + * constructor. + */ + gtk3_widgets[_GTK_CONTAINER_TYPE] = + (*fp_gtk_fixed_new)(); + } + result = gtk3_widgets[_GTK_CONTAINER_TYPE]; + break; + case EDITOR_PANE: + case TEXT_AREA: + case TEXT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE])) + { + gtk3_widgets[_GTK_TEXT_VIEW_TYPE] = + (*fp_gtk_text_view_new)(); + } + result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE]; + break; + case FORMATTED_TEXT_FIELD: + case PASSWORD_FIELD: + case TEXT_FIELD: + if (init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE])) + { + gtk3_widgets[_GTK_ENTRY_TYPE] = + (*fp_gtk_entry_new)(); + } + result = gtk3_widgets[_GTK_ENTRY_TYPE]; + break; + case HANDLE_BOX: + if (init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE])) + { + gtk3_widgets[_GTK_HANDLE_BOX_TYPE] = + (*fp_gtk_handle_box_new)(); + } + result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE]; + break; + case HSCROLL_BAR: + case HSCROLL_BAR_BUTTON_LEFT: + case HSCROLL_BAR_BUTTON_RIGHT: + case HSCROLL_BAR_TRACK: + case HSCROLL_BAR_THUMB: + if (init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE])) + { + gtk3_widgets[_GTK_HSCROLLBAR_TYPE] = + (*fp_gtk_hscrollbar_new)(create_adjustment()); + } + result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE]; + break; + case HSEPARATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE])) + { + gtk3_widgets[_GTK_HSEPARATOR_TYPE] = + (*fp_gtk_hseparator_new)(); + } + result = gtk3_widgets[_GTK_HSEPARATOR_TYPE]; + break; + case HSLIDER: + case HSLIDER_THUMB: + case HSLIDER_TRACK: + if (init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE])) + { + gtk3_widgets[_GTK_HSCALE_TYPE] = + (*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL); + } + result = gtk3_widgets[_GTK_HSCALE_TYPE]; + break; + case HSPLIT_PANE_DIVIDER: + case SPLIT_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE])) + { + gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); + } + result = gtk3_widgets[_GTK_HPANED_TYPE]; + break; + case IMAGE: + if (init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE])) + { + gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); + } + result = gtk3_widgets[_GTK_IMAGE_TYPE]; + break; + case INTERNAL_FRAME: + if (init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE])) + { + gtk3_widgets[_GTK_WINDOW_TYPE] = + (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + } + result = gtk3_widgets[_GTK_WINDOW_TYPE]; + break; + case TOOL_TIP: + if (init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE])) + { + result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); + gtk3_widgets[_GTK_TOOLTIP_TYPE] = result; + } + result = gtk3_widgets[_GTK_TOOLTIP_TYPE]; + break; + case LIST: + case TABLE: + case TREE: + case TREE_CELL: + if (init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE])) + { + gtk3_widgets[_GTK_TREE_VIEW_TYPE] = + (*fp_gtk_tree_view_new)(); + } + result = gtk3_widgets[_GTK_TREE_VIEW_TYPE]; + break; + case TITLED_BORDER: + if (init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE])) + { + gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); + } + result = gtk3_widgets[_GTK_FRAME_TYPE]; + break; + case POPUP_MENU: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE])) + { + gtk3_widgets[_GTK_MENU_TYPE] = + (*fp_gtk_menu_new)(); + } + result = gtk3_widgets[_GTK_MENU_TYPE]; + break; + case MENU: + case MENU_ITEM: + case MENU_ITEM_ACCELERATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_MENU_ITEM_TYPE] = + (*fp_gtk_menu_item_new)(); + } + result = gtk3_widgets[_GTK_MENU_ITEM_TYPE]; + break; + case MENU_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE])) + { + gtk3_widgets[_GTK_MENU_BAR_TYPE] = + (*fp_gtk_menu_bar_new)(); + } + result = gtk3_widgets[_GTK_MENU_BAR_TYPE]; + break; + case COLOR_CHOOSER: + case OPTION_PANE: + if (init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE])) + { + gtk3_widgets[_GTK_DIALOG_TYPE] = + (*fp_gtk_dialog_new)(); + } + result = gtk3_widgets[_GTK_DIALOG_TYPE]; + break; + case POPUP_MENU_SEPARATOR: + if (init_result = + (NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = + (*fp_gtk_separator_menu_item_new)(); + } + result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; + break; + case HPROGRESS_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE])) + { + gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] = + (*fp_gtk_progress_bar_new)(); + } + result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]; + break; + case VPROGRESS_BAR: + if (init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE])) + { + gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] = + (*fp_gtk_progress_bar_new)(); + /* + * Vertical JProgressBars always go bottom-to-top, + * regardless of the ComponentOrientation. + */ + (*fp_gtk_progress_bar_set_orientation)( + (GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE], + GTK_PROGRESS_BOTTOM_TO_TOP); + } + result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]; + break; + case RADIO_BUTTON: + if (init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] = + (*fp_gtk_radio_button_new)(NULL); + } + result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]; + break; + case RADIO_BUTTON_MENU_ITEM: + if (init_result = + (NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE])) + { + gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = + (*fp_gtk_radio_menu_item_new)(NULL); + } + result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; + break; + case SCROLL_PANE: + if (init_result = + (NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE])) + { + gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] = + (*fp_gtk_scrolled_window_new)(NULL, NULL); + } + result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]; + break; + case SPINNER: + case SPINNER_ARROW_BUTTON: + case SPINNER_TEXT_FIELD: + if (init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE])) + { + result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] = + (*fp_gtk_spin_button_new)(NULL, 0, 0); + } + result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]; + break; + case TABBED_PANE: + case TABBED_PANE_TAB_AREA: + case TABBED_PANE_CONTENT: + case TABBED_PANE_TAB: + if (init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE])) + { + gtk3_widgets[_GTK_NOTEBOOK_TYPE] = + (*fp_gtk_notebook_new)(NULL); + } + result = gtk3_widgets[_GTK_NOTEBOOK_TYPE]; + break; + case TOGGLE_BUTTON: + if (init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE])) + { + gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] = + (*fp_gtk_toggle_button_new)(NULL); + } + result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]; + break; + case TOOL_BAR: + case TOOL_BAR_DRAG_WINDOW: + if (init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE])) + { + gtk3_widgets[_GTK_TOOLBAR_TYPE] = + (*fp_gtk_toolbar_new)(NULL); + } + result = gtk3_widgets[_GTK_TOOLBAR_TYPE]; + break; + case TOOL_BAR_SEPARATOR: + if (init_result = + (NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE])) + { + gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = + (*fp_gtk_separator_tool_item_new)(); + } + result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; + break; + case VIEWPORT: + if (init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE])) + { + GtkAdjustment *adjustment = create_adjustment(); + gtk3_widgets[_GTK_VIEWPORT_TYPE] = + (*fp_gtk_viewport_new)(adjustment, adjustment); + } + result = gtk3_widgets[_GTK_VIEWPORT_TYPE]; + break; + case VSCROLL_BAR: + case VSCROLL_BAR_BUTTON_UP: + case VSCROLL_BAR_BUTTON_DOWN: + case VSCROLL_BAR_TRACK: + case VSCROLL_BAR_THUMB: + if (init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE])) + { + gtk3_widgets[_GTK_VSCROLLBAR_TYPE] = + (*fp_gtk_vscrollbar_new)(create_adjustment()); + } + result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE]; + break; + case VSEPARATOR: + if (init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE])) + { + gtk3_widgets[_GTK_VSEPARATOR_TYPE] = + (*fp_gtk_vseparator_new)(); + } + result = gtk3_widgets[_GTK_VSEPARATOR_TYPE]; + break; + case VSLIDER: + case VSLIDER_THUMB: + case VSLIDER_TRACK: + if (init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE])) + { + gtk3_widgets[_GTK_VSCALE_TYPE] = + (*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL); + } + result = gtk3_widgets[_GTK_VSCALE_TYPE]; + /* + * Vertical JSliders start at the bottom, while vertical + * GtkVScale widgets start at the top (by default), so to fix + * this we set the "inverted" flag to get the Swing behavior. + */ + fp_gtk_range_set_inverted((GtkRange*)result, TRUE); + break; + case VSPLIT_PANE_DIVIDER: + if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE])) + { + gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); + } + result = gtk3_widgets[_GTK_VPANED_TYPE]; + break; + default: + result = NULL; + break; + } + + if (result != NULL && init_result) + { + if (widget_type == RADIO_BUTTON_MENU_ITEM || + widget_type == CHECK_BOX_MENU_ITEM || + widget_type == MENU_ITEM || + widget_type == MENU || + widget_type == POPUP_MENU_SEPARATOR) + { + GtkWidget *menu = gtk3_get_widget(POPUP_MENU); + (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); + } + else if (widget_type == POPUP_MENU) + { + GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR); + GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); + (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); + (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); + } + else if (widget_type == COMBO_BOX_TEXT_FIELD ) + { + GtkWidget* combo = gtk3_get_widget(COMBO_BOX); + + /* + * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry + * in order to trick engines into thinking it's a real combobox + * arrow button/text field. + */ + + fp_gtk_container_add ((GtkContainer*)(combo), result); + GtkStyleContext* context = fp_gtk_widget_get_style_context (combo); + fp_gtk_style_context_add_class (context, "combobox-entry"); + context = fp_gtk_widget_get_style_context (result); + fp_gtk_style_context_add_class (context, "combobox"); + fp_gtk_style_context_add_class (context, "entry"); + } + else if (widget_type == COMBO_BOX_ARROW_BUTTON ) + { + GtkWidget* combo = gtk3_get_widget(COMBO_BOX); + fp_gtk_widget_set_parent(result, combo); + } + else if (widget_type != TOOL_TIP && + widget_type != INTERNAL_FRAME && + widget_type != OPTION_PANE) + { + (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result); + } + (*fp_gtk_widget_realize)(result); + } + return result; +} + +static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkArrowType arrow_type, gboolean fill) +{ + gdouble xx, yy, a = G_PI; + int s = width; + gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type); + + switch (widget_type) + { + case SPINNER_ARROW_BUTTON: + s = (int)(0.4 * width + 0.5) + 1; + if (arrow_type == GTK_ARROW_UP) { + a = 0; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = G_PI; + } + break; + + case HSCROLL_BAR_BUTTON_LEFT: + s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; + a = 3 * G_PI / 2; + break; + + case HSCROLL_BAR_BUTTON_RIGHT: + s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; + a = G_PI / 2; + break; + + case VSCROLL_BAR_BUTTON_UP: + s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; + a = 0; + break; + + case VSCROLL_BAR_BUTTON_DOWN: + s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; + a = G_PI; + break; + + case COMBO_BOX_ARROW_BUTTON: + s = (int)(0.3 * height + 0.5) + 1; + a = G_PI; + break; + + case TABLE: + s = (int)(0.8 * height + 0.5) + 1; + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } + break; + + case MENU_ITEM: + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } else if (arrow_type == GTK_ARROW_RIGHT) { + a = G_PI / 2; + } else if (arrow_type == GTK_ARROW_LEFT) { + a = 3 * G_PI / 2; + } + break; + + default: + if (arrow_type == GTK_ARROW_UP) { + a = G_PI; + } else if (arrow_type == GTK_ARROW_DOWN) { + a = 0; + } else if (arrow_type == GTK_ARROW_RIGHT) { + a = G_PI / 2; + } else if (arrow_type == GTK_ARROW_LEFT) { + a = 3 * G_PI / 2; + } + break; + } + + if (s < width && s < height) { + xx = x + (0.5 * (width - s) + 0.5); + yy = y + (0.5 * (height - s) + 0.5); + } else { + xx = x; + yy = y; + } + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + + if (detail != NULL) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + fp_gtk_style_context_set_state (context, flags); + + (*fp_gtk_render_arrow)(context, cr, a, xx, yy, s); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + if (widget_type == HSLIDER_TRACK) { + /* + * For horizontal JSliders with right-to-left orientation, we need + * to set the "inverted" flag to match the native GTK behavior where + * the foreground highlight is on the right side of the slider thumb. + * This is needed especially for the ubuntulooks engine, which looks + * exclusively at the "inverted" flag to determine on which side of + * the thumb to paint the highlight... + */ + fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir == + GTK_TEXT_DIR_RTL); + + /* + * Note however that other engines like clearlooks will look at both + * the "inverted" field and the text direction to determine how + * the foreground highlight is painted: + * !inverted && ltr --> paint highlight on left side + * !inverted && rtl --> paint highlight on right side + * inverted && ltr --> paint highlight on right side + * inverted && rtl --> paint highlight on left side + * So the only way to reliably get the desired results for horizontal + * JSlider (i.e., highlight on left side for LTR ComponentOrientation + * and highlight on right side for RTL ComponentOrientation) is to + * always override text direction as LTR, and then set the "inverted" + * flag accordingly (as we have done above). + */ + dir = GTK_TEXT_DIR_LTR; + } + + /* + * Some engines (e.g. clearlooks) will paint the shadow of certain + * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the + * the text direction. + */ + gtk3_set_direction(gtk3_widget, dir); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + transform_detail_string(detail, context); + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) { + flags |= GTK_STATE_FLAG_ACTIVE; + } + + if (synth_state & MOUSE_OVER) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (synth_state & FOCUSED) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + if (synth_state & DEFAULT) { + fp_gtk_style_context_add_class (context, "default"); + } + + fp_gtk_style_context_set_state (context, flags); + + if (fp_gtk_style_context_has_class(context, "progressbar")) { + fp_gtk_render_activity (context, cr, x, y, width, height); + } else { + fp_gtk_render_background (context, cr, x, y, width, height); + if (shadow_type != GTK_SHADOW_NONE) { + fp_gtk_render_frame(context, cr, x, y, width, height); + } + } + + fp_gtk_style_context_restore (context); + /* + * Reset the text direction to the default value so that we don't + * accidentally affect other operations and widgets. + */ + gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); +} + +static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + fp_gtk_render_background(context, cr, x, y, width, height); + + if (shadow_type != GTK_SHADOW_NONE) { + fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side, + (gdouble)gap_x, (gdouble)gap_x + gap_width); + } + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_check(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_state_flags(synth_state); + if (gtk3_version_3_14 && (synth_state & SELECTED)) { + flags = GTK_STATE_FLAG_CHECKED; + } + fp_gtk_style_context_set_state(context, flags); + + fp_gtk_style_context_add_class (context, "check"); + + fp_gtk_render_check (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + + +static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height, + GtkExpanderStyle expander_style) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_expander (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkPositionType gap_side) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = GTK_STATE_FLAG_NORMAL; + + if (state_type == 0) { + flags = GTK_STATE_FLAG_ACTIVE; + } + + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + switch(gap_side) { + case GTK_POS_LEFT: + fp_gtk_style_context_add_class(context, "right"); + break; + case GTK_POS_RIGHT: + fp_gtk_style_context_add_class(context, "left"); + break; + case GTK_POS_TOP: + fp_gtk_style_context_add_class(context, "bottom"); + break; + case GTK_POS_BOTTOM: + fp_gtk_style_context_add_class(context, "top"); + break; + default: + break; + } + + fp_gtk_render_extension(context, cr, x, y, width, height, gap_side); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, gboolean has_focus) +{ + if (state_type == GTK_STATE_PRELIGHT && + (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) { + return; + } + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (has_focus) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + if (widget_type == COMBO_BOX_TEXT_FIELD) { + width += height /2; + } + + fp_gtk_render_background (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type, + const char *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + transform_detail_string(detail, context); + fp_gtk_render_focus (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); + +} + +static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT); + + if (detail != 0) { + transform_detail_string(detail, context); + fp_gtk_style_context_add_class (context, "handlebox_bin"); + } + + fp_gtk_render_handle(context, cr, x, y, width, height); + fp_gtk_render_background(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_line(context, cr, x, y, x + width, y); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_line(context, cr, x, y, x, y + height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_option(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_state_flags(synth_state); + if (gtk3_version_3_14 && (synth_state & SELECTED)) { + flags = GTK_STATE_FLAG_CHECKED; + } + fp_gtk_style_context_set_state(context, flags); + + if (detail != 0) { + transform_detail_string(detail, context); + } + + fp_gtk_render_option(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir) +{ + if (shadow_type == GTK_SHADOW_NONE) { + return; + } + gtk3_widget = gtk3_get_widget(widget_type); + + /* + * Some engines (e.g. clearlooks) will paint the shadow of certain + * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the + * the text direction. + */ + gtk3_set_direction(gtk3_widget, dir); + + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + if (detail) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (synth_state & MOUSE_OVER) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (synth_state & FOCUSED) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + if (widget_type == COMBO_BOX_TEXT_FIELD) { + width += height / 2; + } + fp_gtk_render_frame(context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); + + /* + * Reset the text direction to the default value so that we don't + * accidentally affect other operations and widgets. + */ + gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); +} + +static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus) +{ + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + + fp_gtk_style_context_save (context); + + if (detail) { + transform_detail_string(detail, context); + } + + GtkStateFlags flags = get_gtk_flags(state_type); + + if (state_type == GTK_STATE_ACTIVE) { + flags |= GTK_STATE_FLAG_PRELIGHT; + } + + if (has_focus) { + flags |= GTK_STATE_FLAG_FOCUSED; + } + + fp_gtk_style_context_set_state (context, flags); + + (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation); + + fp_gtk_style_context_restore (context); +} + +static void gtk3_paint_background(WidgetType widget_type, + GtkStateType state_type, gint x, gint y, gint width, gint height) { + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + fp_gtk_style_context_save (context); + + GtkStateFlags flags = get_gtk_flags(state_type); + + fp_gtk_style_context_set_state (context, flags); + + fp_gtk_render_background (context, cr, x, y, width, height); + + fp_gtk_style_context_restore (context); +} + +static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id, + GtkIconSize size, GtkTextDirection direction, const char *detail) +{ + int sz; + + switch(size) { + case GTK_ICON_SIZE_MENU: + sz = 16; + break; + case GTK_ICON_SIZE_SMALL_TOOLBAR: + sz = 18; + break; + case GTK_ICON_SIZE_LARGE_TOOLBAR: + sz = 24; + break; + case GTK_ICON_SIZE_BUTTON: + sz = 20; + break; + case GTK_ICON_SIZE_DND: + sz = 32; + break; + case GTK_ICON_SIZE_DIALOG: + sz = 48; + break; + default: + sz = 0; + break; + } + + init_containers(); + gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type); + (*fp_gtk_widget_set_direction)(gtk3_widget, direction); + GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default(); + GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz, + GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + return result; +} + +static jboolean gtk3_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, + jmethodID icon_upcall_method, jobject this) { + if (!pixbuf) { + return JNI_FALSE; + } + guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + if (pixbuf_data) { + int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + int width = (*fp_gdk_pixbuf_get_width)(pixbuf); + int height = (*fp_gdk_pixbuf_get_height)(pixbuf); + int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); + int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); + + jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); + JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); + + (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), + (jbyte *)pixbuf_data); + (*fp_g_object_unref)(pixbuf); + + /* Call the callback method to create the image on the Java side. */ + (*env)->CallVoidMethod(env, this, icon_upcall_method, data, + width, height, row_stride, bps, channels, alpha); + return JNI_TRUE; + } + return JNI_FALSE; +} + +static jboolean gtk3_get_file_icon_data(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); + return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +static jboolean gtk3_get_icon_data(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this) { + GdkPixbuf* pixbuf = gtk3_get_stock_icon(widget_type, stock_id, size, + direction, detail); + return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); +} + +/*************************************************/ +static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) { + GtkBorder padding; + fp_gtk_style_context_get_padding(context, 0, &padding); + return padding.left + 1; + } + return 0; +} + +static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) { + GtkBorder padding; + fp_gtk_style_context_get_padding(context, 0, &padding); + return padding.top + 1; + } + return 0; +} + +/*************************************************/ +static guint8 recode_color(gdouble channel) +{ + guint16 result = (guint16)(channel * 65535); + if (result < 0) { + result = 0; + } else if (result > 65535) { + result = 65535; + } + return (guint8)( result >> 8); +} + +static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) { + switch (state_type) + { + case GTK_STATE_NORMAL: + return GTK_STATE_FLAG_NORMAL; + case GTK_STATE_ACTIVE: + return GTK_STATE_FLAG_ACTIVE; + case GTK_STATE_PRELIGHT: + return GTK_STATE_FLAG_PRELIGHT; + case GTK_STATE_SELECTED: + return GTK_STATE_FLAG_SELECTED; + case GTK_STATE_INSENSITIVE: + return GTK_STATE_FLAG_INSENSITIVE; + case GTK_STATE_INCONSISTENT: + return GTK_STATE_FLAG_INCONSISTENT; + case GTK_STATE_FOCUSED: + return GTK_STATE_FLAG_FOCUSED; + } + return 0; +} + + +static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) { + gdouble min; + gdouble max; + gdouble red; + gdouble green; + gdouble blue; + gdouble h, l, s; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + l = (max + min) / 2; + s = 0; + h = 0; + + if (max != min) + { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max -min; + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h *= 60; + if (h < 0.0) + h += 360; + } + + *r = h; + *g = l; + *b = s; +} + +static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s) +{ + gdouble hue; + gdouble lightness; + gdouble saturation; + gdouble m1, m2; + gdouble r, g, b; + + lightness = *l; + saturation = *s; + + if (lightness <= 0.5) + m2 = lightness * (1 + saturation); + else + m2 = lightness + saturation - lightness * saturation; + m1 = 2 * lightness - m2; + + if (saturation == 0) + { + *h = lightness; + *l = lightness; + *s = lightness; + } + else + { + hue = *h + 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + r = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + r = m2; + else if (hue < 240) + r = m1 + (m2 - m1) * (240 - hue) / 60; + else + r = m1; + + hue = *h; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + g = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + g = m2; + else if (hue < 240) + g = m1 + (m2 - m1) * (240 - hue) / 60; + else + g = m1; + + hue = *h - 120; + while (hue > 360) + hue -= 360; + while (hue < 0) + hue += 360; + + if (hue < 60) + b = m1 + (m2 - m1) * hue / 60; + else if (hue < 180) + b = m2; + else if (hue < 240) + b = m1 + (m2 - m1) * (240 - hue) / 60; + else + b = m1; + + *h = r; + *l = g; + *s = b; + } +} + + + +static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) { + gdouble red = a->red; + gdouble green = a->green; + gdouble blue = a->blue; + + rgb_to_hls (&red, &green, &blue); + + green *= k; + if (green > 1.0) + green = 1.0; + else if (green < 0.0) + green = 0.0; + + blue *= k; + if (blue > 1.0) + blue = 1.0; + else if (blue < 0.0) + blue = 0.0; + + hls_to_rgb (&red, &green, &blue); + + b->red = red; + b->green = green; + b->blue = blue; +} + +static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context, + GtkStateFlags flags, ColorType color_type) { + GdkRGBA c, color; + + switch (color_type) + { + case FOREGROUND: + case TEXT_FOREGROUND: + fp_gtk_style_context_get_color(context, flags, &color); + break; + case BACKGROUND: + case TEXT_BACKGROUND: + fp_gtk_style_context_get_background_color(context, flags, &color); + break; + case LIGHT: + c = gtk3_get_color_for_flags(context, flags, BACKGROUND); + gtk3_style_shade(&c, &color, LIGHTNESS_MULT); + break; + case DARK: + c = gtk3_get_color_for_flags(context, flags, BACKGROUND); + gtk3_style_shade (&c, &color, DARKNESS_MULT); + break; + case MID: + { + GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT); + GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK); + color.red = (c1.red + c2.red) / 2; + color.green = (c1.green + c2.green) / 2; + color.blue = (c1.blue + c2.blue) / 2; + } + break; + case FOCUS: + case BLACK: + color.red = 0; + color.green = 0; + color.blue = 0; + break; + case WHITE: + color.red = 1; + color.green = 1; + color.blue = 1; + break; + } + return color; +} + +static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type, + GtkStateType state_type, ColorType color_type) +{ + + gint result = 0; + GdkRGBA color; + + GtkStateFlags flags = gtk3_get_state_flags(state_type); + + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + + GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget); + + if (widget_type == TOOL_TIP) { + fp_gtk_style_context_add_class(context, "tooltip"); + } + if (widget_type == CHECK_BOX_MENU_ITEM + || widget_type == RADIO_BUTTON_MENU_ITEM) { + flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED + | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED; + } + + color = gtk3_get_color_for_flags(context, flags, color_type); + + if (recode_color(color.alpha) == 0) { + color = gtk3_get_color_for_flags( + fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)), + 0, BACKGROUND); + } + + result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 | + recode_color(color.green) << 8 | recode_color(color.blue); + + return result; +} + +/*************************************************/ +static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); +static jobject create_Integer(JNIEnv *env, jint int_value); +static jobject create_Long(JNIEnv *env, jlong long_value); +static jobject create_Float(JNIEnv *env, jfloat float_value); +static jobject create_Double(JNIEnv *env, jdouble double_value); +static jobject create_Character(JNIEnv *env, jchar char_value); +static jobject create_Insets(JNIEnv *env, GtkBorder *border); + +static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type, + const char* key) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + + GValue value = { 0, { { 0 } } }; + + GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( + ((GTypeInstance*)gtk3_widget)->g_class, key); + if ( param ) + { + (*fp_g_value_init)( &value, param->value_type ); + (*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value); + + if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) + { + gboolean val = (*fp_g_value_get_boolean)(&value); + return create_Boolean(env, (jboolean)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) + { + gchar val = (*fp_g_value_get_char)(&value); + return create_Character(env, (jchar)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) + { + guchar val = (*fp_g_value_get_uchar)(&value); + return create_Character(env, (jchar)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) + { + gint val = (*fp_g_value_get_int)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) + { + guint val = (*fp_g_value_get_uint)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) + { + glong val = (*fp_g_value_get_long)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) + { + gulong val = (*fp_g_value_get_ulong)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) + { + gint64 val = (*fp_g_value_get_int64)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) + { + guint64 val = (*fp_g_value_get_uint64)(&value); + return create_Long(env, (jlong)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) + { + gfloat val = (*fp_g_value_get_float)(&value); + return create_Float(env, (jfloat)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) + { + gdouble val = (*fp_g_value_get_double)(&value); + return create_Double(env, (jdouble)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) + { + gint val = (*fp_g_value_get_enum)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) + { + guint val = (*fp_g_value_get_flags)(&value); + return create_Integer(env, (jint)val); + } + else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) + { + const gchar* val = (*fp_g_value_get_string)(&value); + + /* We suppose that all values come in C locale and + * utf-8 representation of a string is the same as + * the string itself. If this isn't so we should + * use g_convert. + */ + return (*env)->NewStringUTF(env, val); + } + else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) + { + GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); + return border ? create_Insets(env, border) : NULL; + } + + /* TODO: Other types are not supported yet.*/ +/* else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) + { + GParamSpec* val = (*fp_g_value_get_param)(&value); + printf( "Param: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) + { + gpointer* val = (*fp_g_value_get_boxed)(&value); + printf( "Boxed: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) + { + gpointer* val = (*fp_g_value_get_pointer)(&value); + printf( "Pointer: %p\n", val ); + } + else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) + { + GObject* val = (GObject*)(*fp_g_value_get_object)(&value); + printf( "Object: %p\n", val ); + }*/ + } + + return NULL; +} + +static void gtk3_set_range_value(WidgetType widget_type, jdouble value, + jdouble min, jdouble max, jdouble visible) +{ + GtkAdjustment *adj; + + gtk3_widget = gtk3_get_widget(widget_type); + + adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget); + + fp_gtk_adjustment_set_value(adj, value); + fp_gtk_adjustment_set_lower(adj, min); + fp_gtk_adjustment_set_upper(adj, max); + fp_gtk_adjustment_set_page_size(adj, visible); +} + +/*************************************************/ +static jobject create_Object(JNIEnv *env, jmethodID *cid, + const char* class_name, + const char* signature, + jvalue* value) +{ + jclass class; + jobject result; + + class = (*env)->FindClass(env, class_name); + if (class == NULL) + return NULL; /* can't find/load the class, exception thrown */ + + if (*cid == NULL) + { + *cid = (*env)->GetMethodID(env, class, "", signature); + if (*cid == NULL) + { + (*env)->DeleteLocalRef(env, class); + return NULL; /* can't find/get the method, exception thrown */ + } + } + + result = (*env)->NewObjectA(env, class, *cid, value); + + (*env)->DeleteLocalRef(env, class); + return result; +} + +jobject create_Boolean(JNIEnv *env, jboolean boolean_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.z = boolean_value; + + return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); +} + +jobject create_Integer(JNIEnv *env, jint int_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.i = int_value; + + return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); +} + +jobject create_Long(JNIEnv *env, jlong long_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.j = long_value; + + return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); +} + +jobject create_Float(JNIEnv *env, jfloat float_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.f = float_value; + + return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); +} + +jobject create_Double(JNIEnv *env, jdouble double_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.d = double_value; + + return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); +} + +jobject create_Character(JNIEnv *env, jchar char_value) +{ + static jmethodID cid = NULL; + jvalue value; + + value.c = char_value; + + return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); +} + + +jobject create_Insets(JNIEnv *env, GtkBorder *border) +{ + static jmethodID cid = NULL; + jvalue values[4]; + + values[0].i = border->top; + values[1].i = border->left; + values[2].i = border->bottom; + values[3].i = border->right; + + return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); +} + +/*********************************************/ +static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type) +{ + init_containers(); + + gtk3_widget = gtk3_get_widget(widget_type); + jstring result = NULL; + GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); + if (context) + { + PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0); + gchar* val = (*fp_pango_font_description_to_string)(fd); + result = (*env)->NewStringUTF(env, val); + (*fp_g_free)( val ); + } + + return result; +} + +/***********************************************/ +static jobject get_string_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + jobject result = NULL; + gchar* strval = NULL; + + (*fp_g_object_get)(settings, key, &strval, NULL); + result = (*env)->NewStringUTF(env, strval); + (*fp_g_free)(strval); + + return result; +} + +static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + gint intval = NULL; + (*fp_g_object_get)(settings, key, &intval, NULL); + return create_Integer(env, intval); +} + +static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, + const gchar* key) { + gint intval = NULL; + (*fp_g_object_get)(settings, key, &intval, NULL); + return create_Boolean(env, intval); +} + +static jobject gtk3_get_setting(JNIEnv *env, Setting property) +{ + GtkSettings* settings = (*fp_gtk_settings_get_default)(); + + switch (property) + { + case GTK_FONT_NAME: + return get_string_property(env, settings, "gtk-font-name"); + case GTK_ICON_SIZES: + return get_string_property(env, settings, "gtk-icon-sizes"); + case GTK_CURSOR_BLINK: + return get_boolean_property(env, settings, "gtk-cursor-blink"); + case GTK_CURSOR_BLINK_TIME: + return get_integer_property(env, settings, "gtk-cursor-blink-time"); + } + + return NULL; +} + +static void transform_detail_string (const gchar *detail, + GtkStyleContext *context) { + if (!detail) + return; + + if (strcmp (detail, "arrow") == 0) + fp_gtk_style_context_add_class (context, "arrow"); + else if (strcmp (detail, "button") == 0) + fp_gtk_style_context_add_class (context, "button"); + else if (strcmp (detail, "buttondefault") == 0) + { + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_add_class (context, "default"); + } + else if (strcmp (detail, "calendar") == 0) + fp_gtk_style_context_add_class (context, "calendar"); + else if (strcmp (detail, "cellcheck") == 0) + { + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_class (context, "check"); + } + else if (strcmp (detail, "cellradio") == 0) + { + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_class (context, "radio"); + } + else if (strcmp (detail, "checkbutton") == 0) + fp_gtk_style_context_add_class (context, "check"); + else if (strcmp (detail, "check") == 0) + { + fp_gtk_style_context_add_class (context, "check"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "radiobutton") == 0) + { + fp_gtk_style_context_add_class (context, "radio"); + } + else if (strcmp (detail, "option") == 0) + { + fp_gtk_style_context_add_class (context, "radio"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "entry") == 0 || + strcmp (detail, "entry_bg") == 0) + fp_gtk_style_context_add_class (context, "entry"); + else if (strcmp (detail, "expander") == 0) + fp_gtk_style_context_add_class (context, "expander"); + else if (strcmp (detail, "tooltip") == 0) + fp_gtk_style_context_add_class (context, "tooltip"); + else if (strcmp (detail, "frame") == 0) + fp_gtk_style_context_add_class (context, "frame"); + else if (strcmp (detail, "scrolled_window") == 0) + fp_gtk_style_context_add_class (context, "scrolled-window"); + else if (strcmp (detail, "viewport") == 0 || + strcmp (detail, "viewportbin") == 0) + fp_gtk_style_context_add_class (context, "viewport"); + else if (strncmp (detail, "trough", 6) == 0) + fp_gtk_style_context_add_class (context, "trough"); + else if (strcmp (detail, "spinbutton") == 0) + fp_gtk_style_context_add_class (context, "spinbutton"); + else if (strcmp (detail, "spinbutton_up") == 0) + { + fp_gtk_style_context_add_class (context, "spinbutton"); + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM); + } + else if (strcmp (detail, "spinbutton_down") == 0) + { + fp_gtk_style_context_add_class (context, "spinbutton"); + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); + } + else if ((detail[0] == 'h' || detail[0] == 'v') && + strncmp (&detail[1], "scrollbar_", 9) == 0) + { + fp_gtk_style_context_add_class (context, "button"); + fp_gtk_style_context_add_class (context, "scrollbar"); + } + else if (strcmp (detail, "slider") == 0) + { + fp_gtk_style_context_add_class (context, "slider"); + fp_gtk_style_context_add_class (context, "scrollbar"); + } + else if (strcmp (detail, "vscale") == 0 || + strcmp (detail, "hscale") == 0) + { + fp_gtk_style_context_add_class (context, "slider"); + fp_gtk_style_context_add_class (context, "scale"); + } + else if (strcmp (detail, "menuitem") == 0) + { + fp_gtk_style_context_add_class (context, "menuitem"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "menu") == 0) + { + fp_gtk_style_context_add_class (context, "popup"); + fp_gtk_style_context_add_class (context, "menu"); + } + else if (strcmp (detail, "accellabel") == 0) + fp_gtk_style_context_add_class (context, "accelerator"); + else if (strcmp (detail, "menubar") == 0) + fp_gtk_style_context_add_class (context, "menubar"); + else if (strcmp (detail, "base") == 0) + fp_gtk_style_context_add_class (context, "background"); + else if (strcmp (detail, "bar") == 0 || + strcmp (detail, "progressbar") == 0) + fp_gtk_style_context_add_class (context, "progressbar"); + else if (strcmp (detail, "toolbar") == 0) + fp_gtk_style_context_add_class (context, "toolbar"); + else if (strcmp (detail, "handlebox_bin") == 0) + fp_gtk_style_context_add_class (context, "dock"); + else if (strcmp (detail, "notebook") == 0) + fp_gtk_style_context_add_class (context, "notebook"); + else if (strcmp (detail, "tab") == 0) + { + fp_gtk_style_context_add_class (context, "notebook"); + fp_gtk_style_context_add_region (context, "tab", 0); + } else if (strcmp (detail, "paned") == 0) { + fp_gtk_style_context_add_class (context, "pane-separator"); + } + else if (fp_g_str_has_prefix (detail, "cell")) + { + GtkRegionFlags row, col; + gboolean ruled = FALSE; + gchar** tokens; + guint i; + + tokens = fp_g_strsplit (detail, "_", -1); + row = col = 0; + i = 0; + + while (tokens[i]) + { + if (strcmp (tokens[i], "even") == 0) + row |= GTK_REGION_EVEN; + else if (strcmp (tokens[i], "odd") == 0) + row |= GTK_REGION_ODD; + else if (strcmp (tokens[i], "start") == 0) + col |= GTK_REGION_FIRST; + else if (strcmp (tokens[i], "end") == 0) + col |= GTK_REGION_LAST; + else if (strcmp (tokens[i], "ruled") == 0) + ruled = TRUE; + else if (strcmp (tokens[i], "sorted") == 0) + col |= GTK_REGION_SORTED; + + i++; + } + + if (!ruled) + row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD); + + fp_gtk_style_context_add_class (context, "cell"); + fp_gtk_style_context_add_region (context, "row", row); + fp_gtk_style_context_add_region (context, "column", col); + + fp_g_strfreev (tokens); + } +} + +static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray, + int x, jint y, jint width, jint height, jint jwidth, int dx, int dy, + jint scale) { + GdkPixbuf *pixbuf; + jint *ary; + + GdkWindow *root = (*fp_gdk_get_default_root_window)(); + pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(root, x, y, width, height); + if (pixbuf && scale != 1) { + GdkPixbuf *scaledPixbuf; + x /= scale; + y /= scale; + width /= scale; + height /= scale; + dx /= scale; + dy /= scale; + scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height, + GDK_INTERP_BILINEAR); + (*fp_g_object_unref)(pixbuf); + pixbuf = scaledPixbuf; + } + + if (pixbuf) { + int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); + int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); + if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width + && (*fp_gdk_pixbuf_get_height)(pixbuf) == height + && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 + && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB + && nchan >= 3 + ) { + guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); + ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); + if (ary) { + jint _x, _y; + int index; + for (_y = 0; _y < height; _y++) { + for (_x = 0; _x < width; _x++) { + p = pix + _y * stride + _x * nchan; + + index = (_y + dy) * jwidth + (_x + dx); + ary[index] = 0xff000000 + | (p[0] << 16) + | (p[1] << 8) + | (p[2]); + + } + } + (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); + } + } + (*fp_g_object_unref)(pixbuf); + } + return JNI_FALSE; +} + +static GdkWindow* gtk3_get_window(void *widget) { + return fp_gtk_widget_get_window((GtkWidget*)widget); +} + +static void gtk3_init(GtkApi* gtk) { + gtk->version = GTK_3; + + gtk->show_uri_load = >k3_show_uri_load; + gtk->unload = >k3_unload; + gtk->flush_event_loop = &flush_gtk_event_loop; + gtk->gtk_check_version = fp_gtk_check_version; + gtk->get_setting = >k3_get_setting; + + gtk->paint_arrow = >k3_paint_arrow; + gtk->paint_box = >k3_paint_box; + gtk->paint_box_gap = >k3_paint_box_gap; + gtk->paint_expander = >k3_paint_expander; + gtk->paint_extension = >k3_paint_extension; + gtk->paint_flat_box = >k3_paint_flat_box; + gtk->paint_focus = >k3_paint_focus; + gtk->paint_handle = >k3_paint_handle; + gtk->paint_hline = >k3_paint_hline; + gtk->paint_vline = >k3_paint_vline; + gtk->paint_option = >k3_paint_option; + gtk->paint_shadow = >k3_paint_shadow; + gtk->paint_slider = >k3_paint_slider; + gtk->paint_background = >k3_paint_background; + gtk->paint_check = >k3_paint_check; + gtk->set_range_value = >k3_set_range_value; + + gtk->init_painting = >k3_init_painting; + gtk->copy_image = >k3_copy_image; + + gtk->get_xthickness = >k3_get_xthickness; + gtk->get_ythickness = >k3_get_ythickness; + gtk->get_color_for_state = >k3_get_color_for_state; + gtk->get_class_value = >k3_get_class_value; + + gtk->get_pango_font_name = >k3_get_pango_font_name; + gtk->get_icon_data = >k3_get_icon_data; + gtk->get_file_icon_data = >k3_get_file_icon_data; + gtk->gdk_threads_enter = fp_gdk_threads_enter; + gtk->gdk_threads_leave = fp_gdk_threads_leave; + gtk->gtk_show_uri = fp_gtk_show_uri; + gtk->get_drawable_data = >k3_get_drawable_data; + gtk->g_free = fp_g_free; + + gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; + gtk->gtk_widget_hide = fp_gtk_widget_hide; + gtk->gtk_main_quit = fp_gtk_main_quit; + gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; + gtk->gtk_file_chooser_set_current_folder = + fp_gtk_file_chooser_set_current_folder; + gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; + gtk->gtk_file_chooser_set_current_name = + fp_gtk_file_chooser_set_current_name; + gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; + gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; + gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; + gtk->gtk_file_filter_new = fp_gtk_file_filter_new; + gtk->gtk_file_chooser_set_do_overwrite_confirmation = + fp_gtk_file_chooser_set_do_overwrite_confirmation; + gtk->gtk_file_chooser_set_select_multiple = + fp_gtk_file_chooser_set_select_multiple; + gtk->gtk_file_chooser_get_current_folder = + fp_gtk_file_chooser_get_current_folder; + gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; + gtk->gtk_g_slist_length = fp_gtk_g_slist_length; + gtk->g_signal_connect_data = fp_g_signal_connect_data; + gtk->gtk_widget_show = fp_gtk_widget_show; + gtk->gtk_main = fp_gtk_main; + gtk->gtk_main_level = fp_gtk_main_level; + gtk->g_path_get_dirname = fp_g_path_get_dirname; + gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; + gtk->gtk_widget_destroy = fp_gtk_widget_destroy; + gtk->gtk_window_present = fp_gtk_window_present; + gtk->gtk_window_move = fp_gtk_window_move; + gtk->gtk_window_resize = fp_gtk_window_resize; + gtk->get_window = >k3_get_window; + + gtk->g_object_unref = fp_g_object_unref; + gtk->g_list_append = fp_g_list_append; + gtk->g_list_free = fp_g_list_free; + gtk->g_list_free_full = fp_g_list_free_full; +} diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h new file mode 100644 index 00000000000..1ffaa8fa9d0 --- /dev/null +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h @@ -0,0 +1,577 @@ +/* + * 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 + * 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. + */ +#ifndef _GTK3_INTERFACE_H +#define _GTK3_INTERFACE_H + +#include +#include +#include +#include "gtk_interface.h" + +#define LIGHTNESS_MULT 1.3 +#define DARKNESS_MULT 0.7 + +#define G_PI 3.1415926535897932384626433832795028841971693993751 + +typedef enum +{ + GTK_STATE_FLAG_NORMAL = 0, + GTK_STATE_FLAG_ACTIVE = 1 << 0, + GTK_STATE_FLAG_PRELIGHT = 1 << 1, + GTK_STATE_FLAG_SELECTED = 1 << 2, + GTK_STATE_FLAG_INSENSITIVE = 1 << 3, + GTK_STATE_FLAG_INCONSISTENT = 1 << 4, + GTK_STATE_FLAG_FOCUSED = 1 << 5, + GTK_STATE_FLAG_BACKDROP = 1 << 6, + GTK_STATE_FLAG_DIR_LTR = 1 << 7, + GTK_STATE_FLAG_DIR_RTL = 1 << 8, + GTK_STATE_FLAG_LINK = 1 << 9, + GTK_STATE_FLAG_VISITED = 1 << 10, + GTK_STATE_FLAG_CHECKED = 1 << 11 +} GtkStateFlags; + +typedef enum { + GTK_JUNCTION_NONE = 0, + GTK_JUNCTION_CORNER_TOPLEFT = 1 << 0, + GTK_JUNCTION_CORNER_TOPRIGHT = 1 << 1, + GTK_JUNCTION_CORNER_BOTTOMLEFT = 1 << 2, + GTK_JUNCTION_CORNER_BOTTOMRIGHT = 1 << 3, + GTK_JUNCTION_TOP = + (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_TOPRIGHT), + GTK_JUNCTION_BOTTOM = + (GTK_JUNCTION_CORNER_BOTTOMLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT), + GTK_JUNCTION_LEFT = + (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT), + GTK_JUNCTION_RIGHT = + (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT) +} GtkJunctionSides; + +typedef enum { + GTK_REGION_EVEN = 1 << 0, + GTK_REGION_ODD = 1 << 1, + GTK_REGION_FIRST = 1 << 2, + GTK_REGION_LAST = 1 << 3, + GTK_REGION_ONLY = 1 << 4, + GTK_REGION_SORTED = 1 << 5 +} GtkRegionFlags; + +typedef enum +{ + GTK_WINDOW_TOPLEVEL, + GTK_WINDOW_POPUP +} GtkWindowType; + +typedef enum +{ + G_PARAM_READABLE = 1 << 0, + G_PARAM_WRITABLE = 1 << 1, + G_PARAM_CONSTRUCT = 1 << 2, + G_PARAM_CONSTRUCT_ONLY = 1 << 3, + G_PARAM_LAX_VALIDATION = 1 << 4, + G_PARAM_STATIC_NAME = 1 << 5 +} GParamFlags; + +typedef enum +{ + GTK_ICON_LOOKUP_NO_SVG = 1 << 0, + GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1, + GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2, + GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3, + GTK_ICON_LOOKUP_FORCE_SIZE = 1 << 4 +} GtkIconLookupFlags; + +typedef enum +{ + GTK_UPDATE_CONTINUOUS, + GTK_UPDATE_DISCONTINUOUS, + GTK_UPDATE_DELAYED +} GtkUpdateType; + +typedef enum +{ + GTK_PROGRESS_CONTINUOUS, + GTK_PROGRESS_DISCRETE +} GtkProgressBarStyle; + +typedef enum +{ + GTK_PROGRESS_LEFT_TO_RIGHT, + GTK_PROGRESS_RIGHT_TO_LEFT, + GTK_PROGRESS_BOTTOM_TO_TOP, + GTK_PROGRESS_TOP_TO_BOTTOM +} GtkProgressBarOrientation; + +typedef enum { + CAIRO_FORMAT_INVALID = -1, + CAIRO_FORMAT_ARGB32 = 0, + CAIRO_FORMAT_RGB24 = 1, + CAIRO_FORMAT_A8 = 2, + CAIRO_FORMAT_A1 = 3, + CAIRO_FORMAT_RGB16_565 = 4 +} cairo_format_t; + +/* We define all structure pointers to be void* */ +typedef void GdkPixbuf; +typedef void GMainContext; +typedef void GVfs; + +typedef void GdkColormap; +typedef void GdkDrawable; +typedef void GdkGC; +typedef void GdkPixmap; +typedef void GtkStyleContext; +typedef void GtkFixed; +typedef void GtkMenuItem; +typedef void GtkMenuShell; +typedef void GtkWidgetClass; +typedef void PangoFontDescription; +typedef void GtkSettings; +typedef void GtkStyleProvider; +typedef void cairo_pattern_t; +typedef void cairo_t; +typedef void cairo_surface_t; +typedef void GtkScrolledWindow; +typedef void GtkIconTheme; +typedef void GtkWidget; +typedef void GtkMisc; +typedef void GtkContainer; +typedef void GtkBin; +typedef void GtkAdjustment; +typedef void GtkRange; +typedef void GtkProgressBar; +typedef void GtkProgress; + +/* Some real structures */ +typedef struct +{ + guint32 pixel; + guint16 red; + guint16 green; + guint16 blue; +} GdkColor; + +typedef struct +{ + gdouble red; + gdouble green; + gdouble blue; + gdouble alpha; +} GdkRGBA; + +typedef struct { + gint fd; + gushort events; + gushort revents; +} GPollFD; + +typedef struct { + gint x; + gint y; + gint width; + gint height; +} GdkRectangle; + +typedef struct { + int x, y; + int width, height; +} GtkAllocation; + +typedef struct { + gint width; + gint height; +} GtkRequisition; + +typedef struct { + GtkWidgetClass *g_class; +} GTypeInstance; + +typedef struct { + gint16 left; + gint16 right; + gint16 top; + gint16 bottom; +} GtkBorder; + +typedef struct +{ + GType g_type; + union { + gint v_int; + guint v_uint; + glong v_long; + gulong v_ulong; + gint64 v_int64; + guint64 v_uint64; + gfloat v_float; + gdouble v_double; + gpointer v_pointer; + } data[2]; +} GValue; + +typedef struct { + GTypeInstance g_type_instance; + const gchar *name; + GParamFlags flags; + GType value_type; + GType owner_type; +} GParamSpec; + + +static gchar* (*fp_glib_check_version)(guint required_major, + guint required_minor, guint required_micro); + +/** + * Returns : + * NULL if the GTK+ library is compatible with the given version, or a string + * describing the version mismatch. + */ +static gchar* (*fp_gtk_check_version)(guint required_major, guint + required_minor, guint required_micro); + +static void (*fp_g_free)(gpointer mem); +static void (*fp_g_object_unref)(gpointer object); +static GdkWindow *(*fp_gdk_get_default_root_window) (void); + +static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); +static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); +static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); +static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); +static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, + GError **error); +static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); + +static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkWindow *window, + int src_x, int src_y, int width, int height); +static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, + int dest_width, int dest_heigh, GdkInterpType interp_type); + + +static void (*fp_gtk_widget_destroy)(void *widget); +static void (*fp_gtk_window_present)(GtkWindow *window); +static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); +static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); + +/** + * Function Pointers for GtkFileChooser + */ +static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); +static void (*fp_gtk_widget_hide)(void *widget); +static void (*fp_gtk_main_quit)(void); +static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, GtkFileChooserAction action, + const gchar *first_button_text, ...); +static gboolean (*fp_gtk_file_chooser_set_current_folder) + (GtkFileChooser *chooser, const gchar *filename); +static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, + const char *filename); +static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, + const gchar *name); +static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, + GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); +static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, + GtkFileFilter *filter); +static GType (*fp_gtk_file_chooser_get_type)(void); +static GtkFileFilter* (*fp_gtk_file_filter_new)(void); +static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( + GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +static void (*fp_gtk_file_chooser_set_select_multiple)( + GtkFileChooser *chooser, gboolean select_multiple); +static gchar* (*fp_gtk_file_chooser_get_current_folder) + (GtkFileChooser *chooser); +static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static guint (*fp_gtk_g_slist_length)(GSList *list); +static gulong (*fp_g_signal_connect_data)(gpointer instance, + const gchar *detailed_signal, GCallback c_handler, gpointer data, + GClosureNotify destroy_data, GConnectFlags connect_flags); +static void (*fp_gtk_widget_show)(void *widget); +static void (*fp_gtk_main)(void); +static guint (*fp_gtk_main_level)(void); +static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); +static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); + +static GList* (*fp_g_list_append) (GList *list, gpointer data); +static void (*fp_g_list_free) (GList *list); +static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); + +static void (*fp_gdk_threads_enter)(void); +static void (*fp_gdk_threads_leave)(void); + +static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, + guint32 timestamp, GError **error); + +// Implementation functions prototypes +static void gtk3_init(GtkApi* gtk); +static GValue* (*fp_g_value_init)(GValue *value, GType g_type); +static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type); +static gboolean (*fp_g_value_get_boolean)(const GValue *value); +static gchar (*fp_g_value_get_char)(const GValue *value); +static guchar (*fp_g_value_get_uchar)(const GValue *value); +static gint (*fp_g_value_get_int)(const GValue *value); +static guint (*fp_g_value_get_uint)(const GValue *value); +static glong (*fp_g_value_get_long)(const GValue *value); +static gulong (*fp_g_value_get_ulong)(const GValue *value); +static gint64 (*fp_g_value_get_int64)(const GValue *value); +static guint64 (*fp_g_value_get_uint64)(const GValue *value); +static gfloat (*fp_g_value_get_float)(const GValue *value); +static gdouble (*fp_g_value_get_double)(const GValue *value); +static const gchar* (*fp_g_value_get_string)(const GValue *value); +static gint (*fp_g_value_get_enum)(const GValue *value); +static guint (*fp_g_value_get_flags)(const GValue *value); +static GParamSpec* (*fp_g_value_get_param)(const GValue *value); +static gpointer* (*fp_g_value_get_boxed)(const GValue *value); +static gpointer* (*fp_g_value_get_pointer)(const GValue *value); +static void (*fp_g_object_get)(gpointer object, + const gchar* fpn, ...); +static void (*fp_g_object_set)(gpointer object, + const gchar *first_property_name, + ...); + +static gboolean (*fp_g_main_context_iteration)(GMainContext *context); +static gboolean (*fp_g_str_has_prefix)(const gchar *str, const gchar *prefix); +static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter, + gint max_tokens); +static void (*fp_g_strfreev)(gchar **str_array); + + +static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format, + int width, int height); +static void (*fp_cairo_surface_destroy)(cairo_surface_t *surface); +static cairo_t* (*fp_cairo_create)(cairo_surface_t *target); +static void (*fp_cairo_destroy)(cairo_t *cr); +static void (*fp_cairo_fill)(cairo_t *cr); +static void (*fp_cairo_surface_flush)(cairo_surface_t *surface); +static void (*fp_cairo_rectangle)(cairo_t *cr, double x, double y, double width, + double height); +static void (*fp_cairo_set_source_rgb)(cairo_t *cr, double red, double green, + double blue); +static void (*fp_cairo_set_source_rgba)(cairo_t *cr, double red, double green, + double blue, double alpha); +static void (*fp_cairo_paint)(cairo_t *cr); +static void (*fp_cairo_clip)(cairo_t *cr); +static unsigned char* (*fp_cairo_image_surface_get_data)( + cairo_surface_t *surface); +static int (*fp_cairo_image_surface_get_stride) (cairo_surface_t *surface); +static GdkPixbuf* (*fp_gdk_pixbuf_get_from_surface)(cairo_surface_t *surface, + gint src_x, gint src_y, gint width, gint height); +static GtkStateType (*fp_gtk_widget_get_state)(GtkWidget *widget); +static void (*fp_gtk_widget_set_state)(GtkWidget *widget, GtkStateType state); +static gboolean (*fp_gtk_widget_is_focus)(GtkWidget *widget); +static void (*fp_gtk_widget_set_allocation)(GtkWidget *widget, + const GtkAllocation *allocation); +static GtkWidget* (*fp_gtk_widget_get_parent)(GtkWidget *widget); +static GtkStyleContext* (*fp_gtk_widget_get_style_context)(GtkWidget *widget); +static void (*fp_gtk_style_context_get_color)(GtkStyleContext *context, + GtkStateFlags state, GdkRGBA *color); +static void (*fp_gtk_style_context_get_background_color) + (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color); +static void (*fp_gtk_style_context_get)(GtkStyleContext *context, + GtkStateFlags state, ...); +static GtkStateFlags (*fp_gtk_widget_get_state_flags)(GtkWidget* widget); +static void (*fp_gtk_style_context_set_state)(GtkStyleContext* style, + GtkStateFlags flags); +static void (*fp_gtk_style_context_add_class)(GtkStyleContext *context, + const gchar *class_name); +static void (*fp_gtk_style_context_save)(GtkStyleContext *context); +static void (*fp_gtk_style_context_restore)(GtkStyleContext *context); +static void (*fp_gtk_render_check)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_option)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_extension)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkPositionType gap_side); +static void (*fp_gtk_render_expander)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_frame_gap)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkPositionType gap_side, gdouble xy0_gap, + gdouble xy1_gap); +static void (*fp_gtk_render_line)(GtkStyleContext *context, cairo_t *cr, + gdouble x0, gdouble y0, gdouble x1, gdouble y1); +static GdkPixbuf* (*fp_gtk_widget_render_icon_pixbuf)(GtkWidget *widget, + const gchar *stock_id, GtkIconSize size); +static cairo_surface_t* (*fp_gdk_window_create_similar_image_surface)( + GdkWindow *window, cairo_format_t format, int width, + int height, int scale); +static cairo_surface_t* (*fp_gdk_window_create_similar_surface)( + GdkWindow *window, cairo_format_t format, + int width, int height); +static GdkWindow* (*fp_gtk_widget_get_window)(GtkWidget *widget); +static GtkSettings *(*fp_gtk_settings_get_for_screen)(GdkScreen *screen); +static GdkScreen *(*fp_gtk_widget_get_screen)(GtkWidget *widget); +static GtkStyleProvider* (*fp_gtk_css_provider_get_named)(const gchar *name, + const gchar *variant); +static void (*fp_gtk_style_context_add_provider)(GtkStyleContext *context, + GtkStyleProvider *provider, guint priority); +static void (*fp_gtk_render_frame)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_focus)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_handle)(GtkStyleContext *context,cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_style_context_get_property)(GtkStyleContext *context, + const gchar *property, GtkStateFlags state, GValue *value); +static void (*fp_gtk_render_activity)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static void (*fp_gtk_render_background)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height); +static gboolean (*fp_gtk_style_context_has_class)(GtkStyleContext *context, + const gchar *class_name); +static void transform_detail_string (const gchar *detail, + GtkStyleContext *context); +void (*fp_gtk_style_context_set_junction_sides)(GtkStyleContext *context, + GtkJunctionSides sides); +void (*fp_gtk_style_context_add_region)(GtkStyleContext *context, + const gchar *region_name, GtkRegionFlags flags); +void (*fp_gtk_render_arrow)(GtkStyleContext *context, cairo_t *cr, + gdouble angle, gdouble x, gdouble y, gdouble size); +void (*fp_gtk_bin_set_child)(GtkBin *bin, GtkWidget *widget); +void (*fp_gtk_scrolled_window_set_shadow_type)( + GtkScrolledWindow *scrolled_window, GtkShadowType type); +static void (*fp_gtk_render_slider)(GtkStyleContext *context, cairo_t *cr, + gdouble x, gdouble y, gdouble width, gdouble height, + GtkOrientation orientation); +static void (*fp_gtk_style_context_get_padding)(GtkStyleContext *self, + GtkStateFlags state, GtkBorder* padding); +static void (*fp_gtk_range_set_inverted)(GtkRange *range, gboolean setting); +static PangoFontDescription* (*fp_gtk_style_context_get_font)( + GtkStyleContext *context, GtkStateFlags state); +static int (*fp_gtk_widget_get_allocated_width)(GtkWidget *widget); +static int (*fp_gtk_widget_get_allocated_height)(GtkWidget *widget); +static GtkIconTheme* (*fp_gtk_icon_theme_get_default)(void); +static GdkPixbuf* (*fp_gtk_icon_theme_load_icon)(GtkIconTheme *icon_theme, + const gchar *icon_name, gint size, + GtkIconLookupFlags flags, GError **error); +static void (*fp_gtk_adjustment_set_lower)(GtkAdjustment *adjustment, + gdouble lower); +static void (*fp_gtk_adjustment_set_page_increment)(GtkAdjustment *adjustment, + gdouble page_increment); +static void (*fp_gtk_adjustment_set_page_size)(GtkAdjustment *adjustment, + gdouble page_size); +static void (*fp_gtk_adjustment_set_step_increment)(GtkAdjustment *adjustment, + gdouble step_increment); +static void (*fp_gtk_adjustment_set_upper)(GtkAdjustment *adjustment, + gdouble upper); +static void (*fp_gtk_adjustment_set_value)(GtkAdjustment *adjustment, + gdouble value); +static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*); +static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32); +static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean, + gint, gint, gint, gint); +static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, + gboolean has_alpha, int bits_per_sample, int width, int height); +static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, + gint* width, gint* height); +static gboolean (*fp_gtk_init_check)(int* argc, char** argv); + +/* Widget creation */ +static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type, + GtkShadowType shadow_type); +static GtkWidget* (*fp_gtk_button_new)(); +static GtkWidget* (*fp_gtk_check_button_new)(); +static GtkWidget* (*fp_gtk_check_menu_item_new)(); +static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title); +static GtkWidget* (*fp_gtk_combo_box_new)(); +static GtkWidget* (*fp_gtk_combo_box_entry_new)(); +static GtkWidget* (*fp_gtk_entry_new)(); +static GtkWidget* (*fp_gtk_fixed_new)(); +static GtkWidget* (*fp_gtk_handle_box_new)(); +static GtkWidget* (*fp_gtk_hpaned_new)(); +static GtkWidget* (*fp_gtk_vpaned_new)(); +static GtkWidget* (*fp_gtk_scale_new)(GtkOrientation orientation, + GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment); +static GtkWidget* (*fp_gtk_hseparator_new)(); +static GtkWidget* (*fp_gtk_vseparator_new)(); +static GtkWidget* (*fp_gtk_image_new)(); +static GtkWidget* (*fp_gtk_label_new)(const gchar* str); +static GtkWidget* (*fp_gtk_menu_new)(); +static GtkWidget* (*fp_gtk_menu_bar_new)(); +static GtkWidget* (*fp_gtk_menu_item_new)(); +static GtkWidget* (*fp_gtk_notebook_new)(); +static GtkWidget* (*fp_gtk_progress_bar_new)(); +static GtkWidget* (*fp_gtk_progress_bar_set_orientation)( + GtkProgressBar *pbar, + GtkProgressBarOrientation orientation); +static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group); +static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group); +static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +static GtkWidget* (*fp_gtk_separator_menu_item_new)(); +static GtkWidget* (*fp_gtk_separator_tool_item_new)(); +static GtkWidget* (*fp_gtk_text_view_new)(); +static GtkWidget* (*fp_gtk_toggle_button_new)(); +static GtkWidget* (*fp_gtk_toolbar_new)(); +static GtkWidget* (*fp_gtk_tree_view_new)(); +static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type); +static GtkWidget* (*fp_gtk_dialog_new)(); +static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment, + gdouble climb_rate, guint digits); +static GtkWidget* (*fp_gtk_frame_new)(const gchar *label); + +/* Other widget operations */ +static GtkAdjustment* (*fp_gtk_adjustment_new)(gdouble value, + gdouble lower, gdouble upper, gdouble step_increment, + gdouble page_increment, gdouble page_size); +static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget); +static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, + GtkWidget *child); +static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, + GtkWidget *submenu); +static void (*fp_gtk_widget_realize)(GtkWidget *widget); +static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, + const gchar *stock_id, GtkIconSize size, const gchar *detail); +static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); +static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent); +static void (*fp_gtk_widget_set_direction)(GtkWidget *widget, + GtkTextDirection direction); +static void (*fp_gtk_widget_style_get)(GtkWidget *widget, + const gchar *first_property_name, ...); +static void (*fp_gtk_widget_class_install_style_property)( + GtkWidgetClass* class, GParamSpec *pspec); +static GParamSpec* (*fp_gtk_widget_class_find_style_property)( + GtkWidgetClass* class, const gchar* property_name); +static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget, + const gchar* property_name, GValue* value); +static char* (*fp_pango_font_description_to_string)( + const PangoFontDescription* fd); +static GtkSettings* (*fp_gtk_settings_get_default)(); +static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget); +static GType (*fp_gtk_border_get_type)(); +static void (*fp_gtk_arrow_set)(GtkWidget* arrow, + GtkArrowType arrow_type, + GtkShadowType shadow_type); +static void (*fp_gtk_widget_size_request)(GtkWidget *widget, + GtkRequisition *requisition); +static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); + +#endif /* !_GTK3_INTERFACE_H */ diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c new file mode 100644 index 00000000000..0a136b39768 --- /dev/null +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c @@ -0,0 +1,158 @@ +/* + * 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 + * 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 +#include +#include "jvm_md.h" +#include "gtk_interface.h" + +GtkApi* gtk2_load(JNIEnv *env, const char* lib_name); +GtkApi* gtk3_load(JNIEnv *env, const char* lib_name); + +gboolean gtk2_check(const char* lib_name, int flags); +gboolean gtk3_check(const char* lib_name, int flags); + +GtkApi *gtk; + +typedef struct { + GtkVersion version; + const char* name; + const char* vname; + GtkApi* (*load)(JNIEnv *env, const char* lib_name); + gboolean (*check)(const char* lib_name, int flags); +} GtkLib; + +static GtkLib libs[] = { + { + GTK_2, + JNI_LIB_NAME("gtk-x11-2.0"), + VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"), + >k2_load, + >k2_check + }, + { + GTK_3, + JNI_LIB_NAME("gtk-3"), + VERSIONED_JNI_LIB_NAME("gtk-3", "0"), + >k3_load, + >k3_check + }, + { + 0, + NULL, + NULL, + NULL, + NULL + } +}; + +static GtkLib* get_loaded() { + GtkLib* lib = libs; + while(!gtk && lib->version) { + if (lib->check(lib->vname, RTLD_NOLOAD)) { + return lib; + } + if (lib->check(lib->name, RTLD_NOLOAD)) { + return lib; + } + lib++; + } + return NULL; +} + +gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose) { + if (gtk == NULL) { + GtkLib* lib = get_loaded(); + if (lib) { + if (version != GTK_ANY && lib->version != version) { + if (verbose) { + fprintf(stderr, "WARNING: Cannot load GTK%d library: \ + GTK%d has already been loaded\n", version, lib->version); + } + return FALSE; + } + if (verbose) { + fprintf(stderr, "Looking for GTK%d library...\n", version); + } + gtk = lib->load(env, lib->vname); + if (!gtk) { + gtk = lib->load(env, lib->name); + } + } else { + lib = libs; + while (!gtk && lib->version) { + if (version == GTK_ANY || lib->version == version) { + if (verbose) { + fprintf(stderr, "Looking for GTK%d library...\n", + lib->version); + } + gtk = lib->load(env, lib->vname); + if (!gtk) { + gtk = lib->load(env, lib->name); + } + if (verbose && !gtk) { + fprintf(stderr, "Not found.\n"); + } + } + lib++; + } + lib--; + } + if (verbose) { + if (gtk) { + fprintf(stderr, "GTK%d library loaded.\n", lib->version); + } else { + fprintf(stderr, "Failed to load GTK library.\n"); + } + } + } + return gtk != NULL; +} + +static gboolean check_version(GtkVersion version, int flags) { + GtkLib* lib = libs; + while (lib->version) { + if (version == GTK_ANY || lib->version == version) { + if (lib->check(lib->vname, flags)) { + return TRUE; + } + if (lib->check(lib->name, flags)) { + return TRUE; + } + } + lib++; + } + return FALSE; +} + +gboolean gtk_check_version(GtkVersion version) { + if (gtk) { + return TRUE; + } + if (check_version(version, RTLD_NOLOAD)) { + return TRUE; + } + return check_version(version, RTLD_LAZY | RTLD_LOCAL); +} + diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h new file mode 100644 index 00000000000..e39e172f7e5 --- /dev/null +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h @@ -0,0 +1,560 @@ +/* + * 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 + * 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. + */ +#ifndef _GTK_INTERFACE_H +#define _GTK_INTERFACE_H + +#include +#include + +#ifndef FALSE +#define FALSE (0) +#define TRUE (!FALSE) +#endif + +#define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip) +#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) \ + (_G_TYPE_CIC ((instance), (g_type), c_type)) +#define GTK_TYPE_FILE_CHOOSER (fp_gtk_file_chooser_get_type ()) +#define GTK_FILE_CHOOSER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser)) +#define G_CALLBACK(f) ((GCallback) (f)) +#define G_TYPE_FUNDAMENTAL_SHIFT (2) +#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) +#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) +#define GTK_STOCK_CANCEL "gtk-cancel" +#define GTK_STOCK_SAVE "gtk-save" +#define GTK_STOCK_OPEN "gtk-open" +#define GDK_CURRENT_TIME 0L + +#define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0) +#define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1) +#define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2) +#define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3) +#define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4) +#define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5) +#define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6) +#define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7) +#define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8) +#define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9) +#define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10) +#define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11) +#define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12) +#define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13) +#define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14) +#define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15) +#define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16) +#define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17) +#define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18) +#define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19) +#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20) + +#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) + +#define G_TYPE_FUNDAMENTAL_SHIFT (2) +#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#define CONV_BUFFER_SIZE 128 +#define NO_SYMBOL_EXCEPTION 1 + +/* basic types */ +typedef char gchar; +typedef short gshort; +typedef int gint; +typedef long glong; +typedef float gfloat; +typedef double gdouble; +typedef void* gpointer; +typedef gint gboolean; +typedef signed char gint8; +typedef signed short gint16; +typedef signed int gint32; +typedef unsigned char guchar; +typedef unsigned char guint8; +typedef unsigned short gushort; +typedef unsigned short guint16; +typedef unsigned int guint; +typedef unsigned int guint32; +typedef unsigned int gsize; +typedef unsigned long gulong; +typedef signed long long gint64; +typedef unsigned long long guint64; +typedef gulong GType; + +typedef struct _GList GList; +struct _GList +{ + gpointer data; + GList *next; + GList *prev; +}; + +typedef struct _GSList GSList; +struct _GSList { + gpointer data; + GSList *next; +}; + +typedef enum { + BUTTON, /* GtkButton */ + CHECK_BOX, /* GtkCheckButton */ + CHECK_BOX_MENU_ITEM, /* GtkCheckMenuItem */ + COLOR_CHOOSER, /* GtkColorSelectionDialog */ + COMBO_BOX, /* GtkComboBox */ + COMBO_BOX_ARROW_BUTTON, /* GtkComboBoxEntry */ + COMBO_BOX_TEXT_FIELD, /* GtkComboBoxEntry */ + DESKTOP_ICON, /* GtkLabel */ + DESKTOP_PANE, /* GtkContainer */ + EDITOR_PANE, /* GtkTextView */ + FORMATTED_TEXT_FIELD, /* GtkEntry */ + HANDLE_BOX, /* GtkHandleBox */ + HPROGRESS_BAR, /* GtkProgressBar */ + HSCROLL_BAR, /* GtkHScrollbar */ + HSCROLL_BAR_BUTTON_LEFT, /* GtkHScrollbar */ + HSCROLL_BAR_BUTTON_RIGHT, /* GtkHScrollbar */ + HSCROLL_BAR_TRACK, /* GtkHScrollbar */ + HSCROLL_BAR_THUMB, /* GtkHScrollbar */ + HSEPARATOR, /* GtkHSeparator */ + HSLIDER, /* GtkHScale */ + HSLIDER_TRACK, /* GtkHScale */ + HSLIDER_THUMB, /* GtkHScale */ + HSPLIT_PANE_DIVIDER, /* GtkHPaned */ + INTERNAL_FRAME, /* GtkWindow */ + INTERNAL_FRAME_TITLE_PANE, /* GtkLabel */ + IMAGE, /* GtkImage */ + LABEL, /* GtkLabel */ + LIST, /* GtkTreeView */ + MENU, /* GtkMenu */ + MENU_BAR, /* GtkMenuBar */ + MENU_ITEM, /* GtkMenuItem */ + MENU_ITEM_ACCELERATOR, /* GtkLabel */ + OPTION_PANE, /* GtkMessageDialog */ + PANEL, /* GtkContainer */ + PASSWORD_FIELD, /* GtkEntry */ + POPUP_MENU, /* GtkMenu */ + POPUP_MENU_SEPARATOR, /* GtkSeparatorMenuItem */ + RADIO_BUTTON, /* GtkRadioButton */ + RADIO_BUTTON_MENU_ITEM, /* GtkRadioMenuItem */ + ROOT_PANE, /* GtkContainer */ + SCROLL_PANE, /* GtkScrolledWindow */ + SPINNER, /* GtkSpinButton */ + SPINNER_ARROW_BUTTON, /* GtkSpinButton */ + SPINNER_TEXT_FIELD, /* GtkSpinButton */ + SPLIT_PANE, /* GtkPaned */ + TABBED_PANE, /* GtkNotebook */ + TABBED_PANE_TAB_AREA, /* GtkNotebook */ + TABBED_PANE_CONTENT, /* GtkNotebook */ + TABBED_PANE_TAB, /* GtkNotebook */ + TABLE, /* GtkTreeView */ + TABLE_HEADER, /* GtkButton */ + TEXT_AREA, /* GtkTextView */ + TEXT_FIELD, /* GtkEntry */ + TEXT_PANE, /* GtkTextView */ + TITLED_BORDER, /* GtkFrame */ + TOGGLE_BUTTON, /* GtkToggleButton */ + TOOL_BAR, /* GtkToolbar */ + TOOL_BAR_DRAG_WINDOW, /* GtkToolbar */ + TOOL_BAR_SEPARATOR, /* GtkSeparatorToolItem */ + TOOL_TIP, /* GtkWindow */ + TREE, /* GtkTreeView */ + TREE_CELL, /* GtkTreeView */ + VIEWPORT, /* GtkViewport */ + VPROGRESS_BAR, /* GtkProgressBar */ + VSCROLL_BAR, /* GtkVScrollbar */ + VSCROLL_BAR_BUTTON_UP, /* GtkVScrollbar */ + VSCROLL_BAR_BUTTON_DOWN, /* GtkVScrollbar */ + VSCROLL_BAR_TRACK, /* GtkVScrollbar */ + VSCROLL_BAR_THUMB, /* GtkVScrollbar */ + VSEPARATOR, /* GtkVSeparator */ + VSLIDER, /* GtkVScale */ + VSLIDER_TRACK, /* GtkVScale */ + VSLIDER_THUMB, /* GtkVScale */ + VSPLIT_PANE_DIVIDER, /* GtkVPaned */ + WIDGET_TYPE_SIZE +} WidgetType; + +typedef enum +{ + _GTK_ARROW_TYPE, + _GTK_BUTTON_TYPE, + _GTK_CHECK_BUTTON_TYPE, + _GTK_CHECK_MENU_ITEM_TYPE, + _GTK_COLOR_SELECTION_DIALOG_TYPE, + _GTK_COMBO_BOX_TYPE, + _GTK_COMBO_BOX_ARROW_BUTTON_TYPE, + _GTK_COMBO_BOX_TEXT_FIELD_TYPE, + _GTK_CONTAINER_TYPE, + _GTK_ENTRY_TYPE, + _GTK_FRAME_TYPE, + _GTK_HANDLE_BOX_TYPE, + _GTK_HPANED_TYPE, + _GTK_HPROGRESS_BAR_TYPE, + _GTK_HSCALE_TYPE, + _GTK_HSCROLLBAR_TYPE, + _GTK_HSEPARATOR_TYPE, + _GTK_IMAGE_TYPE, + _GTK_MENU_TYPE, + _GTK_MENU_BAR_TYPE, + _GTK_MENU_ITEM_TYPE, + _GTK_NOTEBOOK_TYPE, + _GTK_LABEL_TYPE, + _GTK_RADIO_BUTTON_TYPE, + _GTK_RADIO_MENU_ITEM_TYPE, + _GTK_SCROLLED_WINDOW_TYPE, + _GTK_SEPARATOR_MENU_ITEM_TYPE, + _GTK_SEPARATOR_TOOL_ITEM_TYPE, + _GTK_SPIN_BUTTON_TYPE, + _GTK_TEXT_VIEW_TYPE, + _GTK_TOGGLE_BUTTON_TYPE, + _GTK_TOOLBAR_TYPE, + _GTK_TOOLTIP_TYPE, + _GTK_TREE_VIEW_TYPE, + _GTK_VIEWPORT_TYPE, + _GTK_VPANED_TYPE, + _GTK_VPROGRESS_BAR_TYPE, + _GTK_VSCALE_TYPE, + _GTK_VSCROLLBAR_TYPE, + _GTK_VSEPARATOR_TYPE, + _GTK_WINDOW_TYPE, + _GTK_DIALOG_TYPE, + _GTK_WIDGET_TYPE_SIZE +} GtkWidgetType; + +typedef enum +{ + GTK_STATE_NORMAL, + GTK_STATE_ACTIVE, + GTK_STATE_PRELIGHT, + GTK_STATE_SELECTED, + GTK_STATE_INSENSITIVE, + GTK_STATE_INCONSISTENT, + GTK_STATE_FOCUSED +} GtkStateType; + +typedef enum +{ + GTK_SHADOW_NONE, + GTK_SHADOW_IN, + GTK_SHADOW_OUT, + GTK_SHADOW_ETCHED_IN, + GTK_SHADOW_ETCHED_OUT +} GtkShadowType; + +typedef enum +{ + GTK_EXPANDER_COLLAPSED, + GTK_EXPANDER_SEMI_COLLAPSED, + GTK_EXPANDER_SEMI_EXPANDED, + GTK_EXPANDER_EXPANDED +} GtkExpanderStyle; + +typedef enum +{ + GTK_ICON_SIZE_INVALID, + GTK_ICON_SIZE_MENU, + GTK_ICON_SIZE_SMALL_TOOLBAR, + GTK_ICON_SIZE_LARGE_TOOLBAR, + GTK_ICON_SIZE_BUTTON, + GTK_ICON_SIZE_DND, + GTK_ICON_SIZE_DIALOG +} GtkIconSize; + +typedef enum +{ + GTK_ORIENTATION_HORIZONTAL, + GTK_ORIENTATION_VERTICAL +} GtkOrientation; + +typedef enum +{ + FOREGROUND, + BACKGROUND, + TEXT_FOREGROUND, + TEXT_BACKGROUND, + FOCUS, + LIGHT, + DARK, + MID, + BLACK, + WHITE +} ColorType; + +typedef enum +{ + GTK_FONT_NAME, + GTK_ICON_SIZES, + GTK_CURSOR_BLINK, + GTK_CURSOR_BLINK_TIME +} Setting; + +typedef enum +{ + GTK_ARROW_UP, + GTK_ARROW_DOWN, + GTK_ARROW_LEFT, + GTK_ARROW_RIGHT, + GTK_ARROW_NONE +} GtkArrowType; + +typedef enum +{ + GTK_TEXT_DIR_NONE, + GTK_TEXT_DIR_LTR, + GTK_TEXT_DIR_RTL +} GtkTextDirection; + +typedef enum +{ + GTK_POS_LEFT, + GTK_POS_RIGHT, + GTK_POS_TOP, + GTK_POS_BOTTOM +} GtkPositionType; + +/* SynthConstants */ +static const gint ENABLED = 1 << 0; +static const gint MOUSE_OVER = 1 << 1; +static const gint PRESSED = 1 << 2; +static const gint DISABLED = 1 << 3; +static const gint FOCUSED = 1 << 8; +static const gint SELECTED = 1 << 9; +static const gint DEFAULT = 1 << 10; + +typedef enum +{ + GTK_ANY, + GTK_1, + GTK_2, + GTK_3 +} GtkVersion; + +//------------------------------ + + + +typedef enum { + GTK_RESPONSE_NONE = -1, + GTK_RESPONSE_REJECT = -2, + GTK_RESPONSE_ACCEPT = -3, + GTK_RESPONSE_DELETE_EVENT = -4, + GTK_RESPONSE_OK = -5, + GTK_RESPONSE_CANCEL = -6, + GTK_RESPONSE_CLOSE = -7, + GTK_RESPONSE_YES = -8, + GTK_RESPONSE_NO = -9, + GTK_RESPONSE_APPLY = -10, + GTK_RESPONSE_HELP = -11 +} GtkResponseType; + +typedef enum { + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +} GtkFileChooserAction; + +typedef enum { + GTK_FILE_FILTER_FILENAME = 1 << 0, + GTK_FILE_FILTER_URI = 1 << 1, + GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, + GTK_FILE_FILTER_MIME_TYPE = 1 << 3 +} GtkFileFilterFlags; + +typedef enum { + GDK_COLORSPACE_RGB +} GdkColorspace; + +typedef enum { + GDK_INTERP_NEAREST, + GDK_INTERP_TILES, + GDK_INTERP_BILINEAR, + GDK_INTERP_HYPER +} GdkInterpType; + +typedef enum { + G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1 +} GConnectFlags; +//------------------------------ + + +typedef void GError; +typedef void GdkScreen; +typedef void GtkWindow; +typedef void GdkWindow; +typedef void GClosure; +typedef void GtkFileChooser; +typedef void GtkFileFilter; +typedef struct { + GtkFileFilterFlags contains; + const gchar *filename; + const gchar *uri; + const gchar *display_name; + const gchar *mime_type; +} GtkFileFilterInfo; +typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info, + gpointer data); +typedef void (*GClosureNotify)(gpointer data, GClosure *closure); +typedef void (*GDestroyNotify)(gpointer data); +typedef void (*GCallback)(void); + + +typedef struct GtkApi { + int version; + gboolean (*show_uri_load)(JNIEnv *env); + gboolean (*unload)(); + void (*flush_event_loop)(); + gchar* (*gtk_check_version)(guint required_major, guint required_minor, + guint required_micro); + jobject (*get_setting)(JNIEnv *env, Setting property); + + void (*paint_arrow)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkArrowType arrow_type, gboolean fill); + void (*paint_box)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir); + void (*paint_box_gap)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + GtkPositionType gap_side, gint gap_x, gint gap_width); + void (*paint_expander)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height, + GtkExpanderStyle expander_style); + void (*paint_extension)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkPositionType gap_side); + void (*paint_flat_box)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, gboolean has_focus); + void (*paint_focus)(WidgetType widget_type, GtkStateType state_type, + const char *detail, gint x, gint y, gint width, gint height); + void (*paint_handle)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation); + void (*paint_hline)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_vline)(WidgetType widget_type, GtkStateType state_type, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_option)(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*paint_shadow)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, + gint synth_state, GtkTextDirection dir); + void (*paint_slider)(WidgetType widget_type, GtkStateType state_type, + GtkShadowType shadow_type, const gchar *detail, + gint x, gint y, gint width, gint height, GtkOrientation orientation, + gboolean has_focus); + void (*paint_background)(WidgetType widget_type, GtkStateType state_type, + gint x, gint y, gint width, gint height); + void (*paint_check)(WidgetType widget_type, gint synth_state, + const gchar *detail, gint x, gint y, gint width, gint height); + void (*set_range_value)(WidgetType widget_type, jdouble value, + jdouble min, jdouble max, jdouble visible); + + void (*init_painting)(JNIEnv *env, gint w, gint h); + gint (*copy_image)(gint *dest, gint width, gint height); + + gint (*get_xthickness)(JNIEnv *env, WidgetType widget_type); + gint (*get_ythickness)(JNIEnv *env, WidgetType widget_type); + gint (*get_color_for_state)(JNIEnv *env, WidgetType widget_type, + GtkStateType state_type, ColorType color_type); + jobject (*get_class_value)(JNIEnv *env, WidgetType widget_type, + const char* key); + + jstring (*get_pango_font_name)(JNIEnv *env, WidgetType widget_type); + jboolean (*get_icon_data)(JNIEnv *env, gint widget_type, + const gchar *stock_id, GtkIconSize size, + GtkTextDirection direction, const char *detail, + jmethodID icon_upcall_method, jobject this); + jboolean (*get_file_icon_data)(JNIEnv *env, const char *filename, + GError **error, jmethodID icon_upcall_method, jobject this); + void (*gdk_threads_enter)(void); + void (*gdk_threads_leave)(void); + gboolean (*gtk_show_uri)(GdkScreen *screen, const gchar *uri, + guint32 timestamp, GError **error); + gboolean (*get_drawable_data)(JNIEnv *env, jintArray pixelArray, + jint x, jint y, jint width, jint height, + jint jwidth, int dx, int dy, jint scale); + void (*g_free)(gpointer mem); + + + gchar* (*gtk_file_chooser_get_filename)(GtkFileChooser *chooser); + void (*gtk_widget_hide)(void* widget); + void (*gtk_main_quit)(void); + void* (*gtk_file_chooser_dialog_new)(const gchar *title, + GtkWindow *parent, GtkFileChooserAction action, + const gchar *first_button_text, ...); + gboolean (*gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, + const gchar *filename); + gboolean (*gtk_file_chooser_set_filename)(GtkFileChooser *chooser, + const char *filename); + void (*gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, + const gchar *name); + void (*gtk_file_filter_add_custom)(GtkFileFilter *filter, + GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); + void (*gtk_file_chooser_set_filter)(GtkFileChooser *chooser, + GtkFileFilter *filter); + GType (*gtk_file_chooser_get_type)(void); + GtkFileFilter* (*gtk_file_filter_new)(void); + void (*gtk_file_chooser_set_do_overwrite_confirmation)( + GtkFileChooser *chooser, gboolean do_overwrite_confirmation); + void (*gtk_file_chooser_set_select_multiple)( + GtkFileChooser *chooser, gboolean select_multiple); + gchar* (*gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); + GSList* (*gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); + guint (*gtk_g_slist_length)(GSList *list); + gulong (*g_signal_connect_data)(gpointer instance, + const gchar *detailed_signal, GCallback c_handler, gpointer data, + GClosureNotify destroy_data, GConnectFlags connect_flags); + void (*gtk_widget_show)(void *widget); + void (*gtk_main)(void); + guint (*gtk_main_level)(void); + gchar* (*g_path_get_dirname) (const gchar *file_name); + XID (*gdk_x11_drawable_get_xid) (void *drawable); + void (*gtk_widget_destroy)(void *widget); + void (*gtk_window_present)(void *window); + void (*gtk_window_move)(void *window, gint x, gint y); + void (*gtk_window_resize)(void *window, gint width, gint height); + GdkWindow *(*get_window)(void *widget); + + void (*g_object_unref)(gpointer object); + GList* (*g_list_append) (GList *list, gpointer data); + void (*g_list_free) (GList *list); + void (*g_list_free_full) (GList *list, GDestroyNotify free_func); +} GtkApi; + +gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose); +gboolean gtk_check_version(GtkVersion version); + +extern GtkApi* gtk; + +#endif /* !_GTK_INTERFACE_H */ diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c index 97fbcc60da0..556fe252538 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,11 +28,12 @@ #include #include #include -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "sun_awt_X11_GtkFileDialogPeer.h" #include "java_awt_FileDialog.h" #include "debug_assert.h" +typedef void GtkWidget; static JavaVM *jvm; /* To cache some method IDs */ @@ -90,20 +91,20 @@ static void quit(JNIEnv * env, jobject jpeer, gboolean isSignalHandler) { // Callbacks from GTK signals are made within the GTK lock // So, within a signal handler there is no need to call - // gdk_threads_enter() / fp_gdk_threads_leave() + // gdk_threads_enter() / gtk->gdk_threads_leave() if (!isSignalHandler) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); } - fp_gtk_widget_hide (dialog); - fp_gtk_widget_destroy (dialog); + gtk->gtk_widget_hide (dialog); + gtk->gtk_widget_destroy (dialog); - fp_gtk_main_quit (); + gtk->gtk_main_quit (); (*env)->SetLongField(env, jpeer, widgetFieldID, 0); if (!isSignalHandler) { - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } } @@ -133,16 +134,16 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_toFront { GtkWidget * dialog; - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); dialog = (GtkWidget*)jlong_to_ptr( (*env)->GetLongField(env, jpeer, widgetFieldID)); if (dialog != NULL) { - fp_gtk_window_present((GtkWindow*)dialog); + gtk->gtk_window_present((GtkWindow*)dialog); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -155,21 +156,21 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_setBounds { GtkWindow* dialog; - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); dialog = (GtkWindow*)jlong_to_ptr( (*env)->GetLongField(env, jpeer, widgetFieldID)); if (dialog != NULL) { if (x >= 0 && y >= 0) { - fp_gtk_window_move(dialog, (gint)x, (gint)y); + gtk->gtk_window_move(dialog, (gint)x, (gint)y); } if (width > 0 && height > 0) { - fp_gtk_window_resize(dialog, (gint)width, (gint)height); + gtk->gtk_window_resize(dialog, (gint)width, (gint)height); } } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -182,18 +183,18 @@ static gboolean isFromSameDirectory(GSList* list, gchar** baseDir) { gboolean isAllDirsSame = TRUE; while (it) { - gchar* dir = fp_g_path_get_dirname((gchar*) it->data); + gchar* dir = gtk->g_path_get_dirname((gchar*) it->data); if (prevDir && strcmp(prevDir, dir) != 0) { isAllDirsSame = FALSE; - fp_g_free(dir); + gtk->g_free(dir); break; } if (!prevDir) { prevDir = strdup(dir); } - fp_g_free(dir); + gtk->g_free(dir); it = it->next; } @@ -233,7 +234,7 @@ static jobjectArray toFilenamesArray(JNIEnv *env, GSList* list, jstring* jcurren return NULL; } - array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL); + array = (*env)->NewObjectArray(env, gtk->gtk_g_slist_length(list), stringCls, NULL); if (array == NULL) { (*env)->ExceptionClear(env); JNU_ThrowInternalError(env, "Could not instantiate array files array"); @@ -287,7 +288,7 @@ static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) filenames = NULL; if (responseId == GTK_RESPONSE_ACCEPT) { - filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); + filenames = gtk->gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog)); } jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder); @@ -318,7 +319,7 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, JNU_CHECK_EXCEPTION(env); } - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0); if (title == NULL) { @@ -329,19 +330,19 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, if (mode == java_awt_FileDialog_SAVE) { /* Save action */ - dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); } else { /* Default action OPEN */ - dialog = fp_gtk_file_chooser_dialog_new(title, NULL, + dialog = gtk->gtk_file_chooser_dialog_new(title, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); /* Set multiple selection mode, that is allowed only in OPEN action */ if (multiple) { - fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), + gtk->gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), multiple); } } @@ -358,7 +359,7 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, JNU_ThrowOutOfMemoryError(env, "Could not get dir"); return; } - fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); + gtk->gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir); (*env)->ReleaseStringUTFChars(env, jdir, dir); } @@ -371,47 +372,48 @@ Java_sun_awt_X11_GtkFileDialogPeer_run(JNIEnv * env, jobject jpeer, return; } if (mode == java_awt_FileDialog_SAVE) { - fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); + gtk->gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename); } else { - fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); + gtk->gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename); } (*env)->ReleaseStringUTFChars(env, jfile, filename); } /* Set the file filter */ if (jfilter != NULL) { - filter = fp_gtk_file_filter_new(); - fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, + filter = gtk->gtk_file_filter_new(); + gtk->gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, filenameFilterCallback, jpeer, NULL); - fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk->gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); } /* Other Properties */ - if (fp_gtk_check_version(2, 8, 0) == NULL) { - fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( + if (gtk->gtk_check_version(2, 8, 0) == NULL || + gtk->gtk_check_version(3, 0, 0) == NULL) { + gtk->gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER( dialog), TRUE); } /* Set the initial location */ if (x >= 0 && y >= 0) { - fp_gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); + gtk->gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y); // NOTE: it doesn't set the initial size for the file chooser // as it seems like the file chooser overrides the size internally } - fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK( - handle_response), jpeer); + gtk->g_signal_connect_data(dialog, "response", G_CALLBACK( + handle_response), jpeer, 0, 0); (*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog)); - fp_gtk_widget_show(dialog); + gtk->gtk_widget_show(dialog); - XID xid = fp_gdk_x11_drawable_get_xid(dialog->window); + XID xid = gtk->gdk_x11_drawable_get_xid(gtk->get_window(dialog)); if( (*env)->CallBooleanMethod(env, jpeer, setWindowMethodID, xid) ) { - fp_gtk_main(); + gtk->gtk_main(); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c index 7d9db4a5632..47c7ad23ebd 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, 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 @@ -24,9 +24,24 @@ */ #include -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "com_sun_java_swing_plaf_gtk_GTKEngine.h" +/* Static buffer for conversion from java.lang.String to UTF-8 */ +static char conversionBuffer[CONV_BUFFER_SIZE]; + +const char *getStrFor(JNIEnv *env, jstring val) +{ + int length = (*env)->GetStringLength(env, val); + if (length > CONV_BUFFER_SIZE-1) + { + length = CONV_BUFFER_SIZE-1; + } + + (*env)->GetStringUTFRegion(env, val, 0, length, conversionBuffer); + return conversionBuffer; +} + /* * Class: com_sun_java_swing_plaf_gtk_GTKEngine * Method: native_paint_arrow @@ -38,10 +53,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint arrow_type) { - fp_gdk_threads_enter(); - gtk2_paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, arrow_type, TRUE); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -56,10 +71,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box( jint x, jint y, jint w, jint h, jint synth_state, jint dir) { - fp_gdk_threads_enter(); - gtk2_paint_box(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -74,10 +89,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box_1gap( jint x, jint y, jint w, jint h, jint gap_side, jint gap_x, jint gap_w) { - fp_gdk_threads_enter(); - gtk2_paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, gap_side, gap_x, gap_w); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -91,10 +106,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1check( jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_check(widget_type, synth_state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_check(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -108,10 +123,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1expander( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h, jint expander_style) { - fp_gdk_threads_enter(); - gtk2_paint_expander(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_expander(widget_type, state, getStrFor(env, detail), x, y, w, h, expander_style); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -125,10 +140,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1extension( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint placement) { - fp_gdk_threads_enter(); - gtk2_paint_extension(widget_type, state, shadow_type, + gtk->gdk_threads_enter(); + gtk->paint_extension(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, placement); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -142,10 +157,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1flat_1box( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jboolean has_focus) { - fp_gdk_threads_enter(); - gtk2_paint_flat_box(widget_type, state, shadow_type, + gtk->gdk_threads_enter(); + gtk->paint_flat_box(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, has_focus); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -159,10 +174,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1focus( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_focus(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_focus(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -176,10 +191,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1handle( jint widget_type, jint state, jint shadow_type, jstring detail, jint x, jint y, jint w, jint h, jint orientation) { - fp_gdk_threads_enter(); - gtk2_paint_handle(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_handle(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, orientation); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -193,10 +208,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1hline( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_hline(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_hline(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -210,10 +225,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1option( jint widget_type, jint synth_state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_option(widget_type, synth_state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_option(widget_type, synth_state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -228,10 +243,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1shadow( jint x, jint y, jint w, jint h, jint synth_state, jint dir) { - fp_gdk_threads_enter(); - gtk2_paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail), x, y, w, h, synth_state, dir); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -243,12 +258,12 @@ JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1slider( JNIEnv *env, jobject this, jint widget_type, jint state, jint shadow_type, jstring detail, - jint x, jint y, jint w, jint h, jint orientation) + jint x, jint y, jint w, jint h, jint orientation, jboolean has_focus) { - fp_gdk_threads_enter(); - gtk2_paint_slider(widget_type, state, shadow_type, getStrFor(env, detail), - x, y, w, h, orientation); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->paint_slider(widget_type, state, shadow_type, getStrFor(env, detail), + x, y, w, h, orientation, has_focus); + gtk->gdk_threads_leave(); } /* @@ -262,10 +277,10 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1vline( jint widget_type, jint state, jstring detail, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_paint_vline(widget_type, state, getStrFor(env, detail), + gtk->gdk_threads_enter(); + gtk->paint_vline(widget_type, state, getStrFor(env, detail), x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -278,9 +293,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1background( JNIEnv *env, jobject this, jint widget_type, jint state, jint x, jint y, jint w, jint h) { - fp_gdk_threads_enter(); - gtk_paint_background(widget_type, state, x, y, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->paint_background(widget_type, state, x, y, w, h); + gtk->gdk_threads_leave(); } /* @@ -292,9 +307,9 @@ JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeStartPainting( JNIEnv *env, jobject this, jint w, jint h) { - fp_gdk_threads_enter(); - gtk2_init_painting(env, w, h); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->init_painting(env, w, h); + gtk->gdk_threads_leave(); } /* @@ -308,9 +323,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeFinishPainting( { jint transparency; gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0); - fp_gdk_threads_enter(); - transparency = gtk2_copy_image(buffer, width, height); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + transparency = gtk->copy_image(buffer, width, height); + gtk->gdk_threads_leave(); (*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0); return transparency; } @@ -324,7 +339,9 @@ JNIEXPORT void JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1switch JNIEnv *env, jobject this) { // Note that flush_gtk_event_loop takes care of locks (7053002) - flush_gtk_event_loop(); + gtk->gdk_threads_enter(); + gtk->flush_event_loop(); + gtk->gdk_threads_leave(); } /* @@ -336,9 +353,9 @@ JNIEXPORT jobject JNICALL Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1get JNIEnv *env, jobject this, jint property) { jobject obj; - fp_gdk_threads_enter(); - obj = gtk2_get_setting(env, property); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + obj = gtk->get_setting(env, property); + gtk->gdk_threads_leave(); return obj; } @@ -352,7 +369,7 @@ Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeSetRangeValue( JNIEnv *env, jobject this, jint widget_type, jdouble value, jdouble min, jdouble max, jdouble visible) { - fp_gdk_threads_enter(); - gtk2_set_range_value(widget_type, value, min, max, visible); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->set_range_value(widget_type, value, min, max, visible); + gtk->gdk_threads_leave(); } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c index 9d24eb44973..a977f6bee2e 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, 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 @@ -24,9 +24,12 @@ */ #include -#include "gtk2_interface.h" +#include +#include "gtk_interface.h" #include "com_sun_java_swing_plaf_gtk_GTKStyle.h" +const char *getStrFor(JNIEnv *env, jstring val); + /* * Class: com_sun_java_swing_plaf_gtk_GTKStyle * Method: nativeGetXThickness @@ -37,9 +40,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetXThickness( JNIEnv *env, jclass klass, jint widget_type) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_xthickness(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_xthickness(env, widget_type); + gtk->gdk_threads_leave(); return ret; } @@ -53,9 +56,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetYThickness( JNIEnv *env, jclass klass, jint widget_type) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_ythickness(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_ythickness(env, widget_type); + gtk->gdk_threads_leave(); return ret; } @@ -70,9 +73,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetColorForState( jint state_type, jint type_id) { jint ret; - fp_gdk_threads_enter(); - ret = gtk2_get_color_for_state(env, widget_type, state_type, type_id); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_color_for_state(env, widget_type, state_type, type_id); + gtk->gdk_threads_leave(); return ret; } @@ -86,9 +89,9 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetClassValue( JNIEnv *env, jclass klass, jint widget_type, jstring key) { jobject ret; - fp_gdk_threads_enter(); - ret = gtk2_get_class_value(env, widget_type, key); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_class_value(env, widget_type, getStrFor(env, key)); + gtk->gdk_threads_leave(); return ret; } @@ -102,8 +105,8 @@ Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetPangoFontName( JNIEnv *env, jclass klass, jint widget_type) { jstring ret; - fp_gdk_threads_enter(); - ret = gtk2_get_pango_font_name(env, widget_type); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + ret = gtk->get_pango_font_name(env, widget_type); + gtk->gdk_threads_leave(); return ret; } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c index 0c41daee3ab..96acfb59d11 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -24,7 +24,7 @@ */ #include "jni_util.h" -#include "gtk2_interface.h" +#include "gtk_interface.h" #include "gnome_interface.h" static gboolean gtk_has_been_loaded = FALSE; @@ -36,14 +36,14 @@ static gboolean gnome_has_been_loaded = FALSE; * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XDesktopPeer_init - (JNIEnv *env, jclass cls) + (JNIEnv *env, jclass cls, jint version, jboolean verbose) { if (gtk_has_been_loaded || gnome_has_been_loaded) { return JNI_TRUE; } - if (gtk2_load(env) && gtk2_show_uri_load(env)) { + if (gtk_load(env, version, verbose) && gtk->show_uri_load(env)) { gtk_has_been_loaded = TRUE; return JNI_TRUE; } else if (gnome_load()) { @@ -74,9 +74,9 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XDesktopPeer_gnome_1url_1show } if (gtk_has_been_loaded) { - fp_gdk_threads_enter(); - success = fp_gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + success = gtk->gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL); + gtk->gdk_threads_leave(); } else if (gnome_has_been_loaded) { success = (*gnome_url_show)(url_c, NULL); } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c index 643cc888b51..210f2de4da4 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c @@ -109,7 +109,7 @@ void callback(DbusmenuMenuitem* mi, guint ts, jobject data) { * Signature: (Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init -(JNIEnv *env, jclass cls, jstring jname) { +(JNIEnv *env, jclass cls, jstring jname, jint version, jboolean verbose) { jclass clazz; jTaskbarCls = (*env)->NewGlobalRef(env, cls); @@ -121,7 +121,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init CHECK_NULL_RETURN( jMenuItemGetLabel = (*env)->GetMethodID(env, clazz, "getLabel", "()Ljava/lang/String;"), JNI_FALSE); - if (gtk2_load(env) && unity_load()) { + if (gtk_load(env, version, verbose) && unity_load()) { const gchar* name = (*env)->GetStringUTFChars(env, jname, NULL); if (name) { entry = fp_unity_launcher_entry_get_for_desktop_file(name); @@ -139,9 +139,9 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init */ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_runloop (JNIEnv *env, jclass cls) { - fp_gdk_threads_enter(); - fp_gtk_main(); - fp_gdk_threads_leave(); + gtk->gdk_threads_enter(); + gtk->gtk_main(); + gtk->gdk_threads_leave(); } /* @@ -151,14 +151,14 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_runloop */ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setBadge (JNIEnv *env, jobject obj, jlong value, jboolean visible) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); fp_unity_launcher_entry_set_count(entry, value); fp_unity_launcher_entry_set_count_visible(entry, visible); DbusmenuMenuitem* m; if (m = fp_unity_launcher_entry_get_quicklist(entry)) { fp_unity_launcher_entry_set_quicklist(entry, m); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -168,13 +168,13 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setBadge */ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setUrgent (JNIEnv *env, jobject obj, jboolean urgent) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); fp_unity_launcher_entry_set_urgent(entry, urgent); DbusmenuMenuitem* m; if (m = fp_unity_launcher_entry_get_quicklist(entry)) { fp_unity_launcher_entry_set_quicklist(entry, m); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } /* @@ -184,14 +184,14 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setUrgent */ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_updateProgress (JNIEnv *env, jobject obj, jdouble value, jboolean visible) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); fp_unity_launcher_entry_set_progress(entry, value); fp_unity_launcher_entry_set_progress_visible(entry, visible); DbusmenuMenuitem* m; if (m = fp_unity_launcher_entry_get_quicklist(entry)) { fp_unity_launcher_entry_set_quicklist(entry, m); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } void deleteGlobalRef(gpointer data) { @@ -209,7 +209,7 @@ void fill_menu(JNIEnv *env, jobjectArray items) { } elem = (*env)->NewGlobalRef(env, elem); - globalRefs = fp_g_list_append(globalRefs, elem); + globalRefs = gtk->g_list_append(globalRefs, elem); jstring jlabel = (jstring) (*env)->CallObjectMethod(env, elem, jMenuItemGetLabel); if (!(*env)->ExceptionCheck(env) && jlabel) { @@ -224,7 +224,8 @@ void fill_menu(JNIEnv *env, jobjectArray items) { (*env)->ReleaseStringUTFChars(env, jlabel, label); fp_dbusmenu_menuitem_child_append(menu, mi); - fp_g_signal_connect(mi, "item_activated", G_CALLBACK(callback), elem); + gtk->g_signal_connect_data(mi, "item_activated", + G_CALLBACK(callback), elem, NULL, 0); } } } @@ -238,7 +239,7 @@ void fill_menu(JNIEnv *env, jobjectArray items) { JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setNativeMenu (JNIEnv *env, jobject obj, jobjectArray items) { - fp_gdk_threads_enter(); + gtk->gdk_threads_enter(); if (!menu) { menu = fp_dbusmenu_menuitem_new(); @@ -247,14 +248,14 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setNativeMenu fp_unity_launcher_entry_set_quicklist(entry, menu); GList* list = fp_dbusmenu_menuitem_take_children(menu); - fp_g_list_free_full(list, fp_g_object_unref); + gtk->g_list_free_full(list, gtk->g_object_unref); - fp_g_list_free_full(globalRefs, deleteGlobalRef); + gtk->g_list_free_full(globalRefs, deleteGlobalRef); globalRefs = NULL; if (items) { fill_menu(env, items); } - fp_gdk_threads_leave(); + gtk->gdk_threads_leave(); } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h index 00b8d86dd1f..5baffd8e444 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h @@ -26,7 +26,7 @@ #ifndef AWT_TASKBAR_H #define AWT_TASKBAR_H -#include "gtk2_interface.h" +#include "gtk_interface.h" typedef void UnityLauncherEntry; typedef void DbusmenuMenuitem; diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h index 2ca444725e8..bfd764364d7 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ #ifndef _GNOME_INTERFACE_H #define _GNOME_INTERFACE_H -#include "gtk2_interface.h" +#include "gtk_interface.h" #include #include #include From f4d962e735d90915da9095586b29f2bf671b92e8 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Mon, 25 Apr 2016 09:57:55 -0300 Subject: [PATCH 125/225] 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 126/225] 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 127/225] 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 128/225] 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 129/225] 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 130/225] 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 131/225] 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 132/225] 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 133/225] 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); + From 1c8cb8707ce006fafcec9fc6f11820f8817e710e Mon Sep 17 00:00:00 2001 From: Alexander Stepanov Date: Mon, 25 Apr 2016 18:07:45 +0300 Subject: [PATCH 134/225] 8154962: [TEST] @BeanProperty: add some tests for anonimous classes Reviewed-by: serb --- .../AnonymousClassBeanPropertyTest.java | 867 ++++++++++++++++++ .../beans/Introspector/BeanPropertyTest.java | 107 ++- 2 files changed, 931 insertions(+), 43 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java diff --git a/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java new file mode 100644 index 00000000000..a8ec7d49188 --- /dev/null +++ b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java @@ -0,0 +1,867 @@ +/* + * 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.beans.BeanInfo; +import java.beans.BeanProperty; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; + +import java.util.Arrays; + + +/** + * @test + * @bug 8132973 8132732 8155013 + * @summary Some check for BeanProperty annotation + * @author a.stepanov + * @run main AnonymousClassBeanPropertyTest + */ + + +public class AnonymousClassBeanPropertyTest { + + private final static String DESCRIPTION = "TEST"; + private final static boolean BOUND = true; + private final static boolean EXPERT = false; + private final static boolean HIDDEN = true; + private final static boolean PREFERRED = false; + private final static boolean REQUIRED = true; + private final static boolean UPDATE = false; + + private final static double X = java.lang.Math.PI; + + private final static String + V_NAME = "java.lang.Math.PI", + V_SHORT = "PI", + V = Double.toString(X); + + private final static String DESCRIPTION_2 = "XYZ"; + + + // ---------- test cases (interfaces) ---------- + + private interface IGet { + double getX(); + } + + private interface ISet { + void setX(double v); + } + + private interface IGetByIndex { + double getX(int i); + } + + private interface ISetByIndex { + void setX(int i, double v); + } + + private interface IGetArray { + double[] getX(); + } + + private interface ISetArray { + void setX(double a[]); + } + + private interface IGetBoth { + double getX(int i); + double[] getX(); + } + + private interface ISetBoth { + void setX(int i, double v); + void setX(double a[]); + } + + private interface IGetSet { + double getX(); + void setX(double v); + } + + private interface IGetSetByIndex { + double getX(int i); + void setX(int i, double v); + } + + private interface IGetSetBoth { + double getX(int i); + double[] getX(); + void setX(int i, double v); + void setX(double a[]); + } + + + // ---------- checks ---------- + + private static boolean check(String what, boolean v, boolean ref) { + + boolean ok = (v == ref); + if (!ok) { System.out.println( + "invalid " + what + ": " + v + ", expected: " + ref); } + return ok; + } + + private static boolean checkInfo(Class c, String what) { + + BeanInfo i; + try { i = Introspector.getBeanInfo(c, Object.class); } + catch (IntrospectionException e) { throw new RuntimeException(e); } + + System.out.println("\nchecking info for " + what); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals(DESCRIPTION); + if (!ok) { System.out.println("invalid description: " + descr + + ", expected: " + DESCRIPTION); } + + ok &= check("isBound", d.isBound(), BOUND); + ok &= check("isExpert", d.isExpert(), EXPERT); + ok &= check("isHidden", d.isHidden(), HIDDEN); + ok &= check("isPreferred", d.isPreferred(), PREFERRED); + ok &= check("required", (boolean) d.getValue("required"), REQUIRED); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), UPDATE); + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals == null) { + System.out.println("null enumerationValues"); + return false; + } + + if (vals.length == 0) { + System.out.println("empty enumerationValues"); + return false; + } + + boolean okVals = ( + (vals.length == 3) && + vals[0].toString().equals(V_SHORT) && + vals[1].toString().equals(V) && + vals[2].toString().equals(V_NAME)); + + if (!okVals) { + System.out.println("invalid enumerationValues:"); + for (Object v: vals) { System.out.println(v.toString()); } + } + + return (ok && okVals); + } + + private static boolean checkAlternativeInfo(Class c, String what) { + + BeanInfo i; + try { i = Introspector.getBeanInfo(c, Object.class); } + catch (IntrospectionException e) { throw new RuntimeException(e); } + + System.out.println("checking alternative info for " + what); + + PropertyDescriptor descriptors[] = i.getPropertyDescriptors(); + int nd = descriptors.length; + if (nd != 1) { + System.out.println("invalid number of descriptors: " + nd); + return false; + } + + PropertyDescriptor d = descriptors[0]; + + String descr = d.getShortDescription(); + boolean ok = descr.equals(DESCRIPTION_2); + if (!ok) { System.out.println("invalid alternative description: " + + descr + ", expected: " + DESCRIPTION_2); } + + ok &= check("isBound", d.isBound(), !BOUND); + ok &= check("isExpert", d.isExpert(), !EXPERT); + ok &= check("isHidden", d.isHidden(), !HIDDEN); + ok &= check("isPreferred", d.isPreferred(), !PREFERRED); + ok &= check("required", (boolean) d.getValue("required"), !REQUIRED); + ok &= check("visualUpdate", + (boolean) d.getValue("visualUpdate"), !UPDATE); + + Object vals[] = (Object[]) d.getValue("enumerationValues"); + if (vals != null || vals.length > 0) { + System.out.println("non-empty enumerationValues"); + return false; + } + + return ok; + } + + + + // ---------- run tests ---------- + + public static void main(String[] args) { + + boolean passed = true, ok, ok2; + + //---------------------------------------------------------------------- + + IGet testGet = new IGet() { + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return X; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGet.getClass(), "IGet"); + System.out.println("OK = " + ok); + passed = passed && ok; + + //---------------------------------------------------------------------- + + ISet testSet = new ISet() { + + private double x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSet.getClass(), "ISet"); + System.out.println("OK = " + ok); + passed = passed && ok; + + //---------------------------------------------------------------------- + + IGetByIndex testGetByIndex = new IGetByIndex() { + + private final double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { return x[i]; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetByIndex.getClass(), "IGetByIndex"); + System.out.println("OK = " + ok); + passed = passed && ok; + + //---------------------------------------------------------------------- + + ISetByIndex testSetByIndex = new ISetByIndex() { + + private final double x[] = {X, X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(int i, double v) { x[i] = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSetByIndex.getClass(), "ISetByIndex"); + System.out.println("OK = " + ok); + passed = passed && ok; + + //---------------------------------------------------------------------- + + // TODO: please uncomment/update after 8155013 fix + /* + IGetArray testGetArray = new IGetArray() { + + private final double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double[] getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetArray.getClass(), "IGetArray"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + //---------------------------------------------------------------------- + + // TODO: please uncomment/update after 8155013 fix + /* + ISetArray testSetArray = new ISetArray() { + + private double x[]; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double a[]) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSetArray.getClass(), "ISetArray"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + //---------------------------------------------------------------------- + + IGetBoth testGetBoth_1 = new IGetBoth() { + + private final double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { return x[i]; } + @Override + public double[] getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetBoth_1.getClass(), "IGetBoth-1"); + System.out.println("OK = " + ok); + passed = passed && ok; + + // TODO: please uncomment/update after 8155013 fix + /* + IGetBoth testGetBoth_2 = new IGetBoth() { + + private final double x[] = {X, X}; + + @Override + public double getX(int i) { return x[i]; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double[] getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetBoth_2.getClass(), "IGetBoth-2"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + // TODO: please uncomment/update after 8132732 fix + /* + IGetBoth testGetBoth_3 = new IGetBoth() { + + private final double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { return x[i]; } + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public double[] getX() { return x; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetBoth_3.getClass(), "IGetBoth-3"); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo(testGetBoth_3.getClass(), "IGetBoth-3"); + System.out.println("OK = " + ok2); + passed = passed && ok && ok2; + */ + + //---------------------------------------------------------------------- + + ISetBoth testSetBoth_1 = new ISetBoth() { + + private double x[] = new double[3]; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(int i, double v) { x[i] = v; } + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSetBoth_1.getClass(), "ISetBoth-1"); + System.out.println("OK = " + ok); + passed = passed && ok; + + // TODO: please uncomment/update after 8155013 fix + /* + ISetBoth testSetBoth_2 = new ISetBoth() { + + private double x[] = new double[3]; + + @Override + public void setX(int i, double v) { x[i] = v; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSetBoth_2.getClass(), "ISetBoth-2"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + // TODO: please uncomment/update after 8132732 fix + /* + ISetBoth testSetBoth_3 = new ISetBoth() { + + private double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(int i, double v) { x[i] = v; } + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testSetBoth_3.getClass(), "ISetBoth-3"); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo(testSetBoth_3.getClass(), "ISetBoth-3"); + System.out.println("OK = " + ok2); + passed = passed && ok && ok2; + */ + + //---------------------------------------------------------------------- + + IGetSet testGetSet_1 = new IGetSet() { + + private double x; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX() { return x; } + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSet_1.getClass(), "IGetSet-1"); + System.out.println("OK = " + ok); + passed = passed && ok; + + + IGetSet testGetSet_2 = new IGetSet() { + + private double x; + + @Override + public double getX() { return x; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSet_2.getClass(), "IGetSet-2"); + System.out.println("OK = " + ok); + passed = passed && ok; + + // TODO: please uncomment/update after 8132973 fix + /* + IGetSet testGetSet_3 = new IGetSet() { + + private double x; + + @Override + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + public double getX() { return x; } + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public void setX(double v) { x = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSet_3.getClass(), "IGetSet-3"); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo(testGetSet_3.getClass(), "IGetSet-3"); + System.out.println("OK = " + ok2); + passed = passed && ok && ok2; + */ + + //---------------------------------------------------------------------- + + IGetSetByIndex testGetSetByIndex_1 = new IGetSetByIndex() { + + private final double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { return x[i]; } + @Override + public void setX(int i, double v) { x[i] = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetByIndex_1.getClass(), "IGetSetByIndex-1"); + System.out.println("OK = " + ok); + passed = passed && ok; + + + IGetSetByIndex testGetSetByIndex_2 = new IGetSetByIndex() { + + private final double x[] = {X, X}; + + @Override + public double getX(int i) { return x[i]; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(int i, double v) { x[i] = v; } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetByIndex_2.getClass(), "IGetSetByIndex-2"); + System.out.println("OK = " + ok); + passed = passed && ok; + + // TODO: please uncomment/update after 8132973 fix + /* + IGetSetByIndex testGetSetByIndex_3 = new IGetSetByIndex() { + + private double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { + return x[i]; + } + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public void setX(int i, double v) { + x[i] = v; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetByIndex_3.getClass(), "IGetSetByIndex-3"); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo( + testGetSetByIndex_3.getClass(), "IGetSetByIndex-3"); + System.out.println("OK = " + ok2); + passed = passed && ok && ok2; + */ + + //---------------------------------------------------------------------- + + // TODO: please uncomment/update after 8155013 fix + /* + IGetSetBoth testGetSetBoth_1 = new IGetSetBoth() { + + private double x[] = {X, X}; + + @Override + public double getX(int i) { return x[i]; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double[] getX() { return x; } + @Override + public void setX(int i, double v) { x[i] = v; } + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetBoth_1.getClass(), "IGetSetBoth-1"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + // TODO: please uncomment/update after 8155013 fix + /* + IGetSetBoth testGetSetBoth_2 = new IGetSetBoth() { + + private double x[] = {X, X}; + + @Override + public double getX(int i) { return x[i]; } + @Override + public double[] getX() { return x; } + @Override + public void setX(int i, double v) { x[i] = v; } + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetBoth_2.getClass(), "IGetSetBoth-2"); + System.out.println("OK = " + ok); + passed = passed && ok; + */ + + // TODO: please uncomment/update after 8132973 fix + /* + IGetSetBoth testGetSetBoth_3 = new IGetSetBoth() { + + private double x[] = {X, X}; + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE, + enumerationValues = {V_NAME}) + @Override + public double getX(int i) { return x[i]; } + @Override + public double[] getX() { return x; } + @Override + public void setX(int i, double v) { x[i] = v; } + @BeanProperty( + description = DESCRIPTION_2, + bound = !BOUND, + expert = !EXPERT, + hidden = !HIDDEN, + preferred = !PREFERRED, + required = !REQUIRED, + visualUpdate = !UPDATE) + @Override + public void setX(double[] a) { x = Arrays.copyOf(a, a.length); } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + }; + ok = checkInfo(testGetSetBoth_3.getClass(), "IGetSetBoth-3"); + System.out.println("OK = " + ok); + ok2 = checkAlternativeInfo( + testGetSetBoth_3.getClass(), "IGetSetBoth-3"); + System.out.println("OK = " + ok2); + passed = passed && ok && ok2; + */ + + if (!passed) { throw new RuntimeException("test failed"); } + System.out.println("\ntest passed"); + } +} diff --git a/jdk/test/java/beans/Introspector/BeanPropertyTest.java b/jdk/test/java/beans/Introspector/BeanPropertyTest.java index 0344f378cc6..6f957074c6e 100644 --- a/jdk/test/java/beans/Introspector/BeanPropertyTest.java +++ b/jdk/test/java/beans/Introspector/BeanPropertyTest.java @@ -297,11 +297,7 @@ public class BeanPropertyTest { required = REQUIRED, visualUpdate = UPDATE, enumerationValues = {V_NAME}) - public int getX(int i) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - return x[i]; - } + public int getX(int i) { return x[i]; } public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} @@ -322,11 +318,7 @@ public class BeanPropertyTest { required = REQUIRED, visualUpdate = UPDATE, enumerationValues = {V_NAME}) - public void setX(int i, int v) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - x[i] = v; - } + public void setX(int i, int v) { x[i] = v; } public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} @@ -348,11 +340,7 @@ public class BeanPropertyTest { required = REQUIRED, visualUpdate = UPDATE, enumerationValues = {V_NAME}) - public int getX(int i) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - return x[i]; - } + public int getX(int i) { return x[i]; } public int[] getX() { return x; } @@ -376,11 +364,7 @@ public class BeanPropertyTest { required = REQUIRED, visualUpdate = UPDATE, enumerationValues = {V_NAME}) - public void setX(int i, int v) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - x[i] = v; - } + public void setX(int i, int v) { x[i] = v; } public void setX(int a[]) { x = Arrays.copyOf(a, a.length); } @@ -407,11 +391,7 @@ public class BeanPropertyTest { enumerationValues = {V_NAME}) public int[] getX() { return x; } - public int getX(int i) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - return x[i]; - } + public int getX(int i) { return x[i]; } public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} @@ -436,11 +416,7 @@ public class BeanPropertyTest { enumerationValues = {V_NAME}) public void setX(int a[]) { x = Arrays.copyOf(a, a.length); } - public void setX(int i, int v) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - x[i] = v; - } + public void setX(int i, int v) { x[i] = v; } public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} @@ -472,11 +448,7 @@ public class BeanPropertyTest { preferred = !PREFERRED, required = !REQUIRED, visualUpdate = !UPDATE) - public int getX(int i) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - return x[i]; - } + public int getX(int i) { return x[i]; } public void addPropertyChangeListener(PropertyChangeListener l) {} public void removePropertyChangeListener(PropertyChangeListener l) {} @@ -508,11 +480,7 @@ public class BeanPropertyTest { preferred = !PREFERRED, required = !REQUIRED, visualUpdate = !UPDATE) - public void setX(int i, int v) throws IndexOutOfBoundsException { - if (i < 0 || i >= x.length) { - throw new IndexOutOfBoundsException(); } - x[i] = v; - } + public void setX(int i, int v) { x[i] = v; } public void addPropertyChangeListener(PropertyChangeListener l) {} @@ -837,7 +805,53 @@ public class BeanPropertyTest { public void removePropertyChangeListener(PropertyChangeListener l) {} } + public static class Self { + private final static String TESTCASE = "trivial singleton"; + + private static Self instance = null; + private Self() {} + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public Self getSelf() { + if (instance == null) { instance = new Self(); } + return instance; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } + + public static class SelfArr { + + private final static String TESTCASE = "trivial singleton + array"; + + private static SelfArr arr[] = null; + private SelfArr() {} + + @BeanProperty( + description = DESCRIPTION, + bound = BOUND, + expert = EXPERT, + hidden = HIDDEN, + preferred = PREFERRED, + required = REQUIRED, + visualUpdate = UPDATE) + public SelfArr[] getSelfArr() { + if (arr == null) { arr = new SelfArr[]{new SelfArr(), new SelfArr()}; } + return arr; + } + + public void addPropertyChangeListener(PropertyChangeListener l) {} + public void removePropertyChangeListener(PropertyChangeListener l) {} + } // ---------- checks ---------- @@ -850,7 +864,7 @@ public class BeanPropertyTest { return ok; } - private static boolean checkInfo(BeanInfo i) { + private static boolean checkInfo(BeanInfo i, boolean checkVals) { System.out.println("checking info..."); @@ -876,6 +890,8 @@ public class BeanPropertyTest { ok &= check("visualUpdate", (boolean) d.getValue("visualUpdate"), UPDATE); + if (!checkVals) { return ok; } + Object vals[] = (Object[]) d.getValue("enumerationValues"); if (vals == null) { System.out.println("null enumerationValues"); @@ -936,6 +952,10 @@ public class BeanPropertyTest { c.equals(GS.class)); } + private static boolean ignoreVals(Class c) { + return (c.equals(Self.class) || c.equals(SelfArr.class)); + } + // ---------- run test ---------- @@ -959,7 +979,8 @@ public class BeanPropertyTest { // G14.class, S14.class, // TODO: please update after 8132888 fix or // remove these cases if it is not an issue // GS.class, // TODO: please update after 8132973 fix - getX.class, setX.class + getX.class, setX.class, + Self.class, SelfArr.class }; boolean passed = true; @@ -974,7 +995,7 @@ public class BeanPropertyTest { BeanInfo i; try { i = Introspector.getBeanInfo(c, Object.class); } catch (IntrospectionException e) { throw new RuntimeException(e); } - boolean ok = checkInfo(i); + boolean ok = checkInfo(i, !ignoreVals(c)); if (checkAlternative(c)) { ok |= checkAlternativeInfo(i); } From f49817d6cd8f90f86c7dc4c7ab3f7f058a91ddd0 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Mon, 25 Apr 2016 08:50:16 -0700 Subject: [PATCH 135/225] 8154485: JShell: infrastructure for multi-Snippet class wrappers Reviewed-by: jlahoda --- .../internal/jshell/remote/RemoteAgent.java | 7 +- .../internal/jshell/remote/RemoteCodes.java | 10 +- .../jshell/tool/resources/l10n.properties | 2 +- .../classes/jdk/jshell/ClassTracker.java | 13 ++- .../jdk/jshell/DeclarationSnippet.java | 2 +- .../share/classes/jdk/jshell/Diag.java | 9 +- .../share/classes/jdk/jshell/DiagList.java | 5 +- .../share/classes/jdk/jshell/Eval.java | 78 +++++++-------- .../classes/jdk/jshell/ExecutionControl.java | 9 +- .../share/classes/jdk/jshell/JShell.java | 5 +- .../jdk/jshell/OuterImportSnippetWrap.java | 61 ++++++++++++ .../jdk/jshell/OuterSnippetsClassWrap.java | 95 ++++++++++++++++++ .../share/classes/jdk/jshell/OuterWrap.java | 77 +++++---------- .../classes/jdk/jshell/OuterWrapMap.java | 98 +++++++++++++++++++ .../share/classes/jdk/jshell/Snippet.java | 10 +- .../share/classes/jdk/jshell/SnippetMaps.java | 31 +++--- .../jdk/jshell/SourceCodeAnalysisImpl.java | 19 ++-- .../share/classes/jdk/jshell/TaskFactory.java | 59 +++-------- .../classes/jdk/jshell/TreeDissector.java | 34 ++++--- .../share/classes/jdk/jshell/Unit.java | 70 ++++++++----- .../share/classes/jdk/jshell/Util.java | 8 +- .../share/classes/jdk/jshell/Wrap.java | 51 +++++++++- langtools/test/jdk/jshell/ClassesTest.java | 9 +- langtools/test/jdk/jshell/DropTest.java | 13 ++- langtools/test/jdk/jshell/KullaTesting.java | 2 +- langtools/test/jdk/jshell/MethodsTest.java | 29 +++++- langtools/test/jdk/jshell/ReplaceTest.java | 24 ++--- .../jdk/jshell/SnippetStatusListenerTest.java | 2 +- langtools/test/jdk/jshell/SnippetTest.java | 3 +- langtools/test/jdk/jshell/VariablesTest.java | 4 +- 30 files changed, 573 insertions(+), 266 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java index f7d8e4a186d..83d6419f86a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java @@ -262,9 +262,14 @@ class RemoteAgent { } } + /** + * Expunge internal info from string + * @param s string to process + * @return string the display, JShell package and wrapper class names removed + */ static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java index edb33f0bd38..e8deae7e73c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java @@ -47,8 +47,12 @@ public class RemoteCodes { public static final int RESULT_CORRALLED = 103; public static final int RESULT_KILLED = 104; + // String constants + public static final String REPL_PACKAGE = "REPL"; + public static final String REPL_CLASS_PREFIX = "$JShell$"; public static final String DOIT_METHOD_NAME = "do_it$"; - public static final String replClass = "\\$REPL(?\\d+)[A-Z]*"; - public static final Pattern prefixPattern = Pattern.compile("(REPL\\.)?" + replClass + "[\\$\\.]?"); - + public static final Pattern PREFIX_PATTERN = Pattern.compile( + "(" + REPL_PACKAGE + "\\.)?" + + "(?" + Pattern.quote(REPL_CLASS_PREFIX) + + "\\w+" + ")" + "[\\$\\.]?"); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index 34ef112a527..b70c6de2ac0 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -512,7 +512,7 @@ startup.feedback = \ /set format verbose errorpre '| ' \n\ /set format verbose errorpost '%n' \n\ \n\ -/set format verbose errorline '{pre} {err}' \n\ +/set format verbose errorline '{post}{pre} {err}' \n\ \n\ /set format verbose action 'created' added-primary \n\ /set format verbose action 'modified' modified-primary \n\ diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java index 206aa94b86a..51af9abbc93 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java @@ -27,6 +27,7 @@ package jdk.jshell; import java.util.Arrays; import java.util.HashMap; +import java.util.Objects; import com.sun.jdi.ReferenceType; /** @@ -82,6 +83,17 @@ class ClassTracker { } return rt; } + + @Override + public boolean equals(Object o) { + return o instanceof ClassInfo && + ((ClassInfo) o).className.equals(className); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.className); + } } ClassInfo classInfo(String className, byte[] bytes) { @@ -93,5 +105,4 @@ class ClassTracker { ClassInfo get(String className) { return map.get(className); } - } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java index 8fc60cb749d..3902fbae3bb 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java @@ -84,6 +84,6 @@ public abstract class DeclarationSnippet extends PersistentSnippet { @Override String importLine(JShell state) { - return "import static " + state.maps.classFullName(this) + "." + name() + ";\n"; + return "import static " + classFullName() + "." + name() + ";\n"; } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java index 9a5c7538143..396396dec2a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java @@ -100,10 +100,12 @@ public abstract class Diag { // *** Internal support *** /** - * Internal: If this is from a compile, extract the compilation Unit. + * Internal: If this is from a compile/analyze wrapped in an outer class, extract the snippet. * Otherwise null. */ - abstract Unit unitOrNull(); + Snippet snippetOrNull() { + return null; + } /** * This is an unreachable-statement error @@ -124,6 +126,7 @@ public abstract class Diag { */ boolean isResolutionError() { //TODO: try javac RESOLVE_ERROR flag - return getCode().startsWith("compiler.err.cant.resolve"); + return getCode().startsWith("compiler.err.cant.resolve") + || getCode().equals("compiler.err.cant.apply.symbol"); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java index b0546fe5e12..7007a5f7f1a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java @@ -106,7 +106,10 @@ final class DiagList extends ArrayList { DiagList ofUnit(Unit u) { return this.stream() - .filter(d -> d.unitOrNull() == u) + .filter(d -> { + Snippet snn = d.snippetOrNull(); + return snn == u.snippet(); + }) .collect(Collectors.toCollection(() -> new DiagList())); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 7e0e4b35392..961eafbf0c0 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.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 @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.jshell; import java.util.ArrayList; @@ -50,7 +49,6 @@ import java.io.StringWriter; import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; -import com.sun.tools.javac.util.Context; import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; @@ -68,7 +66,7 @@ import static java.util.stream.Collectors.toSet; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; import static jdk.jshell.Util.*; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -339,18 +337,8 @@ class Eval { return declare(snip); } - private OuterWrap wrapInClass(String className, Set except, String userSource, Wrap guts, Collection plus) { - String imports = state.maps.packageAndImportsExcept(except, plus); - return OuterWrap.wrapInClass(state.maps.packageName(), className, imports, userSource, guts); - } - - OuterWrap wrapInClass(Snippet snip, Set except, Wrap guts, Collection plus) { - return wrapInClass(snip.className(), except, snip.source(), guts, plus); - } - private AnalyzeTask trialCompile(Wrap guts) { - OuterWrap outer = wrapInClass(REPL_DOESNOTMATTER_CLASS_NAME, - Collections.emptySet(), "", guts, null); + OuterWrap outer = state.outerMap.wrapInTrialClass(guts); return state.taskFactory.new AnalyzeTask(outer); } @@ -468,7 +456,7 @@ class Eval { if (si.status().isDefined) { if (si.isExecutable()) { try { - value = state.executionControl().commandInvoke(state.maps.classFullName(si)); + value = state.executionControl().commandInvoke(si.classFullName()); value = si.subKind().hasValue() ? expunge(value) : ""; @@ -504,37 +492,54 @@ class Eval { return events(c, outs, value, exception); } + private boolean interestingEvent(SnippetEvent e) { + return e.isSignatureChange() + || e.causeSnippet() == null + || e.status() != e.previousStatus() + || e.exception() != null; + } + private List events(Unit c, Collection outs, String value, Exception exception) { List events = new ArrayList<>(); events.add(c.event(value, exception)); events.addAll(outs.stream() .filter(u -> u != c) .map(u -> u.event(null, null)) + .filter(this::interestingEvent) .collect(Collectors.toList())); events.addAll(outs.stream() .flatMap(u -> u.secondaryEvents().stream()) + .filter(this::interestingEvent) .collect(Collectors.toList())); //System.err.printf("Events: %s\n", events); return events; } + private Set outerWrapSet(Collection units) { + return units.stream() + .map(u -> u.snippet().outerWrap()) + .collect(toSet()); + } + private Set compileAndLoad(Set ins) { if (ins.isEmpty()) { return ins; } Set replaced = new LinkedHashSet<>(); + // Loop until dependencies and errors are stable while (true) { state.debug(DBG_GEN, "compileAndLoad %s\n", ins); - ins.stream().forEach(u -> u.initialize(ins)); - AnalyzeTask at = state.taskFactory.new AnalyzeTask(ins); + ins.stream().forEach(u -> u.initialize()); + ins.stream().forEach(u -> u.setWrap(ins, ins)); + AnalyzeTask at = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setDiagnostics(at)); // corral any Snippets that need it AnalyzeTask cat; if (ins.stream().anyMatch(u -> u.corralIfNeeded(ins))) { // if any were corralled, re-analyze everything - cat = state.taskFactory.new AnalyzeTask(ins); + cat = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setCorralledDiagnostics(cat)); } else { cat = at; @@ -556,7 +561,7 @@ class Eval { legit.stream().forEach(u -> u.setWrap(ins, legit)); // generate class files for those capable - CompileTask ct = state.taskFactory.new CompileTask(legit); + CompileTask ct = state.taskFactory.new CompileTask(outerWrapSet(legit)); if (!ct.compile()) { // oy! compile failed because of recursive new unresolved if (legit.stream() @@ -572,8 +577,8 @@ class Eval { // load all new classes load(legit.stream() - .flatMap(u -> u.classesToLoad(ct.classInfoList(u))) - .collect(toList())); + .flatMap(u -> u.classesToLoad(ct.classInfoList(u.snippet().outerWrap()))) + .collect(toSet())); // attempt to redefine the remaining classes List toReplace = legit.stream() .filter(u -> !u.doRedefines()) @@ -607,7 +612,7 @@ class Eval { } } - private void load(List cil) { + private void load(Set cil) { if (!cil.isEmpty()) { state.executionControl().commandLoad(cil); } @@ -625,20 +630,14 @@ class Eval { StackTraceElement[] elems = new StackTraceElement[last + 1]; for (int i = 0; i <= last; ++i) { StackTraceElement r = raw[i]; - String rawKlass = r.getClassName(); - Matcher matcher = prefixPattern.matcher(rawKlass); - String num; - if (matcher.find() && (num = matcher.group("num")) != null) { - int end = matcher.end(); - if (rawKlass.charAt(end - 1) == '$') { - --end; - } - int id = Integer.parseInt(num); - Snippet si = state.maps.getSnippet(id); - String klass = expunge(rawKlass); + OuterSnippetsClassWrap outer = state.outerMap.getOuter(r.getClassName()); + if (outer != null) { + String klass = expunge(r.getClassName()); String method = r.getMethodName().equals(DOIT_METHOD_NAME) ? "" : r.getMethodName(); - String file = "#" + id; - int line = si.outerWrap().wrapLineToSnippetLine(r.getLineNumber() - 1) + 1; + int wln = r.getLineNumber() - 1; + int line = outer.wrapLineToSnippetLine(wln) + 1; + Snippet sn = outer.wrapLineToSnippet(wln); + String file = "#" + sn.id(); elems[i] = new StackTraceElement(klass, method, file, line); } else if (r.getFileName().equals("")) { elems[i] = new StackTraceElement(r.getClassName(), r.getMethodName(), null, r.getLineNumber()); @@ -654,7 +653,7 @@ class Eval { } private boolean isWrap(StackTraceElement ste) { - return prefixPattern.matcher(ste.getClassName()).find(); + return PREFIX_PATTERN.matcher(ste.getClassName()).find(); } private DiagList modifierDiagnostics(ModifiersTree modtree, @@ -714,11 +713,6 @@ class Eval { public String getMessage(Locale locale) { return message; } - - @Override - Unit unitOrNull() { - return null; - } } List list = new ArrayList<>(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index abaa5cbd5d5..f69ec57e797 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -36,6 +36,7 @@ import java.net.ServerSocket; import java.net.Socket; import com.sun.jdi.*; import java.io.EOFException; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -94,7 +95,7 @@ class ExecutionControl { } - boolean commandLoad(List cil) { + boolean commandLoad(Collection cil) { try { out.writeInt(CMD_LOAD); out.writeInt(cil.size()); @@ -122,7 +123,7 @@ class ExecutionControl { String result = in.readUTF(); return result; } - } catch (IOException | ClassNotFoundException ex) { + } catch (IOException | RuntimeException ex) { if (!env.connection().isRunning()) { env.shutdown(); } else { @@ -204,7 +205,7 @@ class ExecutionControl { } } - private boolean readAndReportExecutionResult() throws IOException, ClassNotFoundException, EvalException, UnresolvedReferenceException { + private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException { int ok = in.readInt(); switch (ok) { case RESULT_SUCCESS: @@ -224,7 +225,7 @@ class ExecutionControl { case RESULT_CORRALLED: { int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); - Snippet si = maps.getSnippet(id); + Snippet si = maps.getSnippetDeadOrAlive(id); throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index b261e5e67be..0cb2d05c7af 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -77,6 +77,7 @@ public class JShell implements AutoCloseable { final SnippetMaps maps; final KeyMap keyMap; + final OuterWrapMap outerMap; final TaskFactory taskFactory; final InputStream in; final PrintStream out; @@ -106,8 +107,8 @@ public class JShell implements AutoCloseable { this.idGenerator = b.idGenerator; this.maps = new SnippetMaps(this); - maps.setPackageName("REPL"); this.keyMap = new KeyMap(this); + this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); this.classTracker = new ClassTracker(this); @@ -563,7 +564,7 @@ public class JShell implements AutoCloseable { throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } - String value = executionControl().commandVarValue(maps.classFullName(snippet), snippet.name()); + String value = executionControl().commandVarValue(snippet.classFullName(), snippet.name()); return expunge(value); } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java new file mode 100644 index 00000000000..8e336544943 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java @@ -0,0 +1,61 @@ +/* + * 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.jshell; + +import java.util.IdentityHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterImportSnippetWrap extends OuterWrap { + + private final Snippet snippet; + + OuterImportSnippetWrap(Wrap wrap, Snippet snippet) { + super(wrap); + this.snippet = snippet; + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + return snippet; + } + }; + } + + @Override + public String toString() { + return "OISW(" + w + ")"; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java new file mode 100644 index 00000000000..5a58ade38cc --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java @@ -0,0 +1,95 @@ +/* + * 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.jshell; + +import java.util.LinkedHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import jdk.jshell.Wrap.CompoundWrap; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterSnippetsClassWrap extends OuterWrap { + + private final String className; + private final LinkedHashMap wrapToSnippet; + + OuterSnippetsClassWrap(String className, CompoundWrap w, List snippets, List wraps) { + super(w); + assert snippets == null || snippets.size() == wraps.size(); + this.className = className; + wrapToSnippet = new LinkedHashMap<>(); + for (int i = 0; i < snippets.size(); ++i) { + wrapToSnippet.put(wraps.get(i), snippets.get(i)); + } + } + + public Snippet wrapLineToSnippet(int wline) { + Wrap wrap = ((CompoundWrap)w).wrapLineToWrap(wline); + return wrapToSnippet.get(wrap); + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + Wrap wrap = ((CompoundWrap) w).wrapIndexToWrap(diag.getPosition()); + Snippet sn = wrapToSnippet.get(wrap); + if (sn != null) { + return sn; + } else { + return super.snippetOrNull(); + } + } + }; + } + + int ordinal(Snippet sn) { + int i = 0; + for (Snippet si : wrapToSnippet.values()) { + if (si == sn) { + return i; + } + ++i; + } + return -1; + } + + @Override + public String className() { + return className; + } + + @Override + public String toString() { + return "OSCW(" + className + ":" + w + ")"; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java index b44a7015020..f61d8b487d4 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.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 @@ -25,47 +25,23 @@ package jdk.jshell; -import jdk.jshell.Wrap.CompoundWrap; -import static jdk.jshell.Util.*; import java.util.Locale; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; -import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; +import jdk.internal.jshell.remote.RemoteCodes; +import static jdk.jshell.Util.*; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * * @author Robert Field */ -final class OuterWrap implements GeneralWrap { +class OuterWrap implements GeneralWrap { - private final String packageName; - private final String className; - private final String userSource; - private final GeneralWrap w; - private final Wrap guts; + protected final Wrap w; - public static OuterWrap wrapInClass(String packageName, String className, - String imports, String userSource, Wrap guts) { - GeneralWrap kw = new CompoundWrap( - imports - + "class " + className + " {\n", - guts, - "}\n"); - return new OuterWrap(packageName, className, userSource, kw, guts); - } - - public static OuterWrap wrapImport(String userSource, Wrap guts) { - return new OuterWrap("", "", userSource, guts, guts); - } - - private OuterWrap(String packageName, String className, String userSource, - GeneralWrap w, Wrap guts) { - this.packageName = packageName; - this.className = className; - this.userSource = userSource; - this.w = w; - this.guts = guts; + OuterWrap(Wrap wrap) { + this.w = wrap; } @Override @@ -114,19 +90,28 @@ final class OuterWrap implements GeneralWrap { } public String className() { - return className; + return REPL_DOESNOTMATTER_CLASS_NAME; } public String classFullName() { - return packageName + "." + className; + return REPL_PACKAGE + "." + className(); } - public String getUserSource() { - return userSource; + @Override + public int hashCode() { + return className().hashCode(); } - Wrap guts() { - return guts; + @Override + public boolean equals(Object o) { + return (o instanceof OuterWrap) + ? className().equals(((OuterWrap) o).className()) + : false; + } + + @Override + public String toString() { + return "OW(" + w + ")"; } Diag wrapDiag(Diagnostic d) { @@ -135,7 +120,7 @@ final class OuterWrap implements GeneralWrap { class WrappedDiagnostic extends Diag { - private final Diagnostic diag; + final Diagnostic diag; WrappedDiagnostic(Diagnostic diag) { this.diag = diag; @@ -171,18 +156,6 @@ final class OuterWrap implements GeneralWrap { return expunge(diag.getMessage(locale)); } - @Override - Unit unitOrNull() { - JavaFileObject fo = diag.getSource(); - if (fo instanceof SourceMemoryJavaFileObject) { - SourceMemoryJavaFileObject sfo = (SourceMemoryJavaFileObject) fo; - if (sfo.getOrigin() instanceof Unit) { - return (Unit) sfo.getOrigin(); - } - } - return null; - } - @Override boolean isResolutionError() { if (!super.isResolutionError()) { @@ -190,7 +163,7 @@ final class OuterWrap implements GeneralWrap { } for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) { if (line.trim().startsWith("location:")) { - if (!line.contains(REPL_CLASS_PREFIX)) { + if (!line.contains(RemoteCodes.REPL_CLASS_PREFIX)) { // Resolution error must occur within a REPL class or it is not resolvable return false; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java new file mode 100644 index 00000000000..1576ebe7725 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java @@ -0,0 +1,98 @@ +/* + * 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.jshell; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.stream.Collectors; +import jdk.jshell.Wrap.CompoundWrap; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; +import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; +import static jdk.jshell.Util.asLetters; + +/** + * + * @author Robert Field + */ +public class OuterWrapMap { + + private final JShell state; + private final Map classOuters = new HashMap<>(); + + OuterWrapMap(JShell state) { + this.state = state; + } + + OuterSnippetsClassWrap getOuter(String className) { + Matcher matcher = PREFIX_PATTERN.matcher(className); + String cn; + if (matcher.find() && (cn = matcher.group("class")) != null) { + return classOuters.get(cn); + } + return null; + } + + private CompoundWrap wrappedInClass(String className, String imports, List wraps) { + List elems = new ArrayList<>(wraps.size() + 2); + elems.add(imports + + "class " + className + " {\n"); + elems.addAll(wraps); + elems.add("}\n"); + return new CompoundWrap(elems.toArray()); + } + + OuterWrap wrapInClass(Set except, Collection plus, + List snippets, List wraps) { + String imports = state.maps.packageAndImportsExcept(except, plus); + // className is unique to the set of snippets and their version (seq) + String className = REPL_CLASS_PREFIX + snippets.stream() + .sorted((sn1, sn2) -> sn1.key().index() - sn2.key().index()) + .map(sn -> "" + sn.key().index() + asLetters(sn.sequenceNumber())) + .collect(Collectors.joining("_")); + CompoundWrap w = wrappedInClass(className, imports, wraps); + OuterSnippetsClassWrap now = new OuterSnippetsClassWrap(className, w, snippets, wraps); + classOuters.put(className, now); + return now; + } + + OuterWrap wrapInTrialClass(Wrap wrap) { + String imports = state.maps.packageAndImportsExcept(null, null); + CompoundWrap w = wrappedInClass(REPL_DOESNOTMATTER_CLASS_NAME, imports, + Collections.singletonList(wrap)); + return new OuterWrap(w); + } + + OuterWrap wrapImport(Wrap guts, Snippet sn) { + return new OuterImportSnippetWrap(guts, sn); + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java index 5f5489b6a78..6669cf1803d 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java @@ -28,8 +28,6 @@ package jdk.jshell; import java.util.Collection; import java.util.Collections; import java.util.List; -import static jdk.jshell.Util.REPL_CLASS_PREFIX; -import static jdk.jshell.Util.asLetters; /** * A Snippet represents a snippet of Java source code as passed to @@ -503,7 +501,6 @@ public abstract class Snippet { private final SubKind subkind; private int seq; - private String className; private String id; private OuterWrap outer; private Status status; @@ -615,7 +612,6 @@ public abstract class Snippet { final void setSequenceNumber(int seq) { this.seq = seq; - this.className = REPL_CLASS_PREFIX + key().index() + asLetters(seq); } void setOuterWrap(OuterWrap outer) { @@ -653,7 +649,11 @@ public abstract class Snippet { } String className() { - return className; + return outer.className(); + } + + String classFullName() { + return outer.classFullName(); } /** diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index 149a90e05c3..9d0a48505d8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -38,8 +38,9 @@ import java.util.regex.Matcher; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * Maintain relationships between the significant entities: Snippets, @@ -48,7 +49,6 @@ import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; */ final class SnippetMaps { - private String packageName; private final List keyIndexToSnippet = new ArrayList<>(); private final Set snippets = new LinkedHashSet<>(); private final Map> dependencies = new HashMap<>(); @@ -81,6 +81,13 @@ final class SnippetMaps { } Snippet getSnippet(int ki) { + Snippet sn = getSnippetDeadOrAlive(ki); + return (sn != null && !sn.status().isActive) + ? null + : sn; + } + + Snippet getSnippetDeadOrAlive(int ki) { if (ki >= keyIndexToSnippet.size()) { return null; } @@ -91,21 +98,9 @@ final class SnippetMaps { return new ArrayList<>(snippets); } - void setPackageName(String n) { - packageName = n; - } - - String packageName() { - return packageName; - } - - String classFullName(Snippet sn) { - return packageName + "." + sn.className(); - } - String packageAndImportsExcept(Set except, Collection plus) { StringBuilder sb = new StringBuilder(); - sb.append("package ").append(packageName()).append(";\n"); + sb.append("package ").append(REPL_PACKAGE).append(";\n"); for (Snippet si : keyIndexToSnippet) { if (si != null && si.status().isDefined && (except == null || !except.contains(si.key()))) { sb.append(si.importLine(state)); @@ -137,7 +132,7 @@ final class SnippetMaps { } List deps = new ArrayList<>(); for (Integer dss : depset) { - Snippet dep = getSnippet(dss); + Snippet dep = getSnippetDeadOrAlive(dss); if (dep != null) { deps.add(dep); state.debug(DBG_DEP, "Found dependency %s -> %s\n", snip.name(), dep.name()); @@ -161,7 +156,7 @@ final class SnippetMaps { } String fullClassNameAndPackageToClass(String full, String pkg) { - Matcher mat = prefixPattern.matcher(full); + Matcher mat = PREFIX_PATTERN.matcher(full); if (mat.lookingAt()) { return full.substring(mat.end()); } @@ -195,6 +190,6 @@ final class SnippetMaps { private Stream importSnippets() { return state.keyMap.importKeys() .map(key -> (ImportSnippet)getSnippet(key)) - .filter(sn -> state.status(sn).isDefined); + .filter(sn -> sn != null && state.status(sn).isDefined); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index 45f9661d0bb..ca6b08612b9 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -211,11 +211,6 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { throw new InternalError(); } - private OuterWrap wrapInClass(Wrap guts) { - String imports = proc.maps.packageAndImportsExcept(null, null); - return OuterWrap.wrapInClass(proc.maps.packageName(), REPL_DOESNOTMATTER_CLASS_NAME, imports, "", guts); - } - private Tree.Kind guessKind(String code) { ParseTask pt = proc.taskFactory.new ParseTask(code); List units = pt.units(); @@ -258,13 +253,13 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { OuterWrap codeWrap; switch (guessKind(code)) { case IMPORT: - codeWrap = OuterWrap.wrapImport(null, Wrap.simpleWrap(code + "any.any")); + codeWrap = proc.outerMap.wrapImport(Wrap.simpleWrap(code + "any.any"), null); break; case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } String requiredPrefix = identifier; @@ -946,7 +941,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { if (guessKind(code) == Kind.IMPORT) return null; - OuterWrap codeWrap = wrapInClass(Wrap.methodWrap(code)); + OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); SourcePositions sp = at.trees().getSourcePositions(); CompilationUnitTree topLevel = at.firstCuTree(); @@ -1064,7 +1059,7 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { case INTERFACE: case ANNOTATION_TYPE: case VARIABLE: return null; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); @@ -1104,10 +1099,10 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { case IMPORT: return new QualifiedNames(Collections.emptyList(), -1, true, false); case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index 8ad7862c6b4..ce34f5f16a6 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.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 @@ -148,48 +148,22 @@ class TaskFactory { public String getMessage(Locale locale) { return expunge(d.getMessage(locale)); } - - @Override - Unit unitOrNull() { - return null; - } }; } } private class WrapSourceHandler implements SourceHandler { - final OuterWrap wrap; - - WrapSourceHandler(OuterWrap wrap) { - this.wrap = wrap; - } - @Override public JavaFileObject sourceToFileObject(MemoryFileManager fm, OuterWrap w) { return fm.createSourceFileObject(w, w.classFullName(), w.wrapped()); } - @Override - public Diag diag(Diagnostic d) { - return wrap.wrapDiag(d); - } - } - - private class UnitSourceHandler implements SourceHandler { - - @Override - public JavaFileObject sourceToFileObject(MemoryFileManager fm, Unit u) { - return fm.createSourceFileObject(u, - state.maps.classFullName(u.snippet()), - u.snippet().outerWrap().wrapped()); - } - @Override public Diag diag(Diagnostic d) { SourceMemoryJavaFileObject smjfo = (SourceMemoryJavaFileObject) d.getSource(); - Unit u = (Unit) smjfo.getOrigin(); - return u.snippet().outerWrap().wrapDiag(d); + OuterWrap w = (OuterWrap) smjfo.getOrigin(); + return w.wrapDiag(d); } } @@ -242,13 +216,12 @@ class TaskFactory { private final Iterable cuts; AnalyzeTask(final OuterWrap wrap) { - this(Stream.of(wrap), - new WrapSourceHandler(wrap), - "-XDshouldStopPolicy=FLOW", "-proc:none"); + this(Collections.singletonList(wrap)); } - AnalyzeTask(final Collection units) { - this(units.stream(), new UnitSourceHandler(), + AnalyzeTask(final Collection wraps) { + this(wraps.stream(), + new WrapSourceHandler(), "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -287,10 +260,10 @@ class TaskFactory { */ class CompileTask extends BaseTask { - private final Map> classObjs = new HashMap<>(); + private final Map> classObjs = new HashMap<>(); - CompileTask(Collection units) { - super(units.stream(), new UnitSourceHandler(), + CompileTask(final Collection wraps) { + super(wraps.stream(), new WrapSourceHandler(), "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -302,8 +275,8 @@ class TaskFactory { } - List classInfoList(Unit u) { - List l = classObjs.get(u); + List classInfoList(OuterWrap w) { + List l = classObjs.get(w); if (l == null) return Collections.emptyList(); return l.stream() .map(fo -> state.classTracker.classInfo(fo.getName(), fo.getBytes())) @@ -315,11 +288,11 @@ class TaskFactory { //debug("listenForNewClassFile %s loc=%s kind=%s\n", className, location, kind); if (location == CLASS_OUTPUT) { state.debug(DBG_GEN, "Compiler generating class %s\n", className); - Unit u = ((sibling instanceof SourceMemoryJavaFileObject) - && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof Unit)) - ? (Unit) ((SourceMemoryJavaFileObject) sibling).getOrigin() + OuterWrap w = ((sibling instanceof SourceMemoryJavaFileObject) + && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof OuterWrap)) + ? (OuterWrap) ((SourceMemoryJavaFileObject) sibling).getOrigin() : null; - classObjs.compute(u, (k, v) -> (v == null)? new ArrayList<>() : v) + classObjs.compute(w, (k, v) -> (v == null)? new ArrayList<>() : v) .add(jfo); } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java index f59d10b0d3a..c9fd4cedc59 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java @@ -162,18 +162,28 @@ class TreeDissector { return new Range(start, end); } - Tree firstClassMember() { - if (targetClass != null) { - //TODO: missing classes - for (Tree mem : targetClass.getMembers()) { - if (mem.getKind() == Tree.Kind.VARIABLE) { - return mem; - } - if (mem.getKind() == Tree.Kind.METHOD) { - MethodTree mt = (MethodTree) mem; - if (!isDoIt(mt.getName()) && !mt.getName().toString().equals("")) { + MethodTree method(MethodSnippet msn) { + if (targetClass == null) { + return null; + } + OuterWrap ow = msn.outerWrap(); + if (!(ow instanceof OuterSnippetsClassWrap)) { + return null; + } + int ordinal = ((OuterSnippetsClassWrap) ow).ordinal(msn); + if (ordinal < 0) { + return null; + } + int count = 0; + String name = msn.name(); + for (Tree mem : targetClass.getMembers()) { + if (mem.getKind() == Tree.Kind.METHOD) { + MethodTree mt = (MethodTree) mem; + if (mt.getName().toString().equals(name)) { + if (count == ordinal) { return mt; } + ++count; } } } @@ -244,8 +254,8 @@ class TreeDissector { return ei; } - String typeOfMethod() { - Tree unitTree = firstClassMember(); + String typeOfMethod(MethodSnippet msn) { + Tree unitTree = method(msn); if (unitTree instanceof JCMethodDecl) { JCMethodDecl mtree = (JCMethodDecl) unitTree; Type mt = types().erasure(mtree.type); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java index 538f34f5a24..e5892470440 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.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 @@ -68,7 +68,7 @@ final class Unit { private final DiagList generatedDiagnostics; private int seq; - private int seqInitial; + private String classNameInitial; private Wrap activeGuts; private Status status; private Status prevStatus; @@ -95,7 +95,7 @@ final class Unit { this.generatedDiagnostics = generatedDiagnostics; this.seq = isNew? 0 : siOld.sequenceNumber(); - this.seqInitial = seq; + this.classNameInitial = isNew? "" : siOld.className(); this.prevStatus = (isNew || isDependency) ? si.status() : siOld.status(); @@ -136,28 +136,50 @@ final class Unit { return isDependency; } - boolean isNew() { - return isNew; - } - - void initialize(Collection working) { + void initialize() { isAttemptingCorral = false; dependenciesNeeded = false; toRedefine = null; // assure NPE if classToLoad not called activeGuts = si.guts(); markOldDeclarationOverwritten(); - setWrap(working, working); } - void setWrap(Collection except, Collection plus) { - si.setOuterWrap(isImport() - ? OuterWrap.wrapImport(si.source(), activeGuts) - : state.eval.wrapInClass(si, - except.stream().map(u -> u.snippet().key()).collect(toSet()), - activeGuts, - plus.stream().map(u -> u.snippet()) - .filter(sn -> sn != si) - .collect(toList()))); + // Set the outer wrap of our Snippet + void setWrap(Collection exceptUnit, Collection plusUnfiltered) { + if (isImport()) { + si.setOuterWrap(state.outerMap.wrapImport(activeGuts, si)); + } else { + // Collect Units for be wrapped together. Just this except for overloaded methods + List units; + if (snippet().kind() == Kind.METHOD) { + String name = ((MethodSnippet) snippet()).name(); + units = plusUnfiltered.stream() + .filter(u -> u.snippet().kind() == Kind.METHOD && + ((MethodSnippet) u.snippet()).name().equals(name)) + .collect(toList()); + } else { + units = Collections.singletonList(this); + } + // Keys to exclude from imports + Set except = exceptUnit.stream() + .map(u -> u.snippet().key()) + .collect(toSet()); + // Snippets to add to imports + Collection plus = plusUnfiltered.stream() + .filter(u -> !units.contains(u)) + .map(u -> u.snippet()) + .collect(toList()); + // Snippets to wrap in an outer + List snippets = units.stream() + .map(u -> u.snippet()) + .collect(toList()); + // Snippet wraps to wrap in an outer + List wraps = units.stream() + .map(u -> u.activeGuts) + .collect(toList()); + // Set the outer wrap for this snippet + si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps)); + } } void setDiagnostics(AnalyzeTask ct) { @@ -302,11 +324,13 @@ final class Unit { private boolean sigChanged() { return (status.isDefined != prevStatus.isDefined) - || (seq != seqInitial && status.isDefined) + || (status.isDefined && !si.className().equals(classNameInitial)) || signatureChanged; } Stream effectedDependents() { + //System.err.printf("effectedDependents sigChanged=%b dependenciesNeeded=%b status=%s\n", + // sigChanged(), dependenciesNeeded, status); return sigChanged() || dependenciesNeeded || status == RECOVERABLE_NOT_DEFINED ? dependents() : Stream.empty(); @@ -361,7 +385,7 @@ final class Unit { if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent); // Defined methods can overwrite methods of other (equivalent) snippets - if (si.kind() == Kind.METHOD && status.isDefined) { + if (isNew && si.kind() == Kind.METHOD && status.isDefined) { MethodSnippet msi = (MethodSnippet)si; String oqpt = msi.qualifiedParameterTypes(); String nqpt = computeQualifiedParameterTypes(at, msi); @@ -405,7 +429,7 @@ final class Unit { } private String computeQualifiedParameterTypes(AnalyzeTask at, MethodSnippet msi) { - String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(); + String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(msi); String signature = expunge(rawSig); int paren = signature.lastIndexOf(')'); @@ -425,7 +449,9 @@ final class Unit { } List secondaryEvents() { - return secondaryEvents; + return secondaryEvents==null + ? Collections.emptyList() + : secondaryEvents; } @Override diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java index 8cc42150790..553e6c97fb3 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java @@ -30,7 +30,8 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.lang.model.element.Name; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; /** * Assorted shared utilities. @@ -38,8 +39,7 @@ import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; */ class Util { - static final String REPL_CLASS_PREFIX = "$REPL"; - static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"00DOESNOTMATTER"; + static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"DOESNOTMATTER"; static final Locale PARSED_LOCALE = Locale.ROOT; @@ -53,7 +53,7 @@ class Util { static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index 3dd39750cf2..873a0d1cce8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -25,6 +25,8 @@ package jdk.jshell; +import java.util.Arrays; +import static java.util.stream.Collectors.joining; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -237,6 +239,27 @@ abstract class Wrap implements GeneralWrap { return 0; } + Wrap wrapIndexToWrap(long wi) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += s.length(); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int len = w.wrapped().length(); + if ((wi - before) <= len) { + //System.err.printf("Defer to wrap %s - wi: %d. before; %d -- %s >>> %s\n", + // w, wi, before, w.debugPos(wi - before), w.wrapped()); + return w; + } + before += len; + } + } + return w; + } + @Override public int wrapIndexToSnippetIndex(int wi) { int before = 0; @@ -286,6 +309,25 @@ abstract class Wrap implements GeneralWrap { return 0; } + Wrap wrapLineToWrap(int wline) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += countLines(s); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int lns = countLines(w.wrapped()); + if ((wline - before) < lns) { + return w; + } + before += lns; + } + } + return w; + } + @Override public int wrapLineToSnippetLine(int wline) { int before = 0; @@ -315,7 +357,10 @@ abstract class Wrap implements GeneralWrap { return snlineLast; } - + @Override + public String toString() { + return "CompoundWrap(" + Arrays.stream(os).map(u -> u.toString()).collect(joining(",")) + ")"; + } } private static class RangeWrap extends Wrap { @@ -404,6 +449,10 @@ abstract class Wrap implements GeneralWrap { return lastSnline; } + @Override + public String toString() { + return "RangeWrap(" + range + ")"; + } } private static class NoWrap extends RangeWrap { diff --git a/langtools/test/jdk/jshell/ClassesTest.java b/langtools/test/jdk/jshell/ClassesTest.java index 058714fe438..a0848f12f1c 100644 --- a/langtools/test/jdk/jshell/ClassesTest.java +++ b/langtools/test/jdk/jshell/ClassesTest.java @@ -47,6 +47,7 @@ import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; import static jdk.jshell.Snippet.Status.OVERWRITTEN; +import static jdk.jshell.Snippet.Status.NONEXISTENT; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -83,7 +84,7 @@ public class ClassesTest extends KullaTesting { TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + ste(c1, NONEXISTENT, RECOVERABLE_DEFINED, true, null))); assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); @@ -176,6 +177,7 @@ public class ClassesTest extends KullaTesting { assertActiveKeys(); } + //8154496: test3 update: sig change should false public void classesRedeclaration3() { Snippet a = classKey(assertEval("class A { }")); assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); @@ -190,7 +192,7 @@ public class ClassesTest extends KullaTesting { ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(test1, VALID, VALID, true, MAIN_SNIPPET), ste(test2, VALID, VALID, true, MAIN_SNIPPET), - ste(test3, VALID, VALID, false, MAIN_SNIPPET), + ste(test3, VALID, VALID, true, MAIN_SNIPPET), ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A")); assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test")); @@ -201,8 +203,7 @@ public class ClassesTest extends KullaTesting { Snippet b = classKey(assertEval("class B extends A { }", added(RECOVERABLE_NOT_DEFINED))); Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, - added(RECOVERABLE_NOT_DEFINED), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET))); + added(REJECTED))); /*** assertDeclareFail("class A extends B { }", "****", added(REJECTED), diff --git a/langtools/test/jdk/jshell/DropTest.java b/langtools/test/jdk/jshell/DropTest.java index 04e9fb2a4e5..d00003f4b98 100644 --- a/langtools/test/jdk/jshell/DropTest.java +++ b/langtools/test/jdk/jshell/DropTest.java @@ -57,10 +57,10 @@ public class DropTest extends KullaTesting { assertActiveKeys(); method = methodKey(assertEval("int mu() { return x * 4; }", - ste(MAIN_SNIPPET, DROPPED, RECOVERABLE_DEFINED, true, null), + added(RECOVERABLE_DEFINED), ste(clazz, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); assertEval("int x = 10;", "10", - ste(MAIN_SNIPPET, DROPPED, VALID, true, null), + added(VALID), ste(method, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)); PersistentSnippet c0 = varKey(assertEval("C c0 = new C();")); assertEval("c0.v();", "\"#40\""); @@ -189,12 +189,11 @@ public class DropTest extends KullaTesting { assertDrop(c, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null), - ste(d, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, c)); + ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); assertEval("interface A {}", null, null, - DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(a, DROPPED, VALID, true, null), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET)); + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + added(VALID)); assertClasses(); assertActiveKeys(); } diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index 0ea4a622499..7c4224a27db 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -651,7 +651,7 @@ public class KullaTesting { DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates); SnippetEvent e = events.get(0); List diagnostics = getState().diagnostics(e.snippet()); - assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); + if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); return e.snippet(); } diff --git a/langtools/test/jdk/jshell/MethodsTest.java b/langtools/test/jdk/jshell/MethodsTest.java index a5ffcd383ba..6d0c3f4b4f9 100644 --- a/langtools/test/jdk/jshell/MethodsTest.java +++ b/langtools/test/jdk/jshell/MethodsTest.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 @@ -58,7 +58,7 @@ public class MethodsTest extends KullaTesting { MethodSnippet m1 = (MethodSnippet) assertDeclareFail("void f() { return g(); }", "compiler.err.prob.found.req"); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); MethodSnippet m2 = methodKey(assertEval("int f() { return g(); }", - ste(m1, REJECTED, RECOVERABLE_DEFINED, true, null))); + added(RECOVERABLE_DEFINED))); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); assertMethodDeclSnippet(m2, "f", "()int", RECOVERABLE_DEFINED, 1, 0); } @@ -115,6 +115,26 @@ public class MethodsTest extends KullaTesting { assertActiveKeys(); } + /*** + public void methodOverloadDependent() { + assertEval("String m(String s) { return s + s; }"); + assertEval("String m(double d) { return m(\"#\" + d); }"); + assertEval("String m(int x) { return m(2.25 * x); }"); + assertEval("String m() { return m(3); }"); + assertMethods( + method("(String)String", "m"), + method("(double)String", "m"), + method("(int)String", "m"), + method("()String", "m") + ); + assertEval("m();", "\"#6.75#6.75\""); + assertEval("m(2);", "\"#4.5#4.5\""); + assertEval("m(3.14);", "\"#3.14#3.14\""); + assertEval("m(\"hi\");", "\"hihi\""); + assertActiveKeys(); + } + ***/ + public void methodsRedeclaration1() { Snippet x = methodKey(assertEval("int x() { return 10; }")); Snippet y = methodKey(assertEval("String y() { return \"\"; }")); @@ -149,8 +169,7 @@ public class MethodsTest extends KullaTesting { assertEval("double b() { return 3.14159; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertMethods(method("()int", "a"), method("()double", "b"), method("()double", "c")); assertEval("c();", "3.14159"); assertActiveKeys(); @@ -202,7 +221,7 @@ public class MethodsTest extends KullaTesting { assertActiveKeys(); assertDeclareFail("int f() {}", "compiler.err.missing.ret.stmt", - ste(MAIN_SNIPPET, REJECTED, REJECTED, false, null)); + added(REJECTED)); assertNumberOfActiveMethods(0); assertActiveKeys(); diff --git a/langtools/test/jdk/jshell/ReplaceTest.java b/langtools/test/jdk/jshell/ReplaceTest.java index 60807c09601..b631c4958c9 100644 --- a/langtools/test/jdk/jshell/ReplaceTest.java +++ b/langtools/test/jdk/jshell/ReplaceTest.java @@ -97,8 +97,7 @@ public class ReplaceTest extends KullaTesting { assertEval("mu() == 0.0;", "true"); assertEval("double x = 2.5;", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(musn, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection meths = getState().methods(); assertEquals(meths.size(), 1); assertTrue(musn == meths.iterator().next(), "Identity must not change"); @@ -115,8 +114,7 @@ public class ReplaceTest extends KullaTesting { assertEval("d();", "1060.0"); assertEval("int a() { return 5; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(b, VALID, VALID, false, MAIN_SNIPPET)); + ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("d();", "1150.0"); assertActiveKeys(); } @@ -127,8 +125,7 @@ public class ReplaceTest extends KullaTesting { assertEval("m();", "7"); assertEval("class C { int x = 99; int f() { return x; } }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(m, VALID, VALID, false, MAIN_SNIPPET)); + ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("m();", "99"); assertActiveKeys(); } @@ -140,8 +137,7 @@ public class ReplaceTest extends KullaTesting { assertEval("new A().a == 0.0;", "true"); assertEval("double x = 2.5;", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection classes = getState().types(); assertEquals(classes.size(), 1); assertTrue(c == classes.iterator().next(), "Identity must not change"); @@ -157,8 +153,7 @@ public class ReplaceTest extends KullaTesting { assertEval("new A().a == 0.0;", "true"); assertEval("double x() { return 2.5; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("x();", "2.5"); Collection classes = getState().types(); assertEquals(classes.size(), 1); @@ -875,18 +870,15 @@ public class ReplaceTest extends KullaTesting { MethodSnippet k1 = methodKey(assertEval(ms1, added(VALID))); VarSnippet xd = varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k1, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); MethodSnippet k2 = methodKey(assertEval(ms2, ste(MAIN_SNIPPET, VALID, VALID, true, null), //TODO: technically, should be false ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); VarSnippet xi2 = varKey(assertEval(xsi, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); } } diff --git a/langtools/test/jdk/jshell/SnippetStatusListenerTest.java b/langtools/test/jdk/jshell/SnippetStatusListenerTest.java index 715b350a617..14ea0b956a7 100644 --- a/langtools/test/jdk/jshell/SnippetStatusListenerTest.java +++ b/langtools/test/jdk/jshell/SnippetStatusListenerTest.java @@ -65,7 +65,7 @@ public class SnippetStatusListenerTest extends KullaTesting { getState().unsubscribe(subscription1); assertDrop(f, DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, ste(f, REJECTED, DROPPED, false, null)); - assertEval("void f() { }", ste(MAIN_SNIPPET, DROPPED, VALID, true, null)); + assertEval("void f() { }", added(VALID)); assertEvalException("throw new RuntimeException();"); assertEquals(listener1.getEvents(), events1, "Checking that unsubscribed listener does not get events"); diff --git a/langtools/test/jdk/jshell/SnippetTest.java b/langtools/test/jdk/jshell/SnippetTest.java index e3176c0b6c8..f9518ba0aee 100644 --- a/langtools/test/jdk/jshell/SnippetTest.java +++ b/langtools/test/jdk/jshell/SnippetTest.java @@ -142,8 +142,7 @@ public class SnippetTest extends KullaTesting { assertActiveKeys(); assertEval("double f() { return 0.0; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(g, VALID, VALID, false, MAIN_SNIPPET)); + ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertKeys(method("()void", "g"), clazz(KullaTesting.ClassType.INTERFACE, "A"), method("()double", "f")); assertActiveKeys(); diff --git a/langtools/test/jdk/jshell/VariablesTest.java b/langtools/test/jdk/jshell/VariablesTest.java index 3a374a0b52c..35eda77cdcc 100644 --- a/langtools/test/jdk/jshell/VariablesTest.java +++ b/langtools/test/jdk/jshell/VariablesTest.java @@ -83,7 +83,7 @@ public class VariablesTest extends KullaTesting { public void testVarValue2() { VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); badVarValue(v1); - VarSnippet v2 = varKey(assertEval("int a = 0;", ste(v1, REJECTED, VALID, true, null))); + VarSnippet v2 = varKey(assertEval("int a = 0;", added(VALID))); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); badVarValue(v2); } @@ -111,7 +111,7 @@ public class VariablesTest extends KullaTesting { VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); assertVariableDeclSnippet(v1, "a", "int", REJECTED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 1); VarSnippet v2 = varKey(assertEval("int a = 0;", - ste(v1, REJECTED, VALID, true, null))); + added(VALID))); assertVariableDeclSnippet(v2, "a", "int", VALID, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); assertVariableDeclSnippet(v2, "a", "int", DROPPED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0); From 2e406416e029b4127425866c5dd154a0859281a7 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 25 Apr 2016 15:09:15 -0700 Subject: [PATCH 136/225] 8154213: clean up uses of boxed primitive constructors in the java.desktop module Reviewed-by: serb, psadhukhan --- make/CompileJavaModules.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 4ce9cca25bf..d2404007848 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -99,7 +99,7 @@ java.datatransfer_COPY := flavormap.properties ################################################################################ java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \ - '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation + '-Xdoclint/package:java.*,javax.*' java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties From 3f778b5b22c3d45fc4d0553f52b11a7d5fc546ff Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 25 Apr 2016 15:09:45 -0700 Subject: [PATCH 137/225] 8154213: clean up uses of boxed primitive constructors in the java.desktop module Reviewed-by: serb, psadhukhan --- .../tools/generatenimbus/UIProperty.java | 6 ++--- .../com/apple/eawt/_AppMenuBarHandler.java | 2 +- .../com/apple/laf/AquaComboBoxPopup.java | 2 +- .../apple/laf/AquaInternalFramePaneUI.java | 2 +- .../com/apple/laf/AquaLookAndFeel.java | 24 ++++++++--------- .../laf/AquaTabbedPaneCopyFromBasicUI.java | 4 +-- .../com/apple/laf/AquaUtilControlSize.java | 2 +- .../com/apple/laf/ScreenPopupFactory.java | 4 +-- .../macosx/classes/sun/font/CStrike.java | 8 +++--- .../classes/sun/lwawt/macosx/LWCToolkit.java | 6 ++--- .../sun/beans/decoder/NewElementHandler.java | 2 +- .../sun/imageio/plugins/bmp/BMPMetadata.java | 16 ++++++------ .../java/swing/plaf/gtk/GTKLookAndFeel.java | 2 +- .../com/sun/java/swing/plaf/gtk/Metacity.java | 2 +- .../classes/java/awt/font/TextAttribute.java | 2 +- .../classes/java/awt/font/TextMeasurer.java | 2 +- .../awt/image/renderable/ParameterBlock.java | 8 +++--- .../classes/javax/swing/JLayeredPane.java | 16 ++++++------ .../classes/javax/swing/JProgressBar.java | 2 +- .../share/classes/javax/swing/JTable.java | 2 +- .../javax/swing/SpinnerNumberModel.java | 15 ++++++----- .../share/classes/javax/swing/UIDefaults.java | 2 +- .../javax/swing/plaf/metal/OceanTheme.java | 6 ++--- .../javax/swing/text/JTextComponent.java | 6 ++--- .../javax/swing/text/NumberFormatter.java | 2 +- .../javax/swing/text/StyleConstants.java | 12 ++++----- .../classes/javax/swing/text/html/CSS.java | 26 +++++++++---------- .../javax/swing/text/rtf/RTFAttributes.java | 4 +-- .../sun/awt/image/PNGImageDecoder.java | 2 +- .../classes/sun/print/ServiceDialog.java | 12 ++++----- .../sun/print/PrintServiceLookupProvider.java | 2 +- 31 files changed, 102 insertions(+), 101 deletions(-) diff --git a/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java b/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java index 381db518284..943426c6881 100644 --- a/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java +++ b/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java @@ -54,13 +54,13 @@ class UIProperty extends UIDefault { return String.format(" d.put(\"%s%s\", \"%s\");\n", prefix, getName(), getValue()); case INT: - return String.format(" d.put(\"%s%s\", new Integer(%s));\n", + return String.format(" d.put(\"%s%s\", Integer.valueOf(%s));\n", prefix, getName(), getValue()); case FLOAT: - return String.format(" d.put(\"%s%s\", new Float(%sf));\n", + return String.format(" d.put(\"%s%s\", Float.valueOf(%sf));\n", prefix, getName(), getValue()); case DOUBLE: - return String.format(" d.put(\"%s%s\", new Double(%s));\n", + return String.format(" d.put(\"%s%s\", Double.valueOf(%s));\n", prefix, getName(), getValue()); case COLOR: return String.format(" addColor(d, \"%s%s\", %s);\n", diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java index 3a132f25595..027cbcf67e6 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java @@ -83,7 +83,7 @@ class _AppMenuBarHandler { // if we have no foreground frames, then we have to "kick" the menubar final JFrame pingFrame = new JFrame(); - pingFrame.getRootPane().putClientProperty("Window.alpha", new Float(0.0f)); + pingFrame.getRootPane().putClientProperty("Window.alpha", Float.valueOf(0.0f)); pingFrame.setUndecorated(true); pingFrame.setVisible(true); pingFrame.toFront(); diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java index 332cb7e46ff..88faf6b06e8 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java @@ -58,7 +58,7 @@ class AquaComboBoxPopup extends BasicComboPopup { updateContents(false); // TODO: CPlatformWindow? - putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, new Integer(150)); + putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, Integer.valueOf(150)); } public void updateContents(final boolean remove) { diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java index 1534d6d80c7..e12033fceb5 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java @@ -91,7 +91,7 @@ public class AquaInternalFramePaneUI extends BasicDesktopPaneUI implements Mouse JComponent getDock() { if (fDock == null) { fDock = new Dock(desktop); - desktop.add(fDock, new Integer(399)); // Just below the DRAG_LAYER + desktop.add(fDock, Integer.valueOf(399)); // Just below the DRAG_LAYER } return fDock; } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java index f04d42de03b..6694dd4c292 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -416,7 +416,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "Button.select", selected, "Button.border",(LazyValue) t -> AquaButtonBorder.getDynamicButtonBorder(), "Button.font", controlFont, - "Button.textIconGap", new Integer(4), + "Button.textIconGap", Integer.valueOf(4), "Button.textShiftOffset", zero, // radar 3308129 - aqua doesn't move images when pressed. "Button.focusInputMap", controlFocusInputMap, "Button.margin", new InsetsUIResource(0, 2, 0, 2), @@ -635,8 +635,8 @@ public class AquaLookAndFeel extends BasicLookAndFeel { //"Menu.checkIcon", emptyCheckIcon, // A non-drawing GlyphIcon to make the spacing consistent "Menu.arrowIcon",(LazyValue) t -> AquaImageFactory.getMenuArrowIcon(), "Menu.consumesTabs", Boolean.TRUE, - "Menu.menuPopupOffsetY", new Integer(1), - "Menu.submenuPopupOffsetY", new Integer(-4), + "Menu.menuPopupOffsetY", Integer.valueOf(1), + "Menu.submenuPopupOffsetY", Integer.valueOf(-4), "MenuBar.font", menuFont, "MenuBar.background", menuBackgroundColor, // not a menu item, not selected @@ -694,7 +694,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "OptionPane.informationSound", null, // Info and Plain "OptionPane.questionSound", null, "OptionPane.warningSound", null, - "OptionPane.buttonClickThreshhold", new Integer(500), + "OptionPane.buttonClickThreshhold", Integer.valueOf(500), "OptionPane.yesButtonMnemonic", "", "OptionPane.noButtonMnemonic", "", "OptionPane.okButtonMnemonic", "", @@ -717,7 +717,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "PasswordField.caretBlinkRate", textCaretBlinkRate, "PasswordField.border", textFieldBorder, "PasswordField.margin", zeroInsets, - "PasswordField.echoChar", new Character((char)0x25CF), + "PasswordField.echoChar", Character.valueOf((char)0x25CF), "PasswordField.capsLockIconColor", textPasswordFieldCapsLockIconColor, "PopupMenu.font", menuFont, @@ -736,7 +736,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "ProgressBar.selectionForeground", black, "ProgressBar.selectionBackground", white, "ProgressBar.border", new BorderUIResource(BorderFactory.createEmptyBorder()), - "ProgressBar.repaintInterval", new Integer(20), + "ProgressBar.repaintInterval", Integer.valueOf(20), "RadioButton.background", controlBackgroundColor, "RadioButton.foreground", black, @@ -772,7 +772,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "ScrollBar.border", null, "ScrollBar.focusInputMap", aquaKeyBindings.getScrollBarInputMap(), "ScrollBar.focusInputMap.RightToLeft", aquaKeyBindings.getScrollBarRightToLeftInputMap(), - "ScrollBar.width", new Integer(16), + "ScrollBar.width", Integer.valueOf(16), "ScrollBar.background", white, "ScrollBar.foreground", black, @@ -816,7 +816,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { //"SplitPane.shadow", table.get("controlShadow"), "SplitPane.background", panelBackgroundColor, "SplitPane.border", scollListBorder, - "SplitPane.dividerSize", new Integer(9), //$ + "SplitPane.dividerSize", Integer.valueOf(9), //$ "SplitPaneDivider.border", null, // AquaSplitPaneDividerUI draws it "SplitPaneDivider.horizontalGradientVariant",(LazyValue) t -> AquaSplitPaneDividerUI.getHorizontalSplitDividerGradientVariant(), @@ -833,7 +833,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { //"TabbedPane.darkShadow", table.get("controlDkShadow"), //"TabbedPane.focus", table.get("controlText"), "TabbedPane.opaque", useOpaqueComponents, - "TabbedPane.textIconGap", new Integer(4), + "TabbedPane.textIconGap", Integer.valueOf(4), "TabbedPane.tabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right) //"TabbedPane.rightTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right) "TabbedPane.leftTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab @@ -973,9 +973,9 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "Tree.selectionBorderColor", selectionBackground, // match the background so it looks like we don't draw anything "Tree.editorBorderSelectionColor", null, // The EditTextFrame provides its own border // "Tree.editorBorder", textFieldBorder, // If you still have Sun bug 4376328 in DefaultTreeCellEditor, it has to have the same insets as TextField.border - "Tree.leftChildIndent", new Integer(7),//$ - "Tree.rightChildIndent", new Integer(13),//$ - "Tree.rowHeight", new Integer(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching + "Tree.leftChildIndent", Integer.valueOf(7),//$ + "Tree.rightChildIndent", Integer.valueOf(13),//$ + "Tree.rowHeight", Integer.valueOf(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching "Tree.scrollsOnExpand", Boolean.FALSE, "Tree.openIcon",(LazyValue) t -> AquaImageFactory.getTreeOpenFolderIcon(), // Open folder icon "Tree.closedIcon",(LazyValue) t -> AquaImageFactory.getTreeFolderIcon(), // Closed folder icon 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 d85ed9e8f67..ad78bc26ca3 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 @@ -521,7 +521,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing } // [2165820] Mac OS X change: mnemonics need to be triggered with ctrl-option, not just option. mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK | Event.CTRL_MASK), "setSelectedIndex"); - mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index)); + mnemonicToIndexMap.put(Integer.valueOf(mnemonic), Integer.valueOf(index)); } /** @@ -2084,7 +2084,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing if (mnemonic >= 'a' && mnemonic <= 'z') { mnemonic -= ('a' - 'A'); } - final Integer index = ui.mnemonicToIndexMap.get(new Integer(mnemonic)); + final Integer index = ui.mnemonicToIndexMap.get(Integer.valueOf(mnemonic)); if (index != null && pane.isEnabledAt(index.intValue())) { pane.setSelectedIndex(index.intValue()); } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java index 2acc1eaedcf..999d24a7886 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java @@ -268,7 +268,7 @@ public class AquaUtilControlSize { public SizeVariant alterFontSize(final float newSize) { final float oldSize = fontSize == null ? 0.0f : fontSize.floatValue(); - fontSize = new Float(newSize + oldSize); + fontSize = newSize + oldSize; return this; } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java index bb2c0f1081b..b08b890aa2b 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java @@ -32,8 +32,8 @@ import sun.lwawt.macosx.CPlatformWindow; import sun.swing.SwingAccessor; class ScreenPopupFactory extends PopupFactory { - static final Float TRANSLUCENT = new Float(248f/255f); - static final Float OPAQUE = new Float(1.0f); + static final Float TRANSLUCENT = 248f/255f; + static final Float OPAQUE = 1.0f; boolean fIsActive = true; diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java b/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java index c50533a5947..ed3838886c9 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -386,7 +386,7 @@ public final class CStrike extends PhysicalStrike { if (generalCache == null) { return 0L; } - final Long value = generalCache.get(new Integer(index)); + final Long value = generalCache.get(Integer.valueOf(index)); if (value == null) { return 0L; } @@ -415,7 +415,7 @@ public final class CStrike extends PhysicalStrike { generalCache = new HashMap(); } - generalCache.put(new Integer(index), Long.valueOf(value)); + generalCache.put(Integer.valueOf(index), Long.valueOf(value)); } public synchronized void dispose() { @@ -526,7 +526,7 @@ public final class CStrike extends PhysicalStrike { } if (generalCache == null) return 0; - final Float value = generalCache.get(new Integer(index)); + final Float value = generalCache.get(Integer.valueOf(index)); if (value == null) return 0; return value.floatValue(); } @@ -553,7 +553,7 @@ public final class CStrike extends PhysicalStrike { generalCache = new HashMap(); } - generalCache.put(new Integer(index), new Float(value)); + generalCache.put(Integer.valueOf(index), Float.valueOf(value)); } private static class SparseBitShiftingTwoLayerArray { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index f0bf99c7321..309bc8ca8b1 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -378,9 +378,9 @@ public final class LWCToolkit extends LWToolkit { // These DnD properties must be set, otherwise Swing ends up spewing NPEs // all over the place. The values came straight off of MToolkit. - desktopProperties.put("DnD.Autoscroll.initialDelay", new Integer(50)); - desktopProperties.put("DnD.Autoscroll.interval", new Integer(50)); - desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5)); + desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50)); + desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50)); + desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5)); desktopProperties.put("DnD.isDragImageSupported", Boolean.TRUE); diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java index 69fbdce51dd..f753e04e83a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java +++ b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java @@ -42,7 +42,7 @@ import java.util.List; * <new class="java.lang.Long"> * <string>10</string> * </new> - * is equivalent to {@code new Long("10")} in Java code. + * is equivalent to {@code Long.valueOf("10")} in Java code. *

    The following attributes are supported: *

    *
    class diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java index d955c5f593c..4510882ad4b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java @@ -128,7 +128,7 @@ public class BMPMetadata extends IIOMetadata implements BMPConstants { addChildNode(root, "BMPVersion", bmpVersion); addChildNode(root, "Width", width); addChildNode(root, "Height", height); - addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel)); + addChildNode(root, "BitsPerPixel", Short.valueOf(bitsPerPixel)); addChildNode(root, "Compression", compression); addChildNode(root, "ImageSize", imageSize); @@ -172,12 +172,12 @@ public class BMPMetadata extends IIOMetadata implements BMPConstants { red = palette[j++] & 0xff; green = palette[j++] & 0xff; blue = palette[j++] & 0xff; - addChildNode(entry, "Red", new Byte((byte)red)); - addChildNode(entry, "Green", new Byte((byte)green)); - addChildNode(entry, "Blue", new Byte((byte)blue)); + addChildNode(entry, "Red", Byte.valueOf((byte)red)); + addChildNode(entry, "Green", Byte.valueOf((byte)green)); + addChildNode(entry, "Blue", Byte.valueOf((byte)blue)); if (numComps == 4) addChildNode(entry, "Alpha", - new Byte((byte)(palette[j++] & 0xff))); + Byte.valueOf((byte)(palette[j++] & 0xff))); } } @@ -284,9 +284,9 @@ public class BMPMetadata extends IIOMetadata implements BMPConstants { private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) { IIOMetadataNode node = addChildNode(root, name, null); - addChildNode(node, "X", new Double(x)); - addChildNode(node, "Y", new Double(y)); - addChildNode(node, "Z", new Double(z)); + addChildNode(node, "X", Double.valueOf(x)); + addChildNode(node, "Y", Double.valueOf(y)); + addChildNode(node, "Z", Double.valueOf(z)); } private IIOMetadataNode addChildNode(IIOMetadataNode root, diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index f568f6a4bae..be422a6275b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -379,7 +379,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { } Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0); - Double defaultCaretAspectRatio = new Double(0.025); + Double defaultCaretAspectRatio = Double.valueOf(0.025); Color caretColor = table.getColor("caretColor"); Color controlText = table.getColor("controlText"); diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java index 3a0342792b3..b8b77f5ec93 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java @@ -185,7 +185,7 @@ class Metacity implements SynthConstants { getIntAttr(child, "bottom", 0), getIntAttr(child, "right", 0)); } else if ("aspect_ratio".equals(name)) { - value = new Float(getFloatAttr(child, "value", 1.0F)); + value = Float.valueOf(getFloatAttr(child, "value", 1.0F)); } else { logError(themeName, "Unknown Metacity frame geometry value type: "+name); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java b/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java index 238dcb988f9..c9ae83659f6 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java +++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java @@ -79,7 +79,7 @@ import jdk.internal.misc.SharedSecrets; * will be ignored. *
  • The identity of the value does not matter, only the actual * value. For example, {@code TextAttribute.WEIGHT_BOLD} and - * {@code new Float(2.0)} + * {@code Float.valueOf(2.0f)} * indicate the same {@code WEIGHT}. *
  • Attribute values of type {@code Number} (used for * {@code WEIGHT}, {@code WIDTH}, {@code POSTURE}, diff --git a/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java b/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java index 4511d0eab15..5f47384697a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java @@ -105,7 +105,7 @@ public final class TextMeasurer implements Cloneable { String s = System.getProperty("estLines"); if (s != null) { try { - Float f = new Float(s); + Float f = Float.valueOf(s); EST_LINES = f.floatValue(); } catch(NumberFormatException e) { diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java index bfbaf5e1b2a..f9a3a2d2058 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java @@ -392,7 +392,7 @@ public class ParameterBlock implements Cloneable, Serializable { * the specified parameter. */ public ParameterBlock add(float f) { - return add(new Float(f)); + return add(Float.valueOf(f)); } /** @@ -403,7 +403,7 @@ public class ParameterBlock implements Cloneable, Serializable { * the specified parameter. */ public ParameterBlock add(double d) { - return add(new Double(d)); + return add(Double.valueOf(d)); } /** @@ -521,7 +521,7 @@ public class ParameterBlock implements Cloneable, Serializable { * the specified parameter. */ public ParameterBlock set(float f, int index) { - return set(new Float(f), index); + return set(Float.valueOf(f), index); } /** @@ -537,7 +537,7 @@ public class ParameterBlock implements Cloneable, Serializable { * the specified parameter. */ public ParameterBlock set(double d, int index) { - return set(new Double(d), index); + return set(Double.valueOf(d), index); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java b/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java index 3d561b99bef..6de8a0bd750 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java @@ -98,7 +98,7 @@ import javax.accessibility.*; *
      *     layeredPane.add(child, JLayeredPane.DEFAULT_LAYER);
      * or
    - *     layeredPane.add(child, new Integer(10));
    + *     layeredPane.add(child, Integer.valueOf.valueOf(10));
      * 
    * The layer attribute can also be set on a Component by calling
      *     layeredPaneParent.setLayer(child, 10)
    @@ -162,23 +162,23 @@ import javax.accessibility.*; @SuppressWarnings("serial") public class JLayeredPane extends JComponent implements Accessible { /// Watch the values in getObjectForLayer() - /** Convenience object defining the Default layer. Equivalent to new Integer(0).*/ + /** Convenience object defining the Default layer. Equivalent to Integer.valueOf(0).*/ public static final Integer DEFAULT_LAYER = 0; - /** Convenience object defining the Palette layer. Equivalent to new Integer(100).*/ + /** Convenience object defining the Palette layer. Equivalent to Integer.valueOf(100).*/ public static final Integer PALETTE_LAYER = 100; - /** Convenience object defining the Modal layer. Equivalent to new Integer(200).*/ + /** Convenience object defining the Modal layer. Equivalent to Integer.valueOf(200).*/ public static final Integer MODAL_LAYER = 200; - /** Convenience object defining the Popup layer. Equivalent to new Integer(300).*/ + /** Convenience object defining the Popup layer. Equivalent to Integer.valueOf(300).*/ public static final Integer POPUP_LAYER = 300; - /** Convenience object defining the Drag layer. Equivalent to new Integer(400).*/ + /** Convenience object defining the Drag layer. Equivalent to Integer.valueOf(400).*/ public static final Integer DRAG_LAYER = 400; /** Convenience object defining the Frame Content layer. * This layer is normally only use to position the contentPane and menuBar * components of JFrame. - * Equivalent to new Integer(-30000). + * Equivalent to Integer.valueOf(-30000). * @see JFrame */ - public static final Integer FRAME_CONTENT_LAYER = new Integer(-30000); + public static final Integer FRAME_CONTENT_LAYER = -30000; /** Bound property */ public static final String LAYER_PROPERTY = "layeredContainerLayer"; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java b/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java index 3504f2ef16a..216b18f4b19 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java @@ -478,7 +478,7 @@ public class JProgressBar extends JComponent implements SwingConstants, Accessib if (format == null) { format = NumberFormat.getPercentInstance(); } - return format.format(new Double(getPercentComplete())); + return format.format(Double.valueOf(getPercentComplete())); } } 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 9ca12ea6ee1..ee53fbffd91 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java @@ -81,7 +81,7 @@ import sun.swing.PrintingStatus; * TableModel dataModel = new AbstractTableModel() { * public int getColumnCount() { return 10; } * public int getRowCount() { return 10;} - * public Object getValueAt(int row, int col) { return new Integer(row*col); } + * public Object getValueAt(int row, int col) { return Integer.valueOf(row*col); } * }; * JTable table = new JTable(dataModel); * JScrollPane scrollpane = new JScrollPane(table); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java b/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java index 1d7fa9dec20..3fbd668bb80 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java @@ -51,10 +51,10 @@ import java.io.Serializable; * range zero to one hundred, with * fifty as the initial value, one could write: *
    - * Integer value = new Integer(50);
    - * Integer min = new Integer(0);
    - * Integer max = new Integer(100);
    - * Integer step = new Integer(1);
    + * Integer value = Integer.valueOf(50);
    + * Integer min = Integer.valueOf(0);
    + * Integer max = Integer.valueOf(100);
    + * Integer step = Integer.valueOf(1);
      * SpinnerNumberModel model = new SpinnerNumberModel(value, min, max, step);
      * int fifty = model.getNumber().intValue();
      * 
    @@ -175,7 +175,8 @@ public class SpinnerNumberModel extends AbstractSpinnerModel implements Serializ * minimum <= value <= maximum */ public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) { - this(new Double(value), new Double(minimum), new Double(maximum), new Double(stepSize)); + this(Double.valueOf(value), Double.valueOf(minimum), + Double.valueOf(maximum), Double.valueOf(stepSize)); } @@ -337,10 +338,10 @@ public class SpinnerNumberModel extends AbstractSpinnerModel implements Serializ if ((value instanceof Float) || (value instanceof Double)) { double v = value.doubleValue() + (stepSize.doubleValue() * (double)dir); if (value instanceof Double) { - newValue = new Double(v); + newValue = Double.valueOf(v); } else { - newValue = new Float(v); + newValue = Float.valueOf((float)v); } } else { long v = value.longValue() + (stepSize.longValue() * (long)dir); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java index 1955407b75a..2ad447e6a18 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java @@ -120,7 +120,7 @@ public class UIDefaults extends Hashtable Object[] uiDefaults = { "Font", new Font("Dialog", Font.BOLD, 12), "Color", Color.red, - "five", new Integer(5) + "five", Integer.valueOf(5) } UIDefaults myDefaults = new UIDefaults(uiDefaults); * diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java index d37c57076b9..b19632ff141 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java @@ -134,7 +134,7 @@ public class OceanTheme extends DefaultMetalTheme { new BorderUIResource.LineBorderUIResource(getPrimary1()); // .30 0 DDE8F3 white secondary2 java.util.List buttonGradient = Arrays.asList( - new Object[] {new Float(.3f), new Float(0f), + new Object[] {Float.valueOf(.3f), Float.valueOf(0f), new ColorUIResource(0xDDE8F3), getWhite(), getSecondary2() }); // Other possible properties that aren't defined: @@ -150,7 +150,7 @@ public class OceanTheme extends DefaultMetalTheme { Object directoryIcon = getIconResource("icons/ocean/directory.gif"); Object fileIcon = getIconResource("icons/ocean/file.gif"); java.util.List sliderGradient = Arrays.asList(new Object[] { - new Float(.3f), new Float(.2f), + Float.valueOf(.3f), Float.valueOf(.2f), c8ddf2, getWhite(), new ColorUIResource(SECONDARY2) }); Object[] defaults = new Object[] { @@ -192,7 +192,7 @@ public class OceanTheme extends DefaultMetalTheme { "Menu.opaque", Boolean.FALSE, "MenuBar.gradient", Arrays.asList(new Object[] { - new Float(1f), new Float(0f), + Float.valueOf(1f), Float.valueOf(0f), getWhite(), dadada, new ColorUIResource(dadada) }), "MenuBar.borderColor", cccccc, 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 3d31a0d1936..ff28193c3e8 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 @@ -2580,7 +2580,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param e the DocumentEvent */ public void insertUpdate(DocumentEvent e) { - final Integer pos = new Integer (e.getOffset()); + final Integer pos = e.getOffset(); if (SwingUtilities.isEventDispatchThread()) { firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos); } else { @@ -2602,7 +2602,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param e the DocumentEvent */ public void removeUpdate(DocumentEvent e) { - final Integer pos = new Integer (e.getOffset()); + final Integer pos = e.getOffset(); if (SwingUtilities.isEventDispatchThread()) { firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos); } else { @@ -2624,7 +2624,7 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A * @param e the DocumentEvent */ public void changedUpdate(DocumentEvent e) { - final Integer pos = new Integer (e.getOffset()); + final Integer pos = e.getOffset(); if (SwingUtilities.isEventDispatchThread()) { firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos); } else { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java b/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java index 5b5cb3920df..b3db8fceb03 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java @@ -73,7 +73,7 @@ import sun.swing.SwingUtilities2; * type the value class represents. For example: * setValueClass(Integer.class) will cause the resulting * value to be created via - * new Integer(((Number)formatter.parseObject(string)).intValue()). + * Integer.valueOf(((Number)formatter.parseObject(string)).intValue()). * This is typically useful if you * wish to set a min/max value as the various Number * implementations are generally not comparable to each other. This is also diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java b/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java index 583b4dffd72..2aea5e5b2b5 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java @@ -608,7 +608,7 @@ public class StyleConstants { * @param i the value */ public static void setFirstLineIndent(MutableAttributeSet a, float i) { - a.addAttribute(FirstLineIndent, new Float(i)); + a.addAttribute(FirstLineIndent, Float.valueOf(i)); } /** @@ -632,7 +632,7 @@ public class StyleConstants { * @param i the value */ public static void setRightIndent(MutableAttributeSet a, float i) { - a.addAttribute(RightIndent, new Float(i)); + a.addAttribute(RightIndent, Float.valueOf(i)); } /** @@ -656,7 +656,7 @@ public class StyleConstants { * @param i the value */ public static void setLeftIndent(MutableAttributeSet a, float i) { - a.addAttribute(LeftIndent, new Float(i)); + a.addAttribute(LeftIndent, Float.valueOf(i)); } /** @@ -680,7 +680,7 @@ public class StyleConstants { * @param i the value */ public static void setLineSpacing(MutableAttributeSet a, float i) { - a.addAttribute(LineSpacing, new Float(i)); + a.addAttribute(LineSpacing, Float.valueOf(i)); } /** @@ -704,7 +704,7 @@ public class StyleConstants { * @param i the value */ public static void setSpaceAbove(MutableAttributeSet a, float i) { - a.addAttribute(SpaceAbove, new Float(i)); + a.addAttribute(SpaceAbove, Float.valueOf(i)); } /** @@ -728,7 +728,7 @@ public class StyleConstants { * @param i the value */ public static void setSpaceBelow(MutableAttributeSet a, float i) { - a.addAttribute(SpaceBelow, new Float(i)); + a.addAttribute(SpaceBelow, Float.valueOf(i)); } /** 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 06a8ebf6534..c6e715f6672 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 @@ -2564,7 +2564,7 @@ public class CSS implements Serializable { * represents the CSS attribute value */ Object toStyleConstants(StyleConstants key, View v) { - return new Float(getValue(false)); + return Float.valueOf(getValue(false)); } /** If true, span is a percentage value, and that to determine @@ -2837,25 +2837,25 @@ public class CSS implements Serializable { static Hashtable lengthMapping = new Hashtable(6); static Hashtable w3cLengthMapping = new Hashtable(6); static { - lengthMapping.put("pt", new Float(1f)); + lengthMapping.put("pt", Float.valueOf(1f)); // Not sure about 1.3, determined by experiementation. - lengthMapping.put("px", new Float(1.3f)); - lengthMapping.put("mm", new Float(2.83464f)); - lengthMapping.put("cm", new Float(28.3464f)); - lengthMapping.put("pc", new Float(12f)); - lengthMapping.put("in", new Float(72f)); + lengthMapping.put("px", Float.valueOf(1.3f)); + lengthMapping.put("mm", Float.valueOf(2.83464f)); + lengthMapping.put("cm", Float.valueOf(28.3464f)); + lengthMapping.put("pc", Float.valueOf(12f)); + lengthMapping.put("in", Float.valueOf(72f)); int res = 72; try { res = Toolkit.getDefaultToolkit().getScreenResolution(); } catch (HeadlessException e) { } // mapping according to the CSS2 spec - w3cLengthMapping.put("pt", new Float(res/72f)); - w3cLengthMapping.put("px", new Float(1f)); - w3cLengthMapping.put("mm", new Float(res/25.4f)); - w3cLengthMapping.put("cm", new Float(res/2.54f)); - w3cLengthMapping.put("pc", new Float(res/6f)); - w3cLengthMapping.put("in", new Float(res)); + w3cLengthMapping.put("pt", Float.valueOf(res/72f)); + w3cLengthMapping.put("px", Float.valueOf(1f)); + w3cLengthMapping.put("mm", Float.valueOf(res/25.4f)); + w3cLengthMapping.put("cm", Float.valueOf(res/2.54f)); + w3cLengthMapping.put("pc", Float.valueOf(res/6f)); + w3cLengthMapping.put("in", Float.valueOf((float)res)); } LengthUnit(String value, short defaultType, float defaultValue) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java b/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java index 99f2822cdcc..a58fb451de9 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java @@ -357,7 +357,7 @@ class RTFAttributes public static NumericAttribute NewTwips(int d, Object s, String r, float ds, int dr) { - return new NumericAttribute(d, s, r, new Float(ds), dr, 20f); + return new NumericAttribute(d, s, r, Float.valueOf(ds), dr, 20f); } public static NumericAttribute NewTwips(int d, Object s, String r, @@ -378,7 +378,7 @@ class RTFAttributes if (scale == 1f) swingValue = Integer.valueOf(parameter); else - swingValue = new Float(parameter / scale); + swingValue = Float.valueOf(parameter / scale); target.addAttribute(swingName, swingValue); return true; } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java b/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java index 0627f91fca3..edc2fa2039f 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java @@ -87,7 +87,7 @@ public class PNGImageDecoder extends ImageDecoder properties.put(key,value); } private void property(String key,float value) { - property(key,new Float(value)); + property(key, Float.valueOf(value)); } private final void pngassert(boolean b) throws IOException { if(!b) { diff --git a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java index 615304c75f4..6e5a4cf3c93 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java @@ -1402,8 +1402,8 @@ public class ServiceDialog extends JDialog implements ActionListener { format.setParseIntegerOnly(false); format.setDecimalSeparatorAlwaysShown(true); NumberFormatter nf = new NumberFormatter(format); - nf.setMinimum(new Float(0.0f)); - nf.setMaximum(new Float(999.0f)); + nf.setMinimum(Float.valueOf(0.0f)); + nf.setMaximum(Float.valueOf(999.0f)); nf.setAllowsInvalid(true); nf.setCommitsOnValidEdit(true); @@ -1836,10 +1836,10 @@ public class ServiceDialog extends JDialog implements ActionListener { rmVal = mediaSize.getX(units) - pax - paw; bmVal = mediaSize.getY(units) - pay - pah; - lmObj = new Float(lmVal); - rmObj = new Float(rmVal); - tmObj = new Float(tmVal); - bmObj = new Float(bmVal); + lmObj = lmVal; + rmObj = rmVal; + tmObj = tmVal; + bmObj = bmVal; /* Now we know the values to use, we need to assign them * to the fields appropriate for the orientation. 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 4da098d504e..93f65327e08 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java @@ -117,7 +117,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup if (refreshTimeStr != null) { try { - minRefreshTime = (new Integer(refreshTimeStr)).intValue(); + minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue(); } catch (NumberFormatException e) { } if (minRefreshTime < DEFAULT_MINREFRESH) { From 20a9ca787508388551d9a4349e738ea0c5794c81 Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Mon, 25 Apr 2016 16:29:50 -0700 Subject: [PATCH 138/225] 8154594: JFrame.setDefaultCloseOperation is prohibited in jtreg: Missing part of the fix Reviewed-by: alexsch, prr --- .../src/com/sun/swingset3/demos/button/ButtonDemo.java | 5 +++-- .../com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java | 1 - .../src/com/sun/swingset3/demos/window/WindowDemo.java | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) 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 e3aa888e5f3..358ae49d64b 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 @@ -36,6 +36,7 @@ import javax.swing.SwingUtilities; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.JHyperlink; +import java.lang.reflect.InvocationTargetException; /** * @@ -210,10 +211,10 @@ public final class ButtonDemo extends JPanel { return panel; } - public static void main(String args[]) { + public static void main(String args[]) throws InterruptedException, InvocationTargetException { final ButtonDemo buttonDemo = new ButtonDemo(); - javax.swing.SwingUtilities.invokeLater(() -> { + javax.swing.SwingUtilities.invokeAndWait(() -> { JFrame frame = new JFrame(DEMO_TITLE); frame.add(buttonDemo); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java index 9809d6babbe..5d023405b58 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java @@ -91,7 +91,6 @@ public class TabbedPaneDemo 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 TabbedPaneDemo()); 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 89b87776ba2..bbb06a1182a 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 @@ -31,6 +31,7 @@ import javax.swing.border.LineBorder; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.DemoUtilities; +import java.lang.reflect.InvocationTargetException; /** * @author aim @@ -145,8 +146,8 @@ public final class WindowDemo extends JPanel { } } - public static void main(String args[]) { - EventQueue.invokeLater(() -> { + public static void main(String args[]) throws InterruptedException, InvocationTargetException { + EventQueue.invokeAndWait(() -> { JFrame frame = new JFrame(); WindowDemo demo = new WindowDemo(); frame.add(demo); From 5125f7137636702fad6f2bef39c195e14aaeb83b Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Mon, 25 Apr 2016 16:34:03 -0700 Subject: [PATCH 139/225] 8154706: Sanity tests prepareBundle task doesn't produce working bundle Reviewed-by: alexsch, prr --- jdk/test/sanity/client/TEST.ROOT.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/sanity/client/TEST.ROOT.template b/jdk/test/sanity/client/TEST.ROOT.template index 6881809d9f8..e703c4ce236 100644 --- a/jdk/test/sanity/client/TEST.ROOT.template +++ b/jdk/test/sanity/client/TEST.ROOT.template @@ -12,7 +12,7 @@ # A "headful" test requires a graphical environment to meaningfully # run. Tests that are not headful are "headless." -keys=screenshots +keys=2d dnd i18n intermittent randomness headful # Tests that must run in othervm mode othervm.dirs=sanity/client/SwingSet From fb8f4acea810faab05065fcb045facf0b9a4bf35 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Tue, 26 Apr 2016 11:55:52 -0300 Subject: [PATCH 140/225] 8132994: /modules and /packages should not be parsed by the jimage parser Reviewed-by: sundar --- .../jlink/internal/ImageLocationWriter.java | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java index e66ba64210b..0faf8c95d8b 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java @@ -61,24 +61,32 @@ public final class ImageLocationWriter extends ImageLocation { String baseName; String extensionName = ""; - int offset = fullName.indexOf('/', 1); - if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { - moduleName = fullName.substring(1, offset); - fullName = fullName.substring(offset + 1); - } - - offset = fullName.lastIndexOf('/'); - if (1 < offset) { - parentName = fullName.substring(0, offset); - fullName = fullName.substring(offset + 1); - } - - offset = fullName.lastIndexOf('.'); - if (offset != -1) { - baseName = fullName.substring(0, offset); - extensionName = fullName.substring(offset + 1); + if (fullName.startsWith("/modules/")) { + moduleName = "modules"; + baseName = fullName.substring("/modules/".length()); + } else if ( fullName.startsWith("/packages/")) { + moduleName = "packages"; + baseName = fullName.substring("/packages/".length()); } else { - baseName = fullName; + int offset = fullName.indexOf('/', 1); + if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) { + moduleName = fullName.substring(1, offset); + fullName = fullName.substring(offset + 1); + } + + offset = fullName.lastIndexOf('/'); + if (1 < offset) { + parentName = fullName.substring(0, offset); + fullName = fullName.substring(offset + 1); + } + + offset = fullName.lastIndexOf('.'); + if (offset != -1) { + baseName = fullName.substring(0, offset); + extensionName = fullName.substring(offset + 1); + } else { + baseName = fullName; + } } return new ImageLocationWriter(strings) From c08b6a7c8fcf4250eb5ec0ffb3b617b3faa955f6 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 26 Apr 2016 17:35:10 -0400 Subject: [PATCH 141/225] 8066750: Remove HTTP proxy implementation and tests from RMI Reviewed-by: smarks --- .../java/rmi/server/RMISocketFactory.java | 21 +- .../sun/rmi/transport/proxy/CGIHandler.java | 423 ---------------- .../proxy/HttpAwareServerSocket.java | 114 ----- .../rmi/transport/proxy/HttpInputStream.java | 205 -------- .../rmi/transport/proxy/HttpOutputStream.java | 80 --- .../transport/proxy/HttpReceiveSocket.java | 128 ----- .../transport/proxy/HttpSendInputStream.java | 161 ------ .../transport/proxy/HttpSendOutputStream.java | 105 ---- .../rmi/transport/proxy/HttpSendSocket.java | 344 ------------- .../proxy/RMIHttpToCGISocketFactory.java | 55 -- .../proxy/RMIHttpToPortSocketFactory.java | 53 -- .../proxy/RMIMasterSocketFactory.java | 468 ------------------ .../rmi/transport/proxy/RMISocketInfo.java | 39 -- .../rmi/transport/proxy/WrappedSocket.java | 192 ------- .../sun/rmi/transport/tcp/TCPConnection.java | 11 +- .../TCPDirectSocketFactory.java} | 4 +- .../sun/rmi/transport/tcp/TCPTransport.java | 30 +- jdk/test/ProblemList.txt | 2 - .../transport/httpSocket/HttpSocketTest.java | 113 ----- .../httpSocket/HttpSocketTest_Stub.java | 130 ----- .../rmi/transport/httpSocket/security.policy | 10 - .../proxy/DisableHttpDefaultValue.java | 69 --- .../transport/proxy/EagerHttpFallback.java | 73 --- .../tcp/blockAccept/BlockAcceptTest.java | 175 ------- .../transport/tcp/blockAccept/TestIface.java | 31 -- .../transport/tcp/blockAccept/TestImpl.java | 49 -- .../tcp/blockAccept/TestImpl_Stub.java | 66 --- .../transport/tcp/blockAccept/security.policy | 10 - 28 files changed, 10 insertions(+), 3151 deletions(-) delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java delete mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java rename jdk/src/java.rmi/share/classes/sun/rmi/transport/{proxy/RMIDirectSocketFactory.java => tcp/TCPDirectSocketFactory.java} (94%) delete mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java delete mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java delete mode 100644 jdk/test/java/rmi/transport/httpSocket/security.policy delete mode 100644 jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java delete mode 100644 jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java delete mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java index e69c269f81a..df3bc9fd24a 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.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 @@ -35,21 +35,8 @@ import java.net.*; * request that the RMI runtime use its socket factory instance * instead of the default implementation. * - *

    The default socket factory implementation performs a - * three-tiered approach to creating client sockets. First, a direct - * socket connection to the remote VM is attempted. If that fails - * (due to a firewall), the runtime uses HTTP with the explicit port - * number of the server. If the firewall does not allow this type of - * communication, then HTTP to a cgi-bin script on the server is used - * to POST the RMI call. The HTTP tunneling mechanisms are disabled by - * default. This behavior is controlled by the {@code java.rmi.server.disableHttp} - * property, whose default value is {@code true}. Setting this property's - * value to {@code false} will enable the HTTP tunneling mechanisms. - * - *

    Deprecated: HTTP Tunneling. The HTTP tunneling mechanisms - * described above, specifically HTTP with an explicit port and HTTP to a - * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are - * subject to removal in a future release of the platform. + *

    The default socket factory implementation creates a direct + * socket connection to the remote host. * *

    The default socket factory implementation creates server sockets that * are bound to the wildcard address, which accepts requests from all network @@ -181,7 +168,7 @@ public abstract class RMISocketFactory public synchronized static RMISocketFactory getDefaultSocketFactory() { if (defaultSocketFactory == null) { defaultSocketFactory = - new sun.rmi.transport.proxy.RMIMasterSocketFactory(); + new sun.rmi.transport.tcp.TCPDirectSocketFactory(); } return defaultSocketFactory; } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java deleted file mode 100644 index 546ccd8ea10..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 1996, 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. 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.transport.proxy; - -import java.io.*; -import java.net.*; -import java.util.Hashtable; - -/** - * CGIClientException is thrown when an error is detected - * in a client's request. - */ -class CGIClientException extends Exception { - private static final long serialVersionUID = 8147981687059865216L; - - public CGIClientException(String s) { - super(s); - } - - public CGIClientException(String s, Throwable cause) { - super(s, cause); - } -} - -/** - * CGIServerException is thrown when an error occurs here on the server. - */ -class CGIServerException extends Exception { - - private static final long serialVersionUID = 6928425456704527017L; - - public CGIServerException(String s) { - super(s); - } - - public CGIServerException(String s, Throwable cause) { - super(s, cause); - } -} - -/** - * CGICommandHandler is the interface to an object that handles a - * particular supported command. - */ -interface CGICommandHandler { - - /** - * Return the string form of the command - * to be recognized in the query string. - */ - public String getName(); - - /** - * Execute the command with the given string as parameter. - */ - public void execute(String param) throws CGIClientException, CGIServerException; -} - -/** - * The CGIHandler class contains methods for executing as a CGI program. - * The main function interprets the query string as a command of the form - * "{@code =}". - * - * This class depends on the CGI 1.0 environment variables being set as - * properties of the same name in this Java VM. - * - * All data and methods of this class are static because they are specific - * to this particular CGI process. - */ -public final class CGIHandler { - - /* get CGI parameters that we need */ - static int ContentLength; - static String QueryString; - static String RequestMethod; - static String ServerName; - static int ServerPort; - - static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - ContentLength = - Integer.getInteger("CONTENT_LENGTH", 0).intValue(); - QueryString = System.getProperty("QUERY_STRING", ""); - RequestMethod = System.getProperty("REQUEST_METHOD", ""); - ServerName = System.getProperty("SERVER_NAME", ""); - ServerPort = Integer.getInteger("SERVER_PORT", 0).intValue(); - return null; - } - }); - } - - /* list of handlers for supported commands */ - private static CGICommandHandler commands[] = { - new CGIForwardCommand(), - new CGIGethostnameCommand(), - new CGIPingCommand(), - new CGITryHostnameCommand() - }; - - /* construct table mapping command strings to handlers */ - private static Hashtable commandLookup; - static { - commandLookup = new Hashtable<>(); - for (int i = 0; i < commands.length; ++ i) - commandLookup.put(commands[i].getName(), commands[i]); - } - - /* prevent instantiation of this class */ - private CGIHandler() {} - - /** - * Execute command given in query string on URL. The string before - * the first '=' is interpreted as the command name, and the string - * after the first '=' is the parameters to the command. - */ - public static void main(String args[]) - { - try { - String command, param; - int delim = QueryString.indexOf('='); - if (delim == -1) { - command = QueryString; - param = ""; - } - else { - command = QueryString.substring(0, delim); - param = QueryString.substring(delim + 1); - } - CGICommandHandler handler = - commandLookup.get(command); - if (handler != null) - try { - handler.execute(param); - } catch (CGIClientException e) { - e.printStackTrace(); - returnClientError(e.getMessage()); - } catch (CGIServerException e) { - e.printStackTrace(); - returnServerError(e.getMessage()); - } - else - returnClientError("invalid command."); - } catch (Exception e) { - e.printStackTrace(); - returnServerError("internal error: " + e.getMessage()); - } - System.exit(0); - } - - /** - * Return an HTML error message indicating there was error in - * the client's request. - */ - private static void returnClientError(String message) - { - System.out.println("Status: 400 Bad Request: " + message); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Client Error" + - "" + - ""); - System.out.println("

    Java RMI Client Error

    "); - System.out.println(""); - System.out.println(message); - System.out.println(""); - System.exit(1); - } - - /** - * Return an HTML error message indicating an error occurred - * here on the server. - */ - private static void returnServerError(String message) - { - System.out.println("Status: 500 Server Error: " + message); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Server Error" + - "" + - ""); - System.out.println("

    Java RMI Server Error

    "); - System.out.println(""); - System.out.println(message); - System.out.println(""); - System.exit(1); - } -} - -/** - * "forward" command: Forward request body to local port on the server, - * and send response back to client. - */ -final class CGIForwardCommand implements CGICommandHandler { - - public String getName() { - return "forward"; - } - - @SuppressWarnings("deprecation") - private String getLine (DataInputStream socketIn) throws IOException { - return socketIn.readLine(); - } - - public void execute(String param) throws CGIClientException, CGIServerException - { - if (!CGIHandler.RequestMethod.equals("POST")) - throw new CGIClientException("can only forward POST requests"); - - int port; - try { - port = Integer.parseInt(param); - } catch (NumberFormatException e) { - throw new CGIClientException("invalid port number.", e); - } - if (port <= 0 || port > 0xFFFF) - throw new CGIClientException("invalid port: " + port); - if (port < 1024) - throw new CGIClientException("permission denied for port: " + - port); - - byte buffer[]; - Socket socket; - try { - socket = new Socket(InetAddress.getLocalHost(), port); - } catch (IOException e) { - throw new CGIServerException("could not connect to local port", e); - } - - /* - * read client's request body - */ - DataInputStream clientIn = new DataInputStream(System.in); - buffer = new byte[CGIHandler.ContentLength]; - try { - clientIn.readFully(buffer); - } catch (EOFException e) { - throw new CGIClientException("unexpected EOF reading request body", e); - } catch (IOException e) { - throw new CGIClientException("error reading request body", e); - } - - /* - * send to local server in HTTP - */ - try { - DataOutputStream socketOut = - new DataOutputStream(socket.getOutputStream()); - socketOut.writeBytes("POST / HTTP/1.0\r\n"); - socketOut.writeBytes("Content-length: " + - CGIHandler.ContentLength + "\r\n\r\n"); - socketOut.write(buffer); - socketOut.flush(); - } catch (IOException e) { - throw new CGIServerException("error writing to server", e); - } - - /* - * read response - */ - DataInputStream socketIn; - try { - socketIn = new DataInputStream(socket.getInputStream()); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - String key = "Content-length:".toLowerCase(); - boolean contentLengthFound = false; - String line; - int responseContentLength = -1; - do { - try { - line = getLine(socketIn); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - if (line == null) - throw new CGIServerException( - "unexpected EOF reading server response"); - - if (line.toLowerCase().startsWith(key)) { - if (contentLengthFound) { - throw new CGIServerException( - "Multiple Content-length entries found."); - } else { - responseContentLength = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; - } - } - } while ((line.length() != 0) && - (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); - - if (!contentLengthFound || responseContentLength < 0) - throw new CGIServerException( - "missing or invalid content length in server response"); - buffer = new byte[responseContentLength]; - try { - socketIn.readFully(buffer); - } catch (EOFException e) { - throw new CGIServerException( - "unexpected EOF reading server response", e); - } catch (IOException e) { - throw new CGIServerException("error reading from server", e); - } - - /* - * send response back to client - */ - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println(""); - try { - System.out.write(buffer); - } catch (IOException e) { - throw new CGIServerException("error writing response", e); - } - System.out.flush(); - } -} - -/** - * "gethostname" command: Return the host name of the server as the - * response body - */ -final class CGIGethostnameCommand implements CGICommandHandler { - - public String getName() { - return "gethostname"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println("Content-length: " + - CGIHandler.ServerName.length()); - System.out.println(""); - System.out.print(CGIHandler.ServerName); - System.out.flush(); - } -} - -/** - * "ping" command: Return an OK status to indicate that connection - * was successful. - */ -final class CGIPingCommand implements CGICommandHandler { - - public String getName() { - return "ping"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: application/octet-stream"); - System.out.println("Content-length: 0"); - System.out.println(""); - } -} - -/** - * "tryhostname" command: Return a human readable message describing - * what host name is available to local Java VMs. - */ -final class CGITryHostnameCommand implements CGICommandHandler { - - public String getName() { - return "tryhostname"; - } - - public void execute(String param) - { - System.out.println("Status: 200 OK"); - System.out.println("Content-type: text/html"); - System.out.println(""); - System.out.println("" + - "Java RMI Server Hostname Info" + - "" + - ""); - System.out.println("

    Java RMI Server Hostname Info

    "); - System.out.println("

    Local host name available to Java VM:

    "); - System.out.print("

    InetAddress.getLocalHost().getHostName()"); - try { - String localHostName = InetAddress.getLocalHost().getHostName(); - - System.out.println(" = " + localHostName); - } catch (UnknownHostException e) { - System.out.println(" threw java.net.UnknownHostException"); - } - - System.out.println("

    Server host information obtained through CGI interface from HTTP server:

    "); - System.out.println("

    SERVER_NAME = " + CGIHandler.ServerName); - System.out.println("

    SERVER_PORT = " + CGIHandler.ServerPort); - System.out.println(""); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java deleted file mode 100644 index b4512fecd93..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 1996, 2005, 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.transport.proxy; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import sun.rmi.runtime.Log; - -/** - * The HttpAwareServerSocket class extends the java.net.ServerSocket - * class. It behaves like a ServerSocket, except that if - * the first four bytes of an accepted socket are the letters "POST", - * then it returns an HttpReceiveSocket instead of a java.net.Socket. - * This means that the accept method blocks until four bytes have been - * read from the new socket's input stream. - */ -class HttpAwareServerSocket extends ServerSocket { - - /** - * Create a server socket on a specified port. - * @param port the port - * @exception IOException IO error when opening the socket. - */ - public HttpAwareServerSocket(int port) throws IOException - { - super(port); - } - - /** - * Create a server socket, bind it to the specified local port - * and listen to it. You can connect to an annonymous port by - * specifying the port number to be 0. backlog specifies - * how many connection requests the system will queue up while waiting - * for the ServerSocket to execute accept(). - * @param port the specified port - * @param backlog the number of queued connect requests pending accept - */ - public HttpAwareServerSocket(int port, int backlog) throws IOException - { - super(port, backlog); - } - - /** - * Accept a connection. This method will block until the connection - * is made and four bytes can be read from the input stream. - * If the first four bytes are "POST", then an HttpReceiveSocket is - * returned, which will handle the HTTP protocol wrapping. - * Otherwise, a WrappedSocket is returned. The input stream will be - * reset to the beginning of the transmission. - * In either case, a BufferedInputStream will already be on top of - * the underlying socket's input stream. - * @exception IOException IO error when waiting for the connection. - */ - public Socket accept() throws IOException - { - Socket socket = super.accept(); - BufferedInputStream in = - new BufferedInputStream(socket.getInputStream()); - - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - "socket accepted (checking for POST)"); - - in.mark(4); - boolean isHttp = (in.read() == 'P') && - (in.read() == 'O') && - (in.read() == 'S') && - (in.read() == 'T'); - in.reset(); - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - (isHttp ? "POST found, HTTP socket returned" : - "POST not found, direct socket returned")); - } - - if (isHttp) - return new HttpReceiveSocket(socket, in, null); - else - return new WrappedSocket(socket, in, null); - } - - /** - * Return the implementation address and implementation port of - * the HttpAwareServerSocket as a String. - */ - public String toString() - { - return "HttpAware" + super.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java deleted file mode 100644 index 4b5cad95044..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 1996, 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. 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.transport.proxy; - -import java.io.*; - -import sun.rmi.runtime.Log; - -/** - * The HttpInputStream class assists the HttpSendSocket and HttpReceiveSocket - * classes by filtering out the header for the message as well as any - * data after its proper content length. - */ -class HttpInputStream extends FilterInputStream { - - /** bytes remaining to be read from proper content of message */ - protected int bytesLeft; - - /** bytes remaining to be read at time of last mark */ - protected int bytesLeftAtMark; - - /** - * Create new filter on a given input stream. - * @param in the InputStream to filter from - */ - @SuppressWarnings("deprecation") - public HttpInputStream(InputStream in) throws IOException - { - super(in); - - if (in.markSupported()) - in.mark(0); // prevent resetting back to old marks - - // pull out header, looking for content length - - DataInputStream dis = new DataInputStream(in); - String key = "Content-length:".toLowerCase(); - boolean contentLengthFound = false; - String line; - do { - line = dis.readLine(); - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "received header line: \"" + line + "\""); - } - - if (line == null) - throw new EOFException(); - - if (line.toLowerCase().startsWith(key)) { - if (contentLengthFound) { - throw new IOException( - "Multiple Content-length entries found."); - } else { - bytesLeft = - Integer.parseInt(line.substring(key.length()).trim()); - contentLengthFound = true; - } - } - - // The idea here is to go past the first blank line. - // Some DataInputStream.readLine() documentation specifies that - // it does include the line-terminating character(s) in the - // returned string, but it actually doesn't, so we'll cover - // all cases here... - } while ((line.length() != 0) && - (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); - - if (!contentLengthFound || bytesLeft < 0) { - // This really shouldn't happen, but if it does, shoud we fail?? - // For now, just give up and let a whole lot of bytes through... - bytesLeft = Integer.MAX_VALUE; - } - bytesLeftAtMark = bytesLeft; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "content length: " + bytesLeft); - } - } - - /** - * Returns the number of bytes that can be read with blocking. - * Make sure that this does not exceed the number of bytes remaining - * in the proper content of the message. - */ - public int available() throws IOException - { - int bytesAvailable = in.available(); - if (bytesAvailable > bytesLeft) - bytesAvailable = bytesLeft; - - return bytesAvailable; - } - - /** - * Read a byte of data from the stream. Make sure that one is available - * from the proper content of the message, else -1 is returned to - * indicate to the user that the end of the stream has been reached. - */ - public int read() throws IOException - { - if (bytesLeft > 0) { - int data = in.read(); - if (data != -1) - -- bytesLeft; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "received byte: '" + - ((data & 0x7F) < ' ' ? " " : String.valueOf((char) data)) + - "' " + data); - } - - return data; - } - else { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read past content length"); - - return -1; - } - } - - public int read(byte b[], int off, int len) throws IOException - { - if (bytesLeft == 0 && len > 0) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read past content length"); - - return -1; - } - if (len > bytesLeft) - len = bytesLeft; - int bytesRead = in.read(b, off, len); - bytesLeft -= bytesRead; - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "read " + bytesRead + " bytes, " + bytesLeft + " remaining"); - } - - return bytesRead; - } - - /** - * Mark the current position in the stream (for future calls to reset). - * Remember where we are within the proper content of the message, so - * that a reset method call can recreate our state properly. - * @param readlimit how many bytes can be read before mark becomes invalid - */ - public void mark(int readlimit) - { - in.mark(readlimit); - if (in.markSupported()) - bytesLeftAtMark = bytesLeft; - } - - /** - * Repositions the stream to the last marked position. Make sure to - * adjust our position within the proper content accordingly. - */ - public void reset() throws IOException - { - in.reset(); - bytesLeft = bytesLeftAtMark; - } - - /** - * Skips bytes of the stream. Make sure to adjust our - * position within the proper content accordingly. - * @param n number of bytes to be skipped - */ - public long skip(long n) throws IOException - { - if (n > bytesLeft) - n = bytesLeft; - long bytesSkipped = in.skip(n); - bytesLeft -= bytesSkipped; - return bytesSkipped; - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java deleted file mode 100644 index 5f1f2a6a680..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1996, 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.transport.proxy; - -import java.io.*; - -/** - * The HttpOutputStream class assists the HttpSendSocket and HttpReceiveSocket - * classes by providing an output stream that buffers its entire input until - * closed, and then it sends the complete transmission prefixed by the end of - * an HTTP header that specifies the content length. - */ -class HttpOutputStream extends ByteArrayOutputStream { - - /** the output stream to send response to */ - protected OutputStream out; - - /** true if HTTP response has been sent */ - boolean responseSent = false; - - /** - * Begin buffering new HTTP response to be sent to a given stream. - * @param out the OutputStream to send response to - */ - public HttpOutputStream(OutputStream out) { - super(); - this.out = out; - } - - /** - * On close, send HTTP-packaged response. - */ - public synchronized void close() throws IOException { - if (!responseSent) { - /* - * If response would have zero content length, then make it - * have some arbitrary data so that certain clients will not - * fail because the "document contains no data". - */ - if (size() == 0) - write(emptyData); - - DataOutputStream dos = new DataOutputStream(out); - dos.writeBytes("Content-type: application/octet-stream\r\n"); - dos.writeBytes("Content-length: " + size() + "\r\n"); - dos.writeBytes("\r\n"); - writeTo(dos); - dos.flush(); - // Do not close the underlying stream here, because that would - // close the underlying socket and prevent reading a response. - reset(); // reset byte array - responseSent = true; - } - } - - /** data to send if the response would otherwise be empty */ - private static byte[] emptyData = { 0 }; -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java deleted file mode 100644 index c916254ffcd..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 1996, 2000, 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.transport.proxy; - -import java.io.*; -import java.net.Socket; -import java.net.InetAddress; - -/** - * The HttpReceiveSocket class extends the WrappedSocket class - * by removing the HTTP protocol packaging from the input stream and - * formatting the output stream as an HTTP response. - * - * NOTES: - * - * The output stream must be explicitly closed for the output to be - * sent, since the HttpResponseOutputStream needs to buffer the entire - * transmission to be able to fill in the content-length field of - * the HTTP header. Closing this socket will do this. - * - * The constructor blocks until the HTTP protocol header - * is received. This could be fixed, but I don't think it should be a - * problem because this object would not be created unless the - * HttpAwareServerSocket has detected the beginning of the header - * anyway, so the rest should be there. - * - * This socket can only be used to process one POST and reply to it. - * Another message would be received on a newly accepted socket anyway. - */ -public class HttpReceiveSocket extends WrappedSocket implements RMISocketInfo { - - /** true if the HTTP header has pushed through the output stream yet */ - private boolean headerSent = false; - - /** - * Layer on top of a pre-existing Socket object, and use specified - * input and output streams. - * @param socket the pre-existing socket to use - * @param in the InputStream to use for this socket (can be null) - * @param out the OutputStream to use for this socket (can be null) - */ - public HttpReceiveSocket(Socket socket, InputStream in, OutputStream out) - throws IOException - { - super(socket, in, out); - - this.in = new HttpInputStream(in != null ? in : - socket.getInputStream()); - this.out = (out != null ? out : - socket.getOutputStream()); - } - - /** - * Indicate that this socket is not reusable. - */ - public boolean isReusable() - { - return false; - } - - /** - * Get the address to which this socket is connected. "null" is always - * returned (to indicate an unknown address) because the originating - * host's IP address cannot be reliably determined: both because the - * request probably went through a proxy server, and because if it was - * delivered by a local forwarder (CGI script or servlet), we do NOT - * want it to appear as if the call is coming from the local host (in - * case the remote object makes access control decisions based on the - * "client host" of a remote call; see bugid 4399040). - */ - public InetAddress getInetAddress() { - return null; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - if (!headerSent) { // could this be done in constructor?? - DataOutputStream dos = new DataOutputStream(out); - dos.writeBytes("HTTP/1.0 200 OK\r\n"); - dos.flush(); - headerSent = true; - out = new HttpOutputStream(out); - } - return out; - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - getOutputStream().close(); // make sure response is sent - socket.close(); - } - - /** - * Return string representation of the socket. - */ - public String toString() - { - return "HttpReceive" + socket.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java deleted file mode 100644 index 0c6de28c266..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 1996, 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.transport.proxy; - -import java.io.*; - -/** - * The HttpSendInputStream class is used by the HttpSendSocket class as - * a layer on the top of the InputStream it returns so that it can be - * notified of attempts to read from it. This allows the HttpSendSocket - * to know when it should push across its output message. - */ -class HttpSendInputStream extends FilterInputStream { - - /** the HttpSendSocket object that is providing this stream */ - HttpSendSocket owner; - - /** - * Create new filter on a given input stream. - * @param in the InputStream to filter from - * @param owner the HttpSendSocket that is providing this stream - */ - public HttpSendInputStream(InputStream in, HttpSendSocket owner) - throws IOException - { - super(in); - - this.owner = owner; - } - - /** - * Mark this stream as inactive for its owner socket, so the next time - * a read is attempted, the owner will be notified and a new underlying - * input stream obtained. - */ - public void deactivate() - { - in = null; - } - - /** - * Read a byte of data from the stream. - */ - public int read() throws IOException - { - if (in == null) - in = owner.readNotify(); - return in.read(); - } - - /** - * Read into an array of bytes. - * @param b the buffer into which the data is to be read - * @param off the start offset of the data - * @param len the maximum number of bytes to read - */ - public int read(byte b[], int off, int len) throws IOException - { - if (len == 0) - return 0; - if (in == null) - in = owner.readNotify(); - return in.read(b, off, len); - } - - /** - * Skip bytes of input. - * @param n the number of bytes to be skipped - */ - public long skip(long n) throws IOException - { - if (n == 0) - return 0; - if (in == null) - in = owner.readNotify(); - return in.skip(n); - } - - /** - * Return the number of bytes that can be read without blocking. - */ - public int available() throws IOException - { - if (in == null) - in = owner.readNotify(); - return in.available(); - } - - /** - * Close the stream. - */ - public void close() throws IOException - { - owner.close(); - } - - /** - * Mark the current position in the stream. - * @param readlimit how many bytes can be read before mark becomes invalid - */ - public synchronized void mark(int readlimit) - { - if (in == null) { - try { - in = owner.readNotify(); - } - catch (IOException e) { - return; - } - } - in.mark(readlimit); - } - - /** - * Reposition the stream to the last marked position. - */ - public synchronized void reset() throws IOException - { - if (in == null) - in = owner.readNotify(); - in.reset(); - } - - /** - * Return true if this stream type supports mark/reset. - */ - public boolean markSupported() - { - if (in == null) { - try { - in = owner.readNotify(); - } - catch (IOException e) { - return false; - } - } - return in.markSupported(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java deleted file mode 100644 index bc83945534f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1996, 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.transport.proxy; - -import java.io.*; - -/** - * The HttpSendOutputStream class is used by the HttpSendSocket class as - * a layer on the top of the OutputStream it returns so that it can be - * notified of attempts to write to it. This allows the HttpSendSocket - * to know when it should construct a new message. - */ -class HttpSendOutputStream extends FilterOutputStream { - - /** the HttpSendSocket object that is providing this stream */ - HttpSendSocket owner; - - /** - * Create new filter on a given output stream. - * @param out the OutputStream to filter from - * @param owner the HttpSendSocket that is providing this stream - */ - public HttpSendOutputStream(OutputStream out, HttpSendSocket owner) - throws IOException - { - super(out); - - this.owner = owner; - } - - /** - * Mark this stream as inactive for its owner socket, so the next time - * a write is attempted, the owner will be notified and a new underlying - * output stream obtained. - */ - public void deactivate() - { - out = null; - } - - /** - * Write a byte of data to the stream. - */ - public void write(int b) throws IOException - { - if (out == null) - out = owner.writeNotify(); - out.write(b); - } - - /** - * Write a subarray of bytes. - * @param b the buffer from which the data is to be written - * @param off the start offset of the data - * @param len the number of bytes to be written - */ - public void write(byte b[], int off, int len) throws IOException - { - if (len == 0) - return; - if (out == null) - out = owner.writeNotify(); - out.write(b, off, len); - } - - /** - * Flush the stream. - */ - public void flush() throws IOException - { - if (out != null) - out.flush(); - } - - /** - * Close the stream. - */ - public void close() throws IOException - { - flush(); - owner.close(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java deleted file mode 100644 index a9932be35e1..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 1996, 2012, 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.transport.proxy; - -import java.io.*; -import java.net.*; -import java.security.PrivilegedAction; - -import sun.rmi.runtime.Log; - -/** - * The HttpSendSocket class extends the java.net.Socket class - * by enclosing the data output stream in, then extracting the input - * stream from, an HTTP protocol transmission. - * - * NOTES: - * - * Since the length of the output request must be known before the - * HTTP header can be completed, all of the output is buffered by - * an HttpOutputStream object until either an attempt is made to - * read from this socket, or the socket is explicitly closed. - * - * On the first read attempt to read from this socket, the buffered - * output is sent to the destination as the body of an HTTP POST - * request. All reads will then acquire data from the body of - * the response. A subsequent attempt to write to this socket will - * throw an IOException. - */ -class HttpSendSocket extends Socket implements RMISocketInfo { - - /** the host to connect to */ - protected String host; - - /** the port to connect to */ - protected int port; - - /** the URL to forward through */ - protected URL url; - - /** the object managing this connection through the URL */ - protected URLConnection conn = null; - - /** internal input stream for this socket */ - protected InputStream in = null; - - /** internal output stream for this socket */ - protected OutputStream out = null; - - /** the notifying input stream returned to users */ - protected HttpSendInputStream inNotifier; - - /** the notifying output stream returned to users */ - protected HttpSendOutputStream outNotifier; - - /** - * Line separator string. This is the value of the line.separator - * property at the moment that the socket was created. - */ - private String lineSeparator = - java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("line.separator")); - - /** - * Create a stream socket and connect it to the specified port on - * the specified host. - * @param host the host - * @param port the port - */ - public HttpSendSocket(String host, int port, URL url) throws IOException - { - super((SocketImpl)null); // no underlying SocketImpl for this object - - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "host = " + host + ", port = " + port + ", url = " + url); - } - - this.host = host; - this.port = port; - this.url = url; - - inNotifier = new HttpSendInputStream(null, this); - outNotifier = new HttpSendOutputStream(writeNotify(), this); - } - - /** - * Create a stream socket and connect it to the specified port on - * the specified host. - * @param host the host - * @param port the port - */ - public HttpSendSocket(String host, int port) throws IOException - { - this(host, port, new URL("http", host, port, "/")); - } - - /** - * Create a stream socket and connect it to the specified address on - * the specified port. - * @param address the address - * @param port the port - */ - public HttpSendSocket(InetAddress address, int port) throws IOException - { - this(address.getHostName(), port); - } - - /** - * Indicate that this socket is not reusable. - */ - public boolean isReusable() - { - return false; - } - - /** - * Create a new socket connection to host (or proxy), and prepare to - * send HTTP transmission. - */ - public synchronized OutputStream writeNotify() throws IOException - { - if (conn != null) { - throw new IOException("attempt to write on HttpSendSocket after " + - "request has been sent"); - } - - conn = url.openConnection(); - conn.setDoOutput(true); - conn.setUseCaches(false); - conn.setRequestProperty("Content-type", "application/octet-stream"); - - inNotifier.deactivate(); - in = null; - - return out = conn.getOutputStream(); - } - - /** - * Send HTTP output transmission and prepare to receive response. - */ - public synchronized InputStream readNotify() throws IOException - { - RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, - "sending request and activating input stream"); - - outNotifier.deactivate(); - out.close(); - out = null; - - try { - in = conn.getInputStream(); - } catch (IOException e) { - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, - "failed to get input stream, exception: ", e); - - throw new IOException("HTTP request failed"); - } - - /* - * If an HTTP error response is returned, sometimes an IOException - * is thrown, which is handled above, and other times it isn't, and - * the error response body will be available for reading. - * As a safety net to catch any such unexpected HTTP behavior, we - * verify that the content type of the response is what the - * HttpOutputStream generates: "application/octet-stream". - * (Servers' error responses will generally be "text/html".) - * Any error response body is printed to the log. - */ - String contentType = conn.getContentType(); - if (contentType == null || - !conn.getContentType().equals("application/octet-stream")) - { - if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { - String message; - if (contentType == null) { - message = "missing content type in response" + - lineSeparator; - } else { - message = "invalid content type in response: " + - contentType + lineSeparator; - } - - message += "HttpSendSocket.readNotify: response body: "; - try { - BufferedReader din = new BufferedReader(new InputStreamReader(in)); - String line; - while ((line = din.readLine()) != null) - message += line + lineSeparator; - } catch (IOException e) { - } - RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message); - } - - throw new IOException("HTTP request failed"); - } - - return in; - } - - /** - * Get the address to which the socket is connected. - */ - public InetAddress getInetAddress() - { - try { - return InetAddress.getByName(host); - } catch (UnknownHostException e) { - return null; // null if couldn't resolve destination host - } - } - - /** - * Get the local address to which the socket is bound. - */ - public InetAddress getLocalAddress() - { - try { - return InetAddress.getLocalHost(); - } catch (UnknownHostException e) { - return null; // null if couldn't determine local host - } - } - - /** - * Get the remote port to which the socket is connected. - */ - public int getPort() - { - return port; - } - - /** - * Get the local port to which the socket is connected. - */ - public int getLocalPort() - { - return -1; // request not applicable to this socket type - } - - /** - * Get an InputStream for this socket. - */ - public InputStream getInputStream() throws IOException - { - return inNotifier; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - return outNotifier; - } - - /** - * Enable/disable TCP_NODELAY. - * This operation has no effect for an HttpSendSocket. - */ - public void setTcpNoDelay(boolean on) throws SocketException - { - } - - /** - * Retrieve whether TCP_NODELAY is enabled. - */ - public boolean getTcpNoDelay() throws SocketException - { - return false; // imply option is disabled - } - - /** - * Enable/disable SO_LINGER with the specified linger time. - * This operation has no effect for an HttpSendSocket. - */ - public void setSoLinger(boolean on, int val) throws SocketException - { - } - - /** - * Retrive setting for SO_LINGER. - */ - public int getSoLinger() throws SocketException - { - return -1; // imply option is disabled - } - - /** - * Enable/disable SO_TIMEOUT with the specified timeout - * This operation has no effect for an HttpSendSocket. - */ - public synchronized void setSoTimeout(int timeout) throws SocketException - { - } - - /** - * Retrive setting for SO_TIMEOUT. - */ - public synchronized int getSoTimeout() throws SocketException - { - return 0; // imply option is disabled - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - if (out != null) // push out transmission if not done - out.close(); - } - - /** - * Return string representation of this pseudo-socket. - */ - public String toString() - { - return "HttpSendSocket[host=" + host + - ",port=" + port + - ",url=" + url + "]"; - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java deleted file mode 100644 index 548f584ae11..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1998, 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.transport.proxy; - -import java.io.IOException; -import java.net.Socket; -import java.net.ServerSocket; -import java.net.URL; -import java.rmi.server.RMISocketFactory; - -/** - * RMIHttpToCGISocketFactory creates a socket connection to the - * specified host that is comminicated within an HTTP request, - * forwarded through the default firewall proxy, to the target host's - * normal HTTP server, to a CGI program which forwards the request to - * the actual specified port on the socket. - */ -public class RMIHttpToCGISocketFactory extends RMISocketFactory { - - public Socket createSocket(String host, int port) - throws IOException - { - return new HttpSendSocket(host, port, - new URL("http", host, - "/cgi-bin/java-rmi.cgi" + - "?forward=" + port)); - } - - public ServerSocket createServerSocket(int port) throws IOException - { - return new HttpAwareServerSocket(port); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java deleted file mode 100644 index c23df420e44..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1998, 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.transport.proxy; - -import java.io.IOException; -import java.net.Socket; -import java.net.ServerSocket; -import java.net.URL; -import java.rmi.server.RMISocketFactory; - -/** - * RMIHttpToPortSocketFactory creates a socket connection to the - * specified host that is communicated within an HTTP request, - * forwarded through the default firewall proxy, directly to the - * specified port. - */ -public class RMIHttpToPortSocketFactory extends RMISocketFactory { - - public Socket createSocket(String host, int port) - throws IOException - { - return new HttpSendSocket(host, port, - new URL("http", host, port, "/")); - } - - public ServerSocket createServerSocket(int port) - throws IOException - { - return new HttpAwareServerSocket(port); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java deleted file mode 100644 index 8cb7cc4185f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (c) 1996, 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. 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.transport.proxy; - -import java.io.*; -import java.net.*; -import java.security.*; -import java.util.*; -import java.rmi.server.LogStream; -import java.rmi.server.RMISocketFactory; -import sun.rmi.runtime.Log; -import sun.rmi.runtime.NewThreadAction; - -/** - * RMIMasterSocketFactory attempts to create a socket connection to the - * specified host using successively less efficient mechanisms - * until one succeeds. If the host is successfully connected to, - * the factory for the successful mechanism is stored in an internal - * hash table keyed by the host name, so that future attempts to - * connect to the same host will automatically use the same - * mechanism. - */ -@SuppressWarnings("deprecation") -public class RMIMasterSocketFactory extends RMISocketFactory { - - /** "proxy" package log level */ - static int logLevel = LogStream.parseLevel(getLogLevel()); - - private static String getLogLevel() { - return java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.proxy.logLevel")); - } - - /* proxy package log */ - static final Log proxyLog = - Log.getLog("sun.rmi.transport.tcp.proxy", - "transport", RMIMasterSocketFactory.logLevel); - - /** timeout for attemping direct socket connections */ - private static long connectTimeout = getConnectTimeout(); - - private static long getConnectTimeout() { - return java.security.AccessController.doPrivileged((PrivilegedAction) () -> - Long.getLong("sun.rmi.transport.proxy.connectTimeout", 15000)); // default: 15 seconds - } - - /** whether to fallback to HTTP on general connect failures */ - private static final boolean eagerHttpFallback = - java.security.AccessController.doPrivileged((PrivilegedAction) () -> - Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback")); - - /** table of hosts successfully connected to and the factory used */ - private Hashtable successTable = - new Hashtable<>(); - - /** maximum number of hosts to remember successful connection to */ - private static final int MaxRememberedHosts = 64; - - /** list of the hosts in successTable in initial connection order */ - private Vector hostList = new Vector<>(MaxRememberedHosts); - - /** default factory for initial use for direct socket connection */ - protected RMISocketFactory initialFactory = new RMIDirectSocketFactory(); - - /** ordered list of factories to try as alternate connection - * mechanisms if a direct socket connections fails */ - protected Vector altFactoryList; - - /** - * Create a RMIMasterSocketFactory object. Establish order of - * connection mechanisms to attempt on createSocket, if a direct - * socket connection fails. - */ - public RMIMasterSocketFactory() { - altFactoryList = new Vector<>(2); - boolean setFactories = false; - - try { - String proxyHost; - proxyHost = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("http.proxyHost")); - - if (proxyHost == null) - proxyHost = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("proxyHost")); - - boolean disable = java.security.AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("java.rmi.server.disableHttp", "true")) - .equalsIgnoreCase("true"); - - if (!disable && proxyHost != null && proxyHost.length() > 0) { - setFactories = true; - } - } catch (Exception e) { - // unable to obtain the properties, so use the default behavior. - } - - if (setFactories) { - altFactoryList.addElement(new RMIHttpToPortSocketFactory()); - altFactoryList.addElement(new RMIHttpToCGISocketFactory()); - } - } - - /** - * Create a new client socket. If we remember connecting to this host - * successfully before, then use the same factory again. Otherwise, - * try using a direct socket connection and then the alternate factories - * in the order specified in altFactoryList. - */ - public Socket createSocket(String host, int port) - throws IOException - { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port); - } - - /* - * If we don't have any alternate factories to consult, short circuit - * the fallback procedure and delegate to the initial factory. - */ - if (altFactoryList.size() == 0) { - return initialFactory.createSocket(host, port); - } - - RMISocketFactory factory; - - /* - * If we remember successfully connecting to this host before, - * use the same factory. - */ - factory = successTable.get(host); - if (factory != null) { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "previously successful factory found: " + factory); - } - return factory.createSocket(host, port); - } - - /* - * Next, try a direct socket connection. Open socket in another - * thread and only wait for specified timeout, in case the socket - * would otherwise spend minutes trying an unreachable host. - */ - Socket initialSocket = null; - Socket fallbackSocket = null; - final AsyncConnector connector = - new AsyncConnector(initialFactory, host, port, - AccessController.getContext()); - // connection must be attempted with - // this thread's access control context - IOException initialFailure = null; - - try { - synchronized (connector) { - - Thread t = java.security.AccessController.doPrivileged( - new NewThreadAction(connector, "AsyncConnector", true)); - t.start(); - - try { - long now = System.currentTimeMillis(); - long deadline = now + connectTimeout; - do { - connector.wait(deadline - now); - initialSocket = checkConnector(connector); - if (initialSocket != null) - break; - now = System.currentTimeMillis(); - } while (now < deadline); - } catch (InterruptedException e) { - throw new InterruptedIOException( - "interrupted while waiting for connector"); - } - } - - // assume no route to host (for now) if no connection yet - if (initialSocket == null) - throw new NoRouteToHostException( - "connect timed out: " + host); - - proxyLog.log(Log.BRIEF, "direct socket connection successful"); - - return initialSocket; - - } catch (UnknownHostException | NoRouteToHostException e) { - initialFailure = e; - } catch (SocketException e) { - if (eagerHttpFallback) { - initialFailure = e; - } else { - throw e; - } - } finally { - if (initialFailure != null) { - - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "direct socket connection failed: ", initialFailure); - } - - // Finally, try any alternate connection mechanisms. - for (int i = 0; i < altFactoryList.size(); ++ i) { - factory = altFactoryList.elementAt(i); - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, - "trying with factory: " + factory); - } - try (Socket testSocket = - factory.createSocket(host, port)) { - // For HTTP connections, the output (POST request) must - // be sent before we verify a successful connection. - // So, sacrifice a socket for the sake of testing... - // The following sequence should verify a successful - // HTTP connection if no IOException is thrown. - InputStream in = testSocket.getInputStream(); - int b = in.read(); // probably -1 for EOF... - } catch (IOException ex) { - if (proxyLog.isLoggable(Log.BRIEF)) { - proxyLog.log(Log.BRIEF, "factory failed: ", ex); - } - - continue; - } - proxyLog.log(Log.BRIEF, "factory succeeded"); - - // factory succeeded, open new socket for caller's use - try { - fallbackSocket = factory.createSocket(host, port); - } catch (IOException ex) { // if it fails 2nd time, - } // just give up - break; - } - } - } - - synchronized (successTable) { - try { - // check once again to see if direct connection succeeded - synchronized (connector) { - initialSocket = checkConnector(connector); - } - if (initialSocket != null) { - // if we had made another one as well, clean it up... - if (fallbackSocket != null) - fallbackSocket.close(); - return initialSocket; - } - // if connector ever does get socket, it won't be used - connector.notUsed(); - } catch (UnknownHostException | NoRouteToHostException e) { - initialFailure = e; - } catch (SocketException e) { - if (eagerHttpFallback) { - initialFailure = e; - } else { - throw e; - } - } - // if we had found an alternate mechanism, go and use it - if (fallbackSocket != null) { - // remember this successful host/factory pair - rememberFactory(host, factory); - return fallbackSocket; - } - throw initialFailure; - } - } - - /** - * Remember a successful factory for connecting to host. - * Currently, excess hosts are removed from the remembered list - * using a Least Recently Created strategy. - */ - void rememberFactory(String host, RMISocketFactory factory) { - synchronized (successTable) { - while (hostList.size() >= MaxRememberedHosts) { - successTable.remove(hostList.elementAt(0)); - hostList.removeElementAt(0); - } - hostList.addElement(host); - successTable.put(host, factory); - } - } - - /** - * Check if an AsyncConnector succeeded. If not, return socket - * given to fall back to. - */ - Socket checkConnector(AsyncConnector connector) - throws IOException - { - Exception e = connector.getException(); - if (e != null) { - e.fillInStackTrace(); - /* - * The AsyncConnector implementation guaranteed that the exception - * will be either an IOException or a RuntimeException, and we can - * only throw one of those, so convince that compiler that it must - * be one of those. - */ - if (e instanceof IOException) { - throw (IOException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new Error("internal error: " + - "unexpected checked exception: " + e.toString()); - } - } - return connector.getSocket(); - } - - /** - * Create a new server socket. - */ - public ServerSocket createServerSocket(int port) throws IOException { - //return new HttpAwareServerSocket(port); - return initialFactory.createServerSocket(port); - } - - - /** - * AsyncConnector is used by RMIMasterSocketFactory to attempt socket - * connections on a separate thread. This allows RMIMasterSocketFactory - * to control how long it will wait for the connection to succeed. - */ - private class AsyncConnector implements Runnable { - - /** what factory to use to attempt connection */ - private RMISocketFactory factory; - - /** the host to connect to */ - private String host; - - /** the port to connect to */ - private int port; - - /** access control context to attempt connection within */ - private AccessControlContext acc; - - /** exception that occurred during connection, if any */ - private Exception exception = null; - - /** the connected socket, if successful */ - private Socket socket = null; - - /** socket should be closed after created, if ever */ - private boolean cleanUp = false; - - /** - * Create a new asynchronous connector object. - */ - AsyncConnector(RMISocketFactory factory, String host, int port, - AccessControlContext acc) - { - this.factory = factory; - this.host = host; - this.port = port; - this.acc = acc; - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkConnect(host, port); - } - } - - /** - * Attempt socket connection in separate thread. If successful, - * notify master waiting, - */ - public void run() { - try { - /* - * Using the privileges of the thread that wants to make the - * connection is tempting, but it will fail with applets with - * the current applet security manager because the applet - * network connection policy is not captured in the permission - * framework of the access control context we have. - * - * java.security.AccessController.beginPrivileged(acc); - */ - try { - Socket temp = factory.createSocket(host, port); - synchronized (this) { - socket = temp; - notify(); - } - rememberFactory(host, factory); - synchronized (this) { - if (cleanUp) - try { - socket.close(); - } catch (IOException e) { - } - } - } catch (Exception e) { - /* - * Note that the only exceptions which could actually have - * occurred here are IOException or RuntimeException. - */ - synchronized (this) { - exception = e; - notify(); - } - } - } finally { - /* - * See above comments for matching beginPrivileged() call that - * is also commented out. - * - * java.security.AccessController.endPrivileged(); - */ - } - } - - /** - * Get exception that occurred during connection attempt, if any. - * In the current implementation, this is guaranteed to be either - * an IOException or a RuntimeException. - */ - private synchronized Exception getException() { - return exception; - } - - /** - * Get successful socket, if any. - */ - private synchronized Socket getSocket() { - return socket; - } - - /** - * Note that this connector's socket, if ever successfully created, - * will not be used, so it should be cleaned up quickly - */ - synchronized void notUsed() { - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - } - } - cleanUp = true; - } - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java deleted file mode 100644 index 85008fb231e..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1996, 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.transport.proxy; - -/** - * RMISocketInfo is an interface that extensions of the java.net.Socket - * class may use to provide more information on its capabilities. - */ -public interface RMISocketInfo { - - /** - * Return true if this socket can be used for more than one - * RMI call. If a socket does not implement this interface, then - * it is assumed to be reusable. - */ - public boolean isReusable(); -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java deleted file mode 100644 index 7bc8503f60f..00000000000 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 1996, 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. 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.transport.proxy; - -import java.io.*; -import java.net.InetAddress; -import java.net.Socket; -import java.net.SocketException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * The WrappedSocket class provides a general wrapper for providing an - * extended implementation of java.net.Socket that can be attached to - * a pre-existing Socket object. WrappedSocket itself provides a - * constructor for specifying alternate input or output streams to be - * returned than those of the underlying Socket. - */ -class WrappedSocket extends Socket { - - /** the underlying concrete socket */ - protected Socket socket; - - /** the input stream to return for socket */ - protected InputStream in = null; - - /** the output stream to return for socket */ - protected OutputStream out = null; - - /** - * Layer on top of a pre-existing Socket object, and use specified - * input and output streams. This allows the creator of the - * underlying socket to peek at the beginning of the input with a - * BufferedInputStream and determine which kind of socket - * to create, without consuming the input. - * @param socket the pre-existing socket to use - * @param in the InputStream to return to users (can be null) - * @param out the OutputStream to return to users (can be null) - */ - public WrappedSocket(Socket socket, InputStream in, OutputStream out) - throws IOException - { - super((java.net.SocketImpl)null); // no underlying SocketImpl for this object - this.socket = socket; - this.in = in; - this.out = out; - } - - /** - * Get the address to which the socket is connected. - */ - public InetAddress getInetAddress() - { - return socket.getInetAddress(); - } - - /** - * Get the local address to which the socket is bound. - */ - public InetAddress getLocalAddress() { - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public InetAddress run() { - return socket.getLocalAddress(); - - } - }); - } - - /** - * Get the remote port to which the socket is connected. - */ - public int getPort() - { - return socket.getPort(); - } - - /** - * Get the local port to which the socket is connected. - */ - public int getLocalPort() - { - return socket.getLocalPort(); - } - - /** - * Get an InputStream for this socket. - */ - public InputStream getInputStream() throws IOException - { - if (in == null) - in = socket.getInputStream(); - return in; - } - - /** - * Get an OutputStream for this socket. - */ - public OutputStream getOutputStream() throws IOException - { - if (out == null) - out = socket.getOutputStream(); - return out; - } - - /** - * Enable/disable TCP_NODELAY. - */ - public void setTcpNoDelay(boolean on) throws SocketException - { - socket.setTcpNoDelay(on); - } - - /** - * Retrieve whether TCP_NODELAY is enabled. - */ - public boolean getTcpNoDelay() throws SocketException - { - return socket.getTcpNoDelay(); - } - - /** - * Enable/disable SO_LINGER with the specified linger time. - */ - public void setSoLinger(boolean on, int val) throws SocketException - { - socket.setSoLinger(on, val); - } - - /** - * Retrive setting for SO_LINGER. - */ - public int getSoLinger() throws SocketException - { - return socket.getSoLinger(); - } - - /** - * Enable/disable SO_TIMEOUT with the specified timeout - */ - public synchronized void setSoTimeout(int timeout) throws SocketException - { - socket.setSoTimeout(timeout); - } - - /** - * Retrive setting for SO_TIMEOUT. - */ - public synchronized int getSoTimeout() throws SocketException - { - return socket.getSoTimeout(); - } - - /** - * Close the socket. - */ - public synchronized void close() throws IOException - { - socket.close(); - } - - /** - * Return string representation of the socket. - */ - public String toString() - { - return "Wrapped" + socket.toString(); - } -} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java index 08eb50b29a7..8b5a610005b 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2001, 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 @@ -26,14 +26,10 @@ package sun.rmi.transport.tcp; import java.io.*; -import java.net.InetAddress; import java.net.Socket; -import java.net.SocketException; import java.rmi.*; -import java.rmi.server.RMISocketFactory; import sun.rmi.runtime.Log; import sun.rmi.transport.*; -import sun.rmi.transport.proxy.*; public class TCPConnection implements Connection { @@ -120,10 +116,7 @@ public class TCPConnection implements Connection { */ public boolean isReusable() { - if ((socket != null) && (socket instanceof RMISocketInfo)) - return ((RMISocketInfo) socket).isReusable(); - else - return true; + return true; } /** diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java similarity index 94% rename from jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java rename to jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java index 953d47ca400..8274742ec1b 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package sun.rmi.transport.proxy; +package sun.rmi.transport.tcp; import java.io.IOException; import java.net.Socket; @@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory; * RMIDirectSocketFactory creates a direct socket connection to the * specified port on the specified host. */ -public class RMIDirectSocketFactory extends RMISocketFactory { +public class TCPDirectSocketFactory extends RMISocketFactory { public Socket createSocket(String host, int port) throws IOException { diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index 1caa362803a..764abefb551 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, 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 @@ -75,7 +75,6 @@ import sun.rmi.transport.StreamRemoteCall; import sun.rmi.transport.Target; import sun.rmi.transport.Transport; import sun.rmi.transport.TransportConstants; -import sun.rmi.transport.proxy.HttpReceiveSocket; /** * TCPTransport is the socket-based implementation of the RMI Transport @@ -711,35 +710,10 @@ public class TCPTransport extends Transport { ? sockIn : new BufferedInputStream(sockIn); - // Read magic (or HTTP wrapper) - bufIn.mark(4); + // Read magic DataInputStream in = new DataInputStream(bufIn); int magic = in.readInt(); - if (magic == POST) { - tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call"); - - // It's really a HTTP-wrapped request. Repackage - // the socket in a HttpReceiveSocket, reinitialize - // sockIn and in, and reread magic. - bufIn.reset(); // unread "POST" - - try { - socket = new HttpReceiveSocket(socket, bufIn, null); - remoteHost = "0.0.0.0"; - sockIn = socket.getInputStream(); - bufIn = new BufferedInputStream(sockIn); - in = new DataInputStream(bufIn); - magic = in.readInt(); - - } catch (IOException e) { - throw new RemoteException("Error HTTP-unwrapping call", - e); - } - } - // bufIn's mark will invalidate itself when it overflows - // so it doesn't have to be turned off - // read and verify transport header short version = in.readShort(); if (magic != TransportConstants.Magic || diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 696c9cd270f..684b0cab3ab 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -191,8 +191,6 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all -sun/rmi/transport/proxy/EagerHttpFallback.java 7195095 generic-all - java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java deleted file mode 100644 index 8999c3d7310..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * - * @summary HttpSocket functionality test - * @author Dana Burns - * - * @library ../../testlibrary - * @modules java.rmi/sun.rmi.registry - * java.rmi/sun.rmi.server - * java.rmi/sun.rmi.transport - * java.rmi/sun.rmi.transport.proxy - * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary HttpSocketTest HttpSocketTest_Stub - * @run main/othervm/policy=security.policy HttpSocketTest - */ - -/* - * This test assures remote methods can be carried out over RMI. - * After setting the RMI runtime socket factory to the http proxy version, - * a registry is created, a remote object (an instance of this class) is - * registered with it, and then it is exercised. - */ - -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.Naming; -import java.rmi.RMISecurityManager; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMISocketFactory; -import java.rmi.server.UnicastRemoteObject; -import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; - -interface MyRemoteInterface extends Remote { - void setRemoteObject( Remote r ) throws RemoteException; - Remote getRemoteObject() throws RemoteException; -} - -public class HttpSocketTest extends UnicastRemoteObject - implements MyRemoteInterface -{ - private static final String NAME = "HttpSocketTest"; - - public HttpSocketTest() throws RemoteException{} - - private Remote ro; - - public static void main(String[] args) - throws Exception - { - - Registry registry = null; - - TestLibrary.suggestSecurityManager(null); - - // Set the socket factory. - System.err.println("installing socket factory"); - RMISocketFactory.setSocketFactory(new RMIHttpToPortSocketFactory()); - int registryPort = -1; - - try { - System.err.println("Starting registry"); - registry = TestLibrary.createRegistryOnUnusedPort(); - registryPort = TestLibrary.getRegistryPort(registry); - } catch (Exception e) { - TestLibrary.bomb(e); - } - - try { - registry.rebind( NAME, new HttpSocketTest() ); - MyRemoteInterface httpTest = - (MyRemoteInterface)Naming.lookup("//:" + registryPort + "/" + NAME); - httpTest.setRemoteObject( new HttpSocketTest() ); - Remote r = httpTest.getRemoteObject(); - - } catch (Exception e) { - TestLibrary.bomb(e); - } - - - } - - public void setRemoteObject( Remote ro ) throws RemoteException { - this.ro = ro; - } - - public Remote getRemoteObject() throws RemoteException { - return( this.ro ); - } - -} diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java deleted file mode 100644 index 03757a3df20..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 1999, 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. - */ - -// Stub class generated by rmic, do not edit. -// Contents subject to change without notice. - -public final class HttpSocketTest_Stub - extends java.rmi.server.RemoteStub - implements MyRemoteInterface, java.rmi.Remote -{ - private static final java.rmi.server.Operation[] operations = { - new java.rmi.server.Operation("java.rmi.Remote getRemoteObject()"), - new java.rmi.server.Operation("void setRemoteObject(java.rmi.Remote)") - }; - - private static final long interfaceHash = 3775375480010579665L; - - private static final long serialVersionUID = 2; - - private static boolean useNewInvoke; - private static java.lang.reflect.Method $method_getRemoteObject_0; - private static java.lang.reflect.Method $method_setRemoteObject_1; - - static { - try { - java.rmi.server.RemoteRef.class.getMethod("invoke", - new java.lang.Class[] { - java.rmi.Remote.class, - java.lang.reflect.Method.class, - java.lang.Object[].class, - long.class - }); - useNewInvoke = true; - $method_getRemoteObject_0 = MyRemoteInterface.class.getMethod("getRemoteObject", new java.lang.Class[] {}); - $method_setRemoteObject_1 = MyRemoteInterface.class.getMethod("setRemoteObject", new java.lang.Class[] {java.rmi.Remote.class}); - } catch (java.lang.NoSuchMethodException e) { - useNewInvoke = false; - } - } - - // constructors - public HttpSocketTest_Stub() { - super(); - } - public HttpSocketTest_Stub(java.rmi.server.RemoteRef ref) { - super(ref); - } - - // methods from remote interfaces - - // implementation of getRemoteObject() - public java.rmi.Remote getRemoteObject() - throws java.rmi.RemoteException - { - try { - if (useNewInvoke) { - Object $result = ref.invoke(this, $method_getRemoteObject_0, null, -2578437860804964265L); - return ((java.rmi.Remote) $result); - } else { - java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); - ref.invoke(call); - java.rmi.Remote $result; - try { - java.io.ObjectInput in = call.getInputStream(); - $result = (java.rmi.Remote) in.readObject(); - } catch (java.io.IOException e) { - throw new java.rmi.UnmarshalException("error unmarshalling return", e); - } catch (java.lang.ClassNotFoundException e) { - throw new java.rmi.UnmarshalException("error unmarshalling return", e); - } finally { - ref.done(call); - } - return $result; - } - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } - - // implementation of setRemoteObject(Remote) - public void setRemoteObject(java.rmi.Remote $param_Remote_1) - throws java.rmi.RemoteException - { - try { - if (useNewInvoke) { - ref.invoke(this, $method_setRemoteObject_1, new java.lang.Object[] {$param_Remote_1}, -7518632118115022871L); - } else { - java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); - try { - java.io.ObjectOutput out = call.getOutputStream(); - out.writeObject($param_Remote_1); - } catch (java.io.IOException e) { - throw new java.rmi.MarshalException("error marshalling arguments", e); - } - ref.invoke(call); - ref.done(call); - } - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } -} diff --git a/jdk/test/java/rmi/transport/httpSocket/security.policy b/jdk/test/java/rmi/transport/httpSocket/security.policy deleted file mode 100644 index f1960c9772d..00000000000 --- a/jdk/test/java/rmi/transport/httpSocket/security.policy +++ /dev/null @@ -1,10 +0,0 @@ - -grant { - permission java.net.SocketPermission "*:1024-", "accept,connect,listen"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.proxy"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp"; - permission java.lang.RuntimePermission "setFactory"; -}; diff --git a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java deleted file mode 100644 index 5449c3b8759..00000000000 --- a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -/* @test - * @bug 8023862 - * @summary Verify that the default value of the java.rmi.server.disableHttp - * has been changed from false to true. - * @modules java.rmi/sun.rmi.transport.proxy - * @compile -XDignore.symbol.file DisableHttpDefaultValue.java - * - * @run main/othervm DisableHttpDefaultValue true - * @run main/othervm -Djava.rmi.server.disableHttp DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false - * @run main/othervm -Djava.rmi.server.disableHttp=true DisableHttpDefaultValue true - */ - -import sun.rmi.transport.proxy.RMIMasterSocketFactory; - -public class DisableHttpDefaultValue { - /** - * Subclass RMIMasterSocketFactory to get access to - * protected field altFactoryList. This list has a - * zero size if proxying is disabled. - */ - static class SocketFactory extends RMIMasterSocketFactory { - boolean proxyDisabled() { - return altFactoryList.size() == 0; - } - } - - /** - * Takes a single arg, which is the expected boolean value of - * java.rmi.server.disableHttp. - */ - public static void main(String[] args) throws Exception { - // Force there to be a proxy host, so that we are able to - // tell whether proxying is enabled or disabled. - System.setProperty("http.proxyHost", "proxy.example.com"); - - String propval = System.getProperty("java.rmi.server.disableHttp"); - String propdisp = (propval == null) ? "null" : ("\"" + propval + "\""); - boolean expected = Boolean.parseBoolean(args[0]); - boolean actual = new SocketFactory().proxyDisabled(); - System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual); - if (expected != actual) - throw new AssertionError(); - } -} diff --git a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java deleted file mode 100644 index 5b5691701c7..00000000000 --- a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2002, 2012, 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 4290727 - * @summary Verify that ConnectException will trigger HTTP fallback if - * sun.rmi.transport.proxy.eagerHttpFallback system property is set. - * - * @library ../../../../java/rmi/testlibrary - * @modules java.rmi/sun.rmi.registry - * java.rmi/sun.rmi.server - * java.rmi/sun.rmi.transport - * java.rmi/sun.rmi.transport.tcp - * @build TestLibrary - * @run main/othervm EagerHttpFallback - */ - -import java.rmi.*; -import java.rmi.registry.*; - -public class EagerHttpFallback { - - static final int INITIAL_PORT = TestLibrary.getUnusedRandomPort(); - static final int FALLBACK_PORT = TestLibrary.getUnusedRandomPort(); - - public static void main(String[] args) throws Exception { - System.setProperty("http.proxyHost", "127.0.0.1"); - System.setProperty("http.proxyPort", Integer.toString(FALLBACK_PORT)); - System.setProperty("sun.rmi.transport.proxy.eagerHttpFallback", - "true"); - LocateRegistry.createRegistry(FALLBACK_PORT); - - /* - * The call below should trigger a ConnectException in the - * RMIMasterSocketFactory when it attempts a direct connection to - * INITIAL_PORT, which no one is listening on. Since - * eagerHttpFallback is set, this ConnectException should trigger HTTP - * fallback, which will send a call through the HTTP proxy, which is - * configured to be localhost with a port behind which a registry is - * listening--so if fallback works properly, the list() call should - * succeed. - */ - try { - LocateRegistry.getRegistry(INITIAL_PORT).list(); - } catch (Exception e) { - System.err.println( - "call on registry stub with port " + INITIAL_PORT + - "did not successfully perform HTTP fallback to " + - FALLBACK_PORT); - throw e; - } - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java deleted file mode 100644 index 7de92ee2c47..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 1999, 2012, 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 4203167 - * - * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it - * @author Adrian Colley - * - * @library ../../../../../java/rmi/testlibrary - * @modules java.rmi/sun.rmi.transport.proxy - * @build TestIface TestImpl TestImpl_Stub - * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest - */ - -/* This test attempts to stymie the RMI accept loop. The accept loop in - * RMI endlessly accepts a connection, spawns a thread for it, and repeats. - * The accept() call can be replaced by a user-supplied library which - * might foolishly block indefinitely in its accept() method, which would - * prevent RMI from accepting other connections on that socket. - * - * Unfortunately, HttpAwareServerSocket (default server socket) is/was such - * a foolish thing. It reads 4 bytes to see if they're "POST" before - * returning. The bug fix is to move the HTTP stuff into the mainloop, - * which has the side effect of enabling it for non-default socketfactories. - * - * This test: - * 1. Creates an object and exports it. - * 2. Connects to the listening RMI port and sends nothing, to hold it up. - * 3. Makes a regular call, using HTTP tunnelling. - * 4. Fails to deadlock, thereby passing the test. - * - * Some runtime dependencies I'm trying to eliminate: - * 1. We don't know the port number until after exporting the object, but - * have to set it in http.proxyPort somehow. Hopefully http.proxyPort - * isn't read too soon or this test will fail with a ConnectException. - */ - -import java.rmi.*; -import java.rmi.server.RMISocketFactory; -import java.io.*; -import java.net.*; - -import sun.rmi.transport.proxy.RMIMasterSocketFactory; -import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; - -public class BlockAcceptTest -{ - public static void main(String[] args) - throws Exception - { - // Make trouble for ourselves - if (System.getSecurityManager() == null) - System.setSecurityManager(new RMISecurityManager()); - - // HTTP direct to the server port - System.setProperty("http.proxyHost", "127.0.0.1"); - - // Set the socket factory. - System.err.println("(installing HTTP-out socket factory)"); - HttpOutFactory fac = new HttpOutFactory(); - RMISocketFactory.setSocketFactory(fac); - - // Create remote object - TestImpl impl = new TestImpl(); - - // Export and get which port. - System.err.println("(exporting remote object)"); - TestIface stub = impl.export(); - try { - int port = fac.whichPort(); - - // Sanity - if (port == 0) - throw new Error("TEST FAILED: export didn't reserve a port(?)"); - - // Set the HTTP port, at last. - System.setProperty("http.proxyPort", port+""); - - // Now, connect to that port - //Thread.sleep(2000); - System.err.println("(connecting to listening port on 127.0.0.1:" + - port + ")"); - Socket DoS = new Socket("127.0.0.1", port); - // we hold the connection open until done with the test. - - // The test itself: make a remote call and see if it's blocked or - // if it works - //Thread.sleep(2000); - System.err.println("(making RMI-through-HTTP call)"); - System.err.println("(typical test failure deadlocks here)"); - String result = stub.testCall("dummy load"); - - System.err.println(" => " + result); - if (!("OK".equals(result))) - throw new Error("TEST FAILED: result not OK"); - System.err.println("Test passed."); - - // Clean up, including writing a byte to that connection just in - // case an optimizer thought of optimizing it out of existence - try { - DoS.getOutputStream().write(0); - DoS.getOutputStream().close(); - } catch (Throwable apathy) { - } - - } finally { - try { - impl.unexport(); - } catch (Throwable unmatter) { - } - } - - // Should exit here - } - - private static class HttpOutFactory - extends RMISocketFactory - { - private int servport = 0; - - public Socket createSocket(String h, int p) - throws IOException - { - return ((new RMIHttpToPortSocketFactory()).createSocket(h, p)); - } - - /** Create a server socket and remember which port it's on. - * Aborts if createServerSocket(0) is called twice, because then - * it doesn't know whether to remember the first or second port. - */ - public ServerSocket createServerSocket(int p) - throws IOException - { - ServerSocket ss; - ss = (new RMIMasterSocketFactory()).createServerSocket(p); - if (p == 0) { - if (servport != 0) { - System.err.println("TEST FAILED: " + - "Duplicate createServerSocket(0)"); - throw new Error("Test aborted (createServerSocket)"); - } - servport = ss.getLocalPort(); - } - return (ss); - } - - /** Return which port was reserved by createServerSocket(0). - * If the return value was 0, createServerSocket(0) wasn't called. - */ - public int whichPort() { - return (servport); - } - } // end class HttpOutFactory -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java deleted file mode 100644 index 85bab51483d..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 1999, 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.rmi.*; - -public interface TestIface - extends Remote -{ - public String testCall(String ign) - throws RemoteException; -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java deleted file mode 100644 index 73601a9e3b6..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1999, 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.rmi.*; -import java.rmi.server.*; - -public class TestImpl - extends Object - implements TestIface -{ - public TestImpl() { - } - - public TestIface export() - throws RemoteException - { - return (TestIface)UnicastRemoteObject.exportObject(this); - } - - public void unexport() - throws NoSuchObjectException - { - UnicastRemoteObject.unexportObject(this, true); - } - - public String testCall(String ign) { - return ("OK"); - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java deleted file mode 100644 index 2de40012e16..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 1999, 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. - */ - -// Stub class generated by rmic, do not edit. -// Contents subject to change without notice. - -public final class TestImpl_Stub - extends java.rmi.server.RemoteStub - implements TestIface -{ - private static final long serialVersionUID = 2; - - private static java.lang.reflect.Method $method_testCall_0; - - static { - try { - $method_testCall_0 = TestIface.class.getMethod("testCall", new java.lang.Class[] {java.lang.String.class}); - } catch (java.lang.NoSuchMethodException e) { - throw new java.lang.NoSuchMethodError( - "stub class initialization failed"); - } - } - - // constructors - public TestImpl_Stub(java.rmi.server.RemoteRef ref) { - super(ref); - } - - // methods from remote interfaces - - // implementation of testCall(String) - public java.lang.String testCall(java.lang.String $param_String_1) - throws java.rmi.RemoteException - { - try { - Object $result = ref.invoke(this, $method_testCall_0, new java.lang.Object[] {$param_String_1}, -4495720265115653109L); - return ((java.lang.String) $result); - } catch (java.lang.RuntimeException e) { - throw e; - } catch (java.rmi.RemoteException e) { - throw e; - } catch (java.lang.Exception e) { - throw new java.rmi.UnexpectedException("undeclared checked exception", e); - } - } -} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy deleted file mode 100644 index a8c8d0a64d8..00000000000 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy +++ /dev/null @@ -1,10 +0,0 @@ -grant { - // Take this out once we can specify -Djava.security.debug on - // the run line and figure out what else is needed - permission java.security.AllPermission; - - permission java.net.SocketPermission "*:1024-65535", "connect,listen"; - permission java.util.PropertyPermission "http.proxyHost", "write"; - permission java.util.PropertyPermission "http.proxyPort", "write"; - permission java.lang.RuntimePermission "setFactory"; -}; From 727e63cad7366b75ebe71c7269f0c3515d066a9b Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 26 Apr 2016 21:25:18 -0400 Subject: [PATCH 142/225] 8155182: fix to JDK-8066750 broke jdk9 builds Restore RMI Http Proxy support for now Reviewed-by: darcy, lancea, smarks --- .../java/rmi/server/RMISocketFactory.java | 21 +- .../sun/rmi/transport/proxy/CGIHandler.java | 423 ++++++++++++++++ .../proxy/HttpAwareServerSocket.java | 114 +++++ .../rmi/transport/proxy/HttpInputStream.java | 205 ++++++++ .../rmi/transport/proxy/HttpOutputStream.java | 80 +++ .../transport/proxy/HttpReceiveSocket.java | 128 +++++ .../transport/proxy/HttpSendInputStream.java | 161 ++++++ .../transport/proxy/HttpSendOutputStream.java | 105 ++++ .../rmi/transport/proxy/HttpSendSocket.java | 344 +++++++++++++ .../RMIDirectSocketFactory.java} | 4 +- .../proxy/RMIHttpToCGISocketFactory.java | 55 ++ .../proxy/RMIHttpToPortSocketFactory.java | 53 ++ .../proxy/RMIMasterSocketFactory.java | 468 ++++++++++++++++++ .../rmi/transport/proxy/RMISocketInfo.java | 39 ++ .../rmi/transport/proxy/WrappedSocket.java | 192 +++++++ .../sun/rmi/transport/tcp/TCPConnection.java | 11 +- .../sun/rmi/transport/tcp/TCPTransport.java | 30 +- jdk/test/ProblemList.txt | 2 + .../transport/httpSocket/HttpSocketTest.java | 113 +++++ .../httpSocket/HttpSocketTest_Stub.java | 130 +++++ .../rmi/transport/httpSocket/security.policy | 10 + .../proxy/DisableHttpDefaultValue.java | 69 +++ .../transport/proxy/EagerHttpFallback.java | 73 +++ .../tcp/blockAccept/BlockAcceptTest.java | 175 +++++++ .../transport/tcp/blockAccept/TestIface.java | 31 ++ .../transport/tcp/blockAccept/TestImpl.java | 49 ++ .../tcp/blockAccept/TestImpl_Stub.java | 66 +++ .../transport/tcp/blockAccept/security.policy | 10 + 28 files changed, 3151 insertions(+), 10 deletions(-) create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java rename jdk/src/java.rmi/share/classes/sun/rmi/transport/{tcp/TCPDirectSocketFactory.java => proxy/RMIDirectSocketFactory.java} (94%) create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java create mode 100644 jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java create mode 100644 jdk/test/java/rmi/transport/httpSocket/security.policy create mode 100644 jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java create mode 100644 jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java create mode 100644 jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java index df3bc9fd24a..e69c269f81a 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMISocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -35,8 +35,21 @@ import java.net.*; * request that the RMI runtime use its socket factory instance * instead of the default implementation. * - *

    The default socket factory implementation creates a direct - * socket connection to the remote host. + *

    The default socket factory implementation performs a + * three-tiered approach to creating client sockets. First, a direct + * socket connection to the remote VM is attempted. If that fails + * (due to a firewall), the runtime uses HTTP with the explicit port + * number of the server. If the firewall does not allow this type of + * communication, then HTTP to a cgi-bin script on the server is used + * to POST the RMI call. The HTTP tunneling mechanisms are disabled by + * default. This behavior is controlled by the {@code java.rmi.server.disableHttp} + * property, whose default value is {@code true}. Setting this property's + * value to {@code false} will enable the HTTP tunneling mechanisms. + * + *

    Deprecated: HTTP Tunneling. The HTTP tunneling mechanisms + * described above, specifically HTTP with an explicit port and HTTP to a + * cgi-bin script, are deprecated. These HTTP tunneling mechanisms are + * subject to removal in a future release of the platform. * *

    The default socket factory implementation creates server sockets that * are bound to the wildcard address, which accepts requests from all network @@ -168,7 +181,7 @@ public abstract class RMISocketFactory public synchronized static RMISocketFactory getDefaultSocketFactory() { if (defaultSocketFactory == null) { defaultSocketFactory = - new sun.rmi.transport.tcp.TCPDirectSocketFactory(); + new sun.rmi.transport.proxy.RMIMasterSocketFactory(); } return defaultSocketFactory; } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java new file mode 100644 index 00000000000..546ccd8ea10 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -0,0 +1,423 @@ +/* + * Copyright (c) 1996, 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. 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.transport.proxy; + +import java.io.*; +import java.net.*; +import java.util.Hashtable; + +/** + * CGIClientException is thrown when an error is detected + * in a client's request. + */ +class CGIClientException extends Exception { + private static final long serialVersionUID = 8147981687059865216L; + + public CGIClientException(String s) { + super(s); + } + + public CGIClientException(String s, Throwable cause) { + super(s, cause); + } +} + +/** + * CGIServerException is thrown when an error occurs here on the server. + */ +class CGIServerException extends Exception { + + private static final long serialVersionUID = 6928425456704527017L; + + public CGIServerException(String s) { + super(s); + } + + public CGIServerException(String s, Throwable cause) { + super(s, cause); + } +} + +/** + * CGICommandHandler is the interface to an object that handles a + * particular supported command. + */ +interface CGICommandHandler { + + /** + * Return the string form of the command + * to be recognized in the query string. + */ + public String getName(); + + /** + * Execute the command with the given string as parameter. + */ + public void execute(String param) throws CGIClientException, CGIServerException; +} + +/** + * The CGIHandler class contains methods for executing as a CGI program. + * The main function interprets the query string as a command of the form + * "{@code =}". + * + * This class depends on the CGI 1.0 environment variables being set as + * properties of the same name in this Java VM. + * + * All data and methods of this class are static because they are specific + * to this particular CGI process. + */ +public final class CGIHandler { + + /* get CGI parameters that we need */ + static int ContentLength; + static String QueryString; + static String RequestMethod; + static String ServerName; + static int ServerPort; + + static { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + ContentLength = + Integer.getInteger("CONTENT_LENGTH", 0).intValue(); + QueryString = System.getProperty("QUERY_STRING", ""); + RequestMethod = System.getProperty("REQUEST_METHOD", ""); + ServerName = System.getProperty("SERVER_NAME", ""); + ServerPort = Integer.getInteger("SERVER_PORT", 0).intValue(); + return null; + } + }); + } + + /* list of handlers for supported commands */ + private static CGICommandHandler commands[] = { + new CGIForwardCommand(), + new CGIGethostnameCommand(), + new CGIPingCommand(), + new CGITryHostnameCommand() + }; + + /* construct table mapping command strings to handlers */ + private static Hashtable commandLookup; + static { + commandLookup = new Hashtable<>(); + for (int i = 0; i < commands.length; ++ i) + commandLookup.put(commands[i].getName(), commands[i]); + } + + /* prevent instantiation of this class */ + private CGIHandler() {} + + /** + * Execute command given in query string on URL. The string before + * the first '=' is interpreted as the command name, and the string + * after the first '=' is the parameters to the command. + */ + public static void main(String args[]) + { + try { + String command, param; + int delim = QueryString.indexOf('='); + if (delim == -1) { + command = QueryString; + param = ""; + } + else { + command = QueryString.substring(0, delim); + param = QueryString.substring(delim + 1); + } + CGICommandHandler handler = + commandLookup.get(command); + if (handler != null) + try { + handler.execute(param); + } catch (CGIClientException e) { + e.printStackTrace(); + returnClientError(e.getMessage()); + } catch (CGIServerException e) { + e.printStackTrace(); + returnServerError(e.getMessage()); + } + else + returnClientError("invalid command."); + } catch (Exception e) { + e.printStackTrace(); + returnServerError("internal error: " + e.getMessage()); + } + System.exit(0); + } + + /** + * Return an HTML error message indicating there was error in + * the client's request. + */ + private static void returnClientError(String message) + { + System.out.println("Status: 400 Bad Request: " + message); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Client Error" + + "" + + ""); + System.out.println("

    Java RMI Client Error

    "); + System.out.println(""); + System.out.println(message); + System.out.println(""); + System.exit(1); + } + + /** + * Return an HTML error message indicating an error occurred + * here on the server. + */ + private static void returnServerError(String message) + { + System.out.println("Status: 500 Server Error: " + message); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Server Error" + + "" + + ""); + System.out.println("

    Java RMI Server Error

    "); + System.out.println(""); + System.out.println(message); + System.out.println(""); + System.exit(1); + } +} + +/** + * "forward" command: Forward request body to local port on the server, + * and send response back to client. + */ +final class CGIForwardCommand implements CGICommandHandler { + + public String getName() { + return "forward"; + } + + @SuppressWarnings("deprecation") + private String getLine (DataInputStream socketIn) throws IOException { + return socketIn.readLine(); + } + + public void execute(String param) throws CGIClientException, CGIServerException + { + if (!CGIHandler.RequestMethod.equals("POST")) + throw new CGIClientException("can only forward POST requests"); + + int port; + try { + port = Integer.parseInt(param); + } catch (NumberFormatException e) { + throw new CGIClientException("invalid port number.", e); + } + if (port <= 0 || port > 0xFFFF) + throw new CGIClientException("invalid port: " + port); + if (port < 1024) + throw new CGIClientException("permission denied for port: " + + port); + + byte buffer[]; + Socket socket; + try { + socket = new Socket(InetAddress.getLocalHost(), port); + } catch (IOException e) { + throw new CGIServerException("could not connect to local port", e); + } + + /* + * read client's request body + */ + DataInputStream clientIn = new DataInputStream(System.in); + buffer = new byte[CGIHandler.ContentLength]; + try { + clientIn.readFully(buffer); + } catch (EOFException e) { + throw new CGIClientException("unexpected EOF reading request body", e); + } catch (IOException e) { + throw new CGIClientException("error reading request body", e); + } + + /* + * send to local server in HTTP + */ + try { + DataOutputStream socketOut = + new DataOutputStream(socket.getOutputStream()); + socketOut.writeBytes("POST / HTTP/1.0\r\n"); + socketOut.writeBytes("Content-length: " + + CGIHandler.ContentLength + "\r\n\r\n"); + socketOut.write(buffer); + socketOut.flush(); + } catch (IOException e) { + throw new CGIServerException("error writing to server", e); + } + + /* + * read response + */ + DataInputStream socketIn; + try { + socketIn = new DataInputStream(socket.getInputStream()); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + String key = "Content-length:".toLowerCase(); + boolean contentLengthFound = false; + String line; + int responseContentLength = -1; + do { + try { + line = getLine(socketIn); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + if (line == null) + throw new CGIServerException( + "unexpected EOF reading server response"); + + if (line.toLowerCase().startsWith(key)) { + if (contentLengthFound) { + throw new CGIServerException( + "Multiple Content-length entries found."); + } else { + responseContentLength = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } + } + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); + + if (!contentLengthFound || responseContentLength < 0) + throw new CGIServerException( + "missing or invalid content length in server response"); + buffer = new byte[responseContentLength]; + try { + socketIn.readFully(buffer); + } catch (EOFException e) { + throw new CGIServerException( + "unexpected EOF reading server response", e); + } catch (IOException e) { + throw new CGIServerException("error reading from server", e); + } + + /* + * send response back to client + */ + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println(""); + try { + System.out.write(buffer); + } catch (IOException e) { + throw new CGIServerException("error writing response", e); + } + System.out.flush(); + } +} + +/** + * "gethostname" command: Return the host name of the server as the + * response body + */ +final class CGIGethostnameCommand implements CGICommandHandler { + + public String getName() { + return "gethostname"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println("Content-length: " + + CGIHandler.ServerName.length()); + System.out.println(""); + System.out.print(CGIHandler.ServerName); + System.out.flush(); + } +} + +/** + * "ping" command: Return an OK status to indicate that connection + * was successful. + */ +final class CGIPingCommand implements CGICommandHandler { + + public String getName() { + return "ping"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: application/octet-stream"); + System.out.println("Content-length: 0"); + System.out.println(""); + } +} + +/** + * "tryhostname" command: Return a human readable message describing + * what host name is available to local Java VMs. + */ +final class CGITryHostnameCommand implements CGICommandHandler { + + public String getName() { + return "tryhostname"; + } + + public void execute(String param) + { + System.out.println("Status: 200 OK"); + System.out.println("Content-type: text/html"); + System.out.println(""); + System.out.println("" + + "Java RMI Server Hostname Info" + + "" + + ""); + System.out.println("

    Java RMI Server Hostname Info

    "); + System.out.println("

    Local host name available to Java VM:

    "); + System.out.print("

    InetAddress.getLocalHost().getHostName()"); + try { + String localHostName = InetAddress.getLocalHost().getHostName(); + + System.out.println(" = " + localHostName); + } catch (UnknownHostException e) { + System.out.println(" threw java.net.UnknownHostException"); + } + + System.out.println("

    Server host information obtained through CGI interface from HTTP server:

    "); + System.out.println("

    SERVER_NAME = " + CGIHandler.ServerName); + System.out.println("

    SERVER_PORT = " + CGIHandler.ServerPort); + System.out.println(""); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java new file mode 100644 index 00000000000..b4512fecd93 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpAwareServerSocket.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1996, 2005, 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.transport.proxy; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import sun.rmi.runtime.Log; + +/** + * The HttpAwareServerSocket class extends the java.net.ServerSocket + * class. It behaves like a ServerSocket, except that if + * the first four bytes of an accepted socket are the letters "POST", + * then it returns an HttpReceiveSocket instead of a java.net.Socket. + * This means that the accept method blocks until four bytes have been + * read from the new socket's input stream. + */ +class HttpAwareServerSocket extends ServerSocket { + + /** + * Create a server socket on a specified port. + * @param port the port + * @exception IOException IO error when opening the socket. + */ + public HttpAwareServerSocket(int port) throws IOException + { + super(port); + } + + /** + * Create a server socket, bind it to the specified local port + * and listen to it. You can connect to an annonymous port by + * specifying the port number to be 0. backlog specifies + * how many connection requests the system will queue up while waiting + * for the ServerSocket to execute accept(). + * @param port the specified port + * @param backlog the number of queued connect requests pending accept + */ + public HttpAwareServerSocket(int port, int backlog) throws IOException + { + super(port, backlog); + } + + /** + * Accept a connection. This method will block until the connection + * is made and four bytes can be read from the input stream. + * If the first four bytes are "POST", then an HttpReceiveSocket is + * returned, which will handle the HTTP protocol wrapping. + * Otherwise, a WrappedSocket is returned. The input stream will be + * reset to the beginning of the transmission. + * In either case, a BufferedInputStream will already be on top of + * the underlying socket's input stream. + * @exception IOException IO error when waiting for the connection. + */ + public Socket accept() throws IOException + { + Socket socket = super.accept(); + BufferedInputStream in = + new BufferedInputStream(socket.getInputStream()); + + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + "socket accepted (checking for POST)"); + + in.mark(4); + boolean isHttp = (in.read() == 'P') && + (in.read() == 'O') && + (in.read() == 'S') && + (in.read() == 'T'); + in.reset(); + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + (isHttp ? "POST found, HTTP socket returned" : + "POST not found, direct socket returned")); + } + + if (isHttp) + return new HttpReceiveSocket(socket, in, null); + else + return new WrappedSocket(socket, in, null); + } + + /** + * Return the implementation address and implementation port of + * the HttpAwareServerSocket as a String. + */ + public String toString() + { + return "HttpAware" + super.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java new file mode 100644 index 00000000000..4b5cad95044 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpInputStream.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1996, 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. 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.transport.proxy; + +import java.io.*; + +import sun.rmi.runtime.Log; + +/** + * The HttpInputStream class assists the HttpSendSocket and HttpReceiveSocket + * classes by filtering out the header for the message as well as any + * data after its proper content length. + */ +class HttpInputStream extends FilterInputStream { + + /** bytes remaining to be read from proper content of message */ + protected int bytesLeft; + + /** bytes remaining to be read at time of last mark */ + protected int bytesLeftAtMark; + + /** + * Create new filter on a given input stream. + * @param in the InputStream to filter from + */ + @SuppressWarnings("deprecation") + public HttpInputStream(InputStream in) throws IOException + { + super(in); + + if (in.markSupported()) + in.mark(0); // prevent resetting back to old marks + + // pull out header, looking for content length + + DataInputStream dis = new DataInputStream(in); + String key = "Content-length:".toLowerCase(); + boolean contentLengthFound = false; + String line; + do { + line = dis.readLine(); + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "received header line: \"" + line + "\""); + } + + if (line == null) + throw new EOFException(); + + if (line.toLowerCase().startsWith(key)) { + if (contentLengthFound) { + throw new IOException( + "Multiple Content-length entries found."); + } else { + bytesLeft = + Integer.parseInt(line.substring(key.length()).trim()); + contentLengthFound = true; + } + } + + // The idea here is to go past the first blank line. + // Some DataInputStream.readLine() documentation specifies that + // it does include the line-terminating character(s) in the + // returned string, but it actually doesn't, so we'll cover + // all cases here... + } while ((line.length() != 0) && + (line.charAt(0) != '\r') && (line.charAt(0) != '\n')); + + if (!contentLengthFound || bytesLeft < 0) { + // This really shouldn't happen, but if it does, shoud we fail?? + // For now, just give up and let a whole lot of bytes through... + bytesLeft = Integer.MAX_VALUE; + } + bytesLeftAtMark = bytesLeft; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "content length: " + bytesLeft); + } + } + + /** + * Returns the number of bytes that can be read with blocking. + * Make sure that this does not exceed the number of bytes remaining + * in the proper content of the message. + */ + public int available() throws IOException + { + int bytesAvailable = in.available(); + if (bytesAvailable > bytesLeft) + bytesAvailable = bytesLeft; + + return bytesAvailable; + } + + /** + * Read a byte of data from the stream. Make sure that one is available + * from the proper content of the message, else -1 is returned to + * indicate to the user that the end of the stream has been reached. + */ + public int read() throws IOException + { + if (bytesLeft > 0) { + int data = in.read(); + if (data != -1) + -- bytesLeft; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "received byte: '" + + ((data & 0x7F) < ' ' ? " " : String.valueOf((char) data)) + + "' " + data); + } + + return data; + } + else { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read past content length"); + + return -1; + } + } + + public int read(byte b[], int off, int len) throws IOException + { + if (bytesLeft == 0 && len > 0) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read past content length"); + + return -1; + } + if (len > bytesLeft) + len = bytesLeft; + int bytesRead = in.read(b, off, len); + bytesLeft -= bytesRead; + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "read " + bytesRead + " bytes, " + bytesLeft + " remaining"); + } + + return bytesRead; + } + + /** + * Mark the current position in the stream (for future calls to reset). + * Remember where we are within the proper content of the message, so + * that a reset method call can recreate our state properly. + * @param readlimit how many bytes can be read before mark becomes invalid + */ + public void mark(int readlimit) + { + in.mark(readlimit); + if (in.markSupported()) + bytesLeftAtMark = bytesLeft; + } + + /** + * Repositions the stream to the last marked position. Make sure to + * adjust our position within the proper content accordingly. + */ + public void reset() throws IOException + { + in.reset(); + bytesLeft = bytesLeftAtMark; + } + + /** + * Skips bytes of the stream. Make sure to adjust our + * position within the proper content accordingly. + * @param n number of bytes to be skipped + */ + public long skip(long n) throws IOException + { + if (n > bytesLeft) + n = bytesLeft; + long bytesSkipped = in.skip(n); + bytesLeft -= bytesSkipped; + return bytesSkipped; + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java new file mode 100644 index 00000000000..5f1f2a6a680 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpOutputStream.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1996, 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.transport.proxy; + +import java.io.*; + +/** + * The HttpOutputStream class assists the HttpSendSocket and HttpReceiveSocket + * classes by providing an output stream that buffers its entire input until + * closed, and then it sends the complete transmission prefixed by the end of + * an HTTP header that specifies the content length. + */ +class HttpOutputStream extends ByteArrayOutputStream { + + /** the output stream to send response to */ + protected OutputStream out; + + /** true if HTTP response has been sent */ + boolean responseSent = false; + + /** + * Begin buffering new HTTP response to be sent to a given stream. + * @param out the OutputStream to send response to + */ + public HttpOutputStream(OutputStream out) { + super(); + this.out = out; + } + + /** + * On close, send HTTP-packaged response. + */ + public synchronized void close() throws IOException { + if (!responseSent) { + /* + * If response would have zero content length, then make it + * have some arbitrary data so that certain clients will not + * fail because the "document contains no data". + */ + if (size() == 0) + write(emptyData); + + DataOutputStream dos = new DataOutputStream(out); + dos.writeBytes("Content-type: application/octet-stream\r\n"); + dos.writeBytes("Content-length: " + size() + "\r\n"); + dos.writeBytes("\r\n"); + writeTo(dos); + dos.flush(); + // Do not close the underlying stream here, because that would + // close the underlying socket and prevent reading a response. + reset(); // reset byte array + responseSent = true; + } + } + + /** data to send if the response would otherwise be empty */ + private static byte[] emptyData = { 0 }; +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java new file mode 100644 index 00000000000..c916254ffcd --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpReceiveSocket.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1996, 2000, 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.transport.proxy; + +import java.io.*; +import java.net.Socket; +import java.net.InetAddress; + +/** + * The HttpReceiveSocket class extends the WrappedSocket class + * by removing the HTTP protocol packaging from the input stream and + * formatting the output stream as an HTTP response. + * + * NOTES: + * + * The output stream must be explicitly closed for the output to be + * sent, since the HttpResponseOutputStream needs to buffer the entire + * transmission to be able to fill in the content-length field of + * the HTTP header. Closing this socket will do this. + * + * The constructor blocks until the HTTP protocol header + * is received. This could be fixed, but I don't think it should be a + * problem because this object would not be created unless the + * HttpAwareServerSocket has detected the beginning of the header + * anyway, so the rest should be there. + * + * This socket can only be used to process one POST and reply to it. + * Another message would be received on a newly accepted socket anyway. + */ +public class HttpReceiveSocket extends WrappedSocket implements RMISocketInfo { + + /** true if the HTTP header has pushed through the output stream yet */ + private boolean headerSent = false; + + /** + * Layer on top of a pre-existing Socket object, and use specified + * input and output streams. + * @param socket the pre-existing socket to use + * @param in the InputStream to use for this socket (can be null) + * @param out the OutputStream to use for this socket (can be null) + */ + public HttpReceiveSocket(Socket socket, InputStream in, OutputStream out) + throws IOException + { + super(socket, in, out); + + this.in = new HttpInputStream(in != null ? in : + socket.getInputStream()); + this.out = (out != null ? out : + socket.getOutputStream()); + } + + /** + * Indicate that this socket is not reusable. + */ + public boolean isReusable() + { + return false; + } + + /** + * Get the address to which this socket is connected. "null" is always + * returned (to indicate an unknown address) because the originating + * host's IP address cannot be reliably determined: both because the + * request probably went through a proxy server, and because if it was + * delivered by a local forwarder (CGI script or servlet), we do NOT + * want it to appear as if the call is coming from the local host (in + * case the remote object makes access control decisions based on the + * "client host" of a remote call; see bugid 4399040). + */ + public InetAddress getInetAddress() { + return null; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + if (!headerSent) { // could this be done in constructor?? + DataOutputStream dos = new DataOutputStream(out); + dos.writeBytes("HTTP/1.0 200 OK\r\n"); + dos.flush(); + headerSent = true; + out = new HttpOutputStream(out); + } + return out; + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + getOutputStream().close(); // make sure response is sent + socket.close(); + } + + /** + * Return string representation of the socket. + */ + public String toString() + { + return "HttpReceive" + socket.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java new file mode 100644 index 00000000000..0c6de28c266 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendInputStream.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1996, 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.transport.proxy; + +import java.io.*; + +/** + * The HttpSendInputStream class is used by the HttpSendSocket class as + * a layer on the top of the InputStream it returns so that it can be + * notified of attempts to read from it. This allows the HttpSendSocket + * to know when it should push across its output message. + */ +class HttpSendInputStream extends FilterInputStream { + + /** the HttpSendSocket object that is providing this stream */ + HttpSendSocket owner; + + /** + * Create new filter on a given input stream. + * @param in the InputStream to filter from + * @param owner the HttpSendSocket that is providing this stream + */ + public HttpSendInputStream(InputStream in, HttpSendSocket owner) + throws IOException + { + super(in); + + this.owner = owner; + } + + /** + * Mark this stream as inactive for its owner socket, so the next time + * a read is attempted, the owner will be notified and a new underlying + * input stream obtained. + */ + public void deactivate() + { + in = null; + } + + /** + * Read a byte of data from the stream. + */ + public int read() throws IOException + { + if (in == null) + in = owner.readNotify(); + return in.read(); + } + + /** + * Read into an array of bytes. + * @param b the buffer into which the data is to be read + * @param off the start offset of the data + * @param len the maximum number of bytes to read + */ + public int read(byte b[], int off, int len) throws IOException + { + if (len == 0) + return 0; + if (in == null) + in = owner.readNotify(); + return in.read(b, off, len); + } + + /** + * Skip bytes of input. + * @param n the number of bytes to be skipped + */ + public long skip(long n) throws IOException + { + if (n == 0) + return 0; + if (in == null) + in = owner.readNotify(); + return in.skip(n); + } + + /** + * Return the number of bytes that can be read without blocking. + */ + public int available() throws IOException + { + if (in == null) + in = owner.readNotify(); + return in.available(); + } + + /** + * Close the stream. + */ + public void close() throws IOException + { + owner.close(); + } + + /** + * Mark the current position in the stream. + * @param readlimit how many bytes can be read before mark becomes invalid + */ + public synchronized void mark(int readlimit) + { + if (in == null) { + try { + in = owner.readNotify(); + } + catch (IOException e) { + return; + } + } + in.mark(readlimit); + } + + /** + * Reposition the stream to the last marked position. + */ + public synchronized void reset() throws IOException + { + if (in == null) + in = owner.readNotify(); + in.reset(); + } + + /** + * Return true if this stream type supports mark/reset. + */ + public boolean markSupported() + { + if (in == null) { + try { + in = owner.readNotify(); + } + catch (IOException e) { + return false; + } + } + return in.markSupported(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java new file mode 100644 index 00000000000..bc83945534f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendOutputStream.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1996, 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.transport.proxy; + +import java.io.*; + +/** + * The HttpSendOutputStream class is used by the HttpSendSocket class as + * a layer on the top of the OutputStream it returns so that it can be + * notified of attempts to write to it. This allows the HttpSendSocket + * to know when it should construct a new message. + */ +class HttpSendOutputStream extends FilterOutputStream { + + /** the HttpSendSocket object that is providing this stream */ + HttpSendSocket owner; + + /** + * Create new filter on a given output stream. + * @param out the OutputStream to filter from + * @param owner the HttpSendSocket that is providing this stream + */ + public HttpSendOutputStream(OutputStream out, HttpSendSocket owner) + throws IOException + { + super(out); + + this.owner = owner; + } + + /** + * Mark this stream as inactive for its owner socket, so the next time + * a write is attempted, the owner will be notified and a new underlying + * output stream obtained. + */ + public void deactivate() + { + out = null; + } + + /** + * Write a byte of data to the stream. + */ + public void write(int b) throws IOException + { + if (out == null) + out = owner.writeNotify(); + out.write(b); + } + + /** + * Write a subarray of bytes. + * @param b the buffer from which the data is to be written + * @param off the start offset of the data + * @param len the number of bytes to be written + */ + public void write(byte b[], int off, int len) throws IOException + { + if (len == 0) + return; + if (out == null) + out = owner.writeNotify(); + out.write(b, off, len); + } + + /** + * Flush the stream. + */ + public void flush() throws IOException + { + if (out != null) + out.flush(); + } + + /** + * Close the stream. + */ + public void close() throws IOException + { + flush(); + owner.close(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java new file mode 100644 index 00000000000..a9932be35e1 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/HttpSendSocket.java @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1996, 2012, 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.transport.proxy; + +import java.io.*; +import java.net.*; +import java.security.PrivilegedAction; + +import sun.rmi.runtime.Log; + +/** + * The HttpSendSocket class extends the java.net.Socket class + * by enclosing the data output stream in, then extracting the input + * stream from, an HTTP protocol transmission. + * + * NOTES: + * + * Since the length of the output request must be known before the + * HTTP header can be completed, all of the output is buffered by + * an HttpOutputStream object until either an attempt is made to + * read from this socket, or the socket is explicitly closed. + * + * On the first read attempt to read from this socket, the buffered + * output is sent to the destination as the body of an HTTP POST + * request. All reads will then acquire data from the body of + * the response. A subsequent attempt to write to this socket will + * throw an IOException. + */ +class HttpSendSocket extends Socket implements RMISocketInfo { + + /** the host to connect to */ + protected String host; + + /** the port to connect to */ + protected int port; + + /** the URL to forward through */ + protected URL url; + + /** the object managing this connection through the URL */ + protected URLConnection conn = null; + + /** internal input stream for this socket */ + protected InputStream in = null; + + /** internal output stream for this socket */ + protected OutputStream out = null; + + /** the notifying input stream returned to users */ + protected HttpSendInputStream inNotifier; + + /** the notifying output stream returned to users */ + protected HttpSendOutputStream outNotifier; + + /** + * Line separator string. This is the value of the line.separator + * property at the moment that the socket was created. + */ + private String lineSeparator = + java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("line.separator")); + + /** + * Create a stream socket and connect it to the specified port on + * the specified host. + * @param host the host + * @param port the port + */ + public HttpSendSocket(String host, int port, URL url) throws IOException + { + super((SocketImpl)null); // no underlying SocketImpl for this object + + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.VERBOSE)) { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "host = " + host + ", port = " + port + ", url = " + url); + } + + this.host = host; + this.port = port; + this.url = url; + + inNotifier = new HttpSendInputStream(null, this); + outNotifier = new HttpSendOutputStream(writeNotify(), this); + } + + /** + * Create a stream socket and connect it to the specified port on + * the specified host. + * @param host the host + * @param port the port + */ + public HttpSendSocket(String host, int port) throws IOException + { + this(host, port, new URL("http", host, port, "/")); + } + + /** + * Create a stream socket and connect it to the specified address on + * the specified port. + * @param address the address + * @param port the port + */ + public HttpSendSocket(InetAddress address, int port) throws IOException + { + this(address.getHostName(), port); + } + + /** + * Indicate that this socket is not reusable. + */ + public boolean isReusable() + { + return false; + } + + /** + * Create a new socket connection to host (or proxy), and prepare to + * send HTTP transmission. + */ + public synchronized OutputStream writeNotify() throws IOException + { + if (conn != null) { + throw new IOException("attempt to write on HttpSendSocket after " + + "request has been sent"); + } + + conn = url.openConnection(); + conn.setDoOutput(true); + conn.setUseCaches(false); + conn.setRequestProperty("Content-type", "application/octet-stream"); + + inNotifier.deactivate(); + in = null; + + return out = conn.getOutputStream(); + } + + /** + * Send HTTP output transmission and prepare to receive response. + */ + public synchronized InputStream readNotify() throws IOException + { + RMIMasterSocketFactory.proxyLog.log(Log.VERBOSE, + "sending request and activating input stream"); + + outNotifier.deactivate(); + out.close(); + out = null; + + try { + in = conn.getInputStream(); + } catch (IOException e) { + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, + "failed to get input stream, exception: ", e); + + throw new IOException("HTTP request failed"); + } + + /* + * If an HTTP error response is returned, sometimes an IOException + * is thrown, which is handled above, and other times it isn't, and + * the error response body will be available for reading. + * As a safety net to catch any such unexpected HTTP behavior, we + * verify that the content type of the response is what the + * HttpOutputStream generates: "application/octet-stream". + * (Servers' error responses will generally be "text/html".) + * Any error response body is printed to the log. + */ + String contentType = conn.getContentType(); + if (contentType == null || + !conn.getContentType().equals("application/octet-stream")) + { + if (RMIMasterSocketFactory.proxyLog.isLoggable(Log.BRIEF)) { + String message; + if (contentType == null) { + message = "missing content type in response" + + lineSeparator; + } else { + message = "invalid content type in response: " + + contentType + lineSeparator; + } + + message += "HttpSendSocket.readNotify: response body: "; + try { + BufferedReader din = new BufferedReader(new InputStreamReader(in)); + String line; + while ((line = din.readLine()) != null) + message += line + lineSeparator; + } catch (IOException e) { + } + RMIMasterSocketFactory.proxyLog.log(Log.BRIEF, message); + } + + throw new IOException("HTTP request failed"); + } + + return in; + } + + /** + * Get the address to which the socket is connected. + */ + public InetAddress getInetAddress() + { + try { + return InetAddress.getByName(host); + } catch (UnknownHostException e) { + return null; // null if couldn't resolve destination host + } + } + + /** + * Get the local address to which the socket is bound. + */ + public InetAddress getLocalAddress() + { + try { + return InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + return null; // null if couldn't determine local host + } + } + + /** + * Get the remote port to which the socket is connected. + */ + public int getPort() + { + return port; + } + + /** + * Get the local port to which the socket is connected. + */ + public int getLocalPort() + { + return -1; // request not applicable to this socket type + } + + /** + * Get an InputStream for this socket. + */ + public InputStream getInputStream() throws IOException + { + return inNotifier; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + return outNotifier; + } + + /** + * Enable/disable TCP_NODELAY. + * This operation has no effect for an HttpSendSocket. + */ + public void setTcpNoDelay(boolean on) throws SocketException + { + } + + /** + * Retrieve whether TCP_NODELAY is enabled. + */ + public boolean getTcpNoDelay() throws SocketException + { + return false; // imply option is disabled + } + + /** + * Enable/disable SO_LINGER with the specified linger time. + * This operation has no effect for an HttpSendSocket. + */ + public void setSoLinger(boolean on, int val) throws SocketException + { + } + + /** + * Retrive setting for SO_LINGER. + */ + public int getSoLinger() throws SocketException + { + return -1; // imply option is disabled + } + + /** + * Enable/disable SO_TIMEOUT with the specified timeout + * This operation has no effect for an HttpSendSocket. + */ + public synchronized void setSoTimeout(int timeout) throws SocketException + { + } + + /** + * Retrive setting for SO_TIMEOUT. + */ + public synchronized int getSoTimeout() throws SocketException + { + return 0; // imply option is disabled + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + if (out != null) // push out transmission if not done + out.close(); + } + + /** + * Return string representation of this pseudo-socket. + */ + public String toString() + { + return "HttpSendSocket[host=" + host + + ",port=" + port + + ",url=" + url + "]"; + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java similarity index 94% rename from jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java rename to jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java index 8274742ec1b..953d47ca400 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPDirectSocketFactory.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIDirectSocketFactory.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package sun.rmi.transport.tcp; +package sun.rmi.transport.proxy; import java.io.IOException; import java.net.Socket; @@ -33,7 +33,7 @@ import java.rmi.server.RMISocketFactory; * RMIDirectSocketFactory creates a direct socket connection to the * specified port on the specified host. */ -public class TCPDirectSocketFactory extends RMISocketFactory { +public class RMIDirectSocketFactory extends RMISocketFactory { public Socket createSocket(String host, int port) throws IOException { diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java new file mode 100644 index 00000000000..548f584ae11 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToCGISocketFactory.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1998, 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.transport.proxy; + +import java.io.IOException; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.URL; +import java.rmi.server.RMISocketFactory; + +/** + * RMIHttpToCGISocketFactory creates a socket connection to the + * specified host that is comminicated within an HTTP request, + * forwarded through the default firewall proxy, to the target host's + * normal HTTP server, to a CGI program which forwards the request to + * the actual specified port on the socket. + */ +public class RMIHttpToCGISocketFactory extends RMISocketFactory { + + public Socket createSocket(String host, int port) + throws IOException + { + return new HttpSendSocket(host, port, + new URL("http", host, + "/cgi-bin/java-rmi.cgi" + + "?forward=" + port)); + } + + public ServerSocket createServerSocket(int port) throws IOException + { + return new HttpAwareServerSocket(port); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java new file mode 100644 index 00000000000..c23df420e44 --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIHttpToPortSocketFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998, 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.transport.proxy; + +import java.io.IOException; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.URL; +import java.rmi.server.RMISocketFactory; + +/** + * RMIHttpToPortSocketFactory creates a socket connection to the + * specified host that is communicated within an HTTP request, + * forwarded through the default firewall proxy, directly to the + * specified port. + */ +public class RMIHttpToPortSocketFactory extends RMISocketFactory { + + public Socket createSocket(String host, int port) + throws IOException + { + return new HttpSendSocket(host, port, + new URL("http", host, port, "/")); + } + + public ServerSocket createServerSocket(int port) + throws IOException + { + return new HttpAwareServerSocket(port); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java new file mode 100644 index 00000000000..8cb7cc4185f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMIMasterSocketFactory.java @@ -0,0 +1,468 @@ +/* + * Copyright (c) 1996, 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. 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.transport.proxy; + +import java.io.*; +import java.net.*; +import java.security.*; +import java.util.*; +import java.rmi.server.LogStream; +import java.rmi.server.RMISocketFactory; +import sun.rmi.runtime.Log; +import sun.rmi.runtime.NewThreadAction; + +/** + * RMIMasterSocketFactory attempts to create a socket connection to the + * specified host using successively less efficient mechanisms + * until one succeeds. If the host is successfully connected to, + * the factory for the successful mechanism is stored in an internal + * hash table keyed by the host name, so that future attempts to + * connect to the same host will automatically use the same + * mechanism. + */ +@SuppressWarnings("deprecation") +public class RMIMasterSocketFactory extends RMISocketFactory { + + /** "proxy" package log level */ + static int logLevel = LogStream.parseLevel(getLogLevel()); + + private static String getLogLevel() { + return java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("sun.rmi.transport.proxy.logLevel")); + } + + /* proxy package log */ + static final Log proxyLog = + Log.getLog("sun.rmi.transport.tcp.proxy", + "transport", RMIMasterSocketFactory.logLevel); + + /** timeout for attemping direct socket connections */ + private static long connectTimeout = getConnectTimeout(); + + private static long getConnectTimeout() { + return java.security.AccessController.doPrivileged((PrivilegedAction) () -> + Long.getLong("sun.rmi.transport.proxy.connectTimeout", 15000)); // default: 15 seconds + } + + /** whether to fallback to HTTP on general connect failures */ + private static final boolean eagerHttpFallback = + java.security.AccessController.doPrivileged((PrivilegedAction) () -> + Boolean.getBoolean("sun.rmi.transport.proxy.eagerHttpFallback")); + + /** table of hosts successfully connected to and the factory used */ + private Hashtable successTable = + new Hashtable<>(); + + /** maximum number of hosts to remember successful connection to */ + private static final int MaxRememberedHosts = 64; + + /** list of the hosts in successTable in initial connection order */ + private Vector hostList = new Vector<>(MaxRememberedHosts); + + /** default factory for initial use for direct socket connection */ + protected RMISocketFactory initialFactory = new RMIDirectSocketFactory(); + + /** ordered list of factories to try as alternate connection + * mechanisms if a direct socket connections fails */ + protected Vector altFactoryList; + + /** + * Create a RMIMasterSocketFactory object. Establish order of + * connection mechanisms to attempt on createSocket, if a direct + * socket connection fails. + */ + public RMIMasterSocketFactory() { + altFactoryList = new Vector<>(2); + boolean setFactories = false; + + try { + String proxyHost; + proxyHost = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("http.proxyHost")); + + if (proxyHost == null) + proxyHost = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("proxyHost")); + + boolean disable = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty("java.rmi.server.disableHttp", "true")) + .equalsIgnoreCase("true"); + + if (!disable && proxyHost != null && proxyHost.length() > 0) { + setFactories = true; + } + } catch (Exception e) { + // unable to obtain the properties, so use the default behavior. + } + + if (setFactories) { + altFactoryList.addElement(new RMIHttpToPortSocketFactory()); + altFactoryList.addElement(new RMIHttpToCGISocketFactory()); + } + } + + /** + * Create a new client socket. If we remember connecting to this host + * successfully before, then use the same factory again. Otherwise, + * try using a direct socket connection and then the alternate factories + * in the order specified in altFactoryList. + */ + public Socket createSocket(String host, int port) + throws IOException + { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port); + } + + /* + * If we don't have any alternate factories to consult, short circuit + * the fallback procedure and delegate to the initial factory. + */ + if (altFactoryList.size() == 0) { + return initialFactory.createSocket(host, port); + } + + RMISocketFactory factory; + + /* + * If we remember successfully connecting to this host before, + * use the same factory. + */ + factory = successTable.get(host); + if (factory != null) { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "previously successful factory found: " + factory); + } + return factory.createSocket(host, port); + } + + /* + * Next, try a direct socket connection. Open socket in another + * thread and only wait for specified timeout, in case the socket + * would otherwise spend minutes trying an unreachable host. + */ + Socket initialSocket = null; + Socket fallbackSocket = null; + final AsyncConnector connector = + new AsyncConnector(initialFactory, host, port, + AccessController.getContext()); + // connection must be attempted with + // this thread's access control context + IOException initialFailure = null; + + try { + synchronized (connector) { + + Thread t = java.security.AccessController.doPrivileged( + new NewThreadAction(connector, "AsyncConnector", true)); + t.start(); + + try { + long now = System.currentTimeMillis(); + long deadline = now + connectTimeout; + do { + connector.wait(deadline - now); + initialSocket = checkConnector(connector); + if (initialSocket != null) + break; + now = System.currentTimeMillis(); + } while (now < deadline); + } catch (InterruptedException e) { + throw new InterruptedIOException( + "interrupted while waiting for connector"); + } + } + + // assume no route to host (for now) if no connection yet + if (initialSocket == null) + throw new NoRouteToHostException( + "connect timed out: " + host); + + proxyLog.log(Log.BRIEF, "direct socket connection successful"); + + return initialSocket; + + } catch (UnknownHostException | NoRouteToHostException e) { + initialFailure = e; + } catch (SocketException e) { + if (eagerHttpFallback) { + initialFailure = e; + } else { + throw e; + } + } finally { + if (initialFailure != null) { + + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "direct socket connection failed: ", initialFailure); + } + + // Finally, try any alternate connection mechanisms. + for (int i = 0; i < altFactoryList.size(); ++ i) { + factory = altFactoryList.elementAt(i); + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, + "trying with factory: " + factory); + } + try (Socket testSocket = + factory.createSocket(host, port)) { + // For HTTP connections, the output (POST request) must + // be sent before we verify a successful connection. + // So, sacrifice a socket for the sake of testing... + // The following sequence should verify a successful + // HTTP connection if no IOException is thrown. + InputStream in = testSocket.getInputStream(); + int b = in.read(); // probably -1 for EOF... + } catch (IOException ex) { + if (proxyLog.isLoggable(Log.BRIEF)) { + proxyLog.log(Log.BRIEF, "factory failed: ", ex); + } + + continue; + } + proxyLog.log(Log.BRIEF, "factory succeeded"); + + // factory succeeded, open new socket for caller's use + try { + fallbackSocket = factory.createSocket(host, port); + } catch (IOException ex) { // if it fails 2nd time, + } // just give up + break; + } + } + } + + synchronized (successTable) { + try { + // check once again to see if direct connection succeeded + synchronized (connector) { + initialSocket = checkConnector(connector); + } + if (initialSocket != null) { + // if we had made another one as well, clean it up... + if (fallbackSocket != null) + fallbackSocket.close(); + return initialSocket; + } + // if connector ever does get socket, it won't be used + connector.notUsed(); + } catch (UnknownHostException | NoRouteToHostException e) { + initialFailure = e; + } catch (SocketException e) { + if (eagerHttpFallback) { + initialFailure = e; + } else { + throw e; + } + } + // if we had found an alternate mechanism, go and use it + if (fallbackSocket != null) { + // remember this successful host/factory pair + rememberFactory(host, factory); + return fallbackSocket; + } + throw initialFailure; + } + } + + /** + * Remember a successful factory for connecting to host. + * Currently, excess hosts are removed from the remembered list + * using a Least Recently Created strategy. + */ + void rememberFactory(String host, RMISocketFactory factory) { + synchronized (successTable) { + while (hostList.size() >= MaxRememberedHosts) { + successTable.remove(hostList.elementAt(0)); + hostList.removeElementAt(0); + } + hostList.addElement(host); + successTable.put(host, factory); + } + } + + /** + * Check if an AsyncConnector succeeded. If not, return socket + * given to fall back to. + */ + Socket checkConnector(AsyncConnector connector) + throws IOException + { + Exception e = connector.getException(); + if (e != null) { + e.fillInStackTrace(); + /* + * The AsyncConnector implementation guaranteed that the exception + * will be either an IOException or a RuntimeException, and we can + * only throw one of those, so convince that compiler that it must + * be one of those. + */ + if (e instanceof IOException) { + throw (IOException) e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new Error("internal error: " + + "unexpected checked exception: " + e.toString()); + } + } + return connector.getSocket(); + } + + /** + * Create a new server socket. + */ + public ServerSocket createServerSocket(int port) throws IOException { + //return new HttpAwareServerSocket(port); + return initialFactory.createServerSocket(port); + } + + + /** + * AsyncConnector is used by RMIMasterSocketFactory to attempt socket + * connections on a separate thread. This allows RMIMasterSocketFactory + * to control how long it will wait for the connection to succeed. + */ + private class AsyncConnector implements Runnable { + + /** what factory to use to attempt connection */ + private RMISocketFactory factory; + + /** the host to connect to */ + private String host; + + /** the port to connect to */ + private int port; + + /** access control context to attempt connection within */ + private AccessControlContext acc; + + /** exception that occurred during connection, if any */ + private Exception exception = null; + + /** the connected socket, if successful */ + private Socket socket = null; + + /** socket should be closed after created, if ever */ + private boolean cleanUp = false; + + /** + * Create a new asynchronous connector object. + */ + AsyncConnector(RMISocketFactory factory, String host, int port, + AccessControlContext acc) + { + this.factory = factory; + this.host = host; + this.port = port; + this.acc = acc; + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkConnect(host, port); + } + } + + /** + * Attempt socket connection in separate thread. If successful, + * notify master waiting, + */ + public void run() { + try { + /* + * Using the privileges of the thread that wants to make the + * connection is tempting, but it will fail with applets with + * the current applet security manager because the applet + * network connection policy is not captured in the permission + * framework of the access control context we have. + * + * java.security.AccessController.beginPrivileged(acc); + */ + try { + Socket temp = factory.createSocket(host, port); + synchronized (this) { + socket = temp; + notify(); + } + rememberFactory(host, factory); + synchronized (this) { + if (cleanUp) + try { + socket.close(); + } catch (IOException e) { + } + } + } catch (Exception e) { + /* + * Note that the only exceptions which could actually have + * occurred here are IOException or RuntimeException. + */ + synchronized (this) { + exception = e; + notify(); + } + } + } finally { + /* + * See above comments for matching beginPrivileged() call that + * is also commented out. + * + * java.security.AccessController.endPrivileged(); + */ + } + } + + /** + * Get exception that occurred during connection attempt, if any. + * In the current implementation, this is guaranteed to be either + * an IOException or a RuntimeException. + */ + private synchronized Exception getException() { + return exception; + } + + /** + * Get successful socket, if any. + */ + private synchronized Socket getSocket() { + return socket; + } + + /** + * Note that this connector's socket, if ever successfully created, + * will not be used, so it should be cleaned up quickly + */ + synchronized void notUsed() { + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + } + } + cleanUp = true; + } + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java new file mode 100644 index 00000000000..85008fb231e --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/RMISocketInfo.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1996, 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.transport.proxy; + +/** + * RMISocketInfo is an interface that extensions of the java.net.Socket + * class may use to provide more information on its capabilities. + */ +public interface RMISocketInfo { + + /** + * Return true if this socket can be used for more than one + * RMI call. If a socket does not implement this interface, then + * it is assumed to be reusable. + */ + public boolean isReusable(); +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java new file mode 100644 index 00000000000..7bc8503f60f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/proxy/WrappedSocket.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 1996, 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. 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.transport.proxy; + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * The WrappedSocket class provides a general wrapper for providing an + * extended implementation of java.net.Socket that can be attached to + * a pre-existing Socket object. WrappedSocket itself provides a + * constructor for specifying alternate input or output streams to be + * returned than those of the underlying Socket. + */ +class WrappedSocket extends Socket { + + /** the underlying concrete socket */ + protected Socket socket; + + /** the input stream to return for socket */ + protected InputStream in = null; + + /** the output stream to return for socket */ + protected OutputStream out = null; + + /** + * Layer on top of a pre-existing Socket object, and use specified + * input and output streams. This allows the creator of the + * underlying socket to peek at the beginning of the input with a + * BufferedInputStream and determine which kind of socket + * to create, without consuming the input. + * @param socket the pre-existing socket to use + * @param in the InputStream to return to users (can be null) + * @param out the OutputStream to return to users (can be null) + */ + public WrappedSocket(Socket socket, InputStream in, OutputStream out) + throws IOException + { + super((java.net.SocketImpl)null); // no underlying SocketImpl for this object + this.socket = socket; + this.in = in; + this.out = out; + } + + /** + * Get the address to which the socket is connected. + */ + public InetAddress getInetAddress() + { + return socket.getInetAddress(); + } + + /** + * Get the local address to which the socket is bound. + */ + public InetAddress getLocalAddress() { + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public InetAddress run() { + return socket.getLocalAddress(); + + } + }); + } + + /** + * Get the remote port to which the socket is connected. + */ + public int getPort() + { + return socket.getPort(); + } + + /** + * Get the local port to which the socket is connected. + */ + public int getLocalPort() + { + return socket.getLocalPort(); + } + + /** + * Get an InputStream for this socket. + */ + public InputStream getInputStream() throws IOException + { + if (in == null) + in = socket.getInputStream(); + return in; + } + + /** + * Get an OutputStream for this socket. + */ + public OutputStream getOutputStream() throws IOException + { + if (out == null) + out = socket.getOutputStream(); + return out; + } + + /** + * Enable/disable TCP_NODELAY. + */ + public void setTcpNoDelay(boolean on) throws SocketException + { + socket.setTcpNoDelay(on); + } + + /** + * Retrieve whether TCP_NODELAY is enabled. + */ + public boolean getTcpNoDelay() throws SocketException + { + return socket.getTcpNoDelay(); + } + + /** + * Enable/disable SO_LINGER with the specified linger time. + */ + public void setSoLinger(boolean on, int val) throws SocketException + { + socket.setSoLinger(on, val); + } + + /** + * Retrive setting for SO_LINGER. + */ + public int getSoLinger() throws SocketException + { + return socket.getSoLinger(); + } + + /** + * Enable/disable SO_TIMEOUT with the specified timeout + */ + public synchronized void setSoTimeout(int timeout) throws SocketException + { + socket.setSoTimeout(timeout); + } + + /** + * Retrive setting for SO_TIMEOUT. + */ + public synchronized int getSoTimeout() throws SocketException + { + return socket.getSoTimeout(); + } + + /** + * Close the socket. + */ + public synchronized void close() throws IOException + { + socket.close(); + } + + /** + * Return string representation of the socket. + */ + public String toString() + { + return "Wrapped" + socket.toString(); + } +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java index 8b5a610005b..08eb50b29a7 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2001, 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,10 +26,14 @@ package sun.rmi.transport.tcp; import java.io.*; +import java.net.InetAddress; import java.net.Socket; +import java.net.SocketException; import java.rmi.*; +import java.rmi.server.RMISocketFactory; import sun.rmi.runtime.Log; import sun.rmi.transport.*; +import sun.rmi.transport.proxy.*; public class TCPConnection implements Connection { @@ -116,7 +120,10 @@ public class TCPConnection implements Connection { */ public boolean isReusable() { - return true; + if ((socket != null) && (socket instanceof RMISocketInfo)) + return ((RMISocketInfo) socket).isReusable(); + else + return true; } /** diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java index 764abefb551..1caa362803a 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -75,6 +75,7 @@ import sun.rmi.transport.StreamRemoteCall; import sun.rmi.transport.Target; import sun.rmi.transport.Transport; import sun.rmi.transport.TransportConstants; +import sun.rmi.transport.proxy.HttpReceiveSocket; /** * TCPTransport is the socket-based implementation of the RMI Transport @@ -710,10 +711,35 @@ public class TCPTransport extends Transport { ? sockIn : new BufferedInputStream(sockIn); - // Read magic + // Read magic (or HTTP wrapper) + bufIn.mark(4); DataInputStream in = new DataInputStream(bufIn); int magic = in.readInt(); + if (magic == POST) { + tcpLog.log(Log.BRIEF, "decoding HTTP-wrapped call"); + + // It's really a HTTP-wrapped request. Repackage + // the socket in a HttpReceiveSocket, reinitialize + // sockIn and in, and reread magic. + bufIn.reset(); // unread "POST" + + try { + socket = new HttpReceiveSocket(socket, bufIn, null); + remoteHost = "0.0.0.0"; + sockIn = socket.getInputStream(); + bufIn = new BufferedInputStream(sockIn); + in = new DataInputStream(bufIn); + magic = in.readInt(); + + } catch (IOException e) { + throw new RemoteException("Error HTTP-unwrapping call", + e); + } + } + // bufIn's mark will invalidate itself when it overflows + // so it doesn't have to be turned off + // read and verify transport header short version = in.readShort(); if (magic != TransportConstants.Magic || diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 684b0cab3ab..696c9cd270f 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -191,6 +191,8 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 7191877 generic-all +sun/rmi/transport/proxy/EagerHttpFallback.java 7195095 generic-all + java/rmi/activation/Activatable/extLoadedImpl/ext.sh 8062724 generic-all sun/rmi/rmic/newrmic/equivalence/run.sh 8145980 generic-all diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java new file mode 100644 index 00000000000..8999c3d7310 --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * + * @summary HttpSocket functionality test + * @author Dana Burns + * + * @library ../../testlibrary + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.proxy + * java.rmi/sun.rmi.transport.tcp + * @build TestLibrary HttpSocketTest HttpSocketTest_Stub + * @run main/othervm/policy=security.policy HttpSocketTest + */ + +/* + * This test assures remote methods can be carried out over RMI. + * After setting the RMI runtime socket factory to the http proxy version, + * a registry is created, a remote object (an instance of this class) is + * registered with it, and then it is exercised. + */ + +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.Naming; +import java.rmi.RMISecurityManager; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMISocketFactory; +import java.rmi.server.UnicastRemoteObject; +import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; + +interface MyRemoteInterface extends Remote { + void setRemoteObject( Remote r ) throws RemoteException; + Remote getRemoteObject() throws RemoteException; +} + +public class HttpSocketTest extends UnicastRemoteObject + implements MyRemoteInterface +{ + private static final String NAME = "HttpSocketTest"; + + public HttpSocketTest() throws RemoteException{} + + private Remote ro; + + public static void main(String[] args) + throws Exception + { + + Registry registry = null; + + TestLibrary.suggestSecurityManager(null); + + // Set the socket factory. + System.err.println("installing socket factory"); + RMISocketFactory.setSocketFactory(new RMIHttpToPortSocketFactory()); + int registryPort = -1; + + try { + System.err.println("Starting registry"); + registry = TestLibrary.createRegistryOnUnusedPort(); + registryPort = TestLibrary.getRegistryPort(registry); + } catch (Exception e) { + TestLibrary.bomb(e); + } + + try { + registry.rebind( NAME, new HttpSocketTest() ); + MyRemoteInterface httpTest = + (MyRemoteInterface)Naming.lookup("//:" + registryPort + "/" + NAME); + httpTest.setRemoteObject( new HttpSocketTest() ); + Remote r = httpTest.getRemoteObject(); + + } catch (Exception e) { + TestLibrary.bomb(e); + } + + + } + + public void setRemoteObject( Remote ro ) throws RemoteException { + this.ro = ro; + } + + public Remote getRemoteObject() throws RemoteException { + return( this.ro ); + } + +} diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java new file mode 100644 index 00000000000..03757a3df20 --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest_Stub.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1999, 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. + */ + +// Stub class generated by rmic, do not edit. +// Contents subject to change without notice. + +public final class HttpSocketTest_Stub + extends java.rmi.server.RemoteStub + implements MyRemoteInterface, java.rmi.Remote +{ + private static final java.rmi.server.Operation[] operations = { + new java.rmi.server.Operation("java.rmi.Remote getRemoteObject()"), + new java.rmi.server.Operation("void setRemoteObject(java.rmi.Remote)") + }; + + private static final long interfaceHash = 3775375480010579665L; + + private static final long serialVersionUID = 2; + + private static boolean useNewInvoke; + private static java.lang.reflect.Method $method_getRemoteObject_0; + private static java.lang.reflect.Method $method_setRemoteObject_1; + + static { + try { + java.rmi.server.RemoteRef.class.getMethod("invoke", + new java.lang.Class[] { + java.rmi.Remote.class, + java.lang.reflect.Method.class, + java.lang.Object[].class, + long.class + }); + useNewInvoke = true; + $method_getRemoteObject_0 = MyRemoteInterface.class.getMethod("getRemoteObject", new java.lang.Class[] {}); + $method_setRemoteObject_1 = MyRemoteInterface.class.getMethod("setRemoteObject", new java.lang.Class[] {java.rmi.Remote.class}); + } catch (java.lang.NoSuchMethodException e) { + useNewInvoke = false; + } + } + + // constructors + public HttpSocketTest_Stub() { + super(); + } + public HttpSocketTest_Stub(java.rmi.server.RemoteRef ref) { + super(ref); + } + + // methods from remote interfaces + + // implementation of getRemoteObject() + public java.rmi.Remote getRemoteObject() + throws java.rmi.RemoteException + { + try { + if (useNewInvoke) { + Object $result = ref.invoke(this, $method_getRemoteObject_0, null, -2578437860804964265L); + return ((java.rmi.Remote) $result); + } else { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash); + ref.invoke(call); + java.rmi.Remote $result; + try { + java.io.ObjectInput in = call.getInputStream(); + $result = (java.rmi.Remote) in.readObject(); + } catch (java.io.IOException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } catch (java.lang.ClassNotFoundException e) { + throw new java.rmi.UnmarshalException("error unmarshalling return", e); + } finally { + ref.done(call); + } + return $result; + } + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } + + // implementation of setRemoteObject(Remote) + public void setRemoteObject(java.rmi.Remote $param_Remote_1) + throws java.rmi.RemoteException + { + try { + if (useNewInvoke) { + ref.invoke(this, $method_setRemoteObject_1, new java.lang.Object[] {$param_Remote_1}, -7518632118115022871L); + } else { + java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash); + try { + java.io.ObjectOutput out = call.getOutputStream(); + out.writeObject($param_Remote_1); + } catch (java.io.IOException e) { + throw new java.rmi.MarshalException("error marshalling arguments", e); + } + ref.invoke(call); + ref.done(call); + } + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } +} diff --git a/jdk/test/java/rmi/transport/httpSocket/security.policy b/jdk/test/java/rmi/transport/httpSocket/security.policy new file mode 100644 index 00000000000..f1960c9772d --- /dev/null +++ b/jdk/test/java/rmi/transport/httpSocket/security.policy @@ -0,0 +1,10 @@ + +grant { + permission java.net.SocketPermission "*:1024-", "accept,connect,listen"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.proxy"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp"; + permission java.lang.RuntimePermission "setFactory"; +}; diff --git a/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java new file mode 100644 index 00000000000..5449c3b8759 --- /dev/null +++ b/jdk/test/sun/rmi/transport/proxy/DisableHttpDefaultValue.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +/* @test + * @bug 8023862 + * @summary Verify that the default value of the java.rmi.server.disableHttp + * has been changed from false to true. + * @modules java.rmi/sun.rmi.transport.proxy + * @compile -XDignore.symbol.file DisableHttpDefaultValue.java + * + * @run main/othervm DisableHttpDefaultValue true + * @run main/othervm -Djava.rmi.server.disableHttp DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=false DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=xyzzy DisableHttpDefaultValue false + * @run main/othervm -Djava.rmi.server.disableHttp=true DisableHttpDefaultValue true + */ + +import sun.rmi.transport.proxy.RMIMasterSocketFactory; + +public class DisableHttpDefaultValue { + /** + * Subclass RMIMasterSocketFactory to get access to + * protected field altFactoryList. This list has a + * zero size if proxying is disabled. + */ + static class SocketFactory extends RMIMasterSocketFactory { + boolean proxyDisabled() { + return altFactoryList.size() == 0; + } + } + + /** + * Takes a single arg, which is the expected boolean value of + * java.rmi.server.disableHttp. + */ + public static void main(String[] args) throws Exception { + // Force there to be a proxy host, so that we are able to + // tell whether proxying is enabled or disabled. + System.setProperty("http.proxyHost", "proxy.example.com"); + + String propval = System.getProperty("java.rmi.server.disableHttp"); + String propdisp = (propval == null) ? "null" : ("\"" + propval + "\""); + boolean expected = Boolean.parseBoolean(args[0]); + boolean actual = new SocketFactory().proxyDisabled(); + System.out.printf("### prop=%s exp=%s act=%s%n", propdisp, expected, actual); + if (expected != actual) + throw new AssertionError(); + } +} diff --git a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java new file mode 100644 index 00000000000..5b5691701c7 --- /dev/null +++ b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2002, 2012, 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 4290727 + * @summary Verify that ConnectException will trigger HTTP fallback if + * sun.rmi.transport.proxy.eagerHttpFallback system property is set. + * + * @library ../../../../java/rmi/testlibrary + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.tcp + * @build TestLibrary + * @run main/othervm EagerHttpFallback + */ + +import java.rmi.*; +import java.rmi.registry.*; + +public class EagerHttpFallback { + + static final int INITIAL_PORT = TestLibrary.getUnusedRandomPort(); + static final int FALLBACK_PORT = TestLibrary.getUnusedRandomPort(); + + public static void main(String[] args) throws Exception { + System.setProperty("http.proxyHost", "127.0.0.1"); + System.setProperty("http.proxyPort", Integer.toString(FALLBACK_PORT)); + System.setProperty("sun.rmi.transport.proxy.eagerHttpFallback", + "true"); + LocateRegistry.createRegistry(FALLBACK_PORT); + + /* + * The call below should trigger a ConnectException in the + * RMIMasterSocketFactory when it attempts a direct connection to + * INITIAL_PORT, which no one is listening on. Since + * eagerHttpFallback is set, this ConnectException should trigger HTTP + * fallback, which will send a call through the HTTP proxy, which is + * configured to be localhost with a port behind which a registry is + * listening--so if fallback works properly, the list() call should + * succeed. + */ + try { + LocateRegistry.getRegistry(INITIAL_PORT).list(); + } catch (Exception e) { + System.err.println( + "call on registry stub with port " + INITIAL_PORT + + "did not successfully perform HTTP fallback to " + + FALLBACK_PORT); + throw e; + } + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java new file mode 100644 index 00000000000..7de92ee2c47 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1999, 2012, 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 4203167 + * + * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it + * @author Adrian Colley + * + * @library ../../../../../java/rmi/testlibrary + * @modules java.rmi/sun.rmi.transport.proxy + * @build TestIface TestImpl TestImpl_Stub + * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest + */ + +/* This test attempts to stymie the RMI accept loop. The accept loop in + * RMI endlessly accepts a connection, spawns a thread for it, and repeats. + * The accept() call can be replaced by a user-supplied library which + * might foolishly block indefinitely in its accept() method, which would + * prevent RMI from accepting other connections on that socket. + * + * Unfortunately, HttpAwareServerSocket (default server socket) is/was such + * a foolish thing. It reads 4 bytes to see if they're "POST" before + * returning. The bug fix is to move the HTTP stuff into the mainloop, + * which has the side effect of enabling it for non-default socketfactories. + * + * This test: + * 1. Creates an object and exports it. + * 2. Connects to the listening RMI port and sends nothing, to hold it up. + * 3. Makes a regular call, using HTTP tunnelling. + * 4. Fails to deadlock, thereby passing the test. + * + * Some runtime dependencies I'm trying to eliminate: + * 1. We don't know the port number until after exporting the object, but + * have to set it in http.proxyPort somehow. Hopefully http.proxyPort + * isn't read too soon or this test will fail with a ConnectException. + */ + +import java.rmi.*; +import java.rmi.server.RMISocketFactory; +import java.io.*; +import java.net.*; + +import sun.rmi.transport.proxy.RMIMasterSocketFactory; +import sun.rmi.transport.proxy.RMIHttpToPortSocketFactory; + +public class BlockAcceptTest +{ + public static void main(String[] args) + throws Exception + { + // Make trouble for ourselves + if (System.getSecurityManager() == null) + System.setSecurityManager(new RMISecurityManager()); + + // HTTP direct to the server port + System.setProperty("http.proxyHost", "127.0.0.1"); + + // Set the socket factory. + System.err.println("(installing HTTP-out socket factory)"); + HttpOutFactory fac = new HttpOutFactory(); + RMISocketFactory.setSocketFactory(fac); + + // Create remote object + TestImpl impl = new TestImpl(); + + // Export and get which port. + System.err.println("(exporting remote object)"); + TestIface stub = impl.export(); + try { + int port = fac.whichPort(); + + // Sanity + if (port == 0) + throw new Error("TEST FAILED: export didn't reserve a port(?)"); + + // Set the HTTP port, at last. + System.setProperty("http.proxyPort", port+""); + + // Now, connect to that port + //Thread.sleep(2000); + System.err.println("(connecting to listening port on 127.0.0.1:" + + port + ")"); + Socket DoS = new Socket("127.0.0.1", port); + // we hold the connection open until done with the test. + + // The test itself: make a remote call and see if it's blocked or + // if it works + //Thread.sleep(2000); + System.err.println("(making RMI-through-HTTP call)"); + System.err.println("(typical test failure deadlocks here)"); + String result = stub.testCall("dummy load"); + + System.err.println(" => " + result); + if (!("OK".equals(result))) + throw new Error("TEST FAILED: result not OK"); + System.err.println("Test passed."); + + // Clean up, including writing a byte to that connection just in + // case an optimizer thought of optimizing it out of existence + try { + DoS.getOutputStream().write(0); + DoS.getOutputStream().close(); + } catch (Throwable apathy) { + } + + } finally { + try { + impl.unexport(); + } catch (Throwable unmatter) { + } + } + + // Should exit here + } + + private static class HttpOutFactory + extends RMISocketFactory + { + private int servport = 0; + + public Socket createSocket(String h, int p) + throws IOException + { + return ((new RMIHttpToPortSocketFactory()).createSocket(h, p)); + } + + /** Create a server socket and remember which port it's on. + * Aborts if createServerSocket(0) is called twice, because then + * it doesn't know whether to remember the first or second port. + */ + public ServerSocket createServerSocket(int p) + throws IOException + { + ServerSocket ss; + ss = (new RMIMasterSocketFactory()).createServerSocket(p); + if (p == 0) { + if (servport != 0) { + System.err.println("TEST FAILED: " + + "Duplicate createServerSocket(0)"); + throw new Error("Test aborted (createServerSocket)"); + } + servport = ss.getLocalPort(); + } + return (ss); + } + + /** Return which port was reserved by createServerSocket(0). + * If the return value was 0, createServerSocket(0) wasn't called. + */ + public int whichPort() { + return (servport); + } + } // end class HttpOutFactory +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java new file mode 100644 index 00000000000..85bab51483d --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestIface.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1999, 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.rmi.*; + +public interface TestIface + extends Remote +{ + public String testCall(String ign) + throws RemoteException; +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java new file mode 100644 index 00000000000..73601a9e3b6 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1999, 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.rmi.*; +import java.rmi.server.*; + +public class TestImpl + extends Object + implements TestIface +{ + public TestImpl() { + } + + public TestIface export() + throws RemoteException + { + return (TestIface)UnicastRemoteObject.exportObject(this); + } + + public void unexport() + throws NoSuchObjectException + { + UnicastRemoteObject.unexportObject(this, true); + } + + public String testCall(String ign) { + return ("OK"); + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java new file mode 100644 index 00000000000..2de40012e16 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/TestImpl_Stub.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 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. + */ + +// Stub class generated by rmic, do not edit. +// Contents subject to change without notice. + +public final class TestImpl_Stub + extends java.rmi.server.RemoteStub + implements TestIface +{ + private static final long serialVersionUID = 2; + + private static java.lang.reflect.Method $method_testCall_0; + + static { + try { + $method_testCall_0 = TestIface.class.getMethod("testCall", new java.lang.Class[] {java.lang.String.class}); + } catch (java.lang.NoSuchMethodException e) { + throw new java.lang.NoSuchMethodError( + "stub class initialization failed"); + } + } + + // constructors + public TestImpl_Stub(java.rmi.server.RemoteRef ref) { + super(ref); + } + + // methods from remote interfaces + + // implementation of testCall(String) + public java.lang.String testCall(java.lang.String $param_String_1) + throws java.rmi.RemoteException + { + try { + Object $result = ref.invoke(this, $method_testCall_0, new java.lang.Object[] {$param_String_1}, -4495720265115653109L); + return ((java.lang.String) $result); + } catch (java.lang.RuntimeException e) { + throw e; + } catch (java.rmi.RemoteException e) { + throw e; + } catch (java.lang.Exception e) { + throw new java.rmi.UnexpectedException("undeclared checked exception", e); + } + } +} diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy new file mode 100644 index 00000000000..a8c8d0a64d8 --- /dev/null +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/security.policy @@ -0,0 +1,10 @@ +grant { + // Take this out once we can specify -Djava.security.debug on + // the run line and figure out what else is needed + permission java.security.AllPermission; + + permission java.net.SocketPermission "*:1024-65535", "connect,listen"; + permission java.util.PropertyPermission "http.proxyHost", "write"; + permission java.util.PropertyPermission "http.proxyPort", "write"; + permission java.lang.RuntimePermission "setFactory"; +}; From 1af2806677f4cc6854607c45c7f65f3b12636411 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 26 Apr 2016 18:30:00 -0700 Subject: [PATCH 143/225] 8154556: Use java.nio.ByteOrder instead of boolean value Reviewed-by: alanb --- .../java/lang/invoke/MethodHandles.java | 68 ++++++++++--------- .../VarHandleTestAccessBoolean.java | 1 - .../VarHandles/VarHandleTestAccessByte.java | 1 - .../VarHandles/VarHandleTestAccessChar.java | 1 - .../VarHandles/VarHandleTestAccessDouble.java | 1 - .../VarHandles/VarHandleTestAccessFloat.java | 1 - .../VarHandles/VarHandleTestAccessInt.java | 1 - .../VarHandles/VarHandleTestAccessLong.java | 1 - .../VarHandles/VarHandleTestAccessShort.java | 1 - .../VarHandles/VarHandleTestAccessString.java | 1 - .../VarHandleTestByteArrayAsChar.java | 11 +-- .../VarHandleTestByteArrayAsDouble.java | 11 +-- .../VarHandleTestByteArrayAsFloat.java | 11 +-- .../VarHandleTestByteArrayAsInt.java | 15 ++-- .../VarHandleTestByteArrayAsLong.java | 11 +-- .../VarHandleTestByteArrayAsShort.java | 11 +-- ...X-VarHandleTestByteArrayView.java.template | 10 +-- 17 files changed, 81 insertions(+), 76 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 6c37371a57b..12fcecd125d 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 @@ -25,34 +25,38 @@ 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; -import java.security.AccessController; -import java.security.PrivilegedAction; - +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyAccess; import sun.invoke.util.Wrapper; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; -import java.lang.invoke.LambdaForm.BasicType; -import static java.lang.invoke.MethodHandleImpl.Intrinsic; -import static java.lang.invoke.MethodHandleNatives.Constants.*; +import java.lang.invoke.LambdaForm.BasicType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ReflectPermission; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Opcodes; - +import static java.lang.invoke.MethodHandleImpl.Intrinsic; +import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; import static java.lang.invoke.MethodType.methodType; @@ -2337,13 +2341,12 @@ return mh1; * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code byte} array, is big endian, otherwise - * little endian + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code byte} array * @return a VarHandle giving access to elements of a {@code byte[]} array * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2351,8 +2354,10 @@ return mh1; */ public static VarHandle byteArrayViewVarHandle(Class viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.byteArrayViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } /** @@ -2422,14 +2427,13 @@ return mh1; * * @param viewArrayClass the view array class, with a component type of * type {@code T} - * @param bigEndian true if the endianness of the view array elements, as - * stored in the underlying {@code ByteBuffer}, is big endian, otherwise - * little endian (Note this overrides the endianness of a - * {@code ByteBuffer}) + * @param byteOrder the endianness of the view array elements, as + * stored in the underlying {@code ByteBuffer} (Note this overrides the + * endianness of a {@code ByteBuffer}) * @return a VarHandle giving access to elements of a {@code ByteBuffer} * viewed as if elements corresponding to the components type of the view * array class - * @throws NullPointerException if viewArrayClass is null + * @throws NullPointerException if viewArrayClass or byteOrder is null * @throws IllegalArgumentException if viewArrayClass is not an array type * @throws UnsupportedOperationException if the component type of * viewArrayClass is not supported as a variable type @@ -2437,8 +2441,10 @@ return mh1; */ public static VarHandle byteBufferViewVarHandle(Class viewArrayClass, - boolean bigEndian) throws IllegalArgumentException { - return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian); + ByteOrder byteOrder) throws IllegalArgumentException { + Objects.requireNonNull(byteOrder); + return VarHandles.makeByteBufferViewHandle(viewArrayClass, + byteOrder == ByteOrder.BIG_ENDIAN); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index 5590984e493..b22fc3e182a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index f9c9d4fc31e..088a519e920 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index bd1174efc5a..18ff6542615 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index d8732d239b4..36c84e2f753 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 9976102d027..2ea2d9617be 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index c78e5cb7199..0c3d8d5c841 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index f82ee67960e..a034a536468 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index d235e03a7bf..4ff25cc4a5f 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 61e3690447c..4272c898a4c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index e6941f5fa3c..c46720b738a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsChar * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsChar @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(char[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(char[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(char[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(char[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index ec4b843b2aa..9cee7930dee 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsDouble * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsDouble @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(double[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(double[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(double[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(double[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index 57d37cbe523..e366e84c239 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsFloat * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsFloat @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(float[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(float[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(float[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(float[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index ae66477d3b6..2831fa63210 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsInt * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsInt @@ -37,10 +38,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.List; -import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { static final int SIZE = Integer.BYTES; @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(int[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(int[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(int[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(int[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index ac08db2af5c..263245a5e72 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsLong * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsLong @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(long[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(long[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(long[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(long[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 9742fbd2522..3d6078e6056 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsShort * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsShort @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle(short[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle(short[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle(short[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle(short[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } @@ -93,7 +95,6 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 1c323e2f195..4cdf45bad80 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -23,6 +23,7 @@ /* * @test + * @bug 8154556 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$ * @run testng/othervm -Diters=20000 VarHandleTestByteArrayAs$Type$ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAs$Type$ @@ -57,15 +58,16 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { // Combinations of VarHandle byte[] or ByteBuffer vhss = new ArrayList<>(); for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) { + + ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN + ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; VarHandleSource aeh = new VarHandleSource( - MethodHandles.byteArrayViewVarHandle($type$[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteArrayViewVarHandle($type$[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(aeh); VarHandleSource bbh = new VarHandleSource( - MethodHandles.byteBufferViewVarHandle($type$[].class, - endianess == MemoryMode.BIG_ENDIAN), + MethodHandles.byteBufferViewVarHandle($type$[].class, bo), endianess, MemoryMode.READ_WRITE); vhss.add(bbh); } From 27f82bea87acd8eab8235837c0e2512291fab590 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 26 Apr 2016 18:42:51 -0700 Subject: [PATCH 144/225] 8154447: Exempt classes under java.util.concurrent from MH.Lookup restrictions Reviewed-by: mchung, martin --- .../java/lang/invoke/MethodHandles.java | 9 ++-- .../invoke/JavaUtilConcurrentLookupTest.java | 46 +++++++++++++++++++ .../java/util/concurrent/LookupTester.java | 37 +++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java create mode 100644 jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java 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 12fcecd125d..afe6aecc9f4 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 @@ -745,10 +745,13 @@ public class MethodHandles { if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); - // For caller-sensitive MethodHandles.lookup() - // disallow lookup more restricted packages + // For caller-sensitive MethodHandles.lookup() disallow lookup from + // restricted packages. This a fragile and blunt approach. + // TODO replace with a more formal and less fragile mechanism + // that does not bluntly restrict classes under packages within + // java.base from looking up MethodHandles or VarHandles. if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { - if (name.startsWith("java.") || + if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) || (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); } diff --git a/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java b/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java new file mode 100644 index 00000000000..9715de8fd46 --- /dev/null +++ b/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary Tests that Lookup can be produced from classes under java.util.concurrent + * @bug 8154447 + * @compile/module=java.base java/util/concurrent/LookupTester.java + * @run testng/othervm JavaUtilConcurrentLookupTest + */ + +import org.testng.annotations.Test; + +import java.util.concurrent.LookupTester; + +public class JavaUtilConcurrentLookupTest { + + @Test + public void testLookup() { + LookupTester.getLookup(); + } + + @Test + public void testLookupIn() { + LookupTester.getLookupIn(); + } +} diff --git a/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java b/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java new file mode 100644 index 00000000000..2198495fcac --- /dev/null +++ b/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.concurrent; + +import java.lang.invoke.MethodHandles; + +public class LookupTester { + public static MethodHandles.Lookup getLookup() { + return MethodHandles.lookup(); + } + + + public static MethodHandles.Lookup getLookupIn() { + return MethodHandles.lookup().in(ConcurrentHashMap.class); + } +} From 75b0c4fb9ccda0e42acfc363fd8d2d850b52cf59 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 27 Apr 2016 09:13:51 +0200 Subject: [PATCH 145/225] 8155156: Remove remaining sun.misc.* imports from the jdk repo Reviewed-by: chegar --- .../share/classes/sun/nio/ch/AbstractPollSelectorImpl.java | 3 +-- .../java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java | 3 +-- jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java index 6f1f8e86f04..81fa9836a87 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java @@ -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 @@ -29,7 +29,6 @@ import java.io.IOException; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /** diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java b/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java index 1911c3507c0..27c7a41937e 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, 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 @@ -29,7 +29,6 @@ import java.io.IOException; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; -import sun.misc.*; /** 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 aa460f9f636..9ff2d7ce598 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 @@ -52,7 +52,6 @@ import sun.awt.*; import sun.awt.datatransfer.DataTransferer; import sun.font.FontConfigManager; import sun.java2d.SunGraphicsEnvironment; -import sun.misc.*; import sun.awt.util.PerformanceLogger; import sun.awt.util.ThreadGroupUtils; import sun.print.PrintJob2D; From 59144619a147605a4091b5d23ff96d9e113b0761 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 27 Apr 2016 14:30:32 +0200 Subject: [PATCH 146/225] 8154841: Let different Jib profiles have different default make targets Reviewed-by: dholmes, tbell --- common/conf/jib-profiles.js | 88 +++++++++++++++++++++++++++---------- make/Init.gmk | 7 ++- make/Jprt.gmk | 4 +- make/Main.gmk | 10 +++-- 4 files changed, 79 insertions(+), 30 deletions(-) diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 9ca454e51d1..39196ac553a 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -212,14 +212,17 @@ var getJibProfiles = function (input) { * @returns Common values */ var getJibProfilesCommon = function (input) { - var common = { - dependencies: ["boot_jdk", "gnumake", "jtreg"], - configure_args: ["--with-default-make-target=all", "--enable-jtreg-failure-handler"], - configure_args_32bit: ["--with-target-bits=32", "--with-jvm-variants=client,server"], - configure_args_debug: ["--enable-debug"], - configure_args_slowdebug: ["--with-debug-level=slowdebug"], - organization: "jpg.infra.builddeps" - }; + var common = {}; + + common.dependencies = ["boot_jdk", "gnumake", "jtreg"], + common.default_make_targets = ["product-images", "test-image"], + common.default_make_targets_debug = common.default_make_targets; + common.default_make_targets_slowdebug = common.default_make_targets; + common.configure_args = ["--enable-jtreg-failure-handler"], + common.configure_args_32bit = ["--with-target-bits=32", "--with-jvm-variants=client,server"], + common.configure_args_debug = ["--enable-debug"], + common.configure_args_slowdebug = ["--with-debug-level=slowdebug"], + common.organization = "jpg.infra.builddeps" return common; }; @@ -241,8 +244,8 @@ 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"), - make_args: common.make_args + configure_args: concat(common.configure_args, "--with-zlib=system"), + default_make_targets: concat(common.default_make_targets, "docs-image") }, "linux-x86": { @@ -252,39 +255,39 @@ var getJibProfilesProfiles = function (input, common) { dependencies: concat(common.dependencies, "devkit"), configure_args: concat(common.configure_args, common.configure_args_32bit, "--with-zlib=system"), - make_args: common.make_args + default_make_targets: common.default_make_targets }, "macosx-x64": { target_os: "macosx", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), - make_args: common.make_args + configure_args: concat(common.configure_args, "--with-zlib=system"), + default_make_targets: common.default_make_targets }, "solaris-x64": { target_os: "solaris", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), - make_args: common.make_args + configure_args: concat(common.configure_args, "--with-zlib=system"), + default_make_targets: common.default_make_targets }, "solaris-sparcv9": { target_os: "solaris", target_cpu: "sparcv9", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), - make_args: common.make_args + configure_args: concat(common.configure_args, "--with-zlib=system"), + default_make_targets: common.default_make_targets }, "windows-x64": { target_os: "windows", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "freetype"), - configure_args: common.configure_args, - make_args: common.make_args + configure_args: concat(common.configure_args), + default_make_targets: common.default_make_targets }, "windows-x86": { @@ -293,7 +296,7 @@ var getJibProfilesProfiles = function (input, common) { build_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "freetype"), configure_args: concat(common.configure_args, common.configure_args_32bit), - make_args: common.make_args + default_make_targets: common.default_make_targets } }; profiles = concatObjects(profiles, mainProfiles); @@ -306,14 +309,15 @@ var getJibProfilesProfiles = function (input, common) { // implementation builds. var openOnlyProfiles = generateOpenOnlyProfiles(common, mainProfiles); // The open only profiles on linux are used for reference builds and should - // produce the compact profile images by default. + // produce the compact profile images by default. This adds "profiles" as an + // extra default target. var openOnlyProfilesExtra = { "linux-x64-open": { - configure_args: ["--with-default-make-target=all profiles"], + default_make_targets: "profiles" }, "linux-x86-open": { - configure_args: ["--with-default-make-target=all profiles"], + default_make_targets: "profiles" } }; var openOnlyProfiles = concatObjects(openOnlyProfiles, openOnlyProfilesExtra); @@ -336,6 +340,7 @@ var getJibProfilesProfiles = function (input, common) { // Generate the missing platform attributes profiles = generatePlatformAttributes(profiles); + profiles = generateDefaultMakeTargetsConfigureArg(common, profiles); return profiles; }; @@ -469,6 +474,8 @@ var generateDebugProfiles = function (common, profiles) { var debugProfile = profile + "-debug"; newProfiles[debugProfile] = clone(profiles[profile]); newProfiles[debugProfile].debug_level = "fastdebug"; + newProfiles[debugProfile].default_make_targets + = common.default_make_targets_debug; newProfiles[debugProfile].labels = concat(newProfiles[debugProfile].labels || [], "debug"), newProfiles[debugProfile].configure_args @@ -492,6 +499,8 @@ var generateSlowdebugProfiles = function (common, profiles) { var debugProfile = profile + "-slowdebug"; newProfiles[debugProfile] = clone(profiles[profile]); newProfiles[debugProfile].debug_level = "slowdebug"; + newProfiles[debugProfile].default_make_targets + = common.default_make_targets_slowdebug; newProfiles[debugProfile].labels = concat(newProfiles[debugProfile].labels || [], "slowdebug"), newProfiles[debugProfile].configure_args @@ -523,6 +532,39 @@ var generateOpenOnlyProfiles = function (common, profiles) { return newProfiles; }; +/** + * The default_make_targets attribute on a profile is not a real Jib attribute. + * This function rewrites that attribute into the corresponding configure arg. + * Calling this function multiple times on the same profiles object is safe. + * + * @param common Common values + * @param profiles Profiles map to rewrite profiles for + * @returns {{}} New map of profiles with the make targets converted + */ +var generateDefaultMakeTargetsConfigureArg = function (common, profiles) { + var ret = concatObjects(profiles, {}); + for (var profile in ret) { + if (ret[profile]["default_make_targets"] != null) { + var targetsString = concat(ret[profile].default_make_targets).join(" "); + // Iterate over all configure args and see if --with-default-make-target + // is already there and change it, otherwise add it. + var found = false; + for (var arg in ret[profile].configure_args) { + if (arg.startsWith("--with-default-make-target")) { + found = true; + arg.replace(/=.*/, "=" + targetsString); + } + } + if (!found) { + ret[profile].configure_args = concat( + ret[profile].configure_args, + "--with-default-make-target=" + targetsString); + } + } + } + return ret; +} + /** * Deep clones an object tree. * diff --git a/make/Init.gmk b/make/Init.gmk index ee67aeaa65f..6ed612b28a2 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -268,8 +268,13 @@ else # HAS_SPEC=true ############################################################################## MAIN_TARGETS := $(SEQUENTIAL_TARGETS) $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) + # If building the default target, add what they are to the description. + DESCRIPTION_TARGETS := $(strip $(MAIN_TARGETS)) + ifeq ($(DESCRIPTION_TARGETS), default) + DESCRIPTION_TARGETS += ($(DEFAULT_MAKE_TARGET)) + endif TARGET_DESCRIPTION := target$(if $(word 2, $(MAIN_TARGETS)),s) \ - '$(strip $(MAIN_TARGETS))' in configuration '$(CONF_NAME)' + '$(strip $(DESCRIPTION_TARGETS))' in configuration '$(CONF_NAME)' # MAKEOVERRIDES is automatically set and propagated by Make to sub-Make calls. # We need to clear it of the init-specific variables. The user-specified diff --git a/make/Jprt.gmk b/make/Jprt.gmk index e7eba24bd31..e82b84d5e11 100644 --- a/make/Jprt.gmk +++ b/make/Jprt.gmk @@ -108,8 +108,8 @@ SRC_JDK_MACOSX_BUNDLE_DIR := $(JDK_MACOSX_BUNDLE_DIR) SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR) # Bundle up the images -JPRT_TARGET ?= all -ifeq ($(JPRT_TARGET), all) +JPRT_TARGET ?= default +ifeq ($(JPRT_TARGET), default) bundles: $(JPRT_TARGET) @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles diff --git a/make/Main.gmk b/make/Main.gmk index a693465ec4d..3d596817c08 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -340,10 +340,10 @@ docs-javadoc: docs-jvmtidoc: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk jvmtidocs) -zip-docs: docs-javadoc docs-jvmtidoc +zip-docs: +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk zip-docs) -ALL_TARGETS += docs-javadoc docs-jvmtidoc +ALL_TARGETS += docs-javadoc docs-jvmtidoc zip-docs ################################################################################ # Cross compilation support @@ -602,6 +602,8 @@ else docs-jvmtidoc: hotspot + zip-docs: docs-javadoc docs-jvmtidoc + test: jimages test-image create-buildjdk-copy: jdk.jlink-java java.base-gendata @@ -703,7 +705,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) endif # This target builds the documentation image -docs-image: zip-docs +docs-image: docs-javadoc docs-jvmtidoc # This target builds the test image test-image: prepare-test-image test-image-hotspot-jtreg-native \ @@ -727,7 +729,7 @@ images: product-images docs: docs-image all: all-images -ALL_TARGETS += default jdk images docs all zip-docs +ALL_TARGETS += default jdk images docs all ################################################################################ ################################################################################ From fe4860fe5e30b4db33ad51861b1a3c7e79a78307 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 27 Apr 2016 15:01:21 +0200 Subject: [PATCH 147/225] 8155214: java/lang/invoke/PermuteArgsTest.java fails due to exhausted code cache Reviewed-by: sundar --- jdk/test/java/lang/invoke/PermuteArgsTest.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/invoke/PermuteArgsTest.java b/jdk/test/java/lang/invoke/PermuteArgsTest.java index edb9ba33bc7..a47e4d7fc54 100644 --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, 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 @@ -23,6 +23,7 @@ /* @test * @summary unit tests for method handles which permute their arguments + * @library /lib/testlibrary/jsr292 /lib/testlibrary * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest */ /* Examples of manual runs: @@ -36,6 +37,8 @@ package test.java.lang.invoke; import org.testng.*; import org.testng.annotations.*; +import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor; + import java.util.*; import java.lang.reflect.*; @@ -122,9 +125,15 @@ public class PermuteArgsTest { } new PermuteArgsTest().test(); } + static int testCases; + @Test public void test() throws Throwable { + CodeCacheOverflowProcessor.runMHTest(this::test0); + } + + public void test0() throws Throwable { testCases = 0; Lookup lookup = lookup(); for (Method m : lookup.lookupClass().getDeclaredMethods()) { From 5881148f01f2a5b97c5d475ca08d746812c990e7 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 27 Apr 2016 15:50:33 +0200 Subject: [PATCH 148/225] 8134503: support ES6 parsing in Nashorn Reviewed-by: jlaskey, sundar, mhaupt --- .../internal/codegen/CodeGenerator.java | 2 +- .../internal/codegen/CompilationPhase.java | 4 +- .../internal/codegen/SplitIntoFunctions.java | 4 +- .../nashorn/internal/codegen/WeighNodes.java | 2 +- .../jdk/nashorn/internal/ir/AccessNode.java | 25 +- .../jdk/nashorn/internal/ir/BaseNode.java | 24 +- .../jdk/nashorn/internal/ir/Block.java | 50 +- .../jdk/nashorn/internal/ir/ClassNode.java | 147 + .../nashorn/internal/ir/ExpressionList.java | 87 + .../jdk/nashorn/internal/ir/ForNode.java | 1 - .../jdk/nashorn/internal/ir/FunctionNode.java | 264 +- .../jdk/nashorn/internal/ir/IdentNode.java | 95 + .../jdk/nashorn/internal/ir/IndexNode.java | 25 +- .../jdk/nashorn/internal/ir/Module.java | 338 +++ .../jdk/nashorn/internal/ir/PropertyNode.java | 54 +- .../ir/visitor/NodeOperatorVisitor.java | 16 +- .../internal/ir/visitor/NodeVisitor.java | 19 + .../jdk/nashorn/internal/parser/Parser.java | 2425 +++++++++++++++-- .../internal/parser/ParserContext.java | 7 +- .../parser/ParserContextFunctionNode.java | 84 +- .../parser/ParserContextModuleNode.java | 90 + .../nashorn/internal/parser/TokenType.java | 9 +- .../jdk/nashorn/internal/runtime/Context.java | 4 +- .../runtime/resources/Messages.properties | 21 + .../classes/jdk/nashorn/tools/Shell.java | 3 + .../basic/{yield.js => es6/parser-es6.js} | 80 +- ...function_mult_params_in_strict.js.EXPECTED | 4 +- .../script/nosecurity/parserapi.js.EXPECTED | 22 +- .../nosecurity/parserapi_strict.js.EXPECTED | 4 +- .../treeapi/array_literal.js.EXPECTED | 2 +- .../treeapi/objectLiteral.js.EXPECTED | 10 +- .../nosecurity/treeapi/property.js.EXPECTED | 8 +- .../nosecurity/treeapi/throw.js.EXPECTED | 2 +- .../nosecurity/treeapi/with.js.EXPECTED | 2 +- .../test/framework/ScriptRunnable.java | 4 +- 35 files changed, 3524 insertions(+), 414 deletions(-) create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java rename nashorn/test/script/basic/{yield.js => es6/parser-es6.js} (50%) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java index 3a60ed5f6a8..f784b74ca5f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -4310,7 +4310,7 @@ final class CodeGenerator extends NodeOperatorVisitor { // we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE. FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT, body, - null + null, + originalFn.getModule(), + originalFn.getDebugFlags() ) .setCompileUnit(lc, splitNode.getCompileUnit()); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java index 494afb4d8d7..488beb29a81 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java @@ -435,7 +435,7 @@ final class WeighNodes extends NodeOperatorVisitor { } @Override - public Node leaveBIND(final BinaryNode binaryNode) { + public Node leaveARROW(final BinaryNode binaryNode) { return binaryNodeWeight(binaryNode); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java index 315ee395b92..d490bbbfcd0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -48,12 +48,13 @@ public final class AccessNode extends BaseNode { * @param property property */ public AccessNode(final long token, final int finish, final Expression base, final String property) { - super(token, finish, base, false); + super(token, finish, base, false, false); this.property = property; } - private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) { - super(accessNode, base, isFunction, type, id); + private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, + final Type type, final int id, final boolean isSuper) { + super(accessNode, base, isFunction, type, id, isSuper); this.property = property; } @@ -105,7 +106,7 @@ public final class AccessNode extends BaseNode { if (this.base == base) { return this; } - return new AccessNode(this, base, property, isFunction(), type, programPoint); + return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper()); } @Override @@ -113,7 +114,7 @@ public final class AccessNode extends BaseNode { if (this.type == type) { return this; } - return new AccessNode(this, base, property, isFunction(), type, programPoint); + return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper()); } @Override @@ -121,7 +122,7 @@ public final class AccessNode extends BaseNode { if (this.programPoint == programPoint) { return this; } - return new AccessNode(this, base, property, isFunction(), type, programPoint); + return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper()); } @Override @@ -129,6 +130,14 @@ public final class AccessNode extends BaseNode { if (isFunction()) { return this; } - return new AccessNode(this, base, property, true, type, programPoint); + return new AccessNode(this, base, property, true, type, programPoint, isSuper()); + } + + @Override + public AccessNode setIsSuper() { + if (isSuper()) { + return this; + } + return new AccessNode(this, base, property, isFunction(), type, programPoint, true); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java index 4e59753a5c3..85ded3e92c2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java @@ -52,6 +52,9 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim /** Program point id */ protected final int programPoint; + /** Super property access. */ + private final boolean isSuper; + /** * Constructor * @@ -59,13 +62,15 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim * @param finish finish * @param base base node * @param isFunction is this a function + * @param isSuper is this a super property access */ - public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) { + public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean isSuper) { super(token, base.getStart(), finish); this.base = base; this.isFunction = isFunction; this.type = null; this.programPoint = INVALID_PROGRAM_POINT; + this.isSuper = isSuper; } /** @@ -75,13 +80,15 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim * @param isFunction is this a function * @param callSiteType the callsite type for this base node, either optimistic or conservative * @param programPoint program point id + * @param isSuper is this a super property access */ - protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) { + protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint, final boolean isSuper) { super(baseNode); this.base = base; this.isFunction = isFunction; this.type = callSiteType; this.programPoint = programPoint; + this.isSuper = isSuper; } /** @@ -136,4 +143,17 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim */ public abstract BaseNode setIsFunction(); + /** + * @return {@code true} if a SuperProperty access. + */ + public boolean isSuper() { + return isSuper; + } + + /** + * Mark this node as being a SuperProperty access. + * + * @return a base node identical to this one in all aspects except with its super flag set. + */ + public abstract BaseNode setIsSuper(); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java index cbc0e480bf7..152269f8f0d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java @@ -65,24 +65,39 @@ public class Block extends Node implements BreakableNode, Terminal, Flags private final LocalVariableConversion conversion; /** Flag indicating that this block needs scope */ - public static final int NEEDS_SCOPE = 1 << 0; + public static final int NEEDS_SCOPE = 1 << 0; /** * Is this block tagged as terminal based on its contents * (usually the last statement) */ - public static final int IS_TERMINAL = 1 << 2; + public static final int IS_TERMINAL = 1 << 2; /** * Is this block the eager global scope - i.e. the original program. This isn't true for the * outermost level of recompiles */ - public static final int IS_GLOBAL_SCOPE = 1 << 3; + public static final int IS_GLOBAL_SCOPE = 1 << 3; /** * Is this block a synthetic one introduced by Parser? */ - public static final int IS_SYNTHETIC = 1 << 4; + public static final int IS_SYNTHETIC = 1 << 4; + + /** + * Is this the function body block? May not be the first, if parameter list contains expressions. + */ + public static final int IS_BODY = 1 << 5; + + /** + * Is this the parameter initialization block? If present, must be the first block, immediately wrapping the function body block. + */ + public static final int IS_PARAMETER_BLOCK = 1 << 6; + + /** + * Marks the variable declaration block for case clauses of a switch statement. + */ + public static final int IS_SWITCH_BLOCK = 1 << 7; /** * Constructor @@ -489,4 +504,31 @@ public class Block extends Node implements BreakableNode, Terminal, Flags public Node accept(final NodeVisitor visitor) { return Acceptor.accept(this, visitor); } + + /** + * Checks if this is a function body. + * + * @return true if the function body flag is set + */ + public boolean isFunctionBody() { + return getFlag(IS_BODY); + } + + /** + * Checks if this is a parameter block. + * + * @return true if the parameter block flag is set + */ + public boolean isParameterBlock() { + return getFlag(IS_PARAMETER_BLOCK); + } + + /** + * Checks whether this is a switch block. + * + * @return true if this is a switch block + */ + public boolean isSwitchBlock() { + return getFlag(IS_SWITCH_BLOCK); + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java new file mode 100644 index 00000000000..4c0c6ffb175 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java @@ -0,0 +1,147 @@ +/* + * 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 jdk.nashorn.internal.ir; + +import java.util.Collections; +import java.util.List; + +import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; + +/** + * IR representation for class definitions. + */ +public class ClassNode extends Expression { + private static final long serialVersionUID = 1L; + + private final IdentNode ident; + private final Expression classHeritage; + private final PropertyNode constructor; + private final List classElements; + private final int line; + + /** + * Constructor. + * + * @param line line number + * @param token token + * @param finish finish + * @param ident ident + * @param classHeritage class heritage + * @param constructor constructor + * @param classElements class elements + */ + public ClassNode(final int line, final long token, final int finish, final IdentNode ident, final Expression classHeritage, final PropertyNode constructor, + final List classElements) { + super(token, finish); + this.line = line; + this.ident = ident; + this.classHeritage = classHeritage; + this.constructor = constructor; + this.classElements = classElements; + } + + /** + * Class identifier. Optional. + * + * @return the class identifier + */ + public IdentNode getIdent() { + return ident; + } + + /** + * The expression of the {@code extends} clause. Optional. + * + * @return the class heritage + */ + public Expression getClassHeritage() { + return classHeritage; + } + + /** + * Get the constructor method definition. + * + * @return the constructor + */ + public PropertyNode getConstructor() { + return constructor; + } + + /** + * Get method definitions except the constructor. + * + * @return the class elements + */ + public List getClassElements() { + return Collections.unmodifiableList(classElements); + } + + /** + * Returns the line number. + * + * @return the line number + */ + public int getLineNumber() { + return line; + } + + @Override + public Type getType() { + return Type.OBJECT; + } + + @Override + public Node accept(final NodeVisitor visitor) { + if (visitor.enterClassNode(this)) { + return visitor.leaveClassNode(this); + } + + return this; + } + + @Override + public void toString(final StringBuilder sb, final boolean printType) { + sb.append("class"); + if (ident != null) { + sb.append(' '); + ident.toString(sb, printType); + } + if (classHeritage != null) { + sb.append(" extends"); + classHeritage.toString(sb, printType); + } + sb.append(" {"); + if (constructor != null) { + constructor.toString(sb, printType); + } + for (final PropertyNode classElement : classElements) { + sb.append(" "); + classElement.toString(sb, printType); + } + sb.append("}"); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java new file mode 100644 index 00000000000..9410a90ed42 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java @@ -0,0 +1,87 @@ +/* + * 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 jdk.nashorn.internal.ir; + +import java.util.Collections; +import java.util.List; + +import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; + +/** + * IR for CoverParenthesizedExpressionAndArrowParameterList, used only during parsing. + */ +public final class ExpressionList extends Expression { + private static final long serialVersionUID = 1L; + + private final List expressions; + + /** + * Constructor. + * + * @param token token + * @param finish finish + * @param expressions expression + */ + public ExpressionList(final long token, final int finish, final List expressions) { + super(token, finish); + this.expressions = expressions; + } + + /** + * Get the list of expressions. + * + * @return the list of expressions + */ + public List getExpressions() { + return Collections.unmodifiableList(expressions); + } + + @Override + public Node accept(final NodeVisitor visitor) { + throw new UnsupportedOperationException(); + } + + @Override + public Type getType() { + return null; + } + + @Override + public void toString(StringBuilder sb, boolean printType) { + sb.append("("); + boolean first = true; + for (Expression expression : expressions) { + if (first) { + first = false; + } else { + sb.append(", "); + } + expression.toString(sb, printType); + } + sb.append(")"); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java index 0913b9e64f0..df104340aed 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java @@ -90,7 +90,6 @@ public final class ForNode extends LoopNode { this.init = init; this.modify = modify; this.iterator = null; - } private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test, diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java index ab40c04d3b6..8eda934b542 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java @@ -69,7 +69,13 @@ public final class FunctionNode extends LexicalContextExpression implements Flag /** a getter, @see {@link UserAccessorProperty} */ GETTER, /** a setter, @see {@link UserAccessorProperty} */ - SETTER + SETTER, + /** an arrow function */ + ARROW, + /** a generator function */ + GENERATOR, + /** a module function */ + MODULE } /** Source of entity. */ @@ -122,6 +128,12 @@ public final class FunctionNode extends LexicalContextExpression implements Flag /** Root class for function */ private final Class rootClass; + /** The ES6 module */ + private final Module module; + + /** The debug flags */ + private final int debugFlags; + /** Is anonymous function flag. */ public static final int IS_ANONYMOUS = 1 << 0; @@ -172,49 +184,21 @@ public final class FunctionNode extends LexicalContextExpression implements Flag /** * Is this function the top-level program? */ - public static final int IS_PROGRAM = 1 << 13; + public static final int IS_PROGRAM = 1 << 13; /** * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will * use the symbol in their parent scope instead when they reference themselves by name. */ - public static final int USES_SELF_SYMBOL = 1 << 14; + public static final int USES_SELF_SYMBOL = 1 << 14; /** Does this function use the "this" keyword? */ - public static final int USES_THIS = 1 << 15; + public static final int USES_THIS = 1 << 15; /** Is this declared in a dynamic context */ - public static final int IN_DYNAMIC_CONTEXT = 1 << 16; + public static final int IN_DYNAMIC_CONTEXT = 1 << 16; - /** - * The following flags are derived from directive comments within this function. - * Note that even IS_STRICT is one such flag but that requires special handling. - */ - - /** parser, print parse tree */ - public static final int IS_PRINT_PARSE = 1 << 17; - /** parser, print lower parse tree */ - public static final int IS_PRINT_LOWER_PARSE = 1 << 18; - /** parser, print AST */ - public static final int IS_PRINT_AST = 1 << 19; - /** parser, print lower AST */ - public static final int IS_PRINT_LOWER_AST = 1 << 20; - /** parser, print symbols */ - public static final int IS_PRINT_SYMBOLS = 1 << 21; - - // callsite tracing, profiling within this function - /** profile callsites in this function? */ - public static final int IS_PROFILE = 1 << 22; - - /** trace callsite enterexit in this function? */ - public static final int IS_TRACE_ENTEREXIT = 1 << 23; - - /** trace callsite misses in this function? */ - public static final int IS_TRACE_MISSES = 1 << 24; - - /** trace callsite values in this function? */ - public static final int IS_TRACE_VALUES = 1 << 25; /** * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a @@ -222,18 +206,41 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData} * will, however, cache the value of this flag. */ - public static final int NEEDS_CALLEE = 1 << 26; + public static final int NEEDS_CALLEE = 1 << 17; /** * Is the function node cached? */ - public static final int IS_CACHED = 1 << 27; + public static final int IS_CACHED = 1 << 18; - /** extension callsite flags mask */ - public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | - IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | - IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT | - IS_TRACE_MISSES | IS_TRACE_VALUES; + /** + * Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper) + */ + public static final int ES6_HAS_DIRECT_SUPER = 1 << 19; + + /** + * Does this function use the super binding? + */ + public static final int ES6_USES_SUPER = 1 << 20; + + /** + * Is this function a (class or object) method? + */ + public static final int ES6_IS_METHOD = 1 << 21; + + /** + * Is this the constructor method? + */ + public static final int ES6_IS_CLASS_CONSTRUCTOR = 1 << 22; + + /** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */ + public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23; + + /** is this a strong mode function? */ + public static final int ES6_IS_STRONG = 1 << 24; + + /** Does this function use new.target? */ + public static final int ES6_USES_NEW_TARGET = 1 << 25; /** Does this function or any nested functions contain an eval? */ private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL; @@ -247,8 +254,44 @@ public final class FunctionNode extends LexicalContextExpression implements Flag /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */ public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM; + + /** + * The following flags are derived from directive comments within this function. + * Note that even IS_STRICT is one such flag but that requires special handling. + */ + + /** parser, print parse tree */ + public static final int DEBUG_PRINT_PARSE = 1 << 0; + /** parser, print lower parse tree */ + public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1; + /** parser, print AST */ + public static final int DEBUG_PRINT_AST = 1 << 2; + /** parser, print lower AST */ + public static final int DEBUG_PRINT_LOWER_AST = 1 << 3; + /** parser, print symbols */ + public static final int DEBUG_PRINT_SYMBOLS = 1 << 4; + + // callsite tracing, profiling within this function + /** profile callsites in this function? */ + public static final int DEBUG_PROFILE = 1 << 5; + + /** trace callsite enterexit in this function? */ + public static final int DEBUG_TRACE_ENTEREXIT = 1 << 6; + + /** trace callsite misses in this function? */ + public static final int DEBUG_TRACE_MISSES = 1 << 7; + + /** trace callsite values in this function? */ + public static final int DEBUG_TRACE_VALUES = 1 << 8; + + /** extension callsite flags mask */ + public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE | + DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST | + DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT | + DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES; + /** What is the return type of this function? */ - private Type returnType = Type.UNKNOWN; + public Type returnType = Type.UNKNOWN; /** * Constructor @@ -267,6 +310,8 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * @param flags initial flags * @param body body of the function * @param endParserState The parser state at the end of the parsing. + * @param module the module + * @param debugFlags the debug flags */ public FunctionNode( final Source source, @@ -282,7 +327,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag final FunctionNode.Kind kind, final int flags, final Block body, - final Object endParserState) { + final Object endParserState, + final Module module, + final int debugFlags) { super(token, finish); this.source = source; @@ -299,7 +346,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag this.body = body; this.thisProperties = 0; this.rootClass = null; - this.endParserState = endParserState; + this.endParserState = endParserState; + this.module = module; + this.debugFlags = debugFlags; } private FunctionNode( @@ -335,6 +384,8 @@ public final class FunctionNode extends LexicalContextExpression implements Flag this.ident = functionNode.ident; this.kind = functionNode.kind; this.firstToken = functionNode.firstToken; + this.module = functionNode.module; + this.debugFlags = functionNode.debugFlags; } @Override @@ -366,23 +417,23 @@ public final class FunctionNode extends LexicalContextExpression implements Flag } // quick check for extension callsite flags turned on by directives. - if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) { + if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) { return callsiteFlags; } - if (getFlag(IS_PROFILE)) { + if (getDebugFlag(DEBUG_PROFILE)) { callsiteFlags |= CALLSITE_PROFILE; } - if (getFlag(IS_TRACE_MISSES)) { + if (getDebugFlag(DEBUG_TRACE_MISSES)) { callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES; } - if (getFlag(IS_TRACE_VALUES)) { + if (getDebugFlag(DEBUG_TRACE_VALUES)) { callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES; } - if (getFlag(IS_TRACE_ENTEREXIT)) { + if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) { callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT; } @@ -466,23 +517,23 @@ public final class FunctionNode extends LexicalContextExpression implements Flag public static int getDirectiveFlag(final String directive) { switch (directive) { case "nashorn callsite trace enterexit": - return IS_TRACE_ENTEREXIT; + return DEBUG_TRACE_ENTEREXIT; case "nashorn callsite trace misses": - return IS_TRACE_MISSES; + return DEBUG_TRACE_MISSES; case "nashorn callsite trace objects": - return IS_TRACE_VALUES; + return DEBUG_TRACE_VALUES; case "nashorn callsite profile": - return IS_PROFILE; + return DEBUG_PROFILE; case "nashorn print parse": - return IS_PRINT_PARSE; + return DEBUG_PRINT_PARSE; case "nashorn print lower parse": - return IS_PRINT_LOWER_PARSE; + return DEBUG_PRINT_LOWER_PARSE; case "nashorn print ast": - return IS_PRINT_AST; + return DEBUG_PRINT_AST; case "nashorn print lower ast": - return IS_PRINT_LOWER_AST; + return DEBUG_PRINT_LOWER_AST; case "nashorn print symbols": - return IS_PRINT_SYMBOLS; + return DEBUG_PRINT_SYMBOLS; default: // unknown/unsupported directive return 0; @@ -578,6 +629,25 @@ public final class FunctionNode extends LexicalContextExpression implements Flag return setFlags(lc, flags | flag); } + /** + * Returns the debug flags for this function. + * + * @return the debug flags + */ + public int getDebugFlags() { + return debugFlags; + } + + /** + * Checks whether a debug flag is set for this function. + * + * @param debugFlag the debug flag + * @return true if the flag is set + */ + public boolean getDebugFlag(final int debugFlag) { + return (debugFlags & debugFlag) != 0; + } + /** * Returns true if the function is the top-level program. * @return True if this function node represents the top-level program. @@ -1065,6 +1135,86 @@ public final class FunctionNode extends LexicalContextExpression implements Flag return setFlag(lc, IS_CACHED); } + /** + * Checks if the function is generated in strong mode. + * + * @return true if strong mode enabled for function + */ + public boolean isStrong() { + return getFlag(ES6_IS_STRONG); + } + + /** + * Checks if this is an ES6 method. + * + * @return true if the ES6 method flag is set + */ + public boolean isMethod() { + return getFlag(ES6_IS_METHOD); + } + + /** + * Checks if this function uses the ES6 super binding. + * + * @return true if the ES6 super flag is set + */ + public boolean usesSuper() { + return getFlag(ES6_USES_SUPER); + } + + /** + * Checks if this function directly uses the super binding. + * + * @return true if the ES6 has-direct-super flag is set + */ + public boolean hasDirectSuper() { + return getFlag(ES6_HAS_DIRECT_SUPER); + } + + /** + * Checks if this is an ES6 class constructor. + * + * @return true if the ES6 class constructor flag is set + */ + public boolean isClassConstructor() { + return getFlag(ES6_IS_CLASS_CONSTRUCTOR); + } + + /** + * Checks if this is an ES6 subclass constructor. + * + * @return true if the ES6 subclass constructor flag is set + */ + public boolean isSubclassConstructor() { + return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR); + } + + /** + * Checks if this function uses the ES6 new-targert. + * + * @return true if the ES6 new-target flag is set + */ + public boolean usesNewTarget() { + return getFlag(ES6_USES_NEW_TARGET); + } + + /** + * Checks if this is an ES6 module. + * + * @return true if this is an ES6 module + */ + public boolean isModule() { + return kind == Kind.MODULE; + } + + /** + * Returns the functions's ES6 module. + * + * @return the module, or null if this function is not part of one + */ + public Module getModule() { + return module; + } /** * Get the compile unit used to compile this function diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java index 4570181af07..28103b8ca01 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java @@ -49,6 +49,11 @@ public final class IdentNode extends Expression implements PropertyKey, Function private static final int FUTURESTRICT_NAME = 1 << 3; private static final int IS_DECLARED_HERE = 1 << 4; private static final int IS_DEAD = 1 << 5; + private static final int DIRECT_SUPER = 1 << 6; + private static final int REST_PARAMETER = 1 << 7; + private static final int PROTO_PROPERTY = 1 << 8; + private static final int DEFAULT_PARAMETER = 1 << 9; + private static final int DESTRUCTURED_PARAMETER = 1 << 10; /** Identifier. */ private final String name; @@ -382,4 +387,94 @@ public final class IdentNode extends Expression implements PropertyKey, Function public LocalVariableConversion getLocalVariableConversion() { return conversion; } + + /** + * Checks if this is a direct super identifier + * + * @return true if the direct super flag is set + */ + public boolean isDirectSuper() { + return (flags & DIRECT_SUPER) != 0; + } + + /** + * Return a new identifier with the direct super flag set. + * + * @return the new identifier + */ + public IdentNode setIsDirectSuper() { + return new IdentNode(this, name, type, flags | DIRECT_SUPER, programPoint, conversion); + } + + /** + * Checks if this is a rest parameter + * + * @return true if the rest parameter flag is set + */ + public boolean isRestParameter() { + return (flags & REST_PARAMETER) != 0; + } + + /** + * Return a new identifier with the rest parameter flag set. + * + * @return the new identifier + */ + public IdentNode setIsRestParameter() { + return new IdentNode(this, name, type, flags | REST_PARAMETER, programPoint, conversion); + } + + /** + * Checks if this is a proto property name. + * + * @return true if this is the proto property name + */ + public boolean isProtoPropertyName() { + return (flags & PROTO_PROPERTY) != 0; + } + + /** + * Return a new identifier with the proto property name flag set. + * + * @return the new identifier + */ + public IdentNode setIsProtoPropertyName() { + return new IdentNode(this, name, type, flags | PROTO_PROPERTY, programPoint, conversion); + } + + /** + * Checks whether this is a default parameter. + * + * @return true if this is a default parameter + */ + public boolean isDefaultParameter() { + return (flags & DEFAULT_PARAMETER) != 0; + } + + /** + * Return a new identifier with the default parameter flag set. + * + * @return the new identifier + */ + public IdentNode setIsDefaultParameter() { + return new IdentNode(this, name, type, flags | DEFAULT_PARAMETER, programPoint, conversion); + } + + /** + * Checks whether this is a destructured parameter. + * + * @return true if this is a destructured parameter + */ + public boolean isDestructuredParameter() { + return (flags & DESTRUCTURED_PARAMETER) != 0; + } + + /** + * Return a new identifier with the destructured parameter flag set. + * + * @return the new identifier + */ + public IdentNode setIsDestructuredParameter() { + return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion); + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java index 72df1f9694a..73e220d699c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java @@ -47,12 +47,13 @@ public final class IndexNode extends BaseNode { * @param index index for access */ public IndexNode(final long token, final int finish, final Expression base, final Expression index) { - super(token, finish, base, false); + super(token, finish, base, false, false); this.index = index; } - private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) { - super(indexNode, base, isFunction, type, programPoint); + private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, + final Type type, final int programPoint, final boolean isSuper) { + super(indexNode, base, isFunction, type, programPoint, isSuper); this.index = index; } @@ -101,7 +102,7 @@ public final class IndexNode extends BaseNode { if (this.base == base) { return this; } - return new IndexNode(this, base, index, isFunction(), type, programPoint); + return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper()); } /** @@ -113,7 +114,7 @@ public final class IndexNode extends BaseNode { if(this.index == index) { return this; } - return new IndexNode(this, base, index, isFunction(), type, programPoint); + return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper()); } @Override @@ -121,7 +122,7 @@ public final class IndexNode extends BaseNode { if (this.type == type) { return this; } - return new IndexNode(this, base, index, isFunction(), type, programPoint); + return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper()); } @Override @@ -129,7 +130,7 @@ public final class IndexNode extends BaseNode { if (isFunction()) { return this; } - return new IndexNode(this, base, index, true, type, programPoint); + return new IndexNode(this, base, index, true, type, programPoint, isSuper()); } @Override @@ -137,6 +138,14 @@ public final class IndexNode extends BaseNode { if (this.programPoint == programPoint) { return this; } - return new IndexNode(this, base, index, isFunction(), type, programPoint); + return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper()); + } + + @Override + public IndexNode setIsSuper() { + if (isSuper()) { + return this; + } + return new IndexNode(this, base, index, isFunction(), type, programPoint, true); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java new file mode 100644 index 00000000000..28279abbfc6 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java @@ -0,0 +1,338 @@ +/* + * 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 jdk.nashorn.internal.ir; + +import java.util.List; + +/** + * ES6 Module information. + */ +public final class Module { + + /** The synthetic binding name assigned to export default declarations with unnamed expressions. */ + public static final String DEFAULT_EXPORT_BINDING_NAME = "*default*"; + + /** The {@code export default} name. */ + public static final String DEFAULT_NAME = "default"; + + /** The {@code export *} name. */ + public static final String STAR_NAME = "*"; + + /** + * A module ExportEntry record. + * + * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records + */ + public static final class ExportEntry { + private final String exportName; + private final String moduleRequest; + private final String importName; + private final String localName; + + private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) { + this.exportName = exportName; + this.moduleRequest = moduleRequest; + this.importName = importName; + this.localName = localName; + } + + /** + * Creates a {@code export *} export entry. + * + * @param moduleRequest the module request + * @return the export entry + */ + public static ExportEntry exportStarFrom(final String moduleRequest) { + return new ExportEntry(null, moduleRequest, STAR_NAME, null); + } + + /** + * Creates a {@code export default} export entry. + * + * @return the export entry + */ + public static ExportEntry exportDefault() { + return exportDefault(DEFAULT_EXPORT_BINDING_NAME); + } + + /** + * Creates a {@code export default} export entry with a local name. + * + * @param localName the local name + * @return the export entry + */ + public static ExportEntry exportDefault(final String localName) { + return new ExportEntry(DEFAULT_NAME, null, null, localName); + } + + /** + * Creates a export entry with a local name and export name. + * + * @param exportName the export name + * @param localName the local name + * @return the export entry + */ + public static ExportEntry exportSpecifier(final String exportName, final String localName) { + return new ExportEntry(exportName, null, null, localName); + } + + /** + * Creates a export entry with an export name. + * + * @param exportName the export name + * @return the export entry + */ + public static ExportEntry exportSpecifier(final String exportName) { + return exportSpecifier(exportName, exportName); + } + + /** + * Create a copy of this entry with the specified {@code module request} string. + * + * @param moduleRequest the module request + * @return the new export entry + */ + public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) { + return new ExportEntry(exportName, moduleRequest, localName, null); + } + + /** + * Returns the entry's export name. + * + * @return the export name + */ + public String getExportName() { + return exportName; + } + + /** + * Returns the entry's module request. + * + * @return the module request + */ + public String getModuleRequest() { + return moduleRequest; + } + + /** + * Returns the entry's import name. + * + * @return the import name + */ + public String getImportName() { + return importName; + } + + /** + * Returns the entry's local name. + * + * @return the local name + */ + public String getLocalName() { + return localName; + } + + @Override + public String toString() { + return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]"; + } + } + + /** + * An ImportEntry record. + * + * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records + */ + public static final class ImportEntry { + private final String moduleRequest; + private final String importName; + private final String localName; + + private ImportEntry(final String moduleRequest, final String importName, final String localName) { + this.moduleRequest = moduleRequest; + this.importName = importName; + this.localName = localName; + } + + /** + * Creates an import entry with default name. + * + * @param localName the local name + * @return the import entry + */ + public static ImportEntry importDefault(final String localName) { + return new ImportEntry(null, DEFAULT_NAME, localName); + } + + /** + * Creates an import entry with {@code *} import name. + * + * @param localName the local name + * @return the import entry + */ + public static ImportEntry importStarAsNameSpaceFrom(final String localName) { + return new ImportEntry(null, STAR_NAME, localName); + } + + /** + * Creates an import entry with the given import and local names. + * + * @param importName the import name + * @param localName the local name + * @return the import entry + */ + public static ImportEntry importSpecifier(final String importName, final String localName) { + return new ImportEntry(null, importName, localName); + } + + /** + * Creates a new import entry with the given import name. + * + * @param importName the import name + * @return the import entry + */ + public static ImportEntry importSpecifier(final String importName) { + return importSpecifier(importName, importName); + } + + /** + * Returns a copy of this import entry with the given module request. + * + * @param moduleRequest the module request + * @return the new import entry + */ + public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) { + return new ImportEntry(moduleRequest, importName, localName); + } + + /** + * Returns the entry's module request. + * + * @return the module request + */ + public String getModuleRequest() { + return moduleRequest; + } + + /** + * Returns the entry's import name. + * + * @return the import name + */ + public String getImportName() { + return importName; + } + + /** + * Returns the entry's local name. + * + * @return the local name + */ + public String getLocalName() { + return localName; + } + + @Override + public String toString() { + return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]"; + } + } + + private final List requestedModules; + private final List importEntries; + private final List localExportEntries; + private final List indirectExportEntries; + private final List starExportEntries; + + /** + * Creates a module with the specified requested modules and import and export entries. + * + * @param requestedModules the requested modules + * @param importEntries the import entries + * @param localExportEntries local export entries + * @param indirectExportEntries indirect export entries + * @param starExportEntries star export entries + */ + public Module(final List requestedModules, final List importEntries, final List localExportEntries, + final List indirectExportEntries, final List starExportEntries) { + this.requestedModules = requestedModules; + this.importEntries = importEntries; + this.localExportEntries = localExportEntries; + this.indirectExportEntries = indirectExportEntries; + this.starExportEntries = starExportEntries; + } + + /** + * Returns the list of requested modules. + * + * @return the requested modules + */ + public List getRequestedModules() { + return requestedModules; + } + + /** + * Returns the list of import entries. + * + * @return the import entries + */ + public List getImportEntries() { + return importEntries; + } + + /** + * Returns the list of local export entries. + * + * @return the local export entries + */ + public List getLocalExportEntries() { + return localExportEntries; + } + + /** + * Returns the list of indirect export entries. + * + * @return the indirect export entries + */ + public List getIndirectExportEntries() { + return indirectExportEntries; + } + + /** + * Returns the list of star export entries. + * + * @return the star export entries + */ + public List getStarExportEntries() { + return starExportEntries; + } + + @Override + public String toString() { + return "Module [requestedModules=" + requestedModules + ", importEntries=" + importEntries + ", localExportEntries=" + localExportEntries + ", indirectExportEntries=" + + indirectExportEntries + ", starExportEntries=" + starExportEntries + "]"; + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java index b9b8abea500..d27bfa710b6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java @@ -36,7 +36,7 @@ public final class PropertyNode extends Node { private static final long serialVersionUID = 1L; /** Property key. */ - private final PropertyKey key; + private final Expression key; /** Property value. */ private final Expression value; @@ -47,6 +47,12 @@ public final class PropertyNode extends Node { /** Property getter. */ private final FunctionNode setter; + /** static property flag */ + private final boolean isStatic; + + /** Computed property flag */ + private final boolean computed; + /** * Constructor * @@ -56,21 +62,27 @@ public final class PropertyNode extends Node { * @param value the value of this property * @param getter getter function body * @param setter setter function body + * @param isStatic is this a static property? + * @param computed is this a computed property? */ - public PropertyNode(final long token, final int finish, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) { + public PropertyNode(final long token, final int finish, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) { super(token, finish); this.key = key; this.value = value; this.getter = getter; this.setter = setter; + this.isStatic = isStatic; + this.computed = computed; } - private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) { + private PropertyNode(final PropertyNode propertyNode, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) { super(propertyNode); this.key = key; this.value = value; this.getter = getter; this.setter = setter; + this.isStatic = isStatic; + this.computed = computed; } /** @@ -78,14 +90,14 @@ public final class PropertyNode extends Node { * @return key name */ public String getKeyName() { - return key.getPropertyName(); + return key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : null; } @Override public Node accept(final NodeVisitor visitor) { if (visitor.enterPropertyNode(this)) { return visitor.leavePropertyNode( - setKey((PropertyKey)((Node)key).accept(visitor)). + setKey((Expression) key.accept(visitor)). setValue(value == null ? null : (Expression)value.accept(visitor)). setGetter(getter == null ? null : (FunctionNode)getter.accept(visitor)). setSetter(setter == null ? null : (FunctionNode)setter.accept(visitor))); @@ -134,7 +146,7 @@ public final class PropertyNode extends Node { if (this.getter == getter) { return this; } - return new PropertyNode(this, key, value, getter, setter); + return new PropertyNode(this, key, value, getter, setter, isStatic, computed); } /** @@ -142,14 +154,14 @@ public final class PropertyNode extends Node { * @return the key */ public Expression getKey() { - return (Expression)key; + return key; } - private PropertyNode setKey(final PropertyKey key) { + private PropertyNode setKey(final Expression key) { if (this.key == key) { return this; } - return new PropertyNode(this, key, value, getter, setter); + return new PropertyNode(this, key, value, getter, setter, isStatic, computed); } /** @@ -169,7 +181,7 @@ public final class PropertyNode extends Node { if (this.setter == setter) { return this; } - return new PropertyNode(this, key, value, getter, setter); + return new PropertyNode(this, key, value, getter, setter, isStatic, computed); } /** @@ -189,6 +201,24 @@ public final class PropertyNode extends Node { if (this.value == value) { return this; } - return new PropertyNode(this, key, value, getter, setter); - } + return new PropertyNode(this, key, value, getter, setter, isStatic, computed); + } + + /** + * Returns true if this is a static property. + * + * @return true if static flag is set + */ + public boolean isStatic() { + return isStatic; + } + + /** + * Returns true if this is a computed property. + * + * @return true if the computed flag is set + */ + public boolean isComputed() { + return computed; + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java index 9badcf6b9ca..136e5e0bcfd 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java @@ -133,8 +133,8 @@ public abstract class NodeOperatorVisitor extends Node return enterASSIGN_SHR(binaryNode); case ASSIGN_SUB: return enterASSIGN_SUB(binaryNode); - case BIND: - return enterBIND(binaryNode); + case ARROW: + return enterARROW(binaryNode); case BIT_AND: return enterBIT_AND(binaryNode); case BIT_OR: @@ -217,8 +217,8 @@ public abstract class NodeOperatorVisitor extends Node return leaveASSIGN_SHR(binaryNode); case ASSIGN_SUB: return leaveASSIGN_SUB(binaryNode); - case BIND: - return leaveBIND(binaryNode); + case ARROW: + return leaveARROW(binaryNode); case BIT_AND: return leaveBIT_AND(binaryNode); case BIT_OR: @@ -735,22 +735,22 @@ public abstract class NodeOperatorVisitor extends Node } /** - * Binary enter - callback for entering a bind operator + * Binary enter - callback for entering a arrow operator * * @param binaryNode the node * @return true if traversal should continue and node children be traversed, false otherwise */ - public boolean enterBIND(final BinaryNode binaryNode) { + public boolean enterARROW(final BinaryNode binaryNode) { return enterDefault(binaryNode); } /** - * Binary leave - callback for leaving a bind operator + * Binary leave - callback for leaving a arrow operator * * @param binaryNode the node * @return processed node, which will replace the original one, or the original node */ - public Node leaveBIND(final BinaryNode binaryNode) { + public Node leaveARROW(final BinaryNode binaryNode) { return leaveDefault(binaryNode); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java index adee3673ee4..c83587c34d4 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java @@ -33,6 +33,7 @@ import jdk.nashorn.internal.ir.BreakNode; import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; +import jdk.nashorn.internal.ir.ClassNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.DebuggerNode; import jdk.nashorn.internal.ir.EmptyNode; @@ -897,5 +898,23 @@ public abstract class NodeVisitor { return leaveDefault(withNode); } + /** + * Callback for entering a ClassNode + * + * @param classNode the node + * @return true if traversal should continue and node children be traversed, false otherwise + */ + public boolean enterClassNode(final ClassNode classNode) { + return enterDefault(classNode); + } + /** + * Callback for leaving a ClassNode + * + * @param classNode the node + * @return processed node, which will replace the original one, or the original node + */ + public Node leaveClassNode(final ClassNode classNode) { + return leaveDefault(classNode); + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index 5009c6f5e0e..1608d912606 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -28,35 +28,55 @@ package jdk.nashorn.internal.parser; import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX; import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL; import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM; +import static jdk.nashorn.internal.parser.TokenType.ARROW; import static jdk.nashorn.internal.parser.TokenType.ASSIGN; import static jdk.nashorn.internal.parser.TokenType.CASE; import static jdk.nashorn.internal.parser.TokenType.CATCH; +import static jdk.nashorn.internal.parser.TokenType.CLASS; import static jdk.nashorn.internal.parser.TokenType.COLON; import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT; +import static jdk.nashorn.internal.parser.TokenType.COMMENT; import static jdk.nashorn.internal.parser.TokenType.CONST; import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX; import static jdk.nashorn.internal.parser.TokenType.DECPREFIX; +import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS; import static jdk.nashorn.internal.parser.TokenType.ELSE; import static jdk.nashorn.internal.parser.TokenType.EOF; import static jdk.nashorn.internal.parser.TokenType.EOL; +import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT; +import static jdk.nashorn.internal.parser.TokenType.ESCSTRING; +import static jdk.nashorn.internal.parser.TokenType.EXPORT; +import static jdk.nashorn.internal.parser.TokenType.EXTENDS; import static jdk.nashorn.internal.parser.TokenType.FINALLY; import static jdk.nashorn.internal.parser.TokenType.FUNCTION; import static jdk.nashorn.internal.parser.TokenType.IDENT; import static jdk.nashorn.internal.parser.TokenType.IF; +import static jdk.nashorn.internal.parser.TokenType.IMPORT; import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX; import static jdk.nashorn.internal.parser.TokenType.LBRACE; +import static jdk.nashorn.internal.parser.TokenType.LBRACKET; import static jdk.nashorn.internal.parser.TokenType.LET; import static jdk.nashorn.internal.parser.TokenType.LPAREN; +import static jdk.nashorn.internal.parser.TokenType.MUL; +import static jdk.nashorn.internal.parser.TokenType.PERIOD; import static jdk.nashorn.internal.parser.TokenType.RBRACE; import static jdk.nashorn.internal.parser.TokenType.RBRACKET; import static jdk.nashorn.internal.parser.TokenType.RPAREN; import static jdk.nashorn.internal.parser.TokenType.SEMICOLON; +import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY; +import static jdk.nashorn.internal.parser.TokenType.STATIC; +import static jdk.nashorn.internal.parser.TokenType.STRING; +import static jdk.nashorn.internal.parser.TokenType.SUPER; import static jdk.nashorn.internal.parser.TokenType.TEMPLATE; import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD; import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE; import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL; import static jdk.nashorn.internal.parser.TokenType.TERNARY; +import static jdk.nashorn.internal.parser.TokenType.VAR; +import static jdk.nashorn.internal.parser.TokenType.VOID; import static jdk.nashorn.internal.parser.TokenType.WHILE; +import static jdk.nashorn.internal.parser.TokenType.YIELD; +import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR; import java.io.Serializable; import java.util.ArrayDeque; @@ -68,6 +88,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.Namespace; import jdk.nashorn.internal.ir.AccessNode; @@ -79,11 +101,13 @@ import jdk.nashorn.internal.ir.BreakNode; import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; +import jdk.nashorn.internal.ir.ClassNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.DebuggerNode; import jdk.nashorn.internal.ir.EmptyNode; import jdk.nashorn.internal.ir.ErrorNode; import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ExpressionList; import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; @@ -92,7 +116,9 @@ import jdk.nashorn.internal.ir.IfNode; import jdk.nashorn.internal.ir.IndexNode; import jdk.nashorn.internal.ir.JoinPredecessorExpression; import jdk.nashorn.internal.ir.LabelNode; +import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LiteralNode; +import jdk.nashorn.internal.ir.Module; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.ObjectNode; import jdk.nashorn.internal.ir.PropertyKey; @@ -110,6 +136,7 @@ import jdk.nashorn.internal.ir.WhileNode; import jdk.nashorn.internal.ir.WithNode; import jdk.nashorn.internal.ir.debug.ASTWriter; import jdk.nashorn.internal.ir.debug.PrintVisitor; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; import jdk.nashorn.internal.runtime.JSErrorType; @@ -253,6 +280,14 @@ public class Parser extends AbstractParser implements Loggable { return parse(PROGRAM.symbolName(), 0, source.getLength(), false); } + /** + * Set up first token. Skips opening EOL. + */ + private void scanFirstToken() { + k = -1; + next(); + } + /** * Execute parse and return the resulting function node. * Errors will be thrown and the error manager will contain information @@ -280,9 +315,7 @@ public class Parser extends AbstractParser implements Loggable { lexer.line = lexer.pendingLine = lineOffset + 1; line = lineOffset; - // Set up first token (skips opening EOL.) - k = -1; - next(); + scanFirstToken(); // Begin parse. return program(scriptName, allowPropertyFunction); } catch (final Exception e) { @@ -300,6 +333,44 @@ public class Parser extends AbstractParser implements Loggable { } } + /** + * Parse and return the resulting module. + * Errors will be thrown and the error manager will contain information + * if parsing should fail + * + * @param moduleName name for the module, given to the parsed FunctionNode + * @param startPos start position in source + * @param len length of parse + * + * @return function node resulting from successful parse + */ + public FunctionNode parseModule(final String moduleName, final int startPos, final int len) { + try { + stream = new TokenStream(); + lexer = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null); + lexer.line = lexer.pendingLine = lineOffset + 1; + line = lineOffset; + + scanFirstToken(); + // Begin parse. + return module(moduleName); + } catch (final Exception e) { + handleParseException(e); + + return null; + } + } + + /** + * Entry point for parsing a module. + * + * @param moduleName the module name + * @return the parsed module + */ + public FunctionNode parseModule(final String moduleName) { + return parseModule(moduleName, 0, source.getLength()); + } + /** * Parse and return the list of function parameter list. A comma * separated list of function parameter identifiers is expected to be parsed. @@ -314,11 +385,9 @@ public class Parser extends AbstractParser implements Loggable { stream = new TokenStream(); lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); - // Set up first token (skips opening EOL.) - k = -1; - next(); + scanFirstToken(); - return formalParameterList(TokenType.EOF); + return formalParameterList(TokenType.EOF, false); } catch (final Exception e) { handleParseException(e); return null; @@ -339,9 +408,7 @@ public class Parser extends AbstractParser implements Loggable { lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6); final int functionLine = line; - // Set up first token (skips opening EOL.) - k = -1; - next(); + scanFirstToken(); // Make a fake token for the function. final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); @@ -432,7 +499,7 @@ public class Parser extends AbstractParser implements Loggable { } // Skip to a recovery point. -loop: + loop: while (true) { switch (type) { case EOF: @@ -474,7 +541,7 @@ loop: sb.append(ident.getName()); final String name = namespace.uniqueName(sb.toString()); - assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name; + assert parentFunction != null || name.equals(PROGRAM.symbolName()) : "name = " + name; int flags = 0; if (isStrictMode) { @@ -489,7 +556,8 @@ loop: return functionNode; } - private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List parameters, final FunctionNode.Kind kind, final int functionLine, final Block body){ + private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) { + // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody(); // Start new block. final FunctionNode functionNode = new FunctionNode( @@ -506,7 +574,9 @@ loop: kind, function.getFlags(), body, - function.getEndParserState()); + function.getEndParserState(), + function.getModule(), + function.getDebugFlags()); printAST(functionNode); @@ -544,23 +614,39 @@ loop: expect(RBRACE); } - final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC); + final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC); return new Block(blockToken, finish, flags, newBlock.getStatements()); } + /** + * Get the statements in a case clause. + */ + private List caseStatementList() { + final ParserContextBlockNode newBlock = newBlock(); + try { + statementList(); + } finally { + restoreBlock(newBlock); + } + return newBlock.getStatements(); + } /** * Get all the statements generated by a single statement. * @return Statements. */ private Block getStatement() { + return getStatement(false); + } + + private Block getStatement(boolean labelledStatement) { if (type == LBRACE) { return getBlock(true); } // Set up new block. Captures first token. final ParserContextBlockNode newBlock = newBlock(); try { - statement(false, false, true); + statement(false, false, true, labelledStatement); } finally { restoreBlock(newBlock); } @@ -576,6 +662,9 @@ loop: if (EVAL.symbolName().equals(name)) { markEval(lc); + } else if (SUPER.getName().equals(name)) { + assert ident.isDirectSuper(); + markSuperCall(lc); } } @@ -585,7 +674,8 @@ loop: */ private void detectSpecialProperty(final IdentNode ident) { if (isArguments(ident)) { - lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS); + // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); } + getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS); } } @@ -593,11 +683,15 @@ loop: return env._es6; } + private boolean isES6() { + return env._es6; + } + private static boolean isArguments(final String name) { return ARGUMENTS_NAME.equals(name); } - private static boolean isArguments(final IdentNode ident) { + static boolean isArguments(final IdentNode ident) { return isArguments(ident.getName()); } @@ -634,20 +728,20 @@ loop: case ASSIGN_SHL: case ASSIGN_SHR: case ASSIGN_SUB: - if (!(lhs instanceof AccessNode || - lhs instanceof IndexNode || - lhs instanceof IdentNode)) { - return referenceError(lhs, rhs, env._early_lvalue_error); - } - if (lhs instanceof IdentNode) { if (!checkIdentLValue((IdentNode)lhs)) { return referenceError(lhs, rhs, false); } - verifyStrictIdent((IdentNode)lhs, "assignment"); + verifyIdent((IdentNode)lhs, "assignment"); + break; + } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) { + break; + } else if (opType == ASSIGN && isDestructuringLhs(lhs)) { + verifyDestructuringAssignmentPattern(lhs, "assignment"); + break; + } else { + return referenceError(lhs, rhs, env._early_lvalue_error); } - break; - default: break; } @@ -659,6 +753,114 @@ loop: return new BinaryNode(op, lhs, rhs); } + private boolean isDestructuringLhs(Expression lhs) { + if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) { + return isES6(); + } + return false; + } + + private void verifyDestructuringAssignmentPattern(Expression pattern, String contextString) { + assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode; + pattern.accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterLiteralNode(LiteralNode literalNode) { + if (literalNode.isArray()) { + boolean restElement = false; + for (Expression element : literalNode.getElementExpressions()) { + if (element != null) { + if (restElement) { + throw error(String.format("Unexpected element after rest element"), element.getToken()); + } + if (element.isTokenType(SPREAD_ARRAY)) { + restElement = true; + Expression lvalue = ((UnaryNode) element).getExpression(); + if (!checkValidLValue(lvalue, contextString)) { + throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken()); + } + } + element.accept(this); + } + } + return false; + } else { + return enterDefault(literalNode); + } + } + + @Override + public boolean enterObjectNode(ObjectNode objectNode) { + return true; + } + + @Override + public boolean enterPropertyNode(PropertyNode propertyNode) { + if (propertyNode.getValue() != null) { + propertyNode.getValue().accept(this); + return false; + } else { + return enterDefault(propertyNode); + } + } + + @Override + public boolean enterIdentNode(IdentNode identNode) { + verifyIdent(identNode, contextString); + if (!checkIdentLValue(identNode)) { + referenceError(identNode, null, true); + return false; + } + return false; + } + + @Override + public boolean enterAccessNode(AccessNode accessNode) { + return false; + } + + @Override + public boolean enterIndexNode(IndexNode indexNode) { + return false; + } + + @Override + public boolean enterBinaryNode(BinaryNode binaryNode) { + if (binaryNode.isTokenType(ASSIGN)) { + binaryNode.lhs().accept(this); + // Initializer(rhs) can be any AssignmentExpression + return false; + } else { + return enterDefault(binaryNode); + } + } + + @Override + public boolean enterUnaryNode(UnaryNode unaryNode) { + if (unaryNode.isTokenType(SPREAD_ARRAY)) { + // rest element + return true; + } else { + return enterDefault(unaryNode); + } + } + + @Override + protected boolean enterDefault(Node node) { + throw error(String.format("unexpected node in AssignmentPattern: %s", node)); + } + }); + } + + private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) { + final TokenType opType = Token.descType(op); + + // Build up node. + if (BinaryNode.isLogical(opType)) { + return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs)); + } + return new BinaryNode(op, lhs, rhs); + } + /** * Reduce increment/decrement to simpler operations. @@ -717,7 +919,7 @@ loop: restoreBlock(body); body.setFlag(Block.NEEDS_SCOPE); - final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements()); + final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements()); lc.pop(script); script.setLastToken(token); @@ -776,7 +978,7 @@ loop: try { // Get the next element. - statement(true, allowPropertyFunction, false); + statement(true, allowPropertyFunction, false, false); allowPropertyFunction = false; // check for directive prologues @@ -816,16 +1018,16 @@ loop: // verify that function name as well as parameter names // satisfy strict mode restrictions. - verifyStrictIdent(function.getIdent(), "function name"); + verifyIdent(function.getIdent(), "function name"); for (final IdentNode param : function.getParameters()) { - verifyStrictIdent(param, "function parameter"); + verifyIdent(param, "function parameter"); } } } else if (Context.DEBUG) { - final int flag = FunctionNode.getDirectiveFlag(directive); - if (flag != 0) { + final int debugFlag = FunctionNode.getDirectiveFlag(directive); + if (debugFlag != 0) { final ParserContextFunctionNode function = lc.getCurrentFunction(); - function.setFlag(flag); + function.setDebugFlag(debugFlag); } } } @@ -849,29 +1051,53 @@ loop: } /** + * Parse any of the basic statement types. + * * Statement : - * Block + * BlockStatement * VariableStatement * EmptyStatement * ExpressionStatement * IfStatement - * IterationStatement + * BreakableStatement * ContinueStatement * BreakStatement * ReturnStatement * WithStatement * LabelledStatement - * SwitchStatement * ThrowStatement * TryStatement * DebuggerStatement * - * see 12 + * BreakableStatement : + * IterationStatement + * SwitchStatement * - * Parse any of the basic statement types. + * BlockStatement : + * Block + * + * Block : + * { StatementList opt } + * + * StatementList : + * StatementListItem + * StatementList StatementListItem + * + * StatementItem : + * Statement + * Declaration + * + * Declaration : + * HoistableDeclaration + * ClassDeclaration + * LexicalDeclaration + * + * HoistableDeclaration : + * FunctionDeclaration + * GeneratorDeclaration */ private void statement() { - statement(false, false, false); + statement(false, false, false, false); } /** @@ -879,14 +1105,7 @@ loop: * @param allowPropertyFunction allow property "get" and "set" functions? * @param singleStatement are we in a single statement context? */ - private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) { - if (type == FUNCTION) { - // As per spec (ECMA section 12), function declarations as arbitrary statement - // is not "portable". Implementation can issue a warning or disallow the same. - functionExpression(true, topLevel); - return; - } - + private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement, final boolean labelledStatement) { switch (type) { case LBRACE: block(); @@ -918,9 +1137,6 @@ loop: case RETURN: returnStatement(); break; - case YIELD: - yieldStatement(); - break; case WITH: withStatement(); break; @@ -941,13 +1157,32 @@ loop: case EOF: expect(SEMICOLON); break; + case FUNCTION: + // As per spec (ECMA section 12), function declarations as arbitrary statement + // is not "portable". Implementation can issue a warning or disallow the same. + if (singleStatement) { + // ES6 B.3.2 Labelled Function Declarations + // It is a Syntax Error if any strict mode source code matches this rule: + // LabelledItem : FunctionDeclaration. + if (!labelledStatement || isStrictMode) { + throw error(AbstractParser.message("expected.stmt", "function declaration"), token); + } + } + functionExpression(true, topLevel || labelledStatement); + return; default: - if (useBlockScope() && (type == LET || type == CONST)) { + if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) { if (singleStatement) { throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token); } variableStatement(type); break; + } else if (type == CLASS && isES6()) { + if (singleStatement) { + throw error(AbstractParser.message("expected.stmt", "class declaration"), token); + } + classDeclaration(false); + break; } if (env._const_as_var && type == CONST) { variableStatement(TokenType.VAR); @@ -963,11 +1198,11 @@ loop: final String ident = (String)getValue(); final long propertyToken = token; final int propertyLine = line; - if("get".equals(ident)) { + if ("get".equals(ident)) { next(); addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine)); return; - } else if("set".equals(ident)) { + } else if ("set".equals(ident)) { next(); addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine)); return; @@ -985,6 +1220,267 @@ loop: functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn)); } + /** + * ClassDeclaration[Yield, Default] : + * class BindingIdentifier[?Yield] ClassTail[?Yield] + * [+Default] class ClassTail[?Yield] + */ + private ClassNode classDeclaration(boolean isDefault) { + int classLineNumber = line; + + ClassNode classExpression = classExpression(!isDefault); + + if (!isDefault) { + VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST); + appendStatement(classVar); + } + return classExpression; + } + + /** + * ClassExpression[Yield] : + * class BindingIdentifier[?Yield]opt ClassTail[?Yield] + */ + private ClassNode classExpression(boolean isStatement) { + assert type == CLASS; + int classLineNumber = line; + long classToken = token; + next(); + + IdentNode className = null; + if (isStatement || type == IDENT) { + className = getIdent(); + } + + return classTail(classLineNumber, classToken, className); + } + + private static final class ClassElementKey { + private final boolean isStatic; + private final String propertyName; + + private ClassElementKey(boolean isStatic, String propertyName) { + this.isStatic = isStatic; + this.propertyName = propertyName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (isStatic ? 1231 : 1237); + result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ClassElementKey) { + ClassElementKey other = (ClassElementKey) obj; + return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName); + } + return false; + } + } + + /** + * Parse ClassTail and ClassBody. + * + * ClassTail[Yield] : + * ClassHeritage[?Yield]opt { ClassBody[?Yield]opt } + * ClassHeritage[Yield] : + * extends LeftHandSideExpression[?Yield] + * + * ClassBody[Yield] : + * ClassElementList[?Yield] + * ClassElementList[Yield] : + * ClassElement[?Yield] + * ClassElementList[?Yield] ClassElement[?Yield] + * ClassElement[Yield] : + * MethodDefinition[?Yield] + * static MethodDefinition[?Yield] + * ; + */ + private ClassNode classTail(final int classLineNumber, final long classToken, final IdentNode className) { + final boolean oldStrictMode = isStrictMode; + isStrictMode = true; + try { + Expression classHeritage = null; + if (type == EXTENDS) { + next(); + classHeritage = leftHandSideExpression(); + } + + expect(LBRACE); + + PropertyNode constructor = null; + final ArrayList classElements = new ArrayList<>(); + final Map keyToIndexMap = new HashMap<>(); + for (;;) { + if (type == SEMICOLON) { + next(); + continue; + } + if (type == RBRACE) { + break; + } + final long classElementToken = token; + boolean isStatic = false; + if (type == STATIC) { + isStatic = true; + next(); + } + boolean generator = false; + if (isES6() && type == MUL) { + generator = true; + next(); + } + final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator); + if (classElement.isComputed()) { + classElements.add(classElement); + } else if (!classElement.isStatic() && classElement.getKeyName().equals("constructor")) { + if (constructor == null) { + constructor = classElement; + } else { + throw error(AbstractParser.message("multiple.constructors"), classElementToken); + } + } else { + // Check for duplicate method definitions and combine accessor methods. + // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names). + + final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName()); + final Integer existing = keyToIndexMap.get(key); + + if (existing == null) { + keyToIndexMap.put(key, classElements.size()); + classElements.add(classElement); + } else { + final PropertyNode existingProperty = classElements.get(existing); + + final Expression value = classElement.getValue(); + final FunctionNode getter = classElement.getGetter(); + final FunctionNode setter = classElement.getSetter(); + + if (value != null || existingProperty.getValue() != null) { + keyToIndexMap.put(key, classElements.size()); + classElements.add(classElement); + } else if (getter != null) { + assert existingProperty.getGetter() != null || existingProperty.getSetter() != null; + classElements.set(existing, existingProperty.setGetter(getter)); + } else if (setter != null) { + assert existingProperty.getGetter() != null || existingProperty.getSetter() != null; + classElements.set(existing, existingProperty.setSetter(setter)); + } + } + } + } + + final long lastToken = token; + expect(RBRACE); + + if (constructor == null) { + constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null); + } + + classElements.trimToSize(); + return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements); + } finally { + isStrictMode = oldStrictMode; + } + } + + private PropertyNode createDefaultClassConstructor(int classLineNumber, long classToken, long lastToken, IdentNode className, boolean subclass) { + final int ctorFinish = finish; + final List statements; + final List parameters; + final long identToken = Token.recast(classToken, TokenType.IDENT); + if (subclass) { + final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper(); + final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter(); + final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent); + final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false); + statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall)); + parameters = Collections.singletonList(argsIdent); + } else { + statements = Collections.emptyList(); + parameters = Collections.emptyList(); + } + + final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements); + final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, "constructor"); + final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters); + function.setLastToken(lastToken); + + function.setFlag(FunctionNode.ES6_IS_METHOD); + function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR); + if (subclass) { + function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR); + function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER); + } + if (className == null) { + function.setFlag(FunctionNode.IS_ANONYMOUS); + } + + final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode( + function, + classToken, + ctorName, + parameters, + FunctionNode.Kind.NORMAL, + classLineNumber, + body + ), null, null, false, false); + return constructor; + } + + private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) { + final long methodToken = token; + final int methodLine = line; + final boolean computed = type == LBRACKET; + final boolean isIdent = type == IDENT; + final Expression propertyName = propertyName(); + int flags = FunctionNode.ES6_IS_METHOD; + if (!computed) { + final String name = ((PropertyKey)propertyName).getPropertyName(); + if (!generator && isIdent && type != LPAREN && name.equals("get")) { + final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags); + verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true); + return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed); + } else if (!generator && isIdent && type != LPAREN && name.equals("set")) { + final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags); + verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true); + return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed); + } else { + if (!isStatic && !generator && name.equals("constructor")) { + flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR; + if (subclass) { + flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR; + } + } + verifyAllowedMethodName(propertyName, isStatic, computed, generator, false); + } + } + final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed); + return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed); + } + + /** + * ES6 14.5.1 Static Semantics: Early Errors. + */ + private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) { + if (!computed) { + if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals("constructor")) { + throw error(AbstractParser.message("generator.constructor"), key.getToken()); + } + if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals("constructor")) { + throw error(AbstractParser.message("accessor.constructor"), key.getToken()); + } + if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) { + throw error(AbstractParser.message("static.prototype.method"), key.getToken()); + } + } + } + /** * block : * { StatementList? } @@ -1008,7 +1504,7 @@ loop: */ private void statementList() { // Accumulate statements until end of list. */ -loop: + loop: while (type != EOF) { switch (type) { case EOF: @@ -1025,6 +1521,22 @@ loop: } } + /** + * Make sure that the identifier name used is allowed. + * + * @param ident Identifier that is verified + * @param contextString String used in error message to give context to the user + */ + private void verifyIdent(final IdentNode ident, final String contextString) { + verifyStrictIdent(ident, contextString); + if (isES6()) { + final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length()); + if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) { + throw error(expectMessage(IDENT)); + } + } + } + /** * Make sure that in strict mode, the identifier name used is allowed. * @@ -1066,15 +1578,16 @@ loop: * Parse a VAR statement. * @param isStatement True if a statement (not used in a FOR.) */ - private List variableStatement(final TokenType varType) { - return variableStatement(varType, true, -1); + private void variableStatement(final TokenType varType) { + variableDeclarationList(varType, true, -1); } - private List variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) { + private List variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) { // VAR tested in caller. + assert varType == VAR || varType == LET || varType == CONST; next(); - final List vars = new ArrayList<>(); + final List bindings = new ArrayList<>(); int varFlags = 0; if (varType == LET) { varFlags |= VarNode.IS_LET; @@ -1082,13 +1595,29 @@ loop: varFlags |= VarNode.IS_CONST; } + Expression missingAssignment = null; while (true) { // Get starting token. final int varLine = line; final long varToken = token; // Get name of var. - final IdentNode name = getIdent(); - verifyStrictIdent(name, "variable name"); + if (type == YIELD && inGeneratorFunction()) { + expect(IDENT); + } + + final String contextString = "variable name"; + Expression binding = bindingIdentifierOrPattern(contextString); + final boolean isDestructuring = !(binding instanceof IdentNode); + if (isDestructuring) { + final int finalVarFlags = varFlags; + verifyDestructuringBindingPattern(binding, new Consumer() { + public void accept(final IdentNode identNode) { + verifyIdent(identNode, contextString); + final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags); + appendStatement(var); + } + }); + } // Assume no init. Expression init = null; @@ -1098,22 +1627,53 @@ loop: next(); // Get initializer expression. Suppress IN if not statement. - defaultNames.push(name); + if (!isDestructuring) { + defaultNames.push(binding); + } try { init = assignmentExpression(!isStatement); } finally { - defaultNames.pop(); + if (!isDestructuring) { + defaultNames.pop(); + } } - } else if (varType == CONST && isStatement) { - throw error(AbstractParser.message("missing.const.assignment", name.getName())); + } else if (isStatement) { + if (isDestructuring) { + throw error(AbstractParser.message("missing.destructuring.assignment"), token); + } else if (varType == CONST) { + throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName())); + } + // else, if we are in a for loop, delay checking until we know the kind of loop } - // Only set declaration flag on lexically scoped let/const as it adds runtime overhead. - final IdentNode actualName = varType == LET || varType == CONST ? name.setIsDeclaredHere() : name; - // Allocate var node. - final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, actualName, init, varFlags); - vars.add(var); - appendStatement(var); + if (!isDestructuring) { + assert init != null || varType != CONST || !isStatement; + final IdentNode ident = (IdentNode)binding; + if (!isStatement && ident.getName().equals("let")) { + throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1 + } + // Only set declaration flag on lexically scoped let/const as it adds runtime overhead. + final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident; + binding = name; + final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags); + appendStatement(var); + if (init == null && varType == CONST) { + if (missingAssignment == null) { + missingAssignment = binding; + } + } + } else { + assert init != null || !isStatement; + binding = init == null ? binding : verifyAssignment(Token.recast(varToken, ASSIGN), binding, init); + if (isStatement) { + appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding)); + } else if (init == null) { + if (missingAssignment == null) { + missingAssignment = binding; + } + } + } + bindings.add(binding); if (type != COMMARIGHT) { break; @@ -1124,9 +1684,128 @@ loop: // If is a statement then handle end of line. if (isStatement) { endOfLine(); + } else { + if (type == SEMICOLON) { + // late check for missing assignment, now we know it's a for (init; test; modify) loop + if (missingAssignment != null) { + if (missingAssignment instanceof IdentNode) { + throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)missingAssignment).getName())); + } else { + throw error(AbstractParser.message("missing.destructuring.assignment"), missingAssignment.getToken()); + } + } + } } - return vars; + return bindings; + } + + private boolean isBindingIdentifier() { + return type == IDENT || isNonStrictModeIdent(); + } + + private IdentNode bindingIdentifier(final String contextString) { + final IdentNode name = getIdent(); + verifyIdent(name, contextString); + return name; + } + + private Expression bindingPattern() { + if (type == LBRACKET) { + return arrayLiteral(); + } else if (type == LBRACE) { + return objectLiteral(); + } else { + throw error(AbstractParser.message("expected.binding")); + } + } + + private Expression bindingIdentifierOrPattern(final String contextString) { + if (isBindingIdentifier() || !isES6()) { + return bindingIdentifier(contextString); + } else { + return bindingPattern(); + } + } + + /** + * Verify destructuring variable declaration binding pattern and extract bound variable declarations. + */ + private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer identifierCallback) { + assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode; + pattern.accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterLiteralNode(final LiteralNode literalNode) { + if (literalNode.isArray()) { + boolean restElement = false; + for (final Expression element : literalNode.getElementExpressions()) { + if (restElement) { + throw error(String.format("Unexpected element after rest element"), element.getToken()); + } + if (element != null) { + if (element.isTokenType(SPREAD_ARRAY)) { + restElement = true; + if (!(((UnaryNode) element).getExpression() instanceof IdentNode)) { + throw error(String.format("Expected a valid binding identifier"), element.getToken()); + + } + } + element.accept(this); + } + } + return false; + } else { + return enterDefault(literalNode); + } + } + + @Override + public boolean enterObjectNode(final ObjectNode objectNode) { + return true; + } + + @Override + public boolean enterPropertyNode(final PropertyNode propertyNode) { + if (propertyNode.getValue() != null) { + propertyNode.getValue().accept(this); + return false; + } else { + return enterDefault(propertyNode); + } + } + + @Override + public boolean enterIdentNode(final IdentNode identNode) { + identifierCallback.accept(identNode); + return false; + } + + @Override + public boolean enterBinaryNode(final BinaryNode binaryNode) { + if (binaryNode.isTokenType(ASSIGN)) { + binaryNode.lhs().accept(this); + // Initializer(rhs) can be any AssignmentExpression + return false; + } else { + return enterDefault(binaryNode); + } + } + + @Override + public boolean enterUnaryNode(final UnaryNode unaryNode) { + if (unaryNode.isTokenType(SPREAD_ARRAY)) { + // rest element + return true; + } else { + return enterDefault(unaryNode); + } + } + + @Override + protected boolean enterDefault(final Node node) { + throw error(String.format("unexpected node in BindingPattern: %s", node)); + } + }); } /** @@ -1230,7 +1909,7 @@ loop: final ParserContextLoopNode forNode = new ParserContextLoopNode(); lc.push(forNode); Block body = null; - List vars = null; + List vars = null; Expression init = null; JoinPredecessorExpression test = null; JoinPredecessorExpression modify = null; @@ -1254,20 +1933,20 @@ loop: switch (type) { case VAR: // Var declaration captured in for outer block. - vars = variableStatement(type, false, forStart); + vars = variableDeclarationList(type, false, forStart); break; case SEMICOLON: break; default: - if (useBlockScope() && (type == LET || type == CONST)) { + if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) { flags |= ForNode.PER_ITERATION_SCOPE; // LET/CONST declaration captured in container block created above. - vars = variableStatement(type, false, forStart); + vars = variableDeclarationList(type, false, forStart); break; } if (env._const_as_var && type == CONST) { // Var declaration captured in for outer block. - vars = variableStatement(TokenType.VAR, false, forStart); + vars = variableDeclarationList(TokenType.VAR, false, forStart); break; } @@ -1309,7 +1988,11 @@ loop: if (vars != null) { // for (var i in obj) if (vars.size() == 1) { - init = new IdentNode(vars.get(0).getName()); + init = new IdentNode((IdentNode)vars.get(0)); + if (init.isTokenType(ASSIGN)) { + throw error(AbstractParser.message("for.in.loop.initializer"), init.getToken()); + } + assert init instanceof IdentNode || isDestructuringLhs(init); } else { // for (var i, j in obj) is invalid throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken()); @@ -1351,10 +2034,9 @@ loop: } finally { lc.pop(forNode); - if (vars != null) { - for (final VarNode var : vars) { - appendStatement(var); - } + for (final Statement var : forNode.getStatements()) { + assert var instanceof VarNode; + appendStatement(var); } if (body != null) { appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify)); @@ -1371,6 +2053,49 @@ loop: } } + private boolean checkValidLValue(final Expression init, final String contextString) { + if (init instanceof IdentNode) { + if (!checkIdentLValue((IdentNode)init)) { + return false; + } + verifyIdent((IdentNode)init, contextString); + return true; + } else if (init instanceof AccessNode || init instanceof IndexNode) { + return true; + } else if (isDestructuringLhs(init)) { + verifyDestructuringAssignmentPattern(init, contextString); + return true; + } else { + return false; + } + } + + private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) { + assert type == LET; + for (int i = 1;; i++) { + TokenType t = T(k + i); + switch (t) { + case EOL: + case COMMENT: + continue; + case IDENT: + if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) { + return false; + } + // fall through + case LBRACKET: + case LBRACE: + return true; + default: + // accept future strict tokens in non-strict mode (including LET) + if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) { + return true; + } + return false; + } + } + } + /** * ...IterationStatement : * ... @@ -1559,7 +2284,7 @@ loop: */ private void returnStatement() { // check for return outside function - if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) { + if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) { throw error(AbstractParser.message("invalid.return")); } @@ -1591,39 +2316,61 @@ loop: } /** - * YieldStatement : - * yield Expression? ; // [no LineTerminator here] + * Parse YieldExpression. * - * JavaScript 1.8 - * - * Parse YIELD statement. + * YieldExpression[In] : + * yield + * yield [no LineTerminator here] AssignmentExpression[?In, Yield] + * yield [no LineTerminator here] * AssignmentExpression[?In, Yield] */ - private void yieldStatement() { + private Expression yieldExpression(final boolean noIn) { + assert inGeneratorFunction(); // Capture YIELD token. - final int yieldLine = line; - final long yieldToken = token; + long yieldToken = token; // YIELD tested in caller. + assert type == YIELD; nextOrEOL(); Expression expression = null; - // SEMICOLON or expression. + boolean yieldAsterisk = false; + if (type == MUL) { + yieldAsterisk = true; + yieldToken = Token.recast(yieldToken, YIELD_STAR); + next(); + } + switch (type) { case RBRACE: case SEMICOLON: case EOL: case EOF: - break; + case COMMARIGHT: + case RPAREN: + case RBRACKET: + case COLON: + if (!yieldAsterisk) { + // treat (yield) as (yield void 0) + expression = newUndefinedLiteral(yieldToken, finish); + if (type == EOL) { + next(); + } + break; + } else { + // AssignmentExpression required, fall through + } default: - expression = expression(); + expression = assignmentExpression(noIn); break; } - endOfLine(); - // Construct and add YIELD node. - appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression)); + return new UnaryNode(yieldToken, expression); + } + + private static UnaryNode newUndefinedLiteral(final long token, final int finish) { + return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0)); } /** @@ -1679,11 +2426,15 @@ loop: private void switchStatement() { final int switchLine = line; final long switchToken = token; + + // Block to capture variables declared inside the switch statement. + final ParserContextBlockNode switchBlock = newBlock(); + // SWITCH tested in caller. next(); // Create and add switch statement. - final ParserContextSwitchNode switchNode= new ParserContextSwitchNode(); + final ParserContextSwitchNode switchNode = new ParserContextSwitchNode(); lc.push(switchNode); CaseNode defaultCase = null; @@ -1727,7 +2478,7 @@ loop: expect(COLON); // Get CASE body. - final Block statements = getBlock(false); + final Block statements = getBlock(false); // TODO: List statements = caseStatementList(); final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements); if (caseExpression == null) { @@ -1740,9 +2491,11 @@ loop: next(); } finally { lc.pop(switchNode); + restoreBlock(switchBlock); } - appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase)); + final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase); + appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement))); } /** @@ -1769,7 +2522,7 @@ loop: Block body = null; try { lc.push(labelNode); - body = getStatement(); + body = getStatement(true); } finally { assert lc.peek() instanceof ParserContextLabelNode; lc.pop(labelNode); @@ -1935,13 +2688,19 @@ loop: /** * PrimaryExpression : * this - * Identifier + * IdentifierReference * Literal * ArrayLiteral * ObjectLiteral * RegularExpressionLiteral * TemplateLiteral + * CoverParenthesizedExpressionAndArrowParameterList + * + * CoverParenthesizedExpressionAndArrowParameterList : * ( Expression ) + * ( ) + * ( ... BindingIdentifier ) + * ( Expression , ... BindingIdentifier ) * * Parse primary expression. * @return Expression node. @@ -1956,7 +2715,7 @@ loop: case THIS: final String name = type.getName(); next(); - lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS); + markThis(lc); return new IdentNode(primaryToken, finish, name); case IDENT: final IdentNode ident = getIdent(); @@ -1997,6 +2756,22 @@ loop: case LPAREN: next(); + if (isES6()) { + if (type == RPAREN) { + // () + nextOrEOL(); + expectDontAdvance(ARROW); + return new ExpressionList(primaryToken, finish, Collections.emptyList()); + } else if (type == ELLIPSIS) { + // (...rest) + final IdentNode restParam = formalParameterList(false).get(0); + expectDontAdvance(RPAREN); + nextOrEOL(); + expectDontAdvance(ARROW); + return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam)); + } + } + final Expression expression = expression(); expect(RPAREN); @@ -2073,8 +2848,9 @@ loop: final List elements = new ArrayList<>(); // Track elisions. boolean elision = true; -loop: + loop: while (true) { + long spreadToken = 0; switch (type) { case RBRACKET: next(); @@ -2093,14 +2869,24 @@ loop: break; + case ELLIPSIS: + if (isES6()) { + spreadToken = token; + next(); + } + // fall through + default: if (!elision) { throw error(AbstractParser.message("expected.comma", type.getNameOrType())); } - // Add expression element. - final Expression expression = assignmentExpression(false); + // Add expression element. + Expression expression = assignmentExpression(false); if (expression != null) { + if (spreadToken != 0) { + expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression); + } elements.add(expression); } else { expect(RBRACKET); @@ -2141,7 +2927,7 @@ loop: // Create a block for the object literal. boolean commaSeen = true; -loop: + loop: while (true) { switch (type) { case RBRACE: @@ -2164,6 +2950,12 @@ loop: commaSeen = false; // Get and add the next property. final PropertyNode property = propertyAssignment(); + + if (property.isComputed()) { + elements.add(property); + break; + } + final String key = property.getKeyName(); final Integer existing = map.get(key); @@ -2185,36 +2977,23 @@ loop: final FunctionNode prevGetter = existingProperty.getGetter(); final FunctionNode prevSetter = existingProperty.getSetter(); - // ECMA 11.1.5 strict mode restrictions - if (isStrictMode && value != null && prevValue != null) { - throw error(AbstractParser.message("property.redefinition", key), property.getToken()); - } - - final boolean isPrevAccessor = prevGetter != null || prevSetter != null; - final boolean isAccessor = getter != null || setter != null; - - // data property redefined as accessor property - if (prevValue != null && isAccessor) { - throw error(AbstractParser.message("property.redefinition", key), property.getToken()); - } - - // accessor property redefined as data - if (isPrevAccessor && value != null) { - throw error(AbstractParser.message("property.redefinition", key), property.getToken()); - } - - if (isAccessor && isPrevAccessor) { - if (getter != null && prevGetter != null || - setter != null && prevSetter != null) { - throw error(AbstractParser.message("property.redefinition", key), property.getToken()); + if (!isES6()) { + checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter); + } else { + if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() && + existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) { + throw error(AbstractParser.message("multiple.proto.key"), property.getToken()); } } - if (value != null) { + if (value != null || prevValue != null) { + map.put(key, elements.size()); elements.add(property); } else if (getter != null) { + assert prevGetter != null || prevSetter != null; elements.set(existing, existingProperty.setGetter(getter)); } else if (setter != null) { + assert prevGetter != null || prevSetter != null; elements.set(existing, existingProperty.setSetter(setter)); } break; @@ -2224,18 +3003,43 @@ loop: return new ObjectNode(objectToken, finish, elements); } + private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) { + // ECMA 11.1.5 strict mode restrictions + if (isStrictMode && value != null && prevValue != null) { + throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); + } + + final boolean isPrevAccessor = prevGetter != null || prevSetter != null; + final boolean isAccessor = getter != null || setter != null; + + // data property redefined as accessor property + if (prevValue != null && isAccessor) { + throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); + } + + // accessor property redefined as data + if (isPrevAccessor && value != null) { + throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); + } + + if (isAccessor && isPrevAccessor) { + if (getter != null && prevGetter != null || + setter != null && prevSetter != null) { + throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken()); + } + } + } + /** - * PropertyName : + * LiteralPropertyName : * IdentifierName * StringLiteral * NumericLiteral * - * See 11.1.5 - * * @return PropertyName node */ @SuppressWarnings("fallthrough") - private PropertyKey propertyName() { + private PropertyKey literalPropertyName() { switch (type) { case IDENT: return getIdent().setIsPropertyName(); @@ -2256,6 +3060,34 @@ loop: } } + /** + * ComputedPropertyName : + * AssignmentExpression + * + * @return PropertyName node + */ + private Expression computedPropertyName() { + expect(LBRACKET); + Expression expression = assignmentExpression(false); + expect(RBRACKET); + return expression; + } + + /** + * PropertyName : + * LiteralPropertyName + * ComputedPropertyName + * + * @return PropertyName node + */ + private Expression propertyName() { + if (type == LBRACKET && isES6()) { + return computedPropertyName(); + } else { + return (Expression)literalPropertyName(); + } + } + /** * PropertyAssignment : * PropertyName : AssignmentExpression @@ -2280,51 +3112,95 @@ loop: final long propertyToken = token; final int functionLine = line; - PropertyKey propertyName; + final Expression propertyName; + final boolean isIdentifier; + boolean generator = false; + if (type == MUL && isES6()) { + generator = true; + next(); + } + + final boolean computed = type == LBRACKET; if (type == IDENT) { // Get IDENT. final String ident = (String)expectValue(IDENT); - if (type != COLON) { + if (type != COLON && (type != LPAREN || !isES6())) { final long getSetToken = propertyToken; switch (ident) { case "get": final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine); - return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null); + return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed); case "set": final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine); - return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode); + return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed); default: break; } } - propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); + isIdentifier = true; + IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName(); + if (type == COLON && ident.equals("__proto__")) { + identNode = identNode.setIsProtoPropertyName(); + } + propertyName = identNode; } else { + isIdentifier = isNonStrictModeIdent(); propertyName = propertyName(); } - expect(COLON); + Expression propertyValue; - defaultNames.push(propertyName); - try { - return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null); - } finally { - defaultNames.pop(); + if (generator) { + expectDontAdvance(LPAREN); } + + if (type == LPAREN && isES6()) { + propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode; + } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) { + propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName()); + if (type == ASSIGN && isES6()) { + // TODO if not destructuring, this is a SyntaxError + final long assignToken = token; + next(); + final Expression rhs = assignmentExpression(false); + propertyValue = verifyAssignment(assignToken, propertyValue, rhs); + } + } else { + expect(COLON); + + defaultNames.push(propertyName); + try { + propertyValue = assignmentExpression(false); + } finally { + defaultNames.pop(); + } + } + + return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed); } private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) { - final PropertyKey getIdent = propertyName(); - final String getterName = getIdent.getPropertyName(); - final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName)); + return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); + } + + private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) { + final boolean computed = type == LBRACKET; + final Expression propertyName = propertyName(); + final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); + final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName)); expect(LPAREN); expect(RPAREN); final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.emptyList()); + functionNode.setFlag(flags); + if (computed) { + functionNode.setFlag(FunctionNode.IS_ANONYMOUS); + } lc.push(functionNode); Block functionBody; @@ -2345,20 +3221,25 @@ loop: functionLine, functionBody); - return new PropertyFunction(getIdent, function); + return new PropertyFunction(propertyName, function, computed); } private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) { - final PropertyKey setIdent = propertyName(); - final String setterName = setIdent.getPropertyName(); - final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName)); + return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD); + } + + private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) { + final boolean computed = type == LBRACKET; + final Expression propertyName = propertyName(); + final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false); + final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName)); expect(LPAREN); // be sloppy and allow missing setter parameter even though // spec does not permit it! final IdentNode argIdent; - if (type == IDENT || isNonStrictModeIdent()) { + if (isBindingIdentifier()) { argIdent = getIdent(); - verifyStrictIdent(argIdent, "setter argument"); + verifyIdent(argIdent, "setter argument"); } else { argIdent = null; } @@ -2370,6 +3251,10 @@ loop: final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters); + functionNode.setFlag(flags); + if (computed) { + functionNode.setFlag(FunctionNode.IS_ANONYMOUS); + } lc.push(functionNode); Block functionBody; @@ -2389,33 +3274,81 @@ loop: functionLine, functionBody); - return new PropertyFunction(setIdent, function); + return new PropertyFunction(propertyName, function, computed); + } + + private PropertyFunction propertyMethodFunction(Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, boolean computed) { + final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false); + final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName); + + FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null); + functionNode.setFlag(flags); + if (computed) { + functionNode.setFlag(FunctionNode.IS_ANONYMOUS); + } + lc.push(functionNode); + + try { + final ParserContextBlockNode parameterBlock = newBlock(); + final List parameters; + try { + expect(LPAREN); + parameters = formalParameterList(generator); + functionNode.setParameters(parameters); + expect(RPAREN); + } finally { + restoreBlock(parameterBlock); + } + + Block functionBody = functionBody(functionNode); + + functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); + + final FunctionNode function = createFunctionNode( + functionNode, + methodToken, + methodNameNode, + parameters, + functionKind, + methodLine, + functionBody); + return new PropertyFunction(key, function, computed); + } finally { + lc.pop(functionNode); + } } private static class PropertyFunction { - final PropertyKey ident; + final Expression key; final FunctionNode functionNode; + final boolean computed; - PropertyFunction(final PropertyKey ident, final FunctionNode function) { - this.ident = ident; + PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) { + this.key = key; this.functionNode = function; + this.computed = computed; } } /** - * Parse left hand side expression. - * * LeftHandSideExpression : * NewExpression * CallExpression * * CallExpression : * MemberExpression Arguments + * SuperCall * CallExpression Arguments * CallExpression [ Expression ] * CallExpression . IdentifierName - * CallExpression TemplateLiteral * + * SuperCall : + * super Arguments + * + * See 11.2 + * + * Parse left hand side expression. * @return Expression node. */ private Expression leftHandSideExpression() { @@ -2435,7 +3368,7 @@ loop: lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); } -loop: + loop: while (true) { // Capture token. callLine = line; @@ -2479,6 +3412,7 @@ loop: // tagged template literal final List arguments = templateLiteralArgumentList(); + // Create call node. lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false); break; @@ -2506,6 +3440,20 @@ loop: // NEW is tested in caller. next(); + if (type == PERIOD && isES6()) { + next(); + if (type == IDENT && "target".equals(getValue())) { + if (lc.getCurrentFunction().isProgram()) { + throw error(AbstractParser.message("new.target.in.function"), token); + } + next(); + markNewTarget(lc); + return new IdentNode(newToken, finish, "new.target"); + } else { + throw error(AbstractParser.message("expected.target"), token); + } + } + // Get function base. final int callLine = line; final Expression constructor = memberExpression(); @@ -2541,21 +3489,33 @@ loop: } /** - * Parse member expression. - * * MemberExpression : * PrimaryExpression - * FunctionExpression + * FunctionExpression + * ClassExpression + * GeneratorExpression * MemberExpression [ Expression ] * MemberExpression . IdentifierName * MemberExpression TemplateLiteral + * SuperProperty + * MetaProperty * new MemberExpression Arguments * + * SuperProperty : + * super [ Expression ] + * super . IdentifierName + * + * MetaProperty : + * NewTarget + * + * Parse member expression. * @return Expression node. */ + @SuppressWarnings("fallthrough") private Expression memberExpression() { // Prepare to build operation. Expression lhs; + boolean isSuper = false; switch (type) { case NEW: @@ -2568,13 +3528,53 @@ loop: lhs = functionExpression(false, false); break; + case CLASS: + if (isES6()) { + lhs = classExpression(false); + break; + } else { + // fall through + } + + case SUPER: + if (isES6()) { + final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction(); + if (currentFunction.isMethod()) { + long identToken = Token.recast(token, IDENT); + next(); + lhs = createIdentNode(identToken, finish, SUPER.getName()); + + switch (type) { + case LBRACKET: + case PERIOD: + getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER); + isSuper = true; + break; + case LPAREN: + if (currentFunction.isSubclassConstructor()) { + lhs = ((IdentNode)lhs).setIsDirectSuper(); + break; + } else { + // fall through to throw error + } + default: + throw error(AbstractParser.message("invalid.super"), identToken); + } + break; + } else { + // fall through + } + } else { + // fall through + } + default: // Get primary expression. lhs = primaryExpression(); break; } -loop: + loop: while (true) { // Capture token. final long callToken = token; @@ -2591,6 +3591,11 @@ loop: // Create indexing node. lhs = new IndexNode(callToken, finish, lhs, index); + if (isSuper) { + isSuper = false; + lhs = ((BaseNode) lhs).setIsSuper(); + } + break; } case PERIOD: { @@ -2605,6 +3610,11 @@ loop: // Create property access node. lhs = new AccessNode(callToken, finish, lhs, property.getName()); + if (isSuper) { + isSuper = false; + lhs = ((BaseNode) lhs).setIsSuper(); + } + break; } case TEMPLATE: @@ -2632,7 +3642,9 @@ loop: * * ArgumentList : * AssignmentExpression + * ... AssignmentExpression * ArgumentList , AssignmentExpression + * ArgumentList , ... AssignmentExpression * * See 11.2 * @@ -2656,8 +3668,18 @@ loop: first = false; } + long spreadToken = 0; + if (type == ELLIPSIS && isES6()) { + spreadToken = token; + next(); + } + // Get argument expression. - nodeList.add(assignmentExpression(false)); + Expression expression = assignmentExpression(false); + if (spreadToken != 0) { + expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression); + } + nodeList.add(expression); } expect(RPAREN); @@ -2697,11 +3719,24 @@ loop: final long functionToken = token; final int functionLine = line; // FUNCTION is tested in caller. + assert type == FUNCTION; next(); + boolean generator = false; + if (type == MUL && isES6()) { + generator = true; + next(); + } + IdentNode name = null; - if (type == IDENT || isNonStrictModeIdent()) { + if (isBindingIdentifier()) { + if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) { + // 12.1.1 Early SyntaxError if: + // GeneratorExpression with BindingIdentifier yield + // HoistableDeclaration with BindingIdentifier yield in generator function body + expect(IDENT); + } name = getIdent(); verifyStrictIdent(name, "function name"); } else if (isStatement) { @@ -2723,25 +3758,36 @@ loop: isAnonymous = true; } - expect(LPAREN); - final List parameters = formalParameterList(); - expect(RPAREN); - - final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters); + FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL; + List parameters = Collections.emptyList(); + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters); lc.push(functionNode); + Block functionBody = null; // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}" // If we didn't hide the current default name, then the innermost anonymous function would receive "x3". hideDefaultName(); - try{ + try { + final ParserContextBlockNode parameterBlock = newBlock(); + try { + expect(LPAREN); + parameters = formalParameterList(generator); + functionNode.setParameters(parameters); + expect(RPAREN); + } finally { + restoreBlock(parameterBlock); + } + functionBody = functionBody(functionNode); + + functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); } finally { defaultNames.pop(); lc.pop(functionNode); } if (isStatement) { - if (topLevel || useBlockScope()) { + if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) { functionNode.setFlag(FunctionNode.IS_DECLARED); } else if (isStrictMode) { throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); @@ -2759,45 +3805,14 @@ loop: functionNode.setFlag(FunctionNode.IS_ANONYMOUS); } - final int arity = parameters.size(); - - final boolean strict = functionNode.isStrict(); - if (arity > 1) { - final HashSet parametersSet = new HashSet<>(arity); - - for (int i = arity - 1; i >= 0; i--) { - final IdentNode parameter = parameters.get(i); - String parameterName = parameter.getName(); - - if (isArguments(parameterName)) { - functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS); - } - - if (parametersSet.contains(parameterName)) { - // redefinition of parameter name - if (strict) { - throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken()); - } - // rename in non-strict mode - parameterName = functionNode.uniqueName(parameterName); - final long parameterToken = parameter.getToken(); - parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName))); - } - - parametersSet.add(parameterName); - } - } else if (arity == 1) { - if (isArguments(parameters.get(0))) { - functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS); - } - } + verifyParameterList(parameters, functionNode); final FunctionNode function = createFunctionNode( functionNode, functionToken, name, parameters, - FunctionNode.Kind.NORMAL, + functionKind, functionLine, functionBody); @@ -2822,6 +3837,40 @@ loop: return function; } + private void verifyParameterList(final List parameters, final ParserContextFunctionNode functionNode) { + final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding(); + if (duplicateParameter != null) { + if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) { + throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken()); + } + + final int arity = parameters.size(); + final HashSet parametersSet = new HashSet<>(arity); + + for (int i = arity - 1; i >= 0; i--) { + final IdentNode parameter = parameters.get(i); + String parameterName = parameter.getName(); + + if (parametersSet.contains(parameterName)) { + // redefinition of parameter name, rename in non-strict mode + parameterName = functionNode.uniqueName(parameterName); + final long parameterToken = parameter.getToken(); + parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName))); + } + parametersSet.add(parameterName); + } + } + } + + private static Block maybeWrapBodyInParameterBlock(Block functionBody, ParserContextBlockNode parameterBlock) { + assert functionBody.isFunctionBody(); + if (!parameterBlock.getStatements().isEmpty()) { + parameterBlock.appendStatement(new BlockStatement(functionBody)); + return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements()); + } + return functionBody; + } + private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) { final String defaultFunctionName = getDefaultFunctionName(); if (isValidIdentifier(defaultFunctionName)) { @@ -2836,14 +3885,14 @@ loop: } private static boolean isValidIdentifier(final String name) { - if(name == null || name.isEmpty()) { + if (name == null || name.isEmpty()) { return false; } - if(!Character.isJavaIdentifierStart(name.charAt(0))) { + if (!Character.isJavaIdentifierStart(name.charAt(0))) { return false; } - for(int i = 1; i < name.length(); ++i) { - if(!Character.isJavaIdentifierPart(name.charAt(i))) { + for (int i = 1; i < name.length(); ++i) { + if (!Character.isJavaIdentifierPart(name.charAt(i))) { return false; } } @@ -2851,12 +3900,12 @@ loop: } private String getDefaultFunctionName() { - if(!defaultNames.isEmpty()) { + if (!defaultNames.isEmpty()) { final Object nameExpr = defaultNames.peek(); - if(nameExpr instanceof PropertyKey) { + if (nameExpr instanceof PropertyKey) { markDefaultNameUsed(); return ((PropertyKey)nameExpr).getPropertyName(); - } else if(nameExpr instanceof AccessNode) { + } else if (nameExpr instanceof AccessNode) { markDefaultNameUsed(); return ((AccessNode)nameExpr).getProperty(); } @@ -2885,8 +3934,8 @@ loop: * Parse function parameter list. * @return List of parameter nodes. */ - private List formalParameterList() { - return formalParameterList(RPAREN); + private List formalParameterList(final boolean yield) { + return formalParameterList(RPAREN, yield); } /** @@ -2902,7 +3951,7 @@ loop: * Parse function parameter list. * @return List of parameter nodes. */ - private List formalParameterList(final TokenType endType) { + private List formalParameterList(final TokenType endType, final boolean yield) { // Prepare to gather parameters. final ArrayList parameters = new ArrayList<>(); // Track commas. @@ -2916,12 +3965,84 @@ loop: first = false; } - // Get and add parameter. - final IdentNode ident = getIdent(); + boolean restParameter = false; + if (type == ELLIPSIS && isES6()) { + next(); + restParameter = true; + } - // ECMA 13.1 strict mode restrictions - verifyStrictIdent(ident, "function parameter"); + if (type == YIELD && yield) { + expect(IDENT); + } + final long paramToken = token; + final int paramLine = line; + final String contextString = "function parameter"; + IdentNode ident; + if (isBindingIdentifier() || restParameter || !isES6()) { + ident = bindingIdentifier(contextString); + + if (restParameter) { + ident = ident.setIsRestParameter(); + // rest parameter must be last + expectDontAdvance(endType); + parameters.add(ident); + break; + } else if (type == ASSIGN && isES6()) { + next(); + ident = ident.setIsDefaultParameter(); + + if (type == YIELD && yield) { + // error: yield in default expression + expect(IDENT); + } + + // default parameter + Expression initializer = assignmentExpression(false); + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + // desugar to: param = (param === undefined) ? initializer : param; + // possible alternative: if (param === undefined) param = initializer; + BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); + TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); + BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); + lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); + } + } + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + currentFunction.addParameterBinding(ident); + if (ident.isRestParameter() || ident.isDefaultParameter()) { + currentFunction.setSimpleParameterList(false); + } + } + } else { + final Expression pattern = bindingPattern(); + // Introduce synthetic temporary parameter to capture the object to be destructured. + ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter(); + verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString); + + Expression value = ident; + if (type == ASSIGN) { + next(); + ident = ident.setIsDefaultParameter(); + + // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param + Expression initializer = assignmentExpression(false); + // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list) + BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); + value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); + } + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + // destructuring assignment + BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value); + lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); + } + } parameters.add(ident); } @@ -2929,6 +4050,23 @@ loop: return parameters; } + private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) { + verifyDestructuringBindingPattern(pattern, new Consumer() { + public void accept(IdentNode identNode) { + verifyIdent(identNode, contextString); + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + // declare function-scope variables for destructuring bindings + lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null)); + // detect duplicate bounds names in parameter list + currentFunction.addParameterBinding(identNode); + currentFunction.setSimpleParameterList(false); + } + } + }); + } + /** * FunctionBody : * SourceElements? @@ -2958,7 +4096,7 @@ loop: final int functionId = functionNode.getId(); parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId(); // Nashorn extension: expression closures - if (!env._no_syntax_extensions && type != LBRACE) { + if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) { /* * Example: * @@ -2967,7 +4105,7 @@ loop: */ // just expression as function body - final Expression expr = assignmentExpression(true); + final Expression expr = assignmentExpression(false); lastToken = previousToken; functionNode.setLastToken(previousToken); assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); @@ -2982,6 +4120,7 @@ loop: final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); appendStatement(returnNode); } + // bodyFinish = finish; } else { expectDontAdvance(LBRACE); if (parseBody || !skipFunctionBody(functionNode)) { @@ -3054,7 +4193,7 @@ loop: } } } - functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements()); + functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements()); return functionBody; } @@ -3095,8 +4234,7 @@ loop: // Doesn't really matter, but it's safe to treat it as if there were a semicolon before // the RBRACE. type = SEMICOLON; - k = -1; - next(); + scanFirstToken(); return true; } @@ -3126,11 +4264,11 @@ loop: } private void printAST(final FunctionNode functionNode) { - if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) { + if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) { env.getErr().println(new ASTWriter(functionNode)); } - if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) { + if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) { env.getErr().println(new PrintVisitor(functionNode, true, false)); } } @@ -3222,20 +4360,7 @@ loop: throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); } - if (!(lhs instanceof AccessNode || - lhs instanceof IndexNode || - lhs instanceof IdentNode)) { - return referenceError(lhs, null, env._early_lvalue_error); - } - - if (lhs instanceof IdentNode) { - if (!checkIdentLValue((IdentNode)lhs)) { - return referenceError(lhs, null, false); - } - verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); - } - - return incDecExpression(unaryToken, opType, lhs, false); + return verifyIncDecExpression(unaryToken, opType, lhs, false); default: break; @@ -3247,29 +4372,16 @@ loop: switch (type) { case INCPREFIX: case DECPREFIX: + final long opToken = token; final TokenType opType = type; final Expression lhs = expression; // ++, -- without operand.. if (lhs == null) { throw error(AbstractParser.message("expected.lvalue", type.getNameOrType())); } - - if (!(lhs instanceof AccessNode || - lhs instanceof IndexNode || - lhs instanceof IdentNode)) { - next(); - return referenceError(lhs, null, env._early_lvalue_error); - } - if (lhs instanceof IdentNode) { - if (!checkIdentLValue((IdentNode)lhs)) { - next(); - return referenceError(lhs, null, false); - } - verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); - } - expression = incDecExpression(token, type, expression, true); next(); - break; + + return verifyIncDecExpression(opToken, opType, lhs, true); default: break; } @@ -3282,6 +4394,25 @@ loop: return expression; } + private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) { + assert lhs != null; + + if (!(lhs instanceof AccessNode || + lhs instanceof IndexNode || + lhs instanceof IdentNode)) { + return referenceError(lhs, null, env._early_lvalue_error); + } + + if (lhs instanceof IdentNode) { + if (!checkIdentLValue((IdentNode)lhs)) { + return referenceError(lhs, null, false); + } + verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator"); + } + + return incDecExpression(unaryToken, opType, lhs, isPostfix); + } + /** * {@code * MultiplicativeExpression : @@ -3380,7 +4511,42 @@ loop: // at expression start point! // Include commas in expression parsing. - return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false); + return expression(false); + } + + private Expression expression(final boolean noIn) { + Expression assignmentExpression = assignmentExpression(noIn); + while (type == COMMARIGHT) { + long commaToken = token; + next(); + + boolean rhsRestParameter = false; + if (type == ELLIPSIS && isES6()) { + // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error). + // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead. + if (isRestParameterEndOfArrowFunctionParameterList()) { + next(); + rhsRestParameter = true; + } + } + + Expression rhs = assignmentExpression(noIn); + + if (rhsRestParameter) { + rhs = ((IdentNode)rhs).setIsRestParameter(); + // Our only valid move is to end Expression here and continue with ArrowFunction. + // We've already checked that this is the parameter list of an arrow function (see above). + // RPAREN is next, so we'll finish the binary expression and drop out of the loop. + assert type == RPAREN; + } + + assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs); + } + return assignmentExpression; + } + + private Expression expression(final int minPrecedence, final boolean noIn) { + return expression(unaryExpression(), minPrecedence, noIn); } private JoinPredecessorExpression joinPredecessorExpression() { @@ -3448,12 +4614,316 @@ loop: return lhs; } + /** + * AssignmentExpression. + * + * AssignmentExpression[In, Yield] : + * ConditionalExpression[?In, ?Yield] + * [+Yield] YieldExpression[?In] + * ArrowFunction[?In, ?Yield] + * LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield] + * LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield] + */ protected Expression assignmentExpression(final boolean noIn) { // This method is protected so that subclass can get details // at assignment expression start point! - // Exclude commas in expression parsing. - return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn); + if (type == YIELD && inGeneratorFunction() && isES6()) { + return yieldExpression(noIn); + } + + final long startToken = token; + final int startLine = line; + final Expression exprLhs = conditionalExpression(noIn); + + if (type == ARROW && isES6()) { + if (checkNoLineTerminator()) { + final Expression paramListExpr; + if (exprLhs instanceof ExpressionList) { + paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0)); + } else { + paramListExpr = exprLhs; + } + return arrowFunction(startToken, startLine, paramListExpr); + } + } + assert !(exprLhs instanceof ExpressionList); + + if (isAssignmentOperator(type)) { + final boolean isAssign = type == ASSIGN; + if (isAssign) { + defaultNames.push(exprLhs); + } + try { + final long assignToken = token; + next(); + final Expression exprRhs = assignmentExpression(noIn); + return verifyAssignment(assignToken, exprLhs, exprRhs); + } finally { + if (isAssign) { + defaultNames.pop(); + } + } + } else { + return exprLhs; + } + } + + /** + * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}? + */ + private static boolean isAssignmentOperator(TokenType type) { + switch (type) { + case ASSIGN: + case ASSIGN_ADD: + case ASSIGN_BIT_AND: + case ASSIGN_BIT_OR: + case ASSIGN_BIT_XOR: + case ASSIGN_DIV: + case ASSIGN_MOD: + case ASSIGN_MUL: + case ASSIGN_SAR: + case ASSIGN_SHL: + case ASSIGN_SHR: + case ASSIGN_SUB: + return true; + } + return false; + } + + /** + * ConditionalExpression. + */ + private Expression conditionalExpression(boolean noIn) { + return expression(TERNARY.getPrecedence(), noIn); + } + + /** + * ArrowFunction. + * + * @param startToken start token of the ArrowParameters expression + * @param functionLine start line of the arrow function + * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list) + */ + private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) { + // caller needs to check that there's no LineTerminator between parameter list and arrow + assert type != ARROW || checkNoLineTerminator(); + expect(ARROW); + + final long functionToken = Token.recast(startToken, ARROW); + final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), "=>:" + functionLine); + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null); + functionNode.setFlag(FunctionNode.IS_ANONYMOUS); + + lc.push(functionNode); + try { + ParserContextBlockNode parameterBlock = newBlock(); + final List parameters; + try { + parameters = convertArrowFunctionParameterList(paramListExpr, functionLine); + functionNode.setParameters(parameters); + + if (!functionNode.isSimpleParameterList()) { + markEvalInArrowParameterList(parameterBlock); + } + } finally { + restoreBlock(parameterBlock); + } + Block functionBody = functionBody(functionNode); + + functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock); + + verifyParameterList(parameters, functionNode); + + final FunctionNode function = createFunctionNode( + functionNode, + functionToken, + name, + parameters, + FunctionNode.Kind.ARROW, + functionLine, + functionBody); + return function; + } finally { + lc.pop(functionNode); + } + } + + private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) { + final Iterator iter = lc.getFunctions(); + final ParserContextFunctionNode current = iter.next(); + final ParserContextFunctionNode parent = iter.next(); + + if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) { + // we might have flagged has-eval in the parent function during parsing the parameter list, + // if the parameter list contains eval; must tag arrow function as has-eval. + for (final Statement st : parameterBlock.getStatements()) { + st.accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterCallNode(final CallNode callNode) { + if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) { + current.setFlag(FunctionNode.HAS_EVAL); + } + return true; + } + }); + } + // TODO: function containing the arrow function should not be flagged has-eval + } + } + + private List convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) { + final List parameters; + if (paramListExpr == null) { + // empty parameter list, i.e. () => + parameters = Collections.emptyList(); + } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) { + parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine)); + } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) { + parameters = new ArrayList<>(); + Expression car = paramListExpr; + do { + final Expression cdr = ((BinaryNode) car).rhs(); + parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine)); + car = ((BinaryNode) car).lhs(); + } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT); + parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine)); + } else { + throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken()); + } + return parameters; + } + + private IdentNode verifyArrowParameter(Expression param, int index, int paramLine) { + final String contextString = "function parameter"; + if (param instanceof IdentNode) { + IdentNode ident = (IdentNode)param; + verifyStrictIdent(ident, contextString); + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + currentFunction.addParameterBinding(ident); + } + return ident; + } + + if (param.isTokenType(ASSIGN)) { + Expression lhs = ((BinaryNode) param).lhs(); + long paramToken = lhs.getToken(); + Expression initializer = ((BinaryNode) param).rhs(); + if (lhs instanceof IdentNode) { + // default parameter + IdentNode ident = (IdentNode) lhs; + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); + TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); + BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value); + lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); + + currentFunction.addParameterBinding(ident); + currentFunction.setSimpleParameterList(false); + } + return ident; + } else if (isDestructuringLhs(lhs)) { + // binding pattern with initializer + // Introduce synthetic temporary parameter to capture the object to be destructured. + IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter(); + verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish)); + TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident)); + BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value); + lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); + } + return ident; + } + } else if (isDestructuringLhs(param)) { + // binding pattern + long paramToken = param.getToken(); + + // Introduce synthetic temporary parameter to capture the object to be destructured. + IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter(); + verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString); + + ParserContextFunctionNode currentFunction = lc.getCurrentFunction(); + if (currentFunction != null) { + BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident); + lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment)); + } + return ident; + } + throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken()); + } + + private boolean checkNoLineTerminator() { + assert type == ARROW; + if (last == RPAREN) { + return true; + } else if (last == IDENT) { + return true; + } + for (int i = k - 1; i >= 0; i--) { + TokenType t = T(i); + switch (t) { + case RPAREN: + case IDENT: + return true; + case EOL: + return false; + case COMMENT: + continue; + default: + if (t.getKind() == TokenKind.FUTURESTRICT) { + return true; + } + return false; + } + } + return false; + } + + /** + * Peek ahead to see if what follows after the ellipsis is a rest parameter + * at the end of an arrow function parameter list. + */ + private boolean isRestParameterEndOfArrowFunctionParameterList() { + assert type == ELLIPSIS; + // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT + int i = 1; + for (;;) { + TokenType t = T(k + i++); + if (t == IDENT) { + break; + } else if (t == EOL || t == COMMENT) { + continue; + } else { + return false; + } + } + for (;;) { + TokenType t = T(k + i++); + if (t == RPAREN) { + break; + } else if (t == EOL || t == COMMENT) { + continue; + } else { + return false; + } + } + for (;;) { + TokenType t = T(k + i++); + if (t == ARROW) { + break; + } else if (t == COMMENT) { + continue; + } else { + return false; + } + } + return true; } /** @@ -3551,6 +5021,380 @@ loop: cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString)); } + + /** + * Parse a module. + * + * Module : + * ModuleBody? + * + * ModuleBody : + * ModuleItemList + */ + private FunctionNode module(final String moduleName) { + boolean oldStrictMode = isStrictMode; + try { + isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1) + + // Make a pseudo-token for the script holding its start and length. + int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish); + final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart); + final int functionLine = line; + + final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName); + final ParserContextFunctionNode script = createParserContextFunctionNode( + ident, + functionToken, + FunctionNode.Kind.MODULE, + functionLine, + Collections.emptyList()); + lc.push(script); + + final ParserContextModuleNode module = new ParserContextModuleNode(moduleName); + lc.push(module); + + final ParserContextBlockNode body = newBlock(); + + functionDeclarations = new ArrayList<>(); + moduleBody(); + addFunctionDeclarations(script); + functionDeclarations = null; + + restoreBlock(body); + body.setFlag(Block.NEEDS_SCOPE); + final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements()); + lc.pop(module); + lc.pop(script); + script.setLastToken(token); + + expect(EOF); + + script.setModule(module.createModule()); + return createFunctionNode(script, functionToken, ident, Collections.emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody); + } finally { + isStrictMode = oldStrictMode; + } + } + + /** + * Parse module body. + * + * ModuleBody : + * ModuleItemList + * + * ModuleItemList : + * ModuleItem + * ModuleItemList ModuleItem + * + * ModuleItem : + * ImportDeclaration + * ExportDeclaration + * StatementListItem + */ + private void moduleBody() { + loop: + while (type != EOF) { + switch (type) { + case EOF: + break loop; + case IMPORT: + importDeclaration(); + break; + case EXPORT: + exportDeclaration(); + break; + default: + // StatementListItem + statement(true, false, false, false); + break; + } + } + } + + + /** + * Parse import declaration. + * + * ImportDeclaration : + * import ImportClause FromClause ; + * import ModuleSpecifier ; + * ImportClause : + * ImportedDefaultBinding + * NameSpaceImport + * NamedImports + * ImportedDefaultBinding , NameSpaceImport + * ImportedDefaultBinding , NamedImports + * ImportedDefaultBinding : + * ImportedBinding + * ModuleSpecifier : + * StringLiteral + * ImportedBinding : + * BindingIdentifier + */ + private void importDeclaration() { + expect(IMPORT); + final ParserContextModuleNode module = lc.getCurrentModule(); + if (type == STRING || type == ESCSTRING) { + // import ModuleSpecifier ; + final String moduleSpecifier = (String) getValue(); + next(); + module.addModuleRequest(moduleSpecifier); + } else { + // import ImportClause FromClause ; + List importEntries; + if (type == MUL) { + importEntries = Collections.singletonList(nameSpaceImport()); + } else if (type == LBRACE) { + importEntries = namedImports(); + } else if (isBindingIdentifier()) { + // ImportedDefaultBinding + final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding"); + Module.ImportEntry defaultImport = Module.ImportEntry.importDefault(importedDefaultBinding.getName()); + + if (type == COMMARIGHT) { + next(); + importEntries = new ArrayList<>(); + if (type == MUL) { + importEntries.add(nameSpaceImport()); + } else if (type == LBRACE) { + importEntries.addAll(namedImports()); + } else { + throw error(AbstractParser.message("expected.named.import")); + } + } else { + importEntries = Collections.singletonList(defaultImport); + } + } else { + throw error(AbstractParser.message("expected.import")); + } + + final String moduleSpecifier = fromClause(); + module.addModuleRequest(moduleSpecifier); + for (int i = 0; i < importEntries.size(); i++) { + module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier)); + } + } + expect(SEMICOLON); + } + + /** + * NameSpaceImport : + * * as ImportedBinding + * + * @return imported binding identifier + */ + private Module.ImportEntry nameSpaceImport() { + assert type == MUL; + next(); + final long asToken = token; + final String as = (String) expectValue(IDENT); + if (!"as".equals(as)) { + throw error(AbstractParser.message("expected.as"), asToken); + } + final IdentNode localNameSpace = bindingIdentifier("ImportedBinding"); + return Module.ImportEntry.importStarAsNameSpaceFrom(localNameSpace.getName()); + } + + /** + * NamedImports : + * { } + * { ImportsList } + * { ImportsList , } + * ImportsList : + * ImportSpecifier + * ImportsList , ImportSpecifier + * ImportSpecifier : + * ImportedBinding + * IdentifierName as ImportedBinding + * ImportedBinding : + * BindingIdentifier + */ + private List namedImports() { + assert type == LBRACE; + next(); + List importEntries = new ArrayList<>(); + while (type != RBRACE) { + final boolean bindingIdentifier = isBindingIdentifier(); + final long nameToken = token; + final IdentNode importName = getIdentifierName(); + if (type == IDENT && "as".equals(getValue())) { + next(); + final IdentNode localName = bindingIdentifier("ImportedBinding"); + importEntries.add(Module.ImportEntry.importSpecifier(importName.getName(), localName.getName())); + } else if (!bindingIdentifier) { + throw error(AbstractParser.message("expected.binding.identifier"), nameToken); + } else { + importEntries.add(Module.ImportEntry.importSpecifier(importName.getName())); + } + if (type == COMMARIGHT) { + next(); + } else { + break; + } + } + expect(RBRACE); + return importEntries; + } + + /** + * FromClause : + * from ModuleSpecifier + */ + private String fromClause() { + final long fromToken = token; + final String name = (String) expectValue(IDENT); + if (!"from".equals(name)) { + throw error(AbstractParser.message("expected.from"), fromToken); + } + if (type == STRING || type == ESCSTRING) { + final String moduleSpecifier = (String) getValue(); + next(); + return moduleSpecifier; + } else { + throw error(expectMessage(STRING)); + } + } + + /** + * Parse export declaration. + * + * ExportDeclaration : + * export * FromClause ; + * export ExportClause FromClause ; + * export ExportClause ; + * export VariableStatement + * export Declaration + * export default HoistableDeclaration[Default] + * export default ClassDeclaration[Default] + * export default [lookahead !in {function, class}] AssignmentExpression[In] ; + */ + private void exportDeclaration() { + expect(EXPORT); + final ParserContextModuleNode module = lc.getCurrentModule(); + switch (type) { + case MUL: { + next(); + final String moduleRequest = fromClause(); + expect(SEMICOLON); + module.addModuleRequest(moduleRequest); + module.addStarExportEntry(Module.ExportEntry.exportStarFrom(moduleRequest)); + break; + } + case LBRACE: { + final List exportEntries = exportClause(); + if (type == IDENT && "from".equals(getValue())) { + final String moduleRequest = fromClause(); + module.addModuleRequest(moduleRequest); + for (Module.ExportEntry exportEntry : exportEntries) { + module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest)); + } + } else { + for (Module.ExportEntry exportEntry : exportEntries) { + module.addLocalExportEntry(exportEntry); + } + } + expect(SEMICOLON); + break; + } + case DEFAULT: + next(); + final Expression assignmentExpression; + IdentNode ident; + final int lineNumber = line; + final long rhsToken = token; + final boolean declaration; + switch (type) { + case FUNCTION: + assignmentExpression = functionExpression(false, true); + ident = ((FunctionNode) assignmentExpression).getIdent(); + declaration = true; + break; + case CLASS: + assignmentExpression = classDeclaration(true); + ident = ((ClassNode) assignmentExpression).getIdent(); + declaration = true; + break; + default: + assignmentExpression = assignmentExpression(false); + ident = null; + declaration = false; + break; + } + if (ident != null) { + module.addLocalExportEntry(Module.ExportEntry.exportDefault(ident.getName())); + } else { + ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME); + lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression)); + if (!declaration) { + expect(SEMICOLON); + } + module.addLocalExportEntry(Module.ExportEntry.exportDefault()); + } + break; + case VAR: + case LET: + case CONST: + final List statements = lc.getCurrentBlock().getStatements(); + final int previousEnd = statements.size(); + variableStatement(type); + for (final Statement statement : statements.subList(previousEnd, statements.size())) { + if (statement instanceof VarNode) { + module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName().getName())); + } + } + break; + case CLASS: { + final ClassNode classDeclaration = classDeclaration(false); + module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent().getName())); + break; + } + case FUNCTION: { + final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true); + module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent().getName())); + break; + } + default: + throw error(AbstractParser.message("invalid.export"), token); + } + } + + /** + * ExportClause : + * { } + * { ExportsList } + * { ExportsList , } + * ExportsList : + * ExportSpecifier + * ExportsList , ExportSpecifier + * ExportSpecifier : + * IdentifierName + * IdentifierName as IdentifierName + * + * @return a list of ExportSpecifiers + */ + private List exportClause() { + assert type == LBRACE; + next(); + List exports = new ArrayList<>(); + while (type != RBRACE) { + final IdentNode localName = getIdentifierName(); + if (type == IDENT && "as".equals(getValue())) { + next(); + final IdentNode exportName = getIdentifierName(); + exports.add(Module.ExportEntry.exportSpecifier(exportName.getName(), localName.getName())); + } else { + exports.add(Module.ExportEntry.exportSpecifier(localName.getName())); + } + if (type == COMMARIGHT) { + next(); + } else { + break; + } + } + expect(RBRACE); + return exports; + } + @Override public String toString() { return "'JavaScript Parsing'"; @@ -3564,6 +5408,12 @@ loop: if (!flaggedCurrentFn) { fn.setFlag(FunctionNode.HAS_EVAL); flaggedCurrentFn = true; + if (fn.getKind() == FunctionNode.Kind.ARROW) { + // possible use of this in an eval that's nested in an arrow function, e.g.: + // function fun(){ return (() => eval("this"))(); }; + markThis(lc); + markNewTarget(lc); + } } else { fn.setFlag(FunctionNode.HAS_NESTED_EVAL); } @@ -3583,4 +5433,55 @@ loop: private void appendStatement(final Statement statement) { lc.appendStatementToCurrentNode(statement); } + + private static void markSuperCall(final ParserContext lc) { + final Iterator iter = lc.getFunctions(); + while (iter.hasNext()) { + final ParserContextFunctionNode fn = iter.next(); + if (fn.getKind() != FunctionNode.Kind.ARROW) { + assert fn.isSubclassConstructor(); + fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER); + break; + } + } + } + + private ParserContextFunctionNode getCurrentNonArrowFunction() { + final Iterator iter = lc.getFunctions(); + while (iter.hasNext()) { + final ParserContextFunctionNode fn = iter.next(); + if (fn.getKind() != FunctionNode.Kind.ARROW) { + return fn; + } + } + return null; + } + + private static void markThis(final ParserContext lc) { + final Iterator iter = lc.getFunctions(); + while (iter.hasNext()) { + final ParserContextFunctionNode fn = iter.next(); + fn.setFlag(FunctionNode.USES_THIS); + if (fn.getKind() != FunctionNode.Kind.ARROW) { + break; + } + } + } + + private static void markNewTarget(final ParserContext lc) { + final Iterator iter = lc.getFunctions(); + while (iter.hasNext()) { + final ParserContextFunctionNode fn = iter.next(); + if (fn.getKind() != FunctionNode.Kind.ARROW) { + if (!fn.isProgram()) { + fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET); + } + break; + } + } + } + + private boolean inGeneratorFunction() { + return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR; + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java index b2de378265b..fd2476a7c18 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java @@ -278,7 +278,12 @@ class ParserContext { return new NodeIterator<>(ParserContextFunctionNode.class); } - private class NodeIterator implements Iterator { + public ParserContextModuleNode getCurrentModule() { + final Iterator iter = new NodeIterator<>(ParserContextModuleNode.class, getCurrentFunction()); + return iter.hasNext() ? iter.next() : null; + } + + private class NodeIterator implements Iterator { private int index; private T next; private final Class clazz; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java index 5418caff915..cfd8b293071 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java @@ -24,10 +24,12 @@ */ package jdk.nashorn.internal.parser; +import java.util.HashSet; import java.util.List; import jdk.nashorn.internal.codegen.Namespace; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.IdentNode; +import jdk.nashorn.internal.ir.Module; /** * ParserContextNode that represents a function that is currently being parsed @@ -46,11 +48,11 @@ class ParserContextFunctionNode extends ParserContextBaseNode { /** Line number for function declaration */ private final int line; - /** Function node kind, see {@link FunctionNode#Kind} */ + /** Function node kind, see {@link FunctionNode.Kind} */ private final FunctionNode.Kind kind; /** List of parameter identifiers for function */ - private final List parameters; + private List parameters; /** Token for function start */ private final long token; @@ -61,6 +63,14 @@ class ParserContextFunctionNode extends ParserContextBaseNode { /** Opaque node for parser end state, see {@link Parser} */ private Object endParserState; + private HashSet parameterBoundNames; + private IdentNode duplicateParameterBinding; + private boolean simpleParameterList = true; + + private Module module; + + private int debugFlags; + /** * @param token The token for the function * @param ident External function name @@ -155,6 +165,10 @@ class ParserContextFunctionNode extends ParserContextBaseNode { return parameters; } + void setParameters(List parameters) { + this.parameters = parameters; + } + /** * Set last token * @param token New last token @@ -194,4 +208,70 @@ class ParserContextFunctionNode extends ParserContextBaseNode { public int getId() { return isProgram() ? -1 : Token.descPosition(token); } + + /** + * Returns the debug flags for this function. + * + * @return the debug flags + */ + int getDebugFlags() { + return debugFlags; + } + + /** + * Sets a debug flag for this function. + * + * @param debugFlag the debug flag + */ + void setDebugFlag(final int debugFlag) { + debugFlags |= debugFlag; + } + + public boolean isMethod() { + return getFlag(FunctionNode.ES6_IS_METHOD) != 0; + } + + public boolean isClassConstructor() { + return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0; + } + + public boolean isSubclassConstructor() { + return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0; + } + + boolean addParameterBinding(final IdentNode bindingIdentifier) { + if (Parser.isArguments(bindingIdentifier)) { + setFlag(FunctionNode.DEFINES_ARGUMENTS); + } + + if (parameterBoundNames == null) { + parameterBoundNames = new HashSet<>(); + } + if (parameterBoundNames.add(bindingIdentifier.getName())) { + return true; + } else { + duplicateParameterBinding = bindingIdentifier; + return false; + } + } + + public IdentNode getDuplicateParameterBinding() { + return duplicateParameterBinding; + } + + public boolean isSimpleParameterList() { + return simpleParameterList; + } + + public void setSimpleParameterList(final boolean simpleParameterList) { + this.simpleParameterList = simpleParameterList; + } + + public Module getModule() { + return module; + } + + public void setModule(final Module module) { + this.module = module; + } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java new file mode 100644 index 00000000000..0c883351682 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java @@ -0,0 +1,90 @@ +/* + * 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 jdk.nashorn.internal.parser; + +import java.util.ArrayList; +import java.util.List; + +import jdk.nashorn.internal.ir.Module; +import jdk.nashorn.internal.ir.Module.ExportEntry; +import jdk.nashorn.internal.ir.Module.ImportEntry; + +/** + * ParserContextNode that represents a module. + */ +class ParserContextModuleNode extends ParserContextBaseNode { + + /** Module name. */ + private final String name; + + private List requestedModules = new ArrayList<>(); + private List importEntries = new ArrayList<>(); + private List localExportEntries = new ArrayList<>(); + private List indirectExportEntries = new ArrayList<>(); + private List starExportEntries = new ArrayList<>(); + + /** + * Constructor. + * + * @param name name of the module + */ + ParserContextModuleNode(final String name) { + this.name = name; + } + + /** + * Returns the name of the module. + * + * @return name of the module + */ + public String getModuleName() { + return name; + } + + public void addModuleRequest(final String moduleRequest) { + requestedModules.add(moduleRequest); + } + + public void addImportEntry(final ImportEntry importEntry) { + importEntries.add(importEntry); + } + + public void addLocalExportEntry(final ExportEntry exportEntry) { + localExportEntries.add(exportEntry); + } + + public void addIndirectExportEntry(final ExportEntry exportEntry) { + indirectExportEntries.add(exportEntry); + } + + public void addStarExportEntry(final ExportEntry exportEntry) { + starExportEntries.add(exportEntry); + } + + public Module createModule() { + return new Module(requestedModules, importEntries, localExportEntries, indirectExportEntries, starExportEntries); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java index af9f40a4e8c..080c147d588 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java @@ -82,7 +82,7 @@ public enum TokenType { ASSIGN (BINARY, "=", 2, false), EQ (BINARY, "==", 9, true), EQ_STRICT (BINARY, "===", 9, true), - BIND (BINARY, "=>", 9, true), + ARROW (BINARY, "=>", 2, true), GT (BINARY, ">", 10, true), GE (BINARY, ">=", 10, true), SAR (BINARY, ">>", 11, true), @@ -100,6 +100,7 @@ public enum TokenType { OR (BINARY, "||", 4, true), RBRACE (BRACKET, "}"), BIT_NOT (UNARY, "~", 14, false), + ELLIPSIS (UNARY, "..."), // ECMA 7.6.1.1 Keywords, 7.6.1.2 Future Reserved Words. // All other Java keywords are commented out. @@ -190,7 +191,10 @@ public enum TokenType { COMMALEFT (IR, null), DECPOSTFIX (IR, null), - INCPOSTFIX (IR, null); + INCPOSTFIX (IR, null), + SPREAD_ARGUMENT(IR, null), + SPREAD_ARRAY (IR, null), + YIELD_STAR (IR, null); /** Next token kind in token lookup table. */ private TokenType next; @@ -251,7 +255,6 @@ public enum TokenType { return kind == BINARY && (!noIn || this != IN) && precedence != 0; } - public int getLength() { assert name != null : "Token name not set"; return name.length(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index 64a67d89eb1..94f224e2b22 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -1403,11 +1403,11 @@ public final class Context { return null; } - if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) { + if (env._print_ast || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) { getErr().println(new ASTWriter(functionNode)); } - if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) { + if (env._print_parse || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) { getErr().println(new PrintVisitor(functionNode, true, false)); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties index fb5ccf0cbdf..0116fb4d452 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -63,6 +63,27 @@ parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON parser.error.missing.const.assignment=Missing assignment to constant "{0}" parser.error.unterminated.template.expression=Expected } after expression in template literal +# ES6 mode error messages +parser.error.multiple.constructors=Class contains more than one constructor +parser.error.generator.constructor=Class constructor must not be a generator +parser.error.accessor.constructor=Class constructor must not be an accessor +parser.error.static.prototype.method=Static class method must not be named 'prototype' +parser.error.missing.destructuring.assignment=Missing assignment in destructuring declaration +parser.error.let.binding.for='let' is not a valid binding name in a for loop +parser.error.invalid.export=invalid export declaration +parser.error.expected.binding=expected BindingIdentifier or BindingPattern +parser.error.multiple.proto.key=property name __proto__ appears more than once in object literal +parser.error.new.target.in.function=new.target expression is only allowed in functions +parser.error.expected.target=expected 'target' +parser.error.invalid.super=invalid use of keyword super +parser.error.expected.arrow.parameter=expected arrow function parameter list +parser.error.invalid.arrow.parameter=invalid arrow function parameter +parser.error.expected.named.import=expected NameSpaceImport or NamedImports +parser.error.expected.import=expected ImportClause or ModuleSpecifier +parser.error.expected.as=expected 'as' +parser.error.expected.binding.identifier=expected BindingIdentifier +parser.error.expected.from=expected 'from' + # strict mode error messages parser.error.strict.no.with="with" statement cannot be used in strict mode parser.error.strict.name="{0}" cannot be used as {1} in strict mode diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java index 5142fcd46c1..a7bee7c286b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java @@ -438,6 +438,9 @@ public class Shell implements PartialParser { final File file = new File(fileName); final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global); if (script == null || errors.getNumberOfErrors() != 0) { + if (context.getEnv()._parse_only && !errors.hasErrors()) { + continue; // No error, continue to consume all files in list + } return COMPILATION_ERROR; } diff --git a/nashorn/test/script/basic/yield.js b/nashorn/test/script/basic/es6/parser-es6.js similarity index 50% rename from nashorn/test/script/basic/yield.js rename to nashorn/test/script/basic/es6/parser-es6.js index 935f6402ea6..f3d35eb4126 100644 --- a/nashorn/test/script/basic/yield.js +++ b/nashorn/test/script/basic/es6/parser-es6.js @@ -1,34 +1,94 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * 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. */ - /** - * Check yield keyword is parsed and yield statement does nothing (yet). + * JDK-8134503: support ES6 parsing in Nashorn * * @test - * @run + * @option --language=es6 + * @option --parse-only */ -function func() { - yield 2; + +[].map(v => v + 1); + +class A extends B.C { + constructor(a, b) { + super(a, b); + } + someMethod(c) { + super.someMethod(); + } + get g() { + return this.g; + } + set s(t) { + this.t = t; + } + static m() { + return k; + } } + +var obj = { + __proto__: theProtoObj, + handler, + r() { + return super.m(); + }, + [ '__' + (() => 'x')() ]: 1, + *q (x, y) { + yield 1; + } +}; + +var [a, , b] = [1, 2, 3]; + +var { x: a, y: { z: b }, w: c } = abc(); + +var {a, b, c} = abc(); + +var o = { x, y }; + +function g({name: x}) { + return x; +} + +foo(a, ...b); + +var c = [ ...s ]; + +var [a] = []; + +var [a = 1] = []; + + +var f = { + [Symbol.iterator]: function*() { + var cur = 1; + for (;;) { + yield cur; + } + } +}; + diff --git a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED index bda3808e6ca..f7112ce951a 100644 --- a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED +++ b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED @@ -1,3 +1,3 @@ -test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:14 strict mode function cannot have duplicate parameter name "x" +test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:17 strict mode function cannot have duplicate parameter name "x" function func(x, x) {} - ^ + ^ diff --git a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED index eabe2d4cae8..8fbd95117da 100644 --- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED +++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED @@ -100,7 +100,7 @@ "startPosition": "1181", "properties": [ { - "endPosition": "1185", + "endPosition": "1187", "kind": "PROPERTY", "value": { "endPosition": "1187", @@ -2386,7 +2386,7 @@ "startPosition": "1139", "properties": [ { - "endPosition": "1143", + "endPosition": "1146", "kind": "PROPERTY", "value": { "endPosition": "1146", @@ -2403,7 +2403,7 @@ } }, { - "endPosition": "1150", + "endPosition": "1152", "kind": "PROPERTY", "value": { "endPosition": "1152", @@ -2443,7 +2443,7 @@ "startPosition": "1160", "properties": [ { - "endPosition": "1166", + "endPosition": "1169", "kind": "PROPERTY", "value": { "endPosition": "1169", @@ -2460,7 +2460,7 @@ } }, { - "endPosition": "1175", + "endPosition": "1177", "kind": "PROPERTY", "value": { "endPosition": "1177", @@ -2914,7 +2914,7 @@ "startPosition": "1178", "properties": [ { - "endPosition": "1182", + "endPosition": "1184", "kind": "PROPERTY", "value": { "endPosition": "1184", @@ -3395,7 +3395,7 @@ "startPosition": "1200", "properties": [ { - "endPosition": "1206", + "endPosition": "1214", "kind": "PROPERTY", "value": { "endPosition": "1214", @@ -4709,11 +4709,11 @@ , { "fileName": "parsernegativetests/strict_repeatparam.js", - "code": "ident (1119, 1)", - "columnNumber": "14", + "code": "ident (1122, 1)", + "columnNumber": "17", "kind": "ERROR", - "position": "1119", - "message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^", + "position": "1122", + "message": "parsernegativetests/strict_repeatparam.js:31:17 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^", "lineNumber": "31" } , diff --git a/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED b/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED index 833637a598d..3b4ab0665c6 100644 --- a/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED +++ b/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED @@ -6,10 +6,10 @@ with_stat.js:2:7 Expected ; but found ) with({}) {} ^ -repeat_param.js:2:15 strict mode function cannot have duplicate parameter name "x" +repeat_param.js:2:18 strict mode function cannot have duplicate parameter name "x" function func(x, x) {} - ^ + ^ repeat_prop.js:2:22 Property "foo" already defined var obj = { foo: 34, foo: 'hello' }; diff --git a/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED index 8ea2c83773c..e4a88212dc7 100644 --- a/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED +++ b/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED @@ -74,7 +74,7 @@ "properties": [ { "getter": "null", - "endPosition": "74", + "endPosition": "76", "kind": "PROPERTY", "setter": "null", "value": { diff --git a/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED index 04ec80ac815..3584dea2f73 100644 --- a/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED +++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED @@ -6,7 +6,7 @@ "properties": [ { "getter": "null", - "endPosition": "8", + "endPosition": "12", "kind": "PROPERTY", "setter": "null", "value": { @@ -38,7 +38,7 @@ "properties": [ { "getter": "null", - "endPosition": "34", + "endPosition": "37", "kind": "PROPERTY", "setter": "null", "value": { @@ -57,7 +57,7 @@ }, { "getter": "null", - "endPosition": "41", + "endPosition": "43", "kind": "PROPERTY", "setter": "null", "value": { @@ -83,7 +83,7 @@ "properties": [ { "getter": "null", - "endPosition": "57", + "endPosition": "60", "kind": "PROPERTY", "setter": "null", "value": { @@ -102,7 +102,7 @@ }, { "getter": "null", - "endPosition": "66", + "endPosition": "68", "kind": "PROPERTY", "setter": "null", "value": { diff --git a/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED index b4e3c79eb80..f4c8d4ce0f9 100644 --- a/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED +++ b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED @@ -1,7 +1,7 @@ [ { "getter": "null", - "endPosition": "17", + "endPosition": "22", "kind": "PROPERTY", "setter": "null", "value": { @@ -20,7 +20,7 @@ }, { "getter": "null", - "endPosition": "31", + "endPosition": "38", "kind": "PROPERTY", "setter": "null", "value": { @@ -45,7 +45,7 @@ }, { "getter": "null", - "endPosition": "46", + "endPosition": "61", "kind": "PROPERTY", "setter": "null", "value": { @@ -72,7 +72,7 @@ }, { "getter": "null", - "endPosition": "69", + "endPosition": "72", "kind": "PROPERTY", "setter": "null", "value": { diff --git a/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED index 45afd9cc815..928072707e7 100644 --- a/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED +++ b/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED @@ -80,7 +80,7 @@ "properties": [ { "getter": "null", - "endPosition": "97", + "endPosition": "105", "kind": "PROPERTY", "setter": "null", "value": { diff --git a/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED index 1fdf0807665..5720bc9d46e 100644 --- a/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED +++ b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED @@ -49,7 +49,7 @@ "properties": [ { "getter": "null", - "endPosition": "34", + "endPosition": "39", "kind": "PROPERTY", "setter": "null", "value": { diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java index 3e3c9512756..e52d2a66373 100644 --- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java +++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java @@ -194,9 +194,9 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes pb.redirectError(errorFileHandle); final Process process = pb.start(); - process.waitFor(); + final int exitCode = process.waitFor(); - if (errorFileHandle.length() > 0) { + if (exitCode != 0 || errorFileHandle.length() > 0) { if (expectRunFailure) { return; } From 1e0d1458a251c5696d9b613c7bb03472eb44065f Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 27 Apr 2016 18:04:16 +0200 Subject: [PATCH 149/225] 8148568: LoggerFinder.getLogger and LoggerFinder.getLocalizedLogger should take a Module argument instead of a Class Changes System.LoggerFinder methods to take a Module argument instead of a Class. Reviewed-by: mchung --- .../share/classes/java/lang/System.java | 67 +++++++++-------- .../internal/logger/DefaultLoggerFinder.java | 33 ++++++--- .../jdk/internal/logger/LazyLoggers.java | 73 ++++++++++--------- .../sun/util/logging/PlatformLogger.java | 9 ++- .../classes/java/util/logging/LogManager.java | 48 ++++++++---- .../classes/java/util/logging/Logger.java | 27 ++++--- .../logging/internal/LoggingProviderImpl.java | 20 ++--- .../Logger/custom/CustomLoggerTest.java | 53 ++++++++++---- .../BaseLoggerFinder.java | 3 +- .../BaseLoggerFinderTest.java | 32 ++++---- .../TestLoggerFinder.java | 5 +- .../DefaultLoggerFinderTest.java | 32 ++++---- .../BaseDefaultLoggerFinderTest.java | 16 ++-- .../BaseLoggerBridgeTest.java | 27 ++++--- .../BasePlatformLoggerTest.java | 10 ++- .../BootstrapLoggerAPIsTest.java | 4 +- .../BootstrapLogger/BootstrapLoggerTest.java | 5 +- .../LoggerBridgeTest/LoggerBridgeTest.java | 41 +++++++---- .../LoggerFinderLoaderTest.java | 9 ++- .../PlatformLoggerBridgeTest.java | 7 +- .../internal/api/LoggerFinderAPITest.java | 6 +- .../backend/LoggerFinderBackendTest.java | 39 +++++----- .../DefaultLoggerBridgeTest.java | 19 ++--- .../DefaultPlatformLoggerTest.java | 5 +- .../sun/util/logging/PlatformLoggerTest.java | 2 +- 25 files changed, 342 insertions(+), 250 deletions(-) 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 2ddd37f5da1..d6e80e71908 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1155,8 +1155,9 @@ public final class System { * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * * @throws NullPointerException if {@code level} is {@code null}. */ @@ -1222,8 +1223,9 @@ public final class System { * @param level the log message level. * @param msg the string message (or a key in the message catalog, if * this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param thrown a {@code Throwable} associated with the log message; * can be {@code null}. * @@ -1270,8 +1272,9 @@ public final class System { * @param format the string message format in {@link * java.text.MessageFormat} format, (or a key in the message * catalog, if this logger is a {@link - * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class) - * localized logger}); can be {@code null}. + * LoggerFinder#getLocalizedLogger(java.lang.String, + * java.util.ResourceBundle, java.lang.reflect.Module) localized logger}); + * can be {@code null}. * @param params an optional list of parameters to the message (may be * none). * @@ -1453,30 +1456,30 @@ public final class System { /** * Returns an instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * * @param name the name of the logger. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * - * @return a {@link Logger logger} suitable for the given caller's - * use. + * @return a {@link Logger logger} suitable for use within the given + * module. * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ - public abstract Logger getLogger(String name, /* Module */ Class caller); + public abstract Logger getLogger(String name, Module module); /** * Returns a localizable instance of {@link Logger Logger} - * for the given {@code caller}. + * for the given {@code module}. * The returned logger will use the provided resource bundle for * message localization. * * @implSpec By default, this method calls {@link - * #getLogger(java.lang.String, java.lang.Class) - * this.getLogger(name, caller)} to obtain a logger, then wraps that + * #getLogger(java.lang.String, java.lang.reflect.Module) + * this.getLogger(name, module)} to obtain a logger, then wraps that * logger in a {@link Logger} instance where all methods that do not * take a {@link ResourceBundle} as parameter are redirected to one * which does - passing the given {@code bundle} for @@ -1499,19 +1502,19 @@ public final class System { * * @param name the name of the logger. * @param bundle a resource bundle; can be {@code null}. - * @param caller the class for which the logger is being requested. + * @param module the module for which the logger is being requested. * @return an instance of {@link Logger Logger} which will use the * provided resource bundle for message localization. * * @throws NullPointerException if {@code name} is {@code null} or - * {@code caller} is {@code null}. + * {@code module} is {@code null}. * @throws SecurityException if a security manager is present and its * {@code checkPermission} method doesn't allow the * {@code RuntimePermission("loggerFinder")}. */ public Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class caller) { - return new LocalizedLoggerWrapper<>(getLogger(name, caller), bundle); + Module module) { + return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle); } /** @@ -1558,12 +1561,13 @@ public final class System { * * @implSpec * Instances returned by this method route messages to loggers - * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class) - * LoggerFinder.getLogger(name, caller)}. + * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, + * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where + * {@code module} is the caller's module. * * @apiNote * This method may defer calling the {@link - * LoggerFinder#getLogger(java.lang.String, java.lang.Class) + * LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module) * LoggerFinder.getLogger} method to create an actual logger supplied by * the logging backend, for instance, to allow loggers to be obtained during * the system initialization time. @@ -1579,7 +1583,7 @@ public final class System { public static Logger getLogger(String name) { Objects.requireNonNull(name); final Class caller = Reflection.getCallerClass(); - return LazyLoggers.getLogger(name, caller); + return LazyLoggers.getLogger(name, caller.getModule()); } /** @@ -1591,8 +1595,9 @@ public final class System { * @implSpec * The returned logger will perform message localization as specified * by {@link LoggerFinder#getLocalizedLogger(java.lang.String, - * java.util.ResourceBundle, java.lang.Class) - * LoggerFinder.getLocalizedLogger(name, bundle, caller}. + * java.util.ResourceBundle, java.lang.reflect.Module) + * LoggerFinder.getLocalizedLogger(name, bundle, module}, where + * {@code module} is the caller's module. * * @apiNote * This method is intended to be used after the system is fully initialized. @@ -1624,12 +1629,14 @@ public final class System { // Bootstrap sensitive classes in the JDK do not use resource bundles // when logging. This could be revisited later, if it needs to. if (sm != null) { - return AccessController.doPrivileged((PrivilegedAction) - () -> LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller), - null, - LoggerFinder.LOGGERFINDER_PERMISSION); + final PrivilegedAction pa = + () -> LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); + return AccessController.doPrivileged(pa, null, + LoggerFinder.LOGGERFINDER_PERMISSION); } - return LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller); + return LoggerFinder.accessProvider() + .getLocalizedLogger(name, rb, caller.getModule()); } /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java index da255a3e2b8..e24fcad2bd4 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java @@ -33,6 +33,9 @@ import java.util.function.Function; import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Module; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.ResourceBundle; @@ -129,41 +132,49 @@ public class DefaultLoggerFinder extends LoggerFinder { return w; } - final static SharedLoggers system = new SharedLoggers(); final static SharedLoggers application = new SharedLoggers(); } + public static boolean isSystem(Module m) { + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<>() { + @Override + public ClassLoader run() { + return m.getClassLoader(); + } + }); + return cl == null; + } + @Override - public final Logger getLogger(String name, /* Module */ Class caller) { + public final Logger getLogger(String name, Module module) { checkPermission(); - return demandLoggerFor(name, caller); + return demandLoggerFor(name, module); } @Override public final Logger getLocalizedLogger(String name, ResourceBundle bundle, - /* Module */ Class caller) { - return super.getLocalizedLogger(name, bundle, caller); + Module module) { + return super.getLocalizedLogger(name, bundle, module); } - - /** - * Returns a {@link Logger logger} suitable for the caller usage. + * Returns a {@link Logger logger} suitable for use within the + * given {@code module}. * * @implSpec The default implementation for this method is to return a * simple logger that will print all messages of INFO level and above * to the console. That simple logger is not configurable. * * @param name The name of the logger. - * @param caller The class on behalf of which the logger is created. + * @param module The module on behalf of which the logger is created. * @return A {@link Logger logger} suitable for the application usage. * @throws SecurityException if the calling code does not have the * {@code RuntimePermission("loggerFinder")}. */ - protected Logger demandLoggerFor(String name, /* Module */ Class caller) { + protected Logger demandLoggerFor(String name, Module module) { checkPermission(); - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return SharedLoggers.system.get(SimpleConsoleLogger::makeSimpleLogger, name); } else { return SharedLoggers.application.get(SimpleConsoleLogger::makeSimpleLogger, name); diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java index 04b64ea98b1..6c65426ca8e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java @@ -31,6 +31,7 @@ import java.util.function.BiFunction; import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.ref.WeakReference; +import java.lang.reflect.Module; import java.util.Objects; import jdk.internal.misc.VM; import sun.util.logging.PlatformLogger; @@ -59,15 +60,15 @@ public final class LazyLoggers { * A factory method to create an SPI logger. * Usually, this will be something like LazyLoggers::getSystemLogger. */ - final BiFunction, L> loggerSupplier; + final BiFunction loggerSupplier; - public LazyLoggerFactories(BiFunction, L> loggerSupplier) { + public LazyLoggerFactories(BiFunction loggerSupplier) { this(Objects.requireNonNull(loggerSupplier), (Void)null); } - private LazyLoggerFactories(BiFunction, L> loggerSupplier, + private LazyLoggerFactories(BiFunction loggerSupplier, Void unused) { this.loggerSupplier = loggerSupplier; } @@ -107,8 +108,8 @@ public final class LazyLoggers { // The factories that will be used to create the logger lazyly final LazyLoggerFactories factories; - // We need to pass the actual caller when creating the logger. - private final WeakReference> callerRef; + // We need to pass the actual caller module when creating the logger. + private final WeakReference moduleRef; // The name of the logger that will be created lazyly final String name; @@ -121,17 +122,17 @@ public final class LazyLoggers { private LazyLoggerAccessor(String name, LazyLoggerFactories factories, - Class caller) { + Module module) { this(Objects.requireNonNull(name), Objects.requireNonNull(factories), - Objects.requireNonNull(caller), null); + Objects.requireNonNull(module), null); } private LazyLoggerAccessor(String name, LazyLoggerFactories factories, - Class caller, Void unused) { + Module module, Void unused) { this.name = name; this.factories = factories; - this.callerRef = new WeakReference>(caller); + this.moduleRef = new WeakReference<>(module); } /** @@ -270,12 +271,12 @@ public final class LazyLoggers { // Creates the wrapped logger by invoking the SPI. Logger createLogger() { - final Class caller = callerRef.get(); - if (caller == null) { - throw new IllegalStateException("The class for which this logger" + final Module module = moduleRef.get(); + if (module == null) { + throw new IllegalStateException("The module for which this logger" + " was created has been garbage collected"); } - return this.factories.loggerSupplier.apply(name, caller); + return this.factories.loggerSupplier.apply(name, module); } /** @@ -289,8 +290,8 @@ public final class LazyLoggers { * @return A new LazyLoggerAccessor. */ public static LazyLoggerAccessor makeAccessor(String name, - LazyLoggerFactories factories, Class caller) { - return new LazyLoggerAccessor(name, factories, caller); + LazyLoggerFactories factories, Module module) { + return new LazyLoggerAccessor(name, factories, module); } } @@ -346,11 +347,11 @@ public final class LazyLoggers { // Avoid using lambda here as lazy loggers could be created early // in the bootstrap sequence... - private static final BiFunction, Logger> loggerSupplier = + private static final BiFunction loggerSupplier = new BiFunction<>() { @Override - public Logger apply(String name, Class caller) { - return LazyLoggers.getLoggerFromFinder(name, caller); + public Logger apply(String name, Module module) { + return LazyLoggers.getLoggerFromFinder(name, module); } }; @@ -367,8 +368,8 @@ public final class LazyLoggers { // logger provider until the VM has finished booting. // private static final class JdkLazyLogger extends LazyLoggerWrapper { - JdkLazyLogger(String name, Class caller) { - this(LazyLoggerAccessor.makeAccessor(name, factories, caller), + JdkLazyLogger(String name, Module module) { + this(LazyLoggerAccessor.makeAccessor(name, factories, module), (Void)null); } private JdkLazyLogger(LazyLoggerAccessor holder, Void unused) { @@ -380,16 +381,16 @@ public final class LazyLoggers { * Gets a logger from the LoggerFinder. Creates the actual concrete * logger. * @param name name of the logger - * @param caller class on behalf of which the logger is created + * @param module module on behalf of which the logger is created * @return The logger returned by the LoggerFinder. */ - static Logger getLoggerFromFinder(String name, Class caller) { + static Logger getLoggerFromFinder(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return accessLoggerFinder().getLogger(name, caller); + return accessLoggerFinder().getLogger(name, module); } else { return AccessController.doPrivileged((PrivilegedAction) - () -> {return accessLoggerFinder().getLogger(name, caller);}, + () -> {return accessLoggerFinder().getLogger(name, module);}, null, LOGGERFINDER_PERMISSION); } } @@ -398,22 +399,22 @@ public final class LazyLoggers { * Returns a (possibly lazy) Logger for the caller. * * @param name the logger name - * @param caller The class on behalf of which the logger is created. - * If the caller is not loaded from the Boot ClassLoader, + * @param module The module on behalf of which the logger is created. + * If the module is not loaded from the Boot ClassLoader, * the LoggerFinder is accessed and the logger returned - * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class)} + * by {@link LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller directly. * Otherwise, the logger returned by - * {@link #getLazyLogger(java.lang.String, java.lang.Class)} + * {@link #getLazyLogger(java.lang.String, java.lang.reflect.Module)} * is returned to the caller. * * @return a (possibly lazy) Logger instance. */ - public static final Logger getLogger(String name, Class caller) { - if (caller.getClassLoader() == null) { - return getLazyLogger(name, caller); + public static final Logger getLogger(String name, Module module) { + if (DefaultLoggerFinder.isSystem(module)) { + return getLazyLogger(name, module); } else { - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } } @@ -423,10 +424,10 @@ public final class LazyLoggers { * returned by {@link BootstrapLogger#useLazyLoggers()}. * * @param name the logger name - * @param caller the class on behalf of which the logger is created. + * @param module the module on behalf of which the logger is created. * @return a (possibly lazy) Logger instance. */ - public static final Logger getLazyLogger(String name, Class caller) { + public static final Logger getLazyLogger(String name, Module module) { // BootstrapLogger has the logic to determine whether a LazyLogger // should be used. Usually, it is worth it only if: @@ -438,10 +439,10 @@ public final class LazyLoggers { // configuration, we're not going to delay the creation of loggers... final boolean useLazyLogger = BootstrapLogger.useLazyLoggers(); if (useLazyLogger) { - return new JdkLazyLogger(name, caller); + return new JdkLazyLogger(name, module); } else { // Directly invoke the LoggerFinder. - return getLoggerFromFinder(name, caller); + return getLoggerFromFinder(name, module); } } diff --git a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java index 655dc96a299..e8df610c4c1 100644 --- a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java +++ b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java @@ -286,12 +286,15 @@ public class PlatformLogger { } if (log == null) { log = new PlatformLogger(PlatformLogger.Bridge.convert( - // We pass PlatformLogger.class rather than the actual caller + // We pass PlatformLogger.class.getModule() (java.base) + // rather than the actual module of the caller // because we want PlatformLoggers to be system loggers: we // won't need to resolve any resource bundles anyway. // Note: Many unit tests depend on the fact that - // PlatformLogger.getLoggerFromFinder is not caller sensitive. - LazyLoggers.getLazyLogger(name, PlatformLogger.class))); + // PlatformLogger.getLoggerFromFinder is not caller + // sensitive, and this strategy ensure that the tests + // still pass. + LazyLoggers.getLazyLogger(name, PlatformLogger.class.getModule()))); loggers.put(name, new WeakReference<>(log)); } return log; 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 e15add5a4f8..6d0cc8de4d6 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 @@ -43,6 +43,8 @@ import java.util.stream.Stream; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * There is a single global LogManager object that is used to @@ -503,10 +505,16 @@ public class LogManager { // as a LogManager subclass may override the addLogger, getLogger, // readConfiguration, and other methods. Logger demandLogger(String name, String resourceBundleName, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandLogger(name, resourceBundleName, module); + } + + Logger demandLogger(String name, String resourceBundleName, Module module) { Logger result = getLogger(name); if (result == null) { // only allocate the new logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, this, false); + Logger newLogger = new Logger(name, resourceBundleName, + module == null ? null : module, this, false); do { if (addLogger(newLogger)) { // We successfully added the new Logger that we @@ -532,9 +540,14 @@ public class LogManager { } Logger demandSystemLogger(String name, String resourceBundleName, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + return demandSystemLogger(name, resourceBundleName, module); + } + + Logger demandSystemLogger(String name, String resourceBundleName, Module module) { // Add a system logger in the system context's namespace final Logger sysLogger = getSystemContext() - .demandLogger(name, resourceBundleName, caller); + .demandLogger(name, resourceBundleName, module); // Add the system logger to the LogManager's namespace if not exist // so that there is only one single logger of the given name. @@ -619,11 +632,11 @@ public class LogManager { return global; } - Logger demandLogger(String name, String resourceBundleName, Class caller) { + Logger demandLogger(String name, String resourceBundleName, Module module) { // a LogManager subclass may have its own implementation to add and // get a Logger. So delegate to the LogManager to do the work. final LogManager owner = getOwner(); - return owner.demandLogger(name, resourceBundleName, caller); + return owner.demandLogger(name, resourceBundleName, module); } @@ -907,11 +920,13 @@ public class LogManager { // one single logger of the given name. System loggers are visible // to applications unless a logger of the same name has been added. @Override - Logger demandLogger(String name, String resourceBundleName, Class caller) { + Logger demandLogger(String name, String resourceBundleName, + Module module) { Logger result = findLogger(name); if (result == null) { // only allocate the new system logger once - Logger newLogger = new Logger(name, resourceBundleName, caller, getOwner(), true); + Logger newLogger = new Logger(name, resourceBundleName, + module, getOwner(), true); do { if (addLocalLogger(newLogger)) { // We successfully added the new Logger that we @@ -2622,18 +2637,18 @@ public class LogManager { } /** - * Demands a logger on behalf of the given {@code caller}. + * Demands a logger on behalf of the given {@code module}. *

    - * If a named logger suitable for the given caller is found + * If a named logger suitable for the given module is found * returns it. - * Otherwise, creates a new logger suitable for the given caller. + * Otherwise, creates a new logger suitable for the given module. * * @param name The logger name. - * @param caller The caller on which behalf the logger is created/retrieved. - * @return A logger for the given {@code caller}. + * @param module The module on which behalf the logger is created/retrieved. + * @return A logger for the given {@code module}. * * @throws NullPointerException if {@code name} is {@code null} - * or {@code caller} is {@code null}. + * or {@code module} is {@code null}. * @throws IllegalArgumentException if {@code manager} is not the default * LogManager. * @throws SecurityException if a security manager is present and the @@ -2641,7 +2656,7 @@ public class LogManager { * {@link LoggingPermission LoggingPermission("demandLogger", null)}. */ @Override - public Logger demandLoggerFor(LogManager manager, String name, /* Module */ Class caller) { + public Logger demandLoggerFor(LogManager manager, String name, Module module) { if (manager != getLogManager()) { // having LogManager as parameter just ensures that the // caller will have initialized the LogManager before reaching @@ -2649,15 +2664,16 @@ public class LogManager { throw new IllegalArgumentException("manager"); } Objects.requireNonNull(name); + Objects.requireNonNull(module); SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(controlPermission); } - if (caller.getClassLoader() == null) { + if (isSystem(module)) { return manager.demandSystemLogger(name, - Logger.SYSTEM_LOGGER_RB_NAME, caller); + Logger.SYSTEM_LOGGER_RB_NAME, module); } else { - return manager.demandLogger(name, null, caller); + return manager.demandLogger(name, null, module); } } diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java index d8ada0c4c08..ca055b06af1 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java @@ -40,6 +40,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Supplier; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import static jdk.internal.logger.DefaultLoggerFinder.isSystem; /** * A Logger object is used to log messages for a specific @@ -379,7 +380,8 @@ public class Logger { this(name, resourceBundleName, null, LogManager.getLogManager(), false); } - Logger(String name, String resourceBundleName, Class caller, LogManager manager, boolean isSystemLogger) { + Logger(String name, String resourceBundleName, Module caller, + LogManager manager, boolean isSystemLogger) { this.manager = manager; this.isSystemLogger = isSystemLogger; setupResourceInfo(resourceBundleName, caller); @@ -387,10 +389,7 @@ public class Logger { levelValue = Level.INFO.intValue(); } - private void setCallerModuleRef(Class caller) { - Module callerModule = ((caller != null) - ? caller.getModule() - : null); + private void setCallerModuleRef(Module callerModule) { if (callerModule != null) { this.callerModuleRef = new WeakReference<>(callerModule); } @@ -618,7 +617,7 @@ public class Logger { // all loggers in the system context will default to // the system logger's resource bundle - therefore the caller won't // be needed and can be null. - Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null); + Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null); return result; } @@ -681,8 +680,10 @@ public class Logger { LogManager manager = LogManager.getLogManager(); // cleanup some Loggers that have been GC'ed manager.drainLoggerRefQueueBounded(); + final Class callerClass = Reflection.getCallerClass(); + final Module module = callerClass.getModule(); Logger result = new Logger(null, resourceBundleName, - Reflection.getCallerClass(), manager, false); + module, manager, false); result.anonymous = true; Logger root = manager.getLogger(""); result.doSetParent(root); @@ -2046,6 +2047,11 @@ public class Logger { } } + private void setupResourceInfo(String name, Class caller) { + final Module module = caller == null ? null : caller.getModule(); + setupResourceInfo(name, module); + } + // Private utility method to initialize our one entry // resource bundle name cache and the callers Module // Note: for consistency reasons, we are careful to check @@ -2053,7 +2059,7 @@ public class Logger { // resourceBundleName field. // Synchronized to prevent races in setting the fields. private synchronized void setupResourceInfo(String name, - Class callerClass) { + Module callerModule) { final LoggerBundle lb = loggerBundle; if (lb.resourceBundleName != null) { // this Logger already has a ResourceBundle @@ -2072,8 +2078,9 @@ public class Logger { return; } - setCallerModuleRef(callerClass); - if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) { + setCallerModuleRef(callerModule); + + if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) { checkPermission(); } diff --git a/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java b/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java index 4fcf40d2daa..1ccf2cf7c92 100644 --- a/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java +++ b/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java @@ -32,6 +32,7 @@ import java.util.ResourceBundle; import java.util.function.Supplier; import java.lang.System.LoggerFinder; import java.lang.System.Logger; +import java.lang.reflect.Module; import java.util.Objects; import java.util.logging.LogManager; import jdk.internal.logger.DefaultLoggerFinder; @@ -398,21 +399,20 @@ public final class LoggingProviderImpl extends DefaultLoggerFinder { } /** - * Creates a java.util.logging.Logger for the given caller. + * Creates a java.util.logging.Logger for the given module. * @param name the logger name. - * @param caller the caller for which the logger should be created. - * @return a Logger suitable for use in the given caller. + * @param module the module for which the logger should be created. + * @return a Logger suitable for use in the given module. */ private static java.util.logging.Logger demandJULLoggerFor(final String name, - /* Module */ - final Class caller) { + Module module) { final LogManager manager = LogManager.getLogManager(); final SecurityManager sm = System.getSecurityManager(); if (sm == null) { - return logManagerAccess.demandLoggerFor(manager, name, caller); + return logManagerAccess.demandLoggerFor(manager, name, module); } else { final PrivilegedAction pa = - () -> logManagerAccess.demandLoggerFor(manager, name, caller); + () -> logManagerAccess.demandLoggerFor(manager, name, module); return AccessController.doPrivileged(pa, null, LOGGING_CONTROL_PERMISSION); } } @@ -429,17 +429,17 @@ public final class LoggingProviderImpl extends DefaultLoggerFinder { * {@code RuntimePermission("loggerFinder")}. */ @Override - protected Logger demandLoggerFor(String name, /* Module */ Class caller) { + protected Logger demandLoggerFor(String name, Module module) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); } - return JULWrapper.of(demandJULLoggerFor(name,caller)); + return JULWrapper.of(demandJULLoggerFor(name,module)); } public static interface LogManagerAccess { java.util.logging.Logger demandLoggerFor(LogManager manager, - String name, /* Module */ Class caller); + String name, Module module); } // Hook for tests diff --git a/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java b/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java index 2506905ec7c..d1653ca5f1e 100644 --- a/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java +++ b/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java @@ -46,6 +46,8 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; +import java.lang.reflect.Module; +import java.security.AllPermission; /** * @test @@ -70,6 +72,12 @@ public class CustomLoggerTest { return new AtomicBoolean(false); } }; + static final ThreadLocal allowAll = new ThreadLocal() { + @Override + protected AtomicBoolean initialValue() { + return new AtomicBoolean(false); + } + }; public static class MyBundle extends ResourceBundle { @@ -241,7 +249,7 @@ public class CustomLoggerTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { // We should check the permission to obey the API contract, but // what happens if we don't? // This is the main difference compared with what we test in @@ -251,8 +259,13 @@ public class CustomLoggerTest { sm.checkPermission(SimplePolicy.LOGGERFINDER_PERMISSION); } - PrivilegedAction pa = () -> caller.getClassLoader(); - ClassLoader callerLoader = AccessController.doPrivileged(pa); + final boolean before = allowAll.get().getAndSet(true); + final ClassLoader callerLoader; + try { + callerLoader = caller.getClassLoader(); + } finally { + allowAll.get().set(before); + } if (callerLoader == null) { return system.computeIfAbsent(name, (n) -> new LoggerImpl(n)); } else { @@ -267,7 +280,7 @@ public class CustomLoggerTest { static void setSecurityManager() { if (System.getSecurityManager() == null) { - Policy.setPolicy(new SimplePolicy(allowControl)); + Policy.setPolicy(new SimplePolicy(allowControl, allowAll)); System.setSecurityManager(new SecurityManager()); } } @@ -284,9 +297,9 @@ public class CustomLoggerTest { BaseLoggerFinder provider = BaseLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); BaseLoggerFinder.LoggerImpl appSink = - BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class)); + BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class.getModule())); BaseLoggerFinder.LoggerImpl sysSink = - BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> { @@ -695,34 +708,46 @@ public class CustomLoggerTest { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); final Permissions permissions; + final Permissions controlPermissions; final Permissions allPermissions; final ThreadLocal allowControl; - public SimplePolicy(ThreadLocal allowControl) { + final ThreadLocal allowAll; + public SimplePolicy(ThreadLocal allowControl, ThreadLocal allowAll) { this.allowControl = allowControl; + this.allowAll = allowAll; permissions = new Permissions(); // these are used for configuring the test itself... + controlPermissions = new Permissions(); + controlPermissions.add(LOGGERFINDER_PERMISSION); + + // these are used for simulating a doPrivileged call from + // a class in the BCL allPermissions = new Permissions(); - allPermissions.add(LOGGERFINDER_PERMISSION); + allPermissions.add(new AllPermission()); + + } + + Permissions permissions() { + if (allowAll.get().get()) return allPermissions; + if (allowControl.get().get()) return controlPermissions; + return permissions; } @Override public boolean implies(ProtectionDomain domain, Permission permission) { - if (allowControl.get().get()) return allPermissions.implies(permission); - return permissions.implies(permission); + return permissions().implies(permission); } @Override public PermissionCollection getPermissions(CodeSource codesource) { - return new PermissionsBuilder().addAll(allowControl.get().get() - ? allPermissions : permissions).toPermissions(); + return new PermissionsBuilder().addAll(permissions()).toPermissions(); } @Override public PermissionCollection getPermissions(ProtectionDomain domain) { - return new PermissionsBuilder().addAll(allowControl.get().get() - ? allPermissions : permissions).toPermissions(); + return new PermissionsBuilder().addAll(permissions()).toPermissions(); } } } diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java index 30daa232248..3db7cef65f8 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java @@ -25,13 +25,14 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.System.LoggerFinder; import java.lang.System.Logger; +import java.lang.reflect.Module; public class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java index 2cb57d78559..b3805919e53 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java @@ -182,8 +182,8 @@ public class BaseLoggerFinderTest { TestLoggerFinder.LoggerImpl appLogger1 = null; try { appLogger1 = - TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); - loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); + TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule())); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -199,8 +199,8 @@ public class BaseLoggerFinderTest { allowControl.get().set(true); try { appLogger1 = - TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); - loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); + TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule())); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -208,8 +208,8 @@ public class BaseLoggerFinderTest { TestLoggerFinder.LoggerImpl sysLogger1 = null; try { - sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); - loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); + sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -224,8 +224,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); - loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); + sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); } finally { allowControl.get().set(old); } @@ -254,8 +254,8 @@ public class BaseLoggerFinderTest { // callers and non system callers Logger appLogger2 = null; try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -270,8 +270,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -279,8 +279,8 @@ public class BaseLoggerFinderTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -295,8 +295,8 @@ public class BaseLoggerFinderTest { final boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class))"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule()))"); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java index 716f8b8faec..cb86e513f90 100644 --- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java +++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java @@ -30,6 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; import java.lang.System.Logger; +import java.lang.reflect.Module; /** * What our test provider needs to implement. @@ -176,6 +177,6 @@ public interface TestLoggerFinder { } } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } diff --git a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java index 50c789b5d60..43150eb0f00 100644 --- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java @@ -364,8 +364,8 @@ public class DefaultLoggerFinderTest { Logger appLogger1 = null; try { - appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); + appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -380,8 +380,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); + appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -389,8 +389,8 @@ public class DefaultLoggerFinderTest { Logger sysLogger1 = null; try { - sysLogger1 = provider.getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); + sysLogger1 = provider.getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -405,8 +405,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger1 = provider.getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); + sysLogger1 = provider.getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); } finally { allowControl.get().set(old); } @@ -417,8 +417,8 @@ public class DefaultLoggerFinderTest { Logger appLogger2 = null; try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a logger without permission"); } @@ -433,8 +433,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); - loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); + appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule()); + loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())"); } finally { allowControl.get().set(old); } @@ -442,8 +442,8 @@ public class DefaultLoggerFinderTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -458,8 +458,8 @@ public class DefaultLoggerFinderTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java index ddf1be7731c..ab80d0f8bc6 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java @@ -55,6 +55,7 @@ import java.util.function.Function; import jdk.internal.logger.DefaultLoggerFinder; import jdk.internal.logger.SimpleConsoleLogger; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -112,10 +113,10 @@ public class BaseDefaultLoggerFinderTest { public final static AtomicLong sequencer = new AtomicLong(); - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); - void setLevel(Logger logger, Level level, Class caller); - void setLevel(Logger logger, PlatformLogger.Level level, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); + void setLevel(Logger logger, Level level, Module caller); + void setLevel(Logger logger, PlatformLogger.Level level, Module caller); PlatformLogger.Bridge asPlatformLoggerBridge(Logger logger); } @@ -130,7 +131,7 @@ public class BaseDefaultLoggerFinderTest { } @Override - public void setLevel(Logger logger, Level level, Class caller) { + public void setLevel(Logger logger, Level level, Module caller) { PrivilegedAction pa = () -> { setLevel(logger, PlatformLogger.toPlatformLevel(level), caller); return null; @@ -139,7 +140,7 @@ public class BaseDefaultLoggerFinderTest { } @Override - public void setLevel(Logger logger, PlatformLogger.Level level, Class caller) { + public void setLevel(Logger logger, PlatformLogger.Level level, Module caller) { PrivilegedAction pa = () -> demandLoggerFor(logger.getName(), caller); Logger impl = AccessController.doPrivileged(pa); SimpleConsoleLogger.class.cast(impl) @@ -606,11 +607,12 @@ public class BaseDefaultLoggerFinderTest { String name, ResourceBundle loggerBundle, Logger logger, - Class caller) { + Class callerClass) { System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]"); AtomicLong sequencer = TestLoggerFinder.sequencer; + Module caller = callerClass.getModule(); Foo foo = new Foo(); String fooMsg = foo.toString(); for (Level loggerLevel : Level.values()) { diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java index 5319f0e5fbf..d28481c305f 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java @@ -47,6 +47,7 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; +import java.lang.reflect.Module; /** * @test @@ -209,8 +210,6 @@ public class BaseLoggerBridgeTest { return Arrays.deepToString(toArray(false)); } - - @Override public boolean equals(Object obj) { return obj instanceof LogEvent @@ -342,15 +341,15 @@ public class BaseLoggerBridgeTest { } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { static final RuntimePermission LOGGERFINDER_PERMISSION = new RuntimePermission("loggerFinder"); @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -375,7 +374,7 @@ public class BaseLoggerBridgeTest { } } - static Logger getLogger(String name, Class caller) { + static Logger getLogger(String name, Module caller) { boolean old = allowAll.get().get(); allowAccess.get().set(true); try { @@ -465,7 +464,7 @@ public class BaseLoggerBridgeTest { TestLoggerFinder.LoggerImpl appSink = null; try { - appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class)); + appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule())); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -480,7 +479,7 @@ public class BaseLoggerBridgeTest { boolean old = allowControl.get().get(); allowControl.get().set(true); try { - appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class)); + appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule())); } finally { allowControl.get().set(old); } @@ -489,7 +488,7 @@ public class BaseLoggerBridgeTest { TestLoggerFinder.LoggerImpl sysSink = null; try { - sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule())); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -527,13 +526,13 @@ public class BaseLoggerBridgeTest { Logger sysLogger1 = null; try { - sysLogger1 = getLogger("foo", Thread.class); + sysLogger1 = getLogger("foo", Thread.class.getModule()); loggerDescMap.put(sysLogger1, - "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)"); + "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { // check that the provider would have thrown an exception - provider.getLogger("foo", Thread.class); + provider.getLogger("foo", Thread.class.getModule()); throw new RuntimeException("Managed to obtain a system logger without permission"); } } catch (AccessControlException acx) { @@ -572,8 +571,8 @@ public class BaseLoggerBridgeTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java index da8c2d73b16..a9e441f9d7c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java @@ -47,6 +47,7 @@ import java.lang.System.Logger.Level; import java.security.AccessControlException; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -327,12 +328,12 @@ public class BasePlatformLoggerTest { } } - public Logger getLogger(String name, Class caller); + public Logger getLogger(String name, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -433,7 +434,7 @@ public class BasePlatformLoggerTest { try { allowControl.get().set(true); appSink = TestLoggerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", BasePlatformLoggerTest.class)); + provider.getLogger("foo", BasePlatformLoggerTest.class.getModule())); } finally { allowControl.get().set(before); } @@ -442,7 +443,8 @@ public class BasePlatformLoggerTest { before = allowControl.get().get(); try { allowControl.get().set(true); - sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); + sysSink = TestLoggerFinder.LoggerImpl.class.cast( + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(before); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java index 7c62eb9a763..bedd6117ae8 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java @@ -30,7 +30,7 @@ import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import java.util.Set; - +import java.lang.reflect.Module; import jdk.internal.logger.BootstrapLogger; import jdk.internal.logger.LazyLoggers; @@ -69,7 +69,7 @@ public class BootstrapLoggerAPIsTest { } final Logger LOGGER = - LazyLoggers.getLogger("foo.bar", Thread.class); + LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); final sun.util.logging.PlatformLogger.Level PLATFORM_LEVEL = sun.util.logging.PlatformLogger.Level.SEVERE; final MyResources BUNDLE = new MyResources(); diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java index 033a7d97315..e2f6d4b009d 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java @@ -43,6 +43,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.logger.BootstrapLogger; import jdk.internal.logger.LazyLoggers; +import java.lang.reflect.Module; /* * @test @@ -105,7 +106,7 @@ public class BootstrapLoggerTest { if (BootstrapLogger.isBooted()) { throw new RuntimeException("VM should not be booted!"); } - Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class); + Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); if (test != TestCase.NO_SECURITY) { LogStream.err.println("Setting security manager"); @@ -261,7 +262,7 @@ public class BootstrapLoggerTest { SimplePolicy.allowAll.set(Boolean.TRUE); try { bazbaz = java.lang.System.LoggerFinder - .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class); + .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class.getModule()); } finally { SimplePolicy.allowAll.set(Boolean.FALSE); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java index c3f5e98d39c..be5ad125518 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java @@ -51,6 +51,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -164,6 +165,7 @@ public class LoggerBridgeTest { null, null, level, bundle, key, thrown, params); } + public static LogEvent of(long sequenceNumber, boolean isLoggable, String name, sun.util.logging.PlatformLogger.Level level, ResourceBundle bundle, @@ -231,7 +233,7 @@ public class LoggerBridgeTest { try { // Preload classes before the security manager is on. providerClass = ClassLoader.getSystemClassLoader().loadClass("LoggerBridgeTest$LogProducerFinder"); - ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass); + ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule()); } catch (Exception ex) { throw new ExceptionInInitializerError(ex); } @@ -415,7 +417,7 @@ public class LoggerBridgeTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -430,6 +432,15 @@ public class LoggerBridgeTest { } } + static ClassLoader getClassLoader(Module m) { + final boolean before = allowAll.get().getAndSet(true); + try { + return m.getClassLoader(); + } finally { + allowAll.get().set(before); + } + } + static final sun.util.logging.PlatformLogger.Level[] julLevels = { sun.util.logging.PlatformLogger.Level.ALL, sun.util.logging.PlatformLogger.Level.FINEST, @@ -497,14 +508,14 @@ public class LoggerBridgeTest { try { Class bridgeClass = Class.forName("jdk.internal.logger.LazyLoggers"); lazyGetLogger = bridgeClass.getDeclaredMethod("getLogger", - String.class, Class.class); + String.class, Module.class); lazyGetLogger.setAccessible(true); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } - static Logger getLogger(LoggerFinder provider, String name, Class caller) { + static Logger getLogger(LoggerFinder provider, String name, Module caller) { Logger logger; try { logger = Logger.class.cast(lazyGetLogger.invoke(null, name, caller)); @@ -522,14 +533,14 @@ public class LoggerBridgeTest { // The method above does not throw exception... // call the provider here to verify that an exception would have // been thrown by the provider. - if (logger != null && caller == Thread.class) { + if (logger != null && caller == Thread.class.getModule()) { Logger log = provider.getLogger(name, caller); } return logger; } - static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Class caller) { - if (caller.getClassLoader() != null) { + static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Module caller) { + if (getClassLoader(caller) != null) { return System.getLogger(name,bundle); } else { return provider.getLocalizedLogger(name, bundle, caller); @@ -614,12 +625,12 @@ public class LoggerBridgeTest { Logger appLogger1 = System.getLogger("foo"); - loggerDescMap.put(appLogger1, "LogProducer.getApplicationLogger(\"foo\")"); + loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")"); Logger sysLogger1 = null; try { - sysLogger1 = getLogger(provider, "foo", Thread.class); - loggerDescMap.put(sysLogger1, "LogProducer.getSystemLogger(\"foo\")"); + sysLogger1 = getLogger(provider, "foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -636,12 +647,12 @@ public class LoggerBridgeTest { Logger appLogger2 = System.getLogger("foo", loggerBundle); - loggerDescMap.put(appLogger2, "LogProducer.getApplicationLogger(\"foo\", loggerBundle)"); + loggerDescMap.put(appLogger2, "System.getLogger(\"foo\", loggerBundle)"); Logger sysLogger2 = null; try { - sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getSystemLogger(\"foo\", loggerBundle)"); + sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -671,9 +682,9 @@ public class LoggerBridgeTest { allowControl.get().set(true); try { appSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", LoggerBridgeTest.class)); + provider.getLogger("foo", LoggerBridgeTest.class.getModule())); sysSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", Thread.class)); + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java index 98418430a71..6343a90312c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java @@ -53,6 +53,7 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; import jdk.internal.logger.SimpleConsoleLogger; +import java.lang.reflect.Module; /** * @test @@ -166,8 +167,8 @@ public class LoggerFinderLoaderTest { } - public Logger getLogger(String name, Class caller); - public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class caller); + public Logger getLogger(String name, Module caller); + public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller); } public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { @@ -187,7 +188,7 @@ public class LoggerFinderLoaderTest { @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -210,7 +211,7 @@ public class LoggerFinderLoaderTest { throw new ServiceConfigurationError("Should not come here"); } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { throw new ServiceConfigurationError("Should not come here"); } } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java index 1300c9b2ecd..9576e17bed6 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java @@ -49,6 +49,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.stream.Stream; import sun.util.logging.PlatformLogger; +import java.lang.reflect.Module; /** * @test @@ -94,7 +95,7 @@ public class PlatformLoggerBridgeTest { try { // Preload classes before the security manager is on. providerClass = ClassLoader.getSystemClassLoader().loadClass("PlatformLoggerBridgeTest$LogProducerFinder"); - ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass); + ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule()); } catch (Exception ex) { throw new ExceptionInInitializerError(ex); } @@ -415,7 +416,7 @@ public class PlatformLoggerBridgeTest { } @Override - public Logger getLogger(String name, Class caller) { + public Logger getLogger(String name, Module caller) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(LOGGERFINDER_PERMISSION); @@ -598,7 +599,7 @@ public class PlatformLoggerBridgeTest { allowControl.get().set(true); try { sysSink = LogProducerFinder.LoggerImpl.class.cast( - provider.getLogger("foo", Thread.class)); + provider.getLogger("foo", Thread.class.getModule())); } finally { allowControl.get().set(old); } diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java index e3752b5721c..572695458f1 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java @@ -469,12 +469,12 @@ public class LoggerFinderAPITest { errors.append(test.testGetLoggerOverriddenOnSpi()); java.lang.System.Logger julLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("foo", LoggerFinderAPITest.class); + .getLogger("foo", LoggerFinderAPITest.class.getModule()); errors.append(test.testDefaultJULLogger(julLogger)); if (errors.length() > 0) throw new RuntimeException(errors.toString()); java.lang.System.Logger julSystemLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("bar", Thread.class); + .getLogger("bar", Thread.class.getModule()); errors.append(test.testDefaultJULLogger(julSystemLogger)); if (errors.length() > 0) throw new RuntimeException(errors.toString()); java.lang.System.Logger julLocalizedLogger = @@ -482,7 +482,7 @@ public class LoggerFinderAPITest { System.getLogger("baz", bundleLocalized); java.lang.System.Logger julLocalizedSystemLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("oof", bundleLocalized, Thread.class); + .getLocalizedLogger("oof", bundleLocalized, Thread.class.getModule()); final String error = errors.toString(); if (!error.isEmpty()) throw new RuntimeException(error); for (java.lang.System.Logger logger : new java.lang.System.Logger[] { diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java index 226f2f7cf30..eb3f07c3ec3 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java @@ -77,6 +77,7 @@ import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @author danielfuchs @@ -1506,7 +1507,7 @@ public class LoggerFinderBackendTest { Logger getBackendLogger(String name) { if (isSystem) { return LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), name, Thread.class); + LogManager.getLogManager(), name, Thread.class.getModule()); } else { return Logger.getLogger(name); } @@ -1699,7 +1700,7 @@ public class LoggerFinderBackendTest { Collections.synchronizedMap(new HashMap<>()); @Override - public java.lang.System.Logger getLogger(String name, Class caller) { + public java.lang.System.Logger getLogger(String name, Module caller) { ClassLoader callerLoader = caller.getClassLoader(); if (callerLoader == null) { systemLoggers.putIfAbsent(name, new CustomLogger(name)); @@ -1827,8 +1828,8 @@ public class LoggerFinderBackendTest { public void setLevel(java.lang.System.Logger logger, Level level) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) - (isSystem ? provider.getLogger(logger.getName(), Thread.class) : - provider.getLogger(logger.getName(), LoggerFinderBackendTest.class)); + (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : + provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); l.setLevel(provider.fromJul(level)); } @Override @@ -1840,8 +1841,8 @@ public class LoggerFinderBackendTest { CustomLoggerFinder.CustomLevel getLevel(java.lang.System.Logger logger) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) - (isSystem ? provider.getLogger(logger.getName(), Thread.class) : - provider.getLogger(logger.getName(), LoggerFinderBackendTest.class)); + (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : + provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); return l.level; } @@ -1962,7 +1963,7 @@ public class LoggerFinderBackendTest { try { Class lazyLoggers = jdk.internal.logger.LazyLoggers.class; getLazyLogger = lazyLoggers.getMethod("getLazyLogger", - String.class, Class.class); + String.class, Module.class); getLazyLogger.setAccessible(true); Class loggerFinderLoader = Class.forName("java.lang.System$LoggerFinder"); @@ -1973,7 +1974,7 @@ public class LoggerFinderBackendTest { } } - static java.lang.System.Logger getSystemLogger(String name, Class caller) throws Exception { + static java.lang.System.Logger getSystemLogger(String name, Module caller) throws Exception { try { return java.lang.System.Logger.class.cast(getLazyLogger.invoke(null, name, caller)); } catch (InvocationTargetException x) { @@ -1986,7 +1987,7 @@ public class LoggerFinderBackendTest { } } static java.lang.System.Logger getSystemLogger(String name, - ResourceBundle bundle, Class caller) throws Exception { + ResourceBundle bundle, Module caller) throws Exception { try { LoggerFinder provider = LoggerFinder.class.cast(accessLoggerFinder.invoke(null)); return provider.getLocalizedLogger(name, bundle, caller); @@ -2047,14 +2048,14 @@ public class LoggerFinderBackendTest { final BackendTester tester = factory.createBackendTester(false); final java.lang.System.Logger logger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("foo", LoggerFinderBackendTest.class); + .getLogger("foo", LoggerFinderBackendTest.class.getModule()); testLogger(tester, logger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger system = java.lang.System.LoggerFinder.getLoggerFinder() - .getLogger("bar", Thread.class); + .getLogger("bar", Thread.class.getModule()); final BackendTester systemTester = factory.createBackendTester(true); testLogger(systemTester, system, nb); @@ -2062,7 +2063,7 @@ public class LoggerFinderBackendTest { // JUL backend final java.lang.System.Logger noBundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class); + .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleTester = factory.createBackendTester(false, spiLoggerClass); testLogger(noBundleTester, noBundleLogger, nb); @@ -2071,7 +2072,7 @@ public class LoggerFinderBackendTest { // backend final java.lang.System.Logger noBundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("oof", null, Thread.class); + .getLocalizedLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysTester = factory.createBackendTester(true, spiLoggerClass); testLogger(noBundleSysTester, noBundleSysLogger, nb); @@ -2085,14 +2086,14 @@ public class LoggerFinderBackendTest { System.out.println("System.Loggers.getLogger(\"baz\", null): got expected " + x); } final java.lang.System.Logger noBundleExtensionLogger = - getSystemLogger("baz", null, LoggerFinderBackendTest.class); + getSystemLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleExtensionTester = factory.createBackendTester(false, jdkLoggerClass); testLogger(noBundleExtensionTester, noBundleExtensionLogger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger sysExtensionLogger = - getSystemLogger("oof", Thread.class); + getSystemLogger("oof", Thread.class.getModule()); final BackendTester sysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(sysExtensionTester, sysExtensionLogger, nb); @@ -2100,7 +2101,7 @@ public class LoggerFinderBackendTest { // Test a localized system logger with null resource bundle and JUL // backend final java.lang.System.Logger noBundleSysExtensionLogger = - getSystemLogger("oof", null, Thread.class); + getSystemLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(noBundleSysExtensionTester, noBundleSysExtensionLogger, nb); @@ -2127,7 +2128,7 @@ public class LoggerFinderBackendTest { ResourceBundle.getBundle(ResourceBundeLocalized.class.getName()); final java.lang.System.Logger bundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class); + .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class.getModule()); final BackendTester bundleTester = factory.createBackendTester(false, spiLoggerClass, bundle); testLogger(bundleTester, bundleLogger, nb); @@ -2135,7 +2136,7 @@ public class LoggerFinderBackendTest { // Test a localized system logger with resource bundle and JUL backend final java.lang.System.Logger bundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() - .getLocalizedLogger("titi", bundle, Thread.class); + .getLocalizedLogger("titi", bundle, Thread.class.getModule()); final BackendTester bundleSysTester = factory.createBackendTester(true, spiLoggerClass, bundle); testLogger(bundleSysTester, bundleSysLogger, nb); @@ -2151,7 +2152,7 @@ public class LoggerFinderBackendTest { // Test a localized Jdk system logger with resource bundle and JUL // backend final java.lang.System.Logger bundleExtensionSysLogger = - getSystemLogger("titu", bundle, Thread.class); + getSystemLogger("titu", bundle, Thread.class.getModule()); final BackendTester bundleExtensionSysTester = factory.createBackendTester(true, jdkLoggerClass, bundle); testLogger(bundleExtensionSysTester, bundleExtensionSysLogger, nb); diff --git a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java index 6f15819fcd2..7118101cada 100644 --- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java @@ -48,6 +48,7 @@ import java.lang.System.LoggerFinder; import java.lang.System.Logger; import java.util.stream.Stream; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @test @@ -246,7 +247,7 @@ public class DefaultLoggerBridgeTest { } } - static Logger getLogger(String name, Class caller) { + static Logger getLogger(String name, Module caller) { boolean old = allowAccess.get().get(); allowAccess.get().set(true); try { @@ -311,8 +312,8 @@ public class DefaultLoggerBridgeTest { ResourceBundle.getBundle(MyLoggerBundle.class.getName()); final Map loggerDescMap = new HashMap<>(); - Logger sysLogger1a = getLogger("foo", Thread.class); - loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)"); + Logger sysLogger1a = getLogger("foo", Thread.class.getModule()); + loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())"); Logger appLogger1 = System.getLogger("foo"); loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")"); @@ -341,9 +342,9 @@ public class DefaultLoggerBridgeTest { Logger sysLogger1b = null; try { - sysLogger1b = provider.getLogger("foo", Thread.class); + sysLogger1b = provider.getLogger("foo", Thread.class.getModule()); if (sysLogger1b != sysLogger1a) { - loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class)"); + loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class.getModule())"); } if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); @@ -367,8 +368,8 @@ public class DefaultLoggerBridgeTest { Logger sysLogger2 = null; try { - sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); - loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); + sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule()); + loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())"); if (!hasRequiredPermissions) { throw new RuntimeException("Managed to obtain a system logger without permission"); } @@ -396,9 +397,9 @@ public class DefaultLoggerBridgeTest { allowAll.get().set(true); try { sysSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), "foo", Thread.class); + LogManager.getLogManager(), "foo", Thread.class.getModule()); appSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( - LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class); + LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class.getModule()); if (appSink == sysSink) { throw new RuntimeException("identical backend loggers"); } diff --git a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java index 2eb64d0743d..99b7ee38b2a 100644 --- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java @@ -44,6 +44,7 @@ import java.util.logging.LogRecord; import java.lang.System.LoggerFinder; import sun.util.logging.PlatformLogger; import sun.util.logging.internal.LoggingProviderImpl; +import java.lang.reflect.Module; /** * @test @@ -244,9 +245,9 @@ public class DefaultPlatformLoggerTest { LoggerFinder provider = LoggerFinder.getLoggerFinder(); java.util.logging.Logger appSink = LoggingProviderImpl.getLogManagerAccess() .demandLoggerFor(LogManager.getLogManager(), "foo", - DefaultPlatformLoggerTest.class); + DefaultPlatformLoggerTest.class.getModule()); java.util.logging.Logger sysSink = LoggingProviderImpl.getLogManagerAccess() - .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class); + .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class.getModule()); appSink.addHandler(new MyHandler()); sysSink.addHandler(new MyHandler()); appSink.setUseParentHandlers(VERBOSE); diff --git a/jdk/test/sun/util/logging/PlatformLoggerTest.java b/jdk/test/sun/util/logging/PlatformLoggerTest.java index 0bf94d64a5a..530a2acea8a 100644 --- a/jdk/test/sun/util/logging/PlatformLoggerTest.java +++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java @@ -197,7 +197,7 @@ public class PlatformLoggerTest { // create a brand new java logger Logger javaLogger = sun.util.logging.internal.LoggingProviderImpl.getLogManagerAccess() .demandLoggerFor(LogManager.getLogManager(), - logger.getName()+"."+level.getName(), Thread.class); + logger.getName()+"."+level.getName(), Thread.class.getModule()); // Set a non standard java.util.logging.Level on the java logger // (except for OFF & ALL - which will remain unchanged) From 607d8e443b0914fe25113e6af23e745b683aef7c Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Wed, 27 Apr 2016 18:52:32 +0200 Subject: [PATCH 150/225] 8155236: AIX: fix dectection of Xrender extension Reviewed-by: prr --- .../libawt_xawt/java2d/x11/XRBackendNative.c | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c b/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c index 733606ec444..f408b0178ea 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -72,8 +72,8 @@ typedef struct _XRadialGradient { #include -#if defined(__solaris__) || defined(_AIX) -/* Solaris 10 and AIX will not have these symbols at runtime */ +#if defined(__solaris__) +/* Solaris 10 will not have these symbols at compile time */ typedef Picture (*XRenderCreateLinearGradientFuncType) (Display *dpy, @@ -147,7 +147,22 @@ static jboolean IsXRenderAvailable(jboolean verbose, jboolean ignoreLinuxVersion return JNI_FALSE; } -#if defined(__solaris__) || defined(_AIX) +#if defined(_AIX) + // On AIX we have to use a special syntax because the shared libraries are packed in + // multi-architecture archives. We first try to load the system default libXrender + // which is contained in the 'X11.base.lib' fileset starting with AIX 6.1 + xrenderlib = dlopen("libXrender.a(shr_64.o)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + if (xrenderlib == NULL) { + // If the latter wasn't successful, we also try to load the version under /opt/freeware + // This may be downloaded from the "AIX Toolbox for Linux Applications" even for AIX 5.3 + xrenderlib = dlopen("libXrender.a(libXrender.so.0)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER); + } + if (xrenderlib != NULL) { + dlclose(xrenderlib); + } else { + available = JNI_FALSE; + } +#elif defined(__solaris__) xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY); if (xrenderlib != NULL) { From 0b7775586ffeb3a549e06b297a2ec14a7a139d30 Mon Sep 17 00:00:00 2001 From: Michael Haupt Date: Wed, 27 Apr 2016 20:18:49 +0200 Subject: [PATCH 151/225] 8155106: MHs.Lookup.findConstructor returns handles for array classes Reviewed-by: shade, sundar --- .../java/lang/invoke/MethodHandleImpl.java | 7 +- .../java/lang/invoke/MethodHandles.java | 24 +++++ .../lang/invoke/ArrayConstructorTest.java | 91 +++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/lang/invoke/ArrayConstructorTest.java diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index a108836ce51..782eff613ae 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -25,6 +25,7 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; @@ -1892,7 +1893,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MH_tryFinallyExec = 12, MH_tryFinallyVoidExec = 13, MH_decrementCounter = 14, - MH_LIMIT = 15; + MH_Array_newInstance = 15, + MH_LIMIT = 16; static MethodHandle getConstantHandle(int idx) { MethodHandle handle = HANDLES[idx]; @@ -1965,6 +1967,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; case MH_decrementCounter: return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter", MethodType.methodType(int.class, int.class)); + case MH_Array_newInstance: + return IMPL_LOOKUP.findStatic(Array.class, "newInstance", + MethodType.methodType(Object.class, Class.class, int.class)); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); 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 afe6aecc9f4..c3a97a178a3 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 @@ -1010,6 +1010,9 @@ assertEquals("[x, y, z]", pb.command().toString()); * @throws NullPointerException if any argument is null */ public MethodHandle findConstructor(Class refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { + if (refc.isArray()) { + throw new NoSuchMethodException("no constructor for array class: " + refc.getName()); + } String name = ""; MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type); return getDirectConstructor(refc, ctor); @@ -2220,6 +2223,27 @@ return mh1; static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_LOOKUP_CLASS, Lookup.PUBLIC); } + /** + * Produces a method handle constructing arrays of a desired type. + * The return type of the method handle will be the array type. + * The type of its sole argument will be {@code int}, which specifies the size of the array. + * @param arrayClass an array type + * @return a method handle which can create arrays of the given type + * @throws NullPointerException if the argument is {@code null} + * @throws IllegalArgumentException if {@code arrayClass} is not an array type + * @see java.lang.reflect.Array#newInstance(Class, int) + * @since 9 + */ + public static + MethodHandle arrayConstructor(Class arrayClass) throws IllegalArgumentException { + if (!arrayClass.isArray()) { + throw newIllegalArgumentException("not an array class: " + arrayClass.getName()); + } + MethodHandle ani = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_Array_newInstance). + bindTo(arrayClass.getComponentType()); + return ani.asType(ani.type().changeReturnType(arrayClass)); + } + /** * Produces a method handle giving read access to elements of an array. * The type of the method handle will have a return type of the array's diff --git a/jdk/test/java/lang/invoke/ArrayConstructorTest.java b/jdk/test/java/lang/invoke/ArrayConstructorTest.java new file mode 100644 index 00000000000..9d0ae66188e --- /dev/null +++ b/jdk/test/java/lang/invoke/ArrayConstructorTest.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. 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 8155106 + * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayConstructorTest + */ +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + + +public class ArrayConstructorTest { + + static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testFindConstructorArray() { + boolean caught = false; + try { + MethodHandle h = LOOKUP.findConstructor(Object[].class, methodType(void.class)); + } catch (NoSuchMethodException nsme) { + assertEquals("no constructor for array class: [Ljava.lang.Object;", nsme.getMessage()); + caught = true; + } catch (Exception e) { + throw new AssertionError("unexpected exception: " + e); + } + assertTrue(caught); + } + + @DataProvider + static Object[][] arrayConstructorNegative() { + return new Object[][]{ + {String.class, IllegalArgumentException.class, "not an array class: java.lang.String"}, + {null, NullPointerException.class, null} + }; + } + + @Test(dataProvider = "arrayConstructorNegative") + public static void testArrayConstructorNegative(Class clazz, Class exceptionClass, String message) { + boolean caught = false; + try { + MethodHandle h = MethodHandles.arrayConstructor(clazz); + } catch (Exception e) { + assertEquals(exceptionClass, e.getClass()); + if (message != null) { + assertEquals(message, e.getMessage()); + } + caught = true; + } + assertTrue(caught); + } + + @Test + public static void testArrayConstructor() throws Throwable { + MethodHandle h = MethodHandles.arrayConstructor(String[].class); + assertEquals(methodType(String[].class, int.class), h.type()); + String[] a = (String[]) h.invoke(17); + assertEquals(17, a.length); + } + +} From f3402815334ce329c28f04836fcf96fe8b360f54 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 27 Apr 2016 12:06:51 -0700 Subject: [PATCH 152/225] 8154905: Rename jdk.jvmstat.rmi to jdk.jstatd Reviewed-by: alanb, sundar --- ...Launcher-jdk.jvmstat.rmi.gmk => Launcher-jdk.jstatd.gmk} | 0 .../share/classes/module-info.java | 2 +- .../classes/sun/jvmstat/monitor/remote/RemoteHost.java | 0 .../share/classes/sun/jvmstat/monitor/remote/RemoteVm.java | 0 .../share/classes/sun/jvmstat/monitor/remote/package.html | 0 .../monitor/protocol/rmi/MonitoredHostProvider.java | 0 .../monitor/protocol/rmi/MonitoredHostRmiService.java | 0 .../perfdata/monitor/protocol/rmi/PerfDataBuffer.java | 0 .../perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java | 0 .../perfdata/monitor/protocol/rmi/RemoteVmManager.java | 0 .../sun/jvmstat/perfdata/monitor/protocol/rmi/package.html | 0 .../share/classes/sun/tools/jstatd/Jstatd.java | 0 .../share/classes/sun/tools/jstatd/RemoteHostImpl.java | 0 .../share/classes/sun/tools/jstatd/RemoteVmImpl.java | 0 jdk/src/jdk.jvmstat/share/classes/module-info.java | 6 +++--- 15 files changed, 4 insertions(+), 4 deletions(-) rename jdk/make/launcher/{Launcher-jdk.jvmstat.rmi.gmk => Launcher-jdk.jstatd.gmk} (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/module-info.java (98%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/monitor/remote/package.html (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/Jstatd.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/RemoteHostImpl.java (100%) rename jdk/src/{jdk.jvmstat.rmi => jdk.jstatd}/share/classes/sun/tools/jstatd/RemoteVmImpl.java (100%) diff --git a/jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk b/jdk/make/launcher/Launcher-jdk.jstatd.gmk similarity index 100% rename from jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk rename to jdk/make/launcher/Launcher-jdk.jstatd.gmk diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java b/jdk/src/jdk.jstatd/share/classes/module-info.java similarity index 98% rename from jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java rename to jdk/src/jdk.jstatd/share/classes/module-info.java index 01ed37c3210..1f8a86e214d 100644 --- a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java +++ b/jdk/src/jdk.jstatd/share/classes/module-info.java @@ -23,7 +23,7 @@ * questions. */ -module jdk.jvmstat.rmi { +module jdk.jstatd { requires java.rmi; requires jdk.jvmstat; diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html rename to jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java diff --git a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java similarity index 100% rename from jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java rename to jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java diff --git a/jdk/src/jdk.jvmstat/share/classes/module-info.java b/jdk/src/jdk.jvmstat/share/classes/module-info.java index 2510a362931..d0038c242b2 100644 --- a/jdk/src/jdk.jvmstat/share/classes/module-info.java +++ b/jdk/src/jdk.jvmstat/share/classes/module-info.java @@ -28,12 +28,12 @@ module jdk.jvmstat { jdk.attach, jdk.jcmd, jdk.jconsole, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.monitor.event to jdk.jcmd, - jdk.jvmstat.rmi; + jdk.jstatd; exports sun.jvmstat.perfdata.monitor to - jdk.jvmstat.rmi; + jdk.jstatd; uses sun.jvmstat.monitor.MonitoredHostService; provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService; From da78f43efc7f2a26f583045cb245c2c0e92ff827 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 27 Apr 2016 20:35:23 +0100 Subject: [PATCH 153/225] 8044773: Refactor jdk.net API so that it can be moved out of the base module Co-authored-by: Erik Joelsson Reviewed-by: alanb, erikj, mchung --- make/GensrcModuleInfo.gmk | 19 ++++++++++++++----- make/Javadoc.gmk | 2 +- make/common/Modules.gmk | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/make/GensrcModuleInfo.gmk b/make/GensrcModuleInfo.gmk index 84bed9e8985..2fbcdc6ab24 100644 --- a/make/GensrcModuleInfo.gmk +++ b/make/GensrcModuleInfo.gmk @@ -78,21 +78,30 @@ ifneq ($(MOD_FILES), ) # let space represent new lines in the variable as $(shell) normalizes all # whitespace. $(foreach f, $(MOD_FILES), \ - $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v ".\*" $f | $(TR) ' ' '/'))) + $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v -e ".\*" -e "//" $f | $(TR) ' ' '/'))) + + # Separate the modifications into qualified exports and the rest + MODS_QUALIFIED_EXPORTS := $(call containing, /to/, $(MOD_FILE_CONTENTS)) + MODS_REST := $(filter-out $(MODS_QUALIFIED_EXPORTS), $(MOD_FILE_CONTENTS)) # Filter the contents for modules that are actually being built MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES))) - MODULES_FILTER += provides% - MODIFICATIONS := $(filter $(MODULES_FILTER), $(MOD_FILE_CONTENTS)) + MODIFICATIONS := $(filter $(MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \ + $(MODS_REST) # Convert the modification lines into arguments for the modification tool. # Filter out modifications for non existing to-modules. $(foreach line, $(MODIFICATIONS), \ $(eval split_line := $(subst /,$(SPACE),$(line))) \ $(eval command := $(word 1, $(split_line))) \ - $(eval package := $(word 2, $(split_line))) \ + $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \ $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \ - $(eval ARGS += -$(command) $(package)/$(to_module))) + $(if $(to_module), \ + $(eval ARGS += -$(command) $(package)/$(to_module)) \ + , \ + $(eval ARGS += -$(command) $(package)) \ + ) \ + ) ifneq ($(ARGS), ) $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \ diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk index 2998dbf5242..d1e85b4b746 100644 --- a/make/Javadoc.gmk +++ b/make/Javadoc.gmk @@ -1580,7 +1580,7 @@ JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages # The modules required to be documented -JDKNET_MODULES = java.base +JDKNET_MODULES = jdk.net jdknetdocs: $(JDKNET_INDEX_HTML) diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index cba267b0075..dba855995d7 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -63,6 +63,7 @@ BOOT_MODULES += \ java.xml.crypto \ jdk.httpserver \ jdk.management \ + jdk.net \ jdk.sctp \ jdk.security.auth \ jdk.security.jgss \ From 07cef26155dee0957073ebaf2d57f745d0a32c5c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 27 Apr 2016 20:36:02 +0100 Subject: [PATCH 154/225] 8044773: Refactor jdk.net API so that it can be moved out of the base module Reviewed-by: alanb, erikj, mchung --- jdk/make/lib/Lib-jdk.net.gmk | 51 +++ jdk/make/mapfiles/libextnet/mapfile-vers | 34 ++ jdk/make/mapfiles/libnet/mapfile-vers | 4 - .../tools/module/GenModuleInfoSource.java | 2 +- .../jdk/net/ExtendedSocketOptions.java | 61 ---- .../java.base/share/classes/module-info.java | 4 +- .../classes/sun/net/ExtendedOptionsImpl.java | 92 ----- .../sun/net/ext/ExtendedSocketOptions.java | 110 ++++++ .../nio/ch/AsynchronousSocketChannelImpl.java | 8 +- .../sun/nio/ch/DatagramChannelImpl.java | 8 +- .../share/classes/sun/nio/ch/Net.java | 25 +- .../classes/sun/nio/ch/SocketChannelImpl.java | 9 +- .../java/net/PlainDatagramSocketImpl.java | 44 +-- .../classes/java/net/PlainSocketImpl.java | 47 ++- .../unix/native/libnet/ExtendedOptionsImpl.c | 344 ------------------ .../unix/native/libnet/net_util_md.h | 41 --- .../jdk/net/ExtendedSocketOptions.java | 212 +++++++++++ .../classes/jdk/net/NetworkPermission.java | 0 .../share/classes/jdk/net/SocketFlow.java | 81 +++-- .../share/classes/jdk/net/Sockets.java | 33 +- .../share/classes/jdk/net/package-info.java | 0 .../jdk.net/share/classes/module-info.java | 29 ++ .../jdk/net/SolarisSocketOptions.java} | 67 ++-- .../native/libextnet/SolarisSocketOptions.c | 176 +++++++++ .../native/libextnet/SolarisSocketOptions.h | 79 ++++ .../share/classes/module-info.java | 1 + .../java/net/SocketOption/OptionsTest.java | 25 +- .../SocketOption/UnsupportedOptionsTest.java | 52 ++- .../DatagramChannel/SocketOptionTests.java | 4 +- .../SocketOptionTests.java | 4 +- .../SocketChannel/SocketOptionTests.java | 4 +- .../jdk/net/SocketFlow/SocketFlowBasic.java | 93 +++++ jdk/test/jdk/net/Sockets/Test.java | 165 +++++---- 33 files changed, 1096 insertions(+), 813 deletions(-) create mode 100644 jdk/make/lib/Lib-jdk.net.gmk create mode 100644 jdk/make/mapfiles/libextnet/mapfile-vers delete mode 100644 jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java delete mode 100644 jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java create mode 100644 jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java delete mode 100644 jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c create mode 100644 jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/NetworkPermission.java (100%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/SocketFlow.java (69%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/Sockets.java (94%) rename jdk/src/{java.base => jdk.net}/share/classes/jdk/net/package-info.java (100%) create mode 100644 jdk/src/jdk.net/share/classes/module-info.java rename jdk/src/{java.base/windows/native/libnet/ExtendedOptionsImpl.c => jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java} (52%) create mode 100644 jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c create mode 100644 jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h create mode 100644 jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java diff --git a/jdk/make/lib/Lib-jdk.net.gmk b/jdk/make/lib/Lib-jdk.net.gmk new file mode 100644 index 00000000000..69c789b2f08 --- /dev/null +++ b/jdk/make/lib/Lib-jdk.net.gmk @@ -0,0 +1,51 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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 LibCommon.gmk + +################################################################################ + +ifeq ($(OPENJDK_TARGET_OS), solaris) + + $(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \ + LIBRARY := extnet, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(JDK_TOPDIR)/src/jdk.net/solaris/native/libextnet, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := -lsocket -lc -ljava, \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \ + )) + + $(BUILD_LIBEXTNET): $(call FindLib, java.base, java) + + TARGETS += $(BUILD_LIBEXTNET) +endif + + +################################################################################ diff --git a/jdk/make/mapfiles/libextnet/mapfile-vers b/jdk/make/mapfiles/libextnet/mapfile-vers new file mode 100644 index 00000000000..5dbc5b960aa --- /dev/null +++ b/jdk/make/mapfiles/libextnet/mapfile-vers @@ -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. 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. +# + +SUNWprivate_1.1 { + global: + Java_jdk_net_SolarisSocketOptions_init; + Java_jdk_net_SolarisSocketOptions_setFlowOption; + Java_jdk_net_SolarisSocketOptions_getFlowOption; + Java_jdk_net_SolarisSocketOptions_flowSupported; + local: + *; +}; diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers index 82247780181..92816bfa87d 100644 --- a/jdk/make/mapfiles/libnet/mapfile-vers +++ b/jdk/make/mapfiles/libnet/mapfile-vers @@ -98,10 +98,6 @@ SUNWprivate_1.1 { Java_sun_net_sdp_SdpSupport_create0; Java_sun_net_spi_DefaultProxySelector_init; Java_sun_net_spi_DefaultProxySelector_getSystemProxy; - Java_sun_net_ExtendedOptionsImpl_init; - Java_sun_net_ExtendedOptionsImpl_setFlowOption; - Java_sun_net_ExtendedOptionsImpl_getFlowOption; - Java_sun_net_ExtendedOptionsImpl_flowSupported; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress; diff --git a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java index f2f404e9a0b..e7d932d1141 100644 --- a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java +++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java @@ -52,7 +52,7 @@ public class GenModuleInfoSource { "Usage: GenModuleInfoSource [option] -o \n" + "Options are:\n" + " -exports \n" + - " -exports /\n" + + " -exports [/]\n" + " -uses \n" + " -provides /\n"; diff --git a/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java b/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java deleted file mode 100644 index 12af5aff7ee..00000000000 --- a/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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. 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.net; - -import java.net.SocketOption; - -/** - * Defines extended socket options, beyond those defined in - * {@link java.net.StandardSocketOptions}. These options may be platform - * specific. - * - * @since 1.8 - */ -public final class ExtendedSocketOptions { - - private static class ExtSocketOption implements SocketOption { - private final String name; - private final Class type; - ExtSocketOption(String name, Class type) { - this.name = name; - this.type = type; - } - @Override public String name() { return name; } - @Override public Class type() { return type; } - @Override public String toString() { return name; } - } - - private ExtendedSocketOptions() {} - - /** - * Service level properties. When a security manager is installed, - * setting or getting this option requires a {@link NetworkPermission} - * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} - * respectively. - */ - public static final SocketOption SO_FLOW_SLA = new - ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); -} diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 942c0582ea0..12ad93f6a6d 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -83,8 +83,6 @@ module java.base { // see JDK-8144062 exports jdk; - // see JDK-8044773 - exports jdk.net; // the service types defined by the APIs in this module @@ -194,6 +192,8 @@ module java.base { jdk.jvmstat; exports sun.net to java.httpclient; + exports sun.net.ext to + jdk.net; exports sun.net.dns to java.security.jgss, jdk.naming.dns; diff --git a/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java b/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java deleted file mode 100644 index 8fbcdd7b49d..00000000000 --- a/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. 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; - -import java.net.*; -import jdk.net.*; -import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; -import java.util.Collections; - -/** - * Contains the native implementation for extended socket options - * together with some other static utilities - */ -public class ExtendedOptionsImpl { - - static { - AccessController.doPrivileged((PrivilegedAction)() -> { - System.loadLibrary("net"); - return null; - }); - init(); - } - - private ExtendedOptionsImpl() {} - - public static void checkSetOptionPermission(SocketOption option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "setOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkGetOptionPermission(SocketOption option) { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - return; - } - String check = "getOption." + option.name(); - sm.checkPermission(new NetworkPermission(check)); - } - - public static void checkValueType(Object value, Class type) { - if (!type.isAssignableFrom(value.getClass())) { - String s = "Found: " + value.getClass().toString() + " Expected: " - + type.toString(); - throw new IllegalArgumentException(s); - } - } - - private static native void init(); - - /* - * Extension native implementations - * - * SO_FLOW_SLA - */ - public static native void setFlowOption(FileDescriptor fd, SocketFlow f); - public static native void getFlowOption(FileDescriptor fd, SocketFlow f); - public static native boolean flowSupported(); -} diff --git a/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java b/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java new file mode 100644 index 00000000000..a3300c3c0e9 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java @@ -0,0 +1,110 @@ +/* + * 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.ext; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.util.Collections; +import java.util.Set; + +/** + * Defines the infrastructure to support extended socket options, beyond those + * defined in {@link java.net.StandardSocketOptions}. + * + * Extended socket options are accessed through the jdk.net API, which is in + * the jdk.net module. + */ +public abstract class ExtendedSocketOptions { + + private final Set> options; + + /** Tells whether or not the option is supported. */ + public final boolean isOptionSupported(SocketOption option) { + return options().contains(option); + } + + /** Return the, possibly empty, set of extended socket options available. */ + public final Set> options() { return options; } + + /** Sets the value of a socket option, for the given socket. */ + public abstract void setOption(FileDescriptor fd, SocketOption option, Object value) + throws SocketException; + + /** Returns the value of a socket option, for the given socket. */ + public abstract Object getOption(FileDescriptor fd, SocketOption option) + throws SocketException; + + protected ExtendedSocketOptions(Set> options) { + this.options = options; + } + + private static volatile ExtendedSocketOptions instance; + + public static final ExtendedSocketOptions getInstance() { return instance; } + + /** Registers support for extended socket options. Invoked by the jdk.net module. */ + public static final void register(ExtendedSocketOptions extOptions) { + if (instance != null) + throw new InternalError("Attempting to reregister extended options"); + + instance = extOptions; + } + + static { + try { + // If the class is present, it will be initialized which + // triggers registration of the extended socket options. + Class c = Class.forName("jdk.net.ExtendedSocketOptions"); + } catch (ClassNotFoundException e) { + // the jdk.net module is not present => no extended socket options + instance = new NoExtendedSocketOptions(); + } + } + + static final class NoExtendedSocketOptions extends ExtendedSocketOptions { + + NoExtendedSocketOptions() { + super(Collections.>emptySet()); + } + + @Override + public void setOption(FileDescriptor fd, SocketOption option, Object value) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + + @Override + public Object getOption(FileDescriptor fd, SocketOption option) + throws SocketException + { + throw new UnsupportedOperationException( + "no extended options: " + option.name()); + } + } +} diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 36b3c1b7ab9..1faf49b8578 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -39,7 +39,7 @@ import java.util.Collections; import java.util.concurrent.*; import java.util.concurrent.locks.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * Base implementation of AsynchronousSocketChannel @@ -512,9 +512,9 @@ abstract class AsynchronousSocketChannelImpl set.add(StandardSocketOptions.SO_REUSEPORT); } set.add(StandardSocketOptions.TCP_NODELAY); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 77d14619222..f063e13ac13 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -33,7 +33,7 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; import sun.net.ResourceManager; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of DatagramChannels. @@ -306,9 +306,9 @@ class DatagramChannelImpl set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); set.add(StandardSocketOptions.IP_MULTICAST_LOOP); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } 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 9a5c4dcb6f8..59d3167745b 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 @@ -27,15 +27,13 @@ package sun.nio.ch; import java.io.*; import java.net.*; -import jdk.net.*; import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.net.ExtendedOptionsImpl; +import sun.net.ext.ExtendedSocketOptions; import sun.security.action.GetPropertyAction; - public class Net { private Net() { } @@ -281,6 +279,9 @@ public class Net { // -- Socket options + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + static void setSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption name, Object value) throws IOException @@ -291,12 +292,8 @@ public class Net { // only simple values supported by this method Class type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA")); - } - ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value); + if (extendedOptions.isOptionSupported(name)) { + extendedOptions.setOption(fd, name, value); return; } @@ -353,14 +350,8 @@ public class Net { { Class type = name.type(); - if (type == SocketFlow.class) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA")); - } - SocketFlow flow = SocketFlow.create(); - ExtendedOptionsImpl.getFlowOption(fd, flow); - return flow; + if (extendedOptions.isOptionSupported(name)) { + return extendedOptions.getOption(fd, name); } // only simple values supported by this method diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c4644920c3e..856e0cf2fb6 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -33,8 +33,7 @@ import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; -import sun.net.ExtendedOptionsImpl; - +import sun.net.ext.ExtendedSocketOptions; /** * An implementation of SocketChannels @@ -242,9 +241,9 @@ class SocketChannelImpl // additional options required by socket adaptor set.add(StandardSocketOptions.IP_TOS); set.add(ExtendedSocketOption.SO_OOBINLINE); - if (ExtendedOptionsImpl.flowSupported()) { - set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); - } + ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + set.addAll(extendedOptions.options()); return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java index f7c65931613..32640dff272 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java @@ -27,9 +27,7 @@ package java.net; import java.io.IOException; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -43,8 +41,11 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl init(); } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected void setOption(SocketOption name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -55,21 +56,16 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } } } else { - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } if (isClosed()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -79,31 +75,23 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (isClosed()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (!flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosed()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set> supportedOptions() { - HashSet> options = new HashSet<>( - super.supportedOptions()); - - if (flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); - } + HashSet> options = new HashSet<>(super.supportedOptions()); + options.addAll(extendedOptions.options()); return options; } protected void socketSetOption(int opt, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try { diff --git a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java index 2ec573ea5a9..4a5f2b5ddd6 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java @@ -28,10 +28,7 @@ import java.io.IOException; import java.io.FileDescriptor; import java.util.Set; import java.util.HashSet; -import java.util.Collections; -import jdk.net.*; - -import static sun.net.ExtendedOptionsImpl.*; +import sun.net.ext.ExtendedSocketOptions; /* * On Unix systems we simply delegate to native methods. @@ -57,8 +54,11 @@ class PlainSocketImpl extends AbstractPlainSocketImpl this.fd = fd; } + static final ExtendedSocketOptions extendedOptions = + ExtendedSocketOptions.getInstance(); + protected void setOption(SocketOption name, T value) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { super.setOption(name, value); } else { @@ -69,21 +69,19 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } } } else { - if (getSocket() == null || !flowSupported()) { + if (getSocket() == null) { throw new UnsupportedOperationException("unsupported option"); } if (isClosedOrPending()) { throw new SocketException("Socket closed"); } - checkSetOptionPermission(name); - checkValueType(value, SocketFlow.class); - setFlowOption(getFileDescriptor(), (SocketFlow)value); + extendedOptions.setOption(fd, name, value); } } @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { - if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { + if (!extendedOptions.isOptionSupported(name)) { if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { return super.getOption(name); } else { @@ -93,31 +91,28 @@ class PlainSocketImpl extends AbstractPlainSocketImpl throw new UnsupportedOperationException("unsupported option"); } } + } else { + if (getSocket() == null) { + throw new UnsupportedOperationException("unsupported option"); + } + if (isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + return (T) extendedOptions.getOption(fd, name); } - if (getSocket() == null || !flowSupported()) { - throw new UnsupportedOperationException("unsupported option"); - } - if (isClosedOrPending()) { - throw new SocketException("Socket closed"); - } - checkGetOptionPermission(name); - SocketFlow flow = SocketFlow.create(); - getFlowOption(getFileDescriptor(), flow); - return (T)flow; } protected Set> supportedOptions() { - HashSet> options = new HashSet<>( - super.supportedOptions()); - - if (getSocket() != null && flowSupported()) { - options.add(ExtendedSocketOptions.SO_FLOW_SLA); + HashSet> options = new HashSet<>(super.supportedOptions()); + if (getSocket() != null) { + options.addAll(extendedOptions.options()); } return options; } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { - if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + if (opt == SocketOptions.SO_REUSEPORT && + !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { throw new UnsupportedOperationException("unsupported option"); } try { diff --git a/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c b/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c deleted file mode 100644 index 116d2e97d92..00000000000 --- a/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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. 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 -#include - -#include "net_util.h" -#include "jdk_net_SocketFlow.h" - -static jclass sf_status_class; /* Status enum type */ - -static jfieldID sf_status; -static jfieldID sf_priority; -static jfieldID sf_bandwidth; - -static jfieldID sf_fd_fdID; /* FileDescriptor.fd */ - -/* References to the literal enum values */ - -static jobject sfs_NOSTATUS; -static jobject sfs_OK; -static jobject sfs_NOPERMISSION; -static jobject sfs_NOTCONNECTED; -static jobject sfs_NOTSUPPORTED; -static jobject sfs_ALREADYCREATED; -static jobject sfs_INPROGRESS; -static jobject sfs_OTHER; - -static jobject getEnumField(JNIEnv *env, char *name); -static void setStatus(JNIEnv *env, jobject obj, int errval); - -/* OS specific code is implemented in these three functions */ - -static jboolean flowSupported0() ; - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ - static int initialized = 0; - jclass c; - - /* Global class references */ - - if (initialized) { - return; - } - - c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status"); - CHECK_NULL(c); - sf_status_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(sf_status_class); - - /* int "fd" field of java.io.FileDescriptor */ - - c = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(c); - sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I"); - CHECK_NULL(sf_fd_fdID); - - - /* SocketFlow fields */ - - c = (*env)->FindClass(env, "jdk/net/SocketFlow"); - CHECK_NULL(c); - - /* status */ - - sf_status = (*env)->GetFieldID(env, c, "status", - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL(sf_status); - - /* priority */ - - sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); - CHECK_NULL(sf_priority); - - /* bandwidth */ - - sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); - CHECK_NULL(sf_bandwidth); - - /* Initialize the static enum values */ - - sfs_NOSTATUS = getEnumField(env, "NO_STATUS"); - CHECK_NULL(sfs_NOSTATUS); - sfs_OK = getEnumField(env, "OK"); - CHECK_NULL(sfs_OK); - sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION"); - CHECK_NULL(sfs_NOPERMISSION); - sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED"); - CHECK_NULL(sfs_NOTCONNECTED); - sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED"); - CHECK_NULL(sfs_NOTSUPPORTED); - sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED"); - CHECK_NULL(sfs_ALREADYCREATED); - sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS"); - CHECK_NULL(sfs_INPROGRESS); - sfs_OTHER = getEnumField(env, "OTHER"); - CHECK_NULL(sfs_OTHER); - initialized = JNI_TRUE; -} - -static jobject getEnumField(JNIEnv *env, char *name) -{ - jobject f; - jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name, - "Ljdk/net/SocketFlow$Status;"); - CHECK_NULL_RETURN(fID, NULL); - - f = (*env)->GetStaticObjectField(env, sf_status_class, fID); - CHECK_NULL_RETURN(f, NULL); - f = (*env)->NewGlobalRef(env, f); - CHECK_NULL_RETURN(f, NULL); - return f; -} - -/* - * Retrieve the int file-descriptor from a public socket type object. - * Gets impl, then the FileDescriptor from the impl, and then the fd - * from that. - */ -static int getFD(JNIEnv *env, jobject fileDesc) { - return (*env)->GetIntField(env, fileDesc, sf_fd_fdID); -} - -/** - * Sets the status field of a SocketFlow to one of the - * canned enum values - */ -static void setStatus (JNIEnv *env, jobject obj, int errval) -{ - switch (errval) { - case 0: /* OK */ - (*env)->SetObjectField(env, obj, sf_status, sfs_OK); - break; - case EPERM: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION); - break; - case ENOTCONN: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED); - break; - case EOPNOTSUPP: - (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED); - break; - case EALREADY: - (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED); - break; - case EINPROGRESS: - (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS); - break; - default: - (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER); - break; - } -} - -#ifdef __solaris__ - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: setFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - jlong bandwidth; - int rv; - - jint priority = (*env)->GetIntField(env, flow, sf_priority); - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - - if (priority != jdk_net_SocketFlow_UNSET) { - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = priority; - } - bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth); - if (bandwidth > -1) { - props.sfp_mask |= SFP_MAXBW; - props.sfp_maxbw = (uint64_t) bandwidth; - } - rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - setStatus(env, flow, props.sfp_status); - } -} - -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: getFlowOption - * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - int fd = getFD(env, fileDesc); - - if (fd < 0) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - sock_flow_props_t props; - int status; - socklen_t sz = sizeof(props); - - int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); - if (rv < 0) { - if (errno == ENOPROTOOPT) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); - } else if (errno == EACCES || errno == EPERM) { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "Permission denied"); - } else { - NET_ERROR(env, JNU_JAVANETPKG "SocketException", - "set option SO_FLOW_SLA failed"); - } - return; - } - /* first check status to see if flow exists */ - status = props.sfp_status; - setStatus(env, flow, status); - if (status == 0) { /* OK */ - /* can set the other fields now */ - if (props.sfp_mask & SFP_PRIORITY) { - (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); - } - if (props.sfp_mask & SFP_MAXBW) { - (*env)->SetLongField(env, flow, sf_bandwidth, - (jlong)props.sfp_maxbw); - } - } - } -} - -static jboolean flowsupported; -static jboolean flowsupported_set = JNI_FALSE; - -static jboolean flowSupported0() -{ - /* Do a simple dummy call, and try to figure out from that */ - sock_flow_props_t props; - int rv, s; - if (flowsupported_set) { - return flowsupported; - } - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (s < 0) { - flowsupported = JNI_FALSE; - flowsupported_set = JNI_TRUE; - return JNI_FALSE; - } - memset(&props, 0, sizeof(props)); - props.sfp_version = SOCK_FLOW_PROP_VERSION1; - props.sfp_mask |= SFP_PRIORITY; - props.sfp_priority = SFP_PRIO_NORMAL; - rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); - if (rv != 0 && errno == ENOPROTOOPT) { - rv = JNI_FALSE; - } else { - rv = JNI_TRUE; - } - close(s); - flowsupported = rv; - flowsupported_set = JNI_TRUE; - return flowsupported; -} - -#else /* __solaris__ */ - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return flowSupported0(); -} diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h index f440bd8ae6a..3a8c9f4d48e 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.h +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h @@ -120,47 +120,6 @@ int getDefaultIPv6Interface(struct in6_addr *target_addr); #ifdef __solaris__ int net_getParam(char *driver, char *param); - -#ifndef SO_FLOW_SLA -#define SO_FLOW_SLA 0x1018 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack(4) #endif -/* - * Used with the setsockopt(SO_FLOW_SLA, ...) call to set - * per socket service level properties. - * When the application uses per-socket API, we will enforce the properties - * on both outbound and inbound packets. - * - * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. - */ -typedef struct sock_flow_props_s { - int sfp_version; - uint32_t sfp_mask; - int sfp_priority; /* flow priority */ - uint64_t sfp_maxbw; /* bandwidth limit in bps */ - int sfp_status; /* flow create status for getsockopt */ -} sock_flow_props_t; - -#define SOCK_FLOW_PROP_VERSION1 1 - -/* bit mask values for sfp_mask */ -#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ -#define SFP_PRIORITY 0x00000008 /* Flow priority */ - -/* possible values for sfp_priority */ -#define SFP_PRIO_NORMAL 1 -#define SFP_PRIO_HIGH 2 - -#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 -#pragma pack() -#endif /* _LONG_LONG_ALIGNMENT */ - -#endif /* SO_FLOW_SLA */ -#endif /* __solaris__ */ - -JNIEXPORT jboolean JNICALL NET_IsFlowSupported(); - #endif /* NET_UTILS_MD_H */ diff --git a/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java b/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java new file mode 100644 index 00000000000..bcae6ce2251 --- /dev/null +++ b/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java @@ -0,0 +1,212 @@ +/* + * 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. 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.net; + +import java.io.FileDescriptor; +import java.net.SocketException; +import java.net.SocketOption; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Set; +import jdk.internal.misc.JavaIOFileDescriptorAccess; +import jdk.internal.misc.SharedSecrets; + +/** + * Defines extended socket options, beyond those defined in + * {@link java.net.StandardSocketOptions}. These options may be platform + * specific. + * + * @since 1.8 + */ +public final class ExtendedSocketOptions { + + private static class ExtSocketOption implements SocketOption { + private final String name; + private final Class type; + ExtSocketOption(String name, Class type) { + this.name = name; + this.type = type; + } + @Override public String name() { return name; } + @Override public Class type() { return type; } + @Override public String toString() { return name; } + } + + private ExtendedSocketOptions() { } + + /** + * Service level properties. When a security manager is installed, + * setting or getting this option requires a {@link NetworkPermission} + * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"} + * respectively. + */ + public static final SocketOption SO_FLOW_SLA = new + ExtSocketOption("SO_FLOW_SLA", SocketFlow.class); + + + private static final PlatformSocketOptions platformSocketOptions = + PlatformSocketOptions.get(); + + private static final boolean flowSupported = + platformSocketOptions.flowSupported(); + + private static final Set> extendedOptions = options(); + + static Set> options() { + if (flowSupported) + return Set.of(SO_FLOW_SLA); + else + return Collections.>emptySet(); + } + + static { + // Registers the extended socket options with the base module. + sun.net.ext.ExtendedSocketOptions.register( + new sun.net.ext.ExtendedSocketOptions(extendedOptions) { + + @Override + public void setOption(FileDescriptor fd, + SocketOption option, + Object value) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("setOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = checkValueType(value, option.type()); + setFlowOption(fd, flow); + } else { + throw new InternalError("Unexpected option " + option); + } + } + + @Override + public Object getOption(FileDescriptor fd, + SocketOption option) + throws SocketException + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new NetworkPermission("getOption." + option.name())); + + if (fd == null || !fd.valid()) + throw new SocketException("socket closed"); + + if (option == SO_FLOW_SLA) { + assert flowSupported; + SocketFlow flow = SocketFlow.create(); + getFlowOption(fd, flow); + return flow; + } else { + throw new InternalError("Unexpected option " + option); + } + } + }); + } + + @SuppressWarnings("unchecked") + private static T checkValueType(Object value, Class type) { + if (!type.isAssignableFrom(value.getClass())) { + String s = "Found: " + value.getClass() + ", Expected: " + type; + throw new IllegalArgumentException(s); + } + return (T) value; + } + + private static final JavaIOFileDescriptorAccess fdAccess = + SharedSecrets.getJavaIOFileDescriptorAccess(); + + private static void setFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.setFlowOption(fdAccess.get(fd), + f.priority(), + f.bandwidth()); + f.status(status); // augment the given flow with the status + } + + private static void getFlowOption(FileDescriptor fd, SocketFlow f) + throws SocketException + { + int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f); + f.status(status); // augment the given flow with the status + } + + static class PlatformSocketOptions { + + protected PlatformSocketOptions() {} + + @SuppressWarnings("unchecked") + private static PlatformSocketOptions newInstance(String cn) { + Class c; + try { + c = (Class)Class.forName(cn); + return c.getConstructor(new Class[] { }).newInstance(); + } catch (ReflectiveOperationException x) { + throw new AssertionError(x); + } + } + + private static PlatformSocketOptions create() { + String osname = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("os.name"); + } + }); + if ("SunOS".equals(osname)) + return newInstance("jdk.net.SolarisSocketOptions"); + return new PlatformSocketOptions(); + } + + private static final PlatformSocketOptions instance = create(); + + static PlatformSocketOptions get() { + return instance; + } + + int setFlowOption(int fd, int priority, long bandwidth) + throws SocketException + { + throw new UnsupportedOperationException("unsupported socket option"); + } + + int getFlowOption(int fd, SocketFlow f) throws SocketException { + throw new UnsupportedOperationException("unsupported socket option"); + } + + boolean flowSupported() { + return false; + } + } +} diff --git a/jdk/src/java.base/share/classes/jdk/net/NetworkPermission.java b/jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java similarity index 100% rename from jdk/src/java.base/share/classes/jdk/net/NetworkPermission.java rename to jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java diff --git a/jdk/src/java.base/share/classes/jdk/net/SocketFlow.java b/jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java similarity index 69% rename from jdk/src/java.base/share/classes/jdk/net/SocketFlow.java rename to jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java index 12d1ed386d1..91c62cfa3d4 100644 --- a/jdk/src/java.base/share/classes/jdk/net/SocketFlow.java +++ b/jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java @@ -47,17 +47,18 @@ import java.lang.annotation.Native; */ public class SocketFlow { - private static final int UNSET = -1; + @Native public static final int UNSET = -1; @Native public static final int NORMAL_PRIORITY = 1; @Native public static final int HIGH_PRIORITY = 2; - private int priority = NORMAL_PRIORITY; - - private long bandwidth = UNSET; - - private Status status = Status.NO_STATUS; - - private SocketFlow() {} + @Native private static final int NO_STATUS_VALUE = 0; + @Native private static final int OK_VALUE = 1; + @Native private static final int NO_PERMISSION_VALUE = 2; + @Native private static final int NOT_CONNECTED_VALUE = 3; + @Native private static final int NOT_SUPPORTED_VALUE = 4; + @Native private static final int ALREADY_CREATED_VALUE = 5; + @Native private static final int IN_PROGRESS_VALUE = 6; + @Native private static final int OTHER_VALUE = 7; /** * Enumeration of the return values from the SO_FLOW_SLA @@ -72,37 +73,56 @@ public class SocketFlow { * Set or get socket option has not been called yet. Status * values can only be retrieved after calling set or get. */ - NO_STATUS, + NO_STATUS(NO_STATUS_VALUE), /** * Flow successfully created. */ - OK, + OK(OK_VALUE), /** * Caller has no permission to create flow. */ - NO_PERMISSION, + NO_PERMISSION(NO_PERMISSION_VALUE), /** * Flow can not be created because socket is not connected. */ - NOT_CONNECTED, + NOT_CONNECTED(NOT_CONNECTED_VALUE), /** * Flow creation not supported for this socket. */ - NOT_SUPPORTED, + NOT_SUPPORTED(NOT_SUPPORTED_VALUE), /** * A flow already exists with identical attributes. */ - ALREADY_CREATED, + ALREADY_CREATED(ALREADY_CREATED_VALUE), /** * A flow is being created. */ - IN_PROGRESS, + IN_PROGRESS(IN_PROGRESS_VALUE), /** * Some other unspecified error. */ - OTHER + OTHER(OTHER_VALUE); + + private final int value; + Status(int value) { this.value = value; } + + static Status from(int value) { + if (value == NO_STATUS.value) return NO_STATUS; + else if (value == OK.value) return OK; + else if (value == NO_PERMISSION.value) return NO_PERMISSION; + else if (value == NOT_CONNECTED.value) return NOT_CONNECTED; + else if (value == NOT_SUPPORTED.value) return NOT_SUPPORTED; + else if (value == ALREADY_CREATED.value) return ALREADY_CREATED; + else if (value == IN_PROGRESS.value) return IN_PROGRESS; + else if (value == OTHER.value) return OTHER; + else throw new InternalError("Unknown value: " + value); + } } + private int priority = NORMAL_PRIORITY; + private long bandwidth = UNSET; + private Status status = Status.NO_STATUS; + /** * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA * socket option and create a socket flow. @@ -111,6 +131,8 @@ public class SocketFlow { return new SocketFlow(); } + private SocketFlow() { } + /** * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY * HIGH_PRIORITY. If not set, a flow's priority is normal. @@ -119,9 +141,8 @@ public class SocketFlow { * HIGH_PRIORITY. */ public SocketFlow priority(int priority) { - if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) { - throw new IllegalArgumentException("invalid priority"); - } + if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) + throw new IllegalArgumentException("invalid priority :" + priority); this.priority = priority; return this; } @@ -133,11 +154,9 @@ public class SocketFlow { * @throws IllegalArgumentException if bandwidth is less than zero. */ public SocketFlow bandwidth(long bandwidth) { - if (bandwidth < 0) { - throw new IllegalArgumentException("invalid bandwidth"); - } else { - this.bandwidth = bandwidth; - } + if (bandwidth < 0) + throw new IllegalArgumentException("invalid bandwidth: " + bandwidth); + this.bandwidth = bandwidth; return this; } @@ -164,4 +183,18 @@ public class SocketFlow { public Status status() { return status; } + + void status(int status) { + this.status = Status.from(status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(super.toString()); + sb.append(" [ priority=").append(priority()) + .append(", bandwidth=").append(bandwidth()) + .append(", status=").append(status()) + .append(" ]"); + return sb.toString(); + } } diff --git a/jdk/src/java.base/share/classes/jdk/net/Sockets.java b/jdk/src/jdk.net/share/classes/jdk/net/Sockets.java similarity index 94% rename from jdk/src/java.base/share/classes/jdk/net/Sockets.java rename to jdk/src/jdk.net/share/classes/jdk/net/Sockets.java index a8b78b044d8..983fe38956f 100644 --- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java +++ b/jdk/src/jdk.net/share/classes/jdk/net/Sockets.java @@ -27,15 +27,12 @@ package jdk.net; import java.net.*; import java.io.IOException; -import java.io.FileDescriptor; -import java.security.PrivilegedAction; -import java.security.AccessController; -import java.lang.reflect.Field; -import java.util.Set; -import java.util.HashSet; -import java.util.HashMap; import java.util.Collections; -import sun.net.ExtendedOptionsImpl; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; /** * Defines static methods to set and get socket options defined by the @@ -57,12 +54,8 @@ import sun.net.ExtendedOptionsImpl; */ public class Sockets { - private static final HashMap,Set>> - options = new HashMap<>(); - - static { - initOptionSets(); - } + private static final Map,Set>> + options = optionSets(); private Sockets() {} @@ -259,14 +252,16 @@ public class Sockets { */ static boolean isReusePortAvailable() { if (!checkedReusePort) { - isReusePortAvailable = isReusePortAvailable0(); + Set> s = new Socket().supportedOptions(); + isReusePortAvailable = s.contains(StandardSocketOptions.SO_REUSEPORT); checkedReusePort = true; } return isReusePortAvailable; } - private static void initOptionSets() { - boolean flowsupported = ExtendedOptionsImpl.flowSupported(); + private static Map,Set>> optionSets() { + Map,Set>> options = new HashMap<>(); + boolean flowsupported = PlatformSocketOptions.get().flowSupported(); boolean reuseportsupported = isReusePortAvailable(); // Socket @@ -333,7 +328,7 @@ public class Sockets { } set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); - } - private static native boolean isReusePortAvailable0(); + return Collections.unmodifiableMap(options); + } } diff --git a/jdk/src/java.base/share/classes/jdk/net/package-info.java b/jdk/src/jdk.net/share/classes/jdk/net/package-info.java similarity index 100% rename from jdk/src/java.base/share/classes/jdk/net/package-info.java rename to jdk/src/jdk.net/share/classes/jdk/net/package-info.java diff --git a/jdk/src/jdk.net/share/classes/module-info.java b/jdk/src/jdk.net/share/classes/module-info.java new file mode 100644 index 00000000000..95fb57915a8 --- /dev/null +++ b/jdk/src/jdk.net/share/classes/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. 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. + */ + +module jdk.net { + exports jdk.net; +} + diff --git a/jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c b/jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java similarity index 52% rename from jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c rename to jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java index 2bd955cd13e..1381f22014b 100644 --- a/jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c +++ b/jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,43 +23,34 @@ * questions. */ -#include -#include +package jdk.net; -#include "net_util.h" +import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.net.ExtendedSocketOptions.PlatformSocketOptions; -/* - * Class: sun_net_ExtendedOptionsImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init - (JNIEnv *env, jclass UNUSED) -{ -} - -/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */ - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption - (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow) -{ - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "unsupported socket option"); -} - -static jboolean flowSupported0() { - return JNI_FALSE; -} - -JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported - (JNIEnv *env, jclass UNUSED) -{ - return JNI_FALSE; +class SolarisSocketOptions extends PlatformSocketOptions { + + public SolarisSocketOptions() { } + + @Override native int setFlowOption(int fd, int priority, long bandwidth) + throws SocketException; + + @Override native int getFlowOption(int fd, SocketFlow f) + throws SocketException; + + @Override native boolean flowSupported(); + + private static native void init(); + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("extnet"); + return null; + } + }); + init(); + } } diff --git a/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c new file mode 100644 index 00000000000..96d6ed96088 --- /dev/null +++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c @@ -0,0 +1,176 @@ +/* + * 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. 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 "SolarisSocketOptions.h" + +static jfieldID sf_priority; +static jfieldID sf_bandwidth; + +static int initialized = 0; + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init + (JNIEnv *env, jclass unused) +{ + if (!initialized) { + jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow"); + CHECK_NULL(c); + sf_priority = (*env)->GetFieldID(env, c, "priority", "I"); + CHECK_NULL(sf_priority); + sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J"); + CHECK_NULL(sf_bandwidth); + initialized = 1; + } +} + +/** Return the Status value. */ +static jint toStatus(int errval) +{ + switch (errval) { + case 0: return jdk_net_SocketFlow_OK_VALUE; + case EPERM: return jdk_net_SocketFlow_NO_PERMISSION_VALUE; + case ENOTCONN: return jdk_net_SocketFlow_NOT_CONNECTED_VALUE; + case EOPNOTSUPP: return jdk_net_SocketFlow_NOT_SUPPORTED_VALUE; + case EALREADY: return jdk_net_SocketFlow_ALREADY_CREATED_VALUE; + case EINPROGRESS: return jdk_net_SocketFlow_IN_PROGRESS_VALUE; + default: return jdk_net_SocketFlow_OTHER_VALUE; + } +} + +void throwByNameWithLastError + (JNIEnv *env, const char *name, const char *defaultDetail) +{ + char defaultMsg[255]; + sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail); + JNU_ThrowByNameWithLastError(env, name, defaultMsg); +} + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: setFlowOption0 + * Signature: (IIJ)I + */ +JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption + (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth) +{ + int rv; + sock_flow_props_t props; + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + + if (priority != jdk_net_SocketFlow_UNSET) { + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = priority; + } + if (bandwidth > jdk_net_SocketFlow_UNSET) { + props.sfp_mask |= SFP_MAXBW; + props.sfp_maxbw = (uint64_t) bandwidth; + } + + rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else if (errno == EACCES || errno == EPERM) { + JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); + } else { + throwByNameWithLastError(env, "java/net/SocketException", + "set option SO_FLOW_SLA failed"); + } + return 0; + } + return toStatus(props.sfp_status); +} + +/* + * Class: jdk_net_SolarisSocketOptions + * Method: getFlowOption0 + * Signature: (ILjdk/net/SocketFlow;)I + */ +JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption + (JNIEnv *env, jobject unused, jint fd, jobject flow) +{ + sock_flow_props_t props; + socklen_t sz = sizeof(props); + + int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz); + + if (rv < 0) { + if (errno == ENOPROTOOPT) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "unsupported socket option"); + } else if (errno == EACCES || errno == EPERM) { + JNU_ThrowByName(env, "java/net/SocketException", "Permission denied"); + } else { + throwByNameWithLastError(env, "java/net/SocketException", + "get option SO_FLOW_SLA failed"); + } + return -1; + } + /* first check status to see if flow exists */ + if (props.sfp_status == 0) { /* OK */ + /* can set the other fields now */ + if (props.sfp_mask & SFP_PRIORITY) { + (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority); + } + if (props.sfp_mask & SFP_MAXBW) { + (*env)->SetLongField(env, flow, sf_bandwidth, + (jlong)props.sfp_maxbw); + } + } + return toStatus(props.sfp_status); +} + +JNIEXPORT jboolean JNICALL Java_jdk_net_SolarisSocketOptions_flowSupported + (JNIEnv *env, jobject unused) +{ + /* Do a simple dummy call, and try to figure out from that */ + sock_flow_props_t props; + int rv, s; + + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) { + return JNI_FALSE; + } + memset(&props, 0, sizeof(props)); + props.sfp_version = SOCK_FLOW_PROP_VERSION1; + props.sfp_mask |= SFP_PRIORITY; + props.sfp_priority = SFP_PRIO_NORMAL; + rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props)); + if (rv != 0 && errno == ENOPROTOOPT) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} diff --git a/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h new file mode 100644 index 00000000000..81c65544680 --- /dev/null +++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#ifndef SOLARIS_SOCKET_OPTIONS_H +#define SOLARIS_SOCKET_OPTIONS_H + +#include +#include +#include +#include +#include + +#include "jni_util.h" +#include "jdk_net_SocketFlow.h" +#include "SolarisSocketOptions.h" +#include "jdk_net_SolarisSocketOptions.h" + +#ifndef SO_FLOW_SLA +#define SO_FLOW_SLA 0x1018 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack(4) +#endif + +/* + * Used with the setsockopt(SO_FLOW_SLA, ...) call to set + * per socket service level properties. + * When the application uses per-socket API, we will enforce the properties + * on both outbound and inbound packets. + * + * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1. + */ +typedef struct sock_flow_props_s { + int sfp_version; + uint32_t sfp_mask; + int sfp_priority; /* flow priority */ + uint64_t sfp_maxbw; /* bandwidth limit in bps */ + int sfp_status; /* flow create status for getsockopt */ +} sock_flow_props_t; + +#define SOCK_FLOW_PROP_VERSION1 1 + +/* bit mask values for sfp_mask */ +#define SFP_MAXBW 0x00000001 /* Flow Bandwidth Limit */ +#define SFP_PRIORITY 0x00000008 /* Flow priority */ + +/* possible values for sfp_priority */ +#define SFP_PRIO_NORMAL 1 +#define SFP_PRIO_HIGH 2 + +#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4 +#pragma pack() +#endif /* _LONG_LONG_ALIGNMENT */ + +#endif /* SO_FLOW_SLA */ + +#endif /* SOLARIS_SOCKET_OPTIONS_H */ diff --git a/jdk/src/jdk.policytool/share/classes/module-info.java b/jdk/src/jdk.policytool/share/classes/module-info.java index aedfc91554a..f972e1cd15a 100644 --- a/jdk/src/jdk.policytool/share/classes/module-info.java +++ b/jdk/src/jdk.policytool/share/classes/module-info.java @@ -28,6 +28,7 @@ module jdk.policytool { requires java.logging; requires java.management; requires java.sql; + requires jdk.net; requires java.security.jgss; requires jdk.security.jgss; } diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 5b109d533ac..81f33f73b9f 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -23,11 +23,13 @@ /* * @test - * @bug 8036979 8072384 + * @bug 8036979 8072384 8044773 * @run main/othervm -Xcheck:jni OptionsTest * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest + * @run main/othervm -Djdk.launcher.limitmods=java.base OptionsTest */ +import java.lang.reflect.Method; import java.net.*; import java.util.*; @@ -43,7 +45,7 @@ public class OptionsTest { } Object option; Object testValue; - }; + } // The tests set the option using the new API, read back the set value // which could be diferent, and then use the legacy get API to check @@ -223,8 +225,7 @@ public class OptionsTest { } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { - return Integer.valueOf(jdk.net.Sockets.getOption( - socket, StandardSocketOptions.IP_TOS)); + return getServerSocketTrafficClass(socket); } else { throw new RuntimeException("unexecpted socket option"); } @@ -281,4 +282,20 @@ public class OptionsTest { doDgSocketTests(); doMcSocketTests(); } + + // Reflectively access jdk.net.Sockets.getOption so that the test can run + // without the jdk.net module. + static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception { + try { + Class c = Class.forName("jdk.net.Sockets"); + Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class); + return m.invoke(null, ss, StandardSocketOptions.IP_TOS); + } catch (ClassNotFoundException e) { + // Ok, jdk.net module not present, just fall back + System.out.println("jdk.net module not present, falling back."); + return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS)); + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } } diff --git a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java index 074f7644b9d..0ab43f6ff27 100644 --- a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java +++ b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java @@ -21,34 +21,48 @@ * questions. */ -import jdk.net.ExtendedSocketOptions; - import java.io.IOException; +import java.lang.reflect.Field; import java.net.*; +import java.util.ArrayList; +import java.util.List; /* * @test - * @bug 8143554 - * @run main UnsupportedOptionsTest + * @bug 8143554 8044773 * @summary Test checks that UnsupportedOperationException for unsupported * SOCKET_OPTIONS is thrown by both getOption() and setOption() methods. + * @run main UnsupportedOptionsTest + * @run main/othervm -Djdk.launcher.limitmods=java.base UnsupportedOptionsTest */ + public class UnsupportedOptionsTest { - private static final SocketOption[] SOCKET_OPTIONS = { - StandardSocketOptions.IP_MULTICAST_IF, - StandardSocketOptions.IP_MULTICAST_LOOP, - StandardSocketOptions.IP_MULTICAST_TTL, - StandardSocketOptions.IP_TOS, - StandardSocketOptions.SO_BROADCAST, - StandardSocketOptions.SO_KEEPALIVE, - StandardSocketOptions.SO_LINGER, - StandardSocketOptions.SO_RCVBUF, - StandardSocketOptions.SO_REUSEADDR, - StandardSocketOptions.SO_SNDBUF, - StandardSocketOptions.TCP_NODELAY, - ExtendedSocketOptions.SO_FLOW_SLA - }; + private static final List> socketOptions = new ArrayList<>(); + + static { + socketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); + socketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); + socketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); + socketOptions.add(StandardSocketOptions.IP_TOS); + socketOptions.add(StandardSocketOptions.SO_BROADCAST); + socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); + socketOptions.add(StandardSocketOptions.SO_LINGER); + socketOptions.add(StandardSocketOptions.SO_RCVBUF); + socketOptions.add(StandardSocketOptions.SO_REUSEADDR); + socketOptions.add(StandardSocketOptions.SO_SNDBUF); + socketOptions.add(StandardSocketOptions.TCP_NODELAY); + + try { + Class c = Class.forName("jdk.net.ExtendedSocketOptions"); + Field field = c.getField("SO_FLOW_SLA"); + socketOptions.add((SocketOption)field.get(null)); + } catch (ClassNotFoundException e) { + // ignore, jdk.net module not present + } catch (ReflectiveOperationException e) { + throw new AssertionError(e); + } + } public static void main(String[] args) throws IOException { Socket s = new Socket(); @@ -56,7 +70,7 @@ public class UnsupportedOptionsTest { DatagramSocket ds = new DatagramSocket(); MulticastSocket ms = new MulticastSocket(); - for (SocketOption option : SOCKET_OPTIONS) { + for (SocketOption option : socketOptions) { if (!s.supportedOptions().contains(option)) { testUnsupportedSocketOption(s, option); } diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index 40aef3282ac..00281647f17 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -22,8 +22,10 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test for setOption/getOption/options methods + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index 0a3aa9dee32..a0b2b6a8e82 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -22,9 +22,11 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test for ServerSocketChannel setOption/getOption/options * methods. + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java index f1cb496afea..74f87c71623 100644 --- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -22,9 +22,11 @@ */ /* @test - * @bug 4640544 + * @bug 4640544 8044773 * @summary Unit test to check SocketChannel setOption/getOption/options * methods. + * @run main SocketOptionTests + * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests */ import java.nio.*; diff --git a/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java new file mode 100644 index 00000000000..ca02ad931d6 --- /dev/null +++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.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. + * + * 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 8765432 + * @summary Basic test for SocketFlow API + * @run testng SocketFlowBasic + */ + +import jdk.net.SocketFlow; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static jdk.net.SocketFlow.*; +import static org.testng.Assert.*; + +public class SocketFlowBasic { + + @DataProvider + public Object[][] validPriorities() { + return new Object[][] { {HIGH_PRIORITY}, {NORMAL_PRIORITY} }; + } + + @Test(dataProvider = "validPriorities") + public void priority(long validPriority) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(validPriority); + long bandwidth = flow.bandwidth(); + assertTrue(bandwidth == validPriority, "Expected " + validPriority + ", got" + bandwidth); + } + + @DataProvider + public Object[][] invalidPriorities() { + return new Object[][] { {HIGH_PRIORITY+10}, {NORMAL_PRIORITY-10000} }; + } + + @Test(dataProvider = "invalidPriorities", expectedExceptions = IllegalArgumentException.class) + public void priority(int invalidPriority) { + SocketFlow flow = SocketFlow.create(); + flow.priority(invalidPriority); + } + + @DataProvider + public Object[][] positiveBandwidth() { + return new Object[][] { {0}, {100}, {Integer.MAX_VALUE}, {Long.MAX_VALUE} }; + } + + @Test(dataProvider = "positiveBandwidth") + public void bandwidth(long posBandwidth) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(posBandwidth); + long bandwidth = flow.bandwidth(); + assertTrue(bandwidth == posBandwidth, "Expected " + posBandwidth + ", got" + bandwidth); + } + + + @DataProvider + public Object[][] negativeBandwidth() { + return new Object[][] { {-1}, {-100}, {Integer.MIN_VALUE}, {Long.MIN_VALUE} }; + } + + @Test(dataProvider = "negativeBandwidth", expectedExceptions = IllegalArgumentException.class) + public void invalidBandwidth(long negBandwidth) { + SocketFlow flow = SocketFlow.create(); + flow.bandwidth(negBandwidth); + } + + @Test + public void status() { + SocketFlow flow = SocketFlow.create(); + assertTrue(flow.status() == Status.NO_STATUS); + } +} diff --git a/jdk/test/jdk/net/Sockets/Test.java b/jdk/test/jdk/net/Sockets/Test.java index bf3758c5bae..8bb03c54919 100644 --- a/jdk/test/jdk/net/Sockets/Test.java +++ b/jdk/test/jdk/net/Sockets/Test.java @@ -23,8 +23,9 @@ /* * @test - * @bug 8032808 - * @run main/othervm -Xcheck:jni Test + * @bug 8032808 8044773 + * @modules jdk.net + * @run main/othervm -Xcheck:jni Test success * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail * @run main/othervm/policy=policy.success -Xcheck:jni Test success */ @@ -35,15 +36,13 @@ import java.nio.channels.*; import java.util.concurrent.*; import java.util.Set; import jdk.net.*; +import static java.lang.System.out; public class Test { - static boolean security; - static boolean success; + interface Runner { void run() throws Exception; } - interface Runner { - public void run() throws Exception; - } + static boolean expectSuccess; public static void main(String[] args) throws Exception { @@ -52,95 +51,107 @@ public class Test { Sockets.supportedOptions(Socket.class); - security = System.getSecurityManager() != null; - success = security && args[0].equals("success"); + expectSuccess = args[0].equals("success"); // Main thing is to check for JNI problems // Doesn't matter if current system does not support the option // and currently setting the option with the loopback interface // doesn't work either - System.out.println ("Security Manager enabled: " + security); - if (security) { - System.out.println ("Success expected: " + success); + boolean sm = System.getSecurityManager() != null; + out.println("Security Manager enabled: " + sm); + out.println("Success expected: " + expectSuccess); + + SocketFlow flowIn = SocketFlow.create() + .bandwidth(1000) + .priority(SocketFlow.HIGH_PRIORITY); + + try (ServerSocket ss = new ServerSocket(0); + DatagramSocket dg = new DatagramSocket(0)) { + + int tcp_port = ss.getLocalPort(); + final InetAddress loop = InetAddress.getByName("127.0.0.1"); + final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port); + + final int udp_port = dg.getLocalPort(); + + // If option not available, end test + Set> options = dg.supportedOptions(); + if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { + System.out.println("SO_FLOW_SLA not supported"); + return; + } + + final Socket s = new Socket("127.0.0.1", tcp_port); + final SocketChannel sc = SocketChannel.open(); + sc.connect(new InetSocketAddress("127.0.0.1", tcp_port)); + + doTest("Sockets.setOption Socket", () -> { + out.println(flowIn); + Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + out.println(flowIn); + }); + doTest("Sockets.getOption Socket",() -> { + Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); + out.println(flowIn); + }); + doTest("Sockets.setOption SocketChannel",() -> + sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn) + ); + doTest("Sockets.getOption SocketChannel",() -> + sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA) + ); + doTest("Sockets.setOption DatagramSocket",() -> { + try (DatagramSocket dg1 = new DatagramSocket(0)) { + dg1.connect(loop, udp_port); + Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption DatagramSocket 2", () -> { + try (DatagramChannel dg2 = DatagramChannel.open()) { + dg2.bind(new InetSocketAddress(loop, 0)); + dg2.connect(new InetSocketAddress(loop, udp_port)); + dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption MulticastSocket", () -> { + try (MulticastSocket mc1 = new MulticastSocket(0)) { + mc1.connect(loop, udp_port); + Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); + doTest("Sockets.setOption AsynchronousSocketChannel", () -> { + try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) { + Future f = asc.connect(loopad); + f.get(); + asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); + } + }); } - - final SocketFlow flowIn = SocketFlow.create() - .bandwidth(1000) - .priority(SocketFlow.HIGH_PRIORITY); - - ServerSocket ss = new ServerSocket(0); - int tcp_port = ss.getLocalPort(); - final InetAddress loop = InetAddress.getByName("127.0.0.1"); - final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port); - - DatagramSocket dg = new DatagramSocket(0); - final int udp_port = dg.getLocalPort(); - - // If option not available, end test - Set> options = dg.supportedOptions(); - if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) { - System.out.println("SO_FLOW_SLA not supported"); - return; - } - - final Socket s = new Socket("127.0.0.1", tcp_port); - final SocketChannel sc = SocketChannel.open(); - sc.connect (new InetSocketAddress("127.0.0.1", tcp_port)); - - doTest(()->{ - Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA); - }); - doTest(()->{ - sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA); - }); - doTest(()->{ - DatagramSocket dg1 = new DatagramSocket(0); - dg1.connect(loop, udp_port); - Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - DatagramChannel dg2 = DatagramChannel.open(); - dg2.bind(new InetSocketAddress(loop, 0)); - dg2.connect(new InetSocketAddress(loop, udp_port)); - dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - MulticastSocket mc1 = new MulticastSocket(0); - mc1.connect(loop, udp_port); - Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); - doTest(()->{ - AsynchronousSocketChannel asc = AsynchronousSocketChannel.open(); - Future f = asc.connect(loopad); - f.get(); - asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn); - }); } - static void doTest(Runner func) throws Exception { + static void doTest(String message, Runner func) throws Exception { + out.println(message); try { func.run(); - if (security && !success) { - throw new RuntimeException("Test failed"); + if (expectSuccess) { + out.println("Completed as expected"); + } else { + throw new RuntimeException("Operation succeeded, but expected SecurityException"); } } catch (SecurityException e) { - if (success) { - throw new RuntimeException("Test failed"); + if (expectSuccess) { + throw new RuntimeException("Unexpected SecurityException", e); + } else { + out.println("Caught expected: " + e); } } catch (UnsupportedOperationException e) { - System.out.println (e); + System.out.println(e); } catch (IOException e) { // Probably a permission error, but we're not // going to check unless a specific permission exception // is defined. - System.out.println (e); + System.out.println(e); } } } From 2ef07f57fa9561cee6ed0155d52b5172650b1076 Mon Sep 17 00:00:00 2001 From: Alexander Kouznetsov Date: Wed, 27 Apr 2016 17:47:17 -0700 Subject: [PATCH 155/225] 8154381: SwingSet tests are not auto closed in jtreg Reviewed-by: alexsch --- .../nbproject/genfiles.properties | 2 +- .../nbproject/project.properties | 2 +- .../client_sanity/nbproject/project.xml | 2 +- .../src/ButtonDemoScreenshotTest.java | 24 ++-- .../client/SwingSet/src/ButtonDemoTest.java | 44 ++++---- .../client/SwingSet/src/ComboBoxDemoTest.java | 19 ++-- .../client/SwingSet/src/ListDemoTest.java | 83 +++++++------- .../SwingSet/src/OptionPaneDemoTest.java | 31 +++--- .../SwingSet/src/ProgressBarDemoTest.java | 27 ++--- .../SwingSet/src/ScrollPaneDemoTest.java | 105 +++++++++--------- .../client/SwingSet/src/SpinnerDemoTest.java | 20 ++-- .../SwingSet/src/SplitPaneDemoTest.java | 38 ++++--- .../SwingSet/src/TabbedPaneDemoTest.java | 18 +-- .../SwingSet/src/TextFieldDemoTest.java | 18 +-- .../SwingSet/src/ToggleButtonDemoTest.java | 58 +++++----- .../client/SwingSet/src/TreeDemoTest.java | 81 +++++++------- .../client/SwingSet/src/WindowDemoTest.java | 32 +++--- .../src/org/jemmy2ext/JemmyExt.java | 23 ++-- .../src/org/jtregext/GuiTestListener.java | 72 ++++++++++++ .../demos/tabbedpane/TabbedPaneDemo.java | 6 +- 20 files changed, 395 insertions(+), 310 deletions(-) rename jdk/test/sanity/client/lib/{Jemmy2Ext => Extensions}/src/org/jemmy2ext/JemmyExt.java (97%) create mode 100644 jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java diff --git a/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties b/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties index fc956fd5f2e..48d69459d3f 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties +++ b/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties @@ -3,6 +3,6 @@ build.xml.script.CRC32=f902e8b8 build.xml.stylesheet.CRC32=8064a381@1.75.2.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=55414227 +nbproject/build-impl.xml.data.CRC32=16caf60f nbproject/build-impl.xml.script.CRC32=c12f9d04 nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48 diff --git a/jdk/make/netbeans/client_sanity/nbproject/project.properties b/jdk/make/netbeans/client_sanity/nbproject/project.properties index a43ee024fd8..f3e9384ce3f 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/project.properties +++ b/jdk/make/netbeans/client_sanity/nbproject/project.properties @@ -76,4 +76,4 @@ source.encoding=UTF-8 src.src.dir=..\\..\\..\\test\\sanity\\client\\SwingSet\\src src.src2.dir=..\\..\\..\\test\\sanity\\client\\lib\\SwingSet3\\src src.src3.dir=..\\..\\..\\test\\sanity\\client\\lib\\jemmy\\src -src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Jemmy2Ext\\src +src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Extensions\\src diff --git a/jdk/make/netbeans/client_sanity/nbproject/project.xml b/jdk/make/netbeans/client_sanity/nbproject/project.xml index fccac4ecf31..554dc3073d5 100644 --- a/jdk/make/netbeans/client_sanity/nbproject/project.xml +++ b/jdk/make/netbeans/client_sanity/nbproject/project.xml @@ -6,7 +6,7 @@ SanityTests - + diff --git a/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java b/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java index b6959ac150a..61022339fc2 100644 --- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java @@ -21,6 +21,8 @@ * questions. */ +import com.sun.swingset3.demos.button.ButtonDemo; +import org.jtregext.GuiTestListener; import java.awt.Point; import java.awt.Robot; import java.awt.event.InputEvent; @@ -32,6 +34,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import static org.jemmy2ext.JemmyExt.*; import org.testng.annotations.Test; import static com.sun.swingset3.demos.button.ButtonDemo.*; +import org.testng.annotations.Listeners; /* * @test @@ -41,31 +44,30 @@ import static com.sun.swingset3.demos.button.ButtonDemo.*; * image is different from initial button image. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.button.ButtonDemo * @run testng ButtonDemoScreenshotTest */ +@Listeners(GuiTestListener.class) public class ButtonDemoScreenshotTest { private static final int BUTTON_COUNT = 6; // TODO: Decide about "open browser" buttons (value was 8 originally) @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - Robot rob = new Robot(); + Robot rob = new Robot(); - new ClassReference(com.sun.swingset3.demos.button.ButtonDemo.class.getCanonicalName()).startApplication(); + new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - waitImageIsStill(rob, mainFrame); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + waitImageIsStill(rob, mainFrame); - // Check all the buttons - for (int i = 0; i < BUTTON_COUNT; i++) { - checkButton(mainFrame, i, rob); - } - }); + // Check all the buttons + for (int i = 0; i < BUTTON_COUNT; i++) { + checkButton(mainFrame, i, rob); + } } public void checkButton(JFrameOperator jfo, int i, Robot rob) { diff --git a/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java index 3d0d8f1afea..da540dbb648 100644 --- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.JHyperlink; import com.sun.swingset3.demos.button.ButtonDemo; import java.util.concurrent.ArrayBlockingQueue; @@ -38,7 +39,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import static com.sun.swingset3.demos.button.ButtonDemo.*; import org.jemmy2ext.JemmyExt; import org.jemmy2ext.JemmyExt.MultiThreadedTryCatch; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -48,12 +49,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * on buttons before and after click. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.button.ButtonDemo * @run testng ButtonDemoTest */ +@Listeners(GuiTestListener.class) public class ButtonDemoTest { private static final String[] BUTTON_TEXT_AFTER = { @@ -92,34 +94,30 @@ public class ButtonDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { + new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); - new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication(); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + mainFrame.setComparator(EXACT_STRING_COMPARATOR); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - mainFrame.setComparator(EXACT_STRING_COMPARATOR); + // Check all the buttons + for (int i = 0; i < BUTTON_TOOLTIP.length; i++) { + String tooltip = BUTTON_TOOLTIP[i]; - // Check all the buttons - for (int i = 0; i < BUTTON_TOOLTIP.length; i++) { - String tooltip = BUTTON_TOOLTIP[i]; + JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip)); - JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip)); + assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - - // Two buttons are hyperlinks, we don't want to click them - if (!button.getSource().getClass().equals(JHyperlink.class)) { - checkButton(button); - } - - if (BUTTON_TEXT_AFTER.length > i) { - assertEquals(BUTTON_TEXT_AFTER[i], button.getText()); - } else { - assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); - } + // Two buttons are hyperlinks, we don't want to click them + if (!button.getSource().getClass().equals(JHyperlink.class)) { + checkButton(button); } - }); + if (BUTTON_TEXT_AFTER.length > i) { + assertEquals(BUTTON_TEXT_AFTER[i], button.getText()); + } else { + assertEquals(BUTTON_TEXT_BEFORE[i], button.getText()); + } + } } private void checkButton(JButtonOperator button) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java index 303bbd681f1..790bc9d3711 100644 --- a/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.combobox.ComboBoxDemo; import static org.testng.AssertJUnit.*; import org.testng.annotations.Test; @@ -28,7 +29,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JComboBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import static com.sun.swingset3.demos.combobox.ComboBoxDemo.*; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -37,12 +38,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * each value of each ComboBox. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.combobox.ComboBoxDemo * @run testng ComboBoxDemoTest */ +@Listeners(GuiTestListener.class) public class ComboBoxDemoTest { private static enum ComboBoxInfo { @@ -61,14 +63,13 @@ public class ComboBoxDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) { - comboBoxChecker(frame, comboBoxInfo); - } - }); + new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication(); + + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) { + comboBoxChecker(frame, comboBoxInfo); + } } private void comboBoxChecker(JFrameOperator jfo, ComboBoxInfo comboBoxInfo) { diff --git a/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java index c24399e526b..c977385b9bb 100644 --- a/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.list.ListDemo; import static com.sun.swingset3.demos.list.ListDemo.DEMO_TITLE; import static org.testng.AssertJUnit.*; @@ -30,7 +31,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JCheckBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JListOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,64 +41,64 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * list. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.list.ListDemo * @run testng ListDemoTest */ +@Listeners(GuiTestListener.class) public class ListDemoTest { private static final int CHECKBOX_COUNT = 50; @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ListDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - JListOperator listOp = new JListOperator(frame); + new ClassReference(ListDemo.class.getCanonicalName()).startApplication(); - // Check *NO* Prefix and Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JListOperator listOp = new JListOperator(frame); + + // Check *NO* Prefix and Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + checkBox.changeSelection(false); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize()); + + // Check *ALL* Prefix and Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + checkBox.changeSelection(true); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize()); + + // Check *ALL* Prefix and *NO* Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + if (i < CHECKBOX_COUNT / 2) { + checkBox.changeSelection(true); + } else { checkBox.changeSelection(false); } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize()); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize()); - // Check *ALL* Prefix and Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + // Check *NO* Prefix and *ALL* Suffixes Marked + for (int i = 0; i < CHECKBOX_COUNT; i++) { + JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); + if (i < CHECKBOX_COUNT / 2) { + checkBox.changeSelection(false); + } else { checkBox.changeSelection(true); } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize()); - - // Check *ALL* Prefix and *NO* Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); - if (i < CHECKBOX_COUNT / 2) { - checkBox.changeSelection(true); - } else { - checkBox.changeSelection(false); - } - } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize()); - - // Check *NO* Prefix and *ALL* Suffixes Marked - for (int i = 0; i < CHECKBOX_COUNT; i++) { - JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i); - if (i < CHECKBOX_COUNT / 2) { - checkBox.changeSelection(false); - } else { - checkBox.changeSelection(true); - } - } - System.out.println("######## Number of Items = " + listOp.getModel().getSize()); - assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize()); - }); + } + System.out.println("######## Number of Items = " + listOp.getModel().getSize()); + assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize()); } private JCheckBoxOperator getJCheckBoxOperator(JFrameOperator frame, int index) { diff --git a/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java index 2cecfe72637..9ac377f7d2a 100644 --- a/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java @@ -21,10 +21,10 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.optionpane.OptionPaneDemo; import static com.sun.swingset3.demos.optionpane.OptionPaneDemo.*; import javax.swing.UIManager; -import static org.jemmy2ext.JemmyExt.*; import static org.testng.AssertJUnit.*; import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; @@ -34,6 +34,7 @@ import org.netbeans.jemmy.operators.JDialogOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; +import org.testng.annotations.Listeners; /* @@ -43,12 +44,13 @@ import org.netbeans.jemmy.operators.JTextFieldOperator; * and choosing different options in them. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.optionpane.OptionPaneDemo * @run testng OptionPaneDemoTest */ +@Listeners(GuiTestListener.class) public class OptionPaneDemoTest { public static final String SOME_TEXT_TO_TYPE = "I am some text"; @@ -59,21 +61,20 @@ public class OptionPaneDemoTest { public static final String TEXT_TO_TYPE = "Hooray! I'm a textField"; public static final String NO = "No"; public static final String YES = "Yes"; - public static final String SELECT_AN__OPTION = UIManager.getString("OptionPane.titleText"); + public static final String SELECT_AN_OPTION = UIManager.getString("OptionPane.titleText"); @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication(); - showInputDialog(frame); - showWarningDialog(frame); - showMessageDialog(frame); - showComponentDialog(frame); - showConfirmationDialog(frame); - }); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + + showInputDialog(frame); + showWarningDialog(frame); + showMessageDialog(frame); + showComponentDialog(frame); + showConfirmationDialog(frame); } public void showInputDialog(JFrameOperator jfo) throws Exception { @@ -286,7 +287,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); new JButtonOperator(jdo, YES).pushNoBlock(); JDialogOperator jdo1 = new JDialogOperator(MESSAGE); @@ -306,7 +307,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); new JButtonOperator(jdo, NO).pushNoBlock(); JDialogOperator jdo1 = new JDialogOperator(MESSAGE); @@ -326,7 +327,7 @@ public class OptionPaneDemoTest { { new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock(); - JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION); + JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION); assertTrue("Show Confirmation Dialog Cancel Option", jdo.isShowing()); diff --git a/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java index 411d05cd1b7..b705974274f 100644 --- a/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.progressbar.ProgressBarDemo; import static com.sun.swingset3.demos.progressbar.ProgressBarDemo.*; import java.awt.Component; @@ -31,7 +32,7 @@ import org.netbeans.jemmy.ComponentChooser; import org.netbeans.jemmy.operators.JButtonOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JProgressBarOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,31 +41,31 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * buttons and checking the progress bar and the buttons state. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.progressbar.ProgressBarDemo * @run testng ProgressBarDemoTest */ +@Listeners(GuiTestListener.class) public class ProgressBarDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication(); - JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON); - JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON); - JProgressBarOperator jpbo = new JProgressBarOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Check that progress completes and corect enable/disable of start/stop buttons - checkCompleteProgress(frame, startButton, stopButton, jpbo); + JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON); + JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON); + JProgressBarOperator jpbo = new JProgressBarOperator(frame); - // Check progess bar progression and start/stop button disabled/enabled states - checkStartStop(frame, startButton, stopButton, jpbo); - }); + // Check that progress completes and corect enable/disable of start/stop buttons + checkCompleteProgress(frame, startButton, stopButton, jpbo); + + // Check progess bar progression and start/stop button disabled/enabled states + checkStartStop(frame, startButton, stopButton, jpbo); } // Check that progress completes and corect enable/disable of start/stop buttons diff --git a/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java index bd88904f875..2023eff16a3 100644 --- a/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.scrollpane.ScrollPaneDemo; import static com.sun.swingset3.demos.scrollpane.ScrollPaneDemo.DEMO_TITLE; import static org.testng.AssertJUnit.*; @@ -28,7 +29,7 @@ import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JScrollPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -37,73 +38,73 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * to left and to right and checking scroll bar values. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.scrollpane.ScrollPaneDemo * @run testng ScrollPaneDemoTest */ +@Listeners(GuiTestListener.class) public class ScrollPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ScrollPaneDemo.class.getName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - JScrollPaneOperator jspo = new JScrollPaneOperator(frame); + new ClassReference(ScrollPaneDemo.class.getName()).startApplication(); - // Set initial scrollbar positions - int initialVerticalValue = jspo.getVerticalScrollBar().getValue(); - int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue(); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JScrollPaneOperator jspo = new JScrollPaneOperator(frame); - System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue()); - System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue()); + // Set initial scrollbar positions + int initialVerticalValue = jspo.getVerticalScrollBar().getValue(); + int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue(); - // Check scroll to Bottom - { - jspo.scrollToBottom(); - int currentValue = jspo.getVerticalScrollBar().getValue(); - System.out.println("Final Value = " + currentValue); - assertTrue("Scroll to Bottom of Pane " - + "(initialVerticalValue, actual value: " + initialVerticalValue + " " - + "< currentValue, actual value = " + currentValue + ")", - initialVerticalValue < currentValue); - } + System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue()); + System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue()); - // Check scroll to Top - { - jspo.scrollToTop(); - int currentValue = jspo.getVerticalScrollBar().getValue(); - System.out.println("Top Scroll Final Value = " + currentValue); - assertTrue("Scroll to Top of Pane " - + "(initialVerticalValue, actual value: " + initialVerticalValue + " " - + "> currentValue, actual value = " + currentValue + ")", - initialVerticalValue > currentValue); - } + // Check scroll to Bottom + { + jspo.scrollToBottom(); + int currentValue = jspo.getVerticalScrollBar().getValue(); + System.out.println("Final Value = " + currentValue); + assertTrue("Scroll to Bottom of Pane " + + "(initialVerticalValue, actual value: " + initialVerticalValue + " " + + "< currentValue, actual value = " + currentValue + ")", + initialVerticalValue < currentValue); + } - // Check scroll to Left - { - jspo.scrollToLeft(); - int currentValue = jspo.getHorizontalScrollBar().getValue(); - System.out.println("Scroll to Left Final Value = " + currentValue); - assertTrue("Scroll to Left of Pane " - + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " - + "> currentValue, actual value = " + currentValue + ")", - initialHorizontalValue > currentValue); - } + // Check scroll to Top + { + jspo.scrollToTop(); + int currentValue = jspo.getVerticalScrollBar().getValue(); + System.out.println("Top Scroll Final Value = " + currentValue); + assertTrue("Scroll to Top of Pane " + + "(initialVerticalValue, actual value: " + initialVerticalValue + " " + + "> currentValue, actual value = " + currentValue + ")", + initialVerticalValue > currentValue); + } - // Check scroll to Right - { - jspo.scrollToRight(); - int currentValue = jspo.getHorizontalScrollBar().getValue(); - System.out.println("Scroll to Right Final Value = " + currentValue); - assertTrue("Scroll to Right of Pane " - + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " - + "< currentValue, actual value = " + currentValue + ")", - initialHorizontalValue < currentValue); - } - }); + // Check scroll to Left + { + jspo.scrollToLeft(); + int currentValue = jspo.getHorizontalScrollBar().getValue(); + System.out.println("Scroll to Left Final Value = " + currentValue); + assertTrue("Scroll to Left of Pane " + + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " + + "> currentValue, actual value = " + currentValue + ")", + initialHorizontalValue > currentValue); + } + + // Check scroll to Right + { + jspo.scrollToRight(); + int currentValue = jspo.getHorizontalScrollBar().getValue(); + System.out.println("Scroll to Right Final Value = " + currentValue); + assertTrue("Scroll to Right of Pane " + + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " " + + "< currentValue, actual value = " + currentValue + ")", + initialHorizontalValue < currentValue); + } } } diff --git a/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java b/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java index 89585adb6ad..1b44efa73af 100644 --- a/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.spinner.SpinnerDemo; import static com.sun.swingset3.demos.spinner.SpinnerDemo.DEMO_TITLE; import java.text.DecimalFormat; @@ -30,7 +31,7 @@ import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JSpinnerOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -39,12 +40,13 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * the spinner button and checking text field value. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.spinner.SpinnerDemo * @run testng SpinnerDemoTest */ +@Listeners(GuiTestListener.class) public class SpinnerDemoTest { private static final int SPINNERS_COUNT = 9; @@ -52,16 +54,14 @@ public class SpinnerDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication(); + new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Check changing different spinners - for (int i = 0; i < SPINNERS_COUNT; i++) { - changeValues(frame, i); - } - }); + // Check changing different spinners + for (int i = 0; i < SPINNERS_COUNT; i++) { + changeValues(frame, i); + } } private void changeValues(JFrameOperator jfo, int spinnerIndex) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java index 2a242cc3f16..9993d100316 100644 --- a/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.splitpane.SplitPaneDemo; import static com.sun.swingset3.demos.splitpane.SplitPaneDemo.*; import java.awt.event.KeyEvent; @@ -35,6 +36,7 @@ import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JSplitPaneOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; import static org.jemmy2ext.JemmyExt.*; +import org.testng.annotations.Listeners; /* * @test @@ -44,39 +46,39 @@ import static org.jemmy2ext.JemmyExt.*; * and changing the divider orientation. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.splitpane.SplitPaneDemo * @run testng SplitPaneDemoTest */ +@Listeners(GuiTestListener.class) public class SplitPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication(); - JSplitPaneOperator splitPane = new JSplitPaneOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - // Toggle OneTouch Expandable - checkOneTouch(frame, splitPane, true); - checkOneTouch(frame, splitPane, false); + JSplitPaneOperator splitPane = new JSplitPaneOperator(frame); - // Check changing divider size to minimum and maximum values - changeDividerSize(frame, splitPane, 50); - changeDividerSize(frame, splitPane, 6); + // Toggle OneTouch Expandable + checkOneTouch(frame, splitPane, true); + checkOneTouch(frame, splitPane, false); - // Check moving the divider - checkDividerMoves(frame, splitPane, false); - checkDividerMoves(frame, splitPane, true); + // Check changing divider size to minimum and maximum values + changeDividerSize(frame, splitPane, 50); + changeDividerSize(frame, splitPane, 6); - // Check different minumum Day/Night sizes - changeMinimumSizes(frame, splitPane, 100); - changeMinimumSizes(frame, splitPane, 0); - }); + // Check moving the divider + checkDividerMoves(frame, splitPane, false); + checkDividerMoves(frame, splitPane, true); + + // Check different minumum Day/Night sizes + changeMinimumSizes(frame, splitPane, 100); + changeMinimumSizes(frame, splitPane, 0); } // Check for different day and night minimum size diff --git a/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java index d3d8d28245f..9b2e16b7776 100644 --- a/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo; import static com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo.*; import static org.jemmy2ext.JemmyExt.getLabeledContainerOperator; @@ -31,7 +32,7 @@ import org.netbeans.jemmy.operators.ContainerOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JTabbedPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -40,25 +41,24 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * positions, opening each tab and verifying the the tab gets selected. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo * @run testng TabbedPaneDemoTest */ +@Listeners(GuiTestListener.class) public class TabbedPaneDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication(); + new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); + JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE); - for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) { - testTabs(mainFrame, tp); - } - }); + for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) { + testTabs(mainFrame, tp); + } } public void testTabs(JFrameOperator mainFrame, String tabPlacement) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java index 4d38ce38a38..b46abaaf691 100644 --- a/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.textfield.JHistoryTextField; import com.sun.swingset3.demos.textfield.TextFieldDemo; import static com.sun.swingset3.demos.textfield.TextFieldDemo.*; @@ -41,6 +42,7 @@ import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.JPasswordFieldOperator; import org.netbeans.jemmy.operators.JTextFieldOperator; +import org.testng.annotations.Listeners; /* * @test @@ -49,25 +51,25 @@ import org.netbeans.jemmy.operators.JTextFieldOperator; * checking that app reacts accordingly. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.textfield.TextFieldDemo * @run testng TextFieldDemoTest */ +@Listeners(GuiTestListener.class) public class TextFieldDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication(); - historyTextField(frame); - dateTextField(frame); - passwordField(frame); - }); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + + historyTextField(frame); + dateTextField(frame); + passwordField(frame); } private void historyTextField(JFrameOperator jfo) throws Exception { diff --git a/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java b/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java index c240540739e..2f1b6f01a9f 100644 --- a/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.DemoProperties; import com.sun.swingset3.demos.togglebutton.DirectionPanel; import com.sun.swingset3.demos.togglebutton.LayoutControlPanel; @@ -40,7 +41,7 @@ import org.netbeans.jemmy.operators.JCheckBoxOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JRadioButtonOperator; import org.netbeans.jemmy.operators.JTabbedPaneOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -53,50 +54,49 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * selected. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.togglebutton.ToggleButtonDemo * @run testng ToggleButtonDemoTest */ +@Listeners(GuiTestListener.class) public class ToggleButtonDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication(); + new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication(); - JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); - JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame); + JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); + JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame); - // Radio Button Toggles - testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null); - testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null); - testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t)); + // Radio Button Toggles + testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null); + testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null); + testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t)); - // switch to the Check Boxes Tab - tabPane.selectPage(CHECK_BOXES); + // switch to the Check Boxes Tab + tabPane.selectPage(CHECK_BOXES); - // Check Box Toggles - ContainerOperator textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES); - testCheckBox(textCheckBoxesJPanel, CHECK1, false); - testCheckBox(textCheckBoxesJPanel, CHECK2, false); - testCheckBox(textCheckBoxesJPanel, CHECK3, false); + // Check Box Toggles + ContainerOperator textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES); + testCheckBox(textCheckBoxesJPanel, CHECK1, false); + testCheckBox(textCheckBoxesJPanel, CHECK2, false); + testCheckBox(textCheckBoxesJPanel, CHECK3, false); - ContainerOperator imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES); - testCheckBox(imageCheckBoxesJPanel, CHECK1, false); - testCheckBox(imageCheckBoxesJPanel, CHECK2, false); - testCheckBox(imageCheckBoxesJPanel, CHECK3, false); + ContainerOperator imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES); + testCheckBox(imageCheckBoxesJPanel, CHECK1, false); + testCheckBox(imageCheckBoxesJPanel, CHECK2, false); + testCheckBox(imageCheckBoxesJPanel, CHECK3, false); - ContainerOperator displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS); - testCheckBox(displayOptionsContainer, PAINT_BORDER, false); - testCheckBox(displayOptionsContainer, PAINT_FOCUS, true); - testCheckBox(displayOptionsContainer, ENABLED, true); - testCheckBox(displayOptionsContainer, CONTENT_FILLED, true); + ContainerOperator displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS); + testCheckBox(displayOptionsContainer, PAINT_BORDER, false); + testCheckBox(displayOptionsContainer, PAINT_FOCUS, true); + testCheckBox(displayOptionsContainer, ENABLED, true); + testCheckBox(displayOptionsContainer, CONTENT_FILLED, true); - // Direction Button Toggles - testToggleButtons(mainFrame); - }); + // Direction Button Toggles + testToggleButtons(mainFrame); } /** diff --git a/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java b/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java index b558d6fb96c..31166c12918 100644 --- a/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.tree.TreeDemo; import static com.sun.swingset3.demos.tree.TreeDemo.DEMO_TITLE; import javax.swing.tree.TreePath; @@ -29,7 +30,7 @@ import org.testng.annotations.Test; import org.netbeans.jemmy.ClassReference; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JTreeOperator; -import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; +import org.testng.annotations.Listeners; /* * @test @@ -42,67 +43,67 @@ import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail; * vertically (as ScrollPane allows it). * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.tree.TreeDemo * @run testng TreeDemoTest */ +@Listeners(GuiTestListener.class) public class TreeDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(TreeDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(DEMO_TITLE); + new ClassReference(TreeDemo.class.getCanonicalName()).startApplication(); - JTreeOperator tree = new JTreeOperator(frame); + JFrameOperator frame = new JFrameOperator(DEMO_TITLE); - assertEquals("Initial number of rows in the tree", 4, tree.getRowCount()); + JTreeOperator tree = new JTreeOperator(frame); - int initialTreeHeight = tree.getHeight(); + assertEquals("Initial number of rows in the tree", 4, tree.getRowCount()); - // expand all nodes - int expandsCount = 0; - for (int i = 0; i < tree.getRowCount(); i++) { - TreePath tp = tree.getPathForRow(i); - if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) { - tree.expandRow(i); - expandsCount++; - } + int initialTreeHeight = tree.getHeight(); + + // expand all nodes + int expandsCount = 0; + for (int i = 0; i < tree.getRowCount(); i++) { + TreePath tp = tree.getPathForRow(i); + if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) { + tree.expandRow(i); + expandsCount++; } + } - assertEquals("Number of rows expanded", 75, expandsCount); - assertEquals("Number of rows in the tree after expanding all of them", - 616, tree.getRowCount()); + assertEquals("Number of rows expanded", 75, expandsCount); + assertEquals("Number of rows in the tree after expanding all of them", + 616, tree.getRowCount()); - int expandedTreeHeight = tree.getHeight(); - assertTrue("Expanded tree height has increased, current " - + expandedTreeHeight + " > initial " + initialTreeHeight, - expandedTreeHeight > initialTreeHeight); + int expandedTreeHeight = tree.getHeight(); + assertTrue("Expanded tree height has increased, current " + + expandedTreeHeight + " > initial " + initialTreeHeight, + expandedTreeHeight > initialTreeHeight); - // collapse all nodes - int collapsesCount = 0; - for (int i = tree.getRowCount() - 1; i >= 0; i--) { - TreePath tp = tree.getPathForRow(i); - if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) { - tree.collapseRow(i); - collapsesCount++; - } + // collapse all nodes + int collapsesCount = 0; + for (int i = tree.getRowCount() - 1; i >= 0; i--) { + TreePath tp = tree.getPathForRow(i); + if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) { + tree.collapseRow(i); + collapsesCount++; } + } - assertEquals("Number of rows collapsed", 76, collapsesCount); - assertEquals("Number of rows in the tree after collapsing all of them", - 1, tree.getRowCount()); + assertEquals("Number of rows collapsed", 76, collapsesCount); + assertEquals("Number of rows in the tree after collapsing all of them", + 1, tree.getRowCount()); - int collapsedTreeHeight = tree.getHeight(); - assertTrue("Collpased tree height is not longer than initial, " - + "current " + collapsedTreeHeight + " <= initial " - + initialTreeHeight, - collapsedTreeHeight <= initialTreeHeight); + int collapsedTreeHeight = tree.getHeight(); + assertTrue("Collpased tree height is not longer than initial, " + + "current " + collapsedTreeHeight + " <= initial " + + initialTreeHeight, + collapsedTreeHeight <= initialTreeHeight); - }); } } diff --git a/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java b/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java index ef0fb850360..57b3ead00a3 100644 --- a/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java +++ b/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java @@ -21,6 +21,7 @@ * questions. */ +import org.jtregext.GuiTestListener; import com.sun.swingset3.demos.window.WindowDemo; import static com.sun.swingset3.demos.window.WindowDemo.*; import static org.jemmy2ext.JemmyExt.*; @@ -31,6 +32,7 @@ import org.netbeans.jemmy.operators.JButtonOperator; import org.netbeans.jemmy.operators.JFrameOperator; import org.netbeans.jemmy.operators.JLabelOperator; import org.netbeans.jemmy.operators.WindowOperator; +import org.testng.annotations.Listeners; /* * @test @@ -40,37 +42,37 @@ import org.netbeans.jemmy.operators.WindowOperator; * when the "Show JWindow..." button is clicked. * * @library /sanity/client/lib/jemmy/src - * @library /sanity/client/lib/Jemmy2Ext/src + * @library /sanity/client/lib/Extensions/src * @library /sanity/client/lib/SwingSet3/src * @build org.jemmy2ext.JemmyExt * @build com.sun.swingset3.demos.window.WindowDemo * @run testng WindowDemoTest */ +@Listeners(GuiTestListener.class) public class WindowDemoTest { @Test public void test() throws Exception { - captureDebugInfoOnFail(() -> { - new ClassReference(WindowDemo.class.getCanonicalName()).startApplication(); - JFrameOperator frame = new JFrameOperator(); + new ClassReference(WindowDemo.class.getCanonicalName()).startApplication(); - assertEquals("Only one JWindow is shown", 1, getJWindowCount()); + JFrameOperator frame = new JFrameOperator(); - WindowOperator window = new WindowOperator(getJWindow()); + assertEquals("Only one JWindow is shown", 1, getJWindowCount()); - assertTrue("JFrame is showing", frame.isShowing()); - assertFalse("JFrame is not iconified", isIconified(frame)); - assertTrue("JWindow is showing", window.isShowing()); + WindowOperator window = new WindowOperator(getJWindow()); - final String labelText = I_HAVE_NO_SYSTEM_BORDER; - JLabelOperator jLabelOperator = new JLabelOperator(window, labelText); - assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText()); + assertTrue("JFrame is showing", frame.isShowing()); + assertFalse("JFrame is not iconified", isIconified(frame)); + assertTrue("JWindow is showing", window.isShowing()); - new JButtonOperator(frame, SHOW_J_WINDOW).push(); + final String labelText = I_HAVE_NO_SYSTEM_BORDER; + JLabelOperator jLabelOperator = new JLabelOperator(window, labelText); + assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText()); - assertEquals("Only one JWindow is shown", 1, getJWindowCount()); - }); + new JButtonOperator(frame, SHOW_J_WINDOW).push(); + + assertEquals("Only one JWindow is shown", 1, getJWindowCount()); } } diff --git a/jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java b/jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java similarity index 97% rename from jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java rename to jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java index fe0431b684e..f2d344f4c3f 100644 --- a/jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java +++ b/jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java @@ -258,20 +258,19 @@ public class JemmyExt { } /** - * Wraps the test code so that in case of any failure as much information as - * possible is captured - * - * @param r test code Runnable - * @throws Exception whatever exception the test may throw + * Dispose all AWT/Swing windows causing event thread to stop */ - public static void captureDebugInfoOnFail(RunnableWithException r) throws Exception { - // TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed + public static void disposeAllWindows() { + System.out.println("disposeAllWindows"); try { - r.run(); - System.out.println("TEST PASSED"); - } catch (Throwable t) { - captureAll(); - throw t; + EventQueue.invokeAndWait(() -> { + Window[] windows = Window.getWindows(); + for (Window w : windows) { + w.dispose(); + } + }); + } catch (InterruptedException | InvocationTargetException ex) { + Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, "Failed to dispose all windows", ex); } } diff --git a/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java b/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java new file mode 100644 index 00000000000..407fd52d292 --- /dev/null +++ b/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java @@ -0,0 +1,72 @@ +package org.jtregext; + +/* + * 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 org.jemmy2ext.JemmyExt; +import static org.jemmy2ext.JemmyExt.captureAll; +import org.testng.ITestContext; +import org.testng.ITestListener; +import org.testng.ITestResult; + +// TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed +public class GuiTestListener implements ITestListener { + + private void afterTest() { + JemmyExt.disposeAllWindows(); + } + + @Override + public void onTestStart(ITestResult result) { + } + + @Override + public void onTestSuccess(ITestResult result) { + System.out.println("TEST PASSED"); + afterTest(); + } + + @Override + public void onTestFailure(ITestResult result) { + captureAll(); + afterTest(); + } + + @Override + public void onTestSkipped(ITestResult result) { + } + + @Override + public void onTestFailedButWithinSuccessPercentage(ITestResult result) { + } + + @Override + public void onStart(ITestContext context) { + } + + @Override + public void onFinish(ITestContext context) { + } + +} diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java index 5d023405b58..84336d822c2 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java @@ -204,7 +204,9 @@ public class TabbedPaneDemo extends JPanel implements ActionListener { } public void go() { - animator = new javax.swing.Timer(22 + 22 + 22, this); + if (animator == null) { + animator = new javax.swing.Timer(22 + 22 + 22, this); + } animator.start(); } @@ -246,7 +248,7 @@ public class TabbedPaneDemo extends JPanel implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - if (isVisible()) { + if (isShowing()) { repaint(); } else { animator.stop(); From 83f65483e4e23571c1fe35d64f8b0227ee05a170 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 27 Apr 2016 18:13:19 -0700 Subject: [PATCH 156/225] 8150382: JShell API: Allow setting remote JVM arguments 8151754: jshell tool: add command line options for setting feedback mode Reviewed-by: jlahoda --- .../internal/jshell/tool/ArgTokenizer.java | 8 ++- .../jdk/internal/jshell/tool/Feedback.java | 32 +++++------ .../jdk/internal/jshell/tool/JShellTool.java | 57 +++++++++++++++++-- .../jshell/tool/resources/l10n.properties | 25 +++++--- .../classes/jdk/jshell/ExecutionControl.java | 14 +++-- .../share/classes/jdk/jshell/JShell.java | 22 ++++++- .../test/jdk/jshell/StartOptionTest.java | 31 ++++++++-- langtools/test/jdk/jshell/ToolSimpleTest.java | 37 +++++++++++- 8 files changed, 185 insertions(+), 41 deletions(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java index 2e86d9de290..a7105cf1dc8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java @@ -35,6 +35,7 @@ import java.util.stream.Stream; class ArgTokenizer { private final String str; + private final String prefix; private final int length; private int next = 0; private char buf[] = new char[20]; @@ -49,7 +50,12 @@ class ArgTokenizer { private boolean isQuoted = false; ArgTokenizer(String arg) { + this("", arg); + } + + ArgTokenizer(String prefix, String arg) { this.str = arg; + this.prefix = prefix; this.length = arg.length(); quoteChar('"'); quoteChar('\''); @@ -88,7 +94,7 @@ class ArgTokenizer { } String whole() { - return str; + return prefix + str; } void mark() { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java index 958116c6987..21ac481bd1e 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -95,20 +95,20 @@ class Feedback { return mode.getContinuationPrompt(nextId); } - public boolean setFeedback(JShellTool tool, ArgTokenizer at) { - return new Setter(tool, at).setFeedback(); + public boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setFeedback(); } - public boolean setFormat(JShellTool tool, ArgTokenizer at) { - return new Setter(tool, at).setFormat(); + public boolean setFormat(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setFormat(); } - public boolean setNewMode(JShellTool tool, ArgTokenizer at) { - return new Setter(tool, at).setNewMode(); + public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setNewMode(); } - public boolean setPrompt(JShellTool tool, ArgTokenizer at) { - return new Setter(tool, at).setPrompt(); + public boolean setPrompt(MessageHandler messageHandler, ArgTokenizer at) { + return new Setter(messageHandler, at).setPrompt(); } { @@ -529,26 +529,26 @@ class Feedback { private class Setter { private final ArgTokenizer at; - private final JShellTool tool; + private final MessageHandler messageHandler; boolean valid = true; - Setter(JShellTool tool, ArgTokenizer at) { - this.tool = tool; + Setter(MessageHandler messageHandler, ArgTokenizer at) { + this.messageHandler = messageHandler; this.at = at; } void fluff(String format, Object... args) { - tool.fluff(format, args); + messageHandler.fluff(format, args); } - void fluffmsg(String format, Object... args) { - tool.fluffmsg(format, args); + void fluffmsg(String messageKey, Object... args) { + messageHandler.fluffmsg(messageKey, args); } void errorat(String messageKey, Object... args) { Object[] a2 = Arrays.copyOf(args, args.length + 2); - a2[args.length] = "/set " + at.whole(); - tool.errormsg(messageKey, a2); + a2[args.length] = at.whole(); + messageHandler.errormsg(messageKey, a2); } // For /set prompt "" "" diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 144de11c114..b6cd1a370f6 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -108,7 +108,7 @@ import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; * Command line REPL tool for Java using the JShell API. * @author Robert Field */ -public class JShellTool { +public class JShellTool implements MessageHandler { private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); @@ -166,6 +166,8 @@ public class JShellTool { private boolean regenerateOnDeath = true; private boolean live = false; private boolean feedbackInitialized = false; + private String initialMode = null; + private List remoteVMOptions = new ArrayList<>(); SourceCodeAnalysis analysis; JShell state = null; @@ -256,7 +258,8 @@ public class JShellTool { * @param format printf format * @param args printf args */ - void fluff(String format, Object... args) { + @Override + public void fluff(String format, Object... args) { if (feedback.shouldDisplayCommandFluff() && interactive()) { hard(format, args); } @@ -362,7 +365,8 @@ public class JShellTool { * @param key the resource key * @param args */ - void errormsg(String key, Object... args) { + @Override + public void errormsg(String key, Object... args) { cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre())); } @@ -383,7 +387,8 @@ public class JShellTool { * @param key the resource key * @param args */ - void fluffmsg(String key, Object... args) { + @Override + public void fluffmsg(String key, Object... args) { if (feedback.shouldDisplayCommandFluff() && interactive()) { hardmsg(key, args); } @@ -512,6 +517,23 @@ public class JShellTool { case "-fullversion": cmdout.printf("jshell %s\n", fullVersion()); return null; + case "-feedback": + if (ai.hasNext()) { + initialMode = ai.next(); + } else { + startmsg("jshell.err.opt.feedback.arg"); + return null; + } + break; + case "-q": + initialMode = "concise"; + break; + case "-qq": + initialMode = "silent"; + break; + case "-v": + initialMode = "verbose"; + break; case "-startup": if (cmdlineStartup != null) { startmsg("jshell.err.opt.startup.conflict"); @@ -530,6 +552,10 @@ public class JShellTool { cmdlineStartup = ""; break; default: + if (arg.startsWith("-R")) { + remoteVMOptions.add(arg.substring(2)); + break; + } startmsg("jshell.err.opt.unknown", arg); printUsage(); return null; @@ -567,6 +593,7 @@ public class JShellTool { .idGenerator((sn, i) -> (currentNameSpace == startNamespace || state.status(sn).isActive) ? currentNameSpace.tid(sn) : errorNamespace.tid(sn)) + .remoteVMOptions(remoteVMOptions.toArray(new String[remoteVMOptions.size()])) .build(); shutdownSubscription = state.onShutdown((JShell deadState) -> { if (deadState == state) { @@ -596,6 +623,26 @@ public class JShellTool { start = cmdlineStartup; } startUpRun(start); + if (initialMode != null) { + MessageHandler mh = new MessageHandler() { + @Override + public void fluff(String format, Object... args) { + } + + @Override + public void fluffmsg(String messageKey, Object... args) { + } + + @Override + public void errormsg(String messageKey, Object... args) { + startmsg(messageKey, args); + } + }; + if (!feedback.setFeedback(mh, new ArgTokenizer("-feedback ", initialMode))) { + regenerateOnDeath = false; + } + initialMode = null; + } currentNameSpace = mainNamespace; } //where @@ -1050,7 +1097,7 @@ public class JShellTool { "format", "feedback", "newmode", "prompt", "editor", "start"}; final boolean cmdSet(String arg) { - ArgTokenizer at = new ArgTokenizer(arg.trim()); + ArgTokenizer at = new ArgTokenizer("/set ", arg.trim()); String which = setSubCommand(at); if (which == null) { return false; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties index b70c6de2ac0..06784c86582 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties @@ -28,6 +28,7 @@ Welcome to JShell -- Version {0}\n\ For an introduction type: /help intro\n jshell.err.opt.classpath.conflict = Conflicting -classpath option. jshell.err.opt.classpath.arg = Argument to -classpath missing. +jshell.err.opt.feedback.arg = Argument to -feedback missing. Mode required. jshell.err.opt.startup.conflict = Conflicting -startup or -nostartup option. jshell.err.opt.unknown = Unknown option: {0} @@ -128,13 +129,23 @@ jshell.console.incomplete = \nResults may be incomplete; try again later for com help.usage = \ Usage: jshell \n\ -where possible options include:\n\t\ - -classpath Specify where to find user class files\n\t\ - -cp Specify where to find user class files\n\t\ - -startup One run replacement for the start-up definitions\n\t\ - -nostartup Do not run the start-up definitions\n\t\ - -help Print a synopsis of standard options\n\t\ - -version Version information\n +where possible options include:\n\ +\ -classpath Specify where to find user class files\n\ +\ -cp Specify where to find user class files\n\ +\ -startup One run replacement for the start-up definitions\n\ +\ -nostartup Do not run the start-up definitions\n\ +\ -feedback Specify the initial feedback mode. The mode may be\n\ +\ predefined (silent, concise, normal, or verbose) or\n\ +\ previously user-defined\n\ +\ -q Quiet feedback. Same as: -feedback concise\n\ +\ -qq Really quiet feedback. Same as: -feedback silent\n\ +\ -v Verbose feedback. Same as: -feedback verbose\n\ +\ -J Pass directly to the runtime system.\n\ +\ Use one -J for each runtime flag or flag argument\n\ +\ -R Pass to the remote runtime system.\n\ +\ Use one -R for each remote flag or flag argument\n\ +\ -help Print this synopsis of standard options\n\ +\ -version Version information\n help.list.summary = list the source you have typed help.list.args = [all|start|] diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index f69ec57e797..40186742741 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -57,11 +57,19 @@ class ExecutionControl { private ObjectInputStream in; private ObjectOutputStream out; private final JShell proc; + private final String remoteVMOptions; - ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc) { + ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc, List extraRemoteVMOptions) { this.env = env; this.maps = maps; this.proc = proc; + StringBuilder sb = new StringBuilder(); + extraRemoteVMOptions.stream() + .forEach(s -> { + sb.append(" "); + sb.append(s); + }); + this.remoteVMOptions = sb.toString(); } void launch() throws IOException { @@ -257,11 +265,9 @@ class ExecutionControl { // Locale.getDefault()); String connectorName = "com.sun.jdi.CommandLineLaunch"; - String classPath = System.getProperty("java.class.path"); - String javaArgs = "-classpath " + classPath; Map argumentName2Value = new HashMap<>(); argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port); - argumentName2Value.put("options", javaArgs); + argumentName2Value.put("options", remoteVMOptions); boolean launchImmediately = true; int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 0cb2d05c7af..8b95bbdc7ff 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -26,10 +26,11 @@ package jdk.jshell; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -84,6 +85,7 @@ public class JShell implements AutoCloseable { final PrintStream err; final Supplier tempVariableNameGenerator; final BiFunction idGenerator; + final List extraRemoteVMOptions; private int nextKeyIndex = 1; @@ -105,6 +107,7 @@ public class JShell implements AutoCloseable { this.err = b.err; this.tempVariableNameGenerator = b.tempVariableNameGenerator; this.idGenerator = b.idGenerator; + this.extraRemoteVMOptions = b.extraRemoteVMOptions; this.maps = new SnippetMaps(this); this.keyMap = new KeyMap(this); @@ -139,6 +142,7 @@ public class JShell implements AutoCloseable { PrintStream err = System.err; Supplier tempVariableNameGenerator = null; BiFunction idGenerator = null; + List extraRemoteVMOptions = new ArrayList<>(); Builder() { } @@ -263,6 +267,18 @@ public class JShell implements AutoCloseable { return this; } + /** + * Set additional VM options for launching the VM. + * + * @param options The options for the remote VM. + * @return the Builder instance (for use in chained + * initialization). + */ + public Builder remoteVMOptions(String... options) { + this.extraRemoteVMOptions.addAll(Arrays.asList(options)); + return this; + } + /** * Build a JShell state engine. This is the entry-point to all JShell * functionality. This creates a remote process for execution. It is @@ -621,10 +637,10 @@ public class JShell implements AutoCloseable { ExecutionControl executionControl() { if (executionControl == null) { - this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this); + this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this, extraRemoteVMOptions); try { executionControl.launch(); - } catch (IOException ex) { + } catch (Throwable ex) { throw new InternalError("Launching JDI execution engine threw: " + ex.getMessage(), ex); } } diff --git a/langtools/test/jdk/jshell/StartOptionTest.java b/langtools/test/jdk/jshell/StartOptionTest.java index b813b35691c..071b1523b9d 100644 --- a/langtools/test/jdk/jshell/StartOptionTest.java +++ b/langtools/test/jdk/jshell/StartOptionTest.java @@ -22,7 +22,7 @@ */ /* - * @test + * @test 8151754 * @summary Testing start-up options. * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -34,6 +34,7 @@ */ import java.io.ByteArrayOutputStream; +import java.io.OutputStream; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Path; @@ -47,6 +48,7 @@ import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; @Test public class StartOptionTest { @@ -55,9 +57,24 @@ public class StartOptionTest { private ByteArrayOutputStream err; private JShellTool getShellTool() { - return new JShellTool(null, new PrintStream(out), new PrintStream(err), null, null, null, - null, new ReplToolTesting.MemoryPreferences(), - Locale.ROOT); + class NoOutputAllowedStream extends OutputStream { + private final String label; + NoOutputAllowedStream(String label) { + this.label = label; + } + @Override + public void write(int b) { fail("Unexpected output to: " + label); } + } + return new JShellTool( + new TestingInputStream(), + new PrintStream(out), + new PrintStream(err), + new PrintStream(new NoOutputAllowedStream("console")), + new TestingInputStream(), + new PrintStream(new NoOutputAllowedStream("userout")), + new PrintStream(new NoOutputAllowedStream("usererr")), + new ReplToolTesting.MemoryPreferences(), + Locale.ROOT); } private String getOutput() { @@ -132,6 +149,12 @@ public class StartOptionTest { } } + @Test + public void testNegFeedbackOption() throws Exception { + start("", "Argument to -feedback missing. Mode required.", "-feedback"); + start("", "Does not match any current feedback mode: blorp -- -feedback blorp", "-feedback", "blorp"); + } + @Test public void testVersion() throws Exception { start(s -> assertTrue(s.startsWith("jshell")), null, "-version"); diff --git a/langtools/test/jdk/jshell/ToolSimpleTest.java b/langtools/test/jdk/jshell/ToolSimpleTest.java index 069e571fa41..b0c97a77f0b 100644 --- a/langtools/test/jdk/jshell/ToolSimpleTest.java +++ b/langtools/test/jdk/jshell/ToolSimpleTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8153716 8143955 + * @bug 8153716 8143955 8151754 8150382 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -349,4 +349,39 @@ public class ToolSimpleTest extends ReplToolTesting { System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless); } } + + public void testOptionQ() { + test(new String[]{"-q", "-nostartup"}, + (a) -> assertCommand(a, "1+1", "$1 ==> 2"), + (a) -> assertCommand(a, "int x = 5", "") + ); + } + + public void testOptionQq() { + test(new String[]{"-qq", "-nostartup"}, + (a) -> assertCommand(a, "1+1", "") + ); + } + + public void testOptionV() { + test(new String[]{"-v", "-nostartup"}, + (a) -> assertCommand(a, "1+1", + "$1 ==> 2\n" + + "| created scratch variable $1 : int") + ); + } + + public void testOptionFeedback() { + test(new String[]{"-feedback", "concise", "-nostartup"}, + (a) -> assertCommand(a, "1+1", "$1 ==> 2"), + (a) -> assertCommand(a, "int x = 5", "") + ); + } + + public void testOptionR() { + test(new String[]{"-R-Dthe.sound=blorp", "-nostartup"}, + (a) -> assertCommand(a, "System.getProperty(\"the.sound\")", + "$1 ==> \"blorp\"") + ); + } } From 7e90d3bb14ae2ded0897132f7a57feea5cc387a7 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Wed, 27 Apr 2016 19:56:44 -0700 Subject: [PATCH 157/225] 8155580: jshell tool: push for -R missed added file MessageHandler.java Reviewed-by: jlahoda --- .../internal/jshell/tool/MessageHandler.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java new file mode 100644 index 00000000000..4014f4b423e --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.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.jshell.tool; + + +/** + * User message reporting support + * + * @author Robert Field + */ +public interface MessageHandler { + + void fluff(String format, Object... args); + + void fluffmsg(String messageKey, Object... args); + + void errormsg(String messageKey, Object... args); +} From 560adadb050cf54561f212ab0bd46d8a975112c8 Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Thu, 28 Apr 2016 12:38:22 +0800 Subject: [PATCH 158/225] 8154733: Fix module dependencies missed in java.rmi tests Reviewed-by: alanb, amlu --- jdk/test/java/rmi/TEST.properties | 1 + jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java | 3 ++- jdk/test/sun/rmi/TEST.properties | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/rmi/TEST.properties create mode 100644 jdk/test/sun/rmi/TEST.properties diff --git a/jdk/test/java/rmi/TEST.properties b/jdk/test/java/rmi/TEST.properties new file mode 100644 index 00000000000..d4bbfc905b9 --- /dev/null +++ b/jdk/test/java/rmi/TEST.properties @@ -0,0 +1 @@ +modules = java.rmi diff --git a/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java b/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java index 8f9b715867f..5e6358dba7f 100644 --- a/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java +++ b/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.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 @@ -26,6 +26,7 @@ * @summary The Serialization benchmark test. This java class is used to run the * test under JTREG. * @library ../../ + * @modules java.desktop * @build bench.BenchInfo bench.HtmlReporter bench.Util bench.Benchmark * @build bench.Reporter bench.XmlReporter bench.ConfigFormatException * @build bench.Harness bench.TextReporter diff --git a/jdk/test/sun/rmi/TEST.properties b/jdk/test/sun/rmi/TEST.properties new file mode 100644 index 00000000000..d4bbfc905b9 --- /dev/null +++ b/jdk/test/sun/rmi/TEST.properties @@ -0,0 +1 @@ +modules = java.rmi From 1ac868ea613abe892aa2144a3f202871d74ceb06 Mon Sep 17 00:00:00 2001 From: Bhavesh Patel Date: Thu, 28 Apr 2016 05:10:11 +0000 Subject: [PATCH 159/225] 8154119: Module summary page should display module description Reviewed-by: jjg --- .../formats/html/ModuleWriterImpl.java | 15 ++ .../doclets/formats/html/SectionName.java | 3 +- .../formats/html/markup/HtmlConstants.java | 8 +- .../doclets/toolkit/ModuleSummaryWriter.java | 8 + .../builders/ModuleSummaryBuilder.java | 13 ++ .../doclets/toolkit/resources/doclet.xml | 1 + .../doclet/testModules/TestModules.java | 145 ++++++++++++++++++ .../testModules/module1/module-info.java | 33 ++++ .../testpkgmdl1/TestClassInModule1.java | 28 ++++ .../testModules/module2/module-info.java | 31 ++++ .../testpkgmdl2/TestClassInModule2.java | 28 ++++ 11 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 langtools/test/jdk/javadoc/doclet/testModules/TestModules.java create mode 100644 langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java create mode 100644 langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java create mode 100644 langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java create mode 100644 langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index 105cb706eeb..555f0dcb03d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -167,6 +167,21 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW summaryContentTree.addContent(table); } + /** + * {@inheritDoc} + */ + public void addModuleDescription(Content moduleContentTree) { + if (!utils.getBody(mdle).isEmpty()) { + Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree; + tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION); + tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION)); + addInlineComment(mdle, tree); + if (configuration.allowTag(HtmlTag.SECTION)) { + moduleContentTree.addContent(tree); + } + } + } + /** * Adds list of packages in the package summary table. Generate link to each package. * diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java index a9ff3e50311..19e9a556c4c 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.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 @@ -53,6 +53,7 @@ public enum SectionName { METHOD_DETAIL("method.detail"), METHODS_INHERITANCE("methods.inherited.from.class."), METHOD_SUMMARY("method.summary"), + MODULE_DESCRIPTION("module.description"), NAVBAR_BOTTOM("navbar.bottom"), NAVBAR_BOTTOM_FIRSTROW("navbar.bottom.firstrow"), NAVBAR_TOP("navbar.top"), diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java index 1b7731badf2..8807cd75bba 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -63,6 +63,12 @@ public class HtmlConstants { public static final Content END_OF_BOTTOM_NAVBAR = new Comment("======== END OF BOTTOM NAVBAR ======="); + /** + * Marker to identify start of module description. + */ + public static final Content START_OF_MODULE_DESCRIPTION = + new Comment("============ MODULE DESCRIPTION ==========="); + /** * Marker to identify start of class data. */ diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java index 50a87a63d44..33a76b76028 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java @@ -73,6 +73,14 @@ public interface ModuleSummaryWriter { */ public abstract Content getSummaryTree(Content summaryContentTree); + /** + * Adds the module description. + * + * @param moduleContentTree the content tree to which the module description + * will be added + */ + public abstract void addModuleDescription(Content moduleContentTree); + /** * Adds the table of packages to the documentation tree. * diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java index d2de20daf01..a32a7f595a7 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java @@ -185,4 +185,17 @@ public class ModuleSummaryBuilder extends AbstractBuilder { packageTableSummary, summaryContentTree); } } + + /** + * Build the description for the module. + * + * @param node the XML element that specifies which components to document + * @param moduleContentTree the tree to which the module description will + * be added + */ + public void buildModuleDescription(XMLNode node, Content moduleContentTree) { + if (!configuration.nocomment) { + moduleWriter.addModuleDescription(moduleContentTree); + } + } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml index 62a3183808c..f8349031319 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml @@ -30,6 +30,7 @@ +

    diff --git a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java new file mode 100644 index 00000000000..d887c0933a7 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java @@ -0,0 +1,145 @@ +/* + * 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 8154119 + * @summary Test modules support in javadoc. + * @author bpatel + * @library ../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build JavadocTester + * @run main TestModules + */ + +public class TestModules extends JavadocTester { + + public static void main(String... args) throws Exception { + TestModules tester = new TestModules(); + tester.runTests(); + } + + @Test + void test1() { + javadoc("-d", "out", + "-modulesourcepath", testSrc, + "-addmods", "module1,module2", + "testpkgmdl1", "testpkgmdl2"); + checkExit(Exit.OK); + testDescription(true); + testNoDescription(false); + } + + @Test + void test2() { + javadoc("-d", "out-html5", "-html5", + "-modulesourcepath", testSrc, + "-addmods", "module1,module2", + "testpkgmdl1", "testpkgmdl2"); + checkExit(Exit.OK); + testHtml5Description(true); + testHtml5NoDescription(false); + } + + @Test + void test3() { + javadoc("-d", "out-nocomment", "-nocomment", + "-modulesourcepath", testSrc, + "-addmods", "module1,module2", + "testpkgmdl1", "testpkgmdl2"); + checkExit(Exit.OK); + testDescription(false); + testNoDescription(true); + } + + @Test + void test4() { + javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5", + "-modulesourcepath", testSrc, + "-addmods", "module1,module2", + "testpkgmdl1", "testpkgmdl2"); + checkExit(Exit.OK); + testHtml5Description(false); + testHtml5NoDescription(true); + } + + void testDescription(boolean found) { + checkOutput("module1-summary.html", found, + "\n" + + "\n" + + "\n" + + "\n" + + "
    This is a test description for the module1 module.
    "); + checkOutput("module2-summary.html", found, + "\n" + + "\n" + + "\n" + + "\n" + + "
    This is a test description for the module2 module.
    "); + } + + void testNoDescription(boolean found) { + checkOutput("module1-summary.html", found, + "
    \n" + + "
      \n" + + "
    • \n" + + ""); + checkOutput("module2-summary.html", found, + "
      \n" + + "
        \n" + + "
      • \n" + + "
      "); + } + + void testHtml5Description(boolean found) { + checkOutput("module1-summary.html", found, + "
      \n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
      This is a test description for the module1 module.
      \n" + + "
      "); + checkOutput("module2-summary.html", found, + "
      \n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
      This is a test description for the module2 module.
      \n" + + "
      "); + } + + void testHtml5NoDescription(boolean found) { + checkOutput("module1-summary.html", found, + "
      \n" + + "
        \n" + + "
      • \n" + + "
      "); + checkOutput("module2-summary.html", found, + "
      \n" + + "
        \n" + + "
      • \n" + + "
      "); + } +} diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java new file mode 100644 index 00000000000..37ff3f7c77c --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.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. 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 is a test description for the module1 module. + */ +module module1 { + requires module2; + + exports testpkgmdl1; +} diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java b/langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java new file mode 100644 index 00000000000..63542730c0a --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java @@ -0,0 +1,28 @@ +/* + * 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 testpkgmdl1; + +public class TestClassInModule1 { +} diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java new file mode 100644 index 00000000000..13c77f05998 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 is a test description for the module2 module. + */ +module module2 { + exports testpkgmdl2; +} diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java new file mode 100644 index 00000000000..d4995649b5c --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java @@ -0,0 +1,28 @@ +/* + * 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 testpkgmdl2; + +public class TestClassInModule2 { +} From 1f74d8cba8fc3961285b61074b562b3a04dc1bd4 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 28 Apr 2016 09:33:18 +0100 Subject: [PATCH 160/225] 8155578: OpenJDK build failed after JDK-8044773 Reviewed-by: alanb --- jdk/src/java.base/share/classes/module-info.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 12ad93f6a6d..a597253d168 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -166,6 +166,7 @@ module java.base { java.sql, java.xml, jdk.charsets, + jdk.net, jdk.scripting.nashorn, jdk.unsupported, jdk.vm.ci; From 0f84fadba6462bf1cca60885f102d7609af90768 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 28 Apr 2016 10:42:33 +0200 Subject: [PATCH 161/225] 8155025: 0.001.toFixed(2) should return "0.00" not "0" Reviewed-by: jlaskey, hannesw --- .../runtime/doubleconv/DtoaBuffer.java | 2 + nashorn/test/script/basic/JDK-8155025.js | 37 +++++++++ .../test/script/basic/JDK-8155025.js.EXPECTED | 75 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 nashorn/test/script/basic/JDK-8155025.js create mode 100644 nashorn/test/script/basic/JDK-8155025.js.EXPECTED diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java index 172118ca685..98f39c3a4e0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java @@ -176,6 +176,8 @@ public class DtoaBuffer { buffer.append('0'); } buffer.append(chars, 0, length); + } else { + decimalPoint = 1; } } else if (decimalPoint >= length) { // large integer, add trailing zeroes diff --git a/nashorn/test/script/basic/JDK-8155025.js b/nashorn/test/script/basic/JDK-8155025.js new file mode 100644 index 00000000000..7b1001539f8 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8155025.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8155025: 0.001.toFixed(2) should return "0.00" not "0" + * + * @test + * @run + */ + +for (var i = 0, zeros=""; i <= 9; i++, zeros += "0") { + var n = Number("0." + zeros + "1"); + for (var j = 1; j <= i + 3; j++) { + print(n + ".toFixed(" + j + ")=" + n.toFixed(j)); + } +} + diff --git a/nashorn/test/script/basic/JDK-8155025.js.EXPECTED b/nashorn/test/script/basic/JDK-8155025.js.EXPECTED new file mode 100644 index 00000000000..7cdca19c090 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8155025.js.EXPECTED @@ -0,0 +1,75 @@ +0.1.toFixed(1)=0.1 +0.1.toFixed(2)=0.10 +0.1.toFixed(3)=0.100 +0.01.toFixed(1)=0.0 +0.01.toFixed(2)=0.01 +0.01.toFixed(3)=0.010 +0.01.toFixed(4)=0.0100 +0.001.toFixed(1)=0.0 +0.001.toFixed(2)=0.00 +0.001.toFixed(3)=0.001 +0.001.toFixed(4)=0.0010 +0.001.toFixed(5)=0.00100 +0.0001.toFixed(1)=0.0 +0.0001.toFixed(2)=0.00 +0.0001.toFixed(3)=0.000 +0.0001.toFixed(4)=0.0001 +0.0001.toFixed(5)=0.00010 +0.0001.toFixed(6)=0.000100 +0.00001.toFixed(1)=0.0 +0.00001.toFixed(2)=0.00 +0.00001.toFixed(3)=0.000 +0.00001.toFixed(4)=0.0000 +0.00001.toFixed(5)=0.00001 +0.00001.toFixed(6)=0.000010 +0.00001.toFixed(7)=0.0000100 +0.000001.toFixed(1)=0.0 +0.000001.toFixed(2)=0.00 +0.000001.toFixed(3)=0.000 +0.000001.toFixed(4)=0.0000 +0.000001.toFixed(5)=0.00000 +0.000001.toFixed(6)=0.000001 +0.000001.toFixed(7)=0.0000010 +0.000001.toFixed(8)=0.00000100 +1e-7.toFixed(1)=0.0 +1e-7.toFixed(2)=0.00 +1e-7.toFixed(3)=0.000 +1e-7.toFixed(4)=0.0000 +1e-7.toFixed(5)=0.00000 +1e-7.toFixed(6)=0.000000 +1e-7.toFixed(7)=0.0000001 +1e-7.toFixed(8)=0.00000010 +1e-7.toFixed(9)=0.000000100 +1e-8.toFixed(1)=0.0 +1e-8.toFixed(2)=0.00 +1e-8.toFixed(3)=0.000 +1e-8.toFixed(4)=0.0000 +1e-8.toFixed(5)=0.00000 +1e-8.toFixed(6)=0.000000 +1e-8.toFixed(7)=0.0000000 +1e-8.toFixed(8)=0.00000001 +1e-8.toFixed(9)=0.000000010 +1e-8.toFixed(10)=0.0000000100 +1e-9.toFixed(1)=0.0 +1e-9.toFixed(2)=0.00 +1e-9.toFixed(3)=0.000 +1e-9.toFixed(4)=0.0000 +1e-9.toFixed(5)=0.00000 +1e-9.toFixed(6)=0.000000 +1e-9.toFixed(7)=0.0000000 +1e-9.toFixed(8)=0.00000000 +1e-9.toFixed(9)=0.000000001 +1e-9.toFixed(10)=0.0000000010 +1e-9.toFixed(11)=0.00000000100 +1e-10.toFixed(1)=0.0 +1e-10.toFixed(2)=0.00 +1e-10.toFixed(3)=0.000 +1e-10.toFixed(4)=0.0000 +1e-10.toFixed(5)=0.00000 +1e-10.toFixed(6)=0.000000 +1e-10.toFixed(7)=0.0000000 +1e-10.toFixed(8)=0.00000000 +1e-10.toFixed(9)=0.000000000 +1e-10.toFixed(10)=0.0000000001 +1e-10.toFixed(11)=0.00000000010 +1e-10.toFixed(12)=0.000000000100 From a12239e493d7dcbe1baaa3a7997a74f9c460ca49 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 28 Apr 2016 16:18:59 +0200 Subject: [PATCH 162/225] 8155641: Correct merge typo in compare script Reviewed-by: chegar --- common/autoconf/compare.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index a6cc8d65abc..67a69ff73bd 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -31,7 +31,7 @@ export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@ -sexport OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@" +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@" From c4275c858c1129429fa72b33c993d0115f838317 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 28 Apr 2016 17:14:59 +0200 Subject: [PATCH 163/225] 8155629: MODULES_FILTER should apply to imported modules Reviewed-by: dholmes, tbell, mchung --- make/common/Modules.gmk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index dba855995d7..681c58ad07a 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -186,7 +186,8 @@ FindAllModules = \ $(call GetModuleNameFromModuleInfo, $(MODULE_INFOS)))) FindImportedModules = \ - $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*))) + $(filter-out $(MODULES_FILTER), \ + $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*)))) # Find all source dirs for a particular module # $1 - Module to find source dirs for From e9a10a4fcab03f47ae595ef210a50a0c5db69f12 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:30 -0700 Subject: [PATCH 164/225] Added tag jdk-9+116 for changeset fbab762803ef --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 06edc4a1f53..fa57d754762 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -358,3 +358,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113 1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114 09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115 +6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116 From a78f72848016ffe0cb5c475c7f4884d79e283441 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:32 -0700 Subject: [PATCH 165/225] Added tag jdk-9+116 for changeset e29791634c81 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 11405727ce0..23786130f3e 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -518,3 +518,4 @@ c558850fac5750d8ca98a45180121980f57cdd28 jdk-9+111 c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115 +61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116 From 40edabdf12aa02c11adc929c7add31d9a451d2c2 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:32 -0700 Subject: [PATCH 166/225] Added tag jdk-9+116 for changeset bff09f64dd1c --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index dd25acb220b..9b4adbd6b27 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -358,3 +358,4 @@ b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114 7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115 +7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116 From 61e4e8685db9e99adec7218c7150a1688f4a2afa Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:36 -0700 Subject: [PATCH 167/225] Added tag jdk-9+116 for changeset 318476412bc2 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 07b1b9985f7..53336dcb47a 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -358,3 +358,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113 147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114 1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115 +9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116 From a0bed541c095c71dde3afd772d2550cff26c95c2 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:36 -0700 Subject: [PATCH 168/225] Added tag jdk-9+116 for changeset f0cb22ad8db4 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 7781746dc33..7ca8b5131a5 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -361,3 +361,4 @@ fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 e980062475c10d21137051045bf95ee229db9b27 jdk-9+113 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115 +529f0bf896e58525614d863e283ad155531941cb jdk-9+116 From 21311d2cb71798d52f0d6df9abf90bca8ba4ca2b Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:38 -0700 Subject: [PATCH 169/225] Added tag jdk-9+116 for changeset d91c47cb2992 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 74ad9bf9055..68f3b996bfc 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -358,3 +358,4 @@ b2a69d66dc65ad1d3aeb3bd362cf5bb0deba040e jdk-9+111 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115 +baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116 From 8c52468e73f2a7d4bdb039b1e284620d0b162c6e Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:42 -0700 Subject: [PATCH 170/225] Added tag jdk-9+116 for changeset 33cf53901cac --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index e8881f37c97..b45c9be6af7 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -358,3 +358,4 @@ f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 4e87682893e662421af10a62d29ae822ce0fea04 jdk-9+113 cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114 31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115 +3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116 From 45082e319463fefcbb3f45c37a08a8eb29d65741 Mon Sep 17 00:00:00 2001 From: Lana Steuck Date: Thu, 28 Apr 2016 08:26:43 -0700 Subject: [PATCH 171/225] Added tag jdk-9+116 for changeset 973b1c28c6d2 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 78e30d77611..93b4c4a0b7c 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -349,3 +349,4 @@ c261f8440c5578b34596e6b0419a81aec431a884 jdk-9+112 a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113 ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114 295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115 +208388a5622dcca8227d6ad6c268f2c88087d283 jdk-9+116 From 552f7b32c16bca29540c09940a9a93d85778d222 Mon Sep 17 00:00:00 2001 From: Chris Bensen Date: Thu, 28 Apr 2016 08:28:48 -0700 Subject: [PATCH 172/225] 8150990: Add helper class in jdk.jlink for packager use to avoid coordination with FX and JDK builds Reviewed-by: alanb, mchung, kcr, sundar --- .../packager/AppRuntimeImageBuilder.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java new file mode 100644 index 00000000000..fb785da54b7 --- /dev/null +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -0,0 +1,146 @@ +/* + * 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.tools.jlink.internal.packager; + + +import jdk.tools.jlink.Jlink; +import jdk.tools.jlink.builder.ImageBuilder; +import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.builder.*; +import jdk.tools.jlink.plugin.Pool; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; +import java.util.stream.Collectors; + +/** + * AppRuntimeImageBuilder is a private API used only by the Java Packager to generate + * a Java runtime image using jlink. AppRuntimeImageBuilder encapsulates the + * arguments that jlink requires to generate this image. To create the image call the + * build() method. + */ +public final class AppRuntimeImageBuilder { + private Path outputDir = null; + private List modulePath = null; + private Set addModules = null; + private Set limitModules = null; + private String excludeFileList = null; + private Map userArguments = null; + private Boolean stripNativeCommands = null; + + public AppRuntimeImageBuilder() {} + + public void setOutputDir(Path value) { + outputDir = value; + } + + public void setModulePath(List value) { + modulePath = value; + } + + public void setAddModules(Set value) { + addModules = value; + } + + public void setLimitModules(Set value) { + limitModules = value; + } + + public void setExcludeFileList(String value) { + excludeFileList = value; + } + + public void setStripNativeCommands(boolean value) { + stripNativeCommands = value; + } + + public void setUserArguments(Map value) { + userArguments = value; + } + + public void build() throws IOException { + // jlink main arguments + Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration( + new File("").toPath(), // Unused + modulePath, addModules, limitModules); + + // plugin configuration + List plugins = new ArrayList(); + + if (stripNativeCommands) { + plugins.add(Jlink.newPlugin( + "strip-native-commands", + Collections.singletonMap("strip-native-commands", "on"), + null)); + } + + if (excludeFileList != null && !excludeFileList.isEmpty()) { + plugins.add(Jlink.newPlugin( + "exclude-files", + Collections.singletonMap("exclude-files", excludeFileList), + null)); + } + + // add user supplied jlink arguments + for (Map.Entry entry : userArguments.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + plugins.add(Jlink.newPlugin(key, + Collections.singletonMap(key, value), + null)); + } + + plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null)); + + // build the image + Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration( + plugins, new DefaultImageBuilder(true, outputDir), null); + Jlink jlink = new Jlink(); + jlink.build(jlinkConfig, pluginConfig); + } +} From 8a708bda63d0dcbf0ed4bc87d5c1c58ad7821bbc Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 28 Apr 2016 17:33:49 +0200 Subject: [PATCH 173/225] 8155632: Remove debuginfo from jmod files Reviewed-by: tbell, mchung, alanb --- make/CreateJmods.gmk | 2 +- make/Images.gmk | 49 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/make/CreateJmods.gmk b/make/CreateJmods.gmk index fdfb7dc6884..212132779b1 100644 --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -82,7 +82,7 @@ $(IMAGES_OUTPUTDIR)/jmods/$(MODULE).jmod: $(DEPS) --os-version $(REQUIRED_OS_VERSION) \ --modulepath $(IMAGES_OUTPUTDIR)/jmods\ --hash-dependencies '.*' \ - --exclude '**_the.*' \ + --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.pdb,*.map}' \ $(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@ diff --git a/make/Images.gmk b/make/Images.gmk index 97cce400395..a50cd7ca4d4 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -422,6 +422,55 @@ ifeq ($(GCOV_ENABLED), true) endif +################################################################################ +# Debug symbols +# Since debug symbols are not included in the jmod files, they need to be copied +# in manually after generating the images. + +ALL_JDK_MODULES := $(JDK_MODULES) +ALL_JRE_MODULES := $(sort $(JRE_MODULES), $(foreach m, $(JRE_MODULES), \ + $(call FindTransitiveDepsForModule, $m))) + +ifeq ($(OPENJDK_TARGET_OS), windows) + LIBS_TARGET_SUBDIR := bin +else + LIBS_TARGET_SUBDIR := lib +endif + +DEBUGINFO_SUFFIXES := .diz .debuginfo .pdb .map + +# Param 1 - dir to find debuginfo files in +FindDebuginfoFiles = \ + $(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \ + $(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \ + $(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES))) + +# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM +# dirs. +ifeq ($(OPENJDK_TARGET_OS)-$(ZIP_EXTERNAL_DEBUG_SYMBOLS), macosx-false) + $(eval $(call FillCacheFind, \ + $(SUPPORT_OUTPUTDIR)/modules_cmds $(SUPPORT_OUTPUTDIR)/modules_libs/)) + FindDebuginfoFiles = \ + $(if $(wildcard $1), $(call containing, .dSYM/, $(call CacheFind, $1))) +endif + +# Param 1 - either JDK or JRE +SetupCopyDebuginfo = \ + $(foreach m, $(ALL_$1_MODULES), \ + $(eval $(call SetupCopyFiles, COPY_$1_LIBS_DEBUGINFO_$m, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/$m, \ + DEST := $($1_IMAGE_DIR)/$(LIBS_TARGET_SUBDIR), \ + FILES := $(call FindDebuginfoFiles, \ + $(SUPPORT_OUTPUTDIR)/modules_libs/$m), \ + )) \ + $(eval $1_TARGETS += $$(COPY_$1_LIBS_DEBUGINFO_$m)) \ + ) + +# No space before argument to avoid having to put $(strip ) everywhere in +# implementation above. +$(call SetupCopyDebuginfo,JDK) +$(call SetupCopyDebuginfo,JRE) + ################################################################################ # Include custom post hook here to make it possible to augment the target lists From 2f9ffbd2802e0a8ce7f02edc2fcaa17644135384 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Thu, 28 Apr 2016 09:08:01 -0700 Subject: [PATCH 174/225] 8154220: Semi-colon delimited list of catalog files in System property is throwing IllegalArgumentException Reviewed-by: lancea --- .../javax/xml/catalog/CatalogFeatures.java | 8 ++- .../jaxp/unittest/catalog/CatalogTest.java | 57 ++++++++++++++++++- .../xml/jaxp/unittest/catalog/first_cat.xml | 6 ++ .../xml/jaxp/unittest/catalog/next_cat.xml | 6 ++ .../xml/jaxp/unittest/catalog/second_cat.xml | 7 +++ 5 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml create mode 100644 jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml create mode 100644 jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml diff --git a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java index 8cc0e53ae9e..72a88e2b2a2 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java @@ -444,13 +444,15 @@ public class CatalogFeatures { } } else if (index == Feature.FILES.ordinal()) { try { - if (Util.verifyAndGetURI(value, null) == null) { - CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null); + String[] catalogFile = value.split(";[ ]*"); + for (String temp : catalogFile) { + if (Util.verifyAndGetURI(temp, null) == null) { + CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null); + } } }catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) { CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex); } - } if (states[index] == null || state.compareTo(states[index]) >= 0) { values[index] = value; diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java index 7edd6af3503..01bf4f63e89 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java @@ -23,6 +23,7 @@ package catalog; import java.io.IOException; +import java.nio.file.Paths; import javax.xml.catalog.Catalog; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogFeatures; @@ -34,6 +35,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.testng.Assert; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.xml.sax.Attributes; @@ -44,10 +46,49 @@ import org.xml.sax.XMLReader; import org.xml.sax.ext.DefaultHandler2; /* - * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527 + * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527, 8154220 * @summary Tests basic Catalog functions. */ public class CatalogTest { + static final String KEY_FILES = "javax.xml.catalog.files"; + + public String filepath; + + /* + * Initializing fields + */ + @BeforeClass + public void setUpClass() throws Exception { + String file1 = getClass().getResource("first_cat.xml").getFile(); + if (System.getProperty("os.name").contains("Windows")) { + filepath = file1.substring(1, file1.lastIndexOf("/") + 1); + } else { + filepath = file1.substring(0, file1.lastIndexOf("/") + 1); + } + } + + /* + * @bug 8154220 + * Verifies that the file input is validated properly. Valid input includes + * multiple file paths separated by semicolon. + */ + @Test(dataProvider = "hierarchyOfCatFilesData") + public void hierarchyOfCatFiles2(String systemId, String expectedUri) { + String file1 = getClass().getResource("first_cat.xml").getFile(); + String file2 = getClass().getResource("second_cat.xml").getFile(); + String files = file1 + ";" + file2; + + try { + System.setProperty(KEY_FILES, files); + CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults()); + String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId(); + Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), "System ID match not right"); + } finally { + System.clearProperty(KEY_FILES); + } + + } + /* * @bug 8152527 * This test is the same as the JDK test ResolveEntityTests:testMatch1. @@ -288,6 +329,19 @@ public class CatalogTest { } } + /* + DataProvider: used to verify hierarchical catalogs. Refer to JCK test + hierarchyOfCatFiles2. + */ + @DataProvider(name = "hierarchyOfCatFilesData") + Object[][] getHierarchyOfCatFilesData() { + return new Object[][]{ + {"http://www.oracle.com/sequence.dtd", "first.dtd"}, + {"http://www.oracle.com/sequence_next.dtd", "next.dtd"}, + {"http://www.oracle.com/sequence_second.dtd", "second.dtd"} + }; + } + /* DataProvider: used to verify CatalogResolver's resolveEntity function. Data columns: @@ -300,6 +354,7 @@ public class CatalogTest { {"rewriteSystem_id.xml", "system", "http://www.sys00test.com/rewrite.dtd", "PUB-404", expected, expected, "Relative rewriteSystem with xml:base at group level failed"}, }; } + static String id = "http://openjdk.java.net/xml/catalog/dtd/system.dtd"; /* DataProvider: used to verify how prefer settings affect the result of the diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml new file mode 100644 index 00000000000..545be010596 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml new file mode 100644 index 00000000000..b8adc372248 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml b/jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml new file mode 100644 index 00000000000..c23bfc39abe --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 93a8bd38432584135ee12aaa9fda06ce9eb0e58c Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 28 Apr 2016 14:29:09 -0700 Subject: [PATCH 175/225] 8154801: deprecate Observer and Observable Reviewed-by: darcy --- .../share/classes/java/util/Observable.java | 14 +++++++++++++- .../share/classes/java/util/Observer.java | 7 ++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/Observable.java b/jdk/src/java.base/share/classes/java/util/Observable.java index cff9e1f4d7b..b19830bb64e 100644 --- a/jdk/src/java.base/share/classes/java/util/Observable.java +++ b/jdk/src/java.base/share/classes/java/util/Observable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, 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 @@ -58,7 +58,19 @@ package java.util; * @see java.util.Observer * @see java.util.Observer#update(java.util.Observable, java.lang.Object) * @since 1.0 + * + * @deprecated + * This class and the {@link Observer} interface have been deprecated. + * The event model supported by {@code Observer} and {@code Observable} + * is quite limited, the order of notifications delivered by + * {@code Observable} is unspecified, and state changes are not in + * one-for-one correspondence with notifications. + * For a richer event model, consider using the + * {@link java.beans} package. For reliable and ordered + * messaging among threads, consider using one of the concurrent data + * structures in the {@link java.util.concurrent} package. */ +@Deprecated(since="9") public class Observable { private boolean changed = false; private Vector obs; diff --git a/jdk/src/java.base/share/classes/java/util/Observer.java b/jdk/src/java.base/share/classes/java/util/Observer.java index 2db27b44a2d..47f793376ab 100644 --- a/jdk/src/java.base/share/classes/java/util/Observer.java +++ b/jdk/src/java.base/share/classes/java/util/Observer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 1998, 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 @@ -31,7 +31,12 @@ package java.util; * @author Chris Warth * @see java.util.Observable * @since 1.0 + * + * @deprecated + * This interface has been deprecated. See the {@link Observable} + * class for further information. */ +@Deprecated(since="9") public interface Observer { /** * This method is called whenever the observed object is changed. An From 766c5e26ae93431d850d392b0278d60237877c99 Mon Sep 17 00:00:00 2001 From: Frank Yuan Date: Thu, 28 Apr 2016 19:11:09 -0700 Subject: [PATCH 176/225] 8155514: jaxp.library.TestPolicy should extend the default security policy Reviewed-by: mchung, joehw --- jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java index 1e39fbc36eb..a1922a7cc51 100644 --- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java +++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java @@ -91,6 +91,7 @@ public class TestPolicy extends Policy { permissions.add(new PropertyPermission("line.separator", "read")); permissions.add(new PropertyPermission("fileStringBuffer", "read")); permissions.add(new PropertyPermission("dataproviderthreadcount", "read")); + permissions.add(new RuntimePermission("charsetProvider")); } /* From 9950f584d0fc339300eef9c76096756a37dc9f47 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Fri, 29 Apr 2016 01:45:35 -0400 Subject: [PATCH 177/225] 8155689: Build failing for install on jdk9/dev when using -testset hotspot Add installer target that aliases the expected target Reviewed-by: jmasa, tbell --- make/Main.gmk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/make/Main.gmk b/make/Main.gmk index 3d596817c08..43a6f755ec0 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -831,6 +831,10 @@ create-main-targets-include: ################################################################################ + +# workaround issue when building open targets when closed jib-profiles.js is used +installer: product-images test-image + .PHONY: $(ALL_TARGETS) FRC: # Force target From 46e74c829b39a54ddb44e105bd3d750412a5f9af Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Fri, 29 Apr 2016 11:56:31 +0200 Subject: [PATCH 178/225] 8155036: Remove sun.security.action.GetBooleanSecurityPropertyAction Reviewed-by: mullan, mchung, chegar --- .../GetBooleanSecurityPropertyAction.java | 74 ------------------- 1 file changed, 74 deletions(-) delete mode 100644 jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java diff --git a/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java b/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java deleted file mode 100644 index 9b180f1bdfd..00000000000 --- a/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2009, 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.security.action; - -import java.security.Security; - -/** - * A convenience class for retrieving the boolean value of a security property - * as a privileged action. - * - *

      An instance of this class can be used as the argument of - * AccessController.doPrivileged. - * - *

      The following code retrieves the boolean value of the security - * property named "prop" as a privileged action: - * - *

      - * boolean b = java.security.AccessController.doPrivileged
      - *              (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
      - * 
      - * - */ -public class GetBooleanSecurityPropertyAction - implements java.security.PrivilegedAction { - private String theProp; - - /** - * Constructor that takes the name of the security property whose boolean - * value needs to be determined. - * - * @param theProp the name of the security property - */ - public GetBooleanSecurityPropertyAction(String theProp) { - this.theProp = theProp; - } - - /** - * Determines the boolean value of the security property whose name was - * specified in the constructor. - * - * @return the Boolean value of the security property. - */ - public Boolean run() { - boolean b = false; - try { - String value = Security.getProperty(theProp); - b = (value != null) && value.equalsIgnoreCase("true"); - } catch (NullPointerException e) {} - return b; - } -} From a6f2cdbb0f6a6058eb3dac64dc08259fa594cfc3 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 29 Apr 2016 13:24:27 +0300 Subject: [PATCH 179/225] 8155090: String concatenation fails with a custom SecurityManager that uses concatenation Reviewed-by: redestad, chegar --- .../java/lang/invoke/StringConcatFactory.java | 12 ++++- .../String/concat/WithSecurityManager.java | 53 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/lang/String/concat/WithSecurityManager.java 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 44f29a4a136..f302c75af79 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 @@ -123,7 +123,7 @@ public final class StringConcatFactory { * Concatenation strategy to use. See {@link Strategy} for possible options. * This option is controllable with -Djava.lang.invoke.stringConcat JDK option. */ - private static final Strategy STRATEGY; + private static Strategy STRATEGY; /** * Default strategy to use for concatenation. @@ -187,6 +187,16 @@ public final class StringConcatFactory { private static final ProxyClassesDumper DUMPER; static { + // In case we need to double-back onto the StringConcatFactory during this + // static initialization, make sure we have the reasonable defaults to complete + // the static initialization properly. After that, actual users would use the + // the proper values we have read from the the properties. + STRATEGY = DEFAULT_STRATEGY; + // CACHE_ENABLE = false; // implied + // CACHE = null; // implied + // DEBUG = false; // implied + // DUMPER = null; // implied + Properties props = GetPropertyAction.getProperties(); final String strategy = props.getProperty("java.lang.invoke.stringConcat"); diff --git a/jdk/test/java/lang/String/concat/WithSecurityManager.java b/jdk/test/java/lang/String/concat/WithSecurityManager.java new file mode 100644 index 00000000000..17fc437ff3f --- /dev/null +++ b/jdk/test/java/lang/String/concat/WithSecurityManager.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, 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.security.Permission; + +/** + * @test + * @summary String concatenation fails with a custom SecurityManager that uses concatenation + * @bug 8155090 + * + * @compile WithSecurityManager.java + * + * @run main/othervm -Xverify:all WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT WithSecurityManager + * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT WithSecurityManager +*/ +public class WithSecurityManager { + public static void main(String[] args) throws Throwable { + SecurityManager sm = new SecurityManager() { + @Override + public void checkPermission(Permission perm) { + String abc = "abc"; + String full = abc + "def"; + } + }; + System.setSecurityManager(sm); + ClassLoader cl = new ClassLoader() {}; + } +} From 6db653621d80697ea9f0c9863f9d4897dee7a08f Mon Sep 17 00:00:00 2001 From: "Tagir F. Valeev" Date: Fri, 29 Apr 2016 16:52:05 +0300 Subject: [PATCH 180/225] 8155600: Performance optimization of Arrays.asList().iterator() Reviewed-by: redestad, shade, plevart, attila --- .../share/classes/java/util/Arrays.java | 31 ++++++- jdk/test/java/util/Arrays/AsList.java | 93 +++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/util/Arrays/AsList.java diff --git a/jdk/src/java.base/share/classes/java/util/Arrays.java b/jdk/src/java.base/share/classes/java/util/Arrays.java index cc7b19de64e..6d7e858fbed 100644 --- a/jdk/src/java.base/share/classes/java/util/Arrays.java +++ b/jdk/src/java.base/share/classes/java/util/Arrays.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 @@ -4403,6 +4403,35 @@ public class Arrays { public void sort(Comparator c) { Arrays.sort(a, c); } + + @Override + public Iterator iterator() { + return new ArrayItr<>(a); + } + } + + private static class ArrayItr implements Iterator { + private int cursor; + private final E[] a; + + ArrayItr(E[] a) { + this.a = a; + } + + @Override + public boolean hasNext() { + return cursor < a.length; + } + + @Override + public E next() { + int i = cursor; + if (i >= a.length) { + throw new NoSuchElementException(); + } + cursor = i + 1; + return a[i]; + } } /** diff --git a/jdk/test/java/util/Arrays/AsList.java b/jdk/test/java/util/Arrays/AsList.java new file mode 100644 index 00000000000..c64c473a822 --- /dev/null +++ b/jdk/test/java/util/Arrays/AsList.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. + * + * 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 8155600 + * @summary Tests for Arrays.asList() + * @run testng AsList + */ + +import java.util.Arrays; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.stream.IntStream; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; + +public class AsList { + /* + * Iterator contract test + */ + @Test(dataProvider = "Arrays") + public void testIterator(Object[] array) { + Iterator itr = Arrays.asList(array).iterator(); + for (int i = 0; i < array.length; i++) { + assertTrue(itr.hasNext()); + assertTrue(itr.hasNext()); // must be idempotent + assertSame(array[i], itr.next()); + try { + itr.remove(); + fail("Remove must throw"); + } catch (UnsupportedOperationException ex) { + // expected + } + } + assertFalse(itr.hasNext()); + for (int i = 0; i < 3; i++) { + assertFalse(itr.hasNext()); + try { + itr.next(); + fail("Next succeed when there's no data left"); + } catch (NoSuchElementException ex) { + // expected + } + } + } + + @DataProvider(name = "Arrays") + public static Object[][] arrays() { + Object[][] arrays = { + { new Object[] { } }, + { new Object[] { 1 } }, + { new Object[] { null } }, + { new Object[] { null, 1 } }, + { new Object[] { 1, null } }, + { new Object[] { null, null } }, + { new Object[] { null, 1, 2 } }, + { new Object[] { 1, null, 2 } }, + { new Object[] { 1, 2, null } }, + { new Object[] { null, null, null } }, + { new Object[] { 1, 2, 3, null, 4 } }, + { new Object[] { "a", "a", "a", "a" } }, + { IntStream.range(0, 100).boxed().toArray() } + }; + + return arrays; + } +} From 88fc3658cc381b176adfe1028fb431a8e31cf1c9 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 29 Apr 2016 09:45:46 -0700 Subject: [PATCH 181/225] 8155606: [PIT] Robot's createScreenCapture() broken on Linux Reviewed-by: prr --- jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c index 91ad2515a8a..0e06972207f 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c @@ -265,7 +265,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env, if (isGtkSupported) { gtk->gdk_threads_enter(); gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width, - jwidth, height, dx, dy, scale); + height, jwidth, dx, dy, scale); gtk->gdk_threads_leave(); } From 6ec92b138948df30276c9d99ce2dafea89e9db46 Mon Sep 17 00:00:00 2001 From: Semyon Sadetsky Date: Fri, 29 Apr 2016 09:46:14 -0700 Subject: [PATCH 182/225] 8155613: [PIT] crash in AWT_Desktop/Automated/Exceptions/BasicTest Reviewed-by: prr --- .../java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c | 1 + .../java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c | 1 + 2 files changed, 2 insertions(+) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index 672a8414d8d..42408da5bbb 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -442,6 +442,7 @@ static gboolean gtk2_show_uri_load(JNIEnv *env) { fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); #endif /* DEBUG */ } else { + gtk->gtk_show_uri = fp_gtk_show_uri; update_supported_actions(env); success = TRUE; } diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index 385c8015046..6a188fb3598 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -195,6 +195,7 @@ static gboolean gtk3_show_uri_load(JNIEnv *env) { fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); #endif /* DEBUG */ } else { + gtk->gtk_show_uri = fp_gtk_show_uri; update_supported_actions(env); success = TRUE; } From 528b2cc81a583705fd00075aa465256cd306be09 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 29 Apr 2016 15:17:46 -0400 Subject: [PATCH 183/225] 8155727: java/util/concurrent/locks/Lock/TimedAcquireLeak.java timeouts Fix regex pattern to handle possible (module@version) text Reviewed-by: ctornqvi, martin --- .../java/util/concurrent/locks/Lock/TimedAcquireLeak.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java index 7d6da0b255e..630f3796b8c 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java +++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, 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 @@ -167,7 +167,7 @@ public class TimedAcquireLeak { final String childPid, final String className) { final String regex = - "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E$"; + "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E(?:$| )"; final Callable objectsInUse = new Callable() { public Integer call() { Integer i = Integer.parseInt( From 4d3fe6b205091c212e089187909131de0f324706 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 29 Apr 2016 23:15:15 +0300 Subject: [PATCH 184/225] 8155215: java.lang.String concatenation spec is unnecessarily strong Reviewed-by: abuckley, sherman, chegar --- .../share/classes/java/lang/String.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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 a1772977727..64299b92337 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -78,14 +78,8 @@ import jdk.internal.vm.annotation.Stable; *

      * The Java language provides special support for the string * concatenation operator ( + ), and for conversion of - * other objects to strings. String concatenation is implemented - * through the {@code StringBuilder}(or {@code StringBuffer}) - * class and its {@code append} method. - * String conversions are implemented through the method - * {@code toString}, defined by {@code Object} and - * inherited by all classes in Java. For additional information on - * string concatenation and conversion, see Gosling, Joy, and Steele, - * The Java Language Specification. + * other objects to strings. For additional information on string + * concatenation and conversion, see The Java™ Language Specification. * *

      Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be @@ -106,6 +100,14 @@ import jdk.internal.vm.annotation.Stable; * into account. The {@link java.text.Collator} class provides methods for * finer-grain, locale-sensitive String comparison. * + * @implNote The implementation of the string concatenation operator is left to + * the discretion of a Java compiler, as long as the compiler ultimately conforms + * to The Java™ Language Specification. For example, the {@code javac} compiler + * may implement the operator with {@code StringBuffer}, {@code StringBuilder}, + * or {@code java.lang.invoke.StringConcatFactory} depending on the JDK version. The + * implementation of string conversion is typically through the method {@code toString}, + * defined by {@code Object} and inherited by all classes in Java. + * * @author Lee Boynton * @author Arthur van Hoff * @author Martin Buchholz From e955660cf18082234159590fef00f6d507db2db8 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Fri, 29 Apr 2016 13:46:19 -0700 Subject: [PATCH 185/225] 8154755: Add a VarHandle weakCompareAndSet with volatile semantics Reviewed-by: shade, vlivanov --- .../classes/java/lang/invoke/VarHandle.java | 136 ++++++++++++------ .../lang/invoke/X-VarHandle.java.template | 32 +++++ .../X-VarHandleByteArrayView.java.template | 20 +++ .../invoke/VarHandles/VarHandleBaseTest.java | 1 + .../VarHandleTestAccessBoolean.java | 21 +++ .../VarHandles/VarHandleTestAccessByte.java | 21 +++ .../VarHandles/VarHandleTestAccessChar.java | 21 +++ .../VarHandles/VarHandleTestAccessDouble.java | 21 +++ .../VarHandles/VarHandleTestAccessFloat.java | 21 +++ .../VarHandles/VarHandleTestAccessInt.java | 46 ++++-- .../VarHandles/VarHandleTestAccessLong.java | 46 ++++-- .../VarHandles/VarHandleTestAccessShort.java | 21 +++ .../VarHandles/VarHandleTestAccessString.java | 46 ++++-- .../VarHandleTestByteArrayAsChar.java | 13 ++ .../VarHandleTestByteArrayAsDouble.java | 47 +++++- .../VarHandleTestByteArrayAsFloat.java | 47 +++++- .../VarHandleTestByteArrayAsInt.java | 51 +++++-- .../VarHandleTestByteArrayAsLong.java | 47 +++++- .../VarHandleTestByteArrayAsShort.java | 13 ++ .../VarHandleTestMethodHandleAccessInt.java | 41 ++++-- .../VarHandleTestMethodHandleAccessLong.java | 41 ++++-- ...VarHandleTestMethodHandleAccessString.java | 41 ++++-- .../VarHandleTestMethodTypeInt.java | 72 ++++++++++ .../VarHandleTestMethodTypeLong.java | 72 ++++++++++ .../VarHandleTestMethodTypeString.java | 72 ++++++++++ .../X-VarHandleTestAccess.java.template | 67 +++++++-- ...X-VarHandleTestByteArrayView.java.template | 60 +++++++- ...HandleTestMethodHandleAccess.java.template | 41 ++++-- .../X-VarHandleTestMethodType.java.template | 72 ++++++++++ 29 files changed, 1098 insertions(+), 152 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java index cf869b3ebe7..4eb7f260a6c 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -136,6 +136,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; * consists of the methods * {@link #compareAndSet compareAndSet}, * {@link #weakCompareAndSet weakCompareAndSet}, + * {@link #weakCompareAndSetVolatile weakCompareAndSetVolatile}, * {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire}, * {@link #weakCompareAndSetRelease weakCompareAndSetRelease}, * {@link #compareAndExchangeAcquire compareAndExchangeAcquire}, @@ -458,7 +459,7 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code get} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.get)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET)} on this VarHandle. * *

      This access mode is supported by all VarHandle instances and never * throws {@code UnsupportedOperationException}. @@ -488,7 +489,7 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code set} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.set)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.SET)} on this VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T newValue)} @@ -516,7 +517,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code getVolatile} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.getVolatile)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET_VOLATILE)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT)} @@ -544,7 +546,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code setVolatile} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.setVolatile)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.SET_VOLATILE)} on this + * VarHandle. * * @apiNote * Ignoring the many semantic differences from C and C++, this method has @@ -574,7 +577,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code getOpaque} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.getOpaque)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET_OPAQUE)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT)} @@ -603,7 +607,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code setOpaque} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.setOpaque)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.SET_OPAQUE)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T newValue)} @@ -631,7 +636,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code getAcquire} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.getAcquire)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET_ACQUIRE)} on this + * VarHandle. * * @apiNote * Ignoring the many semantic differences from C and C++, this method has @@ -664,7 +670,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code setRelease} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.setRelease)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.SET_RELEASE)} on this + * VarHandle. * * @apiNote * Ignoring the many semantic differences from C and C++, this method has @@ -700,7 +707,7 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code * compareAndSet} must match the access mode type that is the result of - * calling {@code accessModeType(VarHandle.AccessMode.compareAndSet)} on + * calling {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_SET)} on * this VarHandle. * * @param args the signature-polymorphic parameter list of the form @@ -734,7 +741,7 @@ public abstract class VarHandle { *

      The symbolic type descriptor at the call site of {@code * compareAndExchangeVolatile} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeVolatile)} + * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)} * on this VarHandle. * * @param args the signature-polymorphic parameter list of the form @@ -769,7 +776,7 @@ public abstract class VarHandle { *

      The symbolic type descriptor at the call site of {@code * compareAndExchangeAcquire} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeAcquire)} on + * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)} on * this VarHandle. * * @param args the signature-polymorphic parameter list of the form @@ -804,7 +811,8 @@ public abstract class VarHandle { *

      The symbolic type descriptor at the call site of {@code * compareAndExchangeRelease} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeRelease)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)} + * on this VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T expectedValue, T newValue)} @@ -836,14 +844,14 @@ public abstract class VarHandle { * {@link #get}. * *

      This operation may fail spuriously (typically, due to memory - * contention) even if the current value does match the expected value. + * contention) even if the witness value does match the expected value. * *

      The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}. * *

      The symbolic type descriptor at the call site of {@code * weakCompareAndSet} must match the access mode type that is the result of - * calling {@code accessModeType(VarHandle.AccessMode.weakCompareAndSet)} on - * this VarHandle. + * calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)} + * on this VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T expectedValue, T newValue)} @@ -865,6 +873,43 @@ public abstract class VarHandle { @HotSpotIntrinsicCandidate boolean weakCompareAndSet(Object... args); + /** + * Possibly atomically sets the value of a variable to the {@code newValue} + * with the memory semantics of {@link #setVolatile} if the variable's + * current value, referred to as the witness value, {@code ==} the + * {@code expectedValue}, as accessed with the memory semantics of + * {@link #getVolatile}. + * + *

      This operation may fail spuriously (typically, due to memory + * contention) even if the witness value does match the expected value. + * + *

      The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}. + * + *

      The symbolic type descriptor at the call site of {@code + * weakCompareAndSetVolatile} must match the access mode type that is the + * result of calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)} + * on this VarHandle. + * + * @param args the signature-polymorphic parameter list of the form + * {@code (CT, T expectedValue, T newValue)} + * , statically represented using varargs. + * @return {@code true} if successful, otherwise {@code false} if the + * witness value was not the same as the {@code expectedValue} or if this + * operation spuriously failed. + * @throws UnsupportedOperationException if the access mode is unsupported + * for this VarHandle. + * @throws WrongMethodTypeException if the access mode type is not + * compatible with the caller's symbolic type descriptor. + * @throws ClassCastException if the access mode type is compatible with the + * caller's symbolic type descriptor, but a reference cast fails. + * @see #setVolatile(Object...) + * @see #getVolatile(Object...) + */ + public final native + @MethodHandle.PolymorphicSignature + @HotSpotIntrinsicCandidate + boolean weakCompareAndSetVolatile(Object... args); + /** * Possibly atomically sets the value of a variable to the {@code newValue} * with the semantics of {@link #set} if the variable's current value, @@ -873,14 +918,15 @@ public abstract class VarHandle { * {@link #getAcquire}. * *

      This operation may fail spuriously (typically, due to memory - * contention) even if the current value does match the expected value. + * contention) even if the witness value does match the expected value. * *

      The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}. * *

      The symbolic type descriptor at the call site of {@code * weakCompareAndSetAcquire} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetAcquire)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)} + * on this VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T expectedValue, T newValue)} @@ -910,14 +956,15 @@ public abstract class VarHandle { * {@link #get}. * *

      This operation may fail spuriously (typically, due to memory - * contention) even if the current value does match the expected value. + * contention) even if the witness value does match the expected value. * *

      The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}. * *

      The symbolic type descriptor at the call site of {@code * weakCompareAndSetRelease} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetRelease)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)} + * on this VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T expectedValue, T newValue)} @@ -949,7 +996,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code getAndSet} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.getAndSet)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET_AND_SET)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T newValue)} @@ -985,7 +1033,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code getAndAdd} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.getAndAdd)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.GET_AND_ADD)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T value)} @@ -1017,7 +1066,8 @@ public abstract class VarHandle { * *

      The symbolic type descriptor at the call site of {@code addAndGet} * must match the access mode type that is the result of calling - * {@code accessModeType(VarHandle.AccessMode.addAndGet)} on this VarHandle. + * {@code accessModeType(VarHandle.AccessMode.ADD_AND_GET)} on this + * VarHandle. * * @param args the signature-polymorphic parameter list of the form * {@code (CT, T value)} @@ -1083,109 +1133,115 @@ public abstract class VarHandle { * method * {@link VarHandle#get VarHandle.get} */ - GET("get", AccessType.GET, Object.class), // 0 + GET("get", AccessType.GET, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#set VarHandle.set} */ - SET("set", AccessType.SET, void.class), // 1 + SET("set", AccessType.SET, void.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#getVolatile VarHandle.getVolatile} */ - GET_VOLATILE("getVolatile", AccessType.GET, Object.class), // 2 + GET_VOLATILE("getVolatile", AccessType.GET, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#setVolatile VarHandle.setVolatile} */ - SET_VOLATILE("setVolatile", AccessType.SET, void.class), // 3 + SET_VOLATILE("setVolatile", AccessType.SET, void.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#getAcquire VarHandle.getAcquire} */ - GET_ACQUIRE("getAcquire", AccessType.GET, Object.class), // 4 + GET_ACQUIRE("getAcquire", AccessType.GET, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#setRelease VarHandle.setRelease} */ - SET_RELEASE("setRelease", AccessType.SET, void.class), // 5 + SET_RELEASE("setRelease", AccessType.SET, void.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#getOpaque VarHandle.getOpaque} */ - GET_OPAQUE("getOpaque", AccessType.GET, Object.class), // 6 + GET_OPAQUE("getOpaque", AccessType.GET, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#setOpaque VarHandle.setOpaque} */ - SET_OPAQUE("setOpaque", AccessType.SET, void.class), // 7 + SET_OPAQUE("setOpaque", AccessType.SET, void.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#compareAndSet VarHandle.compareAndSet} */ - COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), // 8 + COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile} */ - COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 9 + COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire} */ - COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 10 + COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease} */ - COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 11 + COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet} */ - WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), // 12 + WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), + /** + * The access mode whose access is specified by the corresponding + * method + * {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile} + */ + WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire} */ - WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class), // 13 + WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease} */ - WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class), // 14 + WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#getAndSet VarHandle.getAndSet} */ - GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class), // 15 + GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#getAndAdd VarHandle.getAndAdd} */ - GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class), // 16 + GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class), /** * The access mode whose access is specified by the corresponding * method * {@link VarHandle#addAndGet VarHandle.addAndGet} */ - ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class), // 17 + ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class), ; static final Map methodNameToAccessMode; diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index bcec64bd390..4a9d9e11e36 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -154,6 +154,15 @@ final class VarHandle$Type$s { {#if[Object]?handle.fieldType.cast(value):value}); } + @ForceInline + static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) { + // TODO defer to strong form until new Unsafe method is added + return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)), + handle.fieldOffset, + {#if[Object]?handle.fieldType.cast(expected):expected}, + {#if[Object]?handle.fieldType.cast(value):value}); + } + @ForceInline static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) { return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)), @@ -318,6 +327,15 @@ final class VarHandle$Type$s { {#if[Object]?handle.fieldType.cast(value):value}); } + @ForceInline + static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) { + // TODO defer to strong form until new Unsafe method is added + return UNSAFE.compareAndSwap$Type$(handle.base, + handle.fieldOffset, + {#if[Object]?handle.fieldType.cast(expected):expected}, + {#if[Object]?handle.fieldType.cast(value):value}); + } + @ForceInline static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) { return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base, @@ -534,6 +552,20 @@ final class VarHandle$Type$s { {#if[Object]?handle.componentType.cast(value):value}); } + @ForceInline + static boolean weakCompareAndSetVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) { +#if[Object] + Object[] array = (Object[]) handle.arrayType.cast(oarray); +#else[Object] + $type$[] array = ($type$[]) oarray; +#end[Object] + // TODO defer to strong form until new Unsafe method is added + return UNSAFE.compareAndSwap$Type$(array, + (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + {#if[Object]?handle.componentType.cast(expected):expected}, + {#if[Object]?handle.componentType.cast(value):value}); + } + @ForceInline static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) { #if[Object] diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index bdc77a820d2..b5bf9cba232 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -227,6 +227,16 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { convEndian(handle.be, expected), convEndian(handle.be, value)); } + @ForceInline + static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) { + byte[] ba = (byte[]) oba; + // TODO defer to strong form until new Unsafe method is added + return UNSAFE.compareAndSwap$RawType$( + ba, + address(ba, index(ba, index)), + convEndian(handle.be, expected), convEndian(handle.be, value)); + } + @ForceInline static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) { byte[] ba = (byte[]) oba; @@ -443,6 +453,16 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { convEndian(handle.be, expected), convEndian(handle.be, value)); } + @ForceInline + static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) { + ByteBuffer bb = (ByteBuffer) obb; + // TODO defer to strong form until new Unsafe method is added + return UNSAFE.compareAndSwap$RawType$( + UNSAFE.getObject(bb, BYTE_BUFFER_HB), + address(bb, indexRO(bb, index)), + convEndian(handle.be, expected), convEndian(handle.be, value)); + } + @ForceInline static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) { ByteBuffer bb = (ByteBuffer) obb; diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java index 241d821c00a..59737dbeb7b 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java @@ -148,6 +148,7 @@ abstract class VarHandleBaseTest { COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE), COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE), WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET), + WEAK_COMPARE_AND_SET_VOLATILE(TestAccessType.COMPARE_AND_SET), WEAK_COMPARE_AND_SET_ACQUIRE(TestAccessType.COMPARE_AND_SET), WEAK_COMPARE_AND_SET_RELEASE(TestAccessType.COMPARE_AND_SET), GET_AND_SET(TestAccessType.GET_AND_SET), diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index b22fc3e182a..021091484e6 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, true, false); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, true, false); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, true, false); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(true, false); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(true, false); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(true, false); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, true, false); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, true, false); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, true, false); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(true, false); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(true, false); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(true, false); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, true, false); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, true, false); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, true, false); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index 088a519e920..e550815156c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet((byte)1, (byte)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet((byte)1, (byte)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, (byte)1, (byte)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, (byte)1, (byte)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index 18ff6542615..5c13c6d6677 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 'a', 'b'); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b'); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b'); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet('a', 'b'); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile('a', 'b'); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire('a', 'b'); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 'a', 'b'); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b'); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b'); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet('a', 'b'); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile('a', 'b'); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire('a', 'b'); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, 'a', 'b'); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, 'a', 'b'); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b'); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index 36c84e2f753..65125e3f62e 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(1.0d, 2.0d); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(1.0d, 2.0d); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, 1.0d, 2.0d); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0d, 2.0d); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0d, 2.0d); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 2ea2d9617be..8e7491ad45a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(1.0f, 2.0f); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(1.0f, 2.0f); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, 1.0f, 2.0f); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0f, 2.0f); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0f, 2.0f); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index 0c3d8d5c841..bfcb5feec4c 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -421,12 +422,19 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = vh.weakCompareAndSetVolatile(recv, 2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) vh.get(recv); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) vh.getAndSet(recv, 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) vh.getAndSet(recv, 2); + assertEquals(o, 1, "getAndSet int"); int x = (int) vh.get(recv); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } vh.set(recv, 1); @@ -549,18 +557,25 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2); + boolean r = (boolean) vh.weakCompareAndSetRelease(1, 2); assertEquals(r, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = (boolean) vh.weakCompareAndSetVolatile(2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) vh.get(); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) vh.getAndSet( 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) vh.getAndSet( 2); + assertEquals(o, 1, "getAndSet int"); int x = (int) vh.get(); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } vh.set(1); @@ -692,12 +707,19 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, 2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) vh.get(array, i); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) vh.getAndSet(array, i, 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) vh.getAndSet(array, i, 2); + assertEquals(o, 1, "getAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } vh.set(array, i, 1); @@ -777,6 +799,10 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, ci, 1, 2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, 1, 2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, 1, 2); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index a034a536468..1f02bed9045 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -421,12 +422,19 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = vh.weakCompareAndSetVolatile(recv, 2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) vh.get(recv); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) vh.getAndSet(recv, 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) vh.getAndSet(recv, 2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) vh.get(recv); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } vh.set(recv, 1L); @@ -549,18 +557,25 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L); + boolean r = (boolean) vh.weakCompareAndSetRelease(1L, 2L); assertEquals(r, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = (boolean) vh.weakCompareAndSetVolatile(2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) vh.get(); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) vh.getAndSet( 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) vh.getAndSet( 2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) vh.get(); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } vh.set(1L); @@ -692,12 +707,19 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, 2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) vh.get(array, i); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) vh.getAndSet(array, i, 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) vh.getAndSet(array, i, 2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } vh.set(array, i, 1L); @@ -777,6 +799,10 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, ci, 1L, 2L); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, 1L, 2L); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, 1L, 2L); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index 4ff25cc4a5f..822252f7a7d 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -279,6 +280,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2); }); @@ -361,6 +366,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet((short)1, (short)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2); }); @@ -433,6 +442,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2); }); @@ -505,6 +518,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet((short)1, (short)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2); }); @@ -584,6 +601,10 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, (short)1, (short)2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, (short)1, (short)2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, (short)1, (short)2); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 4272c898a4c..9e4ec77768b 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -104,6 +104,7 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -435,12 +436,19 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = vh.weakCompareAndSetVolatile(recv, "bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) vh.get(recv); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) vh.getAndSet(recv, "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) vh.getAndSet(recv, "bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) vh.get(recv); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } @@ -561,18 +569,25 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar"); + boolean r = (boolean) vh.weakCompareAndSetRelease("foo", "bar"); assertEquals(r, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = (boolean) vh.weakCompareAndSetVolatile("bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) vh.get(); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) vh.getAndSet( "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) vh.getAndSet( "bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) vh.get(); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } @@ -702,12 +717,19 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, "bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) vh.get(array, i); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) vh.getAndSet(array, i, "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) vh.getAndSet(array, i, "bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) vh.get(array, i); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } @@ -785,6 +807,10 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, ci, "foo", "bar"); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, "foo", "bar"); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar"); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index c46720b738a..8159e16ff62 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -203,6 +204,10 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -264,6 +269,10 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -305,6 +314,10 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index 9cee7930dee..a327b00fb77 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -238,6 +239,10 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkROBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkROBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -333,6 +338,10 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -414,6 +423,10 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -486,6 +499,10 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -561,6 +578,10 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -699,12 +720,19 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value"); + } + // Compare set and get { - double o = (double) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet double"); + double o = (double) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet double value"); + assertEquals(x, VALUE_2, "getAndSet double value"); } } @@ -832,12 +860,19 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile double"); + double x = (double) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value"); + } + // Compare set and get { - double o = (double) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet double"); + double o = (double) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet double"); double x = (double) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet double value"); + assertEquals(x, VALUE_2, "getAndSet double value"); } } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index e366e84c239..196c8101723 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -238,6 +239,10 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkROBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkROBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -333,6 +338,10 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -414,6 +423,10 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -486,6 +499,10 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -561,6 +578,10 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -699,12 +720,19 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value"); + } + // Compare set and get { - float o = (float) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet float"); + float o = (float) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet float value"); + assertEquals(x, VALUE_2, "getAndSet float value"); } } @@ -832,12 +860,19 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile float"); + float x = (float) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value"); + } + // Compare set and get { - float o = (float) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet float"); + float o = (float) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet float"); float x = (float) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet float value"); + assertEquals(x, VALUE_2, "getAndSet float value"); } } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index 2831fa63210..400c20605c5 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -38,10 +38,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; +import static org.testng.Assert.*; public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { static final int SIZE = Integer.BYTES; @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -231,6 +232,10 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkROBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkROBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -319,6 +324,10 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -407,6 +416,10 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -486,6 +499,10 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -568,6 +585,10 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -713,12 +734,19 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet int"); + int o = (int) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet int value"); + assertEquals(x, VALUE_2, "getAndSet int value"); } vh.set(array, i, VALUE_1); @@ -855,12 +883,19 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet int"); + int o = (int) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet int"); int x = (int) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet int value"); + assertEquals(x, VALUE_2, "getAndSet int value"); } vh.set(array, i, VALUE_1); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index 263245a5e72..a0cabc8653a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -231,6 +232,10 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkROBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkROBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -319,6 +324,10 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -407,6 +416,10 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -486,6 +499,10 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -568,6 +585,10 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -713,12 +734,19 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet long"); + long o = (long) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet long value"); + assertEquals(x, VALUE_2, "getAndSet long value"); } vh.set(array, i, VALUE_1); @@ -855,12 +883,19 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet long"); + long o = (long) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet long"); long x = (long) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet long value"); + assertEquals(x, VALUE_2, "getAndSet long value"); } vh.set(array, i, VALUE_1); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 3d6078e6056..2632b00bd23 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -93,6 +93,7 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -203,6 +204,10 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -264,6 +269,10 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -305,6 +314,10 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java index 4e8de0c3bc8..8ccf7983056 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java @@ -228,12 +228,19 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2); + assertEquals(o, 1, "getAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } hs.get(TestAccessMode.SET).invokeExact(recv, 1); @@ -356,18 +363,25 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1, 2); + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2); assertEquals(r, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2); + assertEquals(o, 1, "getAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } hs.get(TestAccessMode.SET).invokeExact(1); @@ -499,12 +513,19 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { assertEquals(x, 2, "weakCompareAndSetRelease int"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1); + assertEquals(r, true, "weakCompareAndSetVolatile int"); + int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1, "weakCompareAndSetVolatile int value"); + } + // Compare set and get { - int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1); - assertEquals(o, 2, "getAndSet int"); + int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2); + assertEquals(o, 1, "getAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1, "getAndSet int value"); + assertEquals(x, 2, "getAndSet int value"); } hs.get(TestAccessMode.SET).invokeExact(array, i, 1); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java index 05efd70079b..65493ec2b49 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java @@ -228,12 +228,19 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } hs.get(TestAccessMode.SET).invokeExact(recv, 1L); @@ -356,18 +363,25 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1L, 2L); + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L); assertEquals(r, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } hs.get(TestAccessMode.SET).invokeExact(1L); @@ -499,12 +513,19 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { assertEquals(x, 2L, "weakCompareAndSetRelease long"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L); + assertEquals(r, true, "weakCompareAndSetVolatile long"); + long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, 1L, "weakCompareAndSetVolatile long value"); + } + // Compare set and get { - long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1L); - assertEquals(o, 2L, "getAndSet long"); + long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2L); + assertEquals(o, 1L, "getAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, 1L, "getAndSet long value"); + assertEquals(x, 2L, "getAndSet long value"); } hs.get(TestAccessMode.SET).invokeExact(array, i, 1L); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java index 62ef4ae7f37..5ae7c877854 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java @@ -228,12 +228,19 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } @@ -352,18 +359,25 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( "foo", "bar"); + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar"); assertEquals(r, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact( "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } @@ -491,12 +505,19 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { assertEquals(x, "bar", "weakCompareAndSetRelease String"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo"); + assertEquals(r, true, "weakCompareAndSetVolatile String"); + String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, "foo", "weakCompareAndSetVolatile String value"); + } + // Compare set and get { - String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "foo"); - assertEquals(o, "bar", "getAndSet String"); + String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar"); + assertEquals(o, "foo", "getAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, "foo", "getAndSet String value"); + assertEquals(x, "bar", "getAndSet String value"); } } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java index 0a41906c4a5..13b6b0607b0 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java @@ -374,6 +374,32 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 1, 1); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 1, 1); + }); + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(recv, 1, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 1, 1); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(recv, 1, 1, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver @@ -972,6 +998,23 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 1); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(1, Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(1, 1, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkWMTE(() -> { // expected reference class @@ -1566,6 +1609,35 @@ public class VarHandleTestMethodTypeInt extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 0, 1, 1); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1, 1); + }); + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 0, 1, 1); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1, 1); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, 1, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java index f520a619a20..44151683133 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java @@ -374,6 +374,32 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 1L, 1L); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L, 1L); + }); + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1L); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(recv, 1L, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 1L, 1L); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(recv, 1L, 1L, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver @@ -972,6 +998,23 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(1L, Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(1L, 1L, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkWMTE(() -> { // expected reference class @@ -1566,6 +1609,35 @@ public class VarHandleTestMethodTypeLong extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 0, 1L, 1L); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1L, 1L); + }); + checkWMTE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1L); + }); + checkWMTE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 0, 1L, 1L); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1L, 1L); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, 1L, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java index 674cc10a236..f3b58c9e2f9 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java @@ -374,6 +374,32 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, "foo", "foo"); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo", "foo"); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, "foo"); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(recv, "foo", Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, "foo", "foo"); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(recv, "foo", "foo", Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver @@ -878,6 +904,23 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo"); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile("foo", Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile("foo", "foo", Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkCCE(() -> { // expected reference class @@ -1407,6 +1450,35 @@ public class VarHandleTestMethodTypeString extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 0, "foo", "foo"); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, "foo", "foo"); + }); + checkCCE(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, "foo"); + }); + checkCCE(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 0, "foo", "foo"); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetVolatile(array, Void.class, "foo", "foo"); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", "foo", Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index fb44c8bbb2b..391dc1a5197 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -105,6 +105,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -114,6 +115,7 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -296,6 +298,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$); }); @@ -382,6 +388,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet($value1$, $value2$); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$); }); @@ -514,12 +524,19 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) vh.get(recv); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) vh.getAndSet(recv, $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) vh.getAndSet(recv, $value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) vh.get(recv); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] @@ -558,6 +575,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$); }); @@ -684,18 +705,25 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSetRelease( $value1$, $value2$); + boolean r = (boolean) vh.weakCompareAndSetRelease($value1$, $value2$); assertEquals(r, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = (boolean) vh.weakCompareAndSetVolatile($value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) vh.get(); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) vh.getAndSet( $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) vh.getAndSet( $value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) vh.get(); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] @@ -734,6 +762,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet($value1$, $value2$); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$); }); @@ -869,12 +901,19 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) vh.getAndSet(array, i, $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) vh.getAndSet(array, i, $value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] @@ -917,6 +956,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, i, $value1$, $value2$); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, i, $value1$, $value2$); }); @@ -996,6 +1039,10 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { boolean r = vh.weakCompareAndSet(array, ci, $value1$, $value2$); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, $value1$, $value2$); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, $value1$, $value2$); }); diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 4cdf45bad80..e433789f8cd 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -94,6 +94,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -103,6 +104,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); + assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); @@ -220,6 +222,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -290,6 +296,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkROBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkROBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -321,6 +331,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -374,6 +388,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkUOE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkUOE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -460,6 +478,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -552,6 +574,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkIOOBE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkIOOBE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -635,6 +661,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -721,6 +751,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2); }); + checkISE(() -> { + boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2); + }); + checkISE(() -> { boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2); }); @@ -870,12 +904,19 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet $type$"); + $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet $type$ value"); + assertEquals(x, VALUE_2, "getAndSet $type$ value"); } #end[CAS] @@ -1016,12 +1057,19 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } + { + boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) vh.get(array, i); + assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1); - assertEquals(o, VALUE_2, "getAndSet $type$"); + $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2); + assertEquals(o, VALUE_1, "getAndSet $type$"); $type$ x = ($type$) vh.get(array, i); - assertEquals(x, VALUE_1, "getAndSet $type$ value"); + assertEquals(x, VALUE_2, "getAndSet $type$ value"); } #end[CAS] diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template index 8e40761a4f3..f56d9a641a7 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template @@ -229,12 +229,19 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] @@ -387,18 +394,25 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( $value1$, $value2$); + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$); assertEquals(r, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact( $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] @@ -560,12 +574,19 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } + { + boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$); + assertEquals(r, true, "weakCompareAndSetVolatile $type$"); + $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); + assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value"); + } + // Compare set and get { - $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value1$); - assertEquals(o, $value2$, "getAndSet $type$"); + $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value2$); + assertEquals(o, $value1$, "getAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); - assertEquals(x, $value1$, "getAndSet $type$ value"); + assertEquals(x, $value2$, "getAndSet $type$ value"); } #end[CAS] diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template index 98e4698c4e4..fe504902f10 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template @@ -375,6 +375,32 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, $value1$, $value1$); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$, $value1$); + }); + check{#if[String]?CCE:WMTE}(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, $value1$); + }); + check{#if[String]?CCE:WMTE}(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, $value1$, $value1$); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value1$, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver @@ -981,6 +1007,23 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + check{#if[String]?CCE:WMTE}(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$); + }); + check{#if[String]?CCE:WMTE}(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile($value1$, Void.class); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile($value1$, $value1$, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types check{#if[String]?CCE:WMTE}(() -> { // expected reference class @@ -1583,6 +1626,35 @@ public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest { }); + // WeakCompareAndSetVolatile + // Incorrect argument types + checkNPE(() -> { // null receiver + boolean r = vh.weakCompareAndSetVolatile(null, 0, $value1$, $value1$); + }); + checkCCE(() -> { // receiver reference class + boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, $value1$, $value1$); + }); + check{#if[String]?CCE:WMTE}(() -> { // expected reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, $value1$); + }); + check{#if[String]?CCE:WMTE}(() -> { // actual reference class + boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, Void.class); + }); + checkWMTE(() -> { // receiver primitive class + boolean r = vh.weakCompareAndSetVolatile(0, 0, $value1$, $value1$); + }); + checkWMTE(() -> { // index reference class + boolean r = vh.weakCompareAndSetVolatile(array, Void.class, $value1$, $value1$); + }); + // Incorrect arity + checkWMTE(() -> { // 0 + boolean r = vh.weakCompareAndSetVolatile(); + }); + checkWMTE(() -> { // > + boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, $value1$, Void.class); + }); + + // WeakCompareAndSetAcquire // Incorrect argument types checkNPE(() -> { // null receiver From 9290ce0c7b17c48c29c2f7e48e6762c0f549d1ce Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Fri, 29 Apr 2016 14:18:09 -0700 Subject: [PATCH 186/225] 8154270: javac wrongly rejects some class literals as annotation element values Reviewed-by: mcimadamore --- .../com/sun/tools/javac/jvm/ClassWriter.java | 2 +- .../EraseClassInfoAnnotationValueTest.java | 57 +++++++++++++++++++ .../javac/annotations/T8154270/Other.java | 29 ++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java create mode 100644 langtools/test/tools/javac/annotations/T8154270/Other.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 3322d0fc5b6..ff02a24d375 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -826,7 +826,7 @@ public class ClassWriter extends ClassFile { } public void visitClass(Attribute.Class clazz) { databuf.appendByte('c'); - databuf.appendChar(pool.put(typeSig(clazz.classType))); + databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType)))); } public void visitCompound(Attribute.Compound compound) { databuf.appendByte('@'); diff --git a/langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java b/langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java new file mode 100644 index 00000000000..a0843a85a2d --- /dev/null +++ b/langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Google Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; + +/* + * @test + * @bug 8154270 + * @summary javac wrongly rejects some class literals as annotation element values + * @compile EraseClassInfoAnnotationValueTest.java + * @compile -implicit:none Other.java + * @run main EraseClassInfoAnnotationValueTest + */ +public class EraseClassInfoAnnotationValueTest { + + @Retention(RetentionPolicy.RUNTIME) + public @interface A { + Class value(); + } + + static class ParametricType { + + @A(Inner.class) + public static class Nested {} + + public class Inner {} + } + + public static void main(String[] args) { + Class clazz = ParametricType.Nested.class.getAnnotation(A.class).value(); + if (!clazz.equals(ParametricType.Inner.class)) { + throw new AssertionError(clazz); + } + } +} diff --git a/langtools/test/tools/javac/annotations/T8154270/Other.java b/langtools/test/tools/javac/annotations/T8154270/Other.java new file mode 100644 index 00000000000..1238316f3e7 --- /dev/null +++ b/langtools/test/tools/javac/annotations/T8154270/Other.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Google Inc. 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. + */ + +/** + * Tests separate compilation. + */ +public class Other { + Class clazz = EraseClassInfoAnnotationValueTest.ParametricType.Nested.class; +} From 4be9fb29fa430659302927ee38312d274652b0e5 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 29 Apr 2016 15:35:51 -0700 Subject: [PATCH 187/225] 8154482: javadoc tool must support legacy doclet and taglet Reviewed-by: jjg --- .../html/resources/standard.properties | 2 +- .../html/resources/standard.properties | 2 +- .../jdk/javadoc/internal/tool/DocEnv.java | 2 +- .../jdk/javadoc/internal/tool/Main.java | 7 - .../jdk/javadoc/internal/tool/Messager.java | 13 +- .../jdk/javadoc/internal/tool/Start.java | 157 +++++-- .../tool/resources/javadoc.properties | 11 +- .../jdk/javadoc/tool/EnsureNewOldDoclet.java | 383 +++++++++++++++--- .../test/tools/lib/toolbox/TestRunner.java | 118 ++++++ 9 files changed, 564 insertions(+), 131 deletions(-) create mode 100644 langtools/test/tools/lib/toolbox/TestRunner.java diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties index 0efe7ee9117..b20f72255fa 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties @@ -1,4 +1,4 @@ -doclet.build_version=Standard Doclet version {0} +doclet.build_version=Standard Doclet (Old) version {0} doclet.Contents=Contents doclet.Overview=Overview doclet.Window_Overview=Overview List diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 6356cbf3591..6eea5f6e887 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -1,4 +1,4 @@ -doclet.build_version=Standard Doclet (Next) version {0} +doclet.build_version=Standard Doclet version {0} doclet.Contents=Contents doclet.Overview=Overview doclet.Window_Overview=Overview List diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java index 674187dee5d..787a22acbbd 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java @@ -550,7 +550,7 @@ public class DocEnv { // Messager should be replaced by a more general // compilation environment. This can probably // subsume DocEnv as well. - messager.exit(); + throw new Messager.ExitJavadoc(); } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java index 5993176d6f9..a8725f1fb9d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java @@ -59,13 +59,6 @@ public class Main { * @return The return code. */ public static int execute(String... args) { - // NOTE: the following should be removed when the old doclet - // is removed. - if (args != null && args.length > 0 && "-Xold".equals(args[0])) { - String[] nargs = new String[args.length - 1]; - System.arraycopy(args, 1, nargs, 0, nargs.length); - return com.sun.tools.javadoc.Main.execute(nargs); - } Start jdoc = new Start(); return jdoc.begin(args); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java index bb798f09c9d..d251569532c 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.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 @@ -139,7 +139,7 @@ public class Messager extends Log implements Reporter { } } - public class ExitJavadoc extends Error { + public static class ExitJavadoc extends Error { private static final long serialVersionUID = 0; } @@ -416,15 +416,6 @@ public class Messager extends Log implements Reporter { } } - /** - * Force program exit, e.g., from a fatal error. - *

      - * TODO: This method does not really belong here. - */ - public void exit() { - throw new ExitJavadoc(); - } - private void report(DiagnosticType type, String pos, String msg) { switch (type) { case ERROR: diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index 824ffc81348..f281ee43a17 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -66,6 +66,7 @@ import jdk.javadoc.doclet.Doclet.Option; import jdk.javadoc.doclet.DocletEnvironment; import static com.sun.tools.javac.main.Option.*; + /** * Main program of Javadoc. * Previously named "Main". @@ -79,6 +80,12 @@ import static com.sun.tools.javac.main.Option.*; * @author Neal Gafter (rewrite) */ public class Start extends ToolOption.Helper { + + private static final Class OldStdDoclet = + com.sun.tools.doclets.standard.Standard.class; + + private static final Class StdDoclet = + jdk.javadoc.internal.doclets.standard.Standard.class; /** Context for this invocation. */ private final Context context; @@ -193,18 +200,26 @@ public class Start extends ToolOption.Helper { if (foot != null) messager.notice(foot); - if (exit) exit(); + if (exit) + throw new Messager.ExitJavadoc(); } - /** - * Exit - */ - private void exit() { - messager.exit(); - } /** - * Main program - external wrapper + * Main program - external wrapper. In order to maintain backward + * CLI compatibility, we dispatch to the old tool or the old doclet's + * Start mechanism, based on the options present on the command line + * with the following precedence: + * 1. presence of -Xold, dispatch to old tool + * 2. doclet variant, if old, dispatch to old Start + * 3. taglet variant, if old, dispatch to old Start + * + * Thus the presence of -Xold switches the tool, soon after command files + * if any, are expanded, this is performed here, noting that the messager + * is available at this point in time. + * The doclet/taglet tests are performed in the begin method, further on, + * this is to minimize argument processing and most importantly the impact + * of class loader creation, needed to detect the doclet/taglet class variants. */ int begin(String... argv) { // Preprocess @file arguments @@ -212,14 +227,18 @@ public class Start extends ToolOption.Helper { argv = CommandLine.parse(argv); } catch (FileNotFoundException e) { messager.error("main.cant.read", e.getMessage()); - exit(); + throw new Messager.ExitJavadoc(); } catch (IOException e) { e.printStackTrace(System.err); - exit(); + throw new Messager.ExitJavadoc(); } - List argList = Arrays.asList(argv); - boolean ok = begin(argList, Collections. emptySet()); + if (argv.length > 0 && "-Xold".equals(argv[0])) { + messager.warning("main.legacy_api"); + String[] nargv = Arrays.copyOfRange(argv, 1, argv.length); + return com.sun.tools.javadoc.Main.execute(nargv); + } + boolean ok = begin(Arrays.asList(argv), Collections. emptySet()); return ok ? 0 : 1; } @@ -231,11 +250,11 @@ public class Start extends ToolOption.Helper { List opts = new ArrayList<>(); for (String opt: options) opts.add(opt); + return begin(opts, fileObjects); } private boolean begin(List options, Iterable fileObjects) { - fileManager = context.get(JavaFileManager.class); if (fileManager == null) { JavacFileManager.preRegister(context); @@ -244,9 +263,8 @@ public class Start extends ToolOption.Helper { ((BaseFileManager) fileManager).autoClose = true; } } - // locale and doclet needs to be determined first + // locale, doclet and maybe taglet, needs to be determined first docletClass = preProcess(fileManager, options); - if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) { // no need to dispatch to old, safe to init now initMessager(); @@ -257,7 +275,7 @@ public class Start extends ToolOption.Helper { exc.printStackTrace(); if (!apiMode) { error("main.could_not_instantiate_class", docletClass); - messager.exit(); + throw new Messager.ExitJavadoc(); } throw new ClientCodeException(exc); } @@ -267,6 +285,7 @@ public class Start extends ToolOption.Helper { = new com.sun.tools.javadoc.Start(context); return ostart.begin(docletClass, options, fileObjects); } + warn("main.legacy_api"); String[] array = options.toArray(new String[options.size()]); return com.sun.tools.javadoc.Main.execute(array) == 0; } @@ -459,6 +478,11 @@ public class Start extends ToolOption.Helper { String userDocletPath = null; String userDocletName = null; + // taglet specifying arguments, since tagletpath is a doclet + // functionality, assume they are repeated and inspect all. + List userTagletPath = new ArrayList<>(); + List userTagletNames = new ArrayList<>(); + // Step 1: loop through the args, set locale early on, if found. for (int i = 0 ; i < argv.size() ; i++) { String arg = argv.get(i); @@ -470,7 +494,7 @@ public class Start extends ToolOption.Helper { oneArg(argv, i++); if (userDocletName != null) { usageError("main.more_than_one_doclet_specified_0_and_1", - userDocletName, argv.get(i)); + userDocletName, argv.get(i)); } if (docletName != null) { usageError("main.more_than_one_doclet_specified_0_and_1", @@ -484,13 +508,20 @@ public class Start extends ToolOption.Helper { } else { userDocletPath += File.pathSeparator + argv.get(i); } + } else if ("-taglet".equals(arg)) { + userTagletNames.add(argv.get(i + 1)); + } else if ("-tagletpath".equals(arg)) { + for (String pathname : argv.get(i + 1).split(File.pathSeparator)) { + userTagletPath.add(new File(pathname)); + } } } - // Step 2: a doclet has already been provided, - // nothing more to do. + + // Step 2: a doclet is provided, nothing more to do. if (docletClass != null) { return docletClass; } + // Step 3: doclet name specified ? if so find a ClassLoader, // and load it. if (userDocletName != null) { @@ -506,38 +537,80 @@ public class Start extends ToolOption.Helper { try { ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths); } catch (IOException ioe) { - panic("main.doclet_no_classloader_found", ioe); - return null; // keep compiler happy + error("main.doclet_could_not_set_location", paths); + throw new Messager.ExitJavadoc(); } } cl = fileManager.getClassLoader(DOCLET_PATH); if (cl == null) { // despite doclet specified on cmdline no classloader found! - panic("main.doclet_no_classloader_found", userDocletName); - return null; // keep compiler happy - } - try { - Class klass = cl.loadClass(userDocletName); - ensureReadable(klass); - return klass; - } catch (ClassNotFoundException cnfe) { - panic("main.doclet_class_not_found", userDocletName); - return null; // keep compiler happy + error("main.doclet_no_classloader_found", userDocletName); + throw new Messager.ExitJavadoc(); } } + try { + Class klass = cl.loadClass(userDocletName); + ensureReadable(klass); + return klass; + } catch (ClassNotFoundException cnfe) { + error("main.doclet_class_not_found", userDocletName); + throw new Messager.ExitJavadoc(); + } } - // Step 4: we have a doclet, try loading it, otherwise - // return back the standard doclet + + // Step 4: we have a doclet, try loading it if (docletName != null) { try { return Class.forName(docletName, true, getClass().getClassLoader()); } catch (ClassNotFoundException cnfe) { - panic("main.doclet_class_not_found", userDocletName); - return null; // happy compiler, should not happen + error("main.doclet_class_not_found", userDocletName); + throw new Messager.ExitJavadoc(); } - } else { - return jdk.javadoc.internal.doclets.standard.Standard.class; } + + // Step 5: we don't have a doclet specified, do we have taglets ? + if (!userTagletNames.isEmpty() && hasOldTaglet(userTagletNames, userTagletPath)) { + // found a bogey, return the old doclet + return OldStdDoclet; + } + + // finally + return StdDoclet; + } + + /* + * This method returns true iff it finds a legacy taglet, but for + * all other conditions including errors it returns false, allowing + * nature to take its own course. + */ + private boolean hasOldTaglet(List tagletNames, List tagletPaths) { + if (!fileManager.hasLocation(TAGLET_PATH)) { + try { + ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, tagletPaths); + } catch (IOException ioe) { + error("main.doclet_could_not_set_location", tagletPaths); + throw new Messager.ExitJavadoc(); + } + } + ClassLoader cl = fileManager.getClassLoader(TAGLET_PATH); + if (cl == null) { + // no classloader found! + error("main.doclet_no_classloader_found", tagletNames.get(0)); + throw new Messager.ExitJavadoc(); + } + for (String tagletName : tagletNames) { + try { + Class klass = cl.loadClass(tagletName); + ensureReadable(klass); + if (com.sun.tools.doclets.Taglet.class.isAssignableFrom(klass)) { + return true; + } + } catch (ClassNotFoundException cnfe) { + error("main.doclet_class_not_found", tagletName); + throw new Messager.ExitJavadoc(); + } + } + return false; } private void parseArgs(List args, List javaNames) { @@ -595,16 +668,14 @@ public class Start extends ToolOption.Helper { usage(true); } - // a terminal call, will not return - void panic(String key, Object... args) { - error(key, args); - messager.exit(); - } - void error(String key, Object... args) { messager.error(key, args); } + void warn(String key, Object... args) { + messager.warning(key, args); + } + /** * indicate an option with no arguments was given. */ diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties index f9cab63f716..71fab2bcd31 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties @@ -73,7 +73,8 @@ main.Xusage=\ \ given module. may be ALL-UNNAMED to require\n\ \ the unnamed module.\n\ \ -Xmodule: Specify a module to which the classes being compiled belong.\n\ -\ -Xpatch: Specify location of module class files to patch\n +\ -Xpatch: Specify location of module class files to patch\n\ +\ -Xold Invoke the legacy javadoc tool\n main.Xusage.foot=\ These options are non-standard and subject to change without notice. @@ -96,6 +97,7 @@ For example, on the JDK Classic or HotSpot VMs, add the option -J-Xmx\n\ such as -J-Xmx32m. main.done_in=[done in {0} ms] main.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}). +main.doclet_could_not_set_location=Could not set location for {0} main.doclet_no_classloader_found=Could not obtain classloader to load {0} main.could_not_instantiate_class=Could not instantiate class {0} main.doclet_class_not_found=Cannot find doclet class {0} @@ -109,10 +111,15 @@ main.release.bootclasspath.conflict=option {0} cannot be used together with -rel main.unsupported.release.version=release version {0} not supported main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager. main.unknown.error=an unknown error has occurred +main.legacy_api=The old Doclet and Taglet APIs in the packages\n\ + com.sun.javadoc, com.sun.tools.doclets and their implementations\n\ + are planned to be removed in a future JDK release. These\n\ + components have been superseded by the new APIs in jdk.javadoc.doclet.\n\ + Users are strongly recommended to migrate to the new APIs.\n + javadoc.class_not_found=Class {0} not found. javadoc.error=error javadoc.warning=warning - javadoc.error.msg={0}: error - {1} javadoc.warning.msg={0}: warning - {1} javadoc.note.msg = {1} diff --git a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java index 9d9547ed65f..6e56617507f 100644 --- a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java +++ b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java @@ -23,96 +23,349 @@ /* * @test - * @bug 8035473 - * @summary make sure the new doclet is invoked by default, and -Xold + * @bug 8035473 8154482 + * @summary make sure the javadoc tool responds correctly to Xold, + * old doclets and taglets. + * @library /tools/lib + * @build toolbox.ToolBox toolbox.TestRunner + * @run main EnsureNewOldDoclet */ import java.io.*; -import java.util.ArrayList; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import com.sun.javadoc.Tag; +import com.sun.source.doctree.DocTree; + +import toolbox.*; + /** - * Dummy javadoc comment. + * This test ensures the doclet responds correctly when given + * various conditions that force a fall back to the old javadoc + * tool. The following condition in the order described will + * force a dispatch to the old tool, -Xold, old doclet and old taglet. + * */ -public class EnsureNewOldDoclet { +public class EnsureNewOldDoclet extends TestRunner { - final File javadoc; + final ToolBox tb; final File testSrc; - final String thisClassName; + final Path javadocPath; + final ExecTask task; + final String testClasses; + final PrintStream ostream; - final static Pattern Expected1 = Pattern.compile("^Standard Doclet \\(Next\\) version.*"); - final static Pattern Expected2 = Pattern.compile("^Standard Doclet version.*"); + final static String CLASS_NAME = "EnsureNewOldDoclet"; + final static String OLD_DOCLET_CLASS_NAME = CLASS_NAME + "$OldDoclet"; + final static String NEW_DOCLET_CLASS_NAME = CLASS_NAME + "$NewDoclet"; //unused + final static String OLD_TAGLET_CLASS_NAME = CLASS_NAME + "$OldTaglet"; + final static String NEW_TAGLET_CLASS_NAME = CLASS_NAME + "$NewTaglet"; - public EnsureNewOldDoclet() { - File javaHome = new File(System.getProperty("java.home")); - if (javaHome.getName().endsWith("jre")) - javaHome = javaHome.getParentFile(); - javadoc = new File(new File(javaHome, "bin"), "javadoc"); - testSrc = new File(System.getProperty("test.src")); - thisClassName = EnsureNewOldDoclet.class.getName(); + final static Pattern OLD_HEADER = Pattern.compile("^Standard Doclet \\(Old\\) version.*"); + final static Pattern NEW_HEADER = Pattern.compile("^Standard Doclet version.*"); + + + final static String OLD_DOCLET_MARKER = "OLD_DOCLET_MARKER"; + final static String OLD_TAGLET_MARKER = "Registered: OldTaglet"; + + final static String NEW_DOCLET_MARKER = "NEW_DOCLET_MARKER"; + final static String NEW_TAGLET_MARKER = "Registered Taglet " + CLASS_NAME + "\\$NewTaglet"; + + final static Pattern WARN_TEXT = Pattern.compile("Users are strongly recommended to migrate" + + " to the new APIs."); + final static String OLD_DOCLET_ERROR = "java.lang.NoSuchMethodException: " + + CLASS_NAME +"\\$NewTaglet"; + final static Pattern NEW_DOCLET_ERROR = Pattern.compile(".*java.lang.ClassCastException.*Taglet " + + CLASS_NAME + "\\$OldTaglet.*"); + + final static String OLD_STDDOCLET = "com.sun.tools.doclets.standard.Standard"; + final static String NEW_STDDOCLET = "jdk.javadoc.internal.doclets.standard.Standard"; + + + public EnsureNewOldDoclet() throws Exception { + super(System.err); + ostream = System.err; + testClasses = System.getProperty("test.classes"); + tb = new ToolBox(); + javadocPath = tb.getJDKTool("javadoc"); + task = new ExecTask(tb, javadocPath); + testSrc = new File("Foo.java"); + generateSample(testSrc); + } + + void generateSample(File testSrc) throws Exception { + String nl = System.getProperty("line.separator"); + String src = Arrays.asList( + "/**", + " * A test class to test javadoc. Nothing more nothing less.", + " */", + " public class Foo{}").stream().collect(Collectors.joining(nl)); + tb.writeFile(testSrc.getPath(), src); } public static void main(String... args) throws Exception { - EnsureNewOldDoclet test = new EnsureNewOldDoclet(); - test.run1(); - test.run2(); + new EnsureNewOldDoclet().runTests(); } - // make sure new doclet is invoked by default - void run1() throws Exception { - List output = doTest(javadoc.getPath(), - "-classpath", ".", // insulates us from ambient classpath - "-Xdoclint:none", - "-package", - new File(testSrc, thisClassName + ".java").getPath()); - System.out.println(output); - for (String x : output) { - if (Expected1.matcher(x).matches()) { + // input: nothing, default mode + // outcome: new tool and new doclet + @Test + public void testDefault() throws Exception { + setArgs("-classpath", ".", // insulates us from ambient classpath + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + checkOutput(testName, out, NEW_HEADER); + } + + // input: -Xold + // outcome: old tool + @Test + public void testXold() throws Exception { + setArgs("-Xold", + "-classpath", ".", // ambient classpath insulation + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, OLD_HEADER); + checkOutput(testName, err, WARN_TEXT); + } + + // input: old doclet + // outcome: old tool + @Test + public void testOldDoclet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-doclet", + OLD_DOCLET_CLASS_NAME, + "-docletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, OLD_DOCLET_MARKER); + checkOutput(testName, err, WARN_TEXT); + } + + // input: old taglet + // outcome: old tool + @Test + public void testOldTaglet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-taglet", + OLD_TAGLET_CLASS_NAME, + "-tagletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, OLD_TAGLET_MARKER); + checkOutput(testName, err, WARN_TEXT); + } + + // input: new doclet and old taglet + // outcome: new doclet with failure + @Test + public void testNewDocletOldTaglet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-doclet", + NEW_STDDOCLET, + "-taglet", + OLD_TAGLET_CLASS_NAME, + "-tagletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.FAIL, 1); + //Task.Result tr = task.run(); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, NEW_HEADER); + checkOutput(testName, err, NEW_DOCLET_ERROR); + } + + // input: old doclet and old taglet + // outcome: old doclet and old taglet should register + @Test + public void testOldDocletOldTaglet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-doclet", + OLD_STDDOCLET, + "-taglet", + OLD_TAGLET_CLASS_NAME, + "-tagletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, OLD_HEADER); + checkOutput(testName, out, OLD_TAGLET_MARKER); + checkOutput(testName, err, WARN_TEXT); + } + + // input: new doclet and new taglet + // outcome: new doclet and new taglet should register + @Test + public void testNewDocletNewTaglet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-doclet", + NEW_STDDOCLET, + "-taglet", + NEW_TAGLET_CLASS_NAME, + "-tagletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.SUCCESS); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, NEW_HEADER); + checkOutput(testName, out, NEW_TAGLET_MARKER); + } + + // input: old doclet and new taglet + // outcome: old doclet and error + @Test + public void testOldDocletNewTaglet() throws Exception { + setArgs("-classpath", ".", // ambient classpath insulation + "-doclet", + OLD_STDDOCLET, + "-taglet", + NEW_TAGLET_CLASS_NAME, + "-tagletpath", + testClasses, + testSrc.toString()); + Task.Result tr = task.run(Task.Expect.FAIL, 1); + List out = tr.getOutputLines(Task.OutputKind.STDOUT); + List err = tr.getOutputLines(Task.OutputKind.STDERR); + checkOutput(testName, out, OLD_HEADER); + checkOutput(testName, err, WARN_TEXT); + checkOutput(testName, err, OLD_DOCLET_ERROR); + } + + void setArgs(String... args) { + ostream.println("cmds: " + Arrays.asList(args)); + task.args(args); + } + + void checkOutput(String testCase, List content, String toFind) throws Exception { + checkOutput(testCase, content, Pattern.compile(".*" + toFind + ".*")); + } + + void checkOutput(String testCase, List content, Pattern toFind) throws Exception { + ostream.println("---" + testCase + "---"); + content.stream().forEach(x -> System.out.println(x)); + for (String x : content) { + ostream.println(x); + if (toFind.matcher(x).matches()) { return; } } - throw new Exception("run1: Expected string not found:"); + throw new Exception(testCase + ": Expected string not found: " + toFind); } - // make sure the old doclet is invoked with -Xold - void run2() throws Exception { - List output = doTest(javadoc.getPath(), - "-Xold", - "-classpath", ".", // insulates us from ambient classpath - "-Xdoclint:none", - "-package", - new File(testSrc, thisClassName + ".java").getPath()); - - for (String x : output) { - if (Expected2.matcher(x).matches()) { - throw new Exception("run2: Expected string not found"); - } - return; + public static class OldDoclet extends com.sun.javadoc.Doclet { + public static boolean start(com.sun.javadoc.RootDoc root) { + System.out.println(OLD_DOCLET_MARKER); + return true; } } - /** - * More dummy comments. - */ - List doTest(String... args) throws Exception { - List output = new ArrayList<>(); - // run javadoc in separate process to ensure doclet executed under - // normal user conditions w.r.t. classloader - Process p = new ProcessBuilder() - .command(args) - .redirectErrorStream(true) - .start(); - try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) { - String line = in.readLine(); - while (line != null) { - output.add(line.trim()); - line = in.readLine(); - } + public static class OldTaglet implements com.sun.tools.doclets.Taglet { + + public static void register(Map map) { + EnsureNewOldDoclet.OldTaglet tag = new OldTaglet(); + com.sun.tools.doclets.Taglet t = (com.sun.tools.doclets.Taglet) map.get(tag.getName()); + System.out.println(OLD_TAGLET_MARKER); } - int rc = p.waitFor(); - if (rc != 0) - throw new Exception("javadoc failed, rc:" + rc); - return output; + + @Override + public boolean inField() { + return true; + } + + @Override + public boolean inConstructor() { + return true; + } + + @Override + public boolean inMethod() { + return true; + } + + @Override + public boolean inOverview() { + return true; + } + + @Override + public boolean inPackage() { + return true; + } + + @Override + public boolean inType() { + return true; + } + + @Override + public boolean isInlineTag() { + return true; + } + + @Override + public String getName() { + return "OldTaglet"; + } + + @Override + public String toString(Tag tag) { + return getName(); + } + + @Override + public String toString(Tag[] tags) { + return getName(); + } + } + + public static class NewTaglet implements jdk.javadoc.doclet.taglet.Taglet { + + @Override + public Set getAllowedLocations() { + return Collections.emptySet(); + } + + @Override + public boolean isInlineTag() { + return true; + } + + @Override + public String getName() { + return "NewTaglet"; + } + + @Override + public String toString(DocTree tag) { + return tag.toString(); + } + + @Override + public String toString(List tags) { + return tags.toString(); + } + } } diff --git a/langtools/test/tools/lib/toolbox/TestRunner.java b/langtools/test/tools/lib/toolbox/TestRunner.java new file mode 100644 index 00000000000..22034730405 --- /dev/null +++ b/langtools/test/tools/lib/toolbox/TestRunner.java @@ -0,0 +1,118 @@ +/* + * 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 toolbox; + +import java.io.PrintStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.function.Function; + +/** + * Utility class to manage and execute sub-tests within a test. + * + * This class does the following: + * i. invokes those test methods annotated with @Test + * ii. keeps track of successful and failed tests + * iii. throws an Exception if any test fails. + * iv. provides a test summary at the end of the run. + * + * Tests must extend this class, annotate the test methods + * with @Test and call one of the runTests method. + */ + +public abstract class TestRunner { + /** Marker annotation for test cases. */ + @Retention(RetentionPolicy.RUNTIME) + public @interface Test { } + + int testCount = 0; + int errorCount = 0; + + public String testName = null; + + final PrintStream out; + + /** + * Constructs the Object. + * @param out the PrintStream to print output to. + */ + public TestRunner(PrintStream out) { + this.out = out; + } + + /** + * Invoke all methods annotated with @Test. + * @throws java.lang.Exception + */ + public void runTests() throws Exception { + runTests(f -> new Object[0]); + } + + /** + * Invoke all methods annotated with @Test. + * @param f a lambda expression to specify arguments. + * @throws java.lang.Exception + */ + public void runTests(Function f) throws Exception { + for (Method m : getClass().getDeclaredMethods()) { + Annotation a = m.getAnnotation(Test.class); + if (a != null) { + testName = m.getName(); + try { + testCount++; + out.println("test: " + testName); + m.invoke(this, f.apply(m)); + } catch (InvocationTargetException e) { + errorCount++; + Throwable cause = e.getCause(); + out.println("Exception: " + e.getCause()); + cause.printStackTrace(out); + } + out.println(); + } + } + + if (testCount == 0) { + throw new Error("no tests found"); + } + + StringBuilder summary = new StringBuilder(); + if (testCount != 1) { + summary.append(testCount).append(" tests"); + } + if (errorCount > 0) { + if (summary.length() > 0) { + summary.append(", "); + } + summary.append(errorCount).append(" errors"); + } + out.println(summary); + if (errorCount > 0) { + throw new Exception(errorCount + " errors found"); + } + } +} From 2006da59300679eb938a5bdb6fd7631d9ef1fbf6 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Fri, 29 Apr 2016 19:53:19 -0700 Subject: [PATCH 188/225] 8139837: JShell API: make a common JShellException Reviewed-by: jlahoda --- .../share/classes/jdk/jshell/Eval.java | 7 ++-- .../classes/jdk/jshell/EvalException.java | 2 +- .../classes/jdk/jshell/ExecutionControl.java | 4 +- .../classes/jdk/jshell/JShellException.java | 37 +++++++++++++++++++ .../classes/jdk/jshell/SnippetEvent.java | 6 +-- .../share/classes/jdk/jshell/Unit.java | 2 +- .../jshell/UnresolvedReferenceException.java | 2 +- 7 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index 961eafbf0c0..1d8af24b28c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -452,7 +452,7 @@ class Eval { // If appropriate, execute the snippet String value = null; - Exception exception = null; + JShellException exception = null; if (si.status().isDefined) { if (si.isExecutable()) { try { @@ -462,7 +462,8 @@ class Eval { : ""; } catch (EvalException ex) { exception = translateExecutionException(ex); - } catch (UnresolvedReferenceException ex) { + } catch (JShellException ex) { + // UnresolvedReferenceException exception = ex; } } else if (si.subKind() == SubKind.VAR_DECLARATION_SUBKIND) { @@ -499,7 +500,7 @@ class Eval { || e.exception() != null; } - private List events(Unit c, Collection outs, String value, Exception exception) { + private List events(Unit c, Collection outs, String value, JShellException exception) { List events = new ArrayList<>(); events.add(c.event(value, exception)); events.addAll(outs.stream() diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java index 6c7a5f8fd63..27c351d635f 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java @@ -40,7 +40,7 @@ package jdk.jshell; * empty string. */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted -public class EvalException extends Exception { +public class EvalException extends JShellException { private final String exceptionClass; EvalException(String message, String exceptionClass, StackTraceElement[] stackElements) { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index 40186742741..f28323e178c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -119,7 +119,7 @@ class ExecutionControl { } } - String commandInvoke(String classname) throws EvalException, UnresolvedReferenceException { + String commandInvoke(String classname) throws JShellException { try { synchronized (STOP_LOCK) { userCodeRunning = true; @@ -213,7 +213,7 @@ class ExecutionControl { } } - private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException { + private boolean readAndReportExecutionResult() throws IOException, JShellException { int ok = in.readInt(); switch (ok) { case RESULT_SUCCESS: diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java new file mode 100644 index 00000000000..721bf1e6c47 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.jshell; + +/** + * The superclass of JShell generated exceptions + */ +@SuppressWarnings("serial") // serialVersionUID intentionally omitted +public class JShellException extends Exception { + + JShellException(String message) { + super(message); + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java index 36446468860..b4d0fb0174f 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java @@ -44,7 +44,7 @@ public class SnippetEvent { SnippetEvent(Snippet snippet, Status previousStatus, Status status, boolean isSignatureChange, Snippet causeSnippet, - String value, Exception exception) { + String value, JShellException exception) { this.snippet = snippet; this.previousStatus = previousStatus; this.status = status; @@ -60,7 +60,7 @@ public class SnippetEvent { private final boolean isSignatureChange; private final Snippet causeSnippet; private final String value; - private final Exception exception; + private final JShellException exception; /** * The Snippet which has changed @@ -121,7 +121,7 @@ public class SnippetEvent { * during execution, otherwise null. * @return the exception or null. */ - public Exception exception() { + public JShellException exception() { return exception; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java index e5892470440..987dc6bc93e 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java @@ -440,7 +440,7 @@ final class Unit { : msi.parameterTypes(); } - SnippetEvent event(String value, Exception exception) { + SnippetEvent event(String value, JShellException exception) { boolean wasSignatureChanged = sigChanged(); state.debug(DBG_EVNT, "Snippet: %s id: %s before: %s status: %s sig: %b cause: %s\n", si, si.id(), prevStatus, si.status(), wasSignatureChanged, causalSnippet); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java index 3e3de8fd943..be91686eff3 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java @@ -38,7 +38,7 @@ package jdk.jshell; * empty string. */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted -public class UnresolvedReferenceException extends Exception { +public class UnresolvedReferenceException extends JShellException { final DeclarationSnippet snippet; From 6ae0f15a000b2f69686a82d9c7f5c7f7eab9c868 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Fri, 29 Apr 2016 16:06:52 -0700 Subject: [PATCH 189/225] 8155061: javadoc incorrectly sorted items in All Classes list and Index files Reviewed-by: jjg --- .../doclets/toolkit/util/IndexBuilder.java | 6 +- .../internal/doclets/toolkit/util/Utils.java | 61 +++++++++++---- .../doclet/testOrdering/TestOrdering.java | 77 +++++++++++++++---- 3 files changed, 115 insertions(+), 29 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java index 60090fa0f3a..61051994adc 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java @@ -73,6 +73,7 @@ public class IndexBuilder { private final Configuration configuration; private final Utils utils; + private final Comparator comparator; /** * Constructor. Build the index map. @@ -106,6 +107,9 @@ public class IndexBuilder { this.classesOnly = classesOnly; this.javafx = configuration.javafx; this.indexmap = new TreeMap<>(); + comparator = classesOnly + ? utils.makeAllClassesComparator() + : utils.makeIndexUseComparator(); buildIndexMap(configuration.root); } @@ -175,7 +179,7 @@ public class IndexBuilder { Character.toUpperCase(name.charAt(0)); Character unicode = ch; SortedSet list = indexmap.computeIfAbsent(unicode, - c -> new TreeSet<>(utils.makeIndexUseComparator())); + c -> new TreeSet<>(comparator)); list.add(element); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 1b32bcc6c75..aaa601e839a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1628,6 +1628,7 @@ public class Utils { /** * Comparator for ModuleElements, simply compares the fully qualified names + * @return a Comparator */ public Comparator makeModuleComparator() { return new Utils.ElementComparator() { @@ -1639,7 +1640,28 @@ public class Utils { } /** - * Comparator for PackageElements, simply compares the fully qualified names + * Returns a Comparator for all classes, compares the simple names of + * TypeElement, if equal then the fully qualified names. + * + * @return Comparator + */ + public Comparator makeAllClassesComparator() { + return new Utils.ElementComparator() { + @Override + public int compare(Element e1, Element e2) { + int result = compareNames(e1, e2); + if (result == 0) + result = compareFullyQualifiedNames(e1, e2); + + return result; + } + }; + } + + /** + * Returns a Comparator for packages, by comparing the fully qualified names. + * + * @return a Comparator */ public Comparator makePackageComparator() { return new Utils.ElementComparator() { @@ -1650,6 +1672,10 @@ public class Utils { }; } + /** + * Returns a Comparator for SerialFieldTree. + * @return a Comparator + */ public Comparator makeSerialFieldTreeComparator() { return (SerialFieldTree o1, SerialFieldTree o2) -> { String s1 = o1.getName().toString(); @@ -1659,18 +1685,19 @@ public class Utils { } /** - * Comparator for General Purpose - * @return a ElementComparatorForClassUse + * Returns a general purpose comparator. + * @return a Comparator */ public Comparator makeGeneralPurposeComparator() { return makeClassUseComparator(); } /** - * A Comparator for Overrides and Implements use used on ExecutableElements - * compares the name first, then compares the SimpleName of the enclosing - * class and the FullyQualifiedName of the enclosing class. - * @return + * Returns a Comparator for overrides and implements, + * used primarily on methods, compares the name first, + * then compares the simple names of the enclosing + * TypeElement and the fully qualified name of the enclosing TypeElement. + * @return a Comparator */ public Comparator makeOverrideUseComparator() { return new Utils.ElementComparator() { @@ -1696,21 +1723,24 @@ public class Utils { } /** - * A comparator for index file presentations, and are sorted as follows: + * Returns a Comparator for index file presentations, and are sorted as follows. + * If comparing packages then simply compare the qualified names, otherwise * 1. sort on simple names of entities * 2. if equal, then compare the ElementKind ex: Package, Interface etc. * 3a. if equal and if the type is of ExecutableElement(Constructor, Methods), * a case insensitive comparison of parameter the type signatures * 3b. if equal, case sensitive comparison of the type signatures * 4. finally, if equal, compare the FQNs of the entities + * Iff comparing packages then simply sort on qualified names. * @return a comparator for index file use */ public Comparator makeIndexUseComparator() { return new Utils.ElementComparator() { /** - * Compare two given elements, first sort on names, then on the kinds, - * then on the parameters only if the type is an instance of ExecutableElement, - * the parameters are compared and finally the fully qualified names. + * Compare two given elements, if comparing two packages, return the + * comparison of FullyQualifiedName, first sort on names, then on the + * kinds, then on the parameters only if the type is an ExecutableElement, + * the parameters are compared and finally the qualified names. * * @param e1 - an element. * @param e2 - an element. @@ -1719,10 +1749,7 @@ public class Utils { */ @Override public int compare(Element e1, Element e2) { - int result = compareElementTypeKinds(e1, e2); - if (result != 0) { - return result; - } + int result = 0; if (isPackage(e1) && isPackage(e2)) { return compareFullyQualifiedNames(e1, e2); } @@ -1730,6 +1757,10 @@ public class Utils { if (result != 0) { return result; } + result = compareElementTypeKinds(e1, e2); + if (result != 0) { + return result; + } if (hasParameters(e1)) { List parameters1 = ((ExecutableElement)e1).getParameters(); List parameters2 = ((ExecutableElement)e2).getParameters(); diff --git a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java index 3e7f7692596..112e6be64ec 100644 --- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java +++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8039410 8042601 8042829 8049393 8050031 + * @bug 8039410 8042601 8042829 8049393 8050031 8155061 * @summary test to determine if members are ordered correctly * @author ksrini * @library ../lib/ @@ -72,6 +72,8 @@ public class TestOrdering extends JavadocTester { checkOrder("pkg1/class-use/UsedClass.html", expectedInnerClassContructors); checkOrder("pkg1/ImplementsOrdering.html", expectedImplementsOrdering); checkOrder("pkg1/OverrideOrdering.html", expectedOverrideOrdering); + checkOrder("allclasses-noframe.html", expectedAllClasses); + checkOrder("allclasses-frame.html", expectedAllClasses); } enum ListOrder { NONE, REVERSE, SHUFFLE }; @@ -179,6 +181,22 @@ public class TestOrdering extends JavadocTester { }; String[] composeTestVectors() { List testList = new ArrayList<>(); + + testList.addAll(Arrays.asList(expectedPackageOrdering)); + + for (String x : expectedMethodOrdering) { + testList.add(x); + for (int i = 0; i < MAX_PACKAGES; i++) { + String wpkg = "add" + i; + testList.add(wpkg + "/" + x); + String dpkg = wpkg; + for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { + dpkg = dpkg + "/" + "add"; + testList.add(dpkg + "/" + x); + } + } + } + for (String x : expectedEnumOrdering) { testList.add(x.replace("REPLACE_ME", "<Unnamed>")); for (int i = 0; i < MAX_PACKAGES; i++) { @@ -194,20 +212,9 @@ public class TestOrdering extends JavadocTester { testList.addAll(Arrays.asList(expectedFieldOrdering)); - for (String x : expectedMethodOrdering) { - testList.add(x); - for (int i = 0; i < MAX_PACKAGES; i++) { - String wpkg = "add" + i; - testList.add(wpkg + "/" + x); - String dpkg = wpkg; - for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) { - dpkg = dpkg + "/" + "add"; - testList.add(dpkg + "/" + x); - } - } - } return testList.toArray(new String[testList.size()]); } + void checkExecutableMemberOrdering(String usePage) { String contents = readFile(usePage); // check constructors @@ -309,6 +316,22 @@ public class TestOrdering extends JavadocTester { return in.replace("/", "."); } + final String expectedAllClasses[] = { + "pkg1/A.html\" title=\"class in pkg1", + "pkg1/A.C.html\" title=\"class in pkg1", + "pkg1/B.html\" title=\"class in pkg1", + "pkg1/B.A.html\" title=\"class in pkg1", + "pkg1/C1.html\" title=\"class in pkg1", + "pkg1/C2.html\" title=\"class in pkg1", + "pkg1/C3.html\" title=\"class in pkg1", + "pkg1/C4.html\" title=\"class in pkg1", + "pkg1/ImplementsOrdering.html\" title=\"interface in pkg1", + "pkg1/MethodOrder.html\" title=\"class in pkg1", + "pkg1/OverrideOrdering.html\" title=\"class in pkg1", + "pkg1/UsedClass.html\" title=\"class in pkg1" + + }; + final String expectedInnerClassContructors[] = { "../../pkg1/A.html#A-pkg1.UsedClass-", "../../pkg1/B.A.html#A-pkg1.UsedClass-", @@ -342,12 +365,33 @@ public class TestOrdering extends JavadocTester { "../../pkg1/MethodOrder.html#m-java.util.Collection-", "../../pkg1/MethodOrder.html#m-java.util.List-" }; + final String expectedClassUseWithTypeParams[] = { "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-", "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass-", "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass:A-", "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-java.lang.String-" }; + + final String expectedPackageOrdering[] = { + "\"add0/package-summary.html\">add0 - package add0", + "\"add0/add/package-summary.html\">add0.add - package add0.add", + "\"add0/add/add/package-summary.html\">add0.add.add - package add0.add.add", + "\"add0/add/add/add/package-summary.html\">add0.add.add.add - package add0.add.add.add", + "\"add1/package-summary.html\">add1 - package add1", + "\"add1/add/package-summary.html\">add1.add - package add1.add", + "\"add1/add/add/package-summary.html\">add1.add.add - package add1.add.add", + "\"add1/add/add/add/package-summary.html\">add1.add.add.add - package add1.add.add.add", + "\"add2/package-summary.html\">add2 - package add2", + "\"add2/add/package-summary.html\">add2.add - package add2.add", + "\"add2/add/add/package-summary.html\">add2.add.add - package add2.add.add", + "\"add2/add/add/add/package-summary.html\">add2.add.add.add - package add2.add.add.add", + "\"add3/package-summary.html\">add3 - package add3", + "\"add3/add/package-summary.html\">add3.add - package add3.add", + "\"add3/add/add/package-summary.html\">add3.add.add - package add3.add.add", + "\"add3/add/add/add/package-summary.html\">add3.add.add.add - package add3.add.add.add" + }; + final String expectedMethodOrdering[] = { "Add.html#add--", "Add.html#add-double-", @@ -361,10 +405,12 @@ public class TestOrdering extends JavadocTester { "Add.html#add-java.lang.Double-", "Add.html#add-java.lang.Integer-" }; + final String expectedEnumOrdering[] = { "Add.add.html\" title=\"enum in REPLACE_ME\"", "Add.ADD.html\" title=\"enum in REPLACE_ME\"" }; + final String expectedFieldOrdering[] = { "Add.html#addadd\"", "add0/add/add/add/Add.html#addadd\"", @@ -418,10 +464,12 @@ public class TestOrdering extends JavadocTester { "add3/add/Add.html#ADDADD\"", "add3/Add.html#ADDADD\"" }; + final String expectedPackageTreeOrdering[] = { "", "" }; + final String expectedOverviewOrdering[] = { "", "", @@ -458,6 +506,7 @@ public class TestOrdering extends JavadocTester { "", "", }; + final static String expectedOverviewFrameOrdering[] = { "<unnamed package>", "add0", @@ -477,11 +526,13 @@ public class TestOrdering extends JavadocTester { "add3.add.add", "add3.add.add.add" }; + final static String expectedImplementsOrdering[] = { "

      close in interface java.lang.AutoCloseable
      ", "
      close in interface java.nio.channels.Channel
      ", "
      close in interface java.io.Closeable
      " }; + final static String expectedOverrideOrdering[] = { "
      iterator in interface java.util.Collection<", "
      iterator in interface java.lang.Iterable<" From bab1d3912ac4a3dc6c580530fabc6bb18abd1434 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Sat, 30 Apr 2016 00:30:31 +0100 Subject: [PATCH 190/225] 8087124: HTTP/2 implementation Reviewed-by: chegar --- .../java/net/http/AsyncConnection.java | 68 ++ .../classes/java/net/http/AsyncEvent.java | 29 +- .../java/net/http/AsyncSSLConnection.java | 129 +++ .../java/net/http/AsyncSSLDelegate.java | 598 +++++++++++++ .../java/net/http/AuthenticationFilter.java | 2 +- .../classes/java/net/http/BufferHandler.java | 16 +- .../java/net/http/ByteBufferConsumer.java | 188 ++++ .../java/net/http/ByteBufferGenerator.java | 136 +++ .../classes/java/net/http/CharsetToolkit.java | 159 ++++ .../classes/java/net/http/ConnectionPool.java | 2 +- .../java/net/http/ContinuationFrame.java | 59 ++ .../classes/java/net/http/CookieFilter.java | 2 +- .../classes/java/net/http/DataFrame.java | 126 +++ .../classes/java/net/http/ErrorFrame.java | 88 ++ .../share/classes/java/net/http/Exchange.java | 51 +- .../classes/java/net/http/FrameReader.java | 70 ++ .../classes/java/net/http/GoAwayFrame.java | 104 +++ .../classes/java/net/http/HeaderFrame.java | 77 ++ .../classes/java/net/http/HeadersFrame.java | 138 +++ .../classes/java/net/http/Http1Exchange.java | 28 +- .../classes/java/net/http/Http1Request.java | 32 +- .../classes/java/net/http/Http1Response.java | 1 - .../java/net/http/Http2ClientImpl.java | 134 ++- .../java/net/http/Http2Connection.java | 781 ++++++++++++++++- .../classes/java/net/http/Http2Frame.java | 211 +++++ .../classes/java/net/http/HttpClientImpl.java | 186 ++-- .../classes/java/net/http/HttpConnection.java | 120 ++- .../java/net/http/HttpHeadersImpl.java | 51 +- .../java/net/http/HttpRequestBuilderImpl.java | 10 +- .../java/net/http/HttpRequestImpl.java | 110 ++- .../classes/java/net/http/HttpResponse.java | 15 +- .../java/net/http/HttpResponseImpl.java | 44 +- .../java/net/http/ImmutableHeaders.java | 79 ++ .../share/classes/java/net/http/Log.java | 60 +- .../classes/java/net/http/MultiExchange.java | 9 +- .../java/net/http/OutgoingHeaders.java | 91 ++ .../share/classes/java/net/http/Pair.java | 5 + .../classes/java/net/http/PingFrame.java | 85 ++ .../java/net/http/PlainHttpConnection.java | 194 ++++- .../net/http/PlainTunnelingConnection.java | 2 +- .../classes/java/net/http/PriorityFrame.java | 82 ++ .../java/net/http/PushPromiseFrame.java | 119 +++ .../share/classes/java/net/http/Queue.java | 143 ++++ .../classes/java/net/http/RawChannel.java | 60 +- .../classes/java/net/http/RedirectFilter.java | 7 +- .../classes/java/net/http/ResetFrame.java | 61 ++ .../java/net/http/ResponseHeaders.java | 6 +- .../classes/java/net/http/SSLConnection.java | 9 +- .../classes/java/net/http/SSLDelegate.java | 35 +- .../java/net/http/SSLTunnelConnection.java | 8 +- .../classes/java/net/http/SettingsFrame.java | 165 ++++ .../share/classes/java/net/http/Stream.java | 805 +++++++++++++++++- .../share/classes/java/net/http/Utils.java | 219 ++++- .../java/net/http/WindowUpdateFrame.java | 78 ++ .../classes/java/net/http/package-info.java | 10 +- jdk/test/java/net/httpclient/APIErrors.java | 47 +- jdk/test/java/net/httpclient/EchoHandler.java | 87 ++ .../net/httpclient/LightWeightHttpServer.java | 8 +- .../java/net/httpclient/ManyRequests.java | 49 +- .../java/net/httpclient/RequestBodyTest.java | 5 +- jdk/test/java/net/httpclient/SmokeTest.java | 22 +- jdk/test/java/net/httpclient/TestKit.java | 101 +++ jdk/test/java/net/httpclient/TestKitTest.java | 130 +++ .../java/net/httpclient/http2/BasicTest.java | 222 +++++ .../java/net/httpclient/http2/ServerPush.java | 107 +++ .../java/net/httpclient/http2/TEST.properties | 1 + .../java/net/http/BodyInputStream.java | 107 +++ .../java/net/http/BodyOutputStream.java | 106 +++ .../java/net/http/EchoHandler.java | 78 ++ .../java/net/http/Http2Handler.java | 18 + .../java/net/http/Http2TestExchange.java | 126 +++ .../java/net/http/Http2TestServer.java | 159 ++++ .../net/http/Http2TestServerConnection.java | 730 ++++++++++++++++ .../java/net/http/OutgoingPushPromise.java | 31 + .../java/net/http/PushHandler.java | 71 ++ .../java/net/http/TestUtil.java | 81 ++ .../java/net/httpclient/security/15.policy | 2 +- 77 files changed, 7799 insertions(+), 586 deletions(-) create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ErrorFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/HeadersFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/Queue.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java create mode 100644 jdk/src/java.httpclient/share/classes/java/net/http/WindowUpdateFrame.java create mode 100644 jdk/test/java/net/httpclient/EchoHandler.java create mode 100644 jdk/test/java/net/httpclient/TestKit.java create mode 100644 jdk/test/java/net/httpclient/TestKitTest.java create mode 100644 jdk/test/java/net/httpclient/http2/BasicTest.java create mode 100644 jdk/test/java/net/httpclient/http2/ServerPush.java create mode 100644 jdk/test/java/net/httpclient/http2/TEST.properties create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java create mode 100644 jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/TestUtil.java diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java new file mode 100644 index 00000000000..8818823af30 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java @@ -0,0 +1,68 @@ +/* + * 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 + */ +package java.net.http; + +import java.nio.ByteBuffer; +import java.util.function.Consumer; + +/** + * Implemented by classes that offer an asynchronous interface. + * + * PlainHttpConnection, AsyncSSLConnection AsyncSSLDelegate. + * + * setAsyncCallbacks() is called to set the callback for reading + * and error notification. Reads all happen on the selector thread, which + * must not block. + * + * Writing uses the same write() methods as used in blocking mode. + * Queues are employed on the writing side to buffer data while it is waiting + * to be sent. This strategy relies on HTTP/2 protocol flow control to stop + * outgoing queue from continually growing. Writes can be initiated by the + * calling thread, but if socket becomes full then the queue is emptied by + * the selector thread + * + */ +interface AsyncConnection { + + /** + * Enables asynchronous sending and receiving mode. The given async + * receiver will receive all incoming data. asyncInput() will be called + * to trigger reads. asyncOutput() will be called to drive writes. + * + * The errorReceiver callback must be called when any fatal exception + * occurs. Connection is assumed to be closed afterwards. + * + * @param asyncReceiver + * @param errorReceiver + */ + void setAsyncCallbacks( + Consumer asyncReceiver, + Consumer errorReceiver); + + /** + * Does whatever is required to start reading. Usually registers + * an event with the selector thread. + */ + void startReading(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java index 1cd606fe7a5..b6284398189 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java @@ -25,24 +25,27 @@ package java.net.http; import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; /** * Event handling interface from HttpClientImpl's selector. * - *

      If blockingChannel is true, then the channel will be put in blocking + * If BLOCKING is set, then the channel will be put in blocking * mode prior to handle() being called. If false, then it remains non-blocking. + * + * If REPEATING is set then the event is not cancelled after being posted. */ abstract class AsyncEvent { - /** - * Implement this if channel should be made blocking before calling handle() - */ - public interface Blocking { } + public static final int BLOCKING = 0x1; // non blocking if not set + public static final int REPEATING = 0x2; // one off event if not set - /** - * Implement this if channel should remain non-blocking before calling handle() - */ - public interface NonBlocking { } + protected final int flags; + + AsyncEvent(int flags) { + this.flags = flags; + } /** Returns the channel */ public abstract SelectableChannel channel(); @@ -55,4 +58,12 @@ abstract class AsyncEvent { /** Called when selector is shutting down. Abort all exchanges. */ public abstract void abort(); + + public boolean blocking() { + return (flags & BLOCKING) != 0; + } + + public boolean repeating() { + return (flags & REPEATING) != 0; + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java new file mode 100644 index 00000000000..3dcd2d4933f --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java @@ -0,0 +1,129 @@ +/* + * 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +/** + * Asynchronous version of SSLConnection. + */ +class AsyncSSLConnection extends HttpConnection implements AsyncConnection { + final AsyncSSLDelegate sslDelegate; + final PlainHttpConnection delegate; + + AsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) { + super(addr, client); + delegate = new PlainHttpConnection(addr, client); + sslDelegate = new AsyncSSLDelegate(delegate, client, ap); + } + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + } + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync(); + } + + @Override + boolean connected() { + return delegate.connected(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return false; + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return ConnectionPool.cacheKey(address, null); + } + + @Override + synchronized long write(ByteBuffer[] buffers, int start, int number) throws IOException { + ByteBuffer[] bufs = Utils.reduce(buffers, start, number); + long n = Utils.remaining(bufs); + sslDelegate.write(bufs); + return n; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + long n = buffer.remaining(); + sslDelegate.write(buffer); + return n; + } + + @Override + public void close() { + Utils.close(sslDelegate, delegate.channel()); + } + + @Override + public void setAsyncCallbacks(Consumer asyncReceiver, Consumer errorReceiver) { + sslDelegate.setAsyncCallbacks(asyncReceiver, errorReceiver); + delegate.setAsyncCallbacks(sslDelegate::lowerRead, errorReceiver); + } + + // Blocking read functions not used here + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + protected int readImpl(ByteBuffer buffer) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + CompletableFuture whenReceivingResponse() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void startReading() { + delegate.startReading(); + sslDelegate.startReading(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java new file mode 100644 index 00000000000..217bd7d16ea --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java @@ -0,0 +1,598 @@ +/* + * 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 + */ +package java.net.http; + +import java.io.Closeable; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; +import static javax.net.ssl.SSLEngineResult.Status.*; +import javax.net.ssl.*; +import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; + +/** + * Asynchronous wrapper around SSLEngine. send and receive is fully non + * blocking. When handshaking is required, a thread is created to perform + * the handshake and application level sends do not take place during this time. + * + * Is implemented using queues and functions operating on the receiving end + * of each queue. + * + * Application writes to: + * || + * \/ + * appOutputQ + * || + * \/ + * appOutputQ read by "upperWrite" method which does SSLEngine.wrap + * and writes to + * || + * \/ + * channelOutputQ + * || + * \/ + * channelOutputQ is read by "lowerWrite" method which is invoked from + * OP_WRITE events on the socket (from selector thread) + * + * Reading side is as follows + * -------------------------- + * + * "upperRead" method reads off channelInputQ and calls SSLEngine.unwrap and + * when decrypted data is returned, it is passed to the user's Consumer + * /\ + * || + * channelInputQ + * /\ + * || + * "lowerRead" method puts buffers into channelInputQ. It is invoked from + * OP_READ events from the selector. + * + * Whenever handshaking is required, the doHandshaking() method is called + * which creates a thread to complete the handshake. It takes over the + * channelInputQ from upperRead, and puts outgoing packets on channelOutputQ. + * Selector events are delivered to lowerRead and lowerWrite as normal. + * + * Errors + * + * Any exception thrown by the engine or channel, causes all Queues to be closed + * the channel to be closed, and the error is reported to the user's + * Consumer + */ +public class AsyncSSLDelegate implements Closeable, AsyncConnection { + + // outgoing buffers put in this queue first and may remain here + // while SSL handshaking happening. + final Queue appOutputQ; + + // queue of wrapped ByteBuffers waiting to be sent on socket channel + //final Queue channelOutputQ; + + // Bytes read into this queue before being unwrapped. Backup on this + // Q should only happen when the engine is stalled due to delegated tasks + final Queue channelInputQ; + + // input occurs through the read() method which is expected to be called + // when the selector signals some data is waiting to be read. All incoming + // handshake data is handled in this method, which means some calls to + // read() may return zero bytes of user data. This is not a sign of spinning, + // just that the handshake mechanics are being executed. + + final SSLEngine engine; + final SSLParameters sslParameters; + //final SocketChannel chan; + final HttpConnection lowerOutput; + final HttpClientImpl client; + final ExecutorService executor; + final BufferHandler bufPool; + Consumer receiver; + Consumer errorHandler; + // Locks. + final Object reader = new Object(); + final Object writer = new Object(); + // synchronizing handshake state + final Object handshaker = new Object(); + // flag set when reader or writer is blocked waiting for handshake to finish + boolean writerBlocked; + boolean readerBlocked; + + // some thread is currently doing the handshake + boolean handshaking; + + // alpn[] may be null. upcall is callback which receives incoming decoded bytes off socket + + AsyncSSLDelegate(HttpConnection lowerOutput, HttpClientImpl client, String[] alpn) + { + SSLContext context = client.sslContext(); + executor = client.executorService(); + bufPool = client; + appOutputQ = new Queue<>(); + appOutputQ.registerPutCallback(this::upperWrite); + //channelOutputQ = new Queue<>(); + //channelOutputQ.registerPutCallback(this::lowerWrite); + engine = context.createSSLEngine(); + engine.setUseClientMode(true); + SSLParameters sslp = client.sslParameters().orElse(null); + if (sslp == null) { + sslp = context.getSupportedSSLParameters(); + //sslp = context.getDefaultSSLParameters(); + //printParams(sslp); + } + sslParameters = Utils.copySSLParameters(sslp); + if (alpn != null) { + sslParameters.setApplicationProtocols(alpn); + Log.logSSL("Setting application protocols: " + Arrays.toString(alpn)); + } else { + Log.logSSL("No application protocols proposed"); + } + engine.setSSLParameters(sslParameters); + engine.setEnabledCipherSuites(sslp.getCipherSuites()); + engine.setEnabledProtocols(sslp.getProtocols()); + this.lowerOutput = lowerOutput; + this.client = client; + this.channelInputQ = new Queue<>(); + this.channelInputQ.registerPutCallback(this::upperRead); + } + + /** + * Put buffers to appOutputQ, and call upperWrite() if q was empty. + * + * @param src + */ + public void write(ByteBuffer[] src) throws IOException { + appOutputQ.putAll(src); + } + + public void write(ByteBuffer buf) throws IOException { + ByteBuffer[] a = new ByteBuffer[1]; + a[0] = buf; + write(a); + } + + @Override + public void close() { + Utils.close(appOutputQ, channelInputQ, lowerOutput); + } + + /** + * Attempts to wrap buffers from appOutputQ and place them on the + * channelOutputQ for writing. If handshaking is happening, then the + * process stalls and last buffers taken off the appOutputQ are put back + * into it until handshaking completes. + * + * This same method is called to try and resume output after a blocking + * handshaking operation has completed. + */ + private void upperWrite() { + try { + EngineResult r = null; + ByteBuffer[] buffers = appOutputQ.pollAll(Utils.EMPTY_BB_ARRAY); + int bytes = Utils.remaining(buffers); + while (bytes > 0) { + synchronized (writer) { + r = wrapBuffers(buffers); + int bytesProduced = r.bytesProduced(); + int bytesConsumed = r.bytesConsumed(); + bytes -= bytesConsumed; + if (bytesProduced > 0) { + // pass destination buffer to channelOutputQ. + lowerOutput.write(r.destBuffer); + } + synchronized (handshaker) { + if (r.handshaking()) { + // handshaking is happening or is needed + // so we put the buffers back on Q to process again + // later. It's possible that some may have already + // been processed, which is ok. + appOutputQ.pushbackAll(buffers); + writerBlocked = true; + if (!handshaking()) { + // execute the handshake in another thread. + // This method will be called again to resume sending + // later + doHandshake(r); + } + return; + } + } + } + } + returnBuffers(buffers); + } catch (Throwable t) { + t.printStackTrace(); + close(); + } + } + + private void doHandshake(EngineResult r) { + handshaking = true; + channelInputQ.registerPutCallback(null); + executor.execute(() -> { + try { + doHandshakeImpl(r); + channelInputQ.registerPutCallback(this::upperRead); + } catch (Throwable t) { + t.printStackTrace(); + close(); + } + }); + } + + private void returnBuffers(ByteBuffer[] bufs) { + for (ByteBuffer buf : bufs) + client.returnBuffer(buf); + } + + /** + * Return true if some thread is currently doing the handshake + * + * @return + */ + boolean handshaking() { + synchronized(handshaker) { + return handshaking; + } + } + + /** + * Executes entire handshake in calling thread. + * Returns after handshake is completed or error occurs + * @param r + * @throws IOException + */ + private void doHandshakeImpl(EngineResult r) throws IOException { + while (true) { + SSLEngineResult.HandshakeStatus status = r.handshakeStatus(); + if (status == NEED_TASK) { + LinkedList tasks = obtainTasks(); + for (Runnable task : tasks) + task.run(); + r = handshakeWrapAndSend(); + } else if (status == NEED_WRAP) { + r = handshakeWrapAndSend(); + } else if (status == NEED_UNWRAP) { + r = handshakeReceiveAndUnWrap(); + } + if (!r.handshaking()) + break; + } + boolean dowrite = false; + boolean doread = false; + // Handshake is finished. Now resume reading and/or writing + synchronized(handshaker) { + handshaking = false; + if (writerBlocked) { + writerBlocked = false; + dowrite = true; + } + if (readerBlocked) { + readerBlocked = false; + doread = true; + } + } + if (dowrite) + upperWrite(); + if (doread) + upperRead(); + } + + // acknowledge a received CLOSE request from peer + void doClosure() throws IOException { + //while (!wrapAndSend(emptyArray)) + //; + } + + LinkedList obtainTasks() { + LinkedList l = new LinkedList<>(); + Runnable r; + while ((r = engine.getDelegatedTask()) != null) + l.add(r); + return l; + } + + @Override + public synchronized void setAsyncCallbacks(Consumer asyncReceiver, Consumer errorReceiver) { + this.receiver = asyncReceiver; + this.errorHandler = errorReceiver; + } + + @Override + public void startReading() { + // maybe this class does not need to implement AsyncConnection + } + + static class EngineResult { + ByteBuffer destBuffer; + ByteBuffer srcBuffer; + SSLEngineResult result; + Throwable t; + + boolean handshaking() { + SSLEngineResult.HandshakeStatus s = result.getHandshakeStatus(); + return s != FINISHED && s != NOT_HANDSHAKING; + } + + int bytesConsumed() { + return result.bytesConsumed(); + } + + int bytesProduced() { + return result.bytesProduced(); + } + + Throwable exception() { + return t; + } + + SSLEngineResult.HandshakeStatus handshakeStatus() { + return result.getHandshakeStatus(); + } + + SSLEngineResult.Status status() { + return result.getStatus(); + } + } + + EngineResult handshakeWrapAndSend() throws IOException { + EngineResult r = wrapBuffer(Utils.EMPTY_BYTEBUFFER); + if (r.bytesProduced() > 0) { + lowerOutput.write(r.destBuffer); + } + return r; + } + + // called during handshaking. It blocks until a complete packet + // is available, unwraps it and returns. + EngineResult handshakeReceiveAndUnWrap() throws IOException { + ByteBuffer buf = channelInputQ.take(); + while (true) { + // block waiting for input + EngineResult r = unwrapBuffer(buf); + SSLEngineResult.Status status = r.status(); + if (status == BUFFER_UNDERFLOW) { + // wait for another buffer to arrive + ByteBuffer buf1 = channelInputQ.take(); + buf = combine (buf, buf1); + continue; + } + // OK + // theoretically possible we could receive some user data + if (r.bytesProduced() > 0) { + receiver.accept(r.destBuffer); + } + if (!buf.hasRemaining()) + return r; + } + } + + EngineResult wrapBuffer(ByteBuffer src) throws SSLException { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = src; + return wrapBuffers(bufs); + } + + EngineResult wrapBuffers(ByteBuffer[] src) throws SSLException { + EngineResult r = new EngineResult(); + ByteBuffer dst = bufPool.getBuffer(); + while (true) { + r.result = engine.wrap(src, dst); + switch (r.result.getStatus()) { + case BUFFER_OVERFLOW: + dst = getPacketBuffer(); + break; + case CLOSED: + case OK: + dst.flip(); + r.destBuffer = dst; + return r; + case BUFFER_UNDERFLOW: + // underflow handled externally + bufPool.returnBuffer(dst); + return r; + default: + assert false; + } + } + } + + EngineResult unwrapBuffer(ByteBuffer srcbuf) throws IOException { + EngineResult r = new EngineResult(); + r.srcBuffer = srcbuf; + + ByteBuffer dst = bufPool.getBuffer(); + while (true) { + r.result = engine.unwrap(srcbuf, dst); + switch (r.result.getStatus()) { + case BUFFER_OVERFLOW: + // dest buffer not big enough. Reallocate + int oldcap = dst.capacity(); + dst = getApplicationBuffer(); + assert dst.capacity() > oldcap; + break; + case CLOSED: + doClosure(); + throw new IOException("Engine closed"); + case BUFFER_UNDERFLOW: + bufPool.returnBuffer(dst); + return r; + case OK: + dst.flip(); + r.destBuffer = dst; + return r; + } + } + } + + /** + * Asynchronous read input. Call this when selector fires. + * Unwrap done in upperRead because it also happens in + * doHandshake() when handshake taking place + */ + public void lowerRead(ByteBuffer buffer) { + try { + channelInputQ.put(buffer); + } catch (Throwable t) { + close(); + errorHandler.accept(t); + } + } + + public void upperRead() { + EngineResult r; + ByteBuffer srcbuf; + synchronized (reader) { + try { + srcbuf = channelInputQ.poll(); + if (srcbuf == null) { + return; + } + while (true) { + r = unwrapBuffer(srcbuf); + switch (r.result.getStatus()) { + case BUFFER_UNDERFLOW: + // Buffer too small. Need to combine with next buf + ByteBuffer nextBuf = channelInputQ.poll(); + if (nextBuf == null) { + // no data available. push buffer back until more data available + channelInputQ.pushback(srcbuf); + return; + } else { + srcbuf = combine(srcbuf, nextBuf); + } + break; + case OK: + // check for any handshaking work + synchronized (handshaker) { + if (r.handshaking()) { + // handshaking is happening or is needed + // so we put the buffer back on Q to process again + // later. + channelInputQ.pushback(srcbuf); + readerBlocked = true; + if (!handshaking()) { + // execute the handshake in another thread. + // This method will be called again to resume sending + // later + doHandshake(r); + } + return; + } + } + ByteBuffer dst = r.destBuffer; + if (dst.hasRemaining()) { + receiver.accept(dst); + } + } + if (srcbuf.hasRemaining()) { + continue; + } + srcbuf = channelInputQ.poll(); + if (srcbuf == null) { + return; + } + } + } catch (Throwable t) { + Utils.close(lowerOutput); + errorHandler.accept(t); + } + } + } + + /** + * Get a new buffer that is the right size for application buffers. + * + * @return + */ + ByteBuffer getApplicationBuffer() { + SSLSession session = engine.getSession(); + int appBufsize = session.getApplicationBufferSize(); + bufPool.setMinBufferSize(appBufsize); + return bufPool.getBuffer(appBufsize); + } + + ByteBuffer getPacketBuffer() { + SSLSession session = engine.getSession(); + int packetBufSize = session.getPacketBufferSize(); + bufPool.setMinBufferSize(packetBufSize); + return bufPool.getBuffer(packetBufSize); + } + + ByteBuffer combine(ByteBuffer buf1, ByteBuffer buf2) { + int avail1 = buf1.capacity() - buf1.remaining(); + if (buf2.remaining() < avail1) { + buf1.compact(); + buf1.put(buf2); + buf1.flip(); + return buf1; + } + int newsize = buf1.remaining() + buf2.remaining(); + ByteBuffer newbuf = bufPool.getBuffer(newsize); + newbuf.put(buf1); + newbuf.put(buf2); + newbuf.flip(); + return newbuf; + } + + SSLParameters getSSLParameters() { + return sslParameters; + } + + static void printParams(SSLParameters p) { + System.out.println("SSLParameters:"); + if (p == null) { + System.out.println("Null params"); + return; + } + for (String cipher : p.getCipherSuites()) { + System.out.printf("cipher: %s\n", cipher); + } + for (String approto : p.getApplicationProtocols()) { + System.out.printf("application protocol: %s\n", approto); + } + for (String protocol : p.getProtocols()) { + System.out.printf("protocol: %s\n", protocol); + } + if (p.getServerNames() != null) + for (SNIServerName sname : p.getServerNames()) { + System.out.printf("server name: %s\n", sname.toString()); + } + } + + String getSessionInfo() { + StringBuilder sb = new StringBuilder(); + String application = engine.getApplicationProtocol(); + SSLSession sess = engine.getSession(); + String cipher = sess.getCipherSuite(); + String protocol = sess.getProtocol(); + sb.append("Handshake complete alpn: ") + .append(application) + .append(", Cipher: ") + .append(cipher) + .append(", Protocol: ") + .append(protocol); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java index c06f3886a85..2f1a65cc73f 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java @@ -45,7 +45,7 @@ class AuthenticationFilter implements HeaderFilter { static final int DEFAULT_RETRY_LIMIT = 3; static final int retry_limit = Utils.getIntegerNetProperty( - "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); + "java.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); static final int UNAUTHORIZED = 401; static final int PROXY_UNAUTHORIZED = 407; diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java index a311422a782..eb25e98e9d1 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java @@ -27,11 +27,23 @@ package java.net.http; import java.nio.ByteBuffer; /** - * Implemented by buffer pools. + * Implemented by buffer pools. A buffer pool has a current buffer size + * (number of bytes in each buffer) which may increase over time. */ interface BufferHandler { - ByteBuffer getBuffer(); + default ByteBuffer getBuffer() { + return getBuffer(-1); + } + + void setMinBufferSize(int size); + + /** + * size == -1 means return any sized buffer. Any other value means + * @param size + * @return + */ + ByteBuffer getBuffer(int size); void returnBuffer(ByteBuffer buffer); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java new file mode 100644 index 00000000000..5a37af38b87 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java @@ -0,0 +1,188 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.function.Supplier; + +/** + * Takes a List which is assumed to contain at least one HTTP/2 + * frame and allows it to be processed supplying bytes, ints, shorts, byte[] etc. + * from the list. As each ByteBuffer is consumed it is removed from the List<>. + * + * NOTE. shorts and bytes returned are UNSIGNED ints + * + * When finished processing the frame, the List may be empty or may contain + * partially read or unread ByteBuffers. A new ByteBufferConsumer can be + * created with the List<> + */ +class ByteBufferConsumer { + + ByteBuffer currentBuffer; + + final List buffers; + final ListIterator iterator; + final Supplier newBufferSupplier; + + ByteBufferConsumer(List buffers, + Supplier newBufferSupplier) { + this.buffers = buffers; + this.newBufferSupplier = newBufferSupplier; + this.iterator = buffers.listIterator(); + if (!iterator.hasNext()) { + throw new IllegalArgumentException("Empty buffer list"); + } + currentBuffer = iterator.next(); + } + + private void dump() { + int l = 0; + System.err.printf("ByteBufferConsumer:\n"); + for (ByteBuffer buf : buffers) { + System.err.printf("\t%s\n", buf.toString()); + l+= buf.remaining(); + } + System.err.printf("BBC contains %d bytes\n", l); + } + + private synchronized ByteBuffer getBuffer(boolean exception) throws IOException { + while (currentBuffer == null || !currentBuffer.hasRemaining()) { + if (currentBuffer != null) { + iterator.remove(); + } + if (!iterator.hasNext()) { + currentBuffer = null; + if (exception) { + throw new IOException ("Connection closed unexpectedly"); + } + return null; + } + currentBuffer = iterator.next(); + } + return currentBuffer; + } + + // call this to check if the data has all been consumed + + public boolean consumed() { + try { + return getBuffer(false) == null; + } catch (IOException e) { + /* CAN'T HAPPEN */ + throw new InternalError(); + } + } + + public int getByte() throws IOException { + // TODO: what to do if connection is closed. Throw NPE? + ByteBuffer buf = getBuffer(true); + return buf.get() & 0xff; + } + + public byte[] getBytes(int n) throws IOException { + return getBytes(n, null); + } + + public byte[] getBytes(int n, byte[] buf) throws IOException { + if (buf == null) { + buf = new byte[n]; + } else if (buf.length < n) { + throw new IllegalArgumentException("getBytes: buffer too small"); + } + int offset = 0; + while (n > 0) { + ByteBuffer b = getBuffer(true); + int length = Math.min(n, b.remaining()); + b.get(buf, offset, length); + offset += length; + n -= length; + } + return buf; + } + + public int getShort() throws IOException { + ByteBuffer buf = getBuffer(true); + int rem = buf.remaining(); + if (rem >= 2) { + return buf.getShort() & 0xffff; + } + // Slow path. Not common + int val = 0; + val = (val << 8) + getByte(); + val = (val << 8) + getByte(); + return val; + } + + public int getInt() throws IOException { + ByteBuffer buf = getBuffer(true); + int rem = buf.remaining(); + if (rem >= 4) { + return buf.getInt(); + } + // Slow path. Not common + int val = 0; + for (int nbytes = 0; nbytes < 4; nbytes++) { + val = (val << 8) + getByte(); + } + return val; + } + + private static final ByteBuffer[] EMPTY = new ByteBuffer[0]; + + /** + * Extracts whatever number of ByteBuffers from list to get required number + * of bytes. Any remaining buffers are 'tidied up' so reading can continue. + */ + public ByteBuffer[] getBuffers(int bytecount) throws IOException { + LinkedList l = new LinkedList<>(); + while (bytecount > 0) { + ByteBuffer buffer = getBuffer(true); + int remaining = buffer.remaining(); + if (remaining > bytecount) { + int difference = remaining - bytecount; + // split + ByteBuffer newb = newBufferSupplier.get(); + newb.clear(); + int limit = buffer.limit(); + buffer.limit(limit - difference); + newb.put(buffer); + newb.flip(); + buffer.limit(limit); + l.add(newb); + bytecount = 0; + } else { + l.add(buffer); + currentBuffer = null; + iterator.remove(); + bytecount -= remaining; + } + } + return l.toArray(EMPTY); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java new file mode 100644 index 00000000000..601c4a526b5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java @@ -0,0 +1,136 @@ +/* + * 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 + */ + +package java.net.http; + +import java.nio.ByteBuffer; +import java.util.ArrayList; + +/** + * Manages a ByteBuffer[] for writing frames into for output. The last + * ByteBuffer in the list is always unflipped (able to receive more bytes for + * sending) until getBufferArray() is called, which calls finish(). + * + * This allows multiple frames to be written to the same BBG. + * + * Buffers added with addByteBuffer() must be already flipped. + */ +class ByteBufferGenerator { + + ByteBuffer currentBuffer; + // source is assumed to always return the same sized buffer + final BufferHandler pool; + final ArrayList buflist; + final int bufsize; + boolean finished; + + ByteBufferGenerator(BufferHandler pool) { + this.buflist = new ArrayList<>(); + this.pool = pool; + this.currentBuffer = pool.getBuffer(); + this.bufsize = currentBuffer.capacity(); + } + + private static final ByteBuffer[] EMPTY = new ByteBuffer[0]; + + public ByteBuffer[] getBufferArray() { + finish(); + return buflist.toArray(EMPTY); + } + + public ArrayList getBufferList() { + finish(); + return buflist; + } + + private synchronized void finish() { + if (finished) { + return; + } + finished = true; + currentBuffer.flip(); + if (currentBuffer.hasRemaining()) { + buflist.add(currentBuffer); + } else { + pool.returnBuffer(currentBuffer); + } + } + + // only used for SettingsFrame: offset is number of bytes to + // ignore at start (we only want the payload of the settings frame) + public byte[] asByteArray(int offset) { + ByteBuffer[] bufs = getBufferArray(); + int size = 0; + for (ByteBuffer buf : bufs) { + size += buf.remaining(); + } + byte[] bytes = new byte[size-offset]; + int pos = 0; + for (ByteBuffer buf : bufs) { + int rem = buf.remaining(); + int ignore = Math.min(rem, offset); + buf.position(buf.position()+ignore); + rem -= ignore; + offset -= ignore; + buf.get(bytes, pos, rem); + pos += rem; + } + return bytes; + } + + ByteBuffer getBuffer(long n) { + if (currentBuffer.remaining() < n) { + getNewBuffer(); + if (n > currentBuffer.capacity()) { + throw new IllegalArgumentException("requested buffer too large"); + } + } + return currentBuffer; + } + + void getNewBuffer() { + currentBuffer.flip(); + if (currentBuffer.hasRemaining()) { + buflist.add(currentBuffer); + } else { + pool.returnBuffer(currentBuffer); + } + currentBuffer = pool.getBuffer(); + } + + void addByteBuffer(ByteBuffer buf) { + getNewBuffer(); + buflist.add(buf); + } + + void addPadding(int length) { + while (length > 0) { + int n = Math.min(length, bufsize); + ByteBuffer b = getBuffer(n); + // TODO: currently zeroed? + b.position(b.position() + n); + length -= n; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java b/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java new file mode 100644 index 00000000000..1264fda0a7b --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java @@ -0,0 +1,159 @@ +/* + * 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 + */ +package java.net.http; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; + +import static java.nio.charset.StandardCharsets.UTF_8; + +// The purpose of this class is to separate charset-related tasks from the main +// WebSocket logic, simplifying where possible. +// +// * Coders hide the differences between coding and flushing stages on the +// API level +// * Verifier abstracts the way the verification is performed +// (spoiler: it's a decoding into a throw-away buffer) +// +// Coding methods throw exceptions instead of returning coding result denoting +// errors, since any kind of handling and recovery is not expected. +final class CharsetToolkit { + + private CharsetToolkit() { } + + static final class Verifier { + + private final CharsetDecoder decoder = UTF_8.newDecoder(); + // A buffer used to check validity of UTF-8 byte stream by decoding it. + // The contents of this buffer are never used. + // The size is arbitrary, though it should probably be chosen from the + // performance perspective since it affects the total number of calls to + // decoder.decode() and amount of work in each of these calls + private final CharBuffer blackHole = CharBuffer.allocate(1024); + + void verify(ByteBuffer in, boolean endOfInput) + throws CharacterCodingException { + while (true) { + // Since decoder.flush() cannot produce an error, it's not + // helpful for verification. Therefore this step is skipped. + CoderResult r = decoder.decode(in, blackHole, endOfInput); + if (r.isOverflow()) { + blackHole.clear(); + } else if (r.isUnderflow()) { + break; + } else if (r.isError()) { + r.throwException(); + } else { + // Should not happen + throw new InternalError(); + } + } + } + + Verifier reset() { + decoder.reset(); + return this; + } + } + + static final class Encoder { + + private final CharsetEncoder encoder = UTF_8.newEncoder(); + private boolean coding = true; + + CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) + throws CharacterCodingException { + + if (coding) { + CoderResult r = encoder.encode(in, out, endOfInput); + if (r.isOverflow()) { + return r; + } else if (r.isUnderflow()) { + if (endOfInput) { + coding = false; + } else { + return r; + } + } else if (r.isError()) { + r.throwException(); + } else { + // Should not happen + throw new InternalError(); + } + } + assert !coding; + return encoder.flush(out); + } + + Encoder reset() { + coding = true; + encoder.reset(); + return this; + } + } + + static CharBuffer decode(ByteBuffer in) throws CharacterCodingException { + return UTF_8.newDecoder().decode(in); + } + + static final class Decoder { + + private final CharsetDecoder decoder = UTF_8.newDecoder(); + private boolean coding = true; // Either coding or flushing + + CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput) + throws CharacterCodingException { + + if (coding) { + CoderResult r = decoder.decode(in, out, endOfInput); + if (r.isOverflow()) { + return r; + } else if (r.isUnderflow()) { + if (endOfInput) { + coding = false; + } else { + return r; + } + } else if (r.isError()) { + r.throwException(); + } else { + // Should not happen + throw new InternalError(); + } + } + assert !coding; + return decoder.flush(out); + } + + Decoder reset() { + coding = true; + decoder.reset(); + return this; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java index 70e475ec6e3..fa32ff30adc 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java @@ -35,7 +35,7 @@ import java.util.Objects; class ConnectionPool { static final long KEEP_ALIVE = Utils.getIntegerNetProperty( - "sun.net.httpclient.keepalive.timeout", 1200); // seconds + "java.net.httpclient.keepalive.timeout", 1200); // seconds // Pools of idle connections diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java new file mode 100644 index 00000000000..4981df21ca6 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.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 + */ + +package java.net.http; + +import java.io.IOException; + +class ContinuationFrame extends HeaderFrame { + + public static final int TYPE = 0x9; + + ContinuationFrame() { + type = TYPE; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + headerBlocks = bc.getBuffers(length); + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + for (int i=0; i> userheaders, cookies; - userheaders = r.getUserHeaders().directMap(); + userheaders = r.getUserHeaders().map(); cookies = cookieMan.get(r.uri(), userheaders); // add the returned cookies HttpHeadersImpl systemHeaders = r.getSystemHeaders(); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java new file mode 100644 index 00000000000..d82c7e11623 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class DataFrame extends Http2Frame { + + public final static int TYPE = 0x0; + + DataFrame() { + type = TYPE; + } + + // Flags + public static final int END_STREAM = 0x1; + public static final int PADDED = 0x8; + + int padLength; + int dataLength; + ByteBuffer[] data; + + public void setData(ByteBuffer[] data) { + this.data = data; + setDataLength(); + } + + @Override + String flagAsString(int flag) { + switch (flag) { + case END_STREAM: + return "END_STREAM"; + case PADDED: + return "PADDED"; + } + return super.flagAsString(flag); + } + + public synchronized void setData(ByteBuffer data) { + ByteBuffer[] bb; + if (data == null) { + bb = new ByteBuffer[0]; + } else { + bb = new ByteBuffer[1]; + bb[0] = data; + } + setData(bb); + } + + public synchronized ByteBuffer[] getData() { + return data; + } + + private void setDataLength() { + int len = 0; + for (ByteBuffer buf : data) { + len += buf.remaining(); + } + dataLength = len; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + if ((flags & PADDED) != 0) { + padLength = bc.getByte(); + dataLength = length - (padLength + 1); + } else { + dataLength = length; + } + data = bc.getBuffers(dataLength); + } + + int getPadLength() { + return padLength; + } + + int getDataLength() { + return dataLength; + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + if ((flags & PADDED) != 0) { + ByteBuffer buf = bg.getBuffer(1); + buf.put((byte)getPadLength()); + } + for (int i=0; i LAST_ERROR) { + return "Error: " + Integer.toString(code); + } else { + return errorStrings[code]; + } + } + + int errorCode; + + @Override + public String toString() { + return super.toString() + " Error: " + stringForCode(errorCode); + } + + public int getErrorCode() { + return this.errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java index 9201d22160a..6d00bc2b215 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java @@ -128,7 +128,7 @@ class Exchange { } } - HttpResponseImpl responseImpl0(HttpConnection connection) + private HttpResponseImpl responseImpl0(HttpConnection connection) throws IOException, InterruptedException { exchImpl = ExchangeImpl.get(this, connection); @@ -136,7 +136,7 @@ class Exchange { request.addSystemHeader("Expect", "100-Continue"); exchImpl.sendHeadersOnly(); HttpResponseImpl resp = exchImpl.getResponse(); - logResponse(resp); + Utils.logResponse(resp); if (resp.statusCode() != 100) { return resp; } @@ -145,7 +145,7 @@ class Exchange { } else { exchImpl.sendRequest(); HttpResponseImpl resp = exchImpl.getResponse(); - logResponse(resp); + Utils.logResponse(resp); return checkForUpgrade(resp, exchImpl); } } @@ -163,9 +163,7 @@ class Exchange { } SecurityException e = securityCheck(acc); if (e != null) { - CompletableFuture cf = new CompletableFuture<>(); - cf.completeExceptionally(e); - return cf; + return CompletableFuture.failedFuture(e); } if (permissions.size() > 0) { return AccessController.doPrivileged( @@ -182,9 +180,7 @@ class Exchange { try { exchImpl = ExchangeImpl.get(this, connection); } catch (IOException | InterruptedException e) { - CompletableFuture cf = new CompletableFuture<>(); - cf.completeExceptionally(e); - return cf; + return CompletableFuture.failedFuture(e); } if (request.expectContinue()) { request.addSystemHeader("Expect", "100-Continue"); @@ -200,23 +196,19 @@ class Exchange { return exchImpl.sendBodyAsync() .thenCompose(exchImpl::getResponseAsync) .thenApply((r) -> { - logResponse(r); + Utils.logResponse(r); return r; }); } else { Exchange.this.response = r1; - logResponse(r1); + Utils.logResponse(r1); return CompletableFuture.completedFuture(r1); } }); } else { return exchImpl - .sendHeadersAsync() - .thenCompose((Void v) -> { - // send body and get response at same time - return exchImpl.sendBodyAsync() - .thenCompose(exchImpl::getResponseAsync); - }) + .sendRequestAsync() + .thenCompose(exchImpl::getResponseAsync) .thenCompose((HttpResponseImpl r1) -> { int rcode = r1.statusCode(); CompletableFuture cf = @@ -225,13 +217,13 @@ class Exchange { return cf; } else { Exchange.this.response = r1; - logResponse(r1); + Utils.logResponse(r1); return CompletableFuture.completedFuture(r1); } }) .thenApply((HttpResponseImpl response) -> { this.response = response; - logResponse(response); + Utils.logResponse(response); return response; }); } @@ -254,9 +246,9 @@ class Exchange { client.client2(), this) .thenCompose((Http2Connection c) -> { + c.putConnection(); Stream s = c.getStream(1); exchImpl = s; - c.putConnection(); return s.getResponseAsync(null); }) ); @@ -294,21 +286,6 @@ class Exchange { } - private void logResponse(HttpResponseImpl r) { - if (!Log.requests()) - return; - StringBuilder sb = new StringBuilder(); - String method = r.request().method(); - URI uri = r.uri(); - String uristring = uri == null ? "" : uri.toString(); - sb.append('(') - .append(method) - .append(" ") - .append(uristring) - .append(") ") - .append(Integer.toString(r.statusCode())); - Log.logResponse(sb.toString()); - } CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { return exchImpl.responseBodyAsync(processor); @@ -352,9 +329,9 @@ class Exchange { } String method = request.method(); - HttpHeadersImpl userHeaders = request.getUserHeaders(); + HttpHeaders userHeaders = request.getUserHeaders(); URI u = getURIForSecurityCheck(); - URLPermission p = Utils.getPermission(u, method, userHeaders.directMap()); + URLPermission p = Utils.getPermission(u, method, userHeaders.map()); try { assert acc != null; diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java b/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java new file mode 100644 index 00000000000..5e0d9fb4ebe --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java @@ -0,0 +1,70 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package java.net.http; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +/** + * Represents one frame. May be initialized with a leftover buffer from previous + * frame. Call {@code haveFrame()} to determine if buffers contains at least one + * frame. If false, the obtain another buffer and call {@code}input(ByteBuffer)}. + * There may be additional bytes at end of the frame list. + */ +class FrameReader { + + final List buffers; + + FrameReader() { + buffers = new LinkedList<>(); + } + + FrameReader(FrameReader that) { + this.buffers = that.buffers; + } + + FrameReader(ByteBuffer remainder) { + buffers = new LinkedList<>(); + if (remainder != null) { + buffers.add(remainder); + } + } + + public synchronized void input(ByteBuffer buffer) { + buffers.add(buffer); + } + + public synchronized boolean haveFrame() { + //buffers = Utils.superCompact(buffers, () -> ByteBuffer.allocate(Utils.BUFSIZE)); + int size = 0; + for (ByteBuffer buffer : buffers) { + size += buffer.remaining(); + } + if (size < 3) { + return false; // don't have length yet + } + // we at least have length field + int length = 0; + int j = 0; + ByteBuffer b = buffers.get(j); + b.mark(); + for (int i=0; i<3; i++) { + while (!b.hasRemaining()) { + b.reset(); + b = buffers.get(++j); + b.mark(); + } + length = (length << 8) + (b.get() & 0xff); + } + b.reset(); + return (size >= length + 9); // frame length + } + + synchronized List frame() { + return buffers; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java new file mode 100644 index 00000000000..7737240d300 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java @@ -0,0 +1,104 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class GoAwayFrame extends ErrorFrame { + + GoAwayFrame() { + type = TYPE; + } + + int lastStream; + byte[] debugData = new byte[0]; + + public static final int TYPE = 0x7; + + // Flags + public static final int ACK = 0x1; + + public void setDebugData(byte[] debugData) { + this.debugData = debugData; + } + + @Override + public String toString() { + return super.toString() + " Debugdata: " + new String(debugData); + } + + @Override + String flagAsString(int flag) { + switch (flag) { + case ACK: + return "ACK"; + } + return super.flagAsString(flag); + } + + public void setLastStream(int lastStream) { + this.lastStream = lastStream; + } + + public int getLastStream() { + return this.lastStream; + } + + public byte[] getDebugData() { + return debugData; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + if (length < 8) { + throw new IOException("Invalid GoAway frame"); + } + lastStream = bc.getInt() & 0x7fffffff; + errorCode = bc.getInt(); + //debugData = bc.getBytes(8); + int datalen = length - 8; + if (datalen > 0) { + debugData = bc.getBytes(datalen); + Log.logError("GoAway debugData " + new String(debugData)); + } + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(length); + buf.putInt(lastStream); + buf.putInt(errorCode); + if (length > 8) { + buf.put(debugData); + } + } + + @Override + void computeLength() { + length = 8 + debugData.length; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java new file mode 100644 index 00000000000..57440ea6d37 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java @@ -0,0 +1,77 @@ +/* + * 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 + */ + +package java.net.http; + +import java.nio.ByteBuffer; + +/** + * Either a HeadersFrame or a ContinuationFrame + */ +abstract class HeaderFrame extends Http2Frame { + + int offset; + int number; + int headerLength; + ByteBuffer[] headerBlocks; + + public static final int END_HEADERS = 0x4; + + @Override + String flagAsString(int flag) { + switch (flag) { + case END_HEADERS: + return "END_HEADERS"; + } + return super.flagAsString(flag); + } + + /** + * Sets the array of hpack encoded ByteBuffers + */ + public void setHeaderBlock(ByteBuffer bufs[], int offset, int number) { + this.headerBlocks = bufs; + this.offset = offset; + this.number = number; + int length = 0; + for (int i=offset; i request.getAccessControlContext()); + request::getAccessControlContext); operations.add(cf); return cf; } @@ -269,7 +249,7 @@ class Http1Exchange extends ExchangeImpl { cf.completeExceptionally(e); connection.close(); } - }, () -> request.getAccessControlContext()); + }, request::getAccessControlContext); operations.add(cf); return cf; } @@ -302,7 +282,7 @@ class Http1Exchange extends ExchangeImpl { cf.completeExceptionally(e); connection.close(); } - }, () -> request.getAccessControlContext()); + }, request::getAccessControlContext); operations.add(cf); return cf; } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java index f0da88b3b5c..a4fe1943853 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.net.InetSocketAddress; +import java.net.http.HttpConnection.Mode; import java.nio.charset.StandardCharsets; import java.util.function.LongConsumer; import static java.nio.charset.StandardCharsets.US_ASCII; @@ -48,7 +49,8 @@ class Http1Request { // See line 206 and below for description final ByteBuffer[] buffers; final HttpRequest.BodyProcessor requestProc; - final HttpHeadersImpl userHeaders, systemHeaders; + final HttpHeaders userHeaders; + final HttpHeadersImpl systemHeaders; final LongConsumer flowController; boolean streaming; long contentLength; @@ -91,10 +93,10 @@ class Http1Request { private void collectHeaders1(StringBuilder sb, HttpRequestImpl request, - HttpHeadersImpl headers) + HttpHeaders headers) throws IOException { - Map> h = headers.directMap(); + Map> h = headers.map(); Set>> entries = h.entrySet(); for (Map.Entry> entry : entries) { @@ -112,8 +114,6 @@ class Http1Request { } } - private static final int BUFSIZE = 64 * 1024; // TODO: configurable? - private String getPathAndQuery(URI uri) { String path = uri.getPath(); String query = uri.getQuery(); @@ -134,6 +134,25 @@ class Http1Request { return addr.getHostString() + ":" + addr.getPort(); } + private String hostString() { + URI uri = request.uri(); + int port = uri.getPort(); + String host = uri.getHost(); + + boolean defaultPort; + if (port == -1) + defaultPort = true; + else if (request.secure()) + defaultPort = port == 443; + else + defaultPort = port == 80; + + if (defaultPort) + return host; + else + return host + ":" + Integer.toString(port); + } + private String requestURI() { URI uri = request.uri(); String method = request.method(); @@ -161,6 +180,7 @@ class Http1Request { void sendRequest() throws IOException { collectHeaders(); + chan.configureMode(Mode.BLOCKING); if (contentLength == 0) { chan.write(buffers, 0, 2); } else if (contentLength > 0) { @@ -196,7 +216,7 @@ class Http1Request { buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII)); URI uri = request.uri(); if (uri != null) { - systemHeaders.setHeader("Host", uri.getHost()); + systemHeaders.setHeader("Host", hostString()); } if (request == null) { // this is not a user request. No content diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java index 6fad37b6b8f..d0a937ed4e9 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java @@ -24,7 +24,6 @@ package java.net.http; import java.io.IOException; -import java.net.URI; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java index 4491168225b..2ee03c9de27 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.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 @@ -23,11 +23,133 @@ */ package java.net.http; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import static java.net.http.SettingsFrame.INITIAL_WINDOW_SIZE; +import static java.net.http.SettingsFrame.ENABLE_PUSH; +import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE; +import static java.net.http.SettingsFrame.MAX_CONCURRENT_STREAMS; +import static java.net.http.SettingsFrame.MAX_FRAME_SIZE; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Http2 specific aspects of HttpClientImpl + */ class Http2ClientImpl { - Http2ClientImpl(HttpClientImpl t) {} - String getSettingsString() {return "";} - void debugPrint() {} - Http2Connection getConnectionFor(HttpRequestImpl r) { - return null; + + final private HttpClientImpl client; + + Http2ClientImpl(HttpClientImpl client) { + this.client = client; + } + + /* Map key is "scheme:host:port" */ + final private Map connections = + Collections.synchronizedMap(new HashMap<>()); + + final private Set opening = Collections.synchronizedSet(new HashSet<>()); + + synchronized boolean haveConnectionFor(URI uri, InetSocketAddress proxy) { + return connections.containsKey(Http2Connection.keyFor(uri,proxy)); + } + + /** + * If a https request then blocks and waits until a connection is opened. + * Returns null if the request is 'http' as a different (upgrade) + * mechanism is used. + * + * Only one connection per destination is created. Blocks when opening + * connection, or when waiting for connection to be opened. + * First thread opens the connection and notifies the others when done. + * + * If the request is secure (https) then we open the connection here. + * If not, then the more complicated upgrade from 1.1 to 2 happens (not here) + * In latter case, when the Http2Connection is connected, putConnection() must + * be called to store it. + */ + Http2Connection getConnectionFor(HttpRequestImpl req) + throws IOException, InterruptedException { + URI uri = req.uri(); + InetSocketAddress proxy = req.proxy(); + String key = Http2Connection.keyFor(uri, proxy); + Http2Connection connection; + synchronized (opening) { + while ((connection = connections.get(key)) == null) { + if (!req.secure()) { + return null; + } + if (!opening.contains(key)) { + opening.add(key); + break; + } else { + opening.wait(); + } + } + } + if (connection != null) { + return connection; + } + // we are opening the connection here blocking until it is done. + connection = new Http2Connection(req); + synchronized (opening) { + connections.put(key, connection); + opening.remove(key); + opening.notifyAll(); + } + return connection; + } + + + /* + * TODO: If there isn't a connection to the same destination, then + * store it. If there is already a connection, then close it + */ + synchronized void putConnection(Http2Connection c) { + String key = c.key(); + connections.put(key, c); + } + + synchronized void deleteConnection(Http2Connection c) { + String key = c.key(); + connections.remove(key); + } + + HttpClientImpl client() { + return client; + } + + /** Returns the client settings as a base64 (url) encoded string */ + String getSettingsString() { + SettingsFrame sf = getClientSettings(); + ByteBufferGenerator bg = new ByteBufferGenerator(client); + sf.writeOutgoing(bg); + byte[] settings = bg.asByteArray(9); // without the header + Base64.Encoder encoder = Base64.getUrlEncoder() + .withoutPadding(); + return encoder.encodeToString(settings); + } + + private static final int K = 1024; + + SettingsFrame getClientSettings() { + SettingsFrame frame = new SettingsFrame(); + frame.setParameter(HEADER_TABLE_SIZE, Utils.getIntegerNetProperty( + "java.net.httpclient.hpack.maxheadertablesize", 16 * K)); + frame.setParameter(ENABLE_PUSH, Utils.getIntegerNetProperty( + "java.net.httpclient.enablepush", 1)); + frame.setParameter(MAX_CONCURRENT_STREAMS, Utils.getIntegerNetProperty( + "java.net.httpclient.maxstreams", 16)); + frame.setParameter(INITIAL_WINDOW_SIZE, Utils.getIntegerNetProperty( + "java.net.httpclient.windowsize", 32 * K)); + frame.setParameter(MAX_FRAME_SIZE, Utils.getIntegerNetProperty( + "java.net.httpclient.maxframesize", 16 * K)); + frame.computeLength(); + return frame; } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java index 3f60c4f805e..75eab0f2f34 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.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 @@ -24,42 +24,767 @@ package java.net.http; import java.io.IOException; -import java.net.Authenticator; -import java.net.CookieManager; -import java.net.ProxySelector; +import java.net.InetSocketAddress; import java.net.URI; -import static java.net.http.Utils.BUFSIZE; +import java.net.http.HttpConnection.Mode; import java.nio.ByteBuffer; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import static java.nio.channels.SelectionKey.OP_CONNECT; -import static java.nio.channels.SelectionKey.OP_READ; -import static java.nio.channels.SelectionKey.OP_WRITE; -import java.nio.channels.Selector; +import java.nio.charset.StandardCharsets; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Set; -import java.util.concurrent.*; -import java.security.NoSuchAlgorithmException; -import java.util.ListIterator; -import java.util.Optional; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import sun.net.httpclient.hpack.Encoder; +import sun.net.httpclient.hpack.Decoder; +import static java.net.http.SettingsFrame.*; +import static java.net.http.Utils.BUFSIZE; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Formatter; +import java.util.stream.Collectors; +import sun.net.httpclient.hpack.DecodingCallback; -class Http2Connection { - static CompletableFuture createAsync( - HttpConnection connection, Http2ClientImpl client2, Exchange exchange) { - return null; - } +/** + * An Http2Connection. Encapsulates the socket(channel) and any SSLEngine used + * over it. Contains an HttpConnection which hides the SocketChannel SSL stuff. + * + * Http2Connections belong to a Http2ClientImpl, (one of) which belongs + * to a HttpClientImpl. + * + * Creation cases: + * 1) upgraded HTTP/1.1 plain tcp connection + * 2) prior knowledge directly created plain tcp connection + * 3) directly created HTTP/2 SSL connection which uses ALPN. + * + * Sending is done by writing directly to underlying HttpConnection object which + * is operating in async mode. No flow control applies on output at this level + * and all writes are just executed as puts to an output Q belonging to HttpConnection + * Flow control is implemented by HTTP/2 protocol itself. + * + * Hpack header compression + * and outgoing stream creation is also done here, because these operations + * must be synchronized at the socket level. Stream objects send frames simply + * by placing them on the connection's output Queue. sendFrame() is called + * from a higher level (Stream) thread. + * + * asyncReceive(ByteBuffer) is always called from the selector thread. It assembles + * incoming Http2Frames, and directs them to the appropriate Stream.incoming() + * or handles them directly itself. This thread performs hpack decompression + * and incoming stream creation (Server push). Incoming frames destined for a + * stream are provided by calling Stream.incoming(). + */ +class Http2Connection implements BufferHandler { + final Queue outputQ; + volatile boolean closed; + + //------------------------------------- + final HttpConnection connection; + HttpClientImpl client; + final Http2ClientImpl client2; + Map streams; + int nextstreamid = 3; // stream 1 is registered separately + int nextPushStream = 2; + Encoder hpackOut; + Decoder hpackIn; + SettingsFrame clientSettings, serverSettings; + ByteBufferConsumer bbc; + final LinkedList freeList; + final String key; // for HttpClientImpl.connections map + FrameReader reader; + + // Connection level flow control windows + int sendWindow = INITIAL_WINDOW_SIZE; + + final static int DEFAULT_FRAME_SIZE = 16 * 1024; + private static ByteBuffer[] empty = Utils.EMPTY_BB_ARRAY; + + final ExecutorWrapper executor; + + /** + * This is established by the protocol spec and the peer will update it with + * WINDOW_UPDATEs, which affects the sendWindow. + */ + final static int INITIAL_WINDOW_SIZE = 64 * 1024 - 1; + + // TODO: need list of control frames from other threads + // that need to be sent + + /** + * Case 1) Create from upgraded HTTP/1.1 connection. + * Is ready to use. Will not be SSL. exchange is the Exchange + * that initiated the connection, whose response will be delivered + * on a Stream. + */ Http2Connection(HttpConnection connection, Http2ClientImpl client2, Exchange exchange) throws IOException, InterruptedException { + this.outputQ = new Queue<>(); + String msg = "Connection send window size " + Integer.toString(sendWindow); + Log.logTrace(msg); + + //this.initialExchange = exchange; + assert !(connection instanceof SSLConnection); + this.connection = connection; + this.client = client2.client(); + this.client2 = client2; + this.executor = client.executorWrapper(); + this.freeList = new LinkedList<>(); + this.key = keyFor(connection); + streams = Collections.synchronizedMap(new HashMap<>()); + initCommon(); + //sendConnectionPreface(); + Stream initialStream = createStream(exchange); + initialStream.registerStream(1); + initialStream.requestSent(); + sendConnectionPreface(); + connection.configureMode(Mode.ASYNC); + // start reading and writing + // start reading + AsyncConnection asyncConn = (AsyncConnection)connection; + asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown); + asyncReceive(connection.getRemaining()); + asyncConn.startReading(); } - Stream getStream(int i) {return null;} - Stream createStream(Exchange ex) {return null;} - void putConnection() {} + // async style but completes immediately + static CompletableFuture createAsync(HttpConnection connection, + Http2ClientImpl client2, Exchange exchange) { + CompletableFuture cf = new CompletableFuture<>(); + try { + Http2Connection c = new Http2Connection(connection, client2, exchange); + cf.complete(c); + } catch (IOException | InterruptedException e) { + cf.completeExceptionally(e); + } + return cf; + } + + /** + * Cases 2) 3) + * + * request is request to be sent. + */ + Http2Connection(HttpRequestImpl request) throws IOException, InterruptedException { + InetSocketAddress proxy = request.proxy(); + URI uri = request.uri(); + InetSocketAddress addr = Utils.getAddress(request); + String msg = "Connection send window size " + Integer.toString(sendWindow); + Log.logTrace(msg); + this.key = keyFor(uri, proxy); + this.connection = HttpConnection.getConnection(addr, request, this); + streams = Collections.synchronizedMap(new HashMap<>()); + this.client = request.client(); + this.client2 = client.client2(); + this.executor = client.executorWrapper(); + this.freeList = new LinkedList<>(); + this.outputQ = new Queue<>(); + nextstreamid = 1; + initCommon(); + connection.connect(); + connection.configureMode(Mode.ASYNC); + // start reading + AsyncConnection asyncConn = (AsyncConnection)connection; + asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown); + sendConnectionPreface(); + asyncConn.startReading(); + } + + // NEW + synchronized void obtainSendWindow(int amount) throws InterruptedException { + while (amount > 0) { + int n = Math.min(amount, sendWindow); + sendWindow -= n; + amount -= n; + if (amount > 0) + wait(); + } + } + + synchronized void updateSendWindow(int amount) { + if (sendWindow == 0) { + sendWindow += amount; + notifyAll(); + } else + sendWindow += amount; + } + + synchronized int sendWindow() { + return sendWindow; + } + + static String keyFor(HttpConnection connection) { + boolean isProxy = connection.isProxied(); + boolean isSecure = connection.isSecure(); + InetSocketAddress addr = connection.address(); + + return keyString(isSecure, isProxy, addr.getHostString(), addr.getPort()); + } + + static String keyFor(URI uri, InetSocketAddress proxy) { + boolean isSecure = uri.getScheme().equalsIgnoreCase("https"); + boolean isProxy = proxy != null; + + String host; + int port; + + if (isProxy) { + host = proxy.getHostString(); + port = proxy.getPort(); + } else { + host = uri.getHost(); + port = uri.getPort(); + } + return keyString(isSecure, isProxy, host, port); + } + + // {C,S}:{H:P}:host:port + // C indicates clear text connection "http" + // S indicates secure "https" + // H indicates host (direct) connection + // P indicates proxy + // Eg: "S:H:foo.com:80" + static String keyString(boolean secure, boolean proxy, String host, int port) { + char c1 = secure ? 'S' : 'C'; + char c2 = proxy ? 'P' : 'H'; + + StringBuilder sb = new StringBuilder(128); + sb.append(c1).append(':').append(c2).append(':') + .append(host).append(':').append(port); + return sb.toString(); + } + + String key() { + return this.key; + } + + void putConnection() { + client2.putConnection(this); + } + + private static String toHexdump1(ByteBuffer bb) { + bb.mark(); + StringBuilder sb = new StringBuilder(512); + Formatter f = new Formatter(sb); + + while (bb.hasRemaining()) { + int i = Byte.toUnsignedInt(bb.get()); + f.format("%02x:", i); + } + sb.deleteCharAt(sb.length()-1); + bb.reset(); + return sb.toString(); + } + + private static String toHexdump(ByteBuffer bb) { + List words = new ArrayList<>(); + int i = 0; + bb.mark(); + 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++; + } + bb.reset(); + return words.stream().collect(Collectors.joining(" ")); + } + + private void decodeHeaders(HeaderFrame frame, DecodingCallback decoder) { + boolean endOfHeaders = frame.getFlag(HeaderFrame.END_HEADERS); + + ByteBuffer[] buffers = frame.getHeaderBlock(); + for (int i = 0; i < buffers.length; i++) { + hpackIn.decode(buffers[i], endOfHeaders, decoder); + } + } + + int getInitialSendWindowSize() { + return serverSettings.getParameter(SettingsFrame.INITIAL_WINDOW_SIZE); + } + + void close() { + GoAwayFrame f = new GoAwayFrame(); + f.setDebugData("Requested by user".getBytes()); + // TODO: set last stream. For now zero ok. + sendFrame(f); + } + + // BufferHandler methods + + @Override + public ByteBuffer getBuffer(int n) { + return client.getBuffer(n); + } + + @Override + public void returnBuffer(ByteBuffer buf) { + client.returnBuffer(buf); + } + + @Override + public void setMinBufferSize(int n) { + client.setMinBufferSize(n); + } + + private final Object readlock = new Object(); + + void asyncReceive(ByteBuffer buffer) { + synchronized (readlock) { + try { + if (reader == null) { + reader = new FrameReader(buffer); + } else { + reader.input(buffer); + } + while (true) { + if (reader.haveFrame()) { + List buffers = reader.frame(); + + ByteBufferConsumer bbc = new ByteBufferConsumer(buffers, this::getBuffer); + processFrame(bbc); + if (bbc.consumed()) { + reader = new FrameReader(); + return; + } else { + reader = new FrameReader(reader); + } + } else + return; + } + } catch (Throwable e) { + String msg = Utils.stackTrace(e); + Log.logTrace(msg); + shutdown(e); + } + } + } + + void shutdown(Throwable t) { + System.err.println("Shutdown: " + t); + t.printStackTrace(); + closed = true; + client2.deleteConnection(this); + Collection c = streams.values(); + for (Stream s : c) { + s.cancelImpl(t); + } + connection.close(); + } + + /** + * Handles stream 0 (common) frames that apply to whole connection and passes + * other stream specific frames to that Stream object. + * + * Invokes Stream.incoming() which is expected to process frame without + * blocking. + */ + void processFrame(ByteBufferConsumer bbc) throws IOException, InterruptedException { + Http2Frame frame = Http2Frame.readIncoming(bbc); + Log.logFrames(frame, "IN"); + int streamid = frame.streamid(); + if (streamid == 0) { + handleCommonFrame(frame); + } else { + Stream stream = getStream(streamid); + if (stream == null) { + // should never receive a frame with unknown stream id + resetStream(streamid, ResetFrame.PROTOCOL_ERROR); + } + if (frame instanceof PushPromiseFrame) { + PushPromiseFrame pp = (PushPromiseFrame)frame; + handlePushPromise(stream, pp); + } else if (frame instanceof HeaderFrame) { + // decode headers (or continuation) + decodeHeaders((HeaderFrame) frame, stream.rspHeadersConsumer()); + stream.incoming(frame); + } else + stream.incoming(frame); + } + } + + private void handlePushPromise(Stream parent, PushPromiseFrame pp) + throws IOException, InterruptedException { + + HttpRequestImpl parentReq = parent.request; + int promisedStreamid = pp.getPromisedStream(); + if (promisedStreamid != nextPushStream) { + resetStream(promisedStreamid, ResetFrame.PROTOCOL_ERROR); + return; + } else { + nextPushStream += 2; + } + HeaderDecoder decoder = new HeaderDecoder(); + decodeHeaders(pp, decoder); + HttpHeadersImpl headers = decoder.headers(); + HttpRequestImpl pushReq = HttpRequestImpl.createPushRequest(parentReq, headers); + + Stream.PushedStream pushStream = createPushStream(parent, pushReq); + pushStream.registerStream(promisedStreamid); + parent.incoming_pushPromise(pushReq, pushStream); + } + + private void handleCommonFrame(Http2Frame frame) + throws IOException, InterruptedException { + + switch (frame.type()) { + case SettingsFrame.TYPE: + { SettingsFrame f = (SettingsFrame)frame; + handleSettings(f);} + break; + case PingFrame.TYPE: + { PingFrame f = (PingFrame)frame; + handlePing(f);} + break; + case GoAwayFrame.TYPE: + { GoAwayFrame f = (GoAwayFrame)frame; + handleGoAway(f);} + break; + case WindowUpdateFrame.TYPE: + { WindowUpdateFrame f = (WindowUpdateFrame)frame; + handleWindowUpdate(f);} + break; + default: + protocolError(ErrorFrame.PROTOCOL_ERROR); + } + } + + void resetStream(int streamid, int code) throws IOException, InterruptedException { + Log.logError( + "Resetting stream {0,number,integer} with error code {1,number,integer}", + streamid, code); + ResetFrame frame = new ResetFrame(); + frame.streamid(streamid); + frame.setErrorCode(code); + sendFrame(frame); + streams.remove(streamid); + } + + private void handleWindowUpdate(WindowUpdateFrame f) + throws IOException, InterruptedException { + updateSendWindow(f.getUpdate()); + } + + private void protocolError(int errorCode) + throws IOException, InterruptedException { + GoAwayFrame frame = new GoAwayFrame(); + frame.setErrorCode(errorCode); + sendFrame(frame); + String msg = "Error code: " + errorCode; + shutdown(new IOException("protocol error")); + } + + private void handleSettings(SettingsFrame frame) + throws IOException, InterruptedException { + if (frame.getFlag(SettingsFrame.ACK)) { + // ignore ack frames for now. + return; + } + serverSettings = frame; + SettingsFrame ack = getAckFrame(frame.streamid()); + sendFrame(ack); + } + + private void handlePing(PingFrame frame) + throws IOException, InterruptedException { + frame.setFlag(PingFrame.ACK); + sendFrame(frame); + } + + private void handleGoAway(GoAwayFrame frame) + throws IOException, InterruptedException { + //System.err.printf("GoAWAY: %s\n", ErrorFrame.stringForCode(frame.getErrorCode())); + shutdown(new IOException("GOAWAY received")); + } + + private void initCommon() { + clientSettings = client2.getClientSettings(); + + // serverSettings will be updated by server + serverSettings = SettingsFrame.getDefaultSettings(); + hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE)); + hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE)); + } + + /** + * Max frame size we are allowed to send + */ + public int getMaxSendFrameSize() { + int param = serverSettings.getParameter(MAX_FRAME_SIZE); + if (param == -1) { + param = DEFAULT_FRAME_SIZE; + } + return param; + } + + /** + * Max frame size we will receive + */ + public int getMaxReceiveFrameSize() { + return clientSettings.getParameter(MAX_FRAME_SIZE); + } + + // Not sure how useful this is. + public int getMaxHeadersSize() { + return serverSettings.getParameter(MAX_HEADER_LIST_SIZE); + } + + private static final String CLIENT_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; + + private static final byte[] PREFACE_BYTES = + CLIENT_PREFACE.getBytes(StandardCharsets.ISO_8859_1); + + /** + * Sends Connection preface and Settings frame with current preferred + * values + */ + private void sendConnectionPreface() throws IOException { + ByteBufferGenerator bg = new ByteBufferGenerator(this); + bg.getBuffer(PREFACE_BYTES.length).put(PREFACE_BYTES); + ByteBuffer[] ba = bg.getBufferArray(); + connection.write(ba, 0, ba.length); + + bg = new ByteBufferGenerator(this); + SettingsFrame sf = client2.getClientSettings(); + Log.logFrames(sf, "OUT"); + sf.writeOutgoing(bg); + WindowUpdateFrame wup = new WindowUpdateFrame(); + wup.streamid(0); + // send a Window update for the receive buffer we are using + // minus the initial 64 K specified in protocol + wup.setUpdate(client2.client().getReceiveBufferSize() - (64 * 1024 - 1)); + wup.computeLength(); + wup.writeOutgoing(bg); + Log.logFrames(wup, "OUT"); + ba = bg.getBufferArray(); + connection.write(ba, 0, ba.length); + } + + /** + * Returns an existing Stream with given id, or null if doesn't exist + */ + Stream getStream(int streamid) { + return streams.get(streamid); + } + + /** + * Creates Stream with given id. + */ + Stream createStream(Exchange exchange) { + Stream stream = new Stream(client, this, exchange); + return stream; + } + + Stream.PushedStream createPushStream(Stream parent, HttpRequestImpl pushReq) { + Stream.PushGroup pg = parent.request.pushGroup(); + return new Stream.PushedStream(pg, client, this, parent, pushReq); + } + + void putStream(Stream stream, int streamid) { + streams.put(streamid, stream); + } + + void deleteStream(Stream stream) { + streams.remove(stream.streamid); + } + + static final int MAX_STREAM = Integer.MAX_VALUE - 2; + + // Number of header bytes in a Headers Frame + final static int HEADERS_HEADER_SIZE = 15; + + // Number of header bytes in a Continuation frame + final static int CONTIN_HEADER_SIZE = 9; + + /** + * Encode the headers into a List and then create HEADERS + * and CONTINUATION frames from the list and return the List. + * + * @param frame + * @return + */ + private LinkedList encodeHeaders(OutgoingHeaders frame) { + LinkedList buffers = new LinkedList<>(); + ByteBuffer buf = getBuffer(); + buffers.add(buf); + encodeHeadersImpl(frame.stream.getRequestPseudoHeaders(), buffers); + encodeHeadersImpl(frame.getUserHeaders(), buffers); + encodeHeadersImpl(frame.getSystemHeaders(), buffers); + + for (ByteBuffer b : buffers) { + b.flip(); + } + + LinkedList frames = new LinkedList<>(); + int maxframesize = getMaxSendFrameSize(); + + HeadersFrame oframe = new HeadersFrame(); + oframe.setFlags(frame.getFlags()); + oframe.streamid(frame.streamid()); + + oframe.setHeaderBlock(getBufferArray(buffers, maxframesize)); + frames.add(oframe); + // Any buffers left? + boolean done = buffers.isEmpty(); + if (done) { + oframe.setFlag(HeaderFrame.END_HEADERS); + } else { + ContinuationFrame cf = null; + while (!done) { + cf = new ContinuationFrame(); + cf.streamid(frame.streamid()); + cf.setHeaderBlock(getBufferArray(buffers, maxframesize)); + frames.add(cf); + done = buffers.isEmpty(); + } + cf.setFlag(HeaderFrame.END_HEADERS); + } + return frames; + } + + // should always return at least one buffer + private static ByteBuffer[] getBufferArray(LinkedList list, int maxsize) { + assert maxsize >= BUFSIZE; + LinkedList newlist = new LinkedList<>(); + int size = list.size(); + int nbytes = 0; + for (int i=0; i buffers) { + ByteBuffer buffer; + if (!(buffer = buffers.getLast()).hasRemaining()) { + buffer = getBuffer(); + buffers.add(buffer); + } + for (Map.Entry> e : hdrs.map().entrySet()) { + String key = e.getKey(); + String lkey = key.toLowerCase(); + List values = e.getValue(); + for (String value : values) { + hpackOut.header(lkey, value); + boolean encoded = false; + do { + encoded = hpackOut.encode(buffer); + if (!encoded) { + buffer = getBuffer(); + buffers.add(buffer); + } + } while (!encoded); + } + } + } + + public void sendFrames(List frames) throws IOException, InterruptedException { + for (Http2Frame frame : frames) { + sendFrame(frame); + } + } + + static Throwable getExceptionFrom(CompletableFuture cf) { + try { + cf.get(); + return null; + } catch (Throwable e) { + if (e.getCause() != null) + return e.getCause(); + else + return e; + } + } + + + void execute(Runnable r) { + executor.execute(r, null); + } + + private final Object sendlock = new Object(); + + /** + * + */ + void sendFrame(Http2Frame frame) { + synchronized (sendlock) { + try { + if (frame instanceof OutgoingHeaders) { + OutgoingHeaders oh = (OutgoingHeaders) frame; + Stream stream = oh.getStream(); + stream.registerStream(nextstreamid); + oh.streamid(nextstreamid); + nextstreamid += 2; + // set outgoing window here. This allows thread sending + // body to proceed. + stream.updateOutgoingWindow(getInitialSendWindowSize()); + LinkedList frames = encodeHeaders(oh); + for (Http2Frame f : frames) { + sendOneFrame(f); + } + } else { + sendOneFrame(frame); + } + + } catch (IOException e) { + if (!closed) { + Log.logError(e); + shutdown(e); + } + } + } + } + + /** + * Send a frame. + * + * @param frame + * @throws IOException + */ + private void sendOneFrame(Http2Frame frame) throws IOException { + ByteBufferGenerator bbg = new ByteBufferGenerator(this); + frame.computeLength(); + Log.logFrames(frame, "OUT"); + frame.writeOutgoing(bbg); + ByteBuffer[] currentBufs = bbg.getBufferArray(); + connection.write(currentBufs, 0, currentBufs.length); + } + + + private SettingsFrame getAckFrame(int streamid) { + SettingsFrame frame = new SettingsFrame(); + frame.setFlag(SettingsFrame.ACK); + frame.streamid(streamid); + return frame; + } + + static class HeaderDecoder implements DecodingCallback { + HttpHeadersImpl headers; + + HeaderDecoder() { + this.headers = new HttpHeadersImpl(); + } + + @Override + public void onDecoded(CharSequence name, CharSequence value) { + headers.addHeader(name.toString(), value.toString()); + } + + HttpHeadersImpl headers() { + return headers; + } + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java new file mode 100644 index 00000000000..273fb75fc32 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java @@ -0,0 +1,211 @@ +/* + * 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * When sending a frame, the length field must be set in sub-class + * by calling computeLength() + */ +abstract class Http2Frame { + + int length = -1; + int type; + int streamid; + int flags; + + // called when reading in only + void initCommon(int length, int type, int streamid, int flags) { + this.length = length; + this.type = type; + this.streamid = streamid; + this.flags = flags; + } + + public int length() { + return length; + } + + public int type() { + return type; + } + + public int streamid() { + return streamid; + } + + public void setFlag(int flag) { + flags |= flag; + } + + public void setFlags(int flags) { + this.flags = flags; + } + + public int getFlags() { + return flags; + } + + public boolean getFlag(int flag) { + return (flags & flag) != 0; + } + + public void clearFlag(int flag) { + flags &= 0xffffffff ^ flag; + } + + public void streamid(int streamid) { + this.streamid = streamid; + } + + abstract void readIncomingImpl(ByteBufferConsumer bc) throws IOException; + + /** + * assume given array contains at least one complete frame. + */ + static Http2Frame readIncoming(ByteBufferConsumer bc) throws IOException { + int x = bc.getInt(); + int length = x >> 8; + int type = x & 0xff; + int flags = bc.getByte(); + int streamid = bc.getInt(); + Http2Frame f = null; + switch (type) { + case DataFrame.TYPE: + f = new DataFrame(); + break; + case HeadersFrame.TYPE: + f = new HeadersFrame(); + break; + case ContinuationFrame.TYPE: + f = new ContinuationFrame(); + break; + case ResetFrame.TYPE: + f = new ResetFrame(); + break; + case PriorityFrame.TYPE: + f = new PriorityFrame(); + break; + case SettingsFrame.TYPE: + f = new SettingsFrame(); + break; + case GoAwayFrame.TYPE: + f = new GoAwayFrame(); + break; + case PingFrame.TYPE: + f = new PingFrame(); + break; + case PushPromiseFrame.TYPE: + f = new PushPromiseFrame(); + break; + case WindowUpdateFrame.TYPE: + f = new WindowUpdateFrame(); + break; + default: + String msg = Integer.toString(type); + throw new IOException("unknown frame type " + msg); + } + f.initCommon(length, type, streamid, flags); + f.readIncomingImpl(bc); + return f; + } + + public String typeAsString() { + return asString(this.type); + } + + public static String asString(int type) { + switch (type) { + case DataFrame.TYPE: + return "DATA"; + case HeadersFrame.TYPE: + return "HEADERS"; + case ContinuationFrame.TYPE: + return "CONTINUATION"; + case ResetFrame.TYPE: + return "RESET"; + case PriorityFrame.TYPE: + return "PRIORITY"; + case SettingsFrame.TYPE: + return "SETTINGS"; + case GoAwayFrame.TYPE: + return "GOAWAY"; + case PingFrame.TYPE: + return "PING"; + case PushPromiseFrame.TYPE: + return "PUSH_PROMISE"; + case WindowUpdateFrame.TYPE: + return "WINDOW_UPDATE"; + default: + return "UNKNOWN"; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(typeAsString()) + .append(": length=") + .append(Integer.toString(length)) + .append(", streamid=") + .append(streamid) + .append(", flags="); + + int f = flags; + int i = 0; + if (f == 0) { + sb.append("0 "); + } else { + while (f != 0) { + if ((f & 1) == 1) { + sb.append(flagAsString(1 << i)) + .append(' '); + } + f = f >> 1; + i++; + } + } + return sb.toString(); + } + + // Override + String flagAsString(int f) { + return "unknown"; + } + + abstract void computeLength(); + + void writeOutgoing(ByteBufferGenerator bg) { + if (length == -1) { + throw new InternalError("Length not set on outgoing frame"); + } + ByteBuffer buf = bg.getBuffer(9); + int x = (length << 8) + type; + buf.putInt(x); + buf.put((byte)flags); + buf.putInt(streamid); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java index fd1ab0b012d..0d20fa9a8a9 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java @@ -23,28 +23,32 @@ */ package java.net.http; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; import java.io.IOException; import java.net.Authenticator; import java.net.CookieManager; import java.net.ProxySelector; import java.net.URI; -import static java.net.http.Utils.BUFSIZE; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; -import static java.nio.channels.SelectionKey.OP_CONNECT; -import static java.nio.channels.SelectionKey.OP_READ; -import static java.nio.channels.SelectionKey.OP_WRITE; import java.nio.channels.Selector; -import java.util.*; -import java.util.stream.Stream; -import java.util.concurrent.ExecutorService; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; +import java.util.stream.Stream; + +import static java.net.http.Utils.BUFSIZE; /** * Client implementation. Contains all configuration information and also @@ -53,6 +57,9 @@ import javax.net.ssl.SSLParameters; */ class HttpClientImpl extends HttpClient implements BufferHandler { + private static final ThreadFactory defaultFactory = + (r -> new Thread(null, r, "HttpClient_worker", 0, true)); + private final CookieManager cookieManager; private final Redirect followRedirects; private final ProxySelector proxySelector; @@ -67,7 +74,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler { private final SelectorManager selmgr; private final FilterFactory filters; private final Http2ClientImpl client2; - private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); private final LinkedList timeouts; public static HttpClientImpl create(HttpClientBuilderImpl builder) { @@ -115,7 +121,6 @@ class HttpClientImpl extends HttpClient implements BufferHandler { throw new InternalError(e); } selmgr.setDaemon(true); - selmgr.setName("HttpSelector"); filters = new FilterFactory(); initFilters(); } @@ -135,7 +140,7 @@ class HttpClientImpl extends HttpClient implements BufferHandler { * 4) - mark connection as blocking * 5) - call AsyncEvent.handle() * - * If exchange needs to block again, then call registerEvent() again + * If exchange needs to block again, then call registerEvent() again */ void registerEvent(AsyncEvent exchange) throws IOException { selmgr.register(exchange); @@ -145,35 +150,56 @@ class HttpClientImpl extends HttpClient implements BufferHandler { return client2; } - LinkedList freelist = new LinkedList<>(); + /** + * We keep one size of buffer on free list. That size may increase + * depending on demand. If that happens we dispose of free buffers + * that are smaller than new size. + */ + private final LinkedList freelist = new LinkedList<>(); + int currentSize = BUFSIZE; @Override - public synchronized ByteBuffer getBuffer() { - if (freelist.isEmpty()) { - return ByteBuffer.allocate(BUFSIZE); + public synchronized ByteBuffer getBuffer(int size) { + + ByteBuffer buf; + if (size == -1) + size = currentSize; + + if (size > currentSize) + currentSize = size; + + while (!freelist.isEmpty()) { + buf = freelist.removeFirst(); + if (buf.capacity() < currentSize) + continue; + buf.clear(); + return buf; } - return freelist.removeFirst(); + return ByteBuffer.allocate(size); } @Override public synchronized void returnBuffer(ByteBuffer buffer) { - buffer.clear(); freelist.add(buffer); } + @Override + public synchronized void setMinBufferSize(int n) { + currentSize = Math.max(n, currentSize); + } // Main loop for this client's selector + private final class SelectorManager extends Thread { - class SelectorManager extends Thread { - final Selector selector; - boolean closed; - - final List readyList; - final List registrations; + private final Selector selector; + private volatile boolean closed; + private final List readyList; + private final List registrations; SelectorManager() throws IOException { - readyList = new LinkedList<>(); - registrations = new LinkedList<>(); + super(null, null, "SelectorManager", 0, false); + readyList = new ArrayList<>(); + registrations = new ArrayList<>(); selector = Selector.open(); } @@ -193,32 +219,13 @@ class HttpClientImpl extends HttpClient implements BufferHandler { closed = true; try { selector.close(); - } catch (IOException e) {} - } - - private List copy(List list) { - LinkedList c = new LinkedList<>(); - for (AsyncEvent e : list) { - c.add(e); - } - return c; - } - - String opvals(int i) { - StringBuilder sb = new StringBuilder(); - if ((i & OP_READ) != 0) - sb.append("OP_READ "); - if ((i & OP_CONNECT) != 0) - sb.append("OP_CONNECT "); - if ((i & OP_WRITE) != 0) - sb.append("OP_WRITE "); - return sb.toString(); + } catch (IOException ignored) { } } @Override public void run() { try { - while (true) { + while (!Thread.currentThread().isInterrupted()) { synchronized (this) { for (AsyncEvent exchange : registrations) { SelectableChannel c = exchange.channel(); @@ -229,7 +236,7 @@ class HttpClientImpl extends HttpClient implements BufferHandler { if (key == null) { sa = new SelectorAttachment(c, selector); } else { - sa = (SelectorAttachment)key.attachment(); + sa = (SelectorAttachment) key.attachment(); } sa.register(exchange); } catch (IOException e) { @@ -243,6 +250,7 @@ class HttpClientImpl extends HttpClient implements BufferHandler { } long timeval = getTimeoutValue(); long now = System.currentTimeMillis(); + //debugPrint(selector); int n = selector.select(timeval); if (n == 0) { signalTimeouts(now); @@ -251,7 +259,7 @@ class HttpClientImpl extends HttpClient implements BufferHandler { Set keys = selector.selectedKeys(); for (SelectionKey key : keys) { - SelectorAttachment sa = (SelectorAttachment)key.attachment(); + SelectorAttachment sa = (SelectorAttachment) key.attachment(); int eventsOccurred = key.readyOps(); sa.events(eventsOccurred).forEach(readyList::add); sa.resetInterestOps(eventsOccurred); @@ -260,10 +268,8 @@ class HttpClientImpl extends HttpClient implements BufferHandler { selector.selectedKeys().clear(); for (AsyncEvent exchange : readyList) { - if (exchange instanceof AsyncEvent.Blocking) { + if (exchange.blocking()) { exchange.channel().configureBlocking(true); - } else { - assert exchange instanceof AsyncEvent.NonBlocking; } executor.synchronize(); handleEvent(exchange); // will be delegated to executor @@ -272,14 +278,26 @@ class HttpClientImpl extends HttpClient implements BufferHandler { } } catch (Throwable e) { if (!closed) { - System.err.println("HttpClientImpl terminating on error"); // This terminates thread. So, better just print stack trace String err = Utils.stackTrace(e); Log.logError("HttpClientImpl: fatal error: " + err); } + } finally { + shutdown(); } } + void debugPrint(Selector selector) { + System.err.println("Selector: debugprint start"); + Set keys = selector.keys(); + for (SelectionKey key : keys) { + SelectableChannel c = key.channel(); + int ops = key.interestOps(); + System.err.printf("selector chan:%s ops:%d\n", c, ops); + } + System.err.println("Selector: debugprint end"); + } + void handleEvent(AsyncEvent e) { if (closed) { e.abort(); @@ -303,7 +321,7 @@ class HttpClientImpl extends HttpClient implements BufferHandler { private final SelectableChannel chan; private final Selector selector; private final ArrayList pending; - private int interestops; + private int interestOps; SelectorAttachment(SelectableChannel chan, Selector selector) { this.pending = new ArrayList<>(); @@ -312,53 +330,53 @@ class HttpClientImpl extends HttpClient implements BufferHandler { } void register(AsyncEvent e) throws ClosedChannelException { - int newops = e.interestOps(); - boolean reRegister = (interestops & newops) != newops; - interestops |= newops; + int newOps = e.interestOps(); + boolean reRegister = (interestOps & newOps) != newOps; + interestOps |= newOps; pending.add(e); if (reRegister) { // first time registration happens here also - chan.register(selector, interestops, this); + chan.register(selector, interestOps, this); } } - int interestOps() { - return interestops; - } - /** * Returns a Stream containing only events that are - * registered with the given {@code interestop}. + * registered with the given {@code interestOps}. */ - Stream events(int interestop) { + Stream events(int interestOps) { return pending.stream() - .filter(ev -> (ev.interestOps() & interestop) != 0); + .filter(ev -> (ev.interestOps() & interestOps) != 0); } /** - * Removes any events with the given {@code interestop}, and if no + * Removes any events with the given {@code interestOps}, and if no * events remaining, cancels the associated SelectionKey. */ - void resetInterestOps(int interestop) { - int newops = 0; + void resetInterestOps(int interestOps) { + int newOps = 0; Iterator itr = pending.iterator(); while (itr.hasNext()) { AsyncEvent event = itr.next(); int evops = event.interestOps(); - if ((evops & interestop) != 0) { + if (event.repeating()) { + newOps |= evops; + continue; + } + if ((evops & interestOps) != 0) { itr.remove(); } else { - newops |= evops; + newOps |= evops; } } - interestops = newops; + this.interestOps = newOps; SelectionKey key = chan.keyFor(selector); - if (newops == 0) { + if (newOps == 0) { key.cancel(); } else { - key.interestOps(newops); + key.interestOps(newOps); } } } @@ -366,7 +384,8 @@ class HttpClientImpl extends HttpClient implements BufferHandler { /** * Creates a HttpRequest associated with this group. * - * @throws IllegalStateException if the group has been stopped + * @throws IllegalStateException + * if the group has been stopped */ @Override public HttpRequestBuilderImpl request() { @@ -376,7 +395,8 @@ class HttpClientImpl extends HttpClient implements BufferHandler { /** * Creates a HttpRequest associated with this group. * - * @throws IllegalStateException if the group has been stopped + * @throws IllegalStateException + * if the group has been stopped */ @Override public HttpRequestBuilderImpl request(URI uri) { @@ -444,16 +464,12 @@ class HttpClientImpl extends HttpClient implements BufferHandler { return version.equals(Version.HTTP_2); } - //void setHttp2NotSupported(String host) { - //http2NotSupported.put(host, false); - //} - - final void initFilters() { + private void initFilters() { addFilter(AuthenticationFilter.class); addFilter(RedirectFilter.class); } - final void addFilter(Class f) { + private void addFilter(Class f) { filters.addFilter(f); } @@ -479,14 +495,14 @@ class HttpClientImpl extends HttpClient implements BufferHandler { iter.previous(); break; } else if (!iter.hasNext()) { - event.delta = event.timeval - listval ; + event.delta = event.timeval - listval; } } iter.add(event); selmgr.wakeupSelector(); } - synchronized void signalTimeouts(long then) { + private synchronized void signalTimeouts(long then) { if (timeouts.isEmpty()) { return; } @@ -532,12 +548,12 @@ class HttpClientImpl extends HttpClient implements BufferHandler { // used for the connection window int getReceiveBufferSize() { return Utils.getIntegerNetProperty( - "sun.net.httpclient.connectionWindowSize", 256 * 1024 + "java.net.httpclient.connectionWindowSize", 256 * 1024 ); } // returns 0 meaning block forever, or a number of millis to block for - synchronized long getTimeoutValue() { + private synchronized long getTimeoutValue() { if (timeouts.isEmpty()) { return 0; } else { diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java index ea82531b469..21cecd6498e 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java @@ -23,9 +23,8 @@ */ package java.net.http; -import java.io.FileOutputStream; +import java.io.Closeable; import java.io.IOException; -import java.io.PrintStream; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; @@ -42,7 +41,17 @@ import javax.net.ssl.SSLParameters; * SSLConnection: TLS channel direct to server * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel */ -abstract class HttpConnection implements BufferHandler { +abstract class HttpConnection implements BufferHandler, Closeable { + + protected final static ByteBuffer emptyBuf = Utils.EMPTY_BYTEBUFFER; + + enum Mode { + BLOCKING, + NON_BLOCKING, + ASYNC + } + + protected Mode mode; // address we are connected to. Could be a server or a proxy final InetSocketAddress address; @@ -52,6 +61,7 @@ abstract class HttpConnection implements BufferHandler { HttpConnection(InetSocketAddress address, HttpClientImpl client) { this.address = address; this.client = client; + this.buffer = emptyBuf; } /** @@ -68,7 +78,21 @@ abstract class HttpConnection implements BufferHandler { */ public static HttpConnection getConnection(InetSocketAddress addr, HttpRequestImpl request) { - return getConnectionImpl(addr, request); + return getConnectionImpl(addr, request, null); + } + + /** + * Called specifically to get an async connection for HTTP/2 over SSL. + * + * @param addr + * @param request + * @param http2 + * @return + */ + public static HttpConnection getConnection(InetSocketAddress addr, + HttpRequestImpl request, Http2Connection http2) { + + return getConnectionImpl(addr, request, http2); } public abstract void connect() throws IOException, InterruptedException; @@ -93,7 +117,7 @@ abstract class HttpConnection implements BufferHandler { // at beginning of response. ByteBuffer getRemaining() { ByteBuffer b = buffer; - buffer = null; + buffer = emptyBuf; return b; } @@ -123,17 +147,18 @@ abstract class HttpConnection implements BufferHandler { } private static HttpConnection getSSLConnection(InetSocketAddress addr, - InetSocketAddress proxy, - HttpRequestImpl request, - String[] alpn) { + InetSocketAddress proxy, HttpRequestImpl request, + String[] alpn, Http2Connection http2) { HttpClientImpl client = request.client(); if (proxy != null) { return new SSLTunnelConnection(addr, client, proxy, request.getAccessControlContext()); - } else { + } else if (http2 == null) { return new SSLConnection(addr, client, alpn); + } else { + return new AsyncSSLConnection(addr, client, alpn); } } @@ -142,7 +167,8 @@ abstract class HttpConnection implements BufferHandler { * none available. */ private static HttpConnection getConnectionImpl(InetSocketAddress addr, - HttpRequestImpl request) { + HttpRequestImpl request, Http2Connection http2) { + HttpConnection c; HttpClientImpl client = request.client(); InetSocketAddress proxy = request.proxy(); @@ -167,7 +193,7 @@ abstract class HttpConnection implements BufferHandler { if (c != null) { return c; } else { - return getSSLConnection(addr, proxy, request, alpn); + return getSSLConnection(addr, proxy, request, alpn, http2); } } } @@ -223,64 +249,16 @@ abstract class HttpConnection implements BufferHandler { return address; } - void configureBlocking(boolean mode) throws IOException { - channel().configureBlocking(mode); + synchronized void configureMode(Mode mode) throws IOException { + this.mode = mode; + if (mode == Mode.BLOCKING) + channel().configureBlocking(true); + else + channel().configureBlocking(false); } abstract ConnectionPool.CacheKey cacheKey(); - /* - static PrintStream ps; - - static { - try { - String propval = Utils.getNetProperty("java.net.httpclient.showData"); - if (propval != null && propval.equalsIgnoreCase("true")) { - ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - synchronized final void debugPrint(String s, ByteBuffer b) { - ByteBuffer[] bufs = new ByteBuffer[1]; - bufs[0] = b; - debugPrint(s, bufs, 0, 1); - } - - synchronized final void debugPrint(String s, - ByteBuffer[] bufs, - int start, - int number) { - if (ps == null) { - return; - } - - ps.printf("\n%s:\n", s); - - for (int i=start; i 0x20 && c <= 0x7F) { - ps.printf("%c", (char)c); - } else { - ps.printf("0x%02x ", c); - } - } - } - ps.printf("\n---------------------\n"); - } - - */ - // overridden in SSL only SSLParameters sslParameters() { return null; @@ -296,7 +274,8 @@ abstract class HttpConnection implements BufferHandler { /** * Closes this connection, by returning the socket to its connection pool. */ - abstract void close(); + @Override + public abstract void close(); /** * Returns a ByteBuffer with data, or null if EOF. @@ -356,12 +335,17 @@ abstract class HttpConnection implements BufferHandler { } @Override - public final ByteBuffer getBuffer() { - return client.getBuffer(); + public final ByteBuffer getBuffer(int n) { + return client.getBuffer(n); } @Override public final void returnBuffer(ByteBuffer buffer) { client.returnBuffer(buffer); } + + @Override + public final void setMinBufferSize(int n) { + client.setMinBufferSize(n); + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java index 532625e65da..ee4122d22f8 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java @@ -24,44 +24,22 @@ package java.net.http; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; /** * Implementation of HttpHeaders. */ -class HttpHeadersImpl implements HttpHeaders1 { +class HttpHeadersImpl implements HttpHeaders { - private final HashMap> headers; - private boolean isUnmodifiable = false; + private final TreeMap> headers; public HttpHeadersImpl() { - headers = new HashMap<>(); - } - - /** - * Replace all List in headers with unmodifiable Lists. Call - * this only after all headers are added. The headers HashMap - * is wrapped with an unmodifiable HashMap in map() - */ - @Override - public void makeUnmodifiable() { - if (isUnmodifiable) - return; - - Set keys = new HashSet<>(headers.keySet()); - for (String key : keys) { - List values = headers.remove(key); - if (values != null) { - headers.put(key, Collections.unmodifiableList(values)); - } - } - isUnmodifiable = true; + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); } @Override @@ -88,7 +66,7 @@ class HttpHeadersImpl implements HttpHeaders1 { public HttpHeadersImpl deepCopy() { HttpHeadersImpl h1 = new HttpHeadersImpl(); - HashMap> headers1 = h1.headers; + TreeMap> headers1 = h1.headers; Set keys = headers.keySet(); for (String key : keys) { List vals = headers.get(key); @@ -98,22 +76,13 @@ class HttpHeadersImpl implements HttpHeaders1 { return h1; } - private List getOrCreate(String name) { - List l = headers.get(name); - if (l == null) { - l = new LinkedList<>(); - headers.put(name, l); - } - return l; - } - void addHeader(String name, String value) { - List l = getOrCreate(name); - l.add(value); + headers.computeIfAbsent(name, k -> new LinkedList<>()) + .add(value); } void setHeader(String name, String value) { - List l = getOrCreate(name); + List l = headers.computeIfAbsent(name, k -> new LinkedList<>()); l.clear(); l.add(value); } @@ -122,7 +91,7 @@ class HttpHeadersImpl implements HttpHeaders1 { public Optional firstValueAsLong(String name) { List l = headers.get(name); if (l == null) { - return Optional.ofNullable(null); + return Optional.empty(); } else { String v = l.get(0); Long lv = Long.parseLong(v); @@ -133,4 +102,4 @@ class HttpHeadersImpl implements HttpHeaders1 { void clear() { headers.clear(); } -} +} \ No newline at end of file diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java index bc04ab3e921..d6d6604fd51 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java @@ -39,10 +39,11 @@ class HttpRequestBuilderImpl extends HttpRequest.Builder { private HttpClient.Version version; private final HttpClientImpl client; private ProxySelector proxy; - private long timeval = 0; + private long timeval; public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) { this.client = client; + checkURI(uri); this.uri = uri; this.version = client.version(); this.userHeaders = new HttpHeadersImpl(); @@ -58,10 +59,17 @@ class HttpRequestBuilderImpl extends HttpRequest.Builder { @Override public HttpRequestBuilderImpl uri(URI uri) { Objects.requireNonNull(uri); + checkURI(uri); this.uri = uri; return this; } + private static void checkURI(URI uri) { + String scheme = uri.getScheme().toLowerCase(); + if (!scheme.equals("https") && !scheme.equals("http")) + throw new IllegalArgumentException("invalid URI scheme"); + } + @Override public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) { Objects.requireNonNull(follow); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java index 10c0f16c6fd..dce47d43f72 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java @@ -30,16 +30,14 @@ import java.net.URI; import java.net.http.HttpClient.Version; import java.net.http.HttpResponse.MultiProcessor; import java.util.concurrent.CompletableFuture; -import java.net.SocketPermission; import java.security.AccessControlContext; import java.security.AccessController; -import java.util.Set; import static java.net.http.HttpRedirectImpl.getRedirects; import java.util.Locale; class HttpRequestImpl extends HttpRequest { - private final HttpHeadersImpl userHeaders; + private final ImmutableHeaders userHeaders; private final HttpHeadersImpl systemHeaders; private final URI uri; private InetSocketAddress authority; // only used when URI not specified @@ -56,6 +54,7 @@ class HttpRequestImpl extends HttpRequest { private boolean receiving; private AccessControlContext acc; private final long timeval; + private Stream.PushGroup pushGroup; public HttpRequestImpl(HttpClientImpl client, String method, @@ -63,8 +62,8 @@ class HttpRequestImpl extends HttpRequest { this.client = client; this.method = method == null? "GET" : method; this.userHeaders = builder.headers() == null ? - new HttpHeadersImpl() : builder.headers(); - dropDisallowedHeaders(); + new ImmutableHeaders() : + new ImmutableHeaders(builder.headers(), Utils.ALLOWED_HEADERS); this.followRedirects = getRedirects(builder.followRedirects() == null ? client.followRedirects() : builder.followRedirects()); this.systemHeaders = new HttpHeadersImpl(); @@ -90,15 +89,13 @@ class HttpRequestImpl extends HttpRequest { HttpRequestImpl other) { this.client = client; this.method = method == null? "GET" : method; - this.userHeaders = other.userHeaders == null ? - new HttpHeadersImpl() : other.userHeaders; - dropDisallowedHeaders(); + this.userHeaders = other.userHeaders; this.followRedirects = getRedirects(other.followRedirects() == null ? client.followRedirects() : other.followRedirects()); this.systemHeaders = other.systemHeaders; this.uri = uri; this.expectContinue = other.expectContinue; - this.secure = other.secure; + this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https"); this.requestProcessor = other.requestProcessor; this.proxy = other.proxy; this.version = other.version; @@ -115,7 +112,7 @@ class HttpRequestImpl extends HttpRequest { this.method = method; this.followRedirects = getRedirects(client.followRedirects()); this.systemHeaders = new HttpHeadersImpl(); - this.userHeaders = new HttpHeadersImpl(); + this.userHeaders = new ImmutableHeaders(); this.uri = null; this.proxy = null; this.requestProcessor = HttpRequest.noBody(); @@ -132,16 +129,52 @@ class HttpRequestImpl extends HttpRequest { return client; } + /** + * Creates a HttpRequestImpl from the given set of Headers and the associated + * "parent" request. Fields not taken from the headers are taken from the + * parent. + */ + static HttpRequestImpl createPushRequest(HttpRequestImpl parent, + HttpHeadersImpl headers) throws IOException { + + return new HttpRequestImpl(parent, headers); + } + + // only used for push requests + private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers) throws IOException { + this.method = headers.firstValue(":method") + .orElseThrow(() -> new IOException("No method in Push Promise")); + String path = headers.firstValue(":path") + .orElseThrow(() -> new IOException("No path in Push Promise")); + String scheme = headers.firstValue(":scheme") + .orElseThrow(() -> new IOException("No scheme in Push Promise")); + String authority = headers.firstValue(":authority") + .orElseThrow(() -> new IOException("No authority in Push Promise")); + StringBuilder sb = new StringBuilder(); + sb.append(scheme).append("://").append(authority).append(path); + this.uri = URI.create(sb.toString()); + + this.client = parent.client; + this.userHeaders = new ImmutableHeaders(headers, Utils.ALLOWED_HEADERS); + this.followRedirects = parent.followRedirects; + this.systemHeaders = parent.systemHeaders; + this.expectContinue = parent.expectContinue; + this.secure = parent.secure; + this.requestProcessor = parent.requestProcessor; + this.proxy = parent.proxy; + this.version = parent.version; + this.acc = parent.acc; + this.exchange = parent.exchange; + this.timeval = parent.timeval; + } @Override public String toString() { - return (uri == null ? "" : uri.toString()) + "/" + method + "(" - + hashCode() + ")"; + return (uri == null ? "" : uri.toString()) + " " + method; } @Override public HttpHeaders headers() { - userHeaders.makeUnmodifiable(); return userHeaders; } @@ -154,21 +187,6 @@ class HttpRequestImpl extends HttpRequest { systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString()); } - private static final Set DISALLOWED_HEADERS_SET = Set.of( - "authorization", "connection", "cookie", "content-length", - "date", "expect", "from", "host", "origin", "proxy-authorization", - "referer", "user-agent", "upgrade", "via", "warning"); - - - // we silently drop headers that are disallowed - private void dropDisallowedHeaders() { - Set hdrnames = userHeaders.directMap().keySet(); - - hdrnames.removeIf((s) -> - DISALLOWED_HEADERS_SET.contains(s.toLowerCase()) - ); - } - private synchronized void receiving() { if (receiving) { throw new IllegalStateException("already receiving response"); @@ -176,6 +194,10 @@ class HttpRequestImpl extends HttpRequest { receiving = true; } + synchronized Stream.PushGroup pushGroup() { + return pushGroup; + } + /* * Response filters may result in a new HttpRequestImpl being created * (but still associated with the same API HttpRequest) and the process @@ -200,10 +222,25 @@ class HttpRequestImpl extends HttpRequest { .thenApply((r) -> (HttpResponse)r); } - public CompletableFuture - sendAsyncMulti(HttpResponse.MultiProcessor rspproc) { - // To change body of generated methods, choose Tools | Templates. - throw new UnsupportedOperationException("Not supported yet."); + + @SuppressWarnings("unchecked") + @Override + public synchronized CompletableFuture + multiResponseAsync(MultiProcessor rspproc) { + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + this.pushGroup = new Stream.PushGroup<>(rspproc, this); + CompletableFuture cf = pushGroup.mainResponse(); + responseAsync() + .whenComplete((HttpResponse r, Throwable t) -> { + if (r != null) + cf.complete(r); + else + cf.completeExceptionally(t); + pushGroup.pushError(t); + }); + return (CompletableFuture)pushGroup.groupResult(); } @Override @@ -255,7 +292,7 @@ class HttpRequestImpl extends HttpRequest { @Override public URI uri() { return uri; } - HttpHeadersImpl getUserHeaders() { return userHeaders; } + HttpHeaders getUserHeaders() { return userHeaders; } HttpHeadersImpl getSystemHeaders() { return systemHeaders; } @@ -275,11 +312,4 @@ class HttpRequestImpl extends HttpRequest { } long timeval() { return timeval; } - - @Override - public CompletableFuture - multiResponseAsync(MultiProcessor rspproc) { - //To change body of generated methods, choose Tools | Templates. - throw new UnsupportedOperationException("Not supported yet."); - } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java index c1ff5adb44e..eb7f7fa6930 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java @@ -200,8 +200,12 @@ public abstract class HttpResponse { if (n == -1) { throw new IOException("Bad Content-Disposition type"); } - String disposition = dispoHeader.substring(n + 9, - dispoHeader.lastIndexOf(';')); + int lastsemi = dispoHeader.lastIndexOf(';'); + String disposition; + if (lastsemi < n) + disposition = dispoHeader.substring(n + 9); + else + disposition = dispoHeader.substring(n + 9, lastsemi); file = Paths.get(directory.toString(), disposition); fc = FileChannel.open(file, openOptions); return null; @@ -727,11 +731,14 @@ public abstract class HttpResponse { } private CompletableFuture getBody(HttpRequest req, - CompletableFuture cf) { + CompletableFuture cf) { URI u = req.uri(); String path = u.getPath(); + if (path.startsWith("/")) + path = path.substring(1); + final String fpath = path; return cf.thenCompose((HttpResponse resp) -> { - return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path))); + return resp.bodyAsync(HttpResponse.asFile(destination.resolve(fpath))); }); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java index c71f53a04ea..10758d6db99 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java @@ -26,6 +26,7 @@ package java.net.http; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URI; import java.nio.ByteBuffer; import java.security.AccessControlContext; @@ -42,17 +43,18 @@ class HttpResponseImpl extends HttpResponse { int responseCode; Exchange exchange; HttpRequestImpl request; - HttpHeaders1 headers; - HttpHeaders1 trailers; + HttpHeaders headers; + HttpHeaders trailers; SSLParameters sslParameters; URI uri; HttpClient.Version version; AccessControlContext acc; RawChannel rawchan; HttpConnection connection; + final Stream stream; - public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers, - HttpHeaders1 trailers, SSLParameters sslParameters, + public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders headers, + HttpHeaders trailers, SSLParameters sslParameters, HttpClient.Version version, HttpConnection connection) { this.responseCode = responseCode; this.exchange = exch; @@ -63,6 +65,23 @@ class HttpResponseImpl extends HttpResponse { this.uri = request.uri(); this.version = version; this.connection = connection; + this.stream = null; + } + + // A response to a PUSH_PROMISE + public HttpResponseImpl(int responseCode, HttpRequestImpl pushRequest, + ImmutableHeaders headers, + Stream stream, SSLParameters sslParameters) { + this.responseCode = responseCode; + this.exchange = null; + this.request = pushRequest; + this.headers = headers; + this.trailers = null; + this.sslParameters = sslParameters; + this.uri = request.uri(); // TODO: take from headers + this.version = HttpClient.Version.HTTP_2; + this.connection = null; + this.stream = stream; } @Override @@ -77,26 +96,35 @@ class HttpResponseImpl extends HttpResponse { @Override public HttpHeaders headers() { - headers.makeUnmodifiable(); return headers; } @Override public HttpHeaders trailers() { - trailers.makeUnmodifiable(); return trailers; } @Override public T body(java.net.http.HttpResponse.BodyProcessor processor) { - return exchange.responseBody(processor); + try { + if (exchange != null) { + return exchange.responseBody(processor); + } else { + return stream.responseBody(processor); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } } @Override public CompletableFuture bodyAsync(java.net.http.HttpResponse.BodyProcessor processor) { acc = AccessController.getContext(); - return exchange.responseBodyAsync(processor); + if (exchange != null) + return exchange.responseBodyAsync(processor); + else + return stream.responseBodyAsync(processor); } @Override diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java new file mode 100644 index 00000000000..f1c3d50ff06 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java @@ -0,0 +1,79 @@ +/* + * 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 + */ + +package java.net.http; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; +import java.util.function.Predicate; + +/** + * Immutable HttpHeaders constructed from mutable HttpHeadersImpl. + */ + +class ImmutableHeaders implements HttpHeaders { + + private final Map> map; + + @SuppressWarnings("unchecked") + ImmutableHeaders() { + map = (Map>)Collections.EMPTY_MAP; + } + // TODO: fix lower case issue. Must be lc for http/2 compares ignoreCase for http/1 + ImmutableHeaders(HttpHeadersImpl h, Predicate keyAllowed) { + Map> src = h.directMap(); + Map> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + src.forEach((key, value) -> { + if (keyAllowed.test(key)) + m.put(key, Collections.unmodifiableList(value)); + }); + map = Collections.unmodifiableMap(m); + } + + @Override + public Optional firstValue(String name) { + List l = map.get(name); + String v = l == null ? null : l.get(0); + return Optional.ofNullable(v); + } + + @Override + public Optional firstValueAsLong(String name) { + return firstValue(name).map((v -> Long.parseLong(v))); + } + + @Override + public List allValues(String name) { + return map.get(name); + } + + @Override + public Map> map() { + return map; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java index 986a8fd1503..991edfefa6c 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java @@ -26,7 +26,9 @@ package java.net.http; import java.util.Locale; /** - * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content + * -Djava.net.HttpClient.log= + * errors,requests,headers, + * frames[:type:type2:..],content,ssl,trace * * Any of errors, requests, headers or content are optional. * @@ -47,6 +49,7 @@ abstract class Log implements System.Logger { public static final int CONTENT = 0x8; public static final int FRAMES = 0x10; public static final int SSL = 0x20; + public static final int TRACE = 0x40; static int logging; // Frame types: "control", "data", "window", "all" @@ -81,8 +84,11 @@ abstract class Log implements System.Logger { case "ssl": logging |= SSL; break; + case "trace": + logging |= TRACE; + break; case "all": - logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS; + logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE; break; } if (val.startsWith("frames")) { @@ -130,6 +136,10 @@ abstract class Log implements System.Logger { return (logging & HEADERS) != 0; } + static boolean trace() { + return (logging & TRACE) != 0; + } + static boolean ssl() { return (logging & SSL) != 0; } @@ -138,9 +148,9 @@ abstract class Log implements System.Logger { return (logging & FRAMES) != 0; } - static void logError(String s) { + static void logError(String s, Object... s1) { if (errors()) - logger.log(Level.INFO, "ERROR: " + s); + logger.log(Level.INFO, "ERROR: " + s, s1); } static void logError(Throwable t) { @@ -150,24 +160,50 @@ abstract class Log implements System.Logger { } } - static void logSSL(String s) { + static void logSSL(String s, Object... s1) { if (ssl()) - logger.log(Level.INFO, "SSL: " + s); + logger.log(Level.INFO, "SSL: " + s, s1); } - static void logRequest(String s) { + static void logTrace(String s, Object... s1) { + if (trace()) { + String format = "TRACE: " + s; + logger.log(Level.INFO, format, s1); + } + } + + static void logRequest(String s, Object... s1) { if (requests()) - logger.log(Level.INFO, "REQUEST: " + s); + logger.log(Level.INFO, "REQUEST: " + s, s1); } - static void logResponse(String s) { + static void logResponse(String s, Object... s1) { if (requests()) - logger.log(Level.INFO, "RESPONSE: " + s); + logger.log(Level.INFO, "RESPONSE: " + s, s1); } - static void logHeaders(String s) { + static void logHeaders(String s, Object... s1) { if (headers()) - logger.log(Level.INFO, "HEADERS: " + s); + logger.log(Level.INFO, "HEADERS: " + s, s1); + } +// START HTTP2 + static boolean loggingFrame(Class clazz) { + if (frametypes == ALL) { + return true; + } + if (clazz == DataFrame.class) { + return (frametypes & DATA) != 0; + } else if (clazz == WindowUpdateFrame.class) { + return (frametypes & WINDOW_UPDATES) != 0; + } else { + return (frametypes & CONTROL) != 0; + } + } + + static void logFrames(Http2Frame f, String direction) { + if (frames() && loggingFrame(f.getClass())) { + logger.log(Level.INFO, "FRAME: " + direction + ": " + f.toString()); + } } // not instantiable diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java index 8a53565ae51..69e4bbbc7c4 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java @@ -54,7 +54,7 @@ class MultiExchange { final static int DEFAULT_MAX_ATTEMPTS = 5; final static int max_attempts = Utils.getIntegerNetProperty( - "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS + "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS ); private final List filters; @@ -187,8 +187,7 @@ class MultiExchange { public CompletableFuture responseAsync(Void v) { CompletableFuture cf; if (++attempts > max_attempts) { - cf = new CompletableFuture<>(); - cf.completeExceptionally(new IOException("Too many retries")); + cf = CompletableFuture.failedFuture(new IOException("Too many retries")); } else { if (currentreq.timeval() != 0) { // set timer @@ -241,7 +240,6 @@ class MultiExchange { * completed exceptionally. */ private CompletableFuture getExceptionalCF(Throwable t) { - CompletableFuture error = new CompletableFuture<>(); if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { if (t.getCause() != null) { t = t.getCause(); @@ -250,8 +248,7 @@ class MultiExchange { if (cancelled && t instanceof IOException) { t = new HttpTimeoutException("request timed out"); } - error.completeExceptionally(t); - return error; + return CompletableFuture.failedFuture(t); } T responseBody(HttpResponse.BodyProcessor processor) { diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java new file mode 100644 index 00000000000..6194022c0cc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java @@ -0,0 +1,91 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; + +/** + * Contains all parameters for outgoing headers. Is converted to + * HeadersFrame and ContinuationFrames by Http2Connection. + */ +class OutgoingHeaders extends Http2Frame { + + int streamDependency; + int weight; + boolean exclusive; + Stream stream; + + public static final int PRIORITY = 0x20; + + HttpHeaders user, system; + + OutgoingHeaders(HttpHeaders hdrs1, HttpHeaders hdrs2, Stream stream) { + this.user = hdrs2; + this.system = hdrs1; + this.stream = stream; + } + + public void setPriority(int streamDependency, boolean exclusive, int weight) { + this.streamDependency = streamDependency; + this.exclusive = exclusive; + this.weight = weight; + this.flags |= PRIORITY; + } + + public int getStreamDependency() { + return streamDependency; + } + + public int getWeight() { + return weight; + } + + public boolean getExclusive() { + return exclusive; + } + + public Stream getStream() { + return stream; + } + + public HttpHeaders getUserHeaders() { + return user; + } + + public HttpHeaders getSystemHeaders() { + return system; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + void computeLength() { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java index 5ffeaf6c961..b597b54bd92 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java @@ -43,4 +43,9 @@ final class Pair { static Pair pair(T first, U second) { return new Pair<>(first, second); } + + @Override + public String toString() { + return "(" + first + ", " + second + ")"; + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java new file mode 100644 index 00000000000..f9f202d86dc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java @@ -0,0 +1,85 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class PingFrame extends Http2Frame { + + PingFrame() { + type = TYPE; + } + + byte[] data; + + public final static int TYPE = 0x6; + + // Flags + public static final int ACK = 0x1; + + @Override + String flagAsString(int flag) { + switch (flag) { + case ACK: + return "ACK"; + } + return super.flagAsString(flag); + } + + public void setData(byte[] data) { + if (data.length != 8) { + throw new IllegalArgumentException("Ping data not 8 bytes"); + } + this.data = data; + } + + public byte[] getData() { + return data; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + if (length != 8) { + throw new IOException("Invalid Ping frame"); + } + data = bc.getBytes(8); + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + if (data == null) { + data = new byte[] {0, 0, 0, 0, 0 ,0, 0, 0}; + } + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(8); + buf.put(data); + } + + @Override + void computeLength() { + length = 8; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java index e206f9204e2..eeadb35f7a0 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java @@ -31,20 +31,43 @@ import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; /** - * Plain raw TCP connection direct to destination + * Plain raw TCP connection direct to destination. 2 modes + * 1) Blocking used by http/1. In this case the connect is actually non + * blocking but the request is sent blocking. The first byte of a response + * is received non-blocking and the remainder of the response is received + * blocking + * 2) Non-blocking. In this case (for http/2) the connection is actually opened + * blocking but all reads and writes are done non-blocking under the + * control of a Http2Connection object. */ -class PlainHttpConnection extends HttpConnection { +class PlainHttpConnection extends HttpConnection implements AsyncConnection { protected SocketChannel chan; private volatile boolean connected; private boolean closed; + Consumer asyncReceiver; + Consumer errorReceiver; + Queue asyncOutputQ; + final Object reading = new Object(); + final Object writing = new Object(); - class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking { + @Override + public void startReading() { + try { + client.registerEvent(new ReadEvent()); + } catch (IOException e) { + shutdown(); + } + } + + class ConnectEvent extends AsyncEvent { CompletableFuture cf; ConnectEvent(CompletableFuture cf) { + super(AsyncEvent.BLOCKING); this.cf = cf; } @@ -112,14 +135,62 @@ class PlainHttpConnection extends HttpConnection { @Override long write(ByteBuffer[] buffers, int start, int number) throws IOException { - //debugPrint("Send", buffers, start, number); - return chan.write(buffers, start, number); + if (mode != Mode.ASYNC) + return chan.write(buffers, start, number); + // async + synchronized(writing) { + int qlen = asyncOutputQ.size(); + ByteBuffer[] bufs = Utils.reduce(buffers, start, number); + long n = Utils.remaining(bufs); + asyncOutputQ.putAll(bufs); + if (qlen == 0) + asyncOutput(); + return n; + } + } + + ByteBuffer asyncBuffer = null; + + void asyncOutput() { + synchronized (writing) { + try { + while (true) { + if (asyncBuffer == null) { + asyncBuffer = asyncOutputQ.poll(); + if (asyncBuffer == null) { + return; + } + } + if (!asyncBuffer.hasRemaining()) { + asyncBuffer = null; + continue; + } + int n = chan.write(asyncBuffer); + //System.err.printf("Written %d bytes to chan\n", n); + if (n == 0) { + client.registerEvent(new WriteEvent()); + return; + } + } + } catch (IOException e) { + shutdown(); + } + } } @Override long write(ByteBuffer buffer) throws IOException { - //debugPrint("Send", buffer); - return chan.write(buffer); + if (mode != Mode.ASYNC) + return chan.write(buffer); + // async + synchronized(writing) { + int qlen = asyncOutputQ.size(); + long n = buffer.remaining(); + asyncOutputQ.put(buffer); + if (qlen == 0) + asyncOutput(); + return n; + } } @Override @@ -131,7 +202,7 @@ class PlainHttpConnection extends HttpConnection { * Close this connection */ @Override - synchronized void close() { + public synchronized void close() { if (closed) return; closed = true; @@ -155,14 +226,49 @@ class PlainHttpConnection extends HttpConnection { return buf; } + void shutdown() { + close(); + errorReceiver.accept(new IOException("Connection aborted")); + } + + void asyncRead() { + synchronized (reading) { + try { + while (true) { + ByteBuffer buf = getBuffer(); + int n = chan.read(buf); + //System.err.printf("Read %d bytes from chan\n", n); + if (n == -1) { + throw new IOException(); + } + if (n == 0) { + returnBuffer(buf); + return; + } + buf.flip(); + asyncReceiver.accept(buf); + } + } catch (IOException e) { + shutdown(); + } + } + } + @Override protected int readImpl(ByteBuffer buf) throws IOException { int mark = buf.position(); - int n = chan.read(buf); + int n; + // FIXME: this hack works in conjunction with the corresponding change + // in java.net.http.RawChannel.registerEvent + if ((n = buffer.remaining()) != 0) { + buf.put(buffer); + } else { + n = chan.read(buf); + } if (n == -1) { return -1; } - Utils.flipToMark(buffer, mark); + Utils.flipToMark(buf, mark); String s = "Receive (" + n + " bytes) "; //debugPrint(s, buf); return n; @@ -178,10 +284,67 @@ class PlainHttpConnection extends HttpConnection { return connected; } - class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking { + // used for all output in HTTP/2 + class WriteEvent extends AsyncEvent { + WriteEvent() { + super(0); + } + + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public int interestOps() { + return SelectionKey.OP_WRITE; + } + + @Override + public void handle() { + asyncOutput(); + } + + @Override + public void abort() { + shutdown(); + } + } + + // used for all input in HTTP/2 + class ReadEvent extends AsyncEvent { + ReadEvent() { + super(AsyncEvent.REPEATING); // && !BLOCKING + } + + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void handle() { + asyncRead(); + } + + @Override + public void abort() { + shutdown(); + } + + } + + // used in blocking channels only + class ReceiveResponseEvent extends AsyncEvent { CompletableFuture cf; ReceiveResponseEvent(CompletableFuture cf) { + super(AsyncEvent.BLOCKING); this.cf = cf; } @Override @@ -215,6 +378,15 @@ class PlainHttpConnection extends HttpConnection { return false; } + @Override + public synchronized void setAsyncCallbacks(Consumer asyncReceiver, + Consumer errorReceiver) { + this.asyncReceiver = asyncReceiver; + this.errorReceiver = errorReceiver; + asyncOutputQ = new Queue<>(); + asyncOutputQ.registerPutCallback(this::asyncOutput); + } + @Override CompletableFuture whenReceivingResponse() { CompletableFuture cf = new CompletableFuture<>(); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java index 2042baa2c4e..239bf3f8285 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java @@ -111,7 +111,7 @@ class PlainTunnelingConnection extends HttpConnection { } @Override - void close() { + public void close() { delegate.close(); connected = false; } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java new file mode 100644 index 00000000000..ab609e897ae --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java @@ -0,0 +1,82 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class PriorityFrame extends Http2Frame { + + int streamDependency; + int weight; + boolean exclusive; + + public final static int TYPE = 0x2; + + PriorityFrame() { + type = TYPE; + } + + public PriorityFrame(int streamDependency, boolean exclusive, int weight) { + this.streamDependency = streamDependency; + this.exclusive = exclusive; + this.weight = weight; + this.type = TYPE; + } + + int streamDependency() { + return streamDependency; + } + + int weight() { + return weight; + } + + boolean exclusive() { + return exclusive; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + int x = bc.getInt(); + exclusive = (x & 0x80000000) != 0; + streamDependency = x & 0x7fffffff; + weight = bc.getByte(); + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(5); + int x = exclusive ? (1 << 31) + streamDependency : streamDependency; + buf.putInt(x); + buf.put((byte)weight); + } + + @Override + void computeLength() { + length = 5; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java new file mode 100644 index 00000000000..6de21209dc5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java @@ -0,0 +1,119 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class PushPromiseFrame extends HeaderFrame { + + int padLength; + int promisedStream; + + PushPromiseFrame() { + type = TYPE; + } + + public static final int TYPE = 0x5; + + // Flags + public static final int END_HEADERS = 0x4; + public static final int PADDED = 0x8; + + @Override + public String toString() { + return super.toString() + " promisedStreamid: " + promisedStream + + " headerLength: " + headerLength; + } + + @Override + String flagAsString(int flag) { + switch (flag) { + case PADDED: + return "PADDED"; + case END_HEADERS: + return "END_HEADERS"; + } + return super.flagAsString(flag); + } + + public void setPadLength(int padLength) { + this.padLength = padLength; + flags |= PADDED; + } + + public void setPromisedStream(int stream) { + this.promisedStream = stream; + } + + public int getPromisedStream() { + return promisedStream; + } + + /** + */ + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + if ((flags & PADDED) != 0) { + padLength = bc.getByte(); + headerLength = length - (padLength + 5); + } else + headerLength = length - 4; + + promisedStream = bc.getInt() & 0x7fffffff; + headerBlocks = bc.getBuffers(headerLength); + } + + @Override + void computeLength() { + int len = 0; + if ((flags & PADDED) != 0) { + len += (1 + padLength); + } + len += (4 + headerLength); + this.length = len; + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(length); + if ((flags & PADDED) != 0) { + buf.put((byte)padLength); + } + buf.putInt(promisedStream); + for (int i=0; i implements Closeable { + + private final LinkedList q = new LinkedList<>(); + private volatile boolean closed = false; + private Runnable callback; + private boolean forceCallback; + private int waiters; // true if someone waiting + + synchronized void putAll(T[] objs) throws IOException { + if (closed) { + throw new IOException("stream closed"); + } + boolean wasEmpty = q.isEmpty(); + + for (T obj : objs) { + q.add(obj); + } + + if (waiters > 0) + notifyAll(); + + if (wasEmpty || forceCallback) { + forceCallback = false; + if (callback != null) { + callback.run(); + } + } + } + + synchronized int size() { + return q.size(); + } + + synchronized void put(T obj) throws IOException { + if (closed) { + throw new IOException("stream closed"); + } + + q.add(obj); + if (waiters > 0) + notifyAll(); + + if (q.size() == 1 || forceCallback) { + forceCallback = false; + if (callback != null) { + callback.run(); + } + } + } + + /** + * callback is invoked any time put is called where + * the Queue was empty. + */ + synchronized void registerPutCallback(Runnable callback) { + this.callback = callback; + if (callback != null && q.size() > 0) + callback.run(); + } + + @Override + public synchronized void close() { + closed = true; + notifyAll(); + } + + synchronized T take() throws IOException { + if (closed) { + throw new IOException("stream closed"); + } + try { + while (q.size() == 0) { + waiters++; + wait(); + waiters--; + } + return q.removeFirst(); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + } + + public synchronized T poll() throws IOException { + if (closed) + throw new IOException("stream closed"); + + if (q.isEmpty()) + return null; + T res = q.removeFirst(); + return res; + } + + public synchronized T[] pollAll(T[] type) throws IOException { + T[] ret = q.toArray(type); + q.clear(); + return ret; + } + + public synchronized void pushback(T v) { + forceCallback = true; + q.addFirst(v); + } + + public synchronized void pushbackAll(T[] v) { + forceCallback = true; + for (int i=v.length-1; i>=0; i--) { + q.addFirst(v[i]); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java index 9566eeb555c..536eda47afd 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java @@ -28,18 +28,18 @@ import java.nio.ByteBuffer; import java.nio.channels.ByteChannel; import java.nio.channels.GatheringByteChannel; import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; -/** - * Used to implement WebSocket. Each RawChannel corresponds to - * a TCP connection (SocketChannel) but is connected to a Selector - * and an ExecutorService for invoking the send and receive callbacks - * Also includes SSL processing. - */ -class RawChannel implements ByteChannel, GatheringByteChannel { +// +// Used to implement WebSocket. Each RawChannel corresponds to a TCP connection +// (SocketChannel) but is connected to a Selector and an ExecutorService for +// invoking the send and receive callbacks. Also includes SSL processing. +// +final class RawChannel implements ByteChannel, GatheringByteChannel { private final HttpClientImpl client; private final HttpConnection connection; - private boolean closed; + private volatile boolean closed; private interface RawEvent { @@ -50,8 +50,6 @@ class RawChannel implements ByteChannel, GatheringByteChannel { void handle(); } - interface BlockingEvent extends RawEvent { } - interface NonBlockingEvent extends RawEvent { } RawChannel(HttpClientImpl client, HttpConnection connection) { @@ -64,39 +62,40 @@ class RawChannel implements ByteChannel, GatheringByteChannel { private final RawEvent re; RawAsyncEvent(RawEvent re) { + super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING this.re = re; } + RawAsyncEvent(RawEvent re, int flags) { + super(flags); + this.re = re; + } + + @Override public SelectableChannel channel() { return connection.channel(); } // must return the selector interest op flags OR'd + @Override public int interestOps() { return re.interestOps(); } // called when event occurs + @Override public void handle() { re.handle(); } - public void abort() {} + @Override + public void abort() { } } - private class BlockingRawAsyncEvent extends RawAsyncEvent - implements AsyncEvent.Blocking { - - BlockingRawAsyncEvent(RawEvent re) { - super(re); - } - } - - private class NonBlockingRawAsyncEvent extends RawAsyncEvent - implements AsyncEvent.NonBlocking { + private class NonBlockingRawAsyncEvent extends RawAsyncEvent { NonBlockingRawAsyncEvent(RawEvent re) { - super(re); + super(re, 0); // !BLOCKING & !REPEATING } } @@ -105,17 +104,24 @@ class RawChannel implements ByteChannel, GatheringByteChannel { * (i.e. register new event for each callback) */ public void registerEvent(RawEvent event) throws IOException { - if (event instanceof BlockingEvent) { - client.registerEvent(new BlockingRawAsyncEvent(event)); - } else if (event instanceof NonBlockingEvent) { - client.registerEvent(new NonBlockingRawAsyncEvent(event)); - } else { + if (!(event instanceof NonBlockingEvent)) { throw new InternalError(); } + if ((event.interestOps() & SelectionKey.OP_READ) != 0 + && connection.buffer.hasRemaining()) { + // FIXME: a hack to deal with leftovers from previous reads into an + // internal buffer (works in conjunction with change in + // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer) + connection.channel().configureBlocking(false); + event.handle(); + } else { + client.registerEvent(new NonBlockingRawAsyncEvent(event)); + } } @Override public int read(ByteBuffer dst) throws IOException { + assert !connection.channel().isBlocking(); return connection.read(dst); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java index 3c3be4d17c5..4bd18bd9c50 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java @@ -33,17 +33,19 @@ class RedirectFilter implements HeaderFilter { HttpRequestImpl requestImpl; HttpRequest request; HttpClientImpl client; + HttpClient.Redirect policy; String method; final static int DEFAULT_MAX_REDIRECTS = 5; URI uri; final static int max_redirects = Utils.getIntegerNetProperty( - "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS + "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS ); @Override public void request(HttpRequestImpl r) throws IOException { this.request = r; + this.policy = request.followRedirects(); this.client = r.getClient(); this.method = r.method(); this.requestImpl = r; @@ -61,7 +63,7 @@ class RedirectFilter implements HeaderFilter { */ private HttpRequestImpl handleResponse(HttpResponseImpl r) { int rcode = r.statusCode(); - if (rcode == 200) { + if (rcode == 200 || policy == HttpClient.Redirect.NEVER) { return null; } if (rcode >= 300 && rcode <= 399) { @@ -79,6 +81,7 @@ class RedirectFilter implements HeaderFilter { private URI getRedirectedURI(HttpHeaders headers) { URI redirectedURI; + String ss = headers.firstValue("Location").orElse("Not present"); redirectedURI = headers.firstValue("Location") .map((s) -> URI.create(s)) .orElseThrow(() -> new UncheckedIOException( diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java new file mode 100644 index 00000000000..6e56586fb14 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java @@ -0,0 +1,61 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class ResetFrame extends ErrorFrame { + + public final static int TYPE = 0x3; + + // See ErrorFrame for error values + + ResetFrame() { + type = TYPE; + } + + public ResetFrame(int errorCode) { + this.errorCode = errorCode; + this.type = TYPE; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + errorCode = bc.getInt(); + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(4); + buf.putInt(errorCode); + } + + @Override + void computeLength() { + length = 4; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java index b378e784c51..ad15bd735ff 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java @@ -48,7 +48,7 @@ import java.util.Set; * * This class is not thread-safe */ -class ResponseHeaders implements HttpHeaders1 { +class ResponseHeaders implements HttpHeaders { static final int DATA_SIZE = 16 * 1024; // initial space for headers static final int NUM_HEADERS = 50; // initial expected max number of headers @@ -368,10 +368,6 @@ class ResponseHeaders implements HttpHeaders1 { return Collections.unmodifiableList(l); } - @Override - public void makeUnmodifiable() { - } - // Delegates map to HashMap but converts keys to lower case static class HeaderMap implements Map> { diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java index 4b8cb3c0516..932c5b1c0f5 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java @@ -121,13 +121,8 @@ class SSLConnection extends HttpConnection { } @Override - void close() { - try { - //System.err.println ("Closing: " + this); - delegate.channel().close(); // TODO: proper close - } catch (IOException ex) { - Log.logError(ex.toString()); - } + public void close() { + Utils.close(delegate.channel()); } @Override diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java index fbc0674513c..27bad6659ad 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java @@ -29,13 +29,9 @@ import java.nio.channels.SocketChannel; import java.util.Arrays; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLSession; +import javax.net.ssl.*; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; /** @@ -60,16 +56,18 @@ class SSLDelegate { engine.setUseClientMode(true); SSLParameters sslp = client.sslParameters().orElse(null); if (sslp == null) { - sslp = context.getDefaultSSLParameters(); + sslp = context.getSupportedSSLParameters(); } sslParameters = Utils.copySSLParameters(sslp); if (alpn != null) { sslParameters.setApplicationProtocols(alpn); Log.logSSL("Setting application protocols: " + Arrays.toString(alpn)); } else { - Log.logSSL("Warning no application protocols proposed!"); + Log.logSSL("No application protocols proposed"); } engine.setSSLParameters(sslParameters); + engine.setEnabledCipherSuites(sslp.getCipherSuites()); + engine.setEnabledProtocols(sslp.getProtocols()); wrapper = new EngineWrapper(chan, engine); this.chan = chan; this.client = client; @@ -268,7 +266,7 @@ class SSLDelegate { do { if (needData) { do { - x = chan.read (unwrap_src); + x = chan.read (unwrap_src); } while (x == 0); if (x == -1) { throw new IOException ("connection closed for reading"); @@ -440,6 +438,27 @@ class SSLDelegate { } } + static void printParams(SSLParameters p) { + System.out.println("SSLParameters:"); + if (p == null) { + System.out.println("Null params"); + return; + } + for (String cipher : p.getCipherSuites()) { + System.out.printf("cipher: %s\n", cipher); + } + for (String approto : p.getApplicationProtocols()) { + System.out.printf("application protocol: %s\n", approto); + } + for (String protocol : p.getProtocols()) { + System.out.printf("protocol: %s\n", protocol); + } + if (p.getServerNames() != null) + for (SNIServerName sname : p.getServerNames()) { + System.out.printf("server name: %s\n", sname.toString()); + } + } + String getSessionInfo() { StringBuilder sb = new StringBuilder(); String application = engine.getApplicationProtocol(); diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java index 8ec5786a687..fe8e766af77 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java @@ -130,12 +130,8 @@ class SSLTunnelConnection extends HttpConnection { } @Override - void close() { - try { - //System.err.println ("Closing: " + this); - delegate.channel().close(); // TODO: proper close - } catch (IOException ex) { - } + public void close() { + Utils.close(delegate.channel()); } @Override diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java b/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java new file mode 100644 index 00000000000..822a2564407 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java @@ -0,0 +1,165 @@ +/* + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +class SettingsFrame extends Http2Frame { + + int[] parameters; + + public static final int TYPE = 0x4; + + // Flags + public static final int ACK = 0x1; + + @Override + String flagAsString(int flag) { + switch (flag) { + case ACK: + return "ACK"; + } + return super.flagAsString(flag); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(super.toString()) + .append(" Settings: "); + + for (int i = 0; i < MAX_PARAM; i++) { + if (parameters[i] != -1) { + sb.append(name(i)) + .append("=") + .append(Integer.toString(parameters[i])) + .append(' '); + } + } + return sb.toString(); + } + + // Parameters + public static final int HEADER_TABLE_SIZE = 0x1; + public static final int ENABLE_PUSH = 0x2; + public static final int MAX_CONCURRENT_STREAMS = 0x3; + public static final int INITIAL_WINDOW_SIZE = 0x4; + public static final int MAX_FRAME_SIZE = 0x5; + public static final int MAX_HEADER_LIST_SIZE = 0x6; + + private String name(int i) { + switch (i+1) { + case HEADER_TABLE_SIZE: + return "HEADER_TABLE_SIZE"; + case ENABLE_PUSH: + return "ENABLE_PUSH"; + case MAX_CONCURRENT_STREAMS: + return "MAX_CONCURRENT_STREAMS"; + case INITIAL_WINDOW_SIZE: + return "INITIAL_WINDOW_SIZE"; + case MAX_FRAME_SIZE: + return "MAX_FRAME_SIZE"; + case MAX_HEADER_LIST_SIZE: + return "MAX_HEADER_LIST_SIZE"; + } + return "unknown parameter"; + } + public static final int MAX_PARAM = 0x6; + + public SettingsFrame() { + type = TYPE; + parameters = new int [MAX_PARAM]; + for (int i=0; i < parameters.length; i++) { + parameters[i] = -1; + } + } + + public int getParameter(int paramID) { + if (paramID > MAX_PARAM) { + throw new IllegalArgumentException("illegal parameter"); + } + return parameters[paramID-1]; + } + + public SettingsFrame setParameter(int paramID, int value) { + if (paramID > MAX_PARAM) { + throw new IllegalArgumentException("illegal parameter"); + } + parameters[paramID-1] = value; + return this; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + if (length % 6 != 0) { + throw new IOException("Protocol error: invalid settings frame"); + } + int n = length / 6; + for (int i=0; i 0 || id <= MAX_PARAM) { + // a known parameter. Ignore otherwise + parameters[id-1] = val; + } + } + } + + @Override + void computeLength() { + length = 0; + for (int i : parameters) { + if (i != -1) { + length += 6; + } + } + } + + @Override + void writeOutgoing(ByteBufferGenerator bg) { + super.writeOutgoing(bg); + ByteBuffer buf = bg.getBuffer(length); + for (int i = 0; i < MAX_PARAM; i++) { + if (parameters[i] != -1) { + buf.putShort((short)(i+1)); + buf.putInt(parameters[i]); + } + } + } + + private static final int K = 1024; + + public static SettingsFrame getDefaultSettings() { + SettingsFrame f = new SettingsFrame(); + // TODO: check these values + f.setParameter(ENABLE_PUSH, 1); + f.setParameter(HEADER_TABLE_SIZE, 4 * K); + f.setParameter(MAX_CONCURRENT_STREAMS, 35); + f.setParameter(INITIAL_WINDOW_SIZE, 16 * K); + f.setParameter(MAX_FRAME_SIZE, 16 * K); + return f; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java index 271e81c7a68..cea95c8f2f6 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.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 @@ -24,78 +24,819 @@ package java.net.http; +import sun.net.httpclient.hpack.DecodingCallback; + import java.io.IOException; -import java.io.UncheckedIOException; import java.net.URI; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; +import java.util.function.BiFunction; import java.util.function.LongConsumer; /** - * Http/2 Stream + * Http/2 Stream handling. + * + * REQUESTS + * + * sendHeadersOnly() -- assembles HEADERS frame and puts on connection outbound Q + * + * sendRequest() -- sendHeadersOnly() + sendBody() + * + * sendBody() -- in calling thread: obeys all flow control (so may block) + * obtains data from request body processor and places on connection + * outbound Q. + * + * sendBodyAsync() -- calls sendBody() in an executor thread. + * + * sendHeadersAsync() -- calls sendHeadersOnly() which does not block + * + * sendRequestAsync() -- calls sendRequest() in an executor thread + * + * RESPONSES + * + * Multiple responses can be received per request. Responses are queued up on + * a LinkedList of CF and the the first one on the list is completed + * with the next response + * + * getResponseAsync() -- queries list of response CFs and returns first one + * if one exists. Otherwise, creates one and adds it to list + * and returns it. Completion is achieved through the + * incoming() upcall from connection reader thread. + * + * getResponse() -- calls getResponseAsync() and waits for CF to complete + * + * responseBody() -- in calling thread: blocks for incoming DATA frames on + * stream inputQ. Obeys remote and local flow control so may block. + * Calls user response body processor with data buffers. + * + * responseBodyAsync() -- calls responseBody() in an executor thread. + * + * incoming() -- entry point called from connection reader thread. Frames are + * either handled immediately without blocking or for data frames + * placed on the stream's inputQ which is consumed by the stream's + * reader thread. + * + * PushedStream sub class + * ====================== + * Sending side methods are not used because the request comes from a PUSH_PROMISE + * frame sent by the server. When a PUSH_PROMISE is received the PushedStream + * is created. PushedStream does not use responseCF list as there can be only + * one response. The CF is created when the object created and when the response + * HEADERS frame is received the object is completed. */ class Stream extends ExchangeImpl { - void debugPrint() { - } + final Queue inputQ; + + volatile int streamid; + + long responseContentLen = -1; + long responseBytesProcessed = 0; + long requestContentLen; + + Http2Connection connection; + HttpClientImpl client; + final HttpRequestImpl request; + final DecodingCallback rspHeadersConsumer; + HttpHeadersImpl responseHeaders; + final HttpHeadersImpl requestHeaders; + final HttpHeadersImpl requestPseudoHeaders; + HttpResponse.BodyProcessor responseProcessor; + final HttpRequest.BodyProcessor requestProcessor; + HttpResponse response; + + // state flags + boolean requestSent, responseReceived; + + final FlowController userRequestFlowController = + new FlowController(); + final FlowController remoteRequestFlowController = + new FlowController(); + final FlowController responseFlowController = + new FlowController(); + + final ExecutorWrapper executor; @Override @SuppressWarnings("unchecked") CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { - return null; - } - - Stream(HttpClientImpl client, Http2Connection connection, Exchange e) { - super(e); + this.responseProcessor = processor; + CompletableFuture cf; + try { + T body = processor.onResponseBodyStart( + responseContentLen, responseHeaders, + responseFlowController); // TODO: filter headers + if (body != null) { + cf = CompletableFuture.completedFuture(body); + receiveDataAsync(processor); + } else + cf = receiveDataAsync(processor); + } catch (IOException e) { + cf = CompletableFuture.failedFuture(e); + } + PushGroup pg = request.pushGroup(); + if (pg != null) { + // if an error occurs make sure it is recorded in the PushGroup + cf = cf.whenComplete((t,e) -> pg.pushError(e)); + } + return cf; } @Override - HttpResponseImpl getResponse() throws IOException { - return null; + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("streamid: ") + .append(streamid); + return sb.toString(); } - @Override - void sendRequest() throws IOException, InterruptedException { + // pushes entire response body into response processor + // blocking when required by local or remote flow control + void receiveData() throws IOException { + Http2Frame frame; + DataFrame df = null; + try { + do { + frame = inputQ.take(); + if (!(frame instanceof DataFrame)) { + assert false; + continue; + } + df = (DataFrame) frame; + int len = df.getDataLength(); + ByteBuffer[] buffers = df.getData(); + for (ByteBuffer b : buffers) { + responseFlowController.take(); + responseProcessor.onResponseBodyChunk(b); + } + sendWindowUpdate(len); + } while (!df.getFlag(DataFrame.END_STREAM)); + } catch (InterruptedException e) { + throw new IOException(e); + } } - @Override - void sendHeadersOnly() throws IOException, InterruptedException { + private CompletableFuture receiveDataAsync(HttpResponse.BodyProcessor processor) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + receiveData(); + T body = processor.onResponseComplete(); + cf.complete(body); + responseReceived(); + } catch (Throwable t) { + cf.completeExceptionally(t); + } + }, null); + return cf; } - @Override - void sendBody() throws IOException, InterruptedException { - } - - @Override - CompletableFuture sendHeadersAsync() { - return null; - } - - @Override - CompletableFuture getResponseAsync(Void v) { - return null; + private void sendWindowUpdate(int increment) + throws IOException, InterruptedException { + if (increment == 0) + return; + LinkedList list = new LinkedList<>(); + WindowUpdateFrame frame = new WindowUpdateFrame(); + frame.streamid(streamid); + frame.setUpdate(increment); + list.add(frame); + frame = new WindowUpdateFrame(); + frame.streamid(0); + frame.setUpdate(increment); + list.add(frame); + connection.sendFrames(list); } @Override CompletableFuture sendBodyAsync() { - return null; + final CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + sendBodyImpl(); + cf.complete(null); + } catch (IOException | InterruptedException e) { + cf.completeExceptionally(e); + } + }, null); + return cf; + } + + @SuppressWarnings("unchecked") + Stream(HttpClientImpl client, Http2Connection connection, Exchange e) { + super(e); + this.client = client; + this.connection = connection; + this.request = e.request(); + this.requestProcessor = request.requestProcessor(); + responseHeaders = new HttpHeadersImpl(); + requestHeaders = new HttpHeadersImpl(); + rspHeadersConsumer = (name, value) -> { + responseHeaders.addHeader(name.toString(), value.toString()); + }; + this.executor = client.executorWrapper(); + //this.response_cf = new CompletableFuture(); + this.requestPseudoHeaders = new HttpHeadersImpl(); + // NEW + this.inputQ = new Queue<>(); + } + + @SuppressWarnings("unchecked") + Stream(HttpClientImpl client, Http2Connection connection, HttpRequestImpl req) { + super(null); + this.client = client; + this.connection = connection; + this.request = req; + this.requestProcessor = null; + responseHeaders = new HttpHeadersImpl(); + requestHeaders = new HttpHeadersImpl(); + rspHeadersConsumer = (name, value) -> { + responseHeaders.addHeader(name.toString(), value.toString()); + }; + this.executor = client.executorWrapper(); + //this.response_cf = new CompletableFuture(); + this.requestPseudoHeaders = new HttpHeadersImpl(); + // NEW + this.inputQ = new Queue<>(); + } + + /** + * Entry point from Http2Connection reader thread. + * + * Data frames will be removed by response body thread. + * + * @param frame + * @throws IOException + */ + void incoming(Http2Frame frame) throws IOException, InterruptedException { + if ((frame instanceof HeaderFrame) && ((HeaderFrame)frame).endHeaders()) { + // Complete headers accumulated. handle response. + // It's okay if there are multiple HeaderFrames. + handleResponse(); + } else if (frame instanceof DataFrame) { + inputQ.put(frame); + } else { + otherFrame(frame); + } + } + + void otherFrame(Http2Frame frame) throws IOException { + switch (frame.type()) { + case WindowUpdateFrame.TYPE: + incoming_windowUpdate((WindowUpdateFrame) frame); + break; + case ResetFrame.TYPE: + incoming_reset((ResetFrame) frame); + break; + case PriorityFrame.TYPE: + incoming_priority((PriorityFrame) frame); + break; + default: + String msg = "Unexpected frame: " + frame.toString(); + throw new IOException(msg); + } + } + + // The Hpack decoder decodes into one of these consumers of name,value pairs + + DecodingCallback rspHeadersConsumer() { + return rspHeadersConsumer; + } + + // create and return the HttpResponseImpl + protected void handleResponse() throws IOException { + HttpConnection c = connection.connection; // TODO: improve + long statusCode = responseHeaders + .firstValueAsLong(":status") + .orElseThrow(() -> new IOException("no statuscode in response")); + + this.response = new HttpResponseImpl((int)statusCode, exchange, responseHeaders, null, + c.sslParameters(), HttpClient.Version.HTTP_2, c); + this.responseContentLen = responseHeaders + .firstValueAsLong("content-length") + .orElse(-1L); + // different implementations for normal streams and pushed streams + completeResponse(response); + } + + void incoming_reset(ResetFrame frame) { + // TODO: implement reset + int error = frame.getErrorCode(); + IOException e = new IOException(ErrorFrame.stringForCode(error)); + completeResponseExceptionally(e); + throw new UnsupportedOperationException("Not implemented"); + } + + void incoming_priority(PriorityFrame frame) { + // TODO: implement priority + throw new UnsupportedOperationException("Not implemented"); + } + + void incoming_windowUpdate(WindowUpdateFrame frame) { + int amount = frame.getUpdate(); + if (amount > 0) + remoteRequestFlowController.accept(amount); + } + + void incoming_pushPromise(HttpRequestImpl pushReq, PushedStream pushStream) throws IOException { + if (Log.requests()) { + Log.logRequest("PUSH_PROMISE: " + pushReq.toString()); + } + PushGroup pushGroup = request.pushGroup(); + if (pushGroup == null) { + cancelImpl(new IllegalStateException("unexpected push promise")); + } + // get the handler and call it. + BiFunction,Boolean> ph = + pushGroup.pushHandler(); + + CompletableFuture pushCF = pushStream + .getResponseAsync(null) + .thenApply(r -> (HttpResponse)r); + boolean accept = ph.apply(pushReq, pushCF); + if (!accept) { + IOException ex = new IOException("Stream cancelled by user"); + cancelImpl(ex); + pushCF.completeExceptionally(ex); + } else { + pushStream.requestSent(); + pushGroup.addPush(); + } + } + + private OutgoingHeaders headerFrame(long contentLength) { + HttpHeadersImpl h = request.getSystemHeaders(); + if (contentLength > 0) { + h.setHeader("content-length", Long.toString(contentLength)); + } + setPseudoHeaderFields(); + OutgoingHeaders f = new OutgoingHeaders(h, request.getUserHeaders(), this); + if (contentLength == 0) { + f.setFlag(HeadersFrame.END_STREAM); + } + return f; + } + + private void setPseudoHeaderFields() { + HttpHeadersImpl hdrs = requestPseudoHeaders; + String method = request.method(); + hdrs.setHeader(":method", method); + URI uri = request.uri(); + hdrs.setHeader(":scheme", uri.getScheme()); + // TODO: userinfo deprecated. Needs to be removed + hdrs.setHeader(":authority", uri.getAuthority()); + // TODO: ensure header names beginning with : not in user headers + String query = uri.getQuery(); + String path = uri.getPath(); + if (path == null) { + if (method.equalsIgnoreCase("OPTIONS")) { + path = "*"; + } else { + path = "/"; + } + } + if (query != null) { + path += "?" + query; + } + hdrs.setHeader(":path", path); + } + + HttpHeadersImpl getRequestPseudoHeaders() { + return requestPseudoHeaders; + } + + @Override + HttpResponseImpl getResponse() throws IOException { + try { + return getResponseAsync(null).join(); + } catch (Throwable e) { + Throwable t = e.getCause(); + if (t instanceof IOException) { + throw (IOException)t; + } + throw e; + } + } + + @Override + void sendRequest() throws IOException, InterruptedException { + sendHeadersOnly(); + sendBody(); + } + + /** + * A simple general purpose blocking flow controller + */ + class FlowController implements LongConsumer { + int permits; + + FlowController() { + this.permits = 0; + } + + @Override + public synchronized void accept(long n) { + if (n < 1) { + throw new InternalError("FlowController.accept called with " + n); + } + if (permits == 0) { + permits += n; + notifyAll(); + } else { + permits += n; + } + } + + public synchronized void take() throws InterruptedException { + take(1); + } + + public synchronized void take(int amount) throws InterruptedException { + assert permits >= 0; + while (permits < amount) { + int n = Math.min(amount, permits); + permits -= n; + amount -= n; + if (amount > 0) + wait(); + } + } + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + if (Log.requests() && request != null) { + Log.logRequest(request.toString()); + } + requestContentLen = requestProcessor.onRequestStart(request, userRequestFlowController); + OutgoingHeaders f = headerFrame(requestContentLen); + connection.sendFrame(f); + } + + @Override + void sendBody() throws IOException, InterruptedException { + sendBodyImpl(); + } + + void registerStream(int id) { + this.streamid = id; + connection.putStream(this, streamid); + } + + DataFrame getDataFrame() throws IOException, InterruptedException { + userRequestFlowController.take(); + int maxpayloadLen = connection.getMaxSendFrameSize() - 9; + ByteBuffer buffer = connection.getBuffer(); + buffer.limit(maxpayloadLen); + boolean complete = requestProcessor.onRequestBodyChunk(buffer); + buffer.flip(); + int amount = buffer.remaining(); + // wait for flow control if necessary. Following method will block + // until after headers frame is sent, so correct streamid is set. + remoteRequestFlowController.take(amount); + connection.obtainSendWindow(amount); + + DataFrame df = new DataFrame(); + df.streamid(streamid); + if (complete) { + df.setFlag(DataFrame.END_STREAM); + } + df.setData(buffer); + df.computeLength(); + return df; + } + + + @Override + CompletableFuture sendHeadersAsync() { + try { + sendHeadersOnly(); + return CompletableFuture.completedFuture(null); + } catch (IOException | InterruptedException ex) { + return CompletableFuture.failedFuture(ex); + } + } + + /** + * A List of responses relating to this stream. Normally there is only + * one response, but intermediate responses like 100 are allowed + * and must be passed up to higher level before continuing. Deals with races + * such as if responses are returned before the CFs get created by + * getResponseAsync() + */ + + final List> response_cfs = new LinkedList<>(); + + @Override + CompletableFuture getResponseAsync(Void v) { + CompletableFuture cf; + synchronized (response_cfs) { + if (!response_cfs.isEmpty()) { + cf = response_cfs.remove(0); + } else { + cf = new CompletableFuture<>(); + response_cfs.add(cf); + } + } + PushGroup pg = request.pushGroup(); + if (pg != null) { + // if an error occurs make sure it is recorded in the PushGroup + cf = cf.whenComplete((t,e) -> pg.pushError(e)); + } + return cf; + } + + /** + * Completes the first uncompleted CF on list, and removes it. If there is no + * uncompleted CF then creates one (completes it) and adds to list + */ + void completeResponse(HttpResponse r) { + HttpResponseImpl resp = (HttpResponseImpl)r; + synchronized (response_cfs) { + for (CompletableFuture cf : response_cfs) { + if (!cf.isDone()) { + cf.complete(resp); + response_cfs.remove(cf); + //responseHeaders = new HttpHeadersImpl(); // for any following header blocks + return; + } else + System.err.println("Stream: " + this + " ALREADY DONE"); + } + response_cfs.add(CompletableFuture.completedFuture(resp)); + //responseHeaders = new HttpHeadersImpl(); // for any following header blocks + } + } + + // methods to update state and remove stream when finished + + synchronized void requestSent() { + requestSent = true; + if (responseReceived) + connection.deleteStream(this); + } + + synchronized void responseReceived() { + responseReceived = true; + if (requestSent) + connection.deleteStream(this); + PushGroup pg = request.pushGroup(); + if (pg != null) + pg.noMorePushes(); + } + + /** + * same as above but for errors + * + * @param t + */ + void completeResponseExceptionally(Throwable t) { + synchronized (response_cfs) { + for (CompletableFuture cf : response_cfs) { + if (!cf.isDone()) { + cf.completeExceptionally(t); + response_cfs.remove(cf); + return; + } + } + response_cfs.add(CompletableFuture.failedFuture(t)); + } + } + + void sendBodyImpl() throws IOException, InterruptedException { + if (requestContentLen == 0) { + // no body + return; + } + DataFrame df; + do { + df = getDataFrame(); + // TODO: check accumulated content length (if not checked below) + connection.sendFrame(df); + } while (!df.getFlag(DataFrame.END_STREAM)); + requestSent(); } @Override void cancel() { + cancelImpl(new Exception("Cancelled")); } + void cancelImpl(Throwable e) { + Log.logTrace("cancelling stream: {0}\n", e.toString()); + inputQ.close(); + try { + connection.resetStream(streamid, ResetFrame.CANCEL); + } catch (IOException | InterruptedException ex) { + Log.logError(ex); + } + } + @Override CompletableFuture sendRequestAsync() { - return null; + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + sendRequest(); + cf.complete(null); + } catch (IOException |InterruptedException e) { + cf.completeExceptionally(e); + } + }, null); + return cf; } @Override T responseBody(HttpResponse.BodyProcessor processor) throws IOException { - return null; + this.responseProcessor = processor; + T body = processor.onResponseBodyStart( + responseContentLen, responseHeaders, + responseFlowController); // TODO: filter headers + if (body == null) { + receiveData(); + return processor.onResponseComplete(); + } else + receiveDataAsync(processor); + responseReceived(); + return body; + } + + // called from Http2Connection reader thread + synchronized void updateOutgoingWindow(int update) { + remoteRequestFlowController.accept(update); + } + + void close(String msg) { + cancel(); + } + + static class PushedStream extends Stream { + final PushGroup pushGroup; + final private Stream parent; // used by server push streams + // push streams need the response CF allocated up front as it is + // given directly to user via the multi handler callback function. + final CompletableFuture pushCF; + final HttpRequestImpl pushReq; + + PushedStream(PushGroup pushGroup, HttpClientImpl client, + Http2Connection connection, Stream parent, + HttpRequestImpl pushReq) { + super(client, connection, pushReq); + this.pushGroup = pushGroup; + this.pushReq = pushReq; + this.pushCF = new CompletableFuture<>(); + this.parent = parent; + } + + // Following methods call the super class but in case of + // error record it in the PushGroup. The error method is called + // with a null value when no error occurred (is a no-op) + @Override + CompletableFuture sendBodyAsync() { + return super.sendBodyAsync() + .whenComplete((v, t) -> pushGroup.pushError(t)); + } + + @Override + CompletableFuture sendHeadersAsync() { + return super.sendHeadersAsync() + .whenComplete((v, t) -> pushGroup.pushError(t)); + } + + @Override + CompletableFuture sendRequestAsync() { + return super.sendRequestAsync() + .whenComplete((v, t) -> pushGroup.pushError(t)); + } + + @Override + CompletableFuture getResponseAsync(Void vo) { + return pushCF.whenComplete((v, t) -> pushGroup.pushError(t)); + } + + @Override + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return super.responseBodyAsync(processor) + .whenComplete((v, t) -> pushGroup.pushError(t)); + } + + @Override + void completeResponse(HttpResponse r) { + HttpResponseImpl resp = (HttpResponseImpl)r; + Utils.logResponse(resp); + pushCF.complete(resp); + } + + @Override + void completeResponseExceptionally(Throwable t) { + pushCF.completeExceptionally(t); + } + + @Override + synchronized void responseReceived() { + super.responseReceived(); + pushGroup.pushCompleted(); + } + + // create and return the PushResponseImpl + @Override + protected void handleResponse() { + HttpConnection c = connection.connection; // TODO: improve + long statusCode = responseHeaders + .firstValueAsLong(":status") + .orElse(-1L); + + if (statusCode == -1L) + completeResponseExceptionally(new IOException("No status code")); + ImmutableHeaders h = new ImmutableHeaders(responseHeaders, Utils.ALL_HEADERS); + this.response = new HttpResponseImpl((int)statusCode, pushReq, h, this, + c.sslParameters()); + this.responseContentLen = responseHeaders + .firstValueAsLong("content-length") + .orElse(-1L); + // different implementations for normal streams and pushed streams + completeResponse(response); + } + } + + /** + * One PushGroup object is associated with the parent Stream of + * the pushed Streams. This keeps track of all common state associated + * with the pushes. + */ + static class PushGroup { + // the overall completion object, completed when all pushes are done. + final CompletableFuture resultCF; + Throwable error; // any exception that occured during pushes + + // CF for main response + final CompletableFuture mainResponse; + + // user's processor object + final HttpResponse.MultiProcessor multiProcessor; + + // per push handler function provided by processor + final private BiFunction, + Boolean> pushHandler; + int numberOfPushes; + int remainingPushes; + boolean noMorePushes = false; + + PushGroup(HttpResponse.MultiProcessor multiProcessor, HttpRequestImpl req) { + this.resultCF = new CompletableFuture<>(); + this.mainResponse = new CompletableFuture<>(); + this.multiProcessor = multiProcessor; + this.pushHandler = multiProcessor.onStart(req, mainResponse); + } + + CompletableFuture groupResult() { + return resultCF; + } + + CompletableFuture mainResponse() { + return mainResponse; + } + + private BiFunction, Boolean> pushHandler() + { + return pushHandler; + } + + synchronized void addPush() { + numberOfPushes++; + remainingPushes++; + } + + synchronized int numberOfPushes() { + return numberOfPushes; + } + // This is called when the main body response completes because it means + // no more PUSH_PROMISEs are possible + synchronized void noMorePushes() { + noMorePushes = true; + checkIfCompleted(); + } + + synchronized void pushCompleted() { + remainingPushes--; + checkIfCompleted(); + } + + synchronized void checkIfCompleted() { + if (remainingPushes == 0 && error == null && noMorePushes) { + T overallResult = multiProcessor.onComplete(); + resultCF.complete(overallResult); + } + } + + synchronized void pushError(Throwable t) { + if (t == null) + return; + this.error = t; + resultCF.completeExceptionally(t); + } } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java index a201a23f4bd..d16248d4b6b 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java @@ -21,28 +21,37 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any */ - package java.net.http; +import sun.net.NetProperties; + +import javax.net.ssl.SSLParameters; import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; import java.net.NetPermission; import java.net.URI; import java.net.URLPermission; +import java.nio.Buffer; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; -import javax.net.ssl.SSLParameters; -import sun.net.NetProperties; +import java.util.concurrent.CompletableFuture; +import java.util.function.LongBinaryOperator; +import java.util.function.Predicate; /** * Miscellaneous utilities */ -class Utils { +final class Utils { /** * Allocated buffer size. Must never be higher than 16K. But can be lower @@ -51,7 +60,59 @@ class Utils { */ public static final int BUFSIZE = 16 * 1024; - /** Validates a RFC7230 token */ + private static final Set DISALLOWED_HEADERS_SET = Set.of( + "authorization", "connection", "cookie", "content-length", + "date", "expect", "from", "host", "origin", "proxy-authorization", + "referer", "user-agent", "upgrade", "via", "warning"); + + static final Predicate + ALLOWED_HEADERS = header -> !Utils.DISALLOWED_HEADERS_SET.contains(header); + + static final Predicate + ALL_HEADERS = header -> true; + + static InetSocketAddress getAddress(HttpRequestImpl req) { + URI uri = req.uri(); + if (uri == null) { + return req.authority(); + } + int port = uri.getPort(); + if (port == -1) { + if (uri.getScheme().equalsIgnoreCase("https")) { + port = 443; + } else { + port = 80; + } + } + String host = uri.getHost(); + if (req.proxy() == null) { + return new InetSocketAddress(host, port); + } else { + return InetSocketAddress.createUnresolved(host, port); + } + } + + /** + * Puts position to limit and limit to capacity so we can resume reading + * into this buffer, but if required > 0 then limit may be reduced so that + * no more than required bytes are read next time. + */ + static void resumeChannelRead(ByteBuffer buf, int required) { + int limit = buf.limit(); + buf.position(limit); + int capacity = buf.capacity() - limit; + if (required > 0 && required < capacity) { + buf.limit(limit + required); + } else { + buf.limit(buf.capacity()); + } + } + + private Utils() { } + + /** + * Validates a RFC7230 token + */ static void validateToken(String token, String errormsg) { int length = token.length(); for (int i = 0; i < length; i++) { @@ -69,7 +130,7 @@ class Utils { } /** - * Return sthe security permission required for the given details. + * Returns the security permission required for the given details. * If method is CONNECT, then uri must be of form "scheme://host:port" */ static URLPermission getPermission(URI uri, @@ -117,13 +178,13 @@ class Utils { } static int getIntegerNetProperty(String name, int defaultValue) { - return AccessController.doPrivileged((PrivilegedAction)() -> - NetProperties.getInteger(name, defaultValue) ); + return AccessController.doPrivileged((PrivilegedAction) () -> + NetProperties.getInteger(name, defaultValue)); } static String getNetProperty(String name) { - return AccessController.doPrivileged((PrivilegedAction)() -> - NetProperties.get(name) ); + return AccessController.doPrivileged((PrivilegedAction) () -> + NetProperties.get(name)); } static SSLParameters copySSLParameters(SSLParameters p) { @@ -134,7 +195,9 @@ class Utils { p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm()); p1.setMaximumPacketSize(p.getMaximumPacketSize()); p1.setNeedClientAuth(p.getNeedClientAuth()); - p1.setProtocols(p.getProtocols().clone()); + String[] protocols = p.getProtocols(); + if (protocols != null) + p1.setProtocols(protocols.clone()); p1.setSNIMatchers(p.getSNIMatchers()); p1.setServerNames(p.getServerNames()); p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder()); @@ -142,33 +205,14 @@ class Utils { return p1; } - - /** Resumes reading into the given buffer. */ - static void unflip(ByteBuffer buf) { - buf.position(buf.limit()); - buf.limit(buf.capacity()); - } - /** * Set limit to position, and position to mark. - * - * - * @param buffer - * @param mark */ static void flipToMark(ByteBuffer buffer, int mark) { buffer.limit(buffer.position()); buffer.position(mark); } - /** Compact and leave ready for reading. */ - static void compact(List buffers) { - for (ByteBuffer b : buffers) { - b.compact(); - b.flip(); - } - } - static String stackTrace(Throwable t) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); String s = null; @@ -182,8 +226,10 @@ class Utils { return s; } - /** Copies as much of src to dst as possible. */ - static void copy (ByteBuffer src, ByteBuffer dst) { + /** + * Copies as much of src to dst as possible. + */ + static void copy(ByteBuffer src, ByteBuffer dst) { int srcLen = src.remaining(); int dstLen = dst.remaining(); if (srcLen > dstLen) { @@ -204,18 +250,101 @@ class Utils { return dst; } - static String combine(String[] s) { - StringBuilder sb = new StringBuilder(); - sb.append('['); - boolean first = true; - for (String s1 : s) { - if (!first) { - sb.append(", "); - first = false; - } - sb.append(s1); - } - sb.append(']'); - return sb.toString(); + // + // Helps to trim long names (packages, nested/inner types) in logs/toString + // + static String toStringSimple(Object o) { + return o.getClass().getSimpleName() + "@" + + Integer.toHexString(System.identityHashCode(o)); } + + // + // 1. It adds a number of remaining bytes; + // 2. Standard Buffer-type toString for CharBuffer (since it adheres to the + // contract of java.lang.CharSequence.toString() which is both not too + // useful and not too private) + // + static String toString(Buffer b) { + return toStringSimple(b) + + "[pos=" + b.position() + + " lim=" + b.limit() + + " cap=" + b.capacity() + + " rem=" + b.remaining() + "]"; + } + + static String toString(CharSequence s) { + return s == null + ? "null" + : toStringSimple(s) + "[len=" + s.length() + "]"; + } + + static String dump(Object... objects) { + return Arrays.toString(objects); + } + + static final System.Logger logger = System.getLogger("java.net.http.WebSocket"); + + static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0); + + static String webSocketSpecViolation(String section, String detail) { + return "RFC 6455 " + section + " " + detail; + } + + static void logResponse(HttpResponseImpl r) { + if (!Log.requests()) { + return; + } + StringBuilder sb = new StringBuilder(); + String method = r.request().method(); + URI uri = r.uri(); + String uristring = uri == null ? "" : uri.toString(); + sb.append('(').append(method).append(" ").append(uristring).append(") ").append(Integer.toString(r.statusCode())); + Log.logResponse(sb.toString()); + } + + static int remaining(ByteBuffer[] bufs) { + int remain = 0; + for (ByteBuffer buf : bufs) + remain += buf.remaining(); + return remain; + } + + // assumes buffer was written into starting at position zero + static void unflip(ByteBuffer buf) { + buf.position(buf.limit()); + buf.limit(buf.capacity()); + } + + static void close(Closeable... chans) { + for (Closeable chan : chans) { + System.err.println("Closing " + chan); + try { + chan.close(); + } catch (IOException e) { + } + } + } + + static ByteBuffer[] reduce(ByteBuffer[] bufs, int start, int number) { + if (start == 0 && number == bufs.length) + return bufs; + ByteBuffer[] nbufs = new ByteBuffer[number]; + int j = 0; + for (int i=start; iHigh level HTTP API - * This provides a high-level client interface to HTTP (versions 1.1 and 2). - * Synchronous and asynchronous (via - * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main - * classes defined are: + *

      High level HTTP and WebSocket API

      + * This provides a high-level client interfaces to HTTP (versions 1.1 and 2) + * and WebSocket. Synchronous and asynchronous (via {@link + * java.util.concurrent.CompletableFuture}) modes are provided for HTTP. + * WebSocket works in asynchronous mode only. The main types defined are: *
        *
      • {@link java.net.http.HttpClient}
      • *
      • {@link java.net.http.HttpRequest}
      • diff --git a/jdk/test/java/net/httpclient/APIErrors.java b/jdk/test/java/net/httpclient/APIErrors.java index 845c665088a..193cfa7f2e8 100644 --- a/jdk/test/java/net/httpclient/APIErrors.java +++ b/jdk/test/java/net/httpclient/APIErrors.java @@ -26,6 +26,7 @@ * @bug 8087112 * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @build TestKit * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java * @run main/othervm APIErrors @@ -73,26 +74,6 @@ public class APIErrors { } } - static void reject(Runnable r, Class extype) { - try { - r.run(); - throw new RuntimeException("Expected: " + extype); - } catch (Throwable t) { - if (!extype.isAssignableFrom(t.getClass())) { - throw new RuntimeException("Wrong exception type: " + extype + " / " - +t.getClass()); - } - } - } - - static void accept(Runnable r) { - try { - r.run(); - } catch (Throwable t) { - throw new RuntimeException("Unexpected exception: " + t); - } - } - static void checkNonNull(Supplier r) { if (r.get() == null) throw new RuntimeException("Unexpected null return:"); @@ -108,12 +89,14 @@ public class APIErrors { System.out.println("Test 1"); HttpClient.Builder cb = HttpClient.create(); InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); - reject(() -> { cb.priority(-1);}, IllegalArgumentException.class); - reject(() -> { cb.priority(500);}, IllegalArgumentException.class); - accept(() -> { cb.priority(1);}); - accept(() -> { cb.priority(255);}); - - accept(() -> {clients.add(cb.build()); clients.add(cb.build());}); + TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(-1)); + TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(500)); + TestKit.assertNotThrows(() -> cb.priority(1)); + TestKit.assertNotThrows(() -> cb.priority(255)); + TestKit.assertNotThrows(() -> { + clients.add(cb.build()); + clients.add(cb.build()); + }); } static void test2() throws Exception { @@ -139,7 +122,7 @@ public class APIErrors { static void test3() throws Exception { System.out.println("Test 3"); - reject(()-> { + TestKit.assertThrows(IllegalStateException.class, ()-> { try { HttpRequest r1 = request(); HttpResponse resp = r1.response(); @@ -147,9 +130,9 @@ public class APIErrors { } catch (IOException |InterruptedException e) { throw new RuntimeException(e); } - }, IllegalStateException.class); + }); - reject(()-> { + TestKit.assertThrows(IllegalStateException.class, ()-> { try { HttpRequest r1 = request(); HttpResponse resp = r1.response(); @@ -157,8 +140,8 @@ public class APIErrors { } catch (IOException |InterruptedException | ExecutionException e) { throw new RuntimeException(e); } - }, IllegalStateException.class); - reject(()-> { + }); + TestKit.assertThrows(IllegalStateException.class, ()-> { try { HttpRequest r1 = request(); HttpResponse resp1 = r1.responseAsync().get(); @@ -166,7 +149,7 @@ public class APIErrors { } catch (IOException |InterruptedException | ExecutionException e) { throw new RuntimeException(e); } - }, IllegalStateException.class); + }); } static class Auth extends java.net.Authenticator { diff --git a/jdk/test/java/net/httpclient/EchoHandler.java b/jdk/test/java/net/httpclient/EchoHandler.java new file mode 100644 index 00000000000..ea14d2330fa --- /dev/null +++ b/jdk/test/java/net/httpclient/EchoHandler.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +import com.sun.net.httpserver.*; +import java.net.*; +import java.net.http.*; +import java.io.*; +import java.util.concurrent.*; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import jdk.testlibrary.SimpleSSLContext; +import static java.net.http.HttpRequest.*; +import static java.net.http.HttpResponse.*; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class EchoHandler implements HttpHandler { + public EchoHandler() {} + + @Override + public void handle(HttpExchange t) + throws IOException { + try { + System.err.println("EchoHandler received request to " + t.getRequestURI()); + InputStream is = t.getRequestBody(); + Headers map = t.getRequestHeaders(); + Headers map1 = t.getResponseHeaders(); + map1.add("X-Hello", "world"); + map1.add("X-Bye", "universe"); + String fixedrequest = map.getFirst("XFixed"); + File outfile = File.createTempFile("foo", "bar"); + FileOutputStream fos = new FileOutputStream(outfile); + int count = (int) is.transferTo(fos); + is.close(); + fos.close(); + InputStream is1 = new FileInputStream(outfile); + OutputStream os = null; + // return the number of bytes received (no echo) + String summary = map.getFirst("XSummary"); + if (fixedrequest != null && summary == null) { + t.sendResponseHeaders(200, count); + os = t.getResponseBody(); + is1.transferTo(os); + } else { + t.sendResponseHeaders(200, 0); + os = t.getResponseBody(); + is1.transferTo(os); + + if (summary != null) { + String s = Integer.toString(count); + os.write(s.getBytes()); + } + } + outfile.delete(); + os.close(); + is1.close(); + } catch (Throwable e) { + e.printStackTrace(); + throw new IOException(e); + } + } +} diff --git a/jdk/test/java/net/httpclient/LightWeightHttpServer.java b/jdk/test/java/net/httpclient/LightWeightHttpServer.java index 315849521a0..a0d6e9ac9c7 100644 --- a/jdk/test/java/net/httpclient/LightWeightHttpServer.java +++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java @@ -22,10 +22,10 @@ */ /** - * @library /lib/testlibrary/ - * @build jdk.testlibrary.SimpleSSLContext ProxyServer - * @compile ../../../com/sun/net/httpserver/LogFilter.java - * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * library /lib/testlibrary/ / + * build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler + * compile ../../../com/sun/net/httpserver/LogFilter.java + * compile ../../../com/sun/net/httpserver/FileServerHandler.java */ import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpContext; diff --git a/jdk/test/java/net/httpclient/ManyRequests.java b/jdk/test/java/net/httpclient/ManyRequests.java index 10081f5def7..95b3ae38e6d 100644 --- a/jdk/test/java/net/httpclient/ManyRequests.java +++ b/jdk/test/java/net/httpclient/ManyRequests.java @@ -24,18 +24,17 @@ /** * @test * @bug 8087112 - * @library /lib/testlibrary/ - * @build jdk.testlibrary.SimpleSSLContext + * @library /lib/testlibrary/ / + * @build jdk.testlibrary.SimpleSSLContext EchoHandler * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java - * @run main/othervm ManyRequests + * @run main/othervm/timeout=40 -Djava.net.http.HttpClient.log=ssl ManyRequests * @summary Send a large number of requests asynchronously */ //package javaapplication16; -import com.sun.net.httpserver.HttpsConfigurator; -import com.sun.net.httpserver.HttpsServer; +import com.sun.net.httpserver.*; import java.io.IOException; import java.io.UncheckedIOException; import java.net.http.HttpClient; @@ -47,18 +46,25 @@ import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.Random; +import java.util.logging.*; import java.util.concurrent.CompletableFuture; -import javax.net.ssl.SSLContext; +import javax.net.ssl.*; import jdk.testlibrary.SimpleSSLContext; public class ManyRequests { + volatile static int counter = 0; + public static void main(String[] args) throws Exception { + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + logger.setLevel(Level.ALL); + logger.info("TEST"); + SSLContext ctx = new SimpleSSLContext().get(); InetSocketAddress addr = new InetSocketAddress(0); HttpsServer server = HttpsServer.create(addr, 0); - server.setHttpsConfigurator(new HttpsConfigurator(ctx)); + server.setHttpsConfigurator(new Configurator(ctx)); HttpClient client = HttpClient.create() .sslContext(ctx) @@ -72,7 +78,8 @@ public class ManyRequests { } } - static final int REQUESTS = 1000; + //static final int REQUESTS = 1000; + static final int REQUESTS = 20; static void test(HttpsServer server, HttpClient client) throws Exception { int port = server.getAddress().getPort(); @@ -102,6 +109,9 @@ public class ManyRequests { resp.bodyAsync(HttpResponse.ignoreBody()); String s = "Expected 200, got: " + resp.statusCode(); return completedWithIOException(s); + } else { + counter++; + System.out.println("Result from " + counter); } return resp.bodyAsync(HttpResponse.asByteArray()) .thenApply((b) -> new Pair<>(resp, b)); @@ -114,14 +124,18 @@ public class ManyRequests { }); } + // wait for them all to complete and throw exception in case of error - CompletableFuture.allOf(results).join(); + //try { + CompletableFuture.allOf(results).join(); + //} catch (Exception e) { + //e.printStackTrace(); + //throw e; + //} } static CompletableFuture completedWithIOException(String message) { - CompletableFuture cf = new CompletableFuture<>(); - cf.completeExceptionally(new IOException(message)); - return cf; + return CompletableFuture.failedFuture(new IOException(message)); } static final class Pair { @@ -192,3 +206,14 @@ public class ManyRequests { throw new RuntimeException(sb.toString()); } } + +class Configurator extends HttpsConfigurator { + public Configurator(SSLContext ctx) { + super(ctx); + } + + public void configure (HttpsParameters params) { + params.setSSLParameters (getSSLContext().getSupportedSSLParameters()); + } +} + diff --git a/jdk/test/java/net/httpclient/RequestBodyTest.java b/jdk/test/java/net/httpclient/RequestBodyTest.java index 579f75edfb1..86478f9e5e1 100644 --- a/jdk/test/java/net/httpclient/RequestBodyTest.java +++ b/jdk/test/java/net/httpclient/RequestBodyTest.java @@ -23,10 +23,11 @@ /** * @test @bug 8087112 - * @library /lib/testlibrary/ - * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @library /lib/testlibrary/ / * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @build LightWeightHttpServer + * @build jdk.testlibrary.SimpleSSLContext ProxyServer * @run main/othervm RequestBodyTest */ diff --git a/jdk/test/java/net/httpclient/SmokeTest.java b/jdk/test/java/net/httpclient/SmokeTest.java index ec516623179..5d8fde15c85 100644 --- a/jdk/test/java/net/httpclient/SmokeTest.java +++ b/jdk/test/java/net/httpclient/SmokeTest.java @@ -24,15 +24,13 @@ /** * @test * @bug 8087112 - * @library /lib/testlibrary/ - * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @library /lib/testlibrary/ / + * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java * @run main/othervm SmokeTest */ -//package javaapplication16; - import com.sun.net.httpserver.*; import java.net.*; import java.net.http.*; @@ -69,6 +67,7 @@ import java.util.logging.Logger; */ public class SmokeTest { static SSLContext ctx; + static SSLParameters sslparams; static HttpServer s1 ; static HttpsServer s2; static ExecutorService executor; @@ -107,6 +106,7 @@ public class SmokeTest { client = HttpClient.create() .sslContext(ctx) + .sslParameters(sslparams) .followRedirects(HttpClient.Redirect.ALWAYS) .executorService(Executors.newCachedThreadPool()) .build(); @@ -285,6 +285,7 @@ public class SmokeTest { HttpClient cl = HttpClient.create() .proxy(ProxySelector.of(proxyAddr)) .sslContext(ctx) + .sslParameters(sslparams) .build(); CompletableFuture fut = cl.request(uri) @@ -672,7 +673,8 @@ public class SmokeTest { s1.setExecutor(executor); s2.setExecutor(executor); ctx = new SimpleSSLContext().get(); - s2.setHttpsConfigurator(new HttpsConfigurator(ctx)); + sslparams = ctx.getSupportedSSLParameters(); + s2.setHttpsConfigurator(new Configurator(ctx)); s1.start(); s2.start(); @@ -689,6 +691,16 @@ public class SmokeTest { } } +class Configurator extends HttpsConfigurator { + public Configurator(SSLContext ctx) { + super(ctx); + } + + public void configure (HttpsParameters params) { + params.setSSLParameters (getSSLContext().getSupportedSSLParameters()); + } +} + class UploadServer extends Thread { int statusCode; ServerSocket ss; diff --git a/jdk/test/java/net/httpclient/TestKit.java b/jdk/test/java/net/httpclient/TestKit.java new file mode 100644 index 00000000000..308c004e16a --- /dev/null +++ b/jdk/test/java/net/httpclient/TestKit.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.regex.Pattern; + +import static java.util.Objects.requireNonNull; + +// +// A set of testing utility functions +// +public final class TestKit { + + private TestKit() { } + + public static void assertNotThrows(ThrowingProcedure code) { + requireNonNull(code, "code"); + assertNotThrows(() -> { + code.run(); + return null; + }); + } + + public static V assertNotThrows(ThrowingFunction code) { + requireNonNull(code, "code"); + try { + return code.run(); + } catch (Throwable t) { + throw new RuntimeException("Expected to run normally, but threw " + + t.getClass().getCanonicalName(), t); + } + } + + public static T assertThrows(Class clazz, + ThrowingProcedure code) { + requireNonNull(clazz, "clazz"); + requireNonNull(code, "code"); + try { + code.run(); + } catch (Throwable t) { + if (clazz.isInstance(t)) { + return clazz.cast(t); + } + throw new RuntimeException("Expected to catch an exception of type " + + clazz.getCanonicalName() + ", but caught " + + t.getClass().getCanonicalName(), t); + + } + throw new RuntimeException("Expected to catch an exception of type " + + clazz.getCanonicalName() + ", but caught nothing"); + } + + public interface ThrowingProcedure { + void run() throws Throwable; + } + + public interface ThrowingFunction { + V run() throws Throwable; + } + + // The rationale behind asking for a regex is to not pollute variable names + // space in the scope of assertion: if it's something as simple as checking + // a message, we can do it inside + public static T assertThrows(Class clazz, + String messageRegex, + ThrowingProcedure code) { + requireNonNull(messageRegex, "messagePattern"); + T t = assertThrows(clazz, code); + String m = t.getMessage(); + if (m == null) { + throw new RuntimeException(String.format( + "Expected exception message to match the regex '%s', " + + "but the message was null", messageRegex), t); + } + if (!Pattern.matches(messageRegex, m)) { + throw new RuntimeException(String.format( + "Expected exception message to match the regex '%s', " + + "actual message: %s", messageRegex, m), t); + } + return t; + } +} diff --git a/jdk/test/java/net/httpclient/TestKitTest.java b/jdk/test/java/net/httpclient/TestKitTest.java new file mode 100644 index 00000000000..da0f043191d --- /dev/null +++ b/jdk/test/java/net/httpclient/TestKitTest.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.io.IOException; +import java.util.IllegalFormatException; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @compile TestKit.java + * @run testng TestKitTest + */ +public final class TestKitTest { + + public static void main(String[] args) { + testAssertNotThrows(); + testAssertThrows(); + } + + private static void testAssertNotThrows() { + Integer integer = TestKit.assertNotThrows( + () -> TestKit.assertNotThrows(() -> 1) + ); + assertEquals(integer, Integer.valueOf(1)); + + RuntimeException re = TestKit.assertThrows( + RuntimeException.class, + () -> TestKit.assertNotThrows(() -> { throw new IOException(); }) + ); + assertEquals(re.getMessage(), + "Expected to run normally, but threw " + + "java.io.IOException"); + + TestKit.assertNotThrows( + () -> TestKit.assertNotThrows(() -> { }) + ); + + re = TestKit.assertThrows( + RuntimeException.class, + () -> TestKit.assertNotThrows((TestKit.ThrowingProcedure) () -> { throw new IOException(); }) + ); + assertEquals(re.getMessage(), + "Expected to run normally, but threw " + + "java.io.IOException"); + } + + private static void testAssertThrows() { + NullPointerException npe = TestKit.assertThrows( + NullPointerException.class, + () -> TestKit.assertThrows(null, null) + ); + assertNotNull(npe); + assertTrue(Set.of("clazz", "code").contains(npe.getMessage()), npe.getMessage()); + + npe = TestKit.assertThrows( + NullPointerException.class, + () -> TestKit.assertThrows(IOException.class, null) + ); + assertNotNull(npe); + assertEquals(npe.getMessage(), "code"); + + npe = TestKit.assertThrows( + NullPointerException.class, + () -> TestKit.assertThrows(null, () -> { }) + ); + assertEquals(npe.getMessage(), "clazz"); + + npe = TestKit.assertThrows( + NullPointerException.class, + () -> { throw new NullPointerException(); } + ); + assertNotNull(npe); + assertNull(npe.getMessage()); + assertEquals(npe.getClass(), NullPointerException.class); + + RuntimeException re = TestKit.assertThrows( + RuntimeException.class, + () -> TestKit.assertThrows(NullPointerException.class, () -> { }) + ); + assertEquals(re.getClass(), RuntimeException.class); + assertEquals(re.getMessage(), + "Expected to catch an exception of type " + + "java.lang.NullPointerException, but caught nothing"); + + re = TestKit.assertThrows( + RuntimeException.class, + () -> { throw new NullPointerException(); } + ); + assertNotNull(re); + assertNull(re.getMessage()); + assertEquals(re.getClass(), NullPointerException.class); + + re = TestKit.assertThrows( + RuntimeException.class, + () -> TestKit.assertThrows( + IllegalFormatException.class, + () -> { throw new IndexOutOfBoundsException(); } + )); + assertNotNull(re); + assertEquals(re.getClass(), RuntimeException.class); + assertEquals(re.getMessage(), + "Expected to catch an exception of type java.util.IllegalFormatException" + + ", but caught java.lang.IndexOutOfBoundsException"); + } +} diff --git a/jdk/test/java/net/httpclient/http2/BasicTest.java b/jdk/test/java/net/httpclient/http2/BasicTest.java new file mode 100644 index 00000000000..0d53bbf1b04 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/BasicTest.java @@ -0,0 +1,222 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8087112 + * @library /lib/testlibrary + * @build jdk.testlibrary.SimpleSSLContext + * @modules java.httpclient + * @compile/module=java.httpclient java/net/http/BodyOutputStream.java + * @compile/module=java.httpclient java/net/http/BodyInputStream.java + * @compile/module=java.httpclient java/net/http/EchoHandler.java + * @compile/module=java.httpclient java/net/http/Http2Handler.java + * @compile/module=java.httpclient java/net/http/Http2TestExchange.java + * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java + * @compile/module=java.httpclient java/net/http/Http2TestServer.java + * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java + * @compile/module=java.httpclient java/net/http/TestUtil.java + * @run testng/othervm -Djava.net.http.HttpClient.log=ssl,requests,responses,errors BasicTest + */ + +import java.io.*; +import java.net.*; +import java.net.http.*; +import static java.net.http.HttpClient.Version.HTTP_2; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.concurrent.*; +import jdk.testlibrary.SimpleSSLContext; + + +import org.testng.annotations.Test; +import org.testng.annotations.Parameters; + +@Test +public class BasicTest { + static int httpPort, httpsPort; + static Http2TestServer httpServer, httpsServer; + static HttpClient client = null; + static ExecutorService exec; + static SSLContext sslContext; + + static String httpURIString, httpsURIString; + + static void initialize() throws Exception { + try { + SimpleSSLContext sslct = new SimpleSSLContext(); + sslContext = sslct.get(); + client = getClient(); + exec = client.executorService(); + httpServer = new Http2TestServer(false, 0, new EchoHandler(), + exec, sslContext); + httpPort = httpServer.getAddress().getPort(); + + httpsServer = new Http2TestServer(true, 0, new EchoHandler(), + exec, sslContext); + + httpsPort = httpsServer.getAddress().getPort(); + httpURIString = "http://127.0.0.1:" + Integer.toString(httpPort) + + "/foo/"; + httpsURIString = "https://127.0.0.1:" + Integer.toString(httpsPort) + + "/bar/"; + + httpServer.start(); + httpsServer.start(); + } catch (Throwable e) { + System.err.println("Throwing now"); + e.printStackTrace(); + throw e; + } + } + + @Test(timeOut=30000) + public static void test() throws Exception { + try { + initialize(); + simpleTest(false); + simpleTest(true); + streamTest(false); + streamTest(true); + Thread.sleep(1000 * 4); + } finally { + httpServer.stop(); + httpsServer.stop(); + exec.shutdownNow(); + } + } + + static HttpClient getClient() { + if (client == null) { + client = HttpClient.create() + .sslContext(sslContext) + .version(HTTP_2) + .build(); + } + return client; + } + + static URI getURI(boolean secure) { + if (secure) + return URI.create(httpsURIString); + else + return URI.create(httpURIString); + } + + static void checkStatus(int expected, int found) throws Exception { + if (expected != found) { + System.err.printf ("Test failed: wrong status code %d/%d\n", + expected, found); + throw new RuntimeException("Test failed"); + } + } + + static void checkStrings(String expected, String found) throws Exception { + if (!expected.equals(found)) { + System.err.printf ("Test failed: wrong string %s/%s\n", + expected, found); + throw new RuntimeException("Test failed"); + } + } + + static Void compareFiles(Path path1, Path path2) { + return java.net.http.TestUtil.compareFiles(path1, path2); + } + + static Path tempFile() { + return java.net.http.TestUtil.tempFile(); + } + + static final String SIMPLE_STRING = "Hello world Goodbye world"; + + static final int LOOPS = 13; + static final int FILESIZE = 64 * 1024; + + static void streamTest(boolean secure) throws Exception { + URI uri = getURI(secure); + System.err.printf("streamTest %b to %s\n" , secure, uri); + + HttpClient client = getClient(); + Path src = java.net.http.TestUtil.getAFile(FILESIZE * 4); + HttpRequest req = client.request(uri) + .body(HttpRequest.fromFile(src)) + .POST(); + + CompletableFuture response = req.responseAsync() + .thenCompose(resp -> { + if (resp.statusCode() != 200) + throw new RuntimeException(); + return resp.bodyAsync(HttpResponse.asInputStream()); + }); + InputStream is = response.join(); + File dest = File.createTempFile("foo","bar"); + dest.deleteOnExit(); + FileOutputStream os = new FileOutputStream(dest); + is.transferTo(os); + is.close(); + os.close(); + int count = 0; + compareFiles(src, dest.toPath()); + System.err.println("DONE"); + } + + + static void simpleTest(boolean secure) throws Exception { + URI uri = getURI(secure); + System.err.println("Request to " + uri); + + // Do a simple warmup request + + HttpClient client = getClient(); + HttpRequest req = client.request(uri) + .body(HttpRequest.fromString(SIMPLE_STRING)) + .POST(); + HttpResponse response = req.response(); + HttpHeaders h = response.headers(); + + checkStatus(200, response.statusCode()); + + String responseBody = response.body(HttpResponse.asString()); + checkStrings(SIMPLE_STRING, responseBody); + + checkStrings(h.firstValue("x-hello").get(), "world"); + checkStrings(h.firstValue("x-bye").get(), "universe"); + + // Do loops asynchronously + + CompletableFuture[] responses = new CompletableFuture[LOOPS]; + final Path source = java.net.http.TestUtil.getAFile(FILESIZE); + for (int i = 0; i < LOOPS; i++) { + responses[i] = client.request(uri) + .body(HttpRequest.fromFile(source)) + .version(HTTP_2) + .POST() + .responseAsync() + .thenCompose(r -> r.bodyAsync(HttpResponse.asFile(tempFile()))) + .thenApply(path -> compareFiles(path, source)); + Thread.sleep(100); + } + CompletableFuture.allOf(responses).join(); + System.err.println("DONE"); + } +} diff --git a/jdk/test/java/net/httpclient/http2/ServerPush.java b/jdk/test/java/net/httpclient/http2/ServerPush.java new file mode 100644 index 00000000000..57a72ec9f06 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/ServerPush.java @@ -0,0 +1,107 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8087112 + * @library /lib/testlibrary + * @build jdk.testlibrary.SimpleSSLContext + * @modules java.httpclient + * @compile/module=java.httpclient java/net/http/BodyOutputStream.java + * @compile/module=java.httpclient java/net/http/BodyInputStream.java + * @compile/module=java.httpclient java/net/http/PushHandler.java + * @compile/module=java.httpclient java/net/http/Http2Handler.java + * @compile/module=java.httpclient java/net/http/Http2TestExchange.java + * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java + * @compile/module=java.httpclient java/net/http/Http2TestServer.java + * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java + * @compile/module=java.httpclient java/net/http/TestUtil.java + * @run testng/othervm -Djava.net.http.HttpClient.log=requests,responses ServerPush + */ + +import java.io.*; +import java.net.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.net.http.*; +import java.util.*; +import java.util.concurrent.*; +import org.testng.annotations.Test; + +public class ServerPush { + + static ExecutorService e = Executors.newCachedThreadPool(); + + static final int LOOPS = 13; + static final int FILE_SIZE = 32 * 1024; + + static Path tempFile; + + @Test(timeOut=30000) + public static void test() throws Exception { + Http2TestServer server = null; + Path dir = null; + try { + server = new Http2TestServer(false, 0, + new PushHandler(FILE_SIZE, LOOPS)); + tempFile = TestUtil.getAFile(FILE_SIZE); + + System.err.println("Server listening on port " + server.getAddress().getPort()); + server.start(); + int port = server.getAddress().getPort(); + dir = Files.createTempDirectory("serverPush"); + + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo"); + HttpRequest request = HttpRequest.create(uri) + .version(HttpClient.Version.HTTP_2) + .GET(); + + CompletableFuture> cf = + request.multiResponseAsync(HttpResponse.multiFile(dir)); + Map results = cf.get(); + + //HttpResponse resp = request.response(); + System.err.println(results.size()); + Set uris = results.keySet(); + for (URI u : uris) { + Path result = results.get(u); + System.err.printf("%s -> %s\n", u.toString(), result.toString()); + TestUtil.compareFiles(result, tempFile); + } + System.out.println("TEST OK"); + } finally { + e.shutdownNow(); + server.stop(); + Files.walkFileTree(dir, new SimpleFileVisitor() { + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + dir.toFile().delete(); + return FileVisitResult.CONTINUE; + } + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { + path.toFile().delete(); + return FileVisitResult.CONTINUE; + } + }); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/TEST.properties b/jdk/test/java/net/httpclient/http2/TEST.properties new file mode 100644 index 00000000000..8abaaefc34c --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/TEST.properties @@ -0,0 +1 @@ +bootclasspath.dirs = /java/net/httpclient diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java new file mode 100644 index 00000000000..405003ed143 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java @@ -0,0 +1,107 @@ +package java.net.http; + +import java.io.*; +import java.nio.ByteBuffer; + +/** + * InputStream reads frames off stream q and supplies read demand from any + * DataFrames it finds. Window updates are sent back on the connections send + * q. + */ +class BodyInputStream extends InputStream { + + final Queue q; + final int streamid; + boolean closed; + boolean eof; + final Http2TestServerConnection conn; + + @SuppressWarnings({"rawtypes","unchecked"}) + BodyInputStream(Queue q, int streamid, Http2TestServerConnection conn) { + this.q = q; + this.streamid = streamid; + this.conn = conn; + } + + DataFrame df; + ByteBuffer[] buffers; + ByteBuffer buffer; + int nextIndex = -1; + + private DataFrame getData() throws IOException { + if (eof) { + return null; + } + Http2Frame frame; + do { + frame = q.take(); + if (frame.type() == ResetFrame.TYPE) { + conn.handleStreamReset((ResetFrame) frame); // throws IOException + } + // ignoring others for now Wupdates handled elsewhere + if (frame.type() != DataFrame.TYPE) { + System.out.println("Ignoring " + frame.toString() + " CHECK THIS"); + } + } while (frame.type() != DataFrame.TYPE); + df = (DataFrame) frame; + int len = df.getDataLength(); + eof = frame.getFlag(DataFrame.END_STREAM); + // acknowledge + conn.sendWindowUpdates(len, streamid); + return (DataFrame) frame; + } + + // null return means EOF + private ByteBuffer getBuffer() throws IOException { + if (buffer == null || !buffer.hasRemaining()) { + if (nextIndex == -1 || nextIndex == buffers.length) { + DataFrame df = getData(); + if (df == null) { + return null; + } + int len = df.getDataLength(); + if ((len == 0) && eof) { + return null; + } + buffers = df.getData(); + nextIndex = 0; + } + buffer = buffers[nextIndex++]; + } + return buffer; + } + + @Override + public int read(byte[] buf, int offset, int length) throws IOException { + if (closed) { + throw new IOException("closed"); + } + ByteBuffer b = getBuffer(); + if (b == null) { + return -1; + } + int remaining = b.remaining(); + if (remaining < length) { + length = remaining; + } + b.get(buf, offset, length); + return length; + } + + byte[] one = new byte[1]; + + @Override + public int read() throws IOException { + int c = read(one, 0, 1); + if (c == -1) { + return -1; + } + return one[0]; + } + + @Override + public void close() { + // TODO reset this stream + closed = true; + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java new file mode 100644 index 00000000000..ed77cfc17ce --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java @@ -0,0 +1,106 @@ +package java.net.http; + +import java.io.*; +import java.nio.ByteBuffer; + +/** + * OutputStream. Incoming window updates handled by the main connection + * reader thread. + */ +@SuppressWarnings({"rawtypes","unchecked"}) +class BodyOutputStream extends OutputStream { + final static byte[] EMPTY_BARRAY = new byte[0]; + + final int streamid; + int window; + boolean closed; + boolean goodToGo = false; // not allowed to send until headers sent + final Http2TestServerConnection conn; + final Queue outputQ; + + BodyOutputStream(int streamid, int initialWindow, Http2TestServerConnection conn) { + this.window = initialWindow; + this.streamid = streamid; + this.conn = conn; + this.outputQ = conn.outputQ; + conn.registerStreamWindowUpdater(streamid, this::updateWindow); + } + + // called from connection reader thread as all incoming window + // updates are handled there. + synchronized void updateWindow(int update) { + window += update; + notifyAll(); + } + + void waitForWindow(int demand) throws InterruptedException { + // first wait for the connection window + conn.obtainConnectionWindow(demand); + // now wait for the stream window + synchronized (this) { + while (demand > 0) { + int n = Math.min(demand, window); + demand -= n; + window -= n; + if (demand > 0) { + wait(); + } + } + } + } + + void goodToGo() { + goodToGo = true; + } + + @Override + public void write(byte[] buf, int offset, int len) throws IOException { + if (closed) { + throw new IOException("closed"); + } + + if (!goodToGo) { + throw new IllegalStateException("sendResponseHeaders must be called first"); + } + try { + waitForWindow(len); + send(buf, offset, len, 0); + } catch (InterruptedException ex) { + throw new IOException(ex); + } + } + + private void send(byte[] buf, int offset, int len, int flags) throws IOException { + ByteBuffer buffer = ByteBuffer.allocate(len); + buffer.put(buf, offset, len); + buffer.flip(); + DataFrame df = new DataFrame(); + assert streamid != 0; + df.streamid(streamid); + df.setFlags(flags); + df.setData(buffer); + outputQ.put(df); + } + + byte[] one = new byte[1]; + + @Override + public void write(int b) throws IOException { + one[0] = (byte) b; + write(one, 0, 1); + } + + @Override + public void close() { + if (closed) { + return; + } + closed = true; + try { + send(EMPTY_BARRAY, 0, 0, DataFrame.END_STREAM); + } catch (IOException ex) { + System.err.println("TestServer: OutputStream.close exception: " + ex); + ex.printStackTrace(); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java new file mode 100644 index 00000000000..a568ff84029 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2005, 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 java.net.http; + +import java.util.*; +import java.util.concurrent.*; +import java.io.*; +import java.net.*; + +public class EchoHandler implements Http2Handler { + public EchoHandler() {} + + @Override + public void handle(Http2TestExchange t) + throws IOException { + try { + System.err.println("EchoHandler received request to " + t.getRequestURI()); + InputStream is = t.getRequestBody(); + HttpHeadersImpl map = t.getRequestHeaders(); + HttpHeadersImpl map1 = t.getResponseHeaders(); + map1.addHeader("X-Hello", "world"); + map1.addHeader("X-Bye", "universe"); + String fixedrequest = map.firstValue("XFixed").orElse(null); + File outfile = File.createTempFile("foo", "bar"); + FileOutputStream fos = new FileOutputStream(outfile); + int count = (int) is.transferTo(fos); + System.err.printf("EchoHandler read %d bytes\n", count); + is.close(); + fos.close(); + InputStream is1 = new FileInputStream(outfile); + OutputStream os = null; + // return the number of bytes received (no echo) + String summary = map.firstValue("XSummary").orElse(null); + if (fixedrequest != null && summary == null) { + t.sendResponseHeaders(200, count); + os = t.getResponseBody(); + is1.transferTo(os); + } else { + t.sendResponseHeaders(200, 0); + os = t.getResponseBody(); + int count1 = (int)is1.transferTo(os); + System.err.printf("EchoHandler wrote %d bytes\n", count1); + + if (summary != null) { + String s = Integer.toString(count); + os.write(s.getBytes()); + } + } + outfile.delete(); + os.close(); + is1.close(); + } catch (Throwable e) { + e.printStackTrace(); + throw new IOException(e); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java new file mode 100644 index 00000000000..8ac77c4a770 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java @@ -0,0 +1,18 @@ +package java.net.http; + +import java.io.IOException; + +/** + * A handler which is invoked to process HTTP exchanges. Each + * HTTP exchange is handled by one of these handlers. + */ +public interface Http2Handler { + /** + * Handle the given request and generate an appropriate response. + * @param exchange the exchange containing the request from the + * client and used to send the response + * @throws NullPointerException if exchange is null + */ + public abstract void handle (Http2TestExchange exchange) throws IOException; +} + diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java new file mode 100644 index 00000000000..4b9ce043001 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java @@ -0,0 +1,126 @@ +package java.net.http; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.InetSocketAddress; + +public class Http2TestExchange { + + final HttpHeadersImpl reqheaders; + final HttpHeadersImpl rspheaders; + final URI uri; + final String method; + final InputStream is; + final BodyOutputStream os; + final int streamid; + final boolean pushAllowed; + final Http2TestServerConnection conn; + final Http2TestServer server; + + int responseCode = -1; + long responseLength; + + Http2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders, + HttpHeadersImpl rspheaders, URI uri, InputStream is, + BodyOutputStream os, Http2TestServerConnection conn, boolean pushAllowed) { + this.reqheaders = reqheaders; + this.rspheaders = rspheaders; + this.uri = uri; + this.method = method; + this.is = is; + this.streamid = streamid; + this.os = os; + this.pushAllowed = pushAllowed; + this.conn = conn; + this.server = conn.server; + } + + public HttpHeadersImpl getRequestHeaders() { + return reqheaders; + } + + public HttpHeadersImpl getResponseHeaders() { + return rspheaders; + } + + public URI getRequestURI() { + return uri; + } + + public String getRequestMethod() { + return method; + } + + public void close() { + try { + is.close(); + os.close(); + } catch (IOException e) { + System.err.println("TestServer: HttpExchange.close exception: " + e); + e.printStackTrace(); + } + } + + public InputStream getRequestBody() { + return is; + } + + public OutputStream getResponseBody() { + return os; + } + + public void sendResponseHeaders(int rCode, long responseLength) throws IOException { + this.responseLength = responseLength; + if (responseLength > 0 || responseLength < 0) { + long clen = responseLength > 0 ? responseLength : 0; + rspheaders.setHeader("Content-length", Long.toString(clen)); + } + + rspheaders.setHeader(":status", Integer.toString(rCode)); + + Http2TestServerConnection.ResponseHeaders response + = new Http2TestServerConnection.ResponseHeaders(rspheaders); + response.streamid(streamid); + response.setFlag(HeaderFrame.END_HEADERS); + conn.outputQ.put(response); + os.goodToGo(); + System.err.println("Sent response headers " + rCode); + } + + public InetSocketAddress getRemoteAddress() { + return (InetSocketAddress) conn.socket.getRemoteSocketAddress(); + } + + public int getResponseCode() { + return responseCode; + } + + public InetSocketAddress getLocalAddress() { + return server.getAddress(); + } + + public String getProtocol() { + return "HTTP/2"; + } + + public boolean serverPushAllowed() { + return pushAllowed; + } + + public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) { + OutgoingPushPromise pp = new OutgoingPushPromise( + streamid, uri, headers, content); + headers.setHeader(":method", "GET"); + headers.setHeader(":scheme", uri.getScheme()); + headers.setHeader(":authority", uri.getAuthority()); + headers.setHeader(":path", uri.getPath()); + try { + conn.outputQ.put(pp); + // writeLoop will spin up thread to read the InputStream + } catch (IOException ex) { + System.err.println("TestServer: pushPromise exception: " + ex); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java new file mode 100644 index 00000000000..667a1d6ec55 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java @@ -0,0 +1,159 @@ +/* + * 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 java.net.http; + +import java.io.IOException; +import java.net.*; +import java.util.HashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + +/** + * Waits for incoming TCP connections from a client and establishes + * a HTTP2 connection. Two threads are created per connection. One for reading + * and one for writing. Incoming requests are dispatched to the supplied + * Http2Handler on additional threads. All threads + * obtained from the supplied ExecutorService. + */ +public class Http2TestServer { + final ServerSocket server; + boolean secure; + SettingsFrame serverSettings, clientSettings; + final ExecutorService exec; + volatile boolean stopping = false; + final Http2Handler handler; + final SSLContext sslContext; + final HashMap connections; + + private static ThreadFactory defaultThreadFac = + (Runnable r) -> { + Thread t = new Thread(r); + t.setName("Test-server-pool"); + return t; + }; + + + private static ExecutorService getDefaultExecutor() { + return Executors.newCachedThreadPool(defaultThreadFac); + } + + public Http2TestServer(boolean secure, int port, Http2Handler handler) throws Exception { + this(secure, port, handler, getDefaultExecutor(), null); + } + + public InetSocketAddress getAddress() { + return (InetSocketAddress)server.getLocalSocketAddress(); + } + + /** + * Create a Http2Server listening on the given port. Currently needs + * to know in advance whether incoming connections are plain TCP "h2c" + * or TLS "h2"/ + * + * @param secure https or http + * @param port listen port + * @param handler the handler which receives incoming requests + * @param exec executor service (cached thread pool is used if null) + * @param context the SSLContext used when secure is true + * @throws Exception + */ + public Http2TestServer(boolean secure, int port, Http2Handler handler, + ExecutorService exec, SSLContext context) throws Exception { + if (secure) { + server = initSecure(port); + } else { + server = initPlaintext(port); + } + this.secure = secure; + this.exec = exec == null ? getDefaultExecutor() : exec; + this.handler = handler; + this.sslContext = context; + this.connections = new HashMap<>(); + } + + final ServerSocket initPlaintext(int port) throws Exception { + return new ServerSocket(port); + } + + public void stop() { + // TODO: clean shutdown GoAway + stopping = true; + for (Http2TestServerConnection connection : connections.values()) { + connection.close(); + } + try { + server.close(); + } catch (IOException e) {} + exec.shutdownNow(); + } + + + final ServerSocket initSecure(int port) throws Exception { + ServerSocketFactory fac; + if (sslContext != null) { + fac = sslContext.getServerSocketFactory(); + } else { + fac = SSLServerSocketFactory.getDefault(); + } + SSLServerSocket se = (SSLServerSocket) fac.createServerSocket(port); + SSLParameters sslp = se.getSSLParameters(); + sslp.setApplicationProtocols(new String[]{"h2"}); + se.setSSLParameters(sslp); + se.setEnabledCipherSuites(se.getSupportedCipherSuites()); + se.setEnabledProtocols(se.getSupportedProtocols()); + // other initialisation here + return se; + } + + /** + * Start thread which waits for incoming connections. + * + * @throws Exception + */ + public void start() { + exec.submit(() -> { + try { + while (!stopping) { + Socket socket = server.accept(); + InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress(); + Http2TestServerConnection c = new Http2TestServerConnection(this, socket); + connections.put(addr, c); + c.run(); + } + } catch (Throwable e) { + if (!stopping) { + System.err.println("TestServer: start exception: " + e); + e.printStackTrace(); + } + } + }); + } + +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java new file mode 100644 index 00000000000..2f56f8a3dfb --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java @@ -0,0 +1,730 @@ +/* + * 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 java.net.http; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; +import sun.net.httpclient.hpack.Decoder; +import sun.net.httpclient.hpack.DecodingCallback; +import sun.net.httpclient.hpack.Encoder; + +/** + * Represents one HTTP2 connection, either plaintext upgraded from HTTP/1.1 + * or HTTPS opened using "h2" ALPN. + */ +public class Http2TestServerConnection { + final Http2TestServer server; + @SuppressWarnings({"rawtypes","unchecked"}) + final Map streams; // input q per stream + final Queue outputQ; + int nextstream; + final Socket socket; + final InputStream is; + final OutputStream os; + Encoder hpackOut; + Decoder hpackIn; + SettingsFrame clientSettings, serverSettings; + final ExecutorService exec; + final boolean secure; + final Http2Handler handler; + volatile boolean stopping; + int nextPushStreamId = 2; + + final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); + final static byte[] EMPTY_BARRAY = new byte[0]; + + final static byte[] clientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(); + + Http2TestServerConnection(Http2TestServer server, Socket socket) throws IOException { + System.err.println("New connection from " + socket); + this.server = server; + this.streams = Collections.synchronizedMap(new HashMap<>()); + this.outputQ = new Queue<>(); + this.socket = socket; + this.clientSettings = server.clientSettings; + this.serverSettings = server.serverSettings; + this.exec = server.exec; + this.secure = server.secure; + this.handler = server.handler; + is = new BufferedInputStream(socket.getInputStream()); + os = new BufferedOutputStream(socket.getOutputStream()); + } + + void close() { + streams.forEach((i, q) -> { + q.close(); + }); + stopping = true; + try { + socket.close(); + // TODO: put a reset on each stream + } catch (IOException e) { + } + } + + private void readPreface() throws IOException { + int len = clientPreface.length; + byte[] bytes = new byte[len]; + is.readNBytes(bytes, 0, len); + if (Arrays.compare(clientPreface, bytes) != 0) { + throw new IOException("Invalid preface: " + new String(bytes, 0, len)); + } + } + + String doUpgrade() throws IOException { + String upgrade = readHttp1Request(); + String h2c = getHeader(upgrade, "Upgrade"); + if (h2c == null || !h2c.equals("h2c")) { + throw new IOException("Bad upgrade 1 " + h2c); + } + + sendHttp1Response(101, "Switching Protocols", "Connection", "Upgrade", + "Upgrade", "h2c"); + + sendSettingsFrame(); + readPreface(); + + String clientSettingsString = getHeader(upgrade, "HTTP2-Settings"); + clientSettings = getSettingsFromString(clientSettingsString); + + return upgrade; + } + + /** + * Client settings payload provided in base64 HTTP1 header. Decode it + * and add a header so we can interpret it. + * + * @param s + * @return + * @throws IOException + */ + private SettingsFrame getSettingsFromString(String s) throws IOException { + Base64.Decoder decoder = Base64.getUrlDecoder(); + byte[] payload = decoder.decode(s); + ByteBuffer bb1 = ByteBuffer.wrap(payload); + // simulate header of Settings Frame + ByteBuffer bb0 = ByteBuffer.wrap( + new byte[] {0, 0, (byte)payload.length, 4, 0, 0, 0, 0, 0}); + ByteBufferConsumer bbc = new ByteBufferConsumer( + new LinkedList(List.of(bb0, bb1)), + this::getBuffer); + Http2Frame frame = Http2Frame.readIncoming(bbc); + if (!(frame instanceof SettingsFrame)) + throw new IOException("Expected SettingsFrame"); + return (SettingsFrame)frame; + } + + void run() throws Exception { + String upgrade = null; + if (!secure) { + upgrade = doUpgrade(); + } else { + readPreface(); + sendSettingsFrame(true); + clientSettings = (SettingsFrame) readFrame(); + nextstream = 1; + } + + hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE)); + hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE)); + + exec.submit(() -> { + readLoop(); + }); + exec.submit(() -> { + writeLoop(); + }); + if (!secure) { + createPrimordialStream(upgrade); + nextstream = 3; + } + } + + static class BufferPool implements BufferHandler { + + public void setMinBufferSize(int size) { + } + + public ByteBuffer getBuffer(int size) { + if (size == -1) + size = 32 * 1024; + return ByteBuffer.allocate(size); + } + + public void returnBuffer(ByteBuffer buffer) { + } + } + + static BufferPool bufferpool = new BufferPool(); + + private void writeFrame(Http2Frame frame) throws IOException { + ByteBufferGenerator bg = new ByteBufferGenerator(bufferpool); + frame.computeLength(); + System.err.println("Writing frame " + frame.toString()); + frame.writeOutgoing(bg); + ByteBuffer[] bufs = bg.getBufferArray(); + int c = 0; + for (ByteBuffer buf : bufs) { + byte[] ba = buf.array(); + int start = buf.arrayOffset() + buf.position(); + c += buf.remaining(); + os.write(ba, start, buf.remaining()); + } + os.flush(); + System.err.printf("wrote %d bytes\n", c); + } + + void handleStreamReset(ResetFrame resetFrame) throws IOException { + // TODO: cleanup + throw new IOException("Stream reset"); + } + + private void handleCommonFrame(Http2Frame f) throws IOException { + if (f instanceof SettingsFrame) { + serverSettings = (SettingsFrame) f; + if (serverSettings.getFlag(SettingsFrame.ACK)) // ignore + { + return; + } + // otherwise acknowledge it + SettingsFrame frame = new SettingsFrame(); + frame.setFlag(SettingsFrame.ACK); + frame.streamid(0); + outputQ.put(frame); + return; + } + System.err.println("Received ---> " + f.toString()); + throw new UnsupportedOperationException("Not supported yet."); + } + + void sendWindowUpdates(int len, int streamid) throws IOException { + if (len == 0) + return; + WindowUpdateFrame wup = new WindowUpdateFrame(); + wup.streamid(streamid); + wup.setUpdate(len); + outputQ.put(wup); + wup = new WindowUpdateFrame(); + wup.streamid(0); + wup.setUpdate(len); + outputQ.put(wup); + } + + HttpHeadersImpl decodeHeaders(List frames) { + HttpHeadersImpl headers = new HttpHeadersImpl(); + + DecodingCallback cb = (name, value) -> { + headers.addHeader(name.toString(), value.toString()); + }; + + for (HeaderFrame frame : frames) { + ByteBuffer[] buffers = frame.getHeaderBlock(); + for (ByteBuffer buffer : buffers) { + hpackIn.decode(buffer, false, cb); + } + } + hpackIn.decode(EMPTY_BUFFER, true, cb); + return headers; + } + + String getRequestLine(String request) { + int eol = request.indexOf(CRLF); + return request.substring(0, eol); + } + + // First stream (1) comes from a plaintext HTTP/1.1 request + @SuppressWarnings({"rawtypes","unchecked"}) + void createPrimordialStream(String request) throws IOException { + HttpHeadersImpl headers = new HttpHeadersImpl(); + String requestLine = getRequestLine(request); + String[] tokens = requestLine.split(" "); + if (!tokens[2].equals("HTTP/1.1")) { + throw new IOException("bad request line"); + } + URI uri = null; + try { + uri = new URI(tokens[1]); + } catch (URISyntaxException e) { + throw new IOException(e); + } + String host = getHeader(request, "Host"); + if (host == null) { + throw new IOException("missing Host"); + } + + headers.setHeader(":method", tokens[0]); + headers.setHeader(":scheme", "http"); // always in this case + headers.setHeader(":authority", host); + headers.setHeader(":path", uri.getPath()); + Queue q = new Queue(); + String body = getRequestBody(request); + headers.setHeader("Content-length", Integer.toString(body.length())); + + addRequestBodyToQueue(body, q); + streams.put(1, q); + exec.submit(() -> { + handleRequest(headers, q, 1); + }); + } + + // all other streams created here + @SuppressWarnings({"rawtypes","unchecked"}) + void createStream(HeaderFrame frame) throws IOException { + List frames = new LinkedList<>(); + frames.add(frame); + int streamid = frame.streamid(); + if (streamid != nextstream) { + throw new IOException("unexpected stream id"); + } + nextstream += 2; + + while (!frame.getFlag(HeaderFrame.END_HEADERS)) { + Http2Frame f = readFrame(); + if (!(f instanceof HeaderFrame)) { + handleCommonFrame(f); // should only be error frames + } else { + frame = (HeaderFrame) f; + frames.add(frame); + } + } + HttpHeadersImpl headers = decodeHeaders(frames); + Queue q = new Queue(); + streams.put(streamid, q); + exec.submit(() -> { + handleRequest(headers, q, streamid); + }); + } + + // runs in own thread. Handles request from start to finish. Incoming frames + // for this stream/request delivered on Q + + @SuppressWarnings({"rawtypes","unchecked"}) + void handleRequest(HttpHeadersImpl headers, Queue queue, int streamid) { + String method = headers.firstValue(":method").orElse(""); + System.out.println("method = " + method); + String path = headers.firstValue(":path").orElse(""); + System.out.println("path = " + path); + String scheme = headers.firstValue(":scheme").orElse(""); + System.out.println("scheme = " + scheme); + String authority = headers.firstValue(":authority").orElse(""); + System.out.println("authority = " + authority); + HttpHeadersImpl rspheaders = new HttpHeadersImpl(); + int winsize = clientSettings.getParameter( + SettingsFrame.INITIAL_WINDOW_SIZE); + System.err.println ("Stream window size = " + winsize); + try ( + BodyInputStream bis = new BodyInputStream(queue, streamid, this); + BodyOutputStream bos = new BodyOutputStream(streamid, winsize, this); + ) + { + String us = scheme + "://" + authority + path; + URI uri = new URI(us); + boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1; + Http2TestExchange exchange = new Http2TestExchange(streamid, method, + headers, rspheaders, uri, bis, bos, this, pushAllowed); + + // give to user + handler.handle(exchange); + + // everything happens in the exchange from here. Hopefully will + // return though. + } catch (Throwable e) { + System.err.println("TestServer: handleRequest exception: " + e); + e.printStackTrace(); + } + } + + // Runs in own thread + + @SuppressWarnings({"rawtypes","unchecked"}) + void readLoop() { + try { + while (!stopping) { + Http2Frame frame = readFrame(); + int stream = frame.streamid(); + if (stream == 0) { + if (frame.type() == WindowUpdateFrame.TYPE) { + WindowUpdateFrame wup = (WindowUpdateFrame) frame; + updateConnectionWindow(wup.getUpdate()); + } else { + // other common frame types + handleCommonFrame(frame); + } + } else { + Queue q = streams.get(stream); + if (frame.type() == HeadersFrame.TYPE) { + if (q != null) { + System.err.println("HEADERS frame for existing stream! Error."); + // TODO: close connection + continue; + } else { + createStream((HeadersFrame) frame); + } + } else { + if (q == null) { + System.err.printf("Non Headers frame received with"+ + " non existing stream (%d) ", frame.streamid()); + System.err.println(frame); + continue; + } + if (frame.type() == WindowUpdateFrame.TYPE) { + WindowUpdateFrame wup = (WindowUpdateFrame) frame; + synchronized (updaters) { + Consumer r = updaters.get(stream); + r.accept(wup.getUpdate()); + } + } else { + q.put(frame); + } + } + } + } + } catch (Throwable e) { + close(); + if (!stopping) { + System.err.println("Http server reader thread shutdown"); + e.printStackTrace(); + } + } + } + + // set streamid outside plus other specific fields + void encodeHeaders(HttpHeadersImpl headers, HeaderFrame out) { + List buffers = new LinkedList<>(); + + ByteBuffer buf = getBuffer(); + boolean encoded; + for (Map.Entry> entry : headers.map().entrySet()) { + List values = entry.getValue(); + String key = entry.getKey().toLowerCase(); + for (String value : values) { + do { + hpackOut.header(key, value); + encoded = hpackOut.encode(buf); + if (!encoded) { + buf.flip(); + buffers.add(buf); + buf = getBuffer(); + } + } while (!encoded); + } + } + buf.flip(); + buffers.add(buf); + out.setFlags(HeaderFrame.END_HEADERS); + out.setHeaderBlock(buffers.toArray(bbarray)); + } + + static void closeIgnore(Closeable c) { + try { + c.close(); + } catch (IOException e) {} + } + + // Runs in own thread + void writeLoop() { + try { + while (!stopping) { + Http2Frame frame = outputQ.take(); + if (frame instanceof ResponseHeaders) { + ResponseHeaders rh = (ResponseHeaders)frame; + HeadersFrame hf = new HeadersFrame(); + encodeHeaders(rh.headers, hf); + hf.streamid(rh.streamid()); + writeFrame(hf); + } else if (frame instanceof OutgoingPushPromise) { + handlePush((OutgoingPushPromise)frame); + } else + writeFrame(frame); + } + System.err.println("Connection writer stopping"); + } catch (Throwable e) { + e.printStackTrace(); + /*close(); + if (!stopping) { + e.printStackTrace(); + System.err.println("TestServer: writeLoop exception: " + e); + }*/ + } + } + + private void handlePush(OutgoingPushPromise op) throws IOException { + PushPromiseFrame pp = new PushPromiseFrame(); + encodeHeaders(op.headers, pp); + int promisedStreamid = nextPushStreamId; + nextPushStreamId += 2; + pp.streamid(op.parentStream); + pp.setPromisedStream(promisedStreamid); + writeFrame(pp); + final InputStream ii = op.is; + final BodyOutputStream oo = new BodyOutputStream( + promisedStreamid, + clientSettings.getParameter( + SettingsFrame.INITIAL_WINDOW_SIZE), this); + oo.goodToGo(); + exec.submit(() -> { + try { + ResponseHeaders oh = getPushResponse(promisedStreamid); + outputQ.put(oh); + ii.transferTo(oo); + } catch (Throwable ex) { + System.err.printf("TestServer: pushing response error: %s\n", + ex.toString()); + } finally { + closeIgnore(ii); + closeIgnore(oo); + } + }); + + } + + // returns a minimal response with status 200 + // that is the response to the push promise just sent + private ResponseHeaders getPushResponse(int streamid) { + HttpHeadersImpl h = new HttpHeadersImpl(); + h.addHeader(":status", "200"); + ResponseHeaders oh = new ResponseHeaders(h); + oh.streamid(streamid); + return oh; + } + + private ByteBuffer getBuffer() { + return ByteBuffer.allocate(8 * 1024); + } + + private Http2Frame readFrame() throws IOException { + byte[] buf = new byte[9]; + if (is.readNBytes(buf, 0, 9) != 9) + throw new IOException("readFrame: connection closed"); + int len = 0; + for (int i = 0; i < 3; i++) { + int n = buf[i] & 0xff; + //System.err.println("n = " + n); + len = (len << 8) + n; + } + byte[] rest = new byte[len]; + int n = is.readNBytes(rest, 0, len); + if (n != len) + throw new IOException("Error reading frame"); + ByteBufferConsumer bc = new ByteBufferConsumer( + new LinkedList(List.of(ByteBuffer.wrap(buf), ByteBuffer.wrap(rest))), + this::getBuffer); + return Http2Frame.readIncoming(bc); + } + + void sendSettingsFrame() throws IOException { + sendSettingsFrame(false); + } + + void sendSettingsFrame(boolean now) throws IOException { + if (serverSettings == null) { + serverSettings = SettingsFrame.getDefaultSettings(); + } + if (now) { + writeFrame(serverSettings); + } else { + outputQ.put(serverSettings); + } + } + + String readUntil(String end) throws IOException { + int number = end.length(); + int found = 0; + StringBuilder sb = new StringBuilder(); + while (found < number) { + char expected = end.charAt(found); + int c = is.read(); + if (c == -1) { + throw new IOException("Connection closed"); + } + char c0 = (char) c; + sb.append(c0); + if (c0 != expected) { + found = 0; + continue; + } + found++; + } + return sb.toString(); + } + + private int getContentLength(String headers) { + return getIntHeader(headers, "Content-length"); + } + + private int getIntHeader(String headers, String name) { + String val = getHeader(headers, name); + if (val == null) { + return -1; + } + return Integer.parseInt(val); + } + + private String getHeader(String headers, String name) { + String headers1 = headers.toLowerCase(); // not efficient + name = CRLF + name.toLowerCase(); + int start = headers1.indexOf(name); + if (start == -1) { + return null; + } + start += 2; + int end = headers1.indexOf(CRLF, start); + String line = headers.substring(start, end); + start = line.indexOf(':'); + if (start == -1) { + return null; + } + return line.substring(start + 1).trim(); + } + + final static String CRLF = "\r\n"; + + String readHttp1Request() throws IOException { + String headers = readUntil(CRLF + CRLF); + int clen = getContentLength(headers); + // read the content. There shouldn't be content but .. + byte[] buf = new byte[clen]; + is.readNBytes(buf, 0, clen); + String body = new String(buf, "US-ASCII"); + return headers + body; + } + + void sendHttp1Response(int code, String msg, String... headers) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append("HTTP/1.1 ") + .append(code) + .append(' ') + .append(msg) + .append(CRLF); + int numheaders = headers.length; + for (int i = 0; i < numheaders; i += 2) { + sb.append(headers[i]) + .append(": ") + .append(headers[i + 1]) + .append(CRLF); + } + sb.append(CRLF); + String s = sb.toString(); + os.write(s.getBytes("US-ASCII")); + os.flush(); + } + + private void unexpectedFrame(Http2Frame frame) { + System.err.println("OOPS. Unexpected"); + assert false; + } + + final static ByteBuffer[] bbarray = new ByteBuffer[0]; + + // wrapper around a BlockingQueue that throws an exception when it's closed + // Each stream has one of these + + String getRequestBody(String request) { + int bodystart = request.indexOf(CRLF+CRLF); + String body; + if (bodystart == -1) + body = ""; + else + body = request.substring(bodystart+4); + return body; + } + + @SuppressWarnings({"rawtypes","unchecked"}) + void addRequestBodyToQueue(String body, Queue q) throws IOException { + ByteBuffer buf = ByteBuffer.wrap(body.getBytes(StandardCharsets.US_ASCII)); + DataFrame df = new DataFrame(); + df.streamid(1); // only used for primordial stream + df.setData(buf); + df.computeLength(); + df.setFlag(DataFrame.END_STREAM); + q.put(df); + } + + // window updates done in main reader thread because they may + // be used to unblock BodyOutputStreams waiting for WUPs + + HashMap> updaters = new HashMap<>(); + + void registerStreamWindowUpdater(int streamid, Consumer r) { + synchronized(updaters) { + updaters.put(streamid, r); + } + } + + int sendWindow = 64 * 1024 - 1; // connection level send window + + /** + * BodyOutputStreams call this to get the connection window first. + * + * @param amount + */ + synchronized void obtainConnectionWindow(int amount) throws InterruptedException { + while (amount > 0) { + int n = Math.min(amount, sendWindow); + amount -= n; + sendWindow -= n; + if (amount > 0) + wait(); + } + } + + synchronized void updateConnectionWindow(int amount) { + sendWindow += amount; + notifyAll(); + } + + // simplified output headers class. really just a type safe container + // for the hashmap. + + static class ResponseHeaders extends Http2Frame { + HttpHeadersImpl headers; + + ResponseHeaders(HttpHeadersImpl headers) { + this.headers = headers; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + throw new UnsupportedOperationException("Not supported ever!"); + } + + @Override + void computeLength() { + throw new UnsupportedOperationException("Not supported ever!"); + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java new file mode 100644 index 00000000000..30654096437 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java @@ -0,0 +1,31 @@ +package java.net.http; + +import java.io.*; +import java.net.*; + +// will be converted to a PushPromiseFrame in the writeLoop +// a thread is then created to produce the DataFrames from the InputStream +class OutgoingPushPromise extends Http2Frame { + final HttpHeadersImpl headers; + final URI uri; + final InputStream is; + final int parentStream; // not the pushed streamid + + OutgoingPushPromise(int parentStream, URI uri, HttpHeadersImpl headers, InputStream is) { + this.uri = uri; + this.headers = headers; + this.is = is; + this.parentStream = parentStream; + } + + @Override + void readIncomingImpl(ByteBufferConsumer bc) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + void computeLength() { + throw new UnsupportedOperationException("Not supported yet."); + } + +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java new file mode 100644 index 00000000000..c2797815543 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java @@ -0,0 +1,71 @@ +/* + * 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 java.net.http; + +import java.io.*; +import java.net.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.net.http.*; +import java.util.*; +import java.util.concurrent.*; + +public class PushHandler implements Http2Handler { + + final Path tempFile; + final int loops; + + public PushHandler(int file_size, int loops) throws Exception { + tempFile = TestUtil.getAFile(file_size); + this.loops = loops; + } + + int invocation = 0; + + public void handle(Http2TestExchange ee) { + try { + System.err.println ("Server: handle " + ee); + invocation++; + + if (ee.serverPushAllowed()) { + for (int i=0; i Date: Fri, 29 Apr 2016 16:57:57 -0700 Subject: [PATCH 191/225] 8153293: Preserve SORTED and DISTINCT characteristics for boxed() and asLongStream() operations Reviewed-by: psandoz --- .../java/util/stream/DoublePipeline.java | 30 +++++----- .../classes/java/util/stream/IntPipeline.java | 36 +++++------ .../java/util/stream/LongPipeline.java | 33 +++++----- .../util/stream/DoublePrimitiveOpsTests.java | 30 ++++++++++ .../util/stream/IntPrimitiveOpsTests.java | 60 +++++++++++++++++++ .../util/stream/LongPrimitiveOpsTests.java | 48 +++++++++++++++ 6 files changed, 189 insertions(+), 48 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java index 56a5f57cc57..199a3d37f6a 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.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 @@ -167,6 +167,19 @@ abstract class DoublePipeline return Nodes.doubleBuilder(exactSizeIfKnown); } + private Stream mapToObj(DoubleFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.DOUBLE_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedDouble(sink) { + @Override + public void accept(double t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // DoubleStream @@ -184,7 +197,7 @@ abstract class DoublePipeline @Override public final Stream boxed() { - return mapToObj(Double::valueOf); + return mapToObj(Double::valueOf, 0); } @Override @@ -207,18 +220,7 @@ abstract class DoublePipeline @Override public final Stream mapToObj(DoubleFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.DOUBLE_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { - @Override - public void accept(double t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff --git a/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java index 7cf0622ce89..fe7bac59b6e 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.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 @@ -170,6 +170,19 @@ abstract class IntPipeline return Nodes.intBuilder(exactSizeIfKnown); } + private Stream mapToObj(IntFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.INT_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedInt(sink) { + @Override + public void accept(int t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // IntStream @@ -187,8 +200,7 @@ abstract class IntPipeline @Override public final LongStream asLongStream() { - return new LongPipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new LongPipeline.StatelessOp(this, StreamShape.INT_VALUE, 0) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedInt(sink) { @@ -203,8 +215,7 @@ abstract class IntPipeline @Override public final DoubleStream asDoubleStream() { - return new DoublePipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new DoublePipeline.StatelessOp(this, StreamShape.INT_VALUE, 0) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedInt(sink) { @@ -219,7 +230,7 @@ abstract class IntPipeline @Override public final Stream boxed() { - return mapToObj(Integer::valueOf); + return mapToObj(Integer::valueOf, 0); } @Override @@ -242,18 +253,7 @@ abstract class IntPipeline @Override public final Stream mapToObj(IntFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.INT_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { - @Override - public void accept(int t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff --git a/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java index 19097b7e630..0d70b9707ca 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.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 @@ -167,6 +167,19 @@ abstract class LongPipeline return Nodes.longBuilder(exactSizeIfKnown); } + private Stream mapToObj(LongFunction mapper, int opFlags) { + return new ReferencePipeline.StatelessOp(this, StreamShape.LONG_VALUE, opFlags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return new Sink.ChainedLong(sink) { + @Override + public void accept(long t) { + downstream.accept(mapper.apply(t)); + } + }; + } + }; + } // LongStream @@ -184,8 +197,7 @@ abstract class LongPipeline @Override public final DoubleStream asDoubleStream() { - return new DoublePipeline.StatelessOp(this, StreamShape.LONG_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { + return new DoublePipeline.StatelessOp(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { return new Sink.ChainedLong(sink) { @@ -200,7 +212,7 @@ abstract class LongPipeline @Override public final Stream boxed() { - return mapToObj(Long::valueOf); + return mapToObj(Long::valueOf, 0); } @Override @@ -223,18 +235,7 @@ abstract class LongPipeline @Override public final Stream mapToObj(LongFunction mapper) { Objects.requireNonNull(mapper); - return new ReferencePipeline.StatelessOp(this, StreamShape.LONG_VALUE, - StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { - @Override - Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { - @Override - public void accept(long t) { - downstream.accept(mapper.apply(t)); - } - }; - } - }; + return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT); } @Override diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java index c476f18c624..5819d3f4c80 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java @@ -27,11 +27,18 @@ import org.testng.annotations.Test; import java.util.Arrays; import java.util.Random; +import java.util.Spliterator; import java.util.stream.DoubleStream; import java.util.stream.LongStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class DoublePrimitiveOpsTests { @@ -42,6 +49,13 @@ public class DoublePrimitiveOpsTests { assertEquals(sum, 1.0 + 2.0 + 3.0 + 4.0 + 5.0); } + public void testFlags() { + assertTrue(LongStream.range(1, 10).asDoubleStream().boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(DoubleStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + } + public void testToArray() { { double[] array = LongStream.range(1, 10).asDoubleStream().map(i -> i * 2).toArray(); @@ -72,6 +86,22 @@ public class DoublePrimitiveOpsTests { } } + public void testSortDistinct() { + { + double[] range = LongStream.range(0, 10).asDoubleStream().toArray(); + + assertEquals(LongStream.range(0, 10).asDoubleStream().sorted().distinct().toArray(), range); + assertEquals(LongStream.range(0, 10).asDoubleStream().parallel().sorted().distinct().toArray(), range); + + double[] data = {5, 3, 1, 1, 5, Double.NaN, 3, 9, Double.POSITIVE_INFINITY, + Double.NEGATIVE_INFINITY, 2, 9, 1, 0, 8, Double.NaN, -0.0}; + double[] expected = {Double.NEGATIVE_INFINITY, -0.0, 0, 1, 2, 3, 5, 8, 9, + Double.POSITIVE_INFINITY, Double.NaN}; + assertEquals(DoubleStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(DoubleStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + } + public void testSortSort() { Random r = new Random(); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java index 1efc5fde987..1397d236b30 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java @@ -28,13 +28,21 @@ import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.Spliterator; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.IntConsumer; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class IntPrimitiveOpsTests { @@ -85,6 +93,29 @@ public class IntPrimitiveOpsTests { assertEquals(sum, 15); } + public void testFlags() { + assertTrue(IntStream.range(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(IntStream.range(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).asLongStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(IntStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + } + public void testToArray() { { int[] array = IntStream.range(1, 10).map(i -> i * 2).toArray(); @@ -115,6 +146,35 @@ public class IntPrimitiveOpsTests { } } + public void testSortDistinct() { + { + int[] range = IntStream.range(0, 10).toArray(); + + assertEquals(IntStream.range(0, 10).sorted().distinct().toArray(), range); + assertEquals(IntStream.range(0, 10).parallel().sorted().distinct().toArray(), range); + + int[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8}; + int[] expected = {0, 1, 2, 3, 5, 8, 9}; + assertEquals(IntStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(IntStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + + { + int[] input = new Random().ints(100, -10, 10).map(x -> x+Integer.MAX_VALUE).toArray(); + TreeSet longs = new TreeSet<>(); + for(int i : input) longs.add((long)i); + long[] expectedLongs = longs.stream().mapToLong(Long::longValue).toArray(); + assertEquals(IntStream.of(input).sorted().asLongStream().sorted().distinct().toArray(), + expectedLongs); + + TreeSet doubles = new TreeSet<>(); + for(int i : input) doubles.add((double)i); + double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray(); + assertEquals(IntStream.of(input).sorted().distinct().asDoubleStream() + .sorted().distinct().toArray(), expectedDoubles); + } + } + public void testSortSort() { Random r = new Random(); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java index fc8fa2a6763..496a3542300 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java @@ -28,13 +28,21 @@ import org.testng.annotations.Test; import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.Spliterator; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; import java.util.function.LongConsumer; import java.util.stream.Collectors; import java.util.stream.LongStream; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +/** + * @test + * @bug 8153293 + */ @Test public class LongPrimitiveOpsTests { @@ -85,6 +93,22 @@ public class LongPrimitiveOpsTests { assertEquals(sum, 15); } + public void testFlags() { + assertTrue(LongStream.range(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT)); + assertFalse(LongStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(LongStream.of(1, 10).boxed().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + + assertTrue(LongStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + assertFalse(LongStream.range(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.DISTINCT)); + assertFalse(LongStream.of(1, 10).asDoubleStream().spliterator() + .hasCharacteristics(Spliterator.SORTED)); + } + public void testToArray() { { long[] array = LongStream.range(1, 10).map(i -> i * 2).toArray(); @@ -115,6 +139,30 @@ public class LongPrimitiveOpsTests { } } + public void testSortDistinct() { + { + long[] range = LongStream.range(0, 10).toArray(); + + assertEquals(LongStream.range(0, 10).sorted().distinct().toArray(), range); + assertEquals(LongStream.range(0, 10).parallel().sorted().distinct().toArray(), range); + + long[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8}; + long[] expected = {0, 1, 2, 3, 5, 8, 9}; + assertEquals(LongStream.of(data).sorted().distinct().toArray(), expected); + assertEquals(LongStream.of(data).parallel().sorted().distinct().toArray(), expected); + } + + { + long[] input = new Random().longs(100, -10, 10).map(x -> x+Long.MAX_VALUE).toArray(); + + TreeSet doubles = new TreeSet<>(); + for(long i : input) doubles.add((double)i); + double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray(); + assertEquals(LongStream.of(input).sorted().distinct().asDoubleStream() + .sorted().distinct().toArray(), expectedDoubles); + } + } + public void testSortSort() { Random r = new Random(); From 53420d651623a13b682c87ae50a87f9b4b959cc5 Mon Sep 17 00:00:00 2001 From: "Tagir F. Valeev" Date: Fri, 29 Apr 2016 16:58:00 -0700 Subject: [PATCH 192/225] 8154387: Parallel unordered Stream.limit() tries to collect 128 elements even if limit is less Reviewed-by: psandoz --- .../java/util/stream/StreamSpliterators.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java index 7e8d81150a8..cb92b2ebfad 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java +++ b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java @@ -28,6 +28,7 @@ import java.util.Comparator; import java.util.Objects; import java.util.Spliterator; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ForkJoinPool; import java.util.concurrent.atomic.AtomicLong; import java.util.function.BooleanSupplier; import java.util.function.Consumer; @@ -905,6 +906,7 @@ class StreamSpliterators { // The spliterator to slice protected final T_SPLITR s; protected final boolean unlimited; + protected final int chunkSize; private final long skipThreshold; private final AtomicLong permits; @@ -912,6 +914,8 @@ class StreamSpliterators { this.s = s; this.unlimited = limit < 0; this.skipThreshold = limit >= 0 ? limit : 0; + this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE, + ((skip + limit) / AbstractTask.LEAF_TARGET) + 1) : CHUNK_SIZE; this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip); } @@ -921,6 +925,7 @@ class StreamSpliterators { this.unlimited = parent.unlimited; this.permits = parent.permits; this.skipThreshold = parent.skipThreshold; + this.chunkSize = parent.chunkSize; } /** @@ -1029,13 +1034,13 @@ class StreamSpliterators { PermitStatus permitStatus; while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) { if (permitStatus == PermitStatus.MAYBE_MORE) { - // Optimistically traverse elements up to a threshold of CHUNK_SIZE + // Optimistically traverse elements up to a threshold of chunkSize if (sb == null) - sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE); + sb = new ArrayBuffer.OfRef<>(chunkSize); else sb.reset(); long permitsRequested = 0; - do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE); + do { } while (s.tryAdvance(sb) && ++permitsRequested < chunkSize); if (permitsRequested == 0) return; sb.forEach(action, acquirePermits(permitsRequested)); @@ -1102,15 +1107,15 @@ class StreamSpliterators { PermitStatus permitStatus; while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) { if (permitStatus == PermitStatus.MAYBE_MORE) { - // Optimistically traverse elements up to a threshold of CHUNK_SIZE + // Optimistically traverse elements up to a threshold of chunkSize if (sb == null) - sb = bufferCreate(CHUNK_SIZE); + sb = bufferCreate(chunkSize); else sb.reset(); @SuppressWarnings("unchecked") T_CONS sbc = (T_CONS) sb; long permitsRequested = 0; - do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE); + do { } while (s.tryAdvance(sbc) && ++permitsRequested < chunkSize); if (permitsRequested == 0) return; sb.forEach(action, acquirePermits(permitsRequested)); From 3dfed24a479db9972f0ba9324ca27a9586fe2a45 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Fri, 29 Apr 2016 22:39:44 -0400 Subject: [PATCH 193/225] 8154110: Update class* and safepoint* logging subsystems Refactored logging tags in class and safepoint subsystems. Reviewed-by: coleenp, rehn, hseigel --- jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh | 2 +- jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh | 2 +- .../instrument/appendToClassLoaderSearch/ClassUnloadTest.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh index 3872f813ffd..a00c14077d6 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh @@ -106,7 +106,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter cross # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh index 198cd70827a..1289b4c861e 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh @@ -102,7 +102,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter one-way # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh index f5bb3b83179..b428a59bb28 100644 --- a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh +++ b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh @@ -80,5 +80,5 @@ $JAR ${TESTTOOLVMOPTS} -cfm "${TESTCLASSES}"/ClassUnloadTest.jar "${MANIFEST}" \ # Finally we run the test (cd "${TESTCLASSES}"; \ - $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:classunload \ + $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:class+unload \ -javaagent:ClassUnloadTest.jar ClassUnloadTest "${OTHERDIR}" Bar.jar) From ce05d52251d595196671d6f932111390a9435868 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Sat, 30 Apr 2016 16:08:48 -0700 Subject: [PATCH 194/225] 8155792: Add @jls citations to java.lang.String Reviewed-by: alanb --- jdk/src/java.base/share/classes/java/lang/String.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 64299b92337..33222a586b5 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2015, 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 @@ -117,6 +117,7 @@ import jdk.internal.vm.annotation.Stable; * @see java.lang.StringBuilder * @see java.nio.charset.Charset * @since 1.0 + * @jls 15.18.1 String Concatenation Operator + */ public final class String @@ -2979,6 +2980,7 @@ public final class String * * @return a string that has the same contents as this string, but is * guaranteed to be from a pool of unique strings. + * @jls 3.10.5 String Literals */ public native String intern(); From 2f5a588d257a72c68968d1b70acb05dd1036867d Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Mon, 2 May 2016 10:11:24 +0530 Subject: [PATCH 195/225] 8155028: javac crashes in silly do-while loop Compiler should short circuit code generation for unreachable code. Reviewed-by: mcimadamore --- .../classes/com/sun/tools/javac/jvm/Gen.java | 20 +++-- .../test/tools/javac/UnreachableLoopCond.java | 85 +++++++++++++++++++ 2 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 langtools/test/tools/javac/UnreachableLoopCond.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 5de84f0ab59..ea30fe09a06 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1086,17 +1086,19 @@ public class Gen extends JCTree.Visitor { genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); code.resolve(loopEnv.info.cont); genStats(step, loopEnv); - CondItem c; - if (cond != null) { - code.statBegin(cond.pos); + if (code.isAlive()) { + CondItem c; + if (cond != null) { + code.statBegin(cond.pos); + Assert.check(code.state.stacksize == 0); + c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); + } else { + c = items.makeCondItem(goto_); + } + code.resolve(c.jumpTrue(), startpc); Assert.check(code.state.stacksize == 0); - c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); - } else { - c = items.makeCondItem(goto_); + code.resolve(c.falseJumps); } - code.resolve(c.jumpTrue(), startpc); - Assert.check(code.state.stacksize == 0); - code.resolve(c.falseJumps); } Chain exit = loopEnv.info.exit; if (exit != null) { diff --git a/langtools/test/tools/javac/UnreachableLoopCond.java b/langtools/test/tools/javac/UnreachableLoopCond.java new file mode 100644 index 00000000000..17bfb201c25 --- /dev/null +++ b/langtools/test/tools/javac/UnreachableLoopCond.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 8155028 + * @summary javac crashes in silly do-while loop + * @compile UnreachableLoopCond.java + */ + +class UnreachableLoopCond { + + public void foo() { + Integer i = 100; + do { + return; + } while (i++ < 10); + } + + public void goo() { + Integer i = 100; + do { + break; + } while (i++ < 10); + } + + public void zoo() { + Integer i = 100; + do { + throw new RuntimeException(); + } while (i++ < 10); + } + + public void loo() { + Integer i = 100; + Integer j = 100; + do { + do { + return; + } while (i++ < 10); + } while (j++ < 10); + } + + public void moo() { + Integer i = 100; + do { + if (true) { + return; + } else { + return; + } + } while (i++ < 10); + } + + public void moo(boolean cond) { + Integer i = 100; + do { + if (cond) { + return; + } else { + return; + } + } while (i++ < 10); + } +} From 8ca267abe352314dcebeba40ecd00d700ce472f6 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 2 May 2016 06:43:44 +0200 Subject: [PATCH 196/225] 8050993: There is no record for condition in ternary operator in LineNumberTable Make sure there is an entry in the LineNumberTable for the condition of the ternary operator Co-authored-by: Andrey Nazarov Reviewed-by: jjg --- .../classes/com/sun/tools/javac/jvm/Gen.java | 1 + .../LineNumberTable/LineNumberTestBase.java | 2 +- .../attributes/LineNumberTable/T8050993.java | 53 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index ea30fe09a06..4941b17c096 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1649,6 +1649,7 @@ public class Gen extends JCTree.Visitor { public void visitConditional(JCConditional tree) { Chain thenExit = null; + code.statBegin(tree.cond.pos); CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER); Chain elseChain = c.jumpFalse(); if (!c.isFalse()) { diff --git a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java index eabf5bd5e75..93e9c80d966 100644 --- a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java +++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java @@ -191,7 +191,7 @@ public class LineNumberTestBase extends TestBase { CONDITION("int res = \n" + "testField == 2 ?\n" + "10\n" + - ":9;", 1, 3, 4), // see issue https://bugs.openjdk.java.net/browse/JDK-8050993 + ":9;", 2, 3, 4), TRY("try{\n" + " --testField;\n" + "}\n" + diff --git a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java new file mode 100644 index 00000000000..53ba5fe2366 --- /dev/null +++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java @@ -0,0 +1,53 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8050993 + * @summary Verify that the condition in the conditional lexpression gets a LineNumberTable entry + * @modules jdk.jdeps/com.sun.tools.classfile + * @compile -g T8050993.java + * @run main T8050993 + */ + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import com.sun.tools.classfile.*; + +public class T8050993 { + public static void main(String[] args) throws IOException, ConstantPoolException { + ClassFile someTestIn = ClassFile.read(T8050993.class.getResourceAsStream("T8050993.class")); + Set expectedLineNumbers = new HashSet<>(Arrays.asList(48, 49, 46, 47)); + for (Method m : someTestIn.methods) { + if ("method".equals(m.getName(someTestIn.constant_pool))) { + Code_attribute code_attribute = (Code_attribute) m.attributes.get(Attribute.Code); + for (Attribute at : code_attribute.attributes) { + if (Attribute.LineNumberTable.equals(at.getName(someTestIn.constant_pool))) { + LineNumberTable_attribute att = (LineNumberTable_attribute) at; + Set actualLinesNumbers = Arrays.stream(att.line_number_table) + .map(e -> e.line_number) + .collect(Collectors.toSet()); + if (!Objects.equals(expectedLineNumbers, actualLinesNumbers)) { + throw new AssertionError("Expected LineNumber entries not found;" + + "actual=" + actualLinesNumbers + ";" + + "expected=" + expectedLineNumbers); + } + } + } + } + } + } + + public static int field; + + public static String method() { + String s = + field % 2 == 0 ? + "true" + field : + "false" + field; + return s; + } + +} From d7af112d8da0012955a55d210ba63c65bb1c456d Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 2 May 2016 12:57:05 +0200 Subject: [PATCH 197/225] 8155816: langtools/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java test broken Correcting expected line numbers Reviewed-by: alundblad --- .../javac/classfiles/attributes/LineNumberTable/T8050993.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java index 53ba5fe2366..2c2e8fcd6a3 100644 --- a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java +++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java @@ -19,7 +19,7 @@ import com.sun.tools.classfile.*; public class T8050993 { public static void main(String[] args) throws IOException, ConstantPoolException { ClassFile someTestIn = ClassFile.read(T8050993.class.getResourceAsStream("T8050993.class")); - Set expectedLineNumbers = new HashSet<>(Arrays.asList(48, 49, 46, 47)); + Set expectedLineNumbers = new HashSet<>(Arrays.asList(49, 50, 47, 48)); for (Method m : someTestIn.methods) { if ("method".equals(m.getName(someTestIn.constant_pool))) { Code_attribute code_attribute = (Code_attribute) m.attributes.get(Attribute.Code); From 0dc92a6e8ca34ae92a85db7d76a06f6db77c5a21 Mon Sep 17 00:00:00 2001 From: Matthias Klose Date: Mon, 2 May 2016 15:05:54 +0200 Subject: [PATCH 198/225] 8155821: Typo for s390x for HOTSPOT__CPU_DEFINE Reviewed-by: erikj --- common/autoconf/generated-configure.sh | 8 ++++---- common/autoconf/platform.m4 | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 9563705cdcb..a2d42fb30b8 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -1224,9 +1224,9 @@ with_lcms with_dxsdk with_dxsdk_lib with_dxsdk_include -enable_jtreg_failure_handler enable_new_hotspot_build enable_hotspot_test_in_build +enable_jtreg_failure_handler with_num_cores with_memory_size with_jobs @@ -5070,7 +5070,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=1460963400 +DATE_WHEN_GENERATED=1462194239 ############################################################################### # @@ -15492,7 +15492,7 @@ $as_echo "$COMPILE_TYPE" >&6; } 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 + elif test "x$OPENJDK_TARGET_CPU" = xs390x; then HOTSPOT_TARGET_CPU_DEFINE=S390 fi @@ -15648,7 +15648,7 @@ $as_echo "$COMPILE_TYPE" >&6; } 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 + elif test "x$OPENJDK_BUILD_CPU" = xs390x; then HOTSPOT_BUILD_CPU_DEFINE=S390 fi diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index deaf22ed169..2e99c452694 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -435,7 +435,7 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], 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 + elif test "x$OPENJDK_$1_CPU" = xs390x; then HOTSPOT_$1_CPU_DEFINE=S390 fi AC_SUBST(HOTSPOT_$1_CPU_DEFINE) From c7ff5269963eaa1745b97ebc481365ecce544766 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Mon, 2 May 2016 08:54:14 -0700 Subject: [PATCH 199/225] 8139832: JShell API: Diag constructor should not be exposed and fix typo Reviewed-by: jlahoda --- .../src/jdk.jshell/share/classes/jdk/jshell/Diag.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java index 396396dec2a..c24578b3369 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java @@ -35,13 +35,19 @@ import javax.tools.Diagnostic; public abstract class Diag { // Simplified view on compiler Diagnostic. + /** + * In-package creation only. + */ + Diag() { + } + /** * Used to signal that no position is available. */ public final static long NOPOS = Diagnostic.NOPOS; /** - * Is this diagnostic and error (as opposed to a warning or note) + * Is this diagnostic an error (as opposed to a warning or note) * @return true if this diagnostic is an error */ public abstract boolean isError(); From 7eb46a2e0f7200ad569e36db95aac9439cfd1e47 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Mon, 2 May 2016 17:54:37 +0200 Subject: [PATCH 200/225] 8155824: JDK build should tune down small apps more aggressively Reviewed-by: erikj --- common/autoconf/boot-jdk.m4 | 1 + common/autoconf/generated-configure.sh | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index b27cb9a0b70..f264c510fde 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -397,6 +397,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA]) ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA]) ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA]) + ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs_small]) diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index a2d42fb30b8..f68d8437643 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -5070,7 +5070,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=1462194239 +DATE_WHEN_GENERATED=1462204427 ############################################################################### # @@ -64282,6 +64282,21 @@ $as_echo_n "checking flags for boot jdk java command for small workloads... " >& fi + $ECHO "Check if jvm arg is ok: -XX:TieredStopAtLevel=1" >&5 + $ECHO "Command: $JAVA -XX:TieredStopAtLevel=1 -version" >&5 + OUTPUT=`$JAVA -XX:TieredStopAtLevel=1 -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:TieredStopAtLevel=1" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5 $as_echo "$boot_jdk_jvmargs_small" >&6; } From 46109cd2041acc76327bace37a08c2b359ed9383 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 2 May 2016 12:44:31 -0700 Subject: [PATCH 201/225] 8155784: Build failure on Linux arm64 Reviewed-by: flar, serb --- .../unix/native/libawt_xawt/awt/awt_InputMethod.c | 1 + .../java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c index e4388cd64a4..2dc59c2c77c 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "awt.h" diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index 6a188fb3598..060b082e53b 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -2547,14 +2547,14 @@ static jobject get_string_property(JNIEnv *env, GtkSettings* settings, static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Integer(env, intval); } static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Boolean(env, intval); } From 4b69b86a7f2e4ed4b98d6eeda635b73207034c3f Mon Sep 17 00:00:00 2001 From: Artem Smotrakov Date: Mon, 2 May 2016 13:05:43 -0700 Subject: [PATCH 202/225] 8155859: Problem list tools/pack200/Pack200Props.java Reviewed-by: rriggs --- jdk/test/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 696c9cd270f..f3434f35be4 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -319,6 +319,8 @@ tools/pack200/Pack200Test.java 8059906,8151901 tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all +tools/pack200/Pack200Props.java 8155857 generic-all + ############################################################################ # jdk_jdi From 5950e361a250cc4e11943b44fc065479bfb80629 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Mon, 2 May 2016 15:01:54 -0700 Subject: [PATCH 203/225] 8154578: Drop residual use of addReads from javadoc Reviewed-by: alanb, jjg --- .../toolkit/taglets/TagletManager.java | 22 ----------------- .../com/sun/tools/javadoc/DocletInvoker.java | 24 ------------------- .../toolkit/taglets/TagletManager.java | 22 ----------------- .../jdk/javadoc/internal/tool/Start.java | 23 ------------------ 4 files changed, 91 deletions(-) diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java index bd4ff763147..1b43a69ae06 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java @@ -242,7 +242,6 @@ public class TagletManager { } customTagClass = tagClassLoader.loadClass(classname); - ensureReadable(customTagClass); Method meth = customTagClass.getMethod("register", Map.class); @@ -269,27 +268,6 @@ public class TagletManager { } - /** - * Ensures that the module of the given class is readable to this - * module. - * @param targetClass class in module to be made readable - */ - private void ensureReadable(Class targetClass) { - try { - Method getModuleMethod = Class.class.getMethod("getModule"); - Object thisModule = getModuleMethod.invoke(this.getClass()); - Object targetModule = getModuleMethod.invoke(targetClass); - - Class moduleClass = getModuleMethod.getReturnType(); - Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass); - addReadsMethod.invoke(thisModule, targetModule); - } catch (NoSuchMethodException e) { - // ignore - } catch (Exception e) { - throw new InternalError(e); - } - } - /** * Export javadoc internal API to the unnamed module for a classloader. * This is to support continued use of existing non-standard doclets that diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java index f41edba705a..91e333e8ccb 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java @@ -102,7 +102,6 @@ public class DocletInvoker { this.apiMode = apiMode; this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets - ensureReadable(docletClass); // this may not be soon enough if the class has already been loaded if (exportInternalAPI) { exportInternalAPI(docletClass.getClassLoader()); @@ -149,8 +148,6 @@ public class DocletInvoker { messager.exit(); } docletClass = dc; - - ensureReadable(docletClass); } /* @@ -361,27 +358,6 @@ public class DocletInvoker { } } - /** - * Ensures that the module of the given class is readable to this - * module. - * @param targetClass class in module to be made readable - */ - private void ensureReadable(Class targetClass) { - try { - Method getModuleMethod = Class.class.getMethod("getModule"); - Object thisModule = getModuleMethod.invoke(this.getClass()); - Object targetModule = getModuleMethod.invoke(targetClass); - - Class moduleClass = getModuleMethod.getReturnType(); - Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass); - addReadsMethod.invoke(thisModule, targetModule); - } catch (NoSuchMethodException e) { - // ignore - } catch (Exception e) { - throw new InternalError(e); - } - } - /** * Export javadoc internal API to the unnamed module for a classloader. * This is to support continued use of existing non-standard doclets that diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java index 5b354316a11..ec809050f3c 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java @@ -246,7 +246,6 @@ public class TagletManager { } tagClassLoader = fileManager.getClassLoader(TAGLET_PATH); Class customTagClass = tagClassLoader.loadClass(classname); - ensureReadable(customTagClass); Object instance = customTagClass.newInstance(); Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance); String tname = newLegacy.getName(); @@ -261,27 +260,6 @@ public class TagletManager { } } - /** - * Ensures that the module of the given class is readable to this - * module. - * @param targetClass class in module to be made readable - */ - private void ensureReadable(Class targetClass) { - try { - Method getModuleMethod = Class.class.getMethod("getModule"); - Object thisModule = getModuleMethod.invoke(this.getClass()); - Object targetModule = getModuleMethod.invoke(targetClass); - - Class moduleClass = getModuleMethod.getReturnType(); - Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass); - addReadsMethod.invoke(thisModule, targetModule); - } catch (NoSuchMethodException e) { - // ignore - } catch (Exception e) { - throw new InternalError(e.toString()); - } - } - /** * Add a new SimpleTaglet. If this tag already exists * and the header passed as an argument is null, move tag to the back of the diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index f281ee43a17..d998e077663 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -330,27 +330,6 @@ public class Start extends ToolOption.Helper { return !failed; } - /** - * Ensures that the module of the given class is readable to this - * module. - * @param targetClass class in module to be made readable - */ - private void ensureReadable(Class targetClass) { - try { - Method getModuleMethod = Class.class.getMethod("getModule"); - Object thisModule = getModuleMethod.invoke(this.getClass()); - Object targetModule = getModuleMethod.invoke(targetClass); - - Class moduleClass = getModuleMethod.getReturnType(); - Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass); - addReadsMethod.invoke(thisModule, targetModule); - } catch (NoSuchMethodException e) { - // ignore - } catch (Exception e) { - throw new InternalError(e); - } - } - /** * Main program - internal */ @@ -550,7 +529,6 @@ public class Start extends ToolOption.Helper { } try { Class klass = cl.loadClass(userDocletName); - ensureReadable(klass); return klass; } catch (ClassNotFoundException cnfe) { error("main.doclet_class_not_found", userDocletName); @@ -601,7 +579,6 @@ public class Start extends ToolOption.Helper { for (String tagletName : tagletNames) { try { Class klass = cl.loadClass(tagletName); - ensureReadable(klass); if (com.sun.tools.doclets.Taglet.class.isAssignableFrom(klass)) { return true; } From 325a065aff50274aa3eaf630d380e42ceb513e89 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 2 May 2016 16:17:39 -0700 Subject: [PATCH 204/225] 8155774: move code from ModuleTestBase to toolbox Reviewed-by: ksrini, jlahoda --- .../AbstractOrInnerClassServiceImplTest.java | 6 +- .../tools/javac/modules/AddLimitMods.java | 6 +- .../tools/javac/modules/AddReadsTest.java | 12 +- .../javac/modules/AnnotationProcessing.java | 8 +- .../AnnotationProcessorsInModulesTest.java | 8 +- .../tools/javac/modules/AutomaticModules.java | 6 +- .../javac/modules/DoclintOtherModules.java | 2 +- .../javac/modules/DuplicateClassTest.java | 2 +- .../test/tools/javac/modules/EdgeCases.java | 14 +- .../test/tools/javac/modules/GraphsTest.java | 22 +-- .../tools/javac/modules/HelloWorldTest.java | 8 +- .../test/tools/javac/modules/MOptionTest.java | 8 +- .../tools/javac/modules/ModuleFinderTest.java | 2 +- .../tools/javac/modules/ModuleInfoTest.java | 26 ++-- .../javac/modules/ModuleInfoTreeAccess.java | 2 +- .../tools/javac/modules/ModulePathTest.java | 50 +++---- .../javac/modules/ModuleSourcePathTest.java | 36 ++--- .../tools/javac/modules/ModuleTestBase.java | 127 ++---------------- .../modules/ModulesAndClassPathTest.java | 8 +- .../javac/modules/MultiModuleModeTest.java | 10 +- .../modules/NPECompilingModuleInfoTest.java | 2 +- .../tools/javac/modules/NPEEmptyFileTest.java | 2 +- .../tools/javac/modules/OutputDirTest.java | 10 +- .../javac/modules/PackageConflictTest.java | 45 ++++--- .../javac/modules/PackageMultipleModules.java | 2 +- .../javac/modules/PluginsInModulesTest.java | 2 +- .../tools/javac/modules/ProvidesTest.java | 36 ++--- .../tools/javac/modules/QueryBeforeEnter.java | 10 +- .../modules/RepeatedUsesAndProvidesTest.java | 4 +- .../modules/ReportNonExistentPackageTest.java | 6 +- .../javac/modules/RequiresPublicTest.java | 8 +- .../test/tools/javac/modules/ResolveTest.java | 16 +-- .../ServiceInStaticClassErrorTest.java | 2 +- ...rviceProvidedButNotExportedOrUsedTest.java | 4 +- .../javac/modules/SingleModuleModeTest.java | 10 +- .../tools/javac/modules/SubpackageTest.java | 4 +- .../javac/modules/UpgradeModulePathTest.java | 51 +++---- .../test/tools/javac/modules/UsesTest.java | 33 ++--- .../test/tools/javac/modules/XModuleTest.java | 30 +++-- .../test/tools/lib/toolbox/JavacTask.java | 32 +++++ .../test/tools/lib/toolbox/ModuleBuilder.java | 111 +++++++++++++++ .../test/tools/lib/toolbox/TestRunner.java | 25 ++-- langtools/test/tools/lib/toolbox/ToolBox.java | 32 ++++- 43 files changed, 455 insertions(+), 385 deletions(-) create mode 100644 langtools/test/tools/lib/toolbox/ModuleBuilder.java diff --git a/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java index c4f3b84d2cb..d2b24764ce3 100644 --- a/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java +++ b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java @@ -47,7 +47,7 @@ public class AbstractOrInnerClassServiceImplTest extends ModuleTestBase { } @Test - void testAbstractServiceImpl(Path base) throws Exception { + public void testAbstractServiceImpl(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.Service with p2.Impl; }", @@ -68,7 +68,7 @@ public class AbstractOrInnerClassServiceImplTest extends ModuleTestBase { } @Test - void testInnerClassServiceImpl(Path base) throws Exception { + public void testInnerClassServiceImpl(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.Service with p2.Outer.Inner; }", @@ -89,7 +89,7 @@ public class AbstractOrInnerClassServiceImplTest extends ModuleTestBase { } @Test - void testInnerInterfaceServiceImpl(Path base) throws Exception { + public void testInnerInterfaceServiceImpl(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.Service with p2.Outer.Inner; }", diff --git a/langtools/test/tools/javac/modules/AddLimitMods.java b/langtools/test/tools/javac/modules/AddLimitMods.java index 9df3b221fb5..e5d1c920fd8 100644 --- a/langtools/test/tools/javac/modules/AddLimitMods.java +++ b/langtools/test/tools/javac/modules/AddLimitMods.java @@ -79,7 +79,7 @@ public class AddLimitMods extends ModuleTestBase { } @Test - void testManual(Path base) throws Exception { + public void testManual(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); @@ -176,7 +176,7 @@ public class AddLimitMods extends ModuleTestBase { } @Test - void testAllModulePath(Path base) throws Exception { + public void testAllModulePath(Path base) throws Exception { if (Files.isDirectory(base)) tb.cleanDirectory(base); @@ -284,7 +284,7 @@ public class AddLimitMods extends ModuleTestBase { } @Test - void testRuntime2Compile(Path base) throws Exception { + public void testRuntime2Compile(Path base) throws Exception { Path classpathSrc = base.resolve("classpath-src"); Path classpathOut = base.resolve("classpath-out"); diff --git a/langtools/test/tools/javac/modules/AddReadsTest.java b/langtools/test/tools/javac/modules/AddReadsTest.java index be91ed358c1..2c3c6c66e3b 100644 --- a/langtools/test/tools/javac/modules/AddReadsTest.java +++ b/langtools/test/tools/javac/modules/AddReadsTest.java @@ -58,7 +58,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testAddReads(Path base) throws Exception { + public void testAddReads(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, @@ -150,7 +150,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testAddReadsUnnamedModule(Path base) throws Exception { + public void testAddReadsUnnamedModule(Path base) throws Exception { Path jar = prepareTestJar(base); Path moduleSrc = base.resolve("module-src"); @@ -175,7 +175,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception { + public void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception { Path jar = prepareTestJar(base); Path moduleSrc = base.resolve("module-src"); @@ -202,7 +202,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testAddReadsUnnamedToJavaBase(Path base) throws Exception { + public void testAddReadsUnnamedToJavaBase(Path base) throws Exception { Path jar = prepareTestJar(base); Path src = base.resolve("src"); Path classes = base.resolve("classes"); @@ -223,7 +223,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testAddReadsToJavaBase(Path base) throws Exception { + public void testAddReadsToJavaBase(Path base) throws Exception { Path src = base.resolve("src"); Path classes = base.resolve("classes"); @@ -275,7 +275,7 @@ public class AddReadsTest extends ModuleTestBase { } @Test - void testX(Path base) throws Exception { + public void testX(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, diff --git a/langtools/test/tools/javac/modules/AnnotationProcessing.java b/langtools/test/tools/javac/modules/AnnotationProcessing.java index d344503cbb6..9fa9e082d37 100644 --- a/langtools/test/tools/javac/modules/AnnotationProcessing.java +++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java @@ -68,7 +68,7 @@ public class AnnotationProcessing extends ModuleTestBase { } @Test - void testAPSingleModule(Path base) throws Exception { + public void testAPSingleModule(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); @@ -95,7 +95,7 @@ public class AnnotationProcessing extends ModuleTestBase { } @Test - void testAPMultiModule(Path base) throws Exception { + public void testAPMultiModule(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); Path m2 = moduleSrc.resolve("m2"); @@ -196,7 +196,7 @@ public class AnnotationProcessing extends ModuleTestBase { } @Test - void testVerifyUsesProvides(Path base) throws Exception { + public void testVerifyUsesProvides(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); @@ -254,7 +254,7 @@ public class AnnotationProcessing extends ModuleTestBase { } @Test - void testPackageNoModule(Path base) throws Exception { + public void testPackageNoModule(Path base) throws Exception { Path src = base.resolve("src"); Path classes = base.resolve("classes"); diff --git a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java index cad93dba93f..1fe3a769ff7 100644 --- a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java +++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java @@ -156,7 +156,7 @@ public class AnnotationProcessorsInModulesTest extends ModuleTestBase { Path classes; @Test - void testUseOnlyOneProcessor(Path base) throws Exception { + public void testUseOnlyOneProcessor(Path base) throws Exception { initialization(base); String log = new JavacTask(tb) .options("-processormodulepath", processorCompiledModules.toString(), @@ -172,7 +172,7 @@ public class AnnotationProcessorsInModulesTest extends ModuleTestBase { } @Test - void testAnnotationProcessorExecutionOrder(Path base) throws Exception { + public void testAnnotationProcessorExecutionOrder(Path base) throws Exception { initialization(base); List log = new JavacTask(tb) .options("-processormodulepath", processorCompiledModules.toString(), @@ -202,7 +202,7 @@ public class AnnotationProcessorsInModulesTest extends ModuleTestBase { } @Test - void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception { + public void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception { initialization(base); String log = new JavacTask(tb) .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(), @@ -218,7 +218,7 @@ public class AnnotationProcessorsInModulesTest extends ModuleTestBase { } @Test - void testOptionsExclusion(Path base) throws Exception { + public void testOptionsExclusion(Path base) throws Exception { initialization(base); List log = new JavacTask(tb) .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(), diff --git a/langtools/test/tools/javac/modules/AutomaticModules.java b/langtools/test/tools/javac/modules/AutomaticModules.java index ba4d4401bd3..375d7907f11 100644 --- a/langtools/test/tools/javac/modules/AutomaticModules.java +++ b/langtools/test/tools/javac/modules/AutomaticModules.java @@ -48,7 +48,7 @@ public class AutomaticModules extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path legacySrc = base.resolve("legacy-src"); tb.writeJavaFiles(legacySrc, "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}"); @@ -98,7 +98,7 @@ public class AutomaticModules extends ModuleTestBase { } @Test - void testUnnamedModule(Path base) throws Exception { + public void testUnnamedModule(Path base) throws Exception { Path legacySrc = base.resolve("legacy-src"); tb.writeJavaFiles(legacySrc, "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }", @@ -156,7 +156,7 @@ public class AutomaticModules extends ModuleTestBase { } @Test - void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception { + public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception { Path automaticSrc = base.resolve("automaticSrc"); tb.writeJavaFiles(automaticSrc, "package api; public class Api {}"); Path automaticClasses = base.resolve("automaticClasses"); diff --git a/langtools/test/tools/javac/modules/DoclintOtherModules.java b/langtools/test/tools/javac/modules/DoclintOtherModules.java index 3c5108a41f1..cd89636f869 100644 --- a/langtools/test/tools/javac/modules/DoclintOtherModules.java +++ b/langtools/test/tools/javac/modules/DoclintOtherModules.java @@ -47,7 +47,7 @@ public class DoclintOtherModules extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path src = base.resolve("src"); Path m1 = src.resolve("m1"); Path m2 = src.resolve("m2"); diff --git a/langtools/test/tools/javac/modules/DuplicateClassTest.java b/langtools/test/tools/javac/modules/DuplicateClassTest.java index 192def351e3..48e8332cd4c 100644 --- a/langtools/test/tools/javac/modules/DuplicateClassTest.java +++ b/langtools/test/tools/javac/modules/DuplicateClassTest.java @@ -47,7 +47,7 @@ public class DuplicateClassTest extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path m1 = base.resolve("m1"); Path m2 = base.resolve("m2"); tb.writeJavaFiles(m1, diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java index 4c80bd4f7b4..df3b9f65a9b 100644 --- a/langtools/test/tools/javac/modules/EdgeCases.java +++ b/langtools/test/tools/javac/modules/EdgeCases.java @@ -66,7 +66,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testAddExportUndefinedModule(Path base) throws Exception { + public void testAddExportUndefinedModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}"); Path classes = base.resolve("classes"); @@ -89,7 +89,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testModuleSymbolOutterMostClass(Path base) throws Exception { + public void testModuleSymbolOutterMostClass(Path base) throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { Path moduleSrc = base.resolve("module-src"); @@ -110,7 +110,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testParseEnterAnalyze(Path base) throws Exception { + public void testParseEnterAnalyze(Path base) throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { Path moduleSrc = base.resolve("module-src"); @@ -148,7 +148,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testModuleImplicitModuleBoundaries(Path base) throws Exception { + public void testModuleImplicitModuleBoundaries(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, @@ -180,7 +180,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testAssignClassToAutomaticModule(Path base) throws Exception { + public void testAssignClassToAutomaticModule(Path base) throws Exception { //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not //duplicated when being accessed through a classfile. Path automaticSrc = base.resolve("automaticSrc"); @@ -239,7 +239,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testEmptyImplicitModuleInfo(Path base) throws Exception { + public void testEmptyImplicitModuleInfo(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); Files.createDirectories(src_m1); @@ -270,7 +270,7 @@ public class EdgeCases extends ModuleTestBase { } @Test - void testClassPackageClash(Path base) throws Exception { + public void testClassPackageClash(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, diff --git a/langtools/test/tools/javac/modules/GraphsTest.java b/langtools/test/tools/javac/modules/GraphsTest.java index a27da147f32..aadc180b808 100644 --- a/langtools/test/tools/javac/modules/GraphsTest.java +++ b/langtools/test/tools/javac/modules/GraphsTest.java @@ -28,7 +28,8 @@ * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder + * ModuleTestBase * @run main GraphsTest */ @@ -41,6 +42,7 @@ import java.util.regex.Pattern; import toolbox.JarTask; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; import toolbox.ToolBox; @@ -69,11 +71,11 @@ public class GraphsTest extends ModuleTestBase { * */ @Test - void diamond(Path base) throws Exception { + public void diamond(Path base) throws Exception { Path modules = Files.createDirectories(base.resolve("modules")); - new ModuleBuilder("J") + new ModuleBuilder(tb, "J") .exports("openJ") .classes("package openJ; public class J { }") .classes("package closedJ; public class J { }") @@ -87,25 +89,25 @@ public class GraphsTest extends ModuleTestBase { .run() .writeAll(); - new ModuleBuilder("O") + new ModuleBuilder(tb, "O") .exports("openO") .requiresPublic("J", jarModules) .classes("package openO; public class O { openJ.J j; }") .classes("package closedO; public class O { }") .build(modules); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .requiresPublic("O", modules, jarModules) .exports("openN") .classes("package openN; public class N { }") .classes("package closedN; public class N { }") .build(modules); - new ModuleBuilder("L") + new ModuleBuilder(tb, "L") .requiresPublic("O", modules, jarModules) .exports("openL") .classes("package openL; public class L { }") .classes("package closedL; public class L { }") .build(modules); - ModuleBuilder m = new ModuleBuilder("M"); + ModuleBuilder m = new ModuleBuilder(tb, "M"); //positive case Path positiveSrc = m .requires("N", modules) @@ -178,14 +180,14 @@ public class GraphsTest extends ModuleTestBase { @Test public void reexportOfQualifiedExport(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("M") + new ModuleBuilder(tb, "M") .requiresPublic("N") .write(modules); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exportsTo("pack", "M") .classes("package pack; public class Clazz { }") .write(modules); - new ModuleBuilder("L") + new ModuleBuilder(tb, "L") .requires("M") .classes("package p; public class A { A(pack.Clazz cl){} } ") .write(modules); diff --git a/langtools/test/tools/javac/modules/HelloWorldTest.java b/langtools/test/tools/javac/modules/HelloWorldTest.java index f0757ec167a..6240e306b14 100644 --- a/langtools/test/tools/javac/modules/HelloWorldTest.java +++ b/langtools/test/tools/javac/modules/HelloWorldTest.java @@ -58,7 +58,7 @@ public class HelloWorldTest extends ModuleTestBase { + HELLO_WORLD; @Test - void testLegacyMode(Path base) throws Exception { + public void testLegacyMode(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, HELLO_WORLD); @@ -85,7 +85,7 @@ public class HelloWorldTest extends ModuleTestBase { } @Test - void testUnnamedModule(Path base) throws Exception { + public void testUnnamedModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, HELLO_WORLD); @@ -101,7 +101,7 @@ public class HelloWorldTest extends ModuleTestBase { } @Test - void testSingleModule(Path base) throws Exception { + public void testSingleModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeFile(src.resolve("module-info.java"), "module m { }"); tb.writeJavaFiles(src, PKG_HELLO_WORLD); @@ -121,7 +121,7 @@ public class HelloWorldTest extends ModuleTestBase { } @Test - void testModuleSourcePath(Path base) throws Exception { + public void testModuleSourcePath(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }"); diff --git a/langtools/test/tools/javac/modules/MOptionTest.java b/langtools/test/tools/javac/modules/MOptionTest.java index cb265d867d4..cea2670f7c8 100644 --- a/langtools/test/tools/javac/modules/MOptionTest.java +++ b/langtools/test/tools/javac/modules/MOptionTest.java @@ -47,7 +47,7 @@ public class MOptionTest extends ModuleTestBase { } @Test - void testOneModule(Path base) throws Exception { + public void testOneModule(Path base) throws Exception { Path src = base.resolve("src"); Path m1 = src.resolve("m1"); Path build = base.resolve("build"); @@ -112,7 +112,7 @@ public class MOptionTest extends ModuleTestBase { } @Test - void testNoOutputDir(Path base) throws Exception { + public void testNoOutputDir(Path base) throws Exception { Path src = base.resolve("src"); Path m1 = src.resolve("m1"); Path build = base.resolve("build"); @@ -135,7 +135,7 @@ public class MOptionTest extends ModuleTestBase { } @Test - void testNoModuleSourcePath(Path base) throws Exception { + public void testNoModuleSourcePath(Path base) throws Exception { Path src = base.resolve("src"); Path m1 = src.resolve("m1"); Path build = base.resolve("build"); @@ -158,7 +158,7 @@ public class MOptionTest extends ModuleTestBase { } @Test - void testMultiModule(Path base) throws Exception { + public void testMultiModule(Path base) throws Exception { Path src = base.resolve("src"); Path m1 = src.resolve("m1"); Path m2 = src.resolve("m2"); diff --git a/langtools/test/tools/javac/modules/ModuleFinderTest.java b/langtools/test/tools/javac/modules/ModuleFinderTest.java index d1186b1ae5f..ed228469f85 100644 --- a/langtools/test/tools/javac/modules/ModuleFinderTest.java +++ b/langtools/test/tools/javac/modules/ModuleFinderTest.java @@ -48,7 +48,7 @@ public class ModuleFinderTest extends ModuleTestBase { } @Test - void testDuplicateModulesOnPath(Path base) throws Exception { + public void testDuplicateModulesOnPath(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m1 { }"); diff --git a/langtools/test/tools/javac/modules/ModuleInfoTest.java b/langtools/test/tools/javac/modules/ModuleInfoTest.java index 9b0e7c491a3..600afb321c7 100644 --- a/langtools/test/tools/javac/modules/ModuleInfoTest.java +++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java @@ -51,7 +51,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Check error message if module declaration not in module-info.java. */ @Test - void testModuleDeclNotInModuleJava(Path base) throws Exception { + public void testModuleDeclNotInModuleJava(Path base) throws Exception { Path src = base.resolve("src"); tb.writeFile(src.resolve("M.java"), "module M { }"); String log = new JavacTask(tb) @@ -69,7 +69,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that a package private class can be put in module-info.java. */ @Test - void testNotModuleDeclInModuleJava_1(Path base) throws Exception { + public void testNotModuleDeclInModuleJava_1(Path base) throws Exception { Path src = base.resolve("src"); tb.writeFile(src.resolve("module-info.java"), "class C { }"); new JavacTask(tb) @@ -83,7 +83,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that a public class cannot be put in module-info.java. */ @Test - void testNotModuleDeclInModuleJava_2(Path base) throws Exception { + public void testNotModuleDeclInModuleJava_2(Path base) throws Exception { Path src = base.resolve("src"); tb.writeFile(src.resolve("module-info.java"), "public class C { }"); String log = new JavacTask(tb) @@ -101,7 +101,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that only one module decl can be put in module-info.java. */ @Test - void testSingleModuleDecl(Path base) throws Exception { + public void testSingleModuleDecl(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }"); String log = new JavacTask(tb) @@ -119,7 +119,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that missing requires are reported. */ @Test - void testRequiresNotFound(Path base) throws Exception { + public void testRequiresNotFound(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module M1 { requires M2; }"); String log = new JavacTask(tb) @@ -137,7 +137,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that missing exports are reported. */ @Test - void testExportsNotFound(Path base) throws Exception { + public void testExportsNotFound(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module M1 { exports p to M2; }"); String log = new JavacTask(tb) @@ -155,7 +155,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that a simple loop is detected. */ @Test - void testRequiresSelf(Path base) throws Exception { + public void testRequiresSelf(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module M { requires M; }"); String log = new JavacTask(tb) @@ -173,7 +173,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that a multi-module loop is detected. */ @Test - void testRequiresLoop(Path base) throws Exception { + public void testRequiresLoop(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }"); @@ -201,7 +201,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that a multi-module loop is detected. */ @Test - void testRequiresPublicLoop(Path base) throws Exception { + public void testRequiresPublicLoop(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }"); @@ -229,7 +229,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that duplicate requires are detected. */ @Test - void testDuplicateRequires(Path base) throws Exception { + public void testDuplicateRequires(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }"); @@ -255,7 +255,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that duplicate exported packages are detected. */ @Test - void testDuplicateExports_packages(Path base) throws Exception { + public void testDuplicateExports_packages(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m1 { exports p; exports p; }"); @@ -278,7 +278,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that duplicate exported packages are detected. */ @Test - void testDuplicateExports_packages2(Path base) throws Exception { + public void testDuplicateExports_packages2(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }"); tb.writeJavaFiles(src.resolve("m2"), "module m2 { }"); @@ -302,7 +302,7 @@ public class ModuleInfoTest extends ModuleTestBase { * Verify that duplicate exported packages are detected. */ @Test - void testDuplicateExports_modules(Path base) throws Exception { + public void testDuplicateExports_modules(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }"); diff --git a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java index 3666875a4de..7e0917c9f81 100644 --- a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java +++ b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java @@ -61,7 +61,7 @@ public class ModuleInfoTreeAccess extends ModuleTestBase { } @Test - void testTreePathForModuleDecl(Path base) throws Exception { + public void testTreePathForModuleDecl(Path base) throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { diff --git a/langtools/test/tools/javac/modules/ModulePathTest.java b/langtools/test/tools/javac/modules/ModulePathTest.java index d885512e632..9fb639841b7 100644 --- a/langtools/test/tools/javac/modules/ModulePathTest.java +++ b/langtools/test/tools/javac/modules/ModulePathTest.java @@ -30,7 +30,8 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap * jdk.jlink/jdk.tools.jmod - * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder + * ModuleTestBase * @run main ModulePathTest */ @@ -41,6 +42,7 @@ import java.nio.file.Path; import toolbox.JarTask; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; import toolbox.ToolBox; @@ -54,7 +56,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testNotExistsOnPath(Path base) throws Exception { + public void testNotExistsOnPath(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { }"); @@ -71,7 +73,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testNotADirOnPath_1(Path base) throws Exception { + public void testNotADirOnPath_1(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { }"); tb.writeFile("dummy.txt", ""); @@ -89,7 +91,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testNotADirOnPath_2(Path base) throws Exception { + public void testNotADirOnPath_2(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { }"); tb.writeFile("dummy.jimage", ""); @@ -107,7 +109,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testExplodedModuleOnPath(Path base) throws Exception { + public void testExplodedModuleOnPath(Path base) throws Exception { Path modSrc = base.resolve("modSrc"); tb.writeJavaFiles(modSrc, "module m1 { exports p; }", @@ -137,7 +139,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testBadExplodedModuleOnPath(Path base) throws Exception { + public void testBadExplodedModuleOnPath(Path base) throws Exception { Path modClasses = base.resolve("modClasses"); tb.writeFile(modClasses.resolve("module-info.class"), "module m1 { }"); @@ -162,7 +164,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testAutoJarOnPath(Path base) throws Exception { + public void testAutoJarOnPath(Path base) throws Exception { Path jarSrc = base.resolve("jarSrc"); tb.writeJavaFiles(jarSrc, "package p; public class CC { }"); @@ -195,7 +197,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testModJarOnPath(Path base) throws Exception { + public void testModJarOnPath(Path base) throws Exception { Path jarSrc = base.resolve("jarSrc"); tb.writeJavaFiles(jarSrc, "module m1 { exports p; }", @@ -231,7 +233,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testBadJarOnPath(Path base) throws Exception { + public void testBadJarOnPath(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { }"); tb.writeFile("dummy.jar", ""); @@ -249,7 +251,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testJModOnPath(Path base) throws Exception { + public void testJModOnPath(Path base) throws Exception { Path jmodSrc = base.resolve("jmodSrc"); tb.writeJavaFiles(jmodSrc, "module m1 { exports p; }", @@ -282,7 +284,7 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void testBadJModOnPath(Path base) throws Exception { + public void testBadJModOnPath(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { }"); tb.writeFile("dummy.jmod", ""); @@ -300,9 +302,9 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void relativePath(Path base) throws Exception { + public void relativePath(Path base) throws Exception { final Path modules = base.resolve("modules"); - new ModuleBuilder("m1").build(modules); + new ModuleBuilder(tb, "m1").build(modules); Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }"); @@ -316,9 +318,9 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void duplicatePaths_1(Path base) throws Exception { + public void duplicatePaths_1(Path base) throws Exception { final Path modules = base.resolve("modules"); - new ModuleBuilder("m1").build(modules); + new ModuleBuilder(tb, "m1").build(modules); Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }"); @@ -332,9 +334,9 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void duplicatePaths_2(Path base) throws Exception { + public void duplicatePaths_2(Path base) throws Exception { final Path modules = base.resolve("modules"); - new ModuleBuilder("m1").build(modules); + new ModuleBuilder(tb, "m1").build(modules); Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }"); @@ -349,15 +351,15 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void oneModuleHidesAnother(Path base) throws Exception { + public void oneModuleHidesAnother(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path deepModuleDir = module.resolve("deepModuleDir"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class E { }") .build(deepModuleDir); @@ -374,19 +376,19 @@ public class ModulePathTest extends ModuleTestBase { } @Test - void modulesInDifferentContainers(Path base) throws Exception { + public void modulesInDifferentContainers(Path base) throws Exception { final Path modules = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("one") .classes("package one; public class A { }") .build(modules); - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .requires("m1", modules) .build(base.resolve("tmp")); jar(base.resolve("tmp/m2"), modules.resolve("m2.jar")); - new ModuleBuilder("m3") + new ModuleBuilder(tb, "m3") .requires("m2", modules) .build(base.resolve("tmp")); jmod(base.resolve("tmp/m3"), modules.resolve("m3.jmod")); diff --git a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java index dcb6b102592..e78a368e84d 100644 --- a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java +++ b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java @@ -56,7 +56,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void testSourcePathConflict(Path base) throws Exception { + public void testSourcePathConflict(Path base) throws Exception { Path sp = base.resolve("src"); Path msp = base.resolve("srcmodules"); @@ -74,7 +74,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void testUnnormalizedPath1(Path base) throws Exception { + public void testUnnormalizedPath1(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, "module m1 { }"); @@ -91,7 +91,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void testUnnormalizedPath2(Path base) throws Exception { + public void testUnnormalizedPath2(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, "module m1 { }"); @@ -115,7 +115,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void regularBraces(Path base) throws Exception { + public void regularBraces(Path base) throws Exception { generateModules(base, "src1", "src2/inner_dir"); final Path modules = base.resolve("modules"); @@ -136,7 +136,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void mismatchedBraces(Path base) throws Exception { + public void mismatchedBraces(Path base) throws Exception { final List sourcePaths = Arrays.asList( "{", "}", @@ -165,7 +165,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void deepBraces(Path base) throws Exception { + public void deepBraces(Path base) throws Exception { String[] modulePaths = {"src/src1", "src/src2", "src/src3", @@ -197,7 +197,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void fileInPath(Path base) throws Exception { + public void fileInPath(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); tb.writeFile(base.resolve("dummy.txt"), ""); @@ -218,7 +218,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void noAlternative(Path base) throws Exception { + public void noAlternative(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); @@ -238,7 +238,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void noChoice(Path base) throws Exception { + public void noChoice(Path base) throws Exception { tb.writeJavaFiles(base.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }"); final Path modules = base.resolve("modules"); @@ -257,7 +257,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void nestedModules(Path src) throws Exception { + public void nestedModules(Path src) throws Exception { Path carModule = src.resolve("car"); tb.writeJavaFiles(carModule, "module car { }", "package light; class Headlight { }"); tb.writeJavaFiles(carModule.resolve("engine"), "module engine { }", "package flat; class Piston { }"); @@ -277,7 +277,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void relativePaths(Path base) throws Exception { + public void relativePaths(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("kettle"), "module kettle { }", "package electric; class Heater { }"); @@ -296,7 +296,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void duplicatePaths(Path base) throws Exception { + public void duplicatePaths(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }"); @@ -315,7 +315,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void notExistentPaths(Path base) throws Exception { + public void notExistentPaths(Path base) throws Exception { tb.writeJavaFiles(base.resolve("m1"), "module m1 { requires m0; }", "package a; class A { }"); final Path modules = base.resolve("modules"); @@ -334,7 +334,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void notExistentPathShouldBeSkipped(Path base) throws Exception { + public void notExistentPathShouldBeSkipped(Path base) throws Exception { tb.writeJavaFiles(base.resolve("m1"), "module m1 { }", "package a; class A { }"); final Path modules = base.resolve("modules"); @@ -352,7 +352,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void commas(Path base) throws Exception { + public void commas(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }"); @@ -371,7 +371,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void asterisk(Path base) throws Exception { + public void asterisk(Path base) throws Exception { tb.writeJavaFiles(base.resolve("kettle").resolve("classes"), "module kettle { }", "package electric; class Heater { }"); @@ -391,7 +391,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void asteriskInDifferentSets(Path base) throws Exception { + public void asteriskInDifferentSets(Path base) throws Exception { Path src = base.resolve("src"); final Path module = src.resolve("kettle"); tb.writeJavaFiles(module.resolve("classes"), "module kettle { }", "package electric; class Heater { }"); @@ -417,7 +417,7 @@ public class ModuleSourcePathTest extends ModuleTestBase { } @Test - void asteriskIllegalUse(Path base) throws Exception { + public void asteriskIllegalUse(Path base) throws Exception { final List sourcePaths = Arrays.asList( "*", "**", diff --git a/langtools/test/tools/javac/modules/ModuleTestBase.java b/langtools/test/tools/javac/modules/ModuleTestBase.java index 700e41417c4..d1dcfa9fb6a 100644 --- a/langtools/test/tools/javac/modules/ModuleTestBase.java +++ b/langtools/test/tools/javac/modules/ModuleTestBase.java @@ -43,19 +43,20 @@ import java.util.TreeSet; import java.util.stream.Collectors; import toolbox.JavacTask; +import toolbox.TestRunner; import toolbox.ToolBox; /** * Base class for module tests. */ -public class ModuleTestBase { +public class ModuleTestBase extends TestRunner { protected ToolBox tb; - protected PrintStream out; private int errors; - /** Marker annotation for test methods to be invoked by runTests. */ - @Retention(RetentionPolicy.RUNTIME) - @interface Test { } + ModuleTestBase() { + super(System.err); + tb = new ToolBox(); + } /** * Run all methods annotated with @Test, and throw an exception if any @@ -63,47 +64,12 @@ public class ModuleTestBase { * * @throws Exception if any errors occurred */ - void runTests() throws Exception { - if (tb == null) - tb = new ToolBox(); - out = System.err; - - for (Method m: getClass().getDeclaredMethods()) { - Annotation a = m.getAnnotation(Test.class); - if (a != null) { - try { - out.println("Running test " + m.getName()); - Path baseDir = Paths.get(m.getName()); - m.invoke(this, new Object[] { baseDir }); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - error("Exception: " + e.getCause()); - cause.printStackTrace(out); - } - out.println(); - } - } - if (errors > 0) - throw new Exception(errors + " errors occurred"); + protected void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); } - // move to ToolBox? - // change returntyp to List -- means updating ToolBox methods Path[] findJavaFiles(Path... paths) throws IOException { - Set files = new TreeSet<>(); - for (Path p : paths) { - Files.walkFileTree(p, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - if (file.getFileName().toString().endsWith(".java")) { - files.add(file); - } - return FileVisitResult.CONTINUE; - } - }); - } - return files.toArray(new Path[files.size()]); + return tb.findJavaFiles(paths); } void error(String message) { @@ -111,79 +77,4 @@ public class ModuleTestBase { errors++; } - public class ModuleBuilder { - - private final String name; - private String requires = ""; - private String exports = ""; - private String uses = ""; - private String provides = ""; - private String modulePath = ""; - private List content = new ArrayList<>(); - - public ModuleBuilder(String name) { - this.name = name; - } - - public ModuleBuilder requiresPublic(String requires, Path... modulePath) { - return requires("public " + requires, modulePath); - } - - public ModuleBuilder requires(String requires, Path... modulePath) { - this.requires += " requires " + requires + ";\n"; - this.modulePath += Arrays.stream(modulePath) - .map(Path::toString) - .collect(Collectors.joining(File.pathSeparator)); - return this; - } - - public ModuleBuilder exportsTo(String pkg, String module) { - return exports(pkg + " to " + module); - } - - public ModuleBuilder exports(String pkg) { - this.exports += " exports " + pkg + ";\n"; - return this; - } - - public ModuleBuilder uses(String uses) { - this.uses += " uses " + uses + ";\n"; - return this; - } - - public ModuleBuilder provides(String service, String implementation) { - this.provides += " provides " + service + " with " + implementation + ";\n"; - return this; - } - - public ModuleBuilder classes(String... content) { - this.content.addAll(Arrays.asList(content)); - return this; - } - - public Path write(Path where) throws IOException { - Files.createDirectories(where); - List sources = new ArrayList<>(); - sources.add("module " + name + "{" - + requires - + exports - + uses - + provides - + "}"); - sources.addAll(content); - Path moduleSrc = where.resolve(name + "/src"); - tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{})); - return moduleSrc; - } - - public void build(Path where) throws IOException { - Path moduleSrc = write(where); - new JavacTask(tb) - .outdir(where.resolve(name)) - .options("-mp", modulePath) - .files(findJavaFiles(moduleSrc)) - .run() - .writeAll(); - } - } } diff --git a/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java index 01c75bd3462..ce727c422a2 100644 --- a/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java +++ b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java @@ -55,7 +55,7 @@ public class ModulesAndClassPathTest extends ModuleTestBase { } @Test - void testModulesAndClassPath(Path base) throws Exception { + public void testModulesAndClassPath(Path base) throws Exception { Path jar = prepareTestJar(base); Path moduleSrc = base.resolve("module-src"); @@ -106,7 +106,7 @@ public class ModulesAndClassPathTest extends ModuleTestBase { } @Test - void testImplicitSourcePathModuleInfo(Path base) throws Exception { + public void testImplicitSourcePathModuleInfo(Path base) throws Exception { Path jar = prepareTestJar(base); Path moduleSrc = base.resolve("module-src"); @@ -139,7 +139,7 @@ public class ModulesAndClassPathTest extends ModuleTestBase { } @Test - void testModuleInfoFromOutput(Path base) throws Exception { + public void testModuleInfoFromOutput(Path base) throws Exception { Path jar = prepareTestJar(base); Path moduleSrc = base.resolve("module-src"); @@ -221,7 +221,7 @@ public class ModulesAndClassPathTest extends ModuleTestBase { } @Test - void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception { + public void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); diff --git a/langtools/test/tools/javac/modules/MultiModuleModeTest.java b/langtools/test/tools/javac/modules/MultiModuleModeTest.java index f7291988c6b..e72995bf5ac 100644 --- a/langtools/test/tools/javac/modules/MultiModuleModeTest.java +++ b/langtools/test/tools/javac/modules/MultiModuleModeTest.java @@ -49,7 +49,7 @@ public class MultiModuleModeTest extends ModuleTestBase { } @Test - void testDuplicateModules(Path base) throws Exception { + public void testDuplicateModules(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, "module m1 { }"); @@ -72,7 +72,7 @@ public class MultiModuleModeTest extends ModuleTestBase { } @Test - void testCantFindModule(Path base) throws Exception { + public void testCantFindModule(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, "module m1 { }"); @@ -95,7 +95,7 @@ public class MultiModuleModeTest extends ModuleTestBase { } @Test - void testModuleNameMismatch(Path base) throws Exception { + public void testModuleNameMismatch(Path base) throws Exception { Path src = base.resolve("src"); Path src_m1 = src.resolve("m1"); tb.writeJavaFiles(src_m1, "module m2 { }"); @@ -116,7 +116,7 @@ public class MultiModuleModeTest extends ModuleTestBase { } @Test - void testImplicitModuleSource(Path base) throws Exception { + public void testImplicitModuleSource(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }"); tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; }"); @@ -132,7 +132,7 @@ public class MultiModuleModeTest extends ModuleTestBase { } @Test - void testImplicitModuleClass(Path base) throws Exception { + public void testImplicitModuleClass(Path base) throws Exception { Path src1 = base.resolve("src1"); tb.writeJavaFiles(src1.resolve("m1"), "module m1 { }"); Path modules1 = base.resolve("modules1"); diff --git a/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java b/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java index e1ca690294f..ec70ec2c96b 100644 --- a/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java +++ b/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java @@ -45,7 +45,7 @@ public class NPECompilingModuleInfoTest extends ModuleTestBase { } @Test - void testCompileNoError(Path base) throws Exception { + public void testCompileNoError(Path base) throws Exception { Path mod = base.resolve("mod"); tb.writeJavaFiles(mod, "module mod { exports pkg; }"); Path pkg = mod.resolve("pkg"); diff --git a/langtools/test/tools/javac/modules/NPEEmptyFileTest.java b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java index 4b44e996961..3ace4bb0326 100644 --- a/langtools/test/tools/javac/modules/NPEEmptyFileTest.java +++ b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java @@ -45,7 +45,7 @@ public class NPEEmptyFileTest extends ModuleTestBase { } @Test - void compileEmptyFile(Path base) throws Exception { + public void compileEmptyFile(Path base) throws Exception { Path modules = base.resolve("modules"); Files.createDirectories(modules); Path emptyJavaFile = base.resolve("Test.java"); diff --git a/langtools/test/tools/javac/modules/OutputDirTest.java b/langtools/test/tools/javac/modules/OutputDirTest.java index 6e4d5d0573d..0236a7bda6a 100644 --- a/langtools/test/tools/javac/modules/OutputDirTest.java +++ b/langtools/test/tools/javac/modules/OutputDirTest.java @@ -60,7 +60,7 @@ public class OutputDirTest extends ModuleTestBase { } @Test - void testError(Path base) throws Exception { + public void testError(Path base) throws Exception { String log = new JavacTask(tb) .options("-XDrawDiagnostics", "-modulesourcepath", src.toString()) @@ -74,7 +74,7 @@ public class OutputDirTest extends ModuleTestBase { } @Test - void testProcOnly(Path base) throws IOException { + public void testProcOnly(Path base) throws IOException { new JavacTask(tb) .options("-XDrawDiagnostics", "-proc:only", @@ -85,7 +85,7 @@ public class OutputDirTest extends ModuleTestBase { } @Test - void testClassOutDir(Path base) throws IOException { + public void testClassOutDir(Path base) throws IOException { Path classes = base.resolve("classes"); new JavacTask(tb) .options("-XDrawDiagnostics", @@ -97,7 +97,7 @@ public class OutputDirTest extends ModuleTestBase { } @Test - void testExplodedOutDir(Path base) throws Exception { + public void testExplodedOutDir(Path base) throws Exception { Path modSrc = base.resolve("modSrc"); tb.writeJavaFiles(modSrc, "module m1 { exports p; }", @@ -131,7 +131,7 @@ public class OutputDirTest extends ModuleTestBase { } @Test - void testInExplodedOutDir(Path base) throws Exception { + public void testInExplodedOutDir(Path base) throws Exception { Path modSrc = base.resolve("modSrc"); tb.writeJavaFiles(modSrc, "module m1 { exports p; }", diff --git a/langtools/test/tools/javac/modules/PackageConflictTest.java b/langtools/test/tools/javac/modules/PackageConflictTest.java index 7ebe29927fc..c091089f77a 100644 --- a/langtools/test/tools/javac/modules/PackageConflictTest.java +++ b/langtools/test/tools/javac/modules/PackageConflictTest.java @@ -28,7 +28,7 @@ * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase * @run main PackageConflictTest */ @@ -38,6 +38,7 @@ import java.util.Arrays; import java.util.List; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; import toolbox.ToolBox; @@ -48,7 +49,7 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "package java.util; public class MyList { }"); @@ -68,7 +69,7 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testDisjoint(Path base) throws Exception { + public void testDisjoint(Path base) throws Exception { Path m1 = base.resolve("m1"); Path m2 = base.resolve("m2"); tb.writeJavaFiles(m1, @@ -89,7 +90,7 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testConflictInDependencies(Path base) throws Exception { + public void testConflictInDependencies(Path base) throws Exception { Path m1 = base.resolve("m1"); Path m2 = base.resolve("m2"); Path m3 = base.resolve("m3"); @@ -123,13 +124,13 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testSimple2(Path base) throws Exception { + public void testSimple2(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exports("pack") .classes("package pack; public class A { }") .build(modules); - new ModuleBuilder("M") + new ModuleBuilder(tb, "M") .requires("N") .classes("package pack; public class B { pack.A f; }") .write(modules); @@ -147,14 +148,14 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testPrivateConflict(Path base) throws Exception { + public void testPrivateConflict(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exports("publ") .classes("package pack; public class A { }") .classes("package publ; public class B { }") .write(modules); - new ModuleBuilder("M") + new ModuleBuilder(tb, "M") .requires("N") .classes("package pack; public class C { publ.B b; }") .write(modules); @@ -173,14 +174,14 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testPrivateConflictOnModulePath(Path base) throws Exception { + public void testPrivateConflictOnModulePath(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exports("publ") .classes("package pack; public class A { }") .classes("package publ; public class B { }") .build(modules); - new ModuleBuilder("M") + new ModuleBuilder(tb, "M") .requires("N") .classes("package pack; public class C { publ.B b; }") .write(modules); @@ -199,17 +200,17 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testRequiresConflictExports(Path base) throws Exception { + public void testRequiresConflictExports(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("M") + new ModuleBuilder(tb, "M") .exports("pack") .classes("package pack; public class A { }") .build(modules); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exports("pack") .classes("package pack; public class B { }") .build(modules); - new ModuleBuilder("K") + new ModuleBuilder(tb, "K") .requires("M") .requires("N") .classes("package pkg; public class C { pack.A a; pack.B b; }") @@ -231,18 +232,18 @@ public class PackageConflictTest extends ModuleTestBase { } @Test - void testQulifiedExportsToDifferentModules(Path base) throws Exception { + public void testQulifiedExportsToDifferentModules(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("U").write(modules); - new ModuleBuilder("M") + new ModuleBuilder(tb, "U").write(modules); + new ModuleBuilder(tb, "M") .exports("pkg to U") .classes("package pkg; public class A { public static boolean flagM; }") .write(modules); - new ModuleBuilder("N") + new ModuleBuilder(tb, "N") .exports("pkg to K") .classes("package pkg; public class A { public static boolean flagN; }") .write(modules); - ModuleBuilder moduleK = new ModuleBuilder("K"); + ModuleBuilder moduleK = new ModuleBuilder(tb, "K"); moduleK.requires("M") .requires("N") .classes("package p; public class DependsOnN { boolean f = pkg.A.flagN; } ") diff --git a/langtools/test/tools/javac/modules/PackageMultipleModules.java b/langtools/test/tools/javac/modules/PackageMultipleModules.java index 8f2ae2de90f..888fdaa72e9 100644 --- a/langtools/test/tools/javac/modules/PackageMultipleModules.java +++ b/langtools/test/tools/javac/modules/PackageMultipleModules.java @@ -49,7 +49,7 @@ public class PackageMultipleModules extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path m1 = base.resolve("m1"); Path m2 = base.resolve("m2"); tb.writeJavaFiles(m1, diff --git a/langtools/test/tools/javac/modules/PluginsInModulesTest.java b/langtools/test/tools/javac/modules/PluginsInModulesTest.java index aea94a63729..480b147a7a2 100644 --- a/langtools/test/tools/javac/modules/PluginsInModulesTest.java +++ b/langtools/test/tools/javac/modules/PluginsInModulesTest.java @@ -127,7 +127,7 @@ public class PluginsInModulesTest extends ModuleTestBase { Path classes; @Test - void testUseOnlyOneProcessor(Path base) throws Exception { + public void testUseOnlyOneProcessor(Path base) throws Exception { initialization(base); List log = new JavacTask(tb) .options("-processormodulepath", processorCompiledModules.toString(), diff --git a/langtools/test/tools/javac/modules/ProvidesTest.java b/langtools/test/tools/javac/modules/ProvidesTest.java index 63c3f56a4e0..2224e26fc63 100644 --- a/langtools/test/tools/javac/modules/ProvidesTest.java +++ b/langtools/test/tools/javac/modules/ProvidesTest.java @@ -48,7 +48,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; }", @@ -65,7 +65,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testMulti(Path base) throws Exception { + public void testMulti(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1; }", @@ -86,7 +86,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testMissingWith(Path base) throws Exception { + public void testMissingWith(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.C; }", @@ -108,7 +108,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testDuplicateProvides(Path base) throws Exception { + public void testDuplicateProvides(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }", @@ -126,7 +126,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testMissingService(Path base) throws Exception { + public void testMissingService(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.Missing with p.C; }", @@ -151,7 +151,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testProvidesFromAnotherModule(Path base) throws Exception { + public void testProvidesFromAnotherModule(Path base) throws Exception { Path modules = base.resolve("modules"); tb.writeJavaFiles(modules.resolve("M"), "module M { exports p; }", @@ -177,7 +177,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testServiceIsNotImplemented(Path base) throws Exception { + public void testServiceIsNotImplemented(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.A with p.B; }", @@ -200,7 +200,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testMissingImplementation(Path base) throws Exception { + public void testMissingImplementation(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.C with p.Impl; }", @@ -222,7 +222,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testSeveralImplementations(Path base) throws Exception { + public void testSeveralImplementations(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }", @@ -238,7 +238,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testOneImplementationsForServices(Path base) throws Exception { + public void testOneImplementationsForServices(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }", @@ -254,7 +254,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testAbstractImplementation(Path base) throws Exception { + public void testAbstractImplementation(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; }", @@ -277,7 +277,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testInterfaceImplementation(Path base) throws Exception { + public void testInterfaceImplementation(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.Service with p2.Impl; }", @@ -300,7 +300,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testProtectedImplementation(Path base) throws Exception { + public void testProtectedImplementation(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; }", @@ -323,7 +323,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testNoNoArgConstructor(Path base) throws Exception { + public void testNoNoArgConstructor(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p1.C1; provides p1.C1 with p2.C2; }", @@ -346,7 +346,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testPrivateNoArgConstructor(Path base) throws Exception { + public void testPrivateNoArgConstructor(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p1.C1; provides p1.C1 with p2.C2; }", @@ -369,7 +369,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testServiceIndirectlyImplemented(Path base) throws Exception { + public void testServiceIndirectlyImplemented(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C3; }", @@ -385,7 +385,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testServiceImplementationInnerClass(Path base) throws Exception { + public void testServiceImplementationInnerClass(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2.Inner; }", @@ -408,7 +408,7 @@ public class ProvidesTest extends ModuleTestBase { } @Test - void testServiceDefinitionInnerClass(Path base) throws Exception { + public void testServiceDefinitionInnerClass(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1.InnerDefinition with p2.C2; }", diff --git a/langtools/test/tools/javac/modules/QueryBeforeEnter.java b/langtools/test/tools/javac/modules/QueryBeforeEnter.java index 4e606fe48df..669d95f03ec 100644 --- a/langtools/test/tools/javac/modules/QueryBeforeEnter.java +++ b/langtools/test/tools/javac/modules/QueryBeforeEnter.java @@ -65,7 +65,7 @@ public class QueryBeforeEnter extends ModuleTestBase { } @Test - void testEmpty(Path base) throws Exception { + public void testEmpty(Path base) throws Exception { JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); com.sun.source.util.JavacTask task = (com.sun.source.util.JavacTask) javaCompiler.getTask(null, null, null, null, null, null); @@ -75,7 +75,7 @@ public class QueryBeforeEnter extends ModuleTestBase { } @Test - void testUnnamed(Path base) throws Exception { + public void testUnnamed(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); @@ -151,7 +151,7 @@ public class QueryBeforeEnter extends ModuleTestBase { } @Test - void testSingleNamed(Path base) throws Exception { + public void testSingleNamed(Path base) throws Exception { Path moduleSrc = base.resolve("module-src"); Path m1 = moduleSrc.resolve("m1"); @@ -226,7 +226,7 @@ public class QueryBeforeEnter extends ModuleTestBase { } @Test - void testMultiModule(Path base) throws Exception { + public void testMultiModule(Path base) throws Exception { Path modulePathSrc = base.resolve("module-path-src"); Path m1 = modulePathSrc.resolve("m1"); @@ -311,7 +311,7 @@ public class QueryBeforeEnter extends ModuleTestBase { } @Test - void testTooSoon(Path base) throws Exception { + public void testTooSoon(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, diff --git a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java index c5ea6903b9d..da1f5c8814e 100644 --- a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java +++ b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java @@ -46,7 +46,7 @@ public class RepeatedUsesAndProvidesTest extends ModuleTestBase { } @Test - void testDuplicateUses(Path base) throws Exception { + public void testDuplicateUses(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p1.C1; uses p1.C1; }", @@ -66,7 +66,7 @@ public class RepeatedUsesAndProvidesTest extends ModuleTestBase { } @Test - void testDuplicateProvides(Path base) throws Exception { + public void testDuplicateProvides(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }", diff --git a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java index 5fd54e9afcc..b36944b196c 100644 --- a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java +++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java @@ -46,7 +46,7 @@ public class ReportNonExistentPackageTest extends ModuleTestBase { } @Test - void testExportUnknownPackage(Path base) throws Exception { + public void testExportUnknownPackage(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { exports p1; }"); Path classes = base.resolve("classes"); @@ -64,7 +64,7 @@ public class ReportNonExistentPackageTest extends ModuleTestBase { } @Test - void testExportEmptyPackage(Path base) throws Exception { + public void testExportEmptyPackage(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { exports p1; }", @@ -84,7 +84,7 @@ public class ReportNonExistentPackageTest extends ModuleTestBase { } @Test - void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception { + public void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { exports p1; }"); Path p1 = src.resolve("p1"); diff --git a/langtools/test/tools/javac/modules/RequiresPublicTest.java b/langtools/test/tools/javac/modules/RequiresPublicTest.java index 6b24ec871fa..7ce53d21fe3 100644 --- a/langtools/test/tools/javac/modules/RequiresPublicTest.java +++ b/langtools/test/tools/javac/modules/RequiresPublicTest.java @@ -47,7 +47,7 @@ public class RequiresPublicTest extends ModuleTestBase { } @Test - void testJavaSE_OK(Path base) throws Exception { + public void testJavaSE_OK(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { requires java.se; }", @@ -66,7 +66,7 @@ public class RequiresPublicTest extends ModuleTestBase { } @Test - void testJavaSE_Fail(Path base) throws Exception { + public void testJavaSE_Fail(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { requires java.se; }", @@ -90,7 +90,7 @@ public class RequiresPublicTest extends ModuleTestBase { } @Test - void testComplex_OK(Path base) throws Exception { + public void testComplex_OK(Path base) throws Exception { Path src = getComplexSrc(base, "", ""); Path classes = base.resolve("classes"); Files.createDirectories(classes); @@ -104,7 +104,7 @@ public class RequiresPublicTest extends ModuleTestBase { } @Test - void testComplex_Fail(Path base) throws Exception { + public void testComplex_Fail(Path base) throws Exception { Path src = getComplexSrc(base, "import p5.C5; import p6.C6; import p7.C7;\n", "C5 c5; C6 c6; C7 c7;\n"); diff --git a/langtools/test/tools/javac/modules/ResolveTest.java b/langtools/test/tools/javac/modules/ResolveTest.java index 958cf4e2888..6b4fc51d7bd 100644 --- a/langtools/test/tools/javac/modules/ResolveTest.java +++ b/langtools/test/tools/javac/modules/ResolveTest.java @@ -45,7 +45,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testMissingSimpleTypeUnnamedModule(Path base) throws Exception { + public void testMissingSimpleTypeUnnamedModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "class C { D d; }"); @@ -62,7 +62,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testMissingSimpleTypeNamedModule(Path base) throws Exception { + public void testMissingSimpleTypeNamedModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { }", @@ -81,7 +81,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testUnexportedTypeUnreadableModule(Path base) throws Exception { + public void testUnexportedTypeUnreadableModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", @@ -105,7 +105,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testUnexportedTypeReadableModule(Path base) throws Exception { + public void testUnexportedTypeReadableModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", @@ -129,7 +129,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testQualifiedExportedTypeReadableModule(Path base) throws Exception { + public void testQualifiedExportedTypeReadableModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1 to m3; }", @@ -155,7 +155,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testExportedTypeUnreadableModule(Path base) throws Exception { + public void testExportedTypeUnreadableModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1; }", @@ -179,7 +179,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testExportedTypeReadableModule(Path base) throws Exception { + public void testExportedTypeReadableModule(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1; }", @@ -199,7 +199,7 @@ public class ResolveTest extends ModuleTestBase { } @Test - void testExportedTypeReadableModule2(Path base) throws Exception { + public void testExportedTypeReadableModule2(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1 to m2; }", diff --git a/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java index e05d12265d6..c242cd3efb4 100644 --- a/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java +++ b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java @@ -48,7 +48,7 @@ public class ServiceInStaticClassErrorTest extends ModuleTestBase { } @Test - void testError(Path base) throws Exception { + public void testError(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.I with p1.Outer.A; }", diff --git a/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java index 062b39d2c5f..60899853871 100644 --- a/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java +++ b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java @@ -49,7 +49,7 @@ public class ServiceProvidedButNotExportedOrUsedTest extends ModuleTestBase { } @Test - void testWarning(Path base) throws Exception { + public void testWarning(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { provides p1.C1 with p2.C2; }", @@ -76,7 +76,7 @@ public class ServiceProvidedButNotExportedOrUsedTest extends ModuleTestBase { } @Test - void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception { + public void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p1; }", diff --git a/langtools/test/tools/javac/modules/SingleModuleModeTest.java b/langtools/test/tools/javac/modules/SingleModuleModeTest.java index 4b547723b9a..319c8c20f36 100644 --- a/langtools/test/tools/javac/modules/SingleModuleModeTest.java +++ b/langtools/test/tools/javac/modules/SingleModuleModeTest.java @@ -59,7 +59,7 @@ public class SingleModuleModeTest extends ModuleTestBase{ } @Test - void testTooManyModules(Path base) throws Exception { + public void testTooManyModules(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }"); tb.writeJavaFiles(src.resolve("m2"), "module m2 { }"); @@ -76,7 +76,7 @@ public class SingleModuleModeTest extends ModuleTestBase{ } @Test - void testImplicitModuleSource(Path base) throws Exception { + public void testImplicitModuleSource(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { }", @@ -90,7 +90,7 @@ public class SingleModuleModeTest extends ModuleTestBase{ } @Test - void testImplicitModuleClass(Path base) throws Exception { + public void testImplicitModuleClass(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { }", @@ -112,7 +112,7 @@ public class SingleModuleModeTest extends ModuleTestBase{ } @Test - void testImplicitModuleClassAP(Path base) throws Exception { + public void testImplicitModuleClassAP(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses java.lang.Runnable; }", @@ -137,7 +137,7 @@ public class SingleModuleModeTest extends ModuleTestBase{ } @Test - void testImplicitModuleSourceAP(Path base) throws Exception { + public void testImplicitModuleSourceAP(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses java.lang.Runnable; }", diff --git a/langtools/test/tools/javac/modules/SubpackageTest.java b/langtools/test/tools/javac/modules/SubpackageTest.java index 034f3248b6e..87e9fc9fd46 100644 --- a/langtools/test/tools/javac/modules/SubpackageTest.java +++ b/langtools/test/tools/javac/modules/SubpackageTest.java @@ -52,7 +52,7 @@ public class SubpackageTest extends ModuleTestBase { } @Test // based on JDK-8075435 - void testUnnamedModule(Path base) throws Exception { + public void testUnnamedModule(Path base) throws Exception { Path libsrc = base.resolve("lib/src"); tb.writeJavaFiles(libsrc, "package p; public class E extends Error { }"); @@ -83,7 +83,7 @@ public class SubpackageTest extends ModuleTestBase { } @Test - void testSimpleMulti(Path base) throws Exception { + public void testSimpleMulti(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("mp"), "module mp { exports p; }", diff --git a/langtools/test/tools/javac/modules/UpgradeModulePathTest.java b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java index 63c0741ae18..988076c0e9a 100644 --- a/langtools/test/tools/javac/modules/UpgradeModulePathTest.java +++ b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java @@ -28,7 +28,7 @@ * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase * @run main UpgradeModulePathTest */ @@ -36,6 +36,7 @@ import java.io.File; import java.nio.file.Path; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; import toolbox.ToolBox; @@ -47,15 +48,15 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void simpleUsage(Path base) throws Exception { + public void simpleUsage(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path upgradeModule = base.resolve("upgradeModule"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class E { }") .build(upgradeModule); @@ -73,15 +74,15 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void onlyUpgradeModulePath(Path base) throws Exception { + public void onlyUpgradeModulePath(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path upgradeModule = base.resolve("upgradeModule"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class E { }") .build(upgradeModule); @@ -98,15 +99,15 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void withModuleSourcePath(Path base) throws Exception { + public void withModuleSourcePath(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path upgradeModule = base.resolve("upgradeModule"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class E { }") .build(upgradeModule); @@ -115,7 +116,7 @@ public class UpgradeModulePathTest extends ModuleTestBase { tb.writeJavaFiles(s.resolve("m3"), "module m3 { }"); final Path upgradeModule3 = base.resolve("upgradeModule"); - new ModuleBuilder("m3") + new ModuleBuilder(tb, "m3") .exports("pkg3") .classes("package pkg3; public class E { }") .build(upgradeModule); @@ -135,15 +136,15 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void sameUpgradeAndModulePath(Path base) throws Exception { + public void sameUpgradeAndModulePath(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path upgradeModule = base.resolve("upgradeModule"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class E { }") .build(upgradeModule); @@ -161,9 +162,9 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void dummyFileInUpgradeModulePath(Path base) throws Exception { + public void dummyFileInUpgradeModulePath(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); @@ -189,24 +190,24 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void severalUpgradeModules(Path base) throws Exception { + public void severalUpgradeModules(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class A { }") .build(module); - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .exports("pkg2") .classes("package pkg2; public class B { }") .build(module); Path upgradeModule = base.resolve("upgradeModule"); - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .exports("pkg2") .classes("package pkg2; public class BC { }") .build(upgradeModule); - new ModuleBuilder("m3") + new ModuleBuilder(tb, "m3") .exports("pkg3") .classes("package pkg3; public class DC { }") .build(upgradeModule); @@ -240,21 +241,21 @@ public class UpgradeModulePathTest extends ModuleTestBase { } @Test - void severalUpgradeModulePathsLastWin(Path base) throws Exception { + public void severalUpgradeModulePathsLastWin(Path base) throws Exception { final Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg1") .classes("package pkg1; public class E { }") .build(module); final Path upgradeModule1 = base.resolve("upgradeModule1"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class EC1 { }") .build(upgradeModule1); final Path upgradeModule2 = base.resolve("upgradeModule2"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("pkg2") .classes("package pkg2; public class EC2 { }") .build(upgradeModule2); diff --git a/langtools/test/tools/javac/modules/UsesTest.java b/langtools/test/tools/javac/modules/UsesTest.java index e35d1d4c076..510f70629c9 100644 --- a/langtools/test/tools/javac/modules/UsesTest.java +++ b/langtools/test/tools/javac/modules/UsesTest.java @@ -28,7 +28,7 @@ * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase * @run main UsesTest */ @@ -39,6 +39,7 @@ import java.util.Collection; import java.util.List; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; import toolbox.ToolBox; @@ -49,7 +50,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testSimple(Path base) throws Exception { + public void testSimple(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p.C; }", @@ -65,7 +66,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testSimpleInner(Path base) throws Exception { + public void testSimpleInner(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p.C.Inner; }", @@ -81,7 +82,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testSimpleAnnotation(Path base) throws Exception { + public void testSimpleAnnotation(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p.C; }", @@ -97,7 +98,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testPrivateService(Path base) throws Exception { + public void testPrivateService(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p.C.A; uses p.C; }", @@ -119,7 +120,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testMulti(Path base) throws Exception { + public void testMulti(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; }", @@ -138,13 +139,13 @@ public class UsesTest extends ModuleTestBase { } @Test - void testMultiOnModulePath(Path base) throws Exception { + public void testMultiOnModulePath(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("p") .classes("package p; public class C { }") .build(modules); - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .requires("m1") .uses("p.C") .write(modules); @@ -158,13 +159,13 @@ public class UsesTest extends ModuleTestBase { } @Test - void testMultiOnModulePathInner(Path base) throws Exception { + public void testMultiOnModulePathInner(Path base) throws Exception { Path modules = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .exports("p") .classes("package p; public class C { public class Inner { } }") .build(modules); - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .requires("m1") .uses("p.C.Inner") .write(modules); @@ -178,7 +179,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testDuplicateUses(Path base) throws Exception { + public void testDuplicateUses(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m"), "module m { uses p.C; uses p.C; }", @@ -199,7 +200,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testServiceNotExist(Path base) throws Exception { + public void testServiceNotExist(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src, "module m { uses p.NotExist; }", @@ -220,7 +221,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testUsesUnexportedService(Path base) throws Exception { + public void testUsesUnexportedService(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", @@ -244,7 +245,7 @@ public class UsesTest extends ModuleTestBase { } @Test - void testUsesUnexportedButProvidedService(Path base) throws Exception { + public void testUsesUnexportedButProvidedService(Path base) throws Exception { Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("m1"), "module m1 { provides p.C with p.C; }", diff --git a/langtools/test/tools/javac/modules/XModuleTest.java b/langtools/test/tools/javac/modules/XModuleTest.java index 34465afb42f..1658f148a89 100644 --- a/langtools/test/tools/javac/modules/XModuleTest.java +++ b/langtools/test/tools/javac/modules/XModuleTest.java @@ -28,7 +28,7 @@ * @modules * jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main - * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase + * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase * @run main XModuleTest */ @@ -37,7 +37,9 @@ import java.util.Arrays; import java.util.List; import toolbox.JavacTask; +import toolbox.ModuleBuilder; import toolbox.Task; +import toolbox.TestRunner; import toolbox.ToolBox; public class XModuleTest extends ModuleTestBase { @@ -47,7 +49,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testCorrectXModule(Path base) throws Exception { + public void testCorrectXModule(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }"); @@ -67,7 +69,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testSourcePath(Path base) throws Exception { + public void testSourcePath(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element, Other { }", "package javax.lang.model.element; interface Other { }"); @@ -87,7 +89,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testClassPath(Path base) throws Exception { + public void testClassPath(Path base) throws Exception { Path cpSrc = base.resolve("cpSrc"); tb.writeJavaFiles(cpSrc, "package p; public interface Other { }"); Path cpClasses = base.resolve("cpClasses"); @@ -122,7 +124,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testNoModuleInfoOnSourcePath(Path base) throws Exception { + public void testNoModuleInfoOnSourcePath(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, @@ -147,7 +149,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testNoModuleInfoInClassOutput(Path base) throws Exception { + public void testNoModuleInfoInClassOutput(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path srcMod = base.resolve("src-mod"); tb.writeJavaFiles(srcMod, @@ -187,7 +189,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testModuleSourcePathXModule(Path base) throws Exception { + public void testModuleSourcePathXModule(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }"); @@ -210,7 +212,7 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testXModuleTooMany(Path base) throws Exception { + public void testXModuleTooMany(Path base) throws Exception { //note: avoiding use of java.base, as that gets special handling on some places: Path src = base.resolve("src"); tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }"); @@ -234,9 +236,9 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testWithModulePath(Path base) throws Exception { + public void testWithModulePath(Path base) throws Exception { Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .classes("package pkg1; public interface E { }") .build(module); @@ -251,7 +253,7 @@ public class XModuleTest extends ModuleTestBase { .writeAll(); //checks module bounds still exist - new ModuleBuilder("m2") + new ModuleBuilder(tb, "m2") .classes("package pkg2; public interface D { }") .build(module); @@ -275,14 +277,14 @@ public class XModuleTest extends ModuleTestBase { } @Test - void testWithUpgradeModulePath(Path base) throws Exception { + public void testWithUpgradeModulePath(Path base) throws Exception { Path module = base.resolve("modules"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .classes("package pkg1; public interface E { }") .build(module); Path upgrade = base.resolve("upgrade"); - new ModuleBuilder("m1") + new ModuleBuilder(tb, "m1") .classes("package pkg1; public interface D { }") .build(upgrade); diff --git a/langtools/test/tools/lib/toolbox/JavacTask.java b/langtools/test/tools/lib/toolbox/JavacTask.java index e2da5628969..72ff269d69b 100644 --- a/langtools/test/tools/lib/toolbox/JavacTask.java +++ b/langtools/test/tools/lib/toolbox/JavacTask.java @@ -102,6 +102,16 @@ public class JavacTask extends AbstractTask { return this; } + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavacTask classpath(List classpath) { + this.classpath = classpath; + return this; + } + /** * Sets the sourcepath. * @param sourcepath the sourcepath @@ -125,6 +135,16 @@ public class JavacTask extends AbstractTask { return this; } + /** + * Sets the sourcepath. + * @param sourcepath the sourcepath + * @return this task object + */ + public JavacTask sourcepath(List sourcepath) { + this.sourcepath = sourcepath; + return this; + } + /** * Sets the output directory. * @param outdir the output directory @@ -187,6 +207,18 @@ public class JavacTask extends AbstractTask { return this; } + /** + * Sets the files to be compiled or analyzed. + * @param files the files + * @return this task object + */ + public JavacTask files(List files) { + this.files = files.stream() + .map(Path::toString) + .collect(Collectors.toList()); + return this; + } + /** * Sets the sources to be compiled or analyzed. * Each source string is converted into an in-memory object that diff --git a/langtools/test/tools/lib/toolbox/ModuleBuilder.java b/langtools/test/tools/lib/toolbox/ModuleBuilder.java new file mode 100644 index 00000000000..6c6ed659938 --- /dev/null +++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.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. + * + * 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 toolbox; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ModuleBuilder { + + private final ToolBox tb; + private final String name; + private String requires = ""; + private String exports = ""; + private String uses = ""; + private String provides = ""; + private String modulePath = ""; + private List content = new ArrayList<>(); + + public ModuleBuilder(ToolBox tb, String name) { + this.tb = tb; + this.name = name; + } + + public ModuleBuilder requiresPublic(String requires, Path... modulePath) { + return requires("public " + requires, modulePath); + } + + public ModuleBuilder requires(String requires, Path... modulePath) { + this.requires += " requires " + requires + ";\n"; + this.modulePath += Arrays.stream(modulePath) + .map(Path::toString) + .collect(Collectors.joining(File.pathSeparator)); + return this; + } + + public ModuleBuilder exportsTo(String pkg, String module) { + return exports(pkg + " to " + module); + } + + public ModuleBuilder exports(String pkg) { + this.exports += " exports " + pkg + ";\n"; + return this; + } + + public ModuleBuilder uses(String uses) { + this.uses += " uses " + uses + ";\n"; + return this; + } + + public ModuleBuilder provides(String service, String implementation) { + this.provides += " provides " + service + " with " + implementation + ";\n"; + return this; + } + + public ModuleBuilder classes(String... content) { + this.content.addAll(Arrays.asList(content)); + return this; + } + + public Path write(Path where) throws IOException { + Files.createDirectories(where); + List sources = new ArrayList<>(); + sources.add("module " + name + "{" + + requires + + exports + + uses + + provides + + "}"); + sources.addAll(content); + Path moduleSrc = where.resolve(name + "/src"); + tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{})); + return moduleSrc; + } + + public void build(Path where) throws IOException { + Path moduleSrc = write(where); + new JavacTask(tb) + .outdir(where.resolve(name)) + .options("-mp", modulePath) + .files(tb.findJavaFiles(moduleSrc)) + .run() + .writeAll(); + } +} diff --git a/langtools/test/tools/lib/toolbox/TestRunner.java b/langtools/test/tools/lib/toolbox/TestRunner.java index 22034730405..f0a921ef127 100644 --- a/langtools/test/tools/lib/toolbox/TestRunner.java +++ b/langtools/test/tools/lib/toolbox/TestRunner.java @@ -35,15 +35,16 @@ import java.util.function.Function; * Utility class to manage and execute sub-tests within a test. * * This class does the following: - * i. invokes those test methods annotated with @Test - * ii. keeps track of successful and failed tests - * iii. throws an Exception if any test fails. - * iv. provides a test summary at the end of the run. - * + *
          + *
        • invokes those test methods annotated with @Test + *
        • keeps track of successful and failed tests + *
        • throws an Exception if any test fails. + *
        • provides a test summary at the end of the run. + *
        + * Tests must extend this class, annotate the test methods * with @Test and call one of the runTests method. */ - public abstract class TestRunner { /** Marker annotation for test cases. */ @Retention(RetentionPolicy.RUNTIME) @@ -54,7 +55,7 @@ public abstract class TestRunner { public String testName = null; - final PrintStream out; + protected PrintStream out; /** * Constructs the Object. @@ -66,18 +67,18 @@ public abstract class TestRunner { /** * Invoke all methods annotated with @Test. - * @throws java.lang.Exception + * @throws java.lang.Exception if any errors occur */ - public void runTests() throws Exception { + protected void runTests() throws Exception { runTests(f -> new Object[0]); } /** * Invoke all methods annotated with @Test. - * @param f a lambda expression to specify arguments. - * @throws java.lang.Exception + * @param f a lambda expression to specify arguments for the test method + * @throws java.lang.Exception if any errors occur */ - public void runTests(Function f) throws Exception { + protected void runTests(Function f) throws Exception { for (Method m : getClass().getDeclaredMethods()) { Annotation a = m.getAnnotation(Test.class); if (a != null) { diff --git a/langtools/test/tools/lib/toolbox/ToolBox.java b/langtools/test/tools/lib/toolbox/ToolBox.java index 287313f9c42..5ac6117d8bb 100644 --- a/langtools/test/tools/lib/toolbox/ToolBox.java +++ b/langtools/test/tools/lib/toolbox/ToolBox.java @@ -41,6 +41,7 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -49,6 +50,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -315,7 +317,7 @@ public class ToolBox { * Reads the lines of a file. * The file is read using the default character encoding. * @param path the file to be read - * @return the lines of the file. + * @return the lines of the file * @throws IOException if an error occurred while reading the file */ public List readAllLines(String path) throws IOException { @@ -326,7 +328,7 @@ public class ToolBox { * Reads the lines of a file. * The file is read using the default character encoding. * @param path the file to be read - * @return the lines of the file. + * @return the lines of the file * @throws IOException if an error occurred while reading the file */ public List readAllLines(Path path) throws IOException { @@ -348,7 +350,7 @@ public class ToolBox { * Reads the lines of a file using the given encoding. * @param path the file to be read * @param encoding the encoding to be used to read the file - * @return the lines of the file. + * @return the lines of the file * @throws IOException if an error occurred while reading the file */ public List readAllLines(Path path, String encoding) throws IOException { @@ -359,6 +361,30 @@ public class ToolBox { return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding); } + /** + * Find .java files in one or more directories. + *

        Similar to the shell "find" command: {@code find paths -name \*.java}. + * @param paths the directories in which to search for .java files + * @return the .java files found + * @throws IOException if an error occurred while searching for files + */ + public Path[] findJavaFiles(Path... paths) throws IOException { + Set files = new TreeSet<>(); // use TreeSet to force a consistent order + for (Path p : paths) { + Files.walkFileTree(p, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + if (file.getFileName().toString().endsWith(".java")) { + files.add(file); + } + return FileVisitResult.CONTINUE; + } + }); + } + return files.toArray(new Path[files.size()]); + } + /** * Writes a file containing the given content. * Any necessary directories for the file will be created. From b3854d58300ec1e9518d1aa266e374577f15edd1 Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Mon, 2 May 2016 16:45:38 -0700 Subject: [PATCH 205/225] 8140422: Add mechanism to allow non default root CAs to be not subject to algorithm restrictions Reviewed-by: mullan, xuelei --- jdk/make/gendata/Gendata-java.base.gmk | 14 +- .../provider/certpath/AlgorithmChecker.java | 146 +++--- .../certpath/PKIXMasterCertPathValidator.java | 4 +- .../util/AbstractAlgorithmConstraints.java | 19 +- .../security/util/AlgorithmDecomposer.java | 70 ++- .../sun/security/util/AnchorCertificates.java | 101 +++++ .../util/CertConstraintParameters.java | 59 +++ .../util/DisabledAlgorithmConstraints.java | 420 ++++++++++++++---- .../util/LegacyAlgorithmConstraints.java | 9 +- .../sun/security/x509/X509CertImpl.java | 11 +- .../share/conf/security/java.security | 30 +- .../sun/security/tools/jarsigner/Warning.java | 2 +- 12 files changed, 694 insertions(+), 191 deletions(-) create mode 100644 jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java create mode 100644 jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java diff --git a/jdk/make/gendata/Gendata-java.base.gmk b/jdk/make/gendata/Gendata-java.base.gmk index d94ec3404c0..5c6de721b64 100644 --- a/jdk/make/gendata/Gendata-java.base.gmk +++ b/jdk/make/gendata/Gendata-java.base.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, 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 @@ -41,7 +41,7 @@ include GendataPolicyJars.gmk GENDATA_UNINAME := $(JDK_OUTPUTDIR)/modules/java.base/java/lang/uniName.dat $(GENDATA_UNINAME): $(JDK_TOPDIR)/make/data/unicodedata/UnicodeData.txt $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(@D) + $(call MakeDir, $(@D)) $(TOOL_CHARACTERNAME) $< $@ TARGETS += $(GENDATA_UNINAME) @@ -51,7 +51,7 @@ TARGETS += $(GENDATA_UNINAME) GENDATA_CURDATA := $(JDK_OUTPUTDIR)/modules/java.base/java/util/currency.data $(GENDATA_CURDATA): $(JDK_TOPDIR)/make/data/currency/CurrencyData.properties $(BUILD_TOOLS_JDK) - $(MKDIR) -p $(@D) + $(call MakeDir, $(@D)) $(RM) $@ $(TOOL_GENERATECURRENCYDATA) -o $@.tmp < $< $(MV) $@.tmp $@ @@ -67,10 +67,10 @@ GENDATA_JAVA_SECURITY := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/ja # RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile $(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC) - $(ECHO) "Generating java.security" - $(MKDIR) -p $(@D) + $(call LogInfo, Generating java.security) + $(call MakeDir, $(@D)) $(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \ - $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) || exit 1 + $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) TARGETS += $(GENDATA_JAVA_SECURITY) @@ -78,7 +78,7 @@ TARGETS += $(GENDATA_JAVA_SECURITY) $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist: \ $(JDK_TOPDIR)/make/data/classlist/classlist.$(OPENJDK_TARGET_OS) - $(MKDIR) -p $(@D) + $(call MakeDir, $(@D)) $(RM) $@ $@.tmp $(TOOL_ADDJSUM) $< $@.tmp $(MV) $@.tmp $@ diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index b71121423d8..b210d18e073 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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,12 +31,10 @@ import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.EnumSet; -import java.util.HashSet; import java.math.BigInteger; import java.security.PublicKey; import java.security.KeyFactory; import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; import java.security.GeneralSecurityException; import java.security.cert.Certificate; import java.security.cert.X509CRL; @@ -48,10 +46,13 @@ import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXReason; -import java.io.IOException; -import java.security.interfaces.*; -import java.security.spec.*; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import sun.security.util.AnchorCertificates; +import sun.security.util.CertConstraintParameters; +import sun.security.util.Debug; import sun.security.util.DisabledAlgorithmConstraints; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; @@ -69,6 +70,7 @@ import sun.security.x509.AlgorithmId; * @see PKIXParameters */ public final class AlgorithmChecker extends PKIXCertPathChecker { + private static final Debug debug = Debug.getInstance("certpath"); private final AlgorithmConstraints constraints; private final PublicKey trustedPubKey; @@ -88,6 +90,14 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { certPathDefaultConstraints = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); + // If there is no "cacerts" keyword, then disable anchor checking + private static final boolean publicCALimits = + certPathDefaultConstraints.checkProperty("jdkCA"); + + // If anchor checking enabled, this will be true if the trust anchor + // has a match in the cacerts file + private boolean trustedMatch = false; + /** * Create a new AlgorithmChecker with the algorithm * constraints specified in security property @@ -136,6 +146,11 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { if (anchor.getTrustedCert() != null) { this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } } else { this.trustedPubKey = anchor.getCAPublicKey(); } @@ -144,6 +159,19 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { this.constraints = constraints; } + // Check this 'cert' for restrictions in the AnchorCertificates + // trusted certificates list + private static boolean checkFingerprint(X509Certificate cert) { + if (!publicCALimits) { + return false; + } + + if (debug != null) { + debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName()); + } + return AnchorCertificates.contains(cert); + } + @Override public void init(boolean forward) throws CertPathValidatorException { // Note that this class does not support forward mode. @@ -181,36 +209,8 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { return; } - X509CertImpl x509Cert = null; - try { - x509Cert = X509CertImpl.toImpl((X509Certificate)cert); - } catch (CertificateException ce) { - throw new CertPathValidatorException(ce); - } - - PublicKey currPubKey = x509Cert.getPublicKey(); - String currSigAlg = x509Cert.getSigAlgName(); - - AlgorithmId algorithmId = null; - try { - algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); - } catch (CertificateException ce) { - throw new CertPathValidatorException(ce); - } - - AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); - - // Check the current signature algorithm - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, currSigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg, - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } - // check the key usage and key size - boolean[] keyUsage = x509Cert.getKeyUsage(); + boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage(); if (keyUsage != null && keyUsage.length < 9) { throw new CertPathValidatorException( "incorrect KeyUsage extension", @@ -248,27 +248,67 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { if (primitives.isEmpty()) { throw new CertPathValidatorException( - "incorrect KeyUsage extension", + "incorrect KeyUsage extension bits", null, null, -1, PKIXReason.INVALID_KEY_USAGE); } } - if (!constraints.permits(primitives, currPubKey)) { - throw new CertPathValidatorException( - "algorithm constraints check failed", - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + PublicKey currPubKey = cert.getPublicKey(); + + // Check against DisabledAlgorithmConstraints certpath constraints. + // permits() will throw exception on failure. + certPathDefaultConstraints.permits(primitives, + new CertConstraintParameters((X509Certificate)cert, + trustedMatch)); + // new CertConstraintParameters(x509Cert, trustedMatch)); + // If there is no previous key, set one and exit + if (prevPubKey == null) { + prevPubKey = currPubKey; + return; + } + + X509CertImpl x509Cert; + AlgorithmId algorithmId; + try { + x509Cert = X509CertImpl.toImpl((X509Certificate)cert); + algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); + } catch (CertificateException ce) { + throw new CertPathValidatorException(ce); + } + + AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); + String currSigAlg = x509Cert.getSigAlgName(); + + // If 'constraints' is not of DisabledAlgorithmConstraints, check all + // everything individually + if (!(constraints instanceof DisabledAlgorithmConstraints)) { + // Check the current signature algorithm + if (!constraints.permits( + SIGNATURE_PRIMITIVE_SET, + currSigAlg, currSigAlgParams)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on signature " + + "algorithm: " + currSigAlg, null, null, -1, + BasicReason.ALGORITHM_CONSTRAINED); + } + + if (!constraints.permits(primitives, currPubKey)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on keysize: " + + sun.security.util.KeyUtil.getKeySize(currPubKey), + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } } // Check with previous cert for signature algorithm and public key if (prevPubKey != null) { - if (currSigAlg != null) { - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, prevPubKey, currSigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg, - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } + if (!constraints.permits( + SIGNATURE_PRIMITIVE_SET, + currSigAlg, prevPubKey, currSigAlgParams)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on " + + "signature algorithm: " + currSigAlg, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } // Inherit key parameters from previous key @@ -282,7 +322,7 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); if (params == null) { throw new CertPathValidatorException( - "Key parameters missing"); + "Key parameters missing from public key."); } try { @@ -330,6 +370,11 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { // Don't bother to change the trustedPubKey. if (anchor.getTrustedCert() != null) { prevPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } } else { prevPubKey = anchor.getCAPublicKey(); } @@ -370,7 +415,8 @@ public final class AlgorithmChecker extends PKIXCertPathChecker { if (!certPathDefaultConstraints.permits( SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { throw new CertPathValidatorException( - "algorithm check failed: " + sigAlgName + " is disabled", + "Algorithm constraints check failed on signature algorithm: " + + sigAlgName + " is disabled", null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java index cfffba8329a..e85ef2d0303 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java @@ -131,8 +131,8 @@ class PKIXMasterCertPathValidator { } catch (CertPathValidatorException cpve) { throw new CertPathValidatorException(cpve.getMessage(), - cpve.getCause(), cpOriginal, cpSize - (i + 1), - cpve.getReason()); + (cpve.getCause() != null) ? cpve.getCause() : cpve, + cpOriginal, cpSize - (i + 1), cpve.getReason()); } } diff --git a/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java b/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java index 94670e40324..2825e14254f 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java +++ b/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.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 @@ -29,7 +29,6 @@ import java.security.AccessController; import java.security.AlgorithmConstraints; import java.security.PrivilegedAction; import java.security.Security; -import java.util.Map; import java.util.Set; /** @@ -45,8 +44,7 @@ public abstract class AbstractAlgorithmConstraints } // Get algorithm constraints from the specified security property. - private static void loadAlgorithmsMap(Map algorithmsMap, - String propertyName) { + static String[] getAlgorithms(String propertyName) { String property = AccessController.doPrivileged( (PrivilegedAction) () -> Security.getProperty( propertyName)); @@ -68,18 +66,7 @@ public abstract class AbstractAlgorithmConstraints if (algorithmsInProperty == null) { algorithmsInProperty = new String[0]; } - algorithmsMap.put(propertyName, algorithmsInProperty); - } - - static String[] getAlgorithms(Map algorithmsMap, - String propertyName) { - synchronized (algorithmsMap) { - if (!algorithmsMap.containsKey(propertyName)) { - loadAlgorithmsMap(algorithmsMap, propertyName); - } - - return algorithmsMap.get(propertyName); - } + return algorithmsInProperty; } static boolean checkAlgorithm(String[] algorithms, String algorithm, diff --git a/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java b/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java index 4410a3102be..bff76cf1721 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java +++ b/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.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 @@ -40,19 +40,7 @@ public class AlgorithmDecomposer { private static final Pattern pattern = Pattern.compile("with|and|(? - * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" - * so that we can check the "SHA1" and "RSA" algorithm constraints - * separately. - *

        - * Please override the method if need to support more name pattern. - */ - public Set decompose(String algorithm) { - if (algorithm == null || algorithm.length() == 0) { - return new HashSet<>(); - } + private static Set decomposeImpl(String algorithm) { // algorithm/mode/padding String[] transTockens = transPattern.split(algorithm); @@ -79,6 +67,24 @@ public class AlgorithmDecomposer { elements.add(token); } } + return elements; + } + + /** + * Decompose the standard algorithm name into sub-elements. + *

        + * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" + * so that we can check the "SHA1" and "RSA" algorithm constraints + * separately. + *

        + * Please override the method if need to support more name pattern. + */ + public Set decompose(String algorithm) { + if (algorithm == null || algorithm.length() == 0) { + return new HashSet<>(); + } + + Set elements = decomposeImpl(algorithm); // In Java standard algorithm name specification, for different // purpose, the SHA-1 and SHA-2 algorithm names are different. For @@ -130,4 +136,40 @@ public class AlgorithmDecomposer { return elements; } + private static void hasLoop(Set elements, String find, String replace) { + if (elements.contains(find)) { + if (!elements.contains(replace)) { + elements.add(replace); + } + elements.remove(find); + } + } + + /* + * This decomposes a standard name into sub-elements with a consistent + * message digest algorithm name to avoid overly complicated checking. + */ + public static Set decomposeOneHash(String algorithm) { + if (algorithm == null || algorithm.length() == 0) { + return new HashSet<>(); + } + + Set elements = decomposeImpl(algorithm); + + hasLoop(elements, "SHA-1", "SHA1"); + hasLoop(elements, "SHA-224", "SHA224"); + hasLoop(elements, "SHA-256", "SHA256"); + hasLoop(elements, "SHA-384", "SHA384"); + hasLoop(elements, "SHA-512", "SHA512"); + + return elements; + } + + /* + * The provided message digest algorithm name will return a consistent + * naming scheme. + */ + public static String hashName(String algorithm) { + return algorithm.replace("-", ""); + } } diff --git a/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java new file mode 100644 index 00000000000..6bc003054d1 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.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. 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.security.util; + +import java.io.File; +import java.io.FileInputStream; +import java.security.AccessController; +import java.security.KeyStore; +import java.security.PrivilegedAction; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashSet; + +import sun.security.x509.X509CertImpl; + +/** + * The purpose of this class is to determine the trust anchor certificates is in + * the cacerts file. This is used for PKIX CertPath checking. + */ +public class AnchorCertificates { + + private static final Debug debug = Debug.getInstance("certpath"); + private static final String HASH = "SHA-256"; + private static HashSet certs; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + File f = new File(System.getProperty("java.home"), + "lib/security/cacerts"); + KeyStore cacerts; + try { + cacerts = KeyStore.getInstance("JKS"); + try (FileInputStream fis = new FileInputStream(f)) { + cacerts.load(fis, "changeit".toCharArray()); + certs = new HashSet<>(); + Enumeration list = cacerts.aliases(); + String alias; + while (list.hasMoreElements()) { + alias = list.nextElement(); + // Check if this cert is labeled a trust anchor. + if (alias.contains(" [jdk")) { + X509Certificate cert = (X509Certificate) cacerts + .getCertificate(alias); + certs.add(X509CertImpl.getFingerprint(HASH, cert)); + } + } + } + } catch (Exception e) { + if (debug != null) { + debug.println("Error parsing cacerts"); + } + e.printStackTrace(); + } + return null; + } + }); + } + + /** + * Checks if a certificate is a trust anchor. + * + * @param cert the certificate to check + * @return true if the certificate is trusted. + */ + public static boolean contains(X509Certificate cert) { + String key = X509CertImpl.getFingerprint(HASH, cert); + boolean result = certs.contains(key); + if (result && debug != null) { + debug.println("AnchorCertificate.contains: matched " + + cert.getSubjectDN()); + } + return result; + } + + private AnchorCertificates() {} +} diff --git a/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java new file mode 100644 index 00000000000..9f7a938dede --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.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. 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.security.util; + +import java.security.cert.X509Certificate; + +/** + * This class is a wrapper for keeping state and passing objects between PKIX, + * AlgorithmChecker, and DisabledAlgorithmConstraints. + */ +public class CertConstraintParameters { + // A certificate being passed to check against constraints. + private final X509Certificate cert; + + // This is true if the trust anchor in the certificate chain matches a cert + // in AnchorCertificates + private final boolean trustedMatch; + + public CertConstraintParameters(X509Certificate c, boolean match) { + cert = c; + trustedMatch = match; + } + + public CertConstraintParameters(X509Certificate c) { + this(c, false); + } + + // Returns if the trust anchor has a match if anchor checking is enabled. + public boolean isTrustedMatch() { + return trustedMatch; + } + + public X509Certificate getCertificate() { + return cert; + } +} diff --git a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index fd4b198ce11..d4b2a4054b3 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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,12 +28,14 @@ package sun.security.util; import java.security.CryptoPrimitive; import java.security.AlgorithmParameters; import java.security.Key; -import java.util.Locale; -import java.util.Set; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertPathValidatorException.BasicReason; +import java.security.cert.X509Certificate; import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -44,6 +46,7 @@ import java.util.regex.Matcher; * for the syntax of the disabled algorithm string. */ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { + private static final Debug debug = Debug.getInstance("certpath"); // the known security property, jdk.certpath.disabledAlgorithms public static final String PROPERTY_CERTPATH_DISABLED_ALGS = @@ -53,13 +56,8 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { public static final String PROPERTY_TLS_DISABLED_ALGS = "jdk.tls.disabledAlgorithms"; - private static final Map disabledAlgorithmsMap = - new HashMap<>(); - private static final Map keySizeConstraintsMap = - new HashMap<>(); - private final String[] disabledAlgorithms; - private final KeySizeConstraints keySizeConstraints; + private final Constraints algorithmConstraints; /** * Initialize algorithm constraints with the specified security property. @@ -74,11 +72,14 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { public DisabledAlgorithmConstraints(String propertyName, AlgorithmDecomposer decomposer) { super(decomposer); - disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName); - keySizeConstraints = getKeySizeConstraints(disabledAlgorithms, - propertyName); + disabledAlgorithms = getAlgorithms(propertyName); + algorithmConstraints = new Constraints(disabledAlgorithms); } + /* + * This only checks if the algorithm has been completely disabled. If + * there are keysize or other limit, this method allow the algorithm. + */ @Override public final boolean permits(Set primitives, String algorithm, AlgorithmParameters parameters) { @@ -91,11 +92,19 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); } + /* + * Checks if the key algorithm has been disabled or constraints have been + * placed on the key. + */ @Override public final boolean permits(Set primitives, Key key) { return checkConstraints(primitives, "", key, null); } + /* + * Checks if the key algorithm has been disabled or if constraints have + * been placed on the key. + */ @Override public final boolean permits(Set primitives, String algorithm, Key key, AlgorithmParameters parameters) { @@ -107,7 +116,39 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return checkConstraints(primitives, algorithm, key, parameters); } - // Check algorithm constraints + /* + * Check if a x509Certificate object is permitted. Check if all + * algorithms are allowed, certificate constraints, and the + * public key against key constraints. + * + * Uses new style permit() which throws exceptions. + */ + public final void permits(Set primitives, + CertConstraintParameters cp) throws CertPathValidatorException { + checkConstraints(primitives, cp); + } + + /* + * Check if Certificate object is within the constraints. + * Uses new style permit() which throws exceptions. + */ + public final void permits(Set primitives, + X509Certificate cert) throws CertPathValidatorException { + checkConstraints(primitives, new CertConstraintParameters(cert)); + } + + // Check if a string is contained inside the property + public boolean checkProperty(String param) { + param = param.toLowerCase(Locale.ENGLISH); + for (String block : disabledAlgorithms) { + if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) { + return true; + } + } + return false; + } + + // Check algorithm constraints with key and algorithm private boolean checkConstraints(Set primitives, String algorithm, Key key, AlgorithmParameters parameters) { @@ -116,7 +157,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { throw new IllegalArgumentException("The key cannot be null"); } - // check the target algorithm + // check the signature algorithm if (algorithm != null && algorithm.length() != 0) { if (!permits(primitives, algorithm, parameters)) { return false; @@ -129,97 +170,203 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } // check the key constraints - if (keySizeConstraints.disables(key)) { - return false; - } - - return true; + return algorithmConstraints.permits(key); } - private static KeySizeConstraints getKeySizeConstraints( - String[] disabledAlgorithms, String propertyName) { - synchronized (keySizeConstraintsMap) { - if(!keySizeConstraintsMap.containsKey(propertyName)) { - // map the key constraints - KeySizeConstraints keySizeConstraints = - new KeySizeConstraints(disabledAlgorithms); - keySizeConstraintsMap.put(propertyName, keySizeConstraints); - } + /* + * Check algorithm constraints with Certificate + * Uses new style permit() which throws exceptions. + */ + private void checkConstraints(Set primitives, + CertConstraintParameters cp) throws CertPathValidatorException { - return keySizeConstraintsMap.get(propertyName); + X509Certificate cert = cp.getCertificate(); + String algorithm = cert.getSigAlgName(); + + // Check signature algorithm is not disabled + if (!permits(primitives, algorithm, null)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on disabled "+ + "signature algorithm: " + algorithm, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } + + // Check key algorithm is not disabled + if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on disabled "+ + "public key algorithm: " + algorithm, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + + // Check the certificate and key constraints + algorithmConstraints.permits(cp); + } /** - * key constraints + * Key and Certificate Constraints + * + * The complete disabling of an algorithm is not handled by Constraints or + * Constraint classes. That is addressed with + * permit(Set, String, AlgorithmParameters) + * + * When passing a Key to permit(), the boolean return values follow the + * same as the interface class AlgorithmConstraints.permit(). This is to + * maintain compatibility: + * 'true' means the operation is allowed. + * 'false' means it failed the constraints and is disallowed. + * + * When passing CertConstraintParameters through permit(), an exception + * will be thrown on a failure to better identify why the operation was + * disallowed. */ - private static class KeySizeConstraints { - private static final Pattern pattern = Pattern.compile( - "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); - private Map> constraintsMap = - Collections.synchronizedMap( - new HashMap>()); + private static class Constraints { + private Map> constraintsMap = new HashMap<>(); + private static final Pattern keySizePattern = Pattern.compile( + "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); - public KeySizeConstraints(String[] restrictions) { - for (String restriction : restrictions) { - if (restriction == null || restriction.isEmpty()) { + public Constraints(String[] constraintArray) { + for (String constraintEntry : constraintArray) { + if (constraintEntry == null || constraintEntry.isEmpty()) { continue; } - Matcher matcher = pattern.matcher(restriction); - if (matcher.matches()) { - String algorithm = matcher.group(1); + constraintEntry = constraintEntry.trim(); + if (debug != null) { + debug.println("Constraints: " + constraintEntry); + } - KeySizeConstraint.Operator operator = - KeySizeConstraint.Operator.of(matcher.group(2)); - int length = Integer.parseInt(matcher.group(3)); + // Check if constraint is a complete disabling of an + // algorithm or has conditions. + String algorithm; + String policy; + int space = constraintEntry.indexOf(' '); + if (space > 0) { + algorithm = AlgorithmDecomposer.hashName( + constraintEntry.substring(0, space). + toUpperCase(Locale.ENGLISH)); + policy = constraintEntry.substring(space + 1); + } else { + constraintsMap.computeIfAbsent( + constraintEntry.toUpperCase(Locale.ENGLISH), + k -> new HashSet<>()); + continue; + } - algorithm = algorithm.toLowerCase(Locale.ENGLISH); + // Convert constraint conditions into Constraint classes + Constraint c, lastConstraint = null; + // Allow only one jdkCA entry per constraint entry + boolean jdkCALimit = false; - synchronized (constraintsMap) { - if (!constraintsMap.containsKey(algorithm)) { - constraintsMap.put(algorithm, - new HashSet()); + for (String entry : policy.split("&")) { + entry = entry.trim(); + + Matcher matcher = keySizePattern.matcher(entry); + if (matcher.matches()) { + if (debug != null) { + debug.println("Constraints set to keySize: " + + entry); } + c = new KeySizeConstraint(algorithm, + KeySizeConstraint.Operator.of(matcher.group(1)), + Integer.parseInt(matcher.group(2))); - Set constraintSet = - constraintsMap.get(algorithm); - KeySizeConstraint constraint = - new KeySizeConstraint(operator, length); - constraintSet.add(constraint); + } else if (entry.equalsIgnoreCase("jdkCA")) { + if (debug != null) { + debug.println("Constraints set to jdkCA."); + } + if (jdkCALimit) { + throw new IllegalArgumentException("Only one " + + "jdkCA entry allowed in property. " + + "Constraint: " + constraintEntry); + } + c = new jdkCAConstraint(algorithm); + jdkCALimit = true; + } else { + throw new IllegalArgumentException("Error in security" + + " property. Constraint unknown: " + entry); } + + // Link multiple conditions for a single constraint + // into a linked list. + if (lastConstraint == null) { + if (!constraintsMap.containsKey(algorithm)) { + constraintsMap.putIfAbsent(algorithm, + new HashSet<>()); + } + constraintsMap.get(algorithm).add(c); + } else { + lastConstraint.nextConstraint = c; + } + lastConstraint = c; } } } - // Does this KeySizeConstraints disable the specified key? - public boolean disables(Key key) { - String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH); - synchronized (constraintsMap) { - if (constraintsMap.containsKey(algorithm)) { - Set constraintSet = - constraintsMap.get(algorithm); - for (KeySizeConstraint constraint : constraintSet) { - if (constraint.disables(key)) { - return true; - } + // Get applicable constraints based off the signature algorithm + private Set getConstraints(String algorithm) { + return constraintsMap.get(algorithm); + } + + // Check if KeySizeConstraints permit the specified key + public boolean permits(Key key) { + Set set = getConstraints(key.getAlgorithm()); + if (set == null) { + return true; + } + for (Constraint constraint : set) { + if (!constraint.permits(key)) { + if (debug != null) { + debug.println("keySizeConstraint: failed key " + + "constraint check " + KeyUtil.getKeySize(key)); } + return false; } } + return true; + } - return false; + // Check if constraints permit this cert. + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + X509Certificate cert = cp.getCertificate(); + + if (debug != null) { + debug.println("Constraints.permits(): " + cert.getSigAlgName()); + } + + // Get all signature algorithms to check for constraints + Set algorithms = + AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); + if (algorithms == null || algorithms.isEmpty()) { + return; + } + + // Attempt to add the public key algorithm to the set + algorithms.add(cert.getPublicKey().getAlgorithm()); + + // Check all applicable constraints + for (String algorithm : algorithms) { + Set set = getConstraints(algorithm); + if (set == null) { + continue; + } + for (Constraint constraint : set) { + constraint.permits(cp); + } + } } } - /** - * Key size constraint. - * - * e.g. "keysize <= 1024" - */ - private static class KeySizeConstraint { + // Abstract class for algorithm constraint checking + private abstract static class Constraint { + String algorithm; + Constraint nextConstraint = null; + // operator - static enum Operator { + enum Operator { EQ, // "==" NE, // "!=" LT, // "<" @@ -243,16 +390,77 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { return GE; } - throw new IllegalArgumentException( - s + " is not a legal Operator"); + throw new IllegalArgumentException("Error in security " + + "property. " + s + " is not a legal Operator"); } } + /** + * Check if an algorithm constraint permit this key to be used. + * @param key Public key + * @return true if constraints do not match + */ + public boolean permits(Key key) { + return true; + } + + /** + * Check if an algorithm constraint is permit this certificate to + * be used. + * @param cp CertificateParameter containing certificate and state info + * @return true if constraints do not match + */ + public abstract void permits(CertConstraintParameters cp) + throws CertPathValidatorException; + } + + /* + * This class contains constraints dealing with the certificate chain + * of the certificate. + */ + private static class jdkCAConstraint extends Constraint { + jdkCAConstraint(String algo) { + algorithm = algo; + } + + /* + * Check if each constraint fails and check if there is a linked + * constraint Any permitted constraint will exit the linked list + * to allow the operation. + */ + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + if (debug != null) { + debug.println("jdkCAConstraints.permits(): " + algorithm); + } + + // Return false if the chain has a trust anchor in cacerts + if (cp.isTrustedMatch()) { + if (nextConstraint != null) { + nextConstraint.permits(cp); + return; + } + throw new CertPathValidatorException( + "Algorithm constraints check failed on certificate " + + "anchor limits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + } + } + + + /* + * This class contains constraints dealing with the key size + * support limits per algorithm. e.g. "keySize <= 1024" + */ + private static class KeySizeConstraint extends Constraint { + private int minSize; // the minimal available key size private int maxSize; // the maximal available key size private int prohibitedSize = -1; // unavailable key sizes - public KeySizeConstraint(Operator operator, int length) { + public KeySizeConstraint(String algo, Operator operator, int length) { + algorithm = algo; switch (operator) { case EQ: // an unavailable key size this.minSize = 0; @@ -286,21 +494,59 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } } - // Does this key constraint disable the specified key? - public boolean disables(Key key) { - int size = KeyUtil.getKeySize(key); + /* + * If we are passed a certificate, extract the public key and use it. + * + * Check if each constraint fails and check if there is a linked + * constraint Any permitted constraint will exit the linked list + * to allow the operation. + */ + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + if (!permitsImpl(cp.getCertificate().getPublicKey())) { + if (nextConstraint != null) { + nextConstraint.permits(cp); + return; + } + throw new CertPathValidatorException( + "Algorithm constraints check failed on keysize limits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + } + + // Check if key constraint disable the specified key + // Uses old style permit() + public boolean permits(Key key) { + // If we recursively find a constraint that permits us to use + // this key, return true and skip any other constraint checks. + if (nextConstraint != null && nextConstraint.permits(key)) { + return true; + } + if (debug != null) { + debug.println("KeySizeConstraints.permits(): " + algorithm); + } + + return permitsImpl(key); + } + + private boolean permitsImpl(Key key) { + // Verify this constraint is for this public key algorithm + if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) { + return true; + } + + int size = KeyUtil.getKeySize(key); if (size == 0) { - return true; // we don't allow any key of size 0. + return false; // we don't allow any key of size 0. } else if (size > 0) { - return ((size < minSize) || (size > maxSize) || + return !((size < minSize) || (size > maxSize) || (prohibitedSize == size)); } // Otherwise, the key size is not accessible. Conservatively, // please don't disable such keys. - return false; + return true; } } - } diff --git a/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java b/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java index d8803348a5d..7c8fe9af51d 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java +++ b/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.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 @@ -28,8 +28,6 @@ package sun.security.util; import java.security.AlgorithmParameters; import java.security.CryptoPrimitive; import java.security.Key; -import java.util.HashMap; -import java.util.Map; import java.util.Set; import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms; @@ -42,15 +40,12 @@ public class LegacyAlgorithmConstraints extends AbstractAlgorithmConstraints { public static final String PROPERTY_TLS_LEGACY_ALGS = "jdk.tls.legacyAlgorithms"; - private static final Map legacyAlgorithmsMap = - new HashMap<>(); - private final String[] legacyAlgorithms; public LegacyAlgorithmConstraints(String propertyName, AlgorithmDecomposer decomposer) { super(decomposer); - legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName); + legacyAlgorithms = getAlgorithms(propertyName); } @Override diff --git a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java index 0e4da831a83..8d496ad85c4 100644 --- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, 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 @@ -1924,17 +1924,18 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { public String getFingerprint(String algorithm) { return fingerprints.computeIfAbsent(algorithm, - x -> getCertificateFingerPrint(x)); + x -> getFingerprint(x, this)); } /** * Gets the requested finger print of the certificate. The result * only contains 0-9 and A-F. No small case, no colon. */ - private String getCertificateFingerPrint(String mdAlg) { + public static String getFingerprint(String algorithm, + X509Certificate cert) { try { - byte[] encCertInfo = getEncoded(); - MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] encCertInfo = cert.getEncoded(); + MessageDigest md = MessageDigest.getInstance(algorithm); byte[] digest = md.digest(encCertInfo); StringBuilder sb = new StringBuilder(digest.length * 2); for (int i = 0; i < digest.length; i++) { diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 6a9803bf425..fa2da13c195 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -497,13 +497,13 @@ krb5.kdc.bad.policy = tryLast # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -520,6 +520,9 @@ krb5.kdc.bad.policy = tryLast # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -542,6 +545,29 @@ krb5.kdc.bad.policy = tryLast # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +#   "jdkCA" prohibits the specified algorithm only if the algorithm is used +#     in a certificate chain that terminates at a marked trust anchor in the +#     lib/security/cacerts keystore.  All other chains are not affected. +#     If the jdkCA constraint is not set, then all chains using the +#     specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +#     Example:  To apply this constraint to SHA-1 certificates, include +#     the following:  "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # diff --git a/jdk/test/sun/security/tools/jarsigner/Warning.java b/jdk/test/sun/security/tools/jarsigner/Warning.java index cd8607c8be0..70233634e0b 100644 --- a/jdk/test/sun/security/tools/jarsigner/Warning.java +++ b/jdk/test/sun/security/tools/jarsigner/Warning.java @@ -89,7 +89,7 @@ public class Warning { issueCert("c"); run("jarsigner", "a.jar c") .shouldContain("chain is not validated. " + - "Reason: algorithm constraints check failed"); + "Reason: Algorithm constraints check failed"); recreateJar(); From ae6a62a6c83f249eab34cad57167e6d601745375 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 2 May 2016 18:10:36 -0700 Subject: [PATCH 206/225] 8155516: Suppress warnings from uses of deprecated Class.newInstance langtools Reviewed-by: jjg --- .../share/classes/javax/tools/ToolProvider.java | 4 +++- .../tools/javac/processing/JavacProcessingEnvironment.java | 6 ++++-- .../share/classes/com/sun/tools/sjavac/options/Option.java | 3 ++- .../internal/doclets/toolkit/taglets/TagletManager.java | 1 + .../share/classes/jdk/javadoc/internal/tool/Start.java | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 1909ce4285c..f438198fa33 100644 --- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -123,7 +123,9 @@ public class ToolProvider { private static T getSystemTool(Class clazz, String moduleName, String className) { if (useLegacy) { try { - return Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance(); + @SuppressWarnings("deprecation") + T result = Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance(); + return result; } catch (ReflectiveOperationException e) { throw new Error(e); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 30da7072e54..817e5273f52 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -282,6 +282,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (options.isSet(XPRINT)) { try { + @SuppressWarnings("deprecation") Processor processor = PrintingProcessor.class.newInstance(); processorIterator = List.of(processor).iterator(); } catch (Throwable t) { @@ -549,8 +550,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea try { Class processorClass = processorCL.loadClass(processorName); ensureReadable(processorClass); - processor = - (Processor) (processorClass.newInstance()); + @SuppressWarnings("deprecation") + Object tmp = processorClass.newInstance(); + processor = (Processor) tmp; } catch (ClassNotFoundException cnfe) { log.error("proc.processor.not.found", processorName); return false; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java index d64d3182cc0..9533e98c191 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.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 @@ -151,6 +151,7 @@ public enum Option { // Construct transformer try { Class trCls = Class.forName(classname); + @SuppressWarnings("deprecation") Transformer transformer = (Transformer) trCls.newInstance(); transformer.setExtra(extra); helper.addTransformer(suffix, transformer); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java index ec809050f3c..1b96e61b134 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java @@ -246,6 +246,7 @@ public class TagletManager { } tagClassLoader = fileManager.getClassLoader(TAGLET_PATH); Class customTagClass = tagClassLoader.loadClass(classname); + @SuppressWarnings("deprecation") Object instance = customTagClass.newInstance(); Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance); String tname = newLegacy.getName(); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index d998e077663..2cca6849e26 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -270,7 +270,9 @@ public class Start extends ToolOption.Helper { initMessager(); messager.setLocale(locale); try { - doclet = (Doclet) docletClass.newInstance(); + @SuppressWarnings("deprecation") + Object o = docletClass.newInstance(); + doclet = (Doclet) o; } catch (InstantiationException | IllegalAccessException exc) { exc.printStackTrace(); if (!apiMode) { From 39846dcf8d30421bc1e1bca9b0c49a8d96dd5cd8 Mon Sep 17 00:00:00 2001 From: Alex Kashchenko Date: Tue, 3 May 2016 07:44:52 +0100 Subject: [PATCH 207/225] 8153925: (fs) WatchService hangs on GetOverlappedResult and locks directory (win) Co-authored-by: Thomas Mader Reviewed-by: alanb --- .../sun/nio/fs/WindowsWatchService.java | 26 ++++- .../file/WatchService/DeleteInterference.java | 102 ++++++++++++++++++ 2 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/nio/file/WatchService/DeleteInterference.java diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java index 63b2112aca1..00e68fb785b 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -113,6 +113,10 @@ class WindowsWatchService // completion key (used to map I/O completion to WatchKey) private int completionKey; + // flag indicates that ReadDirectoryChangesW failed + // and overlapped I/O operation wasn't started + private boolean errorStartingOverlapped; + WindowsWatchKey(Path dir, AbstractWatchService watcher, FileKey fileKey) @@ -175,6 +179,14 @@ class WindowsWatchService return completionKey; } + void setErrorStartingOverlapped(boolean value) { + errorStartingOverlapped = value; + } + + boolean isErrorStartingOverlapped() { + return errorStartingOverlapped; + } + // Invalidate the key, assumes that resources have been released void invalidate() { ((WindowsWatchService)watcher()).poller.releaseResources(this); @@ -182,6 +194,7 @@ class WindowsWatchService buffer = null; countAddress = 0; overlappedAddress = 0; + errorStartingOverlapped = false; } @Override @@ -455,11 +468,13 @@ class WindowsWatchService * resources. */ private void releaseResources(WindowsWatchKey key) { - try { - CancelIo(key.handle()); - GetOverlappedResult(key.handle(), key.overlappedAddress()); - } catch (WindowsException expected) { - // expected as I/O operation has been cancelled + if (!key.isErrorStartingOverlapped()) { + try { + CancelIo(key.handle()); + GetOverlappedResult(key.handle(), key.overlappedAddress()); + } catch (WindowsException expected) { + // expected as I/O operation has been cancelled + } } CloseHandle(key.handle()); closeAttachedEvent(key.overlappedAddress()); @@ -628,6 +643,7 @@ class WindowsWatchService } catch (WindowsException x) { // no choice but to cancel key criticalError = true; + key.setErrorStartingOverlapped(true); } } if (criticalError) { diff --git a/jdk/test/java/nio/file/WatchService/DeleteInterference.java b/jdk/test/java/nio/file/WatchService/DeleteInterference.java new file mode 100644 index 00000000000..6a11271a546 --- /dev/null +++ b/jdk/test/java/nio/file/WatchService/DeleteInterference.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Red Hat, Inc. and/or its affiliates. + * 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. + */ + +/** + * @test + * @bug 8153925 + * @summary Tests potential interference between a thread creating and closing + * a WatchService with another thread that is deleting and re-creating the + * directory at around the same time. This scenario tickled a timing bug + * in the Windows implementation. + */ + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.WatchService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static java.nio.file.StandardWatchEventKinds.*; + +public class DeleteInterference { + + private static final int ITERATIONS_COUNT = 1024; + + /** + * Execute two tasks in a thread pool. One task loops on creating and + * closing a WatchService, the other task deletes and re-creates the + * directory. + */ + public static void main(String[] args) throws Exception { + Path dir = Files.createTempDirectory("work"); + ExecutorService pool = Executors.newCachedThreadPool(); + try { + Future task1 = pool.submit(() -> openAndCloseWatcher(dir)); + Future task2 = pool.submit(() -> deleteAndRecreateDirectory(dir)); + task1.get(); + task2.get(); + } finally { + pool.shutdown(); + deleteFileTree(dir); + } + } + + private static void openAndCloseWatcher(Path dir) { + FileSystem fs = FileSystems.getDefault(); + for (int i = 0; i < ITERATIONS_COUNT; i++) { + try (WatchService watcher = fs.newWatchService()) { + dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); + } catch (IOException ioe) { + // ignore + } + } + } + + private static void deleteAndRecreateDirectory(Path dir) { + for (int i = 0; i < ITERATIONS_COUNT; i++) { + try { + deleteFileTree(dir); + Path subdir = Files.createDirectories(dir.resolve("subdir")); + Files.createFile(subdir.resolve("test")); + } catch (IOException ioe) { + // ignore + } + } + } + + private static void deleteFileTree(Path file) { + try { + if (Files.isDirectory(file)) { + try (DirectoryStream stream = Files.newDirectoryStream(file)) { + for (Path pa : stream) { + deleteFileTree(pa); + } + } + } + Files.delete(file); + } catch (IOException ioe) { + // ignore + } + } +} From 36e0820801507c8937a649909dde605984ded79b Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 3 May 2016 09:09:57 +0100 Subject: [PATCH 208/225] 8154956: Module system implementation refresh (4/2016) Co-authored-by: Mandy Chung Co-authored-by: Erik Joelsson Co-authored-by: Chris Hegarty Co-authored-by: Peter Levart Co-authored-by: Sundararajan Athijegannathan Reviewed-by: alanb, mchung, chegar, redestad --- jdk/make/Tools.gmk | 6 + jdk/make/gendata/GendataBreakIterator.gmk | 11 +- jdk/make/launcher/Launcher-java.desktop.gmk | 2 +- jdk/make/launcher/Launcher-java.scripting.gmk | 1 + jdk/make/launcher/Launcher-jdk.compiler.gmk | 3 +- jdk/make/launcher/Launcher-jdk.javadoc.gmk | 1 + jdk/make/launcher/Launcher-jdk.jlink.gmk | 1 + .../Launcher-jdk.scripting.nashorn.shell.gmk | 2 +- .../share/classes/java/lang/ClassLoader.java | 2 +- .../share/classes/java/lang/System.java | 5 - .../java/lang/module/Configuration.java | 44 +- .../java/lang/module/ModuleDescriptor.java | 64 +- .../java/lang/module/ModuleFinder.java | 13 +- .../classes/java/lang/module/ModuleInfo.java | 7 +- .../classes/java/lang/module/ModulePath.java | 117 ++-- .../java/lang/module/ModuleReader.java | 9 +- .../java/lang/module/ModuleReference.java | 62 +- .../java/lang/module/ModuleReferences.java | 17 +- .../classes/java/lang/module/Resolver.java | 204 +++--- .../java/lang/module/SystemModuleFinder.java | 19 +- .../classes/java/lang/reflect/Layer.java | 54 ++ .../classes/java/lang/reflect/Module.java | 245 +++---- .../java/lang/reflect/WeakPairMap.java | 354 +++++++++++ .../classes/java/util/ServiceLoader.java | 55 +- .../jdk/internal/loader/BootLoader.java | 4 +- .../internal/loader/BuiltinClassLoader.java | 2 +- .../internal/misc/JavaLangModuleAccess.java | 39 +- .../misc/JavaLangReflectModuleAccess.java | 18 +- .../classes/jdk/internal/module/Builder.java | 27 +- .../internal/module/ClassFileAttributes.java | 14 +- .../jdk/internal/module/ModuleBootstrap.java | 291 +++++---- .../module/{Hasher.java => ModuleHashes.java} | 97 +-- .../internal/module/ModuleInfoExtender.java | 9 +- .../jdk/internal/module/ModuleInfoWriter.java | 26 +- .../jdk/internal/module/ModulePatcher.java | 65 +- .../classes/jdk/internal/module/Modules.java | 13 +- .../jdk/internal/module/ServicesCatalog.java | 133 ++-- .../jdk/internal/module/SystemModules.java | 14 +- .../java.base/share/classes/module-info.java | 2 + .../launcher/resources/launcher.properties | 7 +- .../sun/tools/jar/GNUStyleOptions.java | 4 +- .../share/classes/sun/tools/jar/Main.java | 300 ++++++--- .../sun/tools/jar/resources/jar.properties | 14 +- .../jlink/builder/DefaultImageBuilder.java | 71 ++- .../jdk/tools/jlink/builder/ImageBuilder.java | 8 +- .../jlink/internal/ImageFileCreator.java | 2 +- .../internal/ImagePluginConfiguration.java | 15 +- .../jlink/internal/ImagePluginStack.java | 16 +- .../jdk/tools/jlink/internal/JlinkTask.java | 65 +- .../jdk/tools/jlink/internal/TaskHelper.java | 10 +- .../packager/AppRuntimeImageBuilder.java | 146 +++++ .../plugins/DefaultCompressPlugin.java | 2 +- .../internal/plugins/ExcludeVMPlugin.java | 2 +- .../plugins/IncludeLocalesPlugin.java | 2 +- .../internal/plugins/OptimizationPlugin.java | 2 +- .../plugins/SystemModuleDescriptorPlugin.java | 121 +++- .../jdk/tools/jlink/plugin/Plugin.java | 5 + .../tools/jlink/resources/jlink.properties | 3 - .../classes/jdk/tools/jmod/JmodTask.java | 599 ++++++++++++------ .../jdk/tools/jmod/resources/jmod.properties | 33 +- jdk/test/TEST.ROOT | 7 +- .../com/sun/corba/5036554/TestCorbaBug.sh | 4 +- .../7130985/CorbaExceptionsCompileTest.java | 3 +- .../corba/se/impl/io/HookPutFieldsTest.java | 2 + .../corba/se/impl/orb/SetDefaultORBTest.java | 3 +- .../com/sun/net/httpserver/bugs/B6373555.java | 1 - .../java/lang/invoke/VarargsArrayTest.java | 2 +- .../java/lang/module/ModuleFinderTest.java | 44 +- .../lang/reflect/WeakPairMap/Driver.java} | 17 +- .../java/lang/reflect/WeakPairMapTest.java | 175 +++++ .../util/ResourceBundle/Bug6299235Test.sh | 2 +- .../crypto/Cipher/CipherStreamClose.java | 2 + .../ConcurrentHashMapTest.java | 8 +- .../javax/smartcardio/CommandAPDUTest.java | 3 +- .../javax/smartcardio/HistoricalBytes.java | 4 +- .../javax/smartcardio/ResponseAPDUTest.java | 3 +- jdk/test/javax/smartcardio/Serialize.java | 2 + .../smartcardio/TerminalFactorySpiTest.java | 3 +- .../javax/smartcardio/TestCardPermission.java | 2 + .../javax/smartcardio/TestCommandAPDU.java | 2 + .../transaction/testng/Driver.java} | 24 +- .../javax/transaction/testng/TEST.properties | 4 - .../xjc/8032884/XjcOptionalPropertyTest.java | 1 + jdk/test/javax/xml/jaxp/common/8035437/run.sh | 4 +- jdk/test/javax/xml/soap/XmlTest.java | 2 + .../javax/xml/soap/spi/SAAJFactoryTest.java | 44 +- jdk/test/javax/xml/ws/8043129/MailTest.java | 4 +- .../javax/xml/ws/clientjar/TestWsImport.java | 3 +- jdk/test/javax/xml/ws/publish/WSTest.java | 3 +- jdk/test/javax/xml/ws/xsanymixed/Test.java | 3 +- .../pkcs11/KeyStore/SecretKeysBasic.java | 8 +- .../security/provider/PolicyFile/Modules.java | 4 +- jdk/test/tools/jar/modularJar/Basic.java | 78 +-- .../modularJar/src/bar/jdk/test/bar/Bar.java | 9 +- .../tools/jlink/ImageFileCreatorTest.java | 6 +- jdk/test/tools/jlink/IntegrationTest.java | 10 +- jdk/test/tools/jlink/JLink2Test.java | 31 - jdk/test/tools/jlink/JLinkTest.java | 2 +- jdk/test/tools/jlink/hashes/HashesTest.java | 160 ----- .../jlink/plugins/FileCopierPluginTest.java | 5 +- jdk/test/tools/jmod/JmodNegativeTest.java | 32 +- jdk/test/tools/jmod/hashes/HashesTest.java | 213 +++++++ .../hashes/src/m1/module-info.java | 2 +- .../hashes/src/m1/org/m1/Main.java | 2 +- .../hashes/src}/m2/module-info.java | 0 .../hashes/src/m2/org/m2/Util.java | 0 .../hashes/src/m3}/module-info.java | 4 +- .../hashes/src/m3/org/m3}/Name.java | 4 +- .../hashes/src/org.bar}/module-info.java | 6 +- .../hashes/src/org.foo}/module-info.java | 6 +- jdk/test/tools/launcher/ToolsOpts.java | 15 +- .../launcher/modules/addmods/AddModsTest.java | 188 ++++-- .../modules/addmods/src/lib/jdk/lib/Util.java | 32 - .../addmods/src/logger/logger/Logger.java | 30 + .../src/{lib => logger}/module-info.java | 8 +- .../modules/addmods/src/test/module-info.java | 24 + .../modules/addmods/src/test/test/Main.java} | 19 +- .../modules/addreads/AddReadsTest.java | 2 +- .../launcher/modules/patch/PatchTest.java | 63 +- jdk/test/tools/lib/tests/JImageGenerator.java | 14 +- 120 files changed, 3161 insertions(+), 1676 deletions(-) create mode 100644 jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java rename jdk/src/java.base/share/classes/jdk/internal/module/{Hasher.java => ModuleHashes.java} (64%) create mode 100644 jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java rename jdk/test/{tools/launcher/modules/addmods/src/app/Main.java => java/lang/reflect/WeakPairMap/Driver.java} (78%) create mode 100644 jdk/test/java/lang/reflect/WeakPairMap/java.base/java/lang/reflect/WeakPairMapTest.java rename jdk/test/{tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java => javax/transaction/testng/Driver.java} (55%) delete mode 100644 jdk/test/javax/transaction/testng/TEST.properties delete mode 100644 jdk/test/tools/jlink/hashes/HashesTest.java create mode 100644 jdk/test/tools/jmod/hashes/HashesTest.java rename jdk/test/tools/{jlink => jmod}/hashes/src/m1/module-info.java (97%) rename jdk/test/tools/{jlink => jmod}/hashes/src/m1/org/m1/Main.java (97%) rename jdk/test/tools/{jlink/hashes/newsrc => jmod/hashes/src}/m2/module-info.java (100%) rename jdk/test/tools/{jlink => jmod}/hashes/src/m2/org/m2/Util.java (100%) rename jdk/test/tools/{jlink/hashes/src/m2 => jmod/hashes/src/m3}/module-info.java (97%) rename jdk/test/tools/{jlink/hashes/src/not_matched/org/not_matched => jmod/hashes/src/m3/org/m3}/Name.java (95%) rename jdk/test/tools/{jlink/hashes/newsrc/not_matched => jmod/hashes/src/org.bar}/module-info.java (89%) rename jdk/test/tools/{jlink/hashes/src/not_matched => jmod/hashes/src/org.foo}/module-info.java (89%) delete mode 100644 jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java create mode 100644 jdk/test/tools/launcher/modules/addmods/src/logger/logger/Logger.java rename jdk/test/tools/launcher/modules/addmods/src/{lib => logger}/module-info.java (90%) create mode 100644 jdk/test/tools/launcher/modules/addmods/src/test/module-info.java rename jdk/test/tools/{jlink/hashes/newsrc/m2/org/m2/Util.java => launcher/modules/addmods/src/test/test/Main.java} (71%) diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk index 1ae471d72b3..62e5f3042e2 100644 --- a/jdk/make/Tools.gmk +++ b/jdk/make/Tools.gmk @@ -96,7 +96,13 @@ TOOL_CHARSETMAPPING = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classe TOOL_SPP = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.spp.Spp # Nimbus is used somewhere in the swing build. + +ifeq ($(BOOT_JDK_MODULAR), true) + COMPILENIMBUS_ADD_MODS := -addmods java.xml.bind +endif + TOOL_GENERATENIMBUS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ + $(COMPILENIMBUS_ADD_MODS) \ build.tools.generatenimbus.Generator TOOL_WRAPPERGENERATOR = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ diff --git a/jdk/make/gendata/GendataBreakIterator.gmk b/jdk/make/gendata/GendataBreakIterator.gmk index 5ee97d77595..06d3c2ac490 100644 --- a/jdk/make/gendata/GendataBreakIterator.gmk +++ b/jdk/make/gendata/GendataBreakIterator.gmk @@ -62,10 +62,13 @@ $(eval $(call SetupJavaCompilation,BUILD_BREAKITERATOR_LD, \ BIN := $(BREAK_ITERATOR_CLASSES)/jdk.localedata)) ifeq ($(BOOT_JDK_MODULAR), true) - BREAK_ITERATOR_BOOTCLASSPATH := -Xpatch:$(BREAK_ITERATOR_CLASSES) \ - -XaddExports:java.base/sun.text=ALL-UNNAMED \ - -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \ - -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED + BREAK_ITERATOR_BOOTCLASSPATH := \ + -Xpatch:java.base=$(BREAK_ITERATOR_CLASSES)/java.base \ + -Xpatch:jdk.localedata=$(BREAK_ITERATOR_CLASSES)/jdk.localedata \ + -XaddExports:java.base/sun.text=ALL-UNNAMED \ + -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \ + -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \ + # else BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \ $(BREAK_ITERATOR_CLASSES)/java.base \ diff --git a/jdk/make/launcher/Launcher-java.desktop.gmk b/jdk/make/launcher/Launcher-java.desktop.gmk index c9f730f4d71..b6b95cb24ed 100644 --- a/jdk/make/launcher/Launcher-java.desktop.gmk +++ b/jdk/make/launcher/Launcher-java.desktop.gmk @@ -31,7 +31,7 @@ $(eval $(call IncludeCustomExtension, jdk, launcher/Launcher-java.desktop.gmk)) ifndef BUILD_HEADLESS_ONLY $(eval $(call SetupBuildLauncher, appletviewer, \ MAIN_CLASS := sun.applet.Main, \ - JAVA_ARGS := -addmods ALL-SYSTEM, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ LIBS_unix := $(X_LIBS), \ )) endif diff --git a/jdk/make/launcher/Launcher-java.scripting.gmk b/jdk/make/launcher/Launcher-java.scripting.gmk index bf8f97084ec..6f3f59da268 100644 --- a/jdk/make/launcher/Launcher-java.scripting.gmk +++ b/jdk/make/launcher/Launcher-java.scripting.gmk @@ -27,4 +27,5 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jrunscript, \ MAIN_CLASS := com.sun.tools.script.shell.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.compiler.gmk b/jdk/make/launcher/Launcher-jdk.compiler.gmk index d1947dae9f2..0259eb0ff8c 100644 --- a/jdk/make/launcher/Launcher-jdk.compiler.gmk +++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk @@ -27,7 +27,8 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, javac, \ MAIN_CLASS := com.sun.tools.javac.Main, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.javadoc.gmk b/jdk/make/launcher/Launcher-jdk.javadoc.gmk index afdb687b0ab..365443618f2 100644 --- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk +++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk @@ -27,6 +27,7 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, javadoc, \ MAIN_CLASS := jdk.javadoc.internal.tool.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ )) diff --git a/jdk/make/launcher/Launcher-jdk.jlink.gmk b/jdk/make/launcher/Launcher-jdk.jlink.gmk index acf8228b6c4..b1edcbc93c0 100644 --- a/jdk/make/launcher/Launcher-jdk.jlink.gmk +++ b/jdk/make/launcher/Launcher-jdk.jlink.gmk @@ -32,6 +32,7 @@ $(eval $(call SetupBuildLauncher, jimage,\ $(eval $(call SetupBuildLauncher, jlink,\ MAIN_CLASS := jdk.tools.jlink.internal.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DENABLE_ARG_FILES \ -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ diff --git a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk index 3dd56d3a554..b6349b56365 100644 --- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk +++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk @@ -27,6 +27,6 @@ include LauncherCommon.gmk $(eval $(call SetupBuildLauncher, jjs, \ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ - JAVA_ARGS := -addmods ALL-SYSTEM, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DENABLE_ARG_FILES, \ )) 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 61123302a3c..013912384d8 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -2615,7 +2615,7 @@ public abstract class ClassLoader { ServicesCatalog createOrGetServicesCatalog() { ServicesCatalog catalog = servicesCatalog; if (catalog == null) { - catalog = new ServicesCatalog(); + catalog = ServicesCatalog.create(); boolean set = trySetObjectField("servicesCatalog", catalog); if (!set) { // beaten by someone else 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 2ddd37f5da1..9b902f89f45 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -69,7 +69,6 @@ import jdk.internal.logger.LazyLoggers; import jdk.internal.logger.LocalizedLoggerWrapper; import jdk.internal.module.ModuleBootstrap; -import jdk.internal.module.Modules; import jdk.internal.module.ServicesCatalog; /** @@ -1917,10 +1916,6 @@ public final class System { // initialize the module system System.bootLayer = ModuleBootstrap.boot(); - // base module needs to be loose (CODETOOLS-7901619) - Module base = Object.class.getModule(); - Modules.addReads(base, null); - // module system initialized VM.initLevel(2); } diff --git a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java index ae9a2313ff0..4b6ab934dcf 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java +++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java @@ -25,6 +25,7 @@ package java.lang.module; +import java.io.PrintStream; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -183,17 +184,20 @@ public final class Configuration { this.nameToModule = Collections.emptyMap(); } - private Configuration(Configuration parent, Resolver resolver) { - Map> graph = resolver.finish(this); + private Configuration(Configuration parent, + Resolver resolver, + boolean check) + { + Map> g = resolver.finish(this, check); Map nameToModule = new HashMap<>(); - for (ResolvedModule resolvedModule : graph.keySet()) { + for (ResolvedModule resolvedModule : g.keySet()) { nameToModule.put(resolvedModule.name(), resolvedModule); } this.parent = parent; - this.graph = graph; - this.modules = Collections.unmodifiableSet(graph.keySet()); + this.graph = g; + this.modules = Collections.unmodifiableSet(g.keySet()); this.nameToModule = Collections.unmodifiableMap(nameToModule); } @@ -283,10 +287,10 @@ public final class Configuration { Objects.requireNonNull(after); Objects.requireNonNull(roots); - Resolver resolver = new Resolver(before, this, after); + Resolver resolver = new Resolver(before, this, after, null); resolver.resolveRequires(roots); - return new Configuration(this, resolver); + return new Configuration(this, resolver, true); } @@ -340,10 +344,32 @@ public final class Configuration { Objects.requireNonNull(after); Objects.requireNonNull(roots); - Resolver resolver = new Resolver(before, this, after); + Resolver resolver = new Resolver(before, this, after, null); resolver.resolveRequires(roots).resolveUses(); - return new Configuration(this, resolver); + return new Configuration(this, resolver, true); + } + + + /** + * Resolves a collection of root modules, with service binding, and with + * the empty configuration as its parent. The post resolution checks + * are optionally run. + * + * This method is used to create the configuration for the boot layer. + */ + static Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection roots, + boolean check, + PrintStream traceOutput) + { + Configuration parent = empty(); + + Resolver resolver + = new Resolver(finder, parent, ModuleFinder.empty(), traceOutput); + resolver.resolveRequires(roots).resolveUses(); + + return new Configuration(parent, resolver, check); } diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java index 495f371422f..7c14e386d53 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java @@ -27,13 +27,17 @@ package java.lang.module; import java.io.InputStream; import java.io.IOException; +import java.io.PrintStream; import java.io.UncheckedIOException; +import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -45,7 +49,7 @@ import static jdk.internal.module.Checks.*; import static java.util.Objects.*; import jdk.internal.module.Checks; -import jdk.internal.module.Hasher.DependencyHashes; +import jdk.internal.module.ModuleHashes; /** @@ -372,8 +376,9 @@ public class ModuleDescriptor private Provides(String service, Set providers, boolean check) { this.service = check ? requireServiceTypeName(service) : service; - providers = check ? Collections.unmodifiableSet(new HashSet<>(providers)) - : Collections.unmodifiableSet(providers); + providers = check + ? Collections.unmodifiableSet(new LinkedHashSet<>(providers)) + : Collections.unmodifiableSet(providers); if (providers.isEmpty()) throw new IllegalArgumentException("Empty providers set"); if (check) @@ -787,7 +792,7 @@ public class ModuleDescriptor private final String osVersion; private final Set conceals; private final Set packages; - private final DependencyHashes hashes; + private final ModuleHashes hashes; private ModuleDescriptor(String name, boolean automatic, @@ -802,7 +807,7 @@ public class ModuleDescriptor String osArch, String osVersion, Set conceals, - DependencyHashes hashes) + ModuleHashes hashes) { this.name = name; @@ -878,7 +883,8 @@ public class ModuleDescriptor String osArch, String osVersion, Set conceals, - Set packages) { + Set packages, + ModuleHashes hashes) { this.name = name; this.automatic = automatic; this.synthetic = synthetic; @@ -894,7 +900,7 @@ public class ModuleDescriptor this.osName = osName; this.osArch = osArch; this.osVersion = osVersion; - this.hashes = null; + this.hashes = hashes; } /** @@ -1063,9 +1069,9 @@ public class ModuleDescriptor } /** - * Returns the object with the hashes of the dependences. + * Returns the object with the hashes of other modules */ - Optional hashes() { + Optional hashes() { return Optional.ofNullable(hashes); } @@ -1103,7 +1109,7 @@ public class ModuleDescriptor String osArch; String osVersion; String mainClass; - DependencyHashes hashes; + ModuleHashes hashes; /** * Initializes a new builder with the given module name. @@ -1580,7 +1586,7 @@ public class ModuleDescriptor return this; } - /* package */ Builder hashes(DependencyHashes hashes) { + /* package */ Builder hashes(ModuleHashes hashes) { this.hashes = hashes; return this; } @@ -1719,7 +1725,9 @@ public class ModuleDescriptor hc = hc * 43 + Objects.hashCode(osVersion); hc = hc * 43 + Objects.hashCode(conceals); hc = hc * 43 + Objects.hashCode(hashes); - if (hc != 0) hash = hc; + if (hc == 0) + hc = -1; + hash = hc; } return hc; } @@ -1925,11 +1933,12 @@ public class ModuleDescriptor static { /** - * Setup the shared secret to allow code in other packages create - * ModuleDescriptor and associated objects directly. + * Setup the shared secret to allow code in other packages access + * private package methods in java.lang.module. */ jdk.internal.misc.SharedSecrets .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() { + @Override public Requires newRequires(Set ms, String mn) { return new Requires(ms, mn, false); @@ -1974,7 +1983,8 @@ public class ModuleDescriptor String osArch, String osVersion, Set conceals, - Set packages) { + Set packages, + ModuleHashes hashes) { return new ModuleDescriptor(name, automatic, synthetic, @@ -1988,7 +1998,29 @@ public class ModuleDescriptor osArch, osVersion, conceals, - packages); + packages, + hashes); + } + + @Override + public Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection roots, + boolean check, + PrintStream traceOutput) + { + return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput); + } + + @Override + public ModuleReference newPatchedModule(ModuleDescriptor descriptor, + URI location, + Supplier s) { + return new ModuleReference(descriptor, location, s, true, null); + } + + @Override + public Optional hashes(ModuleDescriptor descriptor) { + return descriptor.hashes(); } }); } 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 1cdd12838b1..71e98f14c6f 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 @@ -205,11 +205,14 @@ public interface ModuleFinder { * *

        The module finder returned by this method supports modules that are * packaged as JAR files. A JAR file with a {@code module-info.class} in - * the top-level directory of the JAR file is a modular JAR and is an - * explicit module. A JAR file that does not have a {@code - * module-info.class} in the top-level directory is an {@link - * ModuleDescriptor#isAutomatic automatic} module. The {@link - * ModuleDescriptor} for an automatic module is created as follows: + * the top-level directory of the JAR file (or overridden by a versioned + * entry in a {@link java.util.jar.JarFile#isMultiRelease() multi-release} + * JAR file) is a modular JAR and is an explicit module. + * + * A JAR file that does not have a {@code module-info.class} in the + * top-level directory is an {@link ModuleDescriptor#isAutomatic automatic} + * module. The {@link ModuleDescriptor} for an automatic module is created as + * follows: * *

          * diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java index f9e0bfac224..efc8c37b8a2 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java @@ -37,11 +37,12 @@ import java.nio.BufferUnderflowException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import jdk.internal.module.Hasher.DependencyHashes; +import jdk.internal.module.ModuleHashes; import static jdk.internal.module.ClassFileConstants.*; @@ -337,7 +338,7 @@ final class ModuleInfo { // computeIfAbsent Set providers = pm.get(sn); if (providers == null) { - providers = new HashSet<>(); + providers = new LinkedHashSet<>(); // preserve order pm.put(sn, providers); } providers.add(cn); @@ -425,7 +426,7 @@ final class ModuleInfo { map.put(dn, hash); } - builder.hashes(new DependencyHashes(algorithm, map)); + builder.hashes(new ModuleHashes(algorithm, map)); } diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java index fbd1b471381..250de159d74 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java @@ -40,7 +40,7 @@ import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -52,7 +52,6 @@ import java.util.jar.Manifest; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -190,18 +189,16 @@ class ModulePath implements ConfigurableModuleFinder { } } - if (attrs.isRegularFile() || attrs.isDirectory()) { - // packaged or exploded module - ModuleReference mref = readModule(entry, attrs); - if (mref != null) { - String name = mref.descriptor().name(); - return Collections.singletonMap(name, mref); - } + // packaged or exploded module + ModuleReference mref = readModule(entry, attrs); + if (mref != null) { + String name = mref.descriptor().name(); + return Collections.singletonMap(name, mref); + } else { + // skipped + return Collections.emptyMap(); } - // not recognized - throw new FindException("Unrecognized module: " + entry); - } catch (IOException ioe) { throw new FindException(ioe); } @@ -238,16 +235,13 @@ class ModulePath implements ConfigurableModuleFinder { // module found if (mref != null) { - // can have at most one version of a module in the directory String name = mref.descriptor().name(); if (nameToReference.put(name, mref) != null) { throw new FindException("Two versions of module " - + name + " found in " + dir); + + name + " found in " + dir); } - } - } } @@ -257,28 +251,40 @@ class ModulePath implements ConfigurableModuleFinder { /** * Locates a packaged or exploded module, returning a {@code ModuleReference} - * to the module. Returns {@code null} if the module is not recognized - * as a packaged or exploded module. + * to the module. Returns {@code null} if the entry is skipped because it is + * to a directory that does not contain a module-info.class or it's a hidden + * file. * * @throws IOException if an I/O error occurs - * @throws FindException if an error occurs parsing the module descriptor + * @throws FindException if the file is not recognized as a module or an + * error occurs parsing its module descriptor */ private ModuleReference readModule(Path entry, BasicFileAttributes attrs) throws IOException { try { - ModuleReference mref = null; if (attrs.isDirectory()) { - mref = readExplodedModule(entry); - } if (attrs.isRegularFile()) { - if (entry.toString().endsWith(".jar")) { - mref = readJar(entry); - } else if (isLinkPhase && entry.toString().endsWith(".jmod")) { - mref = readJMod(entry); + return readExplodedModule(entry); // may return null + } + + String fn = entry.getFileName().toString(); + if (attrs.isRegularFile()) { + if (fn.endsWith(".jar")) { + return readJar(entry); + } else if (fn.endsWith(".jmod")) { + if (isLinkPhase) + return readJMod(entry); + throw new FindException("JMOD files not supported: " + entry); } } - return mref; + + // skip hidden files + if (fn.startsWith(".") || Files.isHidden(entry)) { + return null; + } else { + throw new FindException("Unrecognized module: " + entry); + } } catch (InvalidModuleDescriptorException e) { throw new FindException("Error reading module: " + entry, e); @@ -292,15 +298,17 @@ class ModulePath implements ConfigurableModuleFinder { return zf.stream() .filter(e -> e.getName().startsWith("classes/") && e.getName().endsWith(".class")) - .map(e -> toPackageName(e)) + .map(e -> toPackageName(e.getName().substring(8))) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } /** * Returns a {@code ModuleReference} to a module in jmod file on the * file system. + * + * @throws IOException + * @throws InvalidModuleDescriptorException */ private ModuleReference readJMod(Path file) throws IOException { try (ZipFile zf = new ZipFile(file.toString())) { @@ -419,13 +427,12 @@ class ModulePath implements ConfigurableModuleFinder { // scan the entries in the JAR file to locate the .class and service // configuration file - Stream stream = jf.stream() - .map(e -> e.getName()) - .filter(e -> (e.endsWith(".class") || e.startsWith(SERVICES_PREFIX))) - .distinct(); - Map> map - = stream.collect(Collectors.partitioningBy(s -> s.endsWith(".class"), - Collectors.toSet())); + Map> map = + jf.stream() + .map(JarEntry::getName) + .filter(s -> (s.endsWith(".class") ^ s.startsWith(SERVICES_PREFIX))) + .collect(Collectors.partitioningBy(s -> s.endsWith(".class"), + Collectors.toSet())); Set classFiles = map.get(Boolean.TRUE); Set configFiles = map.get(Boolean.FALSE); @@ -433,19 +440,18 @@ class ModulePath implements ConfigurableModuleFinder { classFiles.stream() .map(c -> toPackageName(c)) .distinct() - .forEach(p -> builder.exports(p)); + .forEach(builder::exports); // map names of service configuration files to service names Set serviceNames = configFiles.stream() .map(this::toServiceName) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(Optional::stream) .collect(Collectors.toSet()); // parse each service configuration file for (String sn : serviceNames) { JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn); - Set providerClasses = new HashSet<>(); + Set providerClasses = new LinkedHashSet<>(); try (InputStream in = jf.getInputStream(entry)) { BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); @@ -475,19 +481,25 @@ class ModulePath implements ConfigurableModuleFinder { private Set jarPackages(JarFile jf) { return jf.stream() .filter(e -> e.getName().endsWith(".class")) - .map(e -> toPackageName(e)) + .map(e -> toPackageName(e.getName())) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } /** * Returns a {@code ModuleReference} to a module in modular JAR file on * the file system. + * + * @throws IOException + * @throws FindException + * @throws InvalidModuleDescriptorException */ private ModuleReference readJar(Path file) throws IOException { - try (JarFile jf = new JarFile(file.toString())) { - + try (JarFile jf = new JarFile(file.toFile(), + true, // verify + ZipFile.OPEN_READ, + JarFile.Release.RUNTIME)) + { ModuleDescriptor md; JarEntry entry = jf.getJarEntry(MODULE_INFO); if (entry == null) { @@ -520,7 +532,6 @@ class ModulePath implements ConfigurableModuleFinder { path.toString().endsWith(".class"))) .map(path -> toPackageName(dir.relativize(path))) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } catch (IOException x) { throw new UncheckedIOException(x); @@ -530,6 +541,9 @@ class ModulePath implements ConfigurableModuleFinder { /** * Returns a {@code ModuleReference} to an exploded module on the file * system or {@code null} if {@code module-info.class} not found. + * + * @throws IOException + * @throws InvalidModuleDescriptorException */ private ModuleReference readExplodedModule(Path dir) throws IOException { Path mi = dir.resolve(MODULE_INFO); @@ -559,19 +573,6 @@ class ModulePath implements ConfigurableModuleFinder { } } - private String toPackageName(ZipEntry entry) { - String name = entry.getName(); - assert name.endsWith(".class"); - // jmod classes in classes/, jar in / - int start = name.startsWith("classes/") ? 8 : 0; - int index = name.lastIndexOf("/"); - if (index > start) { - return name.substring(start, index).replace('/', '.'); - } else { - return ""; - } - } - private String toPackageName(Path path) { String name = path.toString(); assert name.endsWith(".class"); diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java index 140886d8626..1b77bfd8618 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java @@ -142,10 +142,11 @@ public interface ModuleReader extends Closeable { * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain) */ default Optional read(String name) throws IOException { - Optional in = open(name); - if (in.isPresent()) { - byte[] bytes = in.get().readAllBytes(); - return Optional.of(ByteBuffer.wrap(bytes)); + Optional oin = open(name); + if (oin.isPresent()) { + try (InputStream in = oin.get()) { + return Optional.of(ByteBuffer.wrap(in.readAllBytes())); + } } else { return Optional.empty(); } diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java index 781e7d3d088..10cce789949 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.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 @@ -32,7 +32,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; -import jdk.internal.module.Hasher.HashSupplier; +import jdk.internal.module.ModuleHashes.HashSupplier; /** @@ -54,12 +54,33 @@ public final class ModuleReference { private final URI location; private final Supplier readerSupplier; + // true if this is a reference to a patched module + private boolean patched; + // the function that computes the hash of this module reference private final HashSupplier hasher; // cached hash string to avoid needing to compute it many times private String cachedHash; + + /** + * Constructs a new instance of this class. + */ + ModuleReference(ModuleDescriptor descriptor, + URI location, + Supplier readerSupplier, + boolean patched, + HashSupplier hasher) + + { + this.descriptor = Objects.requireNonNull(descriptor); + this.location = location; + this.readerSupplier = Objects.requireNonNull(readerSupplier); + this.patched = patched; + this.hasher = hasher; + } + /** * Constructs a new instance of this class. */ @@ -67,11 +88,9 @@ public final class ModuleReference { URI location, Supplier readerSupplier, HashSupplier hasher) + { - this.descriptor = Objects.requireNonNull(descriptor); - this.location = location; - this.readerSupplier = Objects.requireNonNull(readerSupplier); - this.hasher = hasher; + this(descriptor, location, readerSupplier, false, hasher); } @@ -96,10 +115,9 @@ public final class ModuleReference { URI location, Supplier readerSupplier) { - this(descriptor, location, readerSupplier, null); + this(descriptor, location, readerSupplier, false, null); } - /** * Returns the module descriptor. * @@ -150,6 +168,20 @@ public final class ModuleReference { } + /** + * Returns {@code true} if this module has been patched via -Xpatch. + */ + boolean isPatched() { + return patched; + } + + /** + * Returns the hash supplier for this module. + */ + HashSupplier hasher() { + return hasher; + } + /** * Computes the hash of this module, returning it as a hex string. * Returns {@code null} if the hash cannot be computed. @@ -166,8 +198,6 @@ public final class ModuleReference { return result; } - private int hash; - /** * Computes a hash code for this module reference. * @@ -181,12 +211,17 @@ public final class ModuleReference { public int hashCode() { int hc = hash; if (hc == 0) { - hc = Objects.hash(descriptor, location, readerSupplier, hasher); - if (hc != 0) hash = hc; + hc = Objects.hash(descriptor, location, readerSupplier, hasher, + Boolean.valueOf(patched)); + if (hc == 0) + hc = -1; + hash = hc; } return hc; } + private int hash; + /** * Tests this module reference for equality with the given object. * @@ -214,7 +249,8 @@ public final class ModuleReference { return Objects.equals(this.descriptor, that.descriptor) && Objects.equals(this.location, that.location) && Objects.equals(this.readerSupplier, that.readerSupplier) - && Objects.equals(this.hasher, that.hasher); + && Objects.equals(this.hasher, that.hasher) + && this.patched == that.patched; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java index 05448e25b33..6b0b5d46fe9 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java @@ -48,8 +48,8 @@ import java.util.zip.ZipFile; import jdk.internal.misc.JavaLangAccess; import jdk.internal.misc.SharedSecrets; -import jdk.internal.module.Hasher; -import jdk.internal.module.Hasher.HashSupplier; +import jdk.internal.module.ModuleHashes; +import jdk.internal.module.ModuleHashes.HashSupplier; import jdk.internal.module.ModulePatcher; import sun.net.www.ParseUtil; @@ -89,7 +89,7 @@ class ModuleReferences { static ModuleReference newJarModule(ModuleDescriptor md, Path file) { URI uri = file.toUri(); Supplier supplier = () -> new JarModuleReader(file, uri); - HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm); + HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a); return newModule(md, uri, supplier, hasher); } @@ -99,7 +99,7 @@ class ModuleReferences { static ModuleReference newJModModule(ModuleDescriptor md, Path file) { URI uri = file.toUri(); Supplier supplier = () -> new JModModuleReader(file, uri); - HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm); + HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a); return newModule(md, file.toUri(), supplier, hasher); } @@ -122,7 +122,7 @@ class ModuleReferences { private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); - private volatile boolean closed; + private boolean closed; SafeCloseModuleReader() { } @@ -198,7 +198,10 @@ class ModuleReferences { static JarFile newJarFile(Path path) { try { - return new JarFile(path.toFile()); + return new JarFile(path.toFile(), + true, // verify + ZipFile.OPEN_READ, + JarFile.Release.RUNTIME); } catch (IOException ioe) { throw new UncheckedIOException(ioe); } @@ -219,6 +222,8 @@ class ModuleReferences { if (je != null) { String encodedPath = ParseUtil.encodePath(name, false); String uris = "jar:" + uri + "!/" + encodedPath; + if (jf.isMultiRelease()) + uris += "#runtime"; return Optional.of(URI.create(uris)); } else { return Optional.empty(); diff --git a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java index 37eb0b1bc77..cefcf19af70 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java +++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java @@ -25,8 +25,8 @@ package java.lang.module; +import java.io.PrintStream; import java.lang.module.ModuleDescriptor.Requires.Modifier; -import java.lang.reflect.Layer; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -43,7 +43,7 @@ import java.util.Set; import java.util.StringJoiner; import java.util.stream.Collectors; -import jdk.internal.module.Hasher; +import jdk.internal.module.ModuleHashes; /** * The resolver used by {@link Configuration#resolveRequires} and @@ -55,6 +55,7 @@ final class Resolver { private final ModuleFinder beforeFinder; private final Configuration parent; private final ModuleFinder afterFinder; + private final PrintStream traceOutput; // maps module name to module reference private final Map nameToReference = new HashMap<>(); @@ -62,10 +63,12 @@ final class Resolver { Resolver(ModuleFinder beforeFinder, Configuration parent, - ModuleFinder afterFinder) { + ModuleFinder afterFinder, + PrintStream traceOutput) { this.beforeFinder = beforeFinder; this.parent = parent; this.afterFinder = afterFinder; + this.traceOutput = traceOutput; } @@ -76,8 +79,6 @@ final class Resolver { */ Resolver resolveRequires(Collection roots) { - long start = trace_start("Resolve"); - // create the visit stack to get us started Deque q = new ArrayDeque<>(); for (String root : roots) { @@ -95,10 +96,9 @@ final class Resolver { } } - if (TRACE) { + if (isTracing()) { trace("Root module %s located", root); - if (mref.location().isPresent()) - trace(" (%s)", mref.location().get()); + mref.location().ifPresent(uri -> trace(" (%s)", uri)); } assert mref.descriptor().name().equals(root); @@ -108,13 +108,6 @@ final class Resolver { resolve(q); - if (TRACE) { - long duration = System.currentTimeMillis() - start; - Set names = nameToReference.keySet(); - trace("Resolver completed in %s ms", duration); - names.stream().sorted().forEach(name -> trace(" %s", name)); - } - return this; } @@ -153,11 +146,10 @@ final class Resolver { q.offer(mref.descriptor()); resolved.add(mref.descriptor()); - if (TRACE) { + if (isTracing()) { trace("Module %s located, required by %s", dn, descriptor.name()); - if (mref.location().isPresent()) - trace(" (%s)", mref.location().get()); + mref.location().ifPresent(uri -> trace(" (%s)", uri)); } } @@ -175,8 +167,6 @@ final class Resolver { */ Resolver resolveUses() { - long start = trace_start("Bind"); - // Scan the finders for all available service provider modules. As // java.base uses services then then module finders will be scanned // anyway. @@ -230,10 +220,10 @@ final class Resolver { String pn = provider.name(); if (!nameToReference.containsKey(pn)) { - - if (TRACE && mref.location().isPresent()) - trace(" (%s)", mref.location().get()); - + if (isTracing()) { + mref.location() + .ifPresent(uri -> trace(" (%s)", uri)); + } nameToReference.put(pn, mref); q.push(provider); } @@ -248,14 +238,6 @@ final class Resolver { } while (!candidateConsumers.isEmpty()); - - if (TRACE) { - long duration = System.currentTimeMillis() - start; - Set names = nameToReference.keySet(); - trace("Bind completed in %s ms", duration); - names.stream().sorted().forEach(name -> trace(" %s", name)); - } - return this; } @@ -264,23 +246,33 @@ final class Resolver { * Execute post-resolution checks and returns the module graph of resolved * modules as {@code Map}. The resolved modules will be in the given * configuration. + * + * @param check {@true} to execute the post resolution checks */ - Map> finish(Configuration cf) { + Map> finish(Configuration cf, + boolean check) + { + if (isTracing()) { + trace("Result:"); + Set names = nameToReference.keySet(); + names.stream().sorted().forEach(name -> trace(" %s", name)); + } - detectCycles(); - - checkPlatformConstraints(); - - checkHashes(); + if (check) { + detectCycles(); + checkPlatformConstraints(); + checkHashes(); + } Map> graph = makeGraph(cf); - checkExportSuppliers(graph); + if (check) { + checkExportSuppliers(graph); + } return graph; } - /** * Checks the given module graph for cycles. * @@ -420,52 +412,44 @@ final class Resolver { } - /** * Checks the hashes in the module descriptor to ensure that they match - * the hash of the dependency's module reference. + * any recorded hashes. */ private void checkHashes() { - for (ModuleReference mref : nameToReference.values()) { ModuleDescriptor descriptor = mref.descriptor(); - // get map of module names to hash - Optional ohashes = descriptor.hashes(); + // get map of module hashes + Optional ohashes = descriptor.hashes(); if (!ohashes.isPresent()) continue; - Hasher.DependencyHashes hashes = ohashes.get(); - - // check dependences - for (ModuleDescriptor.Requires d : descriptor.requires()) { - String dn = d.name(); - String recordedHash = hashes.hashFor(dn); - - if (recordedHash != null) { - - ModuleReference other = nameToReference.get(dn); - if (other == null) { - other = parent.findModule(dn) - .map(ResolvedModule::reference) - .orElse(null); - } - if (other == null) - throw new InternalError(dn + " not found"); - - String actualHash = other.computeHash(hashes.algorithm()); - if (actualHash == null) - fail("Unable to compute the hash of module %s", dn); - - if (!recordedHash.equals(actualHash)) { - fail("Hash of %s (%s) differs to expected hash (%s)", - dn, actualHash, recordedHash); - } + ModuleHashes hashes = ohashes.get(); + String algorithm = hashes.algorithm(); + for (String dn : hashes.names()) { + ModuleReference other = nameToReference.get(dn); + if (other == null) { + other = parent.findModule(dn) + .map(ResolvedModule::reference) + .orElse(null); } + // skip checking the hash if the module has been patched + if (other != null && !other.isPatched()) { + String recordedHash = hashes.hashFor(dn); + String actualHash = other.computeHash(algorithm); + if (actualHash == null) + fail("Unable to compute the hash of module %s", dn); + if (!recordedHash.equals(actualHash)) { + fail("Hash of %s (%s) differs to expected hash (%s)" + + " recorded in %s", dn, actualHash, recordedHash, + descriptor.name()); + } + } } - } + } } @@ -666,7 +650,7 @@ final class Resolver { // source is exported to descriptor2 String source = export.source(); ModuleDescriptor other - = packageToExporter.put(source, descriptor2); + = packageToExporter.put(source, descriptor2); if (other != null && other != descriptor2) { // package might be local to descriptor1 @@ -690,33 +674,38 @@ final class Resolver { } } - // uses S - for (String service : descriptor1.uses()) { - String pn = packageName(service); - if (!packageToExporter.containsKey(pn)) { - fail("Module %s does not read a module that exports %s", - descriptor1.name(), pn); - } - } + // uses/provides checks not applicable to automatic modules + if (!descriptor1.isAutomatic()) { - // provides S - for (Map.Entry entry : - descriptor1.provides().entrySet()) { - String service = entry.getKey(); - ModuleDescriptor.Provides provides = entry.getValue(); - - String pn = packageName(service); - if (!packageToExporter.containsKey(pn)) { - fail("Module %s does not read a module that exports %s", - descriptor1.name(), pn); - } - - for (String provider : provides.providers()) { - if (!packages.contains(packageName(provider))) { - fail("Provider %s not in module %s", - provider, descriptor1.name()); + // uses S + for (String service : descriptor1.uses()) { + String pn = packageName(service); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); } } + + // provides S + for (Map.Entry entry : + descriptor1.provides().entrySet()) { + String service = entry.getKey(); + ModuleDescriptor.Provides provides = entry.getValue(); + + String pn = packageName(service); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); + } + + for (String provider : provides.providers()) { + if (!packages.contains(packageName(provider))) { + fail("Provider %s not in module %s", + provider, descriptor1.name()); + } + } + } + } } @@ -796,27 +785,18 @@ final class Resolver { throw new ResolutionException(msg); } - /** - * Tracing support, limited to boot layer for now. + * Tracing support */ - private final static boolean TRACE - = Boolean.getBoolean("jdk.launcher.traceResolver") - && (Layer.boot() == null); - - private String op; - - private long trace_start(String op) { - this.op = op; - return System.currentTimeMillis(); + private boolean isTracing() { + return traceOutput != null; } private void trace(String fmt, Object ... args) { - if (TRACE) { - System.out.print("[" + op + "] "); - System.out.format(fmt, args); - System.out.println(); + if (traceOutput != null) { + traceOutput.format("[Resolver] " + fmt, args); + traceOutput.println(); } } diff --git a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java index 67766f9ed5b..d14ee8d60e4 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java @@ -44,6 +44,7 @@ import java.util.function.Supplier; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReaderFactory; +import jdk.internal.module.ModuleHashes; import jdk.internal.module.SystemModules; import jdk.internal.module.ModulePatcher; import jdk.internal.perf.PerfCounter; @@ -101,13 +102,16 @@ class SystemModuleFinder implements ModuleFinder { for (int i = 0; i < n; i++) { String mn = moduleNames[i]; ModuleDescriptor md; + String hash; if (fastLoad) { md = descriptors[i]; + hash = SystemModules.MODULES_TO_HASH[i]; } else { // fallback to read module-info.class // if fast loading of ModuleDescriptors is disabled ImageLocation location = imageReader.findLocation(mn, "module-info.class"); md = ModuleDescriptor.read(imageReader.getResourceBuffer(location)); + hash = null; } if (!md.name().equals(mn)) throw new InternalError(); @@ -123,7 +127,8 @@ class SystemModuleFinder implements ModuleFinder { } }; - ModuleReference mref = new ModuleReference(md, uri, readerSupplier); + ModuleReference mref = + new ModuleReference(md, uri, readerSupplier, hashSupplier(hash)); // may need a reference to a patched module if -Xpatch specified mref = ModulePatcher.interposeIfNeeded(mref); @@ -142,6 +147,18 @@ class SystemModuleFinder implements ModuleFinder { initTime.addElapsedTimeFrom(t0); } + private static ModuleHashes.HashSupplier hashSupplier(String hash) { + if (hash == null) + return null; + + return new ModuleHashes.HashSupplier() { + @Override + public String generate(String algorithm) { + return hash; + } + }; + } + SystemModuleFinder() { } @Override diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java index 3dde9710e8a..0ca75a874c4 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java @@ -27,6 +27,7 @@ package java.lang.reflect; import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ResolvedModule; import java.util.Collections; import java.util.HashMap; @@ -41,6 +42,8 @@ import java.util.stream.Collectors; import jdk.internal.loader.Loader; import jdk.internal.loader.LoaderPool; import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.ServicesCatalog; +import jdk.internal.module.ServicesCatalog.ServiceProvider; import sun.security.util.SecurityConstants; @@ -549,4 +552,55 @@ public final class Layer { public static Layer boot() { return SharedSecrets.getJavaLangAccess().getBootLayer(); } + + + /** + * Returns the ServicesCatalog for this Layer, creating it if not + * already created. + */ + ServicesCatalog getServicesCatalog() { + ServicesCatalog servicesCatalog = this.servicesCatalog; + if (servicesCatalog != null) + return servicesCatalog; + + Map> map = new HashMap<>(); + for (Module m : nameToModule.values()) { + ModuleDescriptor descriptor = m.getDescriptor(); + for (Provides provides : descriptor.provides().values()) { + String service = provides.service(); + Set providers + = map.computeIfAbsent(service, k -> new HashSet<>()); + for (String pn : provides.providers()) { + providers.add(new ServiceProvider(m, pn)); + } + } + } + + ServicesCatalog catalog = new ServicesCatalog() { + @Override + public void register(Module module) { + throw new UnsupportedOperationException(); + } + @Override + public Set findServices(String service) { + Set providers = map.get(service); + if (providers == null) { + return Collections.emptySet(); + } else { + return Collections.unmodifiableSet(providers); + } + } + }; + + synchronized (this) { + servicesCatalog = this.servicesCatalog; + if (servicesCatalog == null) { + this.servicesCatalog = servicesCatalog = catalog; + } + } + + return servicesCatalog; + } + + private volatile ServicesCatalog servicesCatalog; } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java index 5de7394a406..59eb856f8fb 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java @@ -43,11 +43,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Stream; @@ -142,9 +138,6 @@ public final class Module { this.name = null; this.loader = loader; this.descriptor = null; - - // unnamed modules are loose - this.loose = true; } @@ -245,17 +238,27 @@ public final class Module { } - // -- readability -- + // -- - // true if this module reads all unnamed modules (a.k.a. loose module) - private volatile boolean loose; + // the special Module to mean reads or exported to "all unnamed modules" + private static final Module ALL_UNNAMED_MODULE = new Module(null); + + // special Module to mean exported to "everyone" + private static final Module EVERYONE_MODULE = new Module(null); + + // exported to all modules + private static final Set EVERYONE = Collections.singleton(EVERYONE_MODULE); + + + // -- readability -- // the modules that this module permanently reads // (will be final when the modules are defined in reverse topology order) private volatile Set reads; - // created lazily, additional modules that this module reflectively reads - private volatile WeakSet transientReads; + // additional module (2nd key) that some module (1st key) reflectively reads + private static final WeakPairMap transientReads + = new WeakPairMap<>(); /** @@ -284,22 +287,19 @@ public final class Module { // check if this module reads other if (other.isNamed()) { - Set reads = this.reads; // volatile read if (reads != null && reads.contains(other)) return true; - - } else { - - // loose modules read all unnamed modules - if (this.loose) - return true; - } // check if this module reads the other module reflectively - WeakSet tr = this.transientReads; // volatile read - if (tr != null && tr.contains(other)) + if (transientReads.containsKeyPair(this, other)) + return true; + + // if other is an unnamed module then check if this module reads + // all unnamed modules + if (!other.isNamed() + && transientReads.containsKeyPair(this, ALL_UNNAMED_MODULE)) return true; return false; @@ -346,8 +346,7 @@ public final class Module { } /** - * Makes the given {@code Module} readable to this module without - * notifying the VM. + * Updates this module to read another module without notifying the VM. * * @apiNote This method is for VM white-box testing. */ @@ -361,40 +360,28 @@ public final class Module { * If {@code syncVM} is {@code true} then the VM is notified. */ private void implAddReads(Module other, boolean syncVM) { + Objects.requireNonNull(other); // nothing to do if (other == this || !this.isNamed()) return; - // if the other is null then change this module to be loose. - if (other == null) { - if (syncVM) - addReads0(this, null); - this.loose = true; - return; - } - // check if we already read this module Set reads = this.reads; if (reads != null && reads.contains(other)) return; // update VM first, just in case it fails - if (syncVM) - addReads0(this, other); - - // add reflective read - WeakSet tr = this.transientReads; - if (tr == null) { - synchronized (this) { - tr = this.transientReads; - if (tr == null) { - tr = new WeakSet<>(); - this.transientReads = tr; - } + if (syncVM) { + if (other == ALL_UNNAMED_MODULE) { + addReads0(this, null); + } else { + addReads0(this, other); } } - tr.add(other); + + // add reflective read + transientReads.putIfAbsent(this, other, Boolean.TRUE); } @@ -404,15 +391,10 @@ public final class Module { // (will be final when the modules are defined in reverse topology order) private volatile Map> exports; - // created lazily, additional exports added at run-time - private volatile Map> transientExports; - - // the special Module to mean exported to all modules - private static final Module EVERYONE_MODULE = new Module(null); - private static final Set EVERYONE = Collections.singleton(EVERYONE_MODULE); - - // the special Module to mean exported to all unnamed modules - private static final Module ALL_UNNAMED_MODULE = new Module(null); + // additional exports added at run-time + // this module (1st key), other module (2nd key), exported packages (value) + private static final WeakPairMap> + transientExports = new WeakPairMap<>(); /** @@ -489,23 +471,9 @@ public final class Module { if (exports != null) { Set targets = exports.get(pn); - if (targets != null) { - - // exported to all modules - if (targets.contains(EVERYONE_MODULE)) - return true; - - if (other != EVERYONE_MODULE) { - // exported to other - if (targets.contains(other)) - return true; - - // other is an unnamed module && exported to all unnamed - if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE)) - return true; - } - - } + if ((targets != null) + && (targets.contains(other) || targets.contains(EVERYONE_MODULE))) + return true; } return false; } @@ -515,29 +483,27 @@ public final class Module { * package package to the given module. */ private boolean isExportedReflectively(String pn, Module other) { - Map> te = this.transientExports; - if (te != null) { - WeakSet targets = te.get(pn); + // exported to all modules + Map exports = transientExports.get(this, EVERYONE_MODULE); + if (exports != null && exports.containsKey(pn)) + return true; - if (targets != null) { + if (other != EVERYONE_MODULE) { - // exported to all modules - if (targets.contains(EVERYONE_MODULE)) + // exported to other + exports = transientExports.get(this, other); + if (exports != null && exports.containsKey(pn)) + return true; + + // other is an unnamed module && exported to all unnamed + if (!other.isNamed()) { + exports = transientExports.get(this, ALL_UNNAMED_MODULE); + if (exports != null && exports.containsKey(pn)) return true; - - if (other != EVERYONE_MODULE) { - - // exported to other - if (targets.contains(other)) - return true; - - // other is an unnamed module && exported to all unnamed - if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE)) - return true; - } } } + return false; } @@ -638,34 +604,19 @@ public final class Module { } } - // create transientExports if needed - Map> te = this.transientExports; // read - if (te == null) { - synchronized (this) { - te = this.transientExports; - if (te == null) { - te = new ConcurrentHashMap<>(); - this.transientExports = te; // volatile write - } - } - } - // add package name to transientExports if absent - WeakSet s = te.get(pn); - if (s == null) { - s = new WeakSet<>(); - WeakSet prev = te.putIfAbsent(pn, s); - if (prev != null) - s = prev; - } - s.add(other); + transientExports + .computeIfAbsent(this, other, + (_this, _other) -> new ConcurrentHashMap<>()) + .putIfAbsent(pn, Boolean.TRUE); } // -- services -- - // created lazily, additional service types that this module uses - private volatile WeakSet> transientUses; + // additional service type (2nd key) that some module (1st key) uses + private static final WeakPairMap, Boolean> transientUses + = new WeakPairMap<>(); /** * If the caller's module is this module then update this module to add a @@ -702,17 +653,7 @@ public final class Module { } if (!canUse(st)) { - WeakSet> uses = this.transientUses; - if (uses == null) { - synchronized (this) { - uses = this.transientUses; - if (uses == null) { - uses = new WeakSet<>(); - this.transientUses = uses; - } - } - } - uses.add(st); + transientUses.putIfAbsent(this, st, Boolean.TRUE); } } @@ -746,11 +687,7 @@ public final class Module { return true; // uses added via addUses - WeakSet> uses = this.transientUses; - if (uses != null && uses.contains(st)) - return true; - - return false; + return transientUses.containsKeyPair(this, st); } @@ -885,7 +822,7 @@ public final class Module { // -- creating Module objects -- /** - * Find the runtime Module corresponding to the given ReadDependence + * Find the runtime Module corresponding to the given ResolvedModule * in the given parent Layer (or its parents). */ private static Module find(ResolvedModule resolvedModule, Layer layer) { @@ -969,7 +906,7 @@ public final class Module { // automatic modules reads all unnamed modules if (descriptor.isAutomatic()) { - m.implAddReads(null, true); + m.implAddReads(ALL_UNNAMED_MODULE, true); } // exports @@ -1097,7 +1034,7 @@ public final class Module { * the representation is the string {@code "module"}, followed by a space, * and then the module name. For an unnamed module, the representation is * the string {@code "unnamed module"}, followed by a space, and then an - * implementation specific identifier for the unnamed module. + * implementation specific string that identifies the unnamed module. * * @return The string representation of this module */ @@ -1112,46 +1049,6 @@ public final class Module { } - // -- supporting classes -- - - - /** - * A "not-a-Set" set of weakly referenced objects that supports concurrent - * access. - */ - private static class WeakSet { - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Lock readLock = lock.readLock(); - private final Lock writeLock = lock.writeLock(); - - private final WeakHashMap map = new WeakHashMap<>(); - - /** - * Adds the specified element to the set. - */ - void add(E e) { - writeLock.lock(); - try { - map.put(e, Boolean.TRUE); - } finally { - writeLock.unlock(); - } - } - - /** - * Returns {@code true} if this set contains the specified element. - */ - boolean contains(E e) { - readLock.lock(); - try { - return map.containsKey(e); - } finally { - readLock.unlock(); - } - } - } - - // -- native methods -- // JVM_DefineModule @@ -1196,8 +1093,12 @@ public final class Module { m1.implAddReads(m2, true); } @Override + public void addReadsAllUnnamed(Module m) { + m.implAddReads(Module.ALL_UNNAMED_MODULE); + } + @Override public void addExports(Module m, String pn, Module other) { - m.implAddExports(pn, Objects.requireNonNull(other), true); + m.implAddExports(pn, other, true); } @Override public void addExportsToAll(Module m, String pn) { @@ -1211,6 +1112,10 @@ public final class Module { public void addPackage(Module m, String pn) { m.implAddPackage(pn, true); } + @Override + public ServicesCatalog getServicesCatalog(Layer layer) { + return layer.getServicesCatalog(); + } }); } } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java b/jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java new file mode 100644 index 00000000000..39a623a4704 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java @@ -0,0 +1,354 @@ +/* + * 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 java.lang.reflect; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiFunction; + +/** + * A WeakHashMap-like data structure that uses a pair of weakly-referenced keys + * with identity equality semantics to associate a strongly-referenced value. + * Unlike WeakHashMap, this data structure is thread-safe. + * + * @param the type of 1st key in key pair + * @param the type of 2nd key in key pair + * @param the type of value + * @author Peter Levart + */ +final class WeakPairMap { + + private final ConcurrentHashMap, V> map = new ConcurrentHashMap<>(); + private final ReferenceQueue queue = new ReferenceQueue<>(); + + /** + * Tests if the specified pair of keys are associated with a value + * in the WeakPairMap. + * + * @param k1 the 1st of the pair of keys + * @param k2 the 2nd of the pair of keys + * @return true if and only if the specified key pair is in this WeakPairMap, + * as determined by the identity comparison; false otherwise + * @throws NullPointerException if any of the specified keys is null + */ + public boolean containsKeyPair(K1 k1, K2 k2) { + expungeStaleAssociations(); + return map.containsKey(Pair.lookup(k1, k2)); + } + + /** + * Returns the value to which the specified pair of keys is mapped, or null + * if this WeakPairMap contains no mapping for the key pair. + *

          More formally, if this WeakPairMap contains a mapping from a key pair + * {@code (_k1, _k2)} to a value {@code v} such that + * {@code k1 == _k1 && k2 == _k2}, then this method returns {@code v}; + * otherwise it returns {@code null}. + * (There can be at most one such mapping.) + * + * @param k1 the 1st of the pair of keys for which the mapped value is to + * be returned + * @param k2 the 2nd of the pair of keys for which the mapped value is to + * be returned + * @return the value to which the specified key pair is mapped, or null if + * this map contains no mapping for the key pair + * @throws NullPointerException if any of the specified keys is null + */ + public V get(K1 k1, K2 k2) { + expungeStaleAssociations(); + return map.get(Pair.lookup(k1, k2)); + } + + /** + * Maps the specified key pair to the specified value in this WeakPairMap. + * Neither the keys nor the value can be null. + *

          The value can be retrieved by calling the {@link #get} method + * with the the same keys (compared by identity). + * + * @param k1 the 1st of the pair of keys with which the specified value is to + * be associated + * @param k2 the 2nd of the pair of keys with which the specified value is to + * be associated + * @param v value to be associated with the specified key pair + * @return the previous value associated with key pair, or {@code null} if + * there was no mapping for key pair + * @throws NullPointerException if any of the specified keys or value is null + */ + public V put(K1 k1, K2 k2, V v) { + expungeStaleAssociations(); + return map.put(Pair.weak(k1, k2, queue), v); + } + + /** + * If the specified key pair is not already associated with a value, + * associates it with the given value and returns {@code null}, else does + * nothing and returns the currently associated value. + * + * @param k1 the 1st of the pair of keys with which the specified value is to + * be associated + * @param k2 the 2nd of the pair of keys with which the specified value is to + * be associated + * @param v value to be associated with the specified key pair + * @return the previous value associated with key pair, or {@code null} if + * there was no mapping for key pair + * @throws NullPointerException if any of the specified keys or value is null + */ + public V putIfAbsent(K1 k1, K2 k2, V v) { + expungeStaleAssociations(); + return map.putIfAbsent(Pair.weak(k1, k2, queue), v); + } + + /** + * If the specified key pair is not already associated with a value, + * attempts to compute its value using the given mapping function + * and enters it into this WeakPairMap unless {@code null}. The entire + * method invocation is performed atomically, so the function is + * applied at most once per key pair. Some attempted update operations + * on this WeakPairMap by other threads may be blocked while computation + * is in progress, so the computation should be short and simple, + * and must not attempt to update any other mappings of this WeakPairMap. + * + * @param k1 the 1st of the pair of keys with which the + * computed value is to be associated + * @param k2 the 2nd of the pair of keys with which the + * computed value is to be associated + * @param mappingFunction the function to compute a value + * @return the current (existing or computed) value associated with + * the specified key pair, or null if the computed value is null + * @throws NullPointerException if any of the specified keys or + * mappingFunction is null + * @throws IllegalStateException if the computation detectably + * attempts a recursive update to this map + * that would otherwise never complete + * @throws RuntimeException or Error if the mappingFunction does so, in + * which case the mapping is left unestablished + */ + public V computeIfAbsent(K1 k1, K2 k2, + BiFunction + mappingFunction) { + expungeStaleAssociations(); + try { + return map.computeIfAbsent( + Pair.weak(k1, k2, queue), + pair -> mappingFunction.apply(pair.first(), pair.second())); + } finally { + Reference.reachabilityFence(k1); + Reference.reachabilityFence(k2); + } + } + + /** + * Returns a {@link Collection} view of the values contained in this + * WeakPairMap. The collection is backed by the WeakPairMap, so changes to + * the map are reflected in the collection, and vice-versa. The collection + * supports element removal, which removes the corresponding + * mapping from this map, via the {@code Iterator.remove}, + * {@code Collection.remove}, {@code removeAll}, + * {@code retainAll}, and {@code clear} operations. It does not + * support the {@code add} or {@code addAll} operations. + * + * @return the collection view + */ + public Collection values() { + expungeStaleAssociations(); + return map.values(); + } + + /** + * Removes associations from this WeakPairMap for which at least one of the + * keys in key pair has been found weakly-reachable and corresponding + * WeakRefPeer(s) enqueued. Called as part of each public operation. + */ + private void expungeStaleAssociations() { + WeakRefPeer peer; + while ((peer = (WeakRefPeer) queue.poll()) != null) { + map.remove(peer.weakPair()); + } + } + + /** + * Common interface of both {@link Weak} and {@link Lookup} key pairs. + */ + private interface Pair { + + static Pair weak(K1 k1, K2 k2, + ReferenceQueue queue) { + return new Weak<>(k1, k2, queue); + } + + static Pair lookup(K1 k1, K2 k2) { + return new Lookup<>(k1, k2); + } + + /** + * @return The 1st of the pair of keys (may be null for {@link Weak} + * when it gets cleared) + */ + K1 first(); + + /** + * @return The 2nd of the pair of keys (may be null for {@link Weak} + * when it gets cleared) + */ + K2 second(); + + static int hashCode(Object first, Object second) { + // assert first != null && second != null; + return System.identityHashCode(first) ^ + System.identityHashCode(second); + } + + static boolean equals(Object first, Object second, Pair p) { + return first != null && second != null && + first == p.first() && second == p.second(); + } + + /** + * A Pair where both keys are weakly-referenced. + * It is composed of two instances of {@link WeakRefPeer}s: + *
          {@code
          +         *
          +         *     +-referent-> [K1]                +-referent-> [K2]
          +         *     |                                |
          +         *   +----------------+               +----------------+
          +         *   | Pair.Weak <:   |-----peer----->| (anonymous) <: |
          +         *   | WeakRefPeer,   |               | WeakRefPeer    |
          +         *   | Pair           |<--weakPair()--|                |
          +         *   +----------------+               +----------------+
          +         *     |            ^
          +         *     |            |
          +         *     +-weakPair()-+
          +         *
          +         * }
          + *

          + * Pair.Weak is used for CHM keys. Both peers are associated with the + * same {@link ReferenceQueue} so when either of their referents + * becomes weakly-reachable, the corresponding entries can be + * {@link #expungeStaleAssociations() expunged} from the map. + */ + final class Weak extends WeakRefPeer implements Pair { + + // saved hash so it can be retrieved after the reference is cleared + private final int hash; + // link to peer + private final WeakRefPeer peer; + + Weak(K1 k1, K2 k2, ReferenceQueue queue) { + super(k1, queue); + hash = Pair.hashCode(k1, k2); + peer = new WeakRefPeer<>(k2, queue) { + // link back to peer + @Override + Weak weakPair() { return Weak.this; } + }; + } + + @Override + Weak weakPair() { + return this; + } + + @Override + public K1 first() { + return get(); + } + + @Override + public K2 second() { + return peer.get(); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + return this == obj || + (obj instanceof Pair && + Pair.equals(first(), second(), (Pair) obj)); + } + } + + /** + * Optimized lookup Pair, used as lookup key in methods like + * {@link java.util.Map#get(Object)} or + * {@link java.util.Map#containsKey(Object)}) where + * there is a great chance its allocation is eliminated + * by escape analysis when such lookups are inlined by JIT. + * All its methods are purposely designed so that 'this' is never + * passed to any other method or used as identity. + */ + final class Lookup implements Pair { + private final K1 k1; + private final K2 k2; + + Lookup(K1 k1, K2 k2) { + this.k1 = Objects.requireNonNull(k1); + this.k2 = Objects.requireNonNull(k2); + } + + @Override + public K1 first() { + return k1; + } + + @Override + public K2 second() { + return k2; + } + + @Override + public int hashCode() { + return Pair.hashCode(k1, k2); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Pair && + Pair.equals(k1, k2, (Pair) obj); + } + } + } + + /** + * Common abstract supertype of a pair of WeakReference peers. + */ + private static abstract class WeakRefPeer extends WeakReference { + + WeakRefPeer(K k, ReferenceQueue queue) { + super(Objects.requireNonNull(k), queue); + } + + /** + * @return the {@link Pair.Weak} side of the pair of peers. + */ + abstract Pair.Weak weakPair(); + } +} diff --git a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java index 7ccce279357..08deac0ed2f 100644 --- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java @@ -29,8 +29,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleDescriptor.Provides; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Layer; @@ -85,7 +83,7 @@ import jdk.internal.reflect.Reflection; * and deployed as a named module must have an appropriate uses clause * in its module descriptor to declare that the module uses * implementations of the service. A corresponding requirement is that a - * provider deployed as a named modules must have an appropriate + * provider deployed as a named module must have an appropriate * provides clause in its module descriptor to declare that the module * provides an implementation of the service. The uses and * provides allow consumers of a service to be linked to @@ -550,35 +548,29 @@ public final class ServiceLoader /** * Implements lazy service provider lookup of service providers that * are provided by modules in a module Layer. - * - * For now, this iterator examines all modules in each Layer. This will - * be replaced once we decide on how the service-use graph is exposed - * in the module API. */ private class LayerLookupIterator extends RestrictedIterator { final String serviceName; Layer currentLayer; - Iterator descriptorIterator; - Iterator providersIterator; - - Module nextModule; - String nextProvider; + Iterator iterator; + ServiceProvider nextProvider; LayerLookupIterator() { serviceName = service.getName(); currentLayer = layer; // need to get us started - descriptorIterator = descriptors(layer, serviceName); + iterator = providers(currentLayer, serviceName); } - Iterator descriptors(Layer layer, String service) { - return layer.modules().stream() - .map(Module::getDescriptor) - .filter(d -> d.provides().get(service) != null) - .iterator(); + Iterator providers(Layer layer, String service) { + ServicesCatalog catalog = SharedSecrets + .getJavaLangReflectModuleAccess() + .getServicesCatalog(layer); + + return catalog.findServices(serviceName).iterator(); } @Override @@ -591,30 +583,18 @@ public final class ServiceLoader while (true) { // next provider - if (providersIterator != null && providersIterator.hasNext()) { - nextProvider = providersIterator.next(); + if (iterator != null && iterator.hasNext()) { + nextProvider = iterator.next(); return true; } - // next descriptor - if (descriptorIterator.hasNext()) { - ModuleDescriptor descriptor = descriptorIterator.next(); - - nextModule = currentLayer.findModule(descriptor.name()).get(); - - Provides provides = descriptor.provides().get(serviceName); - providersIterator = provides.providers().iterator(); - - continue; - } - // next layer Layer parent = currentLayer.parent().orElse(null); if (parent == null) return false; currentLayer = parent; - descriptorIterator = descriptors(currentLayer, serviceName); + iterator = providers(currentLayer, serviceName); } } @@ -623,13 +603,14 @@ public final class ServiceLoader if (!hasNextService()) throw new NoSuchElementException(); - assert nextModule != null && nextProvider != null; - - String cn = nextProvider; + ServiceProvider provider = nextProvider; nextProvider = null; + Module module = provider.module(); + String cn = provider.providerName(); + // attempt to load the provider - Class c = loadClassInModule(nextModule, cn); + Class c = loadClassInModule(module, cn); if (c == null) fail(service, "Provider " + cn + " not found"); if (!service.isAssignableFrom(c)) 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 269c193dbe4..732248a377c 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 @@ -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 @@ -68,7 +68,7 @@ public class BootLoader { } // ServiceCatalog for the boot class loader - private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog(); + private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create(); // ClassLoaderValue map for boot class loader private static final ConcurrentHashMap CLASS_LOADER_VALUE_MAP = diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java index 5d7462e16c4..b6e58fb932b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java @@ -104,7 +104,7 @@ public class BuiltinClassLoader * A module defined/loaded by a built-in class loader. * * A LoadedModule encapsulates a ModuleReference along with its CodeSource - * URL to avoid needing to create this URL when define classes. + * URL to avoid needing to create this URL when defining classes. */ private static class LoadedModule { private final BuiltinClassLoader loader; diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java index e0c7e66cf51..1ff6d0b73b4 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.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 @@ -25,13 +25,24 @@ package jdk.internal.misc; +import java.io.PrintStream; +import java.lang.module.Configuration; +import jdk.internal.module.ModuleHashes; + import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Version; +import java.lang.module.ModuleFinder; +import java.util.Collection; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.net.URI; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.function.Supplier; /** * Provides access to non-public methods in java.lang.module. @@ -89,5 +100,29 @@ public interface JavaLangModuleAccess { String osArch, String osVersion, Set conceals, - Set packages); + Set packages, + ModuleHashes hashes); + + /** + * Resolves a collection of root modules, with service binding + * and the empty configuration as the parent. The post resolution + * checks are optionally run. + */ + Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection roots, + boolean check, + PrintStream traceOutput); + + /** + * Creates a ModuleReference to a "patched" module. + */ + ModuleReference newPatchedModule(ModuleDescriptor descriptor, + URI location, + Supplier readerSupplier); + + /** + * Returns the object with the hashes of other modules + */ + Optional hashes(ModuleDescriptor descriptor); + } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java index 91aa495528c..33c86cf410b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.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,9 +26,12 @@ package jdk.internal.misc; import java.lang.module.ModuleDescriptor; +import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.URI; +import jdk.internal.module.ServicesCatalog; + /** * Provides access to non-public methods in java.lang.reflect.Module */ @@ -56,6 +59,11 @@ public interface JavaLangReflectModuleAccess { */ void addReads(Module m1, Module m2); + /** + * Updates module m to read all unnamed modules. + */ + void addReadsAllUnnamed(Module m); + /** * Updates module m1 to export a package to module m2. The export does * not result in a strong reference to m2 (m2 can be GC'ed). @@ -76,4 +84,10 @@ public interface JavaLangReflectModuleAccess { * Add a package to the given module. */ void addPackage(Module m, String pkg); -} + + /** + * Returns the ServicesCatalog for the given Layer. + */ + ServicesCatalog getServicesCatalog(Layer layer); + +} \ No newline at end of file diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java index 8d51a5c6419..7c85e77d27e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java @@ -74,6 +74,8 @@ final class Builder { String osName; String osArch; String osVersion; + String algorithm; + Map hashes; Builder(String name, int reqs, int exports, int provides, int conceals, int packages) { @@ -251,6 +253,25 @@ final class Builder { return this; } + /** + * Sets the algorithm of the module hashes + */ + public Builder algorithm(String algorithm) { + this.algorithm = algorithm; + return this; + } + + /** + * Sets the module hash for the given module name + */ + public Builder moduleHash(String mn, String hash) { + if (hashes == null) + hashes = new HashMap<>(); + + hashes.put(mn, hash); + return this; + } + /** * Returns the set of packages that is the union of the exported and * concealed packages. @@ -273,6 +294,9 @@ final class Builder { public ModuleDescriptor build() { assert name != null; + ModuleHashes moduleHashes = + hashes != null ? new ModuleHashes(algorithm, hashes) : null; + return jlma.newModuleDescriptor(name, false, // automatic false, // assume not synthetic for now @@ -286,6 +310,7 @@ final class Builder { osArch, osVersion, conceals, - computePackages(exports, conceals)); + computePackages(exports, conceals), + moduleHashes); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java index 66b48915159..73a44c8735c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java @@ -34,6 +34,7 @@ import java.lang.module.ModuleDescriptor.Version; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -42,7 +43,6 @@ import jdk.internal.org.objectweb.asm.ByteVector; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.module.Hasher.DependencyHashes; import static jdk.internal.module.ClassFileConstants.*; @@ -148,7 +148,7 @@ class ClassFileAttributes { for (int i=0; i new HashSet<>()).add(cn); + provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn); off += 4; } provides.entrySet().forEach(e -> builder.provides(e.getKey(), @@ -281,10 +281,10 @@ class ClassFileAttributes { * u4 attribute_length; * * // the number of entries in the packages table - * u2 package_count; + * u2 packages_count; * { // index to CONSTANT_CONSTANT_utf8_info structure with the package name * u2 package_index - * } package[package_count]; + * } packages[package_count]; * * } */ @@ -579,9 +579,9 @@ class ClassFileAttributes { * alternative is to store it as an array of u1. */ static class HashesAttribute extends Attribute { - private final DependencyHashes hashes; + private final ModuleHashes hashes; - HashesAttribute(DependencyHashes hashes) { + HashesAttribute(ModuleHashes hashes) { super(HASHES); this.hashes = hashes; } @@ -613,7 +613,7 @@ class ClassFileAttributes { map.put(dn, hash); } - DependencyHashes hashes = new DependencyHashes(algorithm, map); + ModuleHashes hashes = new ModuleHashes(algorithm, map); return new HashesAttribute(hashes); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index 5b6c3c4372c..f2f7e02598c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -26,12 +26,15 @@ package jdk.internal.module; import java.io.File; +import java.io.PrintStream; import java.lang.module.Configuration; -import java.lang.module.ModuleReference; +import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; import java.lang.reflect.Layer; import java.lang.reflect.Module; +import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; @@ -41,10 +44,10 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; +import jdk.internal.misc.SharedSecrets; import jdk.internal.perf.PerfCounter; /** @@ -54,10 +57,9 @@ import jdk.internal.perf.PerfCounter; * the module system. In summary, the boot method creates a Configuration by * resolving a set of module names specified via the launcher (or equivalent) * -m and -addmods options. The modules are located on a module path that is - * constructed from the upgrade, system and application module paths. The - * Configuration is reified by creating the boot Layer with each module in the - * the configuration defined to one of the built-in class loaders. The mapping - * of modules to class loaders is statically mapped in a helper class. + * constructed from the upgrade module path, system modules, and application + * module path. The Configuration is instantiated as the boot Layer with each + * module in the the configuration defined to one of the built-in class loaders. */ public final class ModuleBootstrap { @@ -65,6 +67,11 @@ public final class ModuleBootstrap { private static final String JAVA_BASE = "java.base"; + private static final String JAVA_SE = "java.se"; + + // the token for "all default modules" + private static final String ALL_DEFAULT = "ALL-DEFAULT"; + // the token for "all unnamed modules" private static final String ALL_UNNAMED = "ALL-UNNAMED"; @@ -94,47 +101,65 @@ public final class ModuleBootstrap { long t0 = System.nanoTime(); - // system module path - ModuleFinder systemModulePath = ModuleFinder.ofSystem(); + // system modules + ModuleFinder systemModules = ModuleFinder.ofSystem(); - // Once we have the system module path then we define the base module. - // We do this here so that java.base is defined to the VM as early as + PerfCounters.systemModulesTime.addElapsedTimeFrom(t0); + + + long t1 = System.nanoTime(); + + // Once we have the system modules then we define the base module to + // the VM. We do this here so that java.base is defined as early as // possible and also that resources in the base module can be located // for error messages that may happen from here on. - Optional obase = systemModulePath.find(JAVA_BASE); - if (!obase.isPresent()) + ModuleReference base = systemModules.find(JAVA_BASE).orElse(null); + if (base == null) throw new InternalError(JAVA_BASE + " not found"); - ModuleReference base = obase.get(); + URI baseUri = base.location().orElse(null); + if (baseUri == null) + throw new InternalError(JAVA_BASE + " does not have a location"); BootLoader.loadModule(base); - Modules.defineModule(null, base.descriptor(), base.location().orElse(null)); + Modules.defineModule(null, base.descriptor(), baseUri); + PerfCounters.defineBaseTime.addElapsedTimeFrom(t1); + + + long t2 = System.nanoTime(); // -upgrademodulepath option specified to launcher ModuleFinder upgradeModulePath = createModulePathFinder("jdk.upgrade.module.path"); + if (upgradeModulePath != null) + systemModules = ModuleFinder.compose(upgradeModulePath, systemModules); // -modulepath option specified to the launcher ModuleFinder appModulePath = createModulePathFinder("jdk.module.path"); - // The module finder: [-upgrademodulepath] system-module-path [-modulepath] - ModuleFinder finder = systemModulePath; - if (upgradeModulePath != null) - finder = ModuleFinder.compose(upgradeModulePath, finder); + // The module finder: [-upgrademodulepath] system [-modulepath] + ModuleFinder finder = systemModules; if (appModulePath != null) finder = ModuleFinder.compose(finder, appModulePath); - // launcher -m option to specify the initial module + // The root modules to resolve + Set roots = new HashSet<>(); + + // launcher -m option to specify the main/initial module String mainModule = System.getProperty("jdk.module.main"); + if (mainModule != null) + roots.add(mainModule); // additional module(s) specified by -addmods + boolean addAllDefaultModules = false; boolean addAllSystemModules = false; boolean addAllApplicationModules = false; - Set addModules = null; String propValue = System.getProperty("jdk.launcher.addmods"); if (propValue != null) { - addModules = new HashSet<>(); for (String mod: propValue.split(",")) { switch (mod) { + case ALL_DEFAULT: + addAllDefaultModules = true; + break; case ALL_SYSTEM: addAllSystemModules = true; break; @@ -142,28 +167,12 @@ public final class ModuleBootstrap { addAllApplicationModules = true; break; default : - addModules.add(mod); + roots.add(mod); } } } - // The root modules to resolve - Set roots = new HashSet<>(); - - // main/initial module - if (mainModule != null) { - roots.add(mainModule); - if (addAllApplicationModules) - fail(ALL_MODULE_PATH + " not allowed with initial module"); - } - - // If -addmods is specified then those modules need to be resolved - if (addModules != null) - roots.addAll(addModules); - - // -limitmods - boolean limitmods = false; propValue = System.getProperty("jdk.launcher.limitmods"); if (propValue != null) { Set mods = new HashSet<>(); @@ -171,62 +180,101 @@ public final class ModuleBootstrap { mods.add(mod); } finder = limitFinder(finder, mods, roots); - limitmods = true; } - - // If there is no initial module specified then assume that the - // initial module is the unnamed module of the application class - // loader. By convention, and for compatibility, this is - // implemented by putting the names of all modules on the system - // module path into the set of modules to resolve. - // - // If `-addmods ALL-SYSTEM` is used then all modules on the system - // module path will be resolved, irrespective of whether an initial - // module is specified. - // - // If `-addmods ALL-MODULE-PATH` is used, and no initial module is - // specified, then all modules on the application module path will - // be resolved. - // - if (mainModule == null || addAllSystemModules) { - Set mrefs; - if (addAllApplicationModules) { - assert mainModule == null; - mrefs = finder.findAll(); - } else { - mrefs = systemModulePath.findAll(); - if (limitmods) { - ModuleFinder f = finder; - mrefs = mrefs.stream() - .filter(m -> f.find(m.descriptor().name()).isPresent()) - .collect(Collectors.toSet()); + // If there is no initial module specified then assume that the initial + // module is the unnamed module of the application class loader. This + // is implemented by resolving "java.se" and all (non-java.*) modules + // that export an API. If "java.se" is not observable then all java.* + // modules are resolved. + if (mainModule == null || addAllDefaultModules) { + boolean hasJava = false; + if (systemModules.find(JAVA_SE).isPresent()) { + // java.se is a system module + if (finder == systemModules || finder.find(JAVA_SE).isPresent()) { + // java.se is observable + hasJava = true; + roots.add(JAVA_SE); } } - // map to module names - for (ModuleReference mref : mrefs) { - roots.add(mref.descriptor().name()); + + for (ModuleReference mref : systemModules.findAll()) { + String mn = mref.descriptor().name(); + if (hasJava && mn.startsWith("java.")) + continue; + + // add as root if observable and exports at least one package + if ((finder == systemModules || finder.find(mn).isPresent())) { + ModuleDescriptor descriptor = mref.descriptor(); + for (ModuleDescriptor.Exports e : descriptor.exports()) { + if (!e.isQualified()) { + roots.add(mn); + break; + } + } + } } } - long t1 = System.nanoTime(); + // If `-addmods ALL-SYSTEM` is specified then all observable system + // modules will be resolved. + if (addAllSystemModules) { + ModuleFinder f = finder; // observable modules + systemModules.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(mn -> f.find(mn).isPresent()) // observable + .forEach(mn -> roots.add(mn)); + } + + // If `-addmods ALL-MODULE-PATH` is specified then all observable + // modules on the application module path will be resolved. + if (appModulePath != null && addAllApplicationModules) { + ModuleFinder f = finder; // observable modules + appModulePath.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(mn -> f.find(mn).isPresent()) // observable + .forEach(mn -> roots.add(mn)); + } + + PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2); + + + long t3 = System.nanoTime(); + + // determine if post resolution checks are needed + boolean needPostResolutionChecks = true; + if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here + && (upgradeModulePath == null) + && (appModulePath == null) + && (System.getProperty("jdk.launcher.patch.0") == null)) { + needPostResolutionChecks = false; + } + + PrintStream traceOutput = null; + if (Boolean.getBoolean("jdk.launcher.traceResolver")) + traceOutput = System.out; // run the resolver to create the configuration - - Configuration cf = Configuration.empty() + Configuration cf = SharedSecrets.getJavaLangModuleAccess() .resolveRequiresAndUses(finder, - ModuleFinder.empty(), - roots); + roots, + needPostResolutionChecks, + traceOutput); // time to create configuration - PerfCounters.resolveTime.addElapsedTimeFrom(t1); + PerfCounters.resolveTime.addElapsedTimeFrom(t3); + // mapping of modules to class loaders Function clf = ModuleLoaderMap.mappingFunction(cf); // check that all modules to be mapped to the boot loader will be - // loaded from the system module path - if (finder != systemModulePath) { + // loaded from the runtime image + if (needPostResolutionChecks) { for (ResolvedModule resolvedModule : cf.modules()) { ModuleReference mref = resolvedModule.reference(); String name = mref.descriptor().name(); @@ -237,20 +285,22 @@ public final class ModuleBootstrap { && upgradeModulePath.find(name).isPresent()) fail(name + ": cannot be loaded from upgrade module path"); - if (!systemModulePath.find(name).isPresent()) + if (!systemModules.find(name).isPresent()) fail(name + ": cannot be loaded from application module path"); } } } - long t2 = System.nanoTime(); + + long t4 = System.nanoTime(); // define modules to VM/runtime Layer bootLayer = Layer.empty().defineModules(cf, clf); - PerfCounters.layerCreateTime.addElapsedTimeFrom(t2); + PerfCounters.layerCreateTime.addElapsedTimeFrom(t4); - long t3 = System.nanoTime(); + + long t5 = System.nanoTime(); // define the module to its class loader, except java.base for (ResolvedModule resolvedModule : cf.modules()) { @@ -264,7 +314,8 @@ public final class ModuleBootstrap { } } - PerfCounters.loadModulesTime.addElapsedTimeFrom(t3); + PerfCounters.loadModulesTime.addElapsedTimeFrom(t5); + // -XaddReads and -XaddExports addExtraReads(bootLayer); @@ -295,25 +346,21 @@ public final class ModuleBootstrap { // module name -> reference Map map = new HashMap<>(); + + // root modules and their transitive dependences cf.modules().stream() .map(ResolvedModule::reference) .forEach(mref -> map.put(mref.descriptor().name(), mref)); + // additional modules + otherMods.stream() + .map(finder::find) + .flatMap(Optional::stream) + .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref)); + // set of modules that are observable Set mrefs = new HashSet<>(map.values()); - // add the other modules - for (String mod : otherMods) { - Optional omref = finder.find(mod); - if (omref.isPresent()) { - ModuleReference mref = omref.get(); - map.putIfAbsent(mod, mref); - mrefs.add(mref); - } else { - // no need to fail - } - } - return new ModuleFinder() { @Override public Optional find(String name) { @@ -369,15 +416,15 @@ public final class ModuleBootstrap { Module other; if (ALL_UNNAMED.equals(name)) { - other = null; // loose + Modules.addReadsAllUnnamed(m); } else { om = bootLayer.findModule(name); if (!om.isPresent()) fail("Unknown module: " + name); other = om.get(); + Modules.addReads(m, other); } - Modules.addReads(m, other); } } } @@ -439,10 +486,6 @@ public final class ModuleBootstrap { * Decodes the values of -XaddReads or -XaddExports options * * The format of the options is: $KEY=$MODULE(,$MODULE)* - * - * For transition purposes, this method allows the first usage to be - * $KEY=$MODULE(,$KEY=$MODULE) - * This format will eventually be removed. */ private static Map> decode(String prefix) { int index = 0; @@ -467,42 +510,15 @@ public final class ModuleBootstrap { if (rhs.isEmpty()) fail("Unable to parse: " + value); - // new format $MODULE(,$MODULE)* or old format $(MODULE)=... - pos = rhs.indexOf('='); - // old format only allowed in first -X option - if (pos >= 0 && index > 0) - fail("Unable to parse: " + value); + // value is (,)* + if (map.containsKey(key)) + fail(key + " specified more than once"); - if (pos == -1) { - - // new format: $KEY=$MODULE(,$MODULE)* - - Set values = map.get(key); - if (values != null) - fail(key + " specified more than once"); - - values = new HashSet<>(); - map.put(key, values); - for (String s : rhs.split(",")) { - if (s.length() > 0) values.add(s); - } - - } else { - - // old format: $KEY=$MODULE(,$KEY=$MODULE)* - - assert index == 0; // old format only allowed in first usage - - for (String expr : value.split(",")) { - if (expr.length() > 0) { - String[] s = expr.split("="); - if (s.length != 2) - fail("Unable to parse: " + expr); - - map.computeIfAbsent(s[0], k -> new HashSet<>()).add(s[1]); - } - } + Set values = new HashSet<>(); + map.put(key, values); + for (String s : rhs.split(",")) { + if (s.length() > 0) values.add(s); } index++; @@ -521,6 +537,13 @@ public final class ModuleBootstrap { } static class PerfCounters { + + static PerfCounter systemModulesTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime"); + static PerfCounter defineBaseTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime"); + static PerfCounter optionsAndRootsTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime"); static PerfCounter resolveTime = PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime"); static PerfCounter layerCreateTime diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java similarity index 64% rename from jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java rename to jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java index 947900f63dd..2012c78c4fd 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.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 @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package jdk.internal.module; import java.io.IOException; @@ -32,17 +33,16 @@ import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; /** - * Supporting class for computing, encoding and decoding hashes (message - * digests). + * The result of hashing the contents of a number of module artifacts. */ -public class Hasher { - private Hasher() { } +public final class ModuleHashes { /** * A supplier of an encoded message digest. @@ -51,43 +51,49 @@ public class Hasher { String generate(String algorithm); } + + private final String algorithm; + private final Map nameToHash; + /** - * Encapsulates the result of hashing the contents of a number of module - * artifacts. + * Creates a {@code ModuleHashes}. + * + * @param algorithm the algorithm used to create the hashes + * @param nameToHash the map of module name to hash value (in string form) */ - public static class DependencyHashes { - private final String algorithm; - private final Map nameToHash; - - public DependencyHashes(String algorithm, Map nameToHash) { - this.algorithm = algorithm; - this.nameToHash = nameToHash; - } - - /** - * Returns the algorithm used to hash the dependences ("SHA-256" or - * "MD5" for example). - */ - public String algorithm() { - return algorithm; - } - - /** - * Returns the set of module names for which hashes are recorded. - */ - public Set names() { - return nameToHash.keySet(); - } - - /** - * Retruns the hash string for the given module name, {@code null} - * if there is no hash recorded for the module. - */ - public String hashFor(String dn) { - return nameToHash.get(dn); - } + public ModuleHashes(String algorithm, Map nameToHash) { + this.algorithm = algorithm; + this.nameToHash = Collections.unmodifiableMap(nameToHash); } + /** + * Returns the algorithm used to hash the modules ("SHA-256" for example). + */ + public String algorithm() { + return algorithm; + } + + /** + * Returns the set of module names for which hashes are recorded. + */ + public Set names() { + return nameToHash.keySet(); + } + + /** + * Returns the hash string for the given module name, {@code null} + * if there is no hash recorded for the module. + */ + public String hashFor(String mn) { + return nameToHash.get(mn); + } + + /** + * Returns unmodifiable map of module name to hash string. + */ + public Map hashes() { + return nameToHash; + } /** * Computes the hash for the given file with the given message digest @@ -96,7 +102,7 @@ public class Hasher { * @throws UncheckedIOException if an I/O error occurs * @throws RuntimeException if the algorithm is not available */ - public static String generate(Path file, String algorithm) { + public static String computeHashAsString(Path file, String algorithm) { try { MessageDigest md = MessageDigest.getInstance(algorithm); @@ -104,8 +110,7 @@ public class Hasher { // memory when jlink is running concurrently on very large jmods try (FileChannel fc = FileChannel.open(file)) { ByteBuffer bb = ByteBuffer.allocate(32*1024); - int nread; - while ((nread = fc.read(bb)) > 0) { + while (fc.read(bb) > 0) { bb.flip(); md.update(bb); assert bb.remaining() == 0; @@ -124,19 +129,19 @@ public class Hasher { /** * Computes the hash for every entry in the given map, returning a - * {@code DependencyHashes} to encapsulate the result. The map key is + * {@code ModuleHashes} to encapsulate the result. The map key is * the entry name, typically the module name. The map value is the file * path to the entry (module artifact). * - * @return DependencyHashes encapsulate the hashes + * @return ModuleHashes encapsulate the hashes */ - public static DependencyHashes generate(Map map, String algorithm) { + public static ModuleHashes generate(Map map, String algorithm) { Map nameToHash = new HashMap<>(); for (Map.Entry entry: map.entrySet()) { String name = entry.getKey(); Path path = entry.getValue(); - nameToHash.put(name, generate(path, algorithm)); + nameToHash.put(name, computeHashAsString(path, algorithm)); } - return new DependencyHashes(algorithm, nameToHash); + return new ModuleHashes(algorithm, nameToHash); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java index 91d1f8ebae3..f3314aa73e5 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.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 @@ -41,7 +41,6 @@ import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.module.Hasher.DependencyHashes; import static jdk.internal.module.ClassFileAttributes.*; @@ -69,7 +68,7 @@ public final class ModuleInfoExtender { private String osVersion; // the hashes for the Hashes attribute - private DependencyHashes hashes; + private ModuleHashes hashes; private ModuleInfoExtender(InputStream in) { this.in = in; @@ -113,10 +112,10 @@ public final class ModuleInfoExtender { /** * The Hashes attribute will be emitted to the module-info with - * the hashes encapsulated in the given {@code DependencyHashes} + * the hashes encapsulated in the given {@code ModuleHashes} * object. */ - public ModuleInfoExtender hashes(DependencyHashes hashes) { + public ModuleInfoExtender hashes(ModuleHashes hashes) { this.hashes = hashes; return this; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java index f418b666a6d..1fb433b9f7c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.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 @@ -49,28 +49,22 @@ public final class ModuleInfoWriter { * Writes the given module descriptor to a module-info.class file, * returning it in a byte array. */ - private static byte[] toModuleInfo(ModuleDescriptor descriptor) { + private static byte[] toModuleInfo(ModuleDescriptor md) { ClassWriter cw = new ClassWriter(0); - String name = descriptor.name().replace('.', '/') + "/module-info"; + String name = md.name().replace('.', '/') + "/module-info"; cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null); - cw.visitAttribute(new ModuleAttribute(descriptor)); - cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals())); - - Optional oversion = descriptor.version(); - if (oversion.isPresent()) - cw.visitAttribute(new VersionAttribute(oversion.get())); - - Optional omain = descriptor.mainClass(); - if (omain.isPresent()) - cw.visitAttribute(new MainClassAttribute(omain.get())); + cw.visitAttribute(new ModuleAttribute(md)); + cw.visitAttribute(new ConcealedPackagesAttribute(md.conceals())); + md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v))); + md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc))); // write the TargetPlatform attribute if have any of OS name/arch/version - String osName = descriptor.osName().orElse(null); - String osArch = descriptor.osArch().orElse(null); - String osVersion = descriptor.osVersion().orElse(null); + String osName = md.osName().orElse(null); + String osArch = md.osArch().orElse(null); + String osVersion = md.osVersion().orElse(null); if (osName != null || osArch != null || osVersion != null) { cw.visitAttribute(new TargetPlatformAttribute(osName, osArch, diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java index 6104b745b78..49104d8c242 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java @@ -91,56 +91,29 @@ public final class ModulePatcher { Map> map = new HashMap<>(); while (value != null) { + + // =(:)* + int pos = value.indexOf('='); - - if (pos == -1 && index > 0) + if (pos == -1) throwIAE("Unable to parse: " + value); - if (pos == 0) throwIAE("Missing module name: " + value); - if (pos > 0) { + String mn = value.substring(0, pos); + List list = map.get(mn); + if (list != null) + throwIAE("Module " + mn + " specified more than once"); + list = new ArrayList<>(); + map.put(mn, list); - // new format: =(:)* - - String mn = value.substring(0, pos); - List list = map.get(mn); - if (list != null) - throwIAE("Module " + mn + " specified more than once"); - list = new ArrayList<>(); - map.put(mn, list); - - String paths = value.substring(pos+1); - for (String path : paths.split(File.pathSeparator)) { - if (!path.isEmpty()) { - list.add(Paths.get(path)); - } + String paths = value.substring(pos+1); + for (String path : paths.split(File.pathSeparator)) { + if (!path.isEmpty()) { + list.add(Paths.get(path)); } - - } else { - - // old format: (:)* - - assert index == 0; // old format only allowed in first -Xpatch - - String[] dirs = value.split(File.pathSeparator); - for (String d : dirs) { - if (d.length() > 0) { - Path top = Paths.get(d); - try { - Files.list(top).forEach(e -> { - String mn = e.getFileName().toString(); - Path dir = top.resolve(mn); - map.computeIfAbsent(mn, k -> new ArrayList<>()) - .add(dir); - }); - } catch (IOException ignore) { } - } - } - } - index++; value = System.getProperty(PATCH_PROPERTY_PREFIX + index); } @@ -175,7 +148,8 @@ public final class ModulePatcher { for (Path file : paths) { if (Files.isRegularFile(file)) { - // JAR file + // JAR file - do not open as a multi-release JAR as this + // is not supported by the boot class loader try (JarFile jf = new JarFile(file.toFile())) { jf.stream() .filter(e -> e.getName().endsWith(".class")) @@ -209,10 +183,11 @@ public final class ModulePatcher { descriptor = JLMA.newModuleDescriptor(descriptor, packages); } - // return a new module reference + // return a module reference to the patched module URI location = mref.location().orElse(null); - return new ModuleReference(descriptor, location, - () -> new PatchedModuleReader(paths, mref)); + return JLMA.newPatchedModule(descriptor, + location, + () -> new PatchedModuleReader(paths, mref)); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java index b33b1a8e416..9a0248a52df 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.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 @@ -58,7 +58,7 @@ public class Modules { * Creates a new Module. The module has the given ModuleDescriptor and * is defined to the given class loader. * - * The resulting Module is in a larva state in that it does not not read + * The resulting Module is in a larval state in that it does not not read * any other module and does not have any exports. * * The URI is for information purposes only. @@ -74,7 +74,7 @@ public class Modules { * Define a new module to the VM. The module has the given set of * concealed packages and is defined to the given class loader. * - * The resulting Module is in a larva state in that it does not not read + * The resulting Module is in a larval state in that it does not not read * any other module and does not have any exports. */ public static Module defineModule(ClassLoader loader, @@ -95,6 +95,13 @@ public class Modules { JLRMA.addReads(m1, m2); } + /** + * Update module {@code m} to read all unnamed modules. + */ + public static void addReadsAllUnnamed(Module m) { + JLRMA.addReadsAllUnnamed(m); + } + /** * Updates module m1 to export a package to module m2. * Same as m1.addExports(pkg, m2) but without a caller check. diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java index 5d597f9ce55..92b80581d3c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.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 @@ -29,94 +29,105 @@ import java.lang.reflect.Module; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Provides; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.ConcurrentHashMap; /** - * A services catalog. Each {@code ClassLoader} has an optional {@code - * ServicesCatalog} for modules that provide services. This is to support - * ClassLoader centric ServiceLoader.load methods. + * A services catalog. Each {@code ClassLoader} and {@code Layer} has + * an optional {@code ServicesCatalog} for modules that provide services. + * + * @see java.util.ServiceLoader */ -public class ServicesCatalog { - - // use RW locks as register is rare - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Lock readLock = lock.readLock(); - private final Lock writeLock = lock.writeLock(); +public interface ServicesCatalog { /** * Represents a service provider in the services catalog. */ - public class ServiceProvider { + public final class ServiceProvider { private final Module module; private final String providerName; - ServiceProvider(Module module, String providerName) { + + public ServiceProvider(Module module, String providerName) { this.module = module; this.providerName = providerName; } + public Module module() { return module; } + public String providerName() { return providerName; } - } - // service providers - private final Map> loaderServices = new HashMap<>(); + @Override + public int hashCode() { + return Objects.hash(module, providerName); + } - /** - * Creates a new module catalog. - */ - public ServicesCatalog() { } - - /** - * Registers the module in this module catalog. - */ - public void register(Module m) { - ModuleDescriptor descriptor = m.getDescriptor(); - - writeLock.lock(); - try { - // extend the services map - for (Provides ps : descriptor.provides().values()) { - String service = ps.service(); - Set providerNames = ps.providers(); - - // create a new set to replace the existing - Set result = new HashSet<>(); - Set providers = loaderServices.get(service); - if (providers != null) { - result.addAll(providers); - } - for (String pn : providerNames) { - result.add(new ServiceProvider(m, pn)); - } - loaderServices.put(service, Collections.unmodifiableSet(result)); - } - - } finally { - writeLock.unlock(); + @Override + public boolean equals(Object ob) { + if (!(ob instanceof ServiceProvider)) + return false; + ServiceProvider that = (ServiceProvider)ob; + return Objects.equals(this.module, that.module) + && Objects.equals(this.providerName, that.providerName); } } + /** + * Registers the providers in the given module in this services catalog. + * + * @throws UnsupportedOperationException + * If this services catalog is immutable + */ + void register(Module module); + /** * Returns the (possibly empty) set of service providers that implement the * given service type. - * - * @see java.util.ServiceLoader */ - public Set findServices(String service) { - readLock.lock(); - try { - return loaderServices.getOrDefault(service, Collections.emptySet()); - } finally { - readLock.unlock(); - } + Set findServices(String service); + + /** + * Creates a ServicesCatalog that supports concurrent registration and + * and lookup. + */ + static ServicesCatalog create() { + return new ServicesCatalog() { + + private Map> map = new ConcurrentHashMap<>(); + + @Override + public void register(Module m) { + ModuleDescriptor descriptor = m.getDescriptor(); + + for (Provides provides : descriptor.provides().values()) { + String service = provides.service(); + Set providerNames = provides.providers(); + + // create a new set to replace the existing + Set result = new HashSet<>(); + Set providers = map.get(service); + if (providers != null) { + result.addAll(providers); + } + for (String pn : providerNames) { + result.add(new ServiceProvider(m, pn)); + } + map.put(service, Collections.unmodifiableSet(result)); + } + + } + + @Override + public Set findServices(String service) { + return map.getOrDefault(service, Collections.emptySet()); + } + + }; } -} +} \ No newline at end of file diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java index 3bd1371ee7d..43de2cda9f7 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java @@ -40,21 +40,26 @@ import java.lang.module.ModuleDescriptor; */ public final class SystemModules { /** - * Name of the installed modules. + * Name of the system modules. * - * This array provides a way for InstalledModuleFinder to fallback + * This array provides a way for SystemModuleFinder to fallback * and read module-info.class from the run-time image instead of * the fastpath. */ public static final String[] MODULE_NAMES = new String[1]; + /** + * Hash of system modules. + */ + public static String[] MODULES_TO_HASH = new String[1]; + /** * Number of packages in the boot layer from the installed modules. * * Don't make it final to avoid inlining during compile time as * the value will be changed at jlink time. */ - public static final int PACKAGES_IN_BOOT_LAYER = 1024; + public static int PACKAGES_IN_BOOT_LAYER = 1024; /** * Returns a non-empty array of ModuleDescriptors in the run-time image. @@ -64,4 +69,5 @@ public final class SystemModules { public static ModuleDescriptor[] modules() { return new ModuleDescriptor[0]; } -} \ No newline at end of file + +} diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 942c0582ea0..09816138126 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -168,6 +168,8 @@ module java.base { java.sql, java.xml, jdk.charsets, + jdk.jartool, + jdk.jlink, jdk.scripting.nashorn, jdk.unsupported, jdk.vm.ci; diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 52d621b414d..6390b9792d4 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -27,7 +27,7 @@ java.launcher.opt.header = Usage: {0} [options] class [args...]\n\ \ (to execute a class)\n or {0} [options] -jar jarfile [args...]\n\ \ (to execute a jar file)\n\ -\ or {0} [-options] -mp -m | /\n\ +\ or {0} [options] -mp -m [/] [args...]\n\ \ (to execute the main class in a module)\n\ where options include:\n @@ -51,8 +51,9 @@ java.launcher.opt.footer =\ -cp | /\n\ -\ the initial or main module to resolve\n\ +\ -m [/]\n\ +\ the initial module to resolve, and the name of the main class\n\ +\ to execute if not specified by the module\n\ \ -addmods [,...]\n\ \ root modules to resolve in addition to the initial module\n\ \ -limitmods [,...]\n\ diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java index 6c97d25b086..49781d7561d 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java @@ -136,10 +136,10 @@ class GNUStyleOptions { jartool.moduleVersion = Version.parse(arg); } }, - new Option(true, OptionType.CREATE_UPDATE, "--hash-dependencies") { + new Option(true, OptionType.CREATE_UPDATE, "--hash-modules") { void process(Main jartool, String opt, String arg) throws BadArgs { try { - jartool.dependenciesToHash = Pattern.compile(arg); + jartool.modulesToHash = Pattern.compile(arg); } catch (PatternSyntaxException e) { throw new BadArgs("err.badpattern", arg).showUsage(true); } diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index ffe38159603..0559fff5540 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -26,21 +26,25 @@ package sun.tools.jar; import java.io.*; +import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Version; import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; -import java.lang.reflect.Method; +import java.lang.module.ResolutionException; +import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.file.Path; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; import java.util.function.Consumer; -import java.util.regex.Matcher; +import java.util.function.Function; +import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.zip.*; @@ -49,9 +53,12 @@ import java.util.jar.Pack200.*; import java.util.jar.Manifest; import java.text.MessageFormat; -import jdk.internal.module.Hasher; +import jdk.internal.misc.JavaLangModuleAccess; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.ModuleHashes; import jdk.internal.module.ModuleInfoExtender; import jdk.internal.util.jar.JarIndex; + import static jdk.internal.util.jar.JarIndex.INDEX_NAME; import static java.util.jar.JarFile.MANIFEST_NAME; import static java.util.stream.Collectors.joining; @@ -117,7 +124,7 @@ class Main { /* Modular jar related options */ boolean printModuleDescriptor; Version moduleVersion; - Pattern dependenciesToHash; + Pattern modulesToHash; ModuleFinder moduleFinder = ModuleFinder.empty(); private static final String MODULE_INFO = "module-info.class"; @@ -241,7 +248,7 @@ class Main { if (isModularJar()) { moduleInfoBytes = addExtendedModuleAttributes( readModuleInfo(moduleInfo)); - } else if (moduleVersion != null || dependenciesToHash != null) { + } else if (moduleVersion != null || modulesToHash != null) { error(getMsg("error.module.options.without.info")); return false; } @@ -801,7 +808,7 @@ class Main { } } else if (isModuleInfoEntry && ((newModuleInfoBytes != null) || (ename != null) - || moduleVersion != null || dependenciesToHash != null)) { + || moduleVersion != null || modulesToHash != null)) { if (newModuleInfoBytes == null) { // Update existing module-info.class newModuleInfoBytes = readModuleInfo(zis); @@ -861,7 +868,7 @@ class Main { if (!updateModuleInfo(newModuleInfoBytes, zos)) { updateOk = false; } - } else if (moduleVersion != null || dependenciesToHash != null) { + } else if (moduleVersion != null || modulesToHash != null) { error(getMsg("error.module.options.without.info")); updateOk = false; } @@ -1642,70 +1649,60 @@ class Main { return false; } - @SuppressWarnings("unchecked") + static String toString(Set set) { + if (set.isEmpty()) { return ""; } + return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT)) + .collect(joining(" ")); + } + + private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); + private void printModuleDescriptor(InputStream entryInputStream) throws IOException { ModuleDescriptor md = ModuleDescriptor.read(entryInputStream); StringBuilder sb = new StringBuilder(); - sb.append("\nName:\n " + md.toNameAndVersion()); + sb.append("\n").append(md.toNameAndVersion()); - Set requires = md.requires(); - if (!requires.isEmpty()) { - sb.append("\nRequires:"); - requires.forEach(r -> - sb.append("\n ").append(r.name()) - .append(toString(r.modifiers(), " [ ", " ]"))); - } + md.requires().stream() + .sorted(Comparator.comparing(Requires::name)) + .forEach(r -> { + sb.append("\n requires "); + if (!r.modifiers().isEmpty()) + sb.append(toString(r.modifiers())).append(" "); + sb.append(r.name()); + }); - Set s = md.uses(); - if (!s.isEmpty()) { - sb.append("\nUses: "); - s.forEach(sv -> sb.append("\n ").append(sv)); - } + md.uses().stream().sorted() + .forEach(p -> sb.append("\n uses ").append(p)); - Set exports = md.exports(); - if (!exports.isEmpty()) { - sb.append("\nExports:"); - exports.forEach(sv -> sb.append("\n ").append(sv)); - } + md.exports().stream() + .sorted(Comparator.comparing(Exports::source)) + .forEach(p -> sb.append("\n exports ").append(p)); - Map provides = md.provides(); - if (!provides.isEmpty()) { - sb.append("\nProvides: "); - provides.values().forEach(p -> - sb.append("\n ").append(p.service()) - .append(" with ") - .append(toString(p.providers(), "", ""))); - } + md.conceals().stream().sorted() + .forEach(p -> sb.append("\n conceals ").append(p)); - Optional mc = md.mainClass(); - if (mc.isPresent()) - sb.append("\nMain class:\n " + mc.get()); + md.provides().values().stream() + .sorted(Comparator.comparing(Provides::service)) + .forEach(p -> sb.append("\n provides ").append(p.service()) + .append(" with ") + .append(toString(p.providers()))); - s = md.conceals(); - if (!s.isEmpty()) { - sb.append("\nConceals:"); - s.forEach(p -> sb.append("\n ").append(p)); - } + md.mainClass().ifPresent(v -> sb.append("\n main-class " + v)); - try { - Method m = ModuleDescriptor.class.getDeclaredMethod("hashes"); - m.setAccessible(true); - Optional optHashes = - (Optional) m.invoke(md); + md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v)); + + md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v)); + + md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v)); + + JLMA.hashes(md).ifPresent(hashes -> + hashes.names().stream().sorted().forEach( + mod -> sb.append("\n hashes ").append(mod).append(" ") + .append(hashes.algorithm()).append(" ") + .append(hashes.hashFor(mod)))); - if (optHashes.isPresent()) { - Hasher.DependencyHashes hashes = optHashes.get(); - sb.append("\nHashes:"); - sb.append("\n Algorithm: " + hashes.algorithm()); - hashes.names().stream().forEach(mod -> - sb.append("\n ").append(mod) - .append(": ").append(hashes.hashFor(mod))); - } - } catch (ReflectiveOperationException x) { - throw new InternalError(x); - } output(sb.toString()); } @@ -1751,7 +1748,6 @@ class Main { md = ModuleDescriptor.read(in); } String name = md.name(); - Set dependences = md.requires(); Set exported = md.exports() .stream() .map(ModuleDescriptor.Exports::source) @@ -1778,9 +1774,17 @@ class Main { if (moduleVersion != null) extender.version(moduleVersion); - // --hash-dependencies - if (dependenciesToHash != null) - extender.hashes(hashDependences(name, dependences)); + // --hash-modules + if (modulesToHash != null) { + Hasher hasher = new Hasher(md, fname); + ModuleHashes moduleHashes = hasher.computeHashes(name); + if (moduleHashes != null) { + extender.hashes(moduleHashes); + } else { + // should it issue warning or silent? + System.out.println("warning: no module is recorded in hash in " + name); + } + } extender.write(baos); return baos.toByteArray(); @@ -1788,36 +1792,156 @@ class Main { } /** - * Examines the module dependences of the given module and computes the - * hash of any module that matches the pattern {@code dependenciesToHash}. + * Compute and record hashes */ - private Hasher.DependencyHashes - hashDependences(String name, - Set moduleDependences) - throws IOException - { - Map map = new HashMap<>(); - Matcher matcher = dependenciesToHash.matcher(""); - for (ModuleDescriptor.Requires md: moduleDependences) { - String dn = md.name(); - if (matcher.reset(dn).find()) { - Optional omref = moduleFinder.find(dn); - if (!omref.isPresent()) { - throw new IOException(formatMsg2("error.hash.dep", name , dn)); - } - map.put(dn, modRefToPath(omref.get())); + private class Hasher { + final ModuleFinder finder; + final Map moduleNameToPath; + final Set modules; + final Configuration configuration; + Hasher(ModuleDescriptor descriptor, String fname) throws IOException { + // Create a module finder that finds the modular JAR + // being created/updated + URI uri = Paths.get(fname).toUri(); + ModuleReference mref = new ModuleReference(descriptor, uri, + new Supplier<>() { + @Override + public ModuleReader get() { + throw new UnsupportedOperationException("should not reach here"); + } + }); + + // Compose a module finder with the module path and + // the modular JAR being created or updated + this.finder = ModuleFinder.compose(moduleFinder, + new ModuleFinder() { + @Override + public Optional find(String name) { + if (descriptor.name().equals(name)) + return Optional.of(mref); + else + return Optional.empty(); + } + + @Override + public Set findAll() { + return Collections.singleton(mref); + } + }); + + // Determine the modules that matches the modulesToHash pattern + this.modules = moduleFinder.findAll().stream() + .map(moduleReference -> moduleReference.descriptor().name()) + .filter(mn -> modulesToHash.matcher(mn).find()) + .collect(Collectors.toSet()); + + // a map from a module name to Path of the modular JAR + this.moduleNameToPath = moduleFinder.findAll().stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn))); + + Configuration config = null; + try { + config = Configuration.empty() + .resolveRequires(ModuleFinder.ofSystem(), finder, modules); + } catch (ResolutionException e) { + // should it throw an error? or emit a warning + System.out.println("warning: " + e.getMessage()); } + this.configuration = config; } - if (map.size() == 0) { - return null; - } else { - return Hasher.generate(map, "SHA-256"); - } - } + /** + * Compute hashes of the modules that depend upon the specified + * module directly or indirectly. + */ + ModuleHashes computeHashes(String name) { + // the transposed graph includes all modules in the resolved graph + Map> graph = transpose(); - private static Path modRefToPath(ModuleReference mref) { - URI location = mref.location().get(); - return Paths.get(location); + // find the modules that transitively depend upon the specified name + Deque deque = new ArrayDeque<>(); + deque.add(name); + Set mods = visitNodes(graph, deque); + + // filter modules matching the pattern specified --hash-modules + // as well as itself as the jmod file is being generated + Map modulesForHash = mods.stream() + .filter(mn -> !mn.equals(name) && modules.contains(mn)) + .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get)); + + if (modulesForHash.isEmpty()) + return null; + + return ModuleHashes.generate(modulesForHash, "SHA-256"); + } + + /** + * Returns all nodes traversed from the given roots. + */ + private Set visitNodes(Map> graph, + Deque roots) { + Set visited = new HashSet<>(); + while (!roots.isEmpty()) { + String mn = roots.pop(); + if (!visited.contains(mn)) { + visited.add(mn); + + // the given roots may not be part of the graph + if (graph.containsKey(mn)) { + for (String dm : graph.get(mn)) { + if (!visited.contains(dm)) + roots.push(dm); + } + } + } + } + return visited; + } + + /** + * Returns a transposed graph from the resolved module graph. + */ + private Map> transpose() { + Map> transposedGraph = new HashMap<>(); + Deque deque = new ArrayDeque<>(modules); + + Set visited = new HashSet<>(); + while (!deque.isEmpty()) { + String mn = deque.pop(); + if (!visited.contains(mn)) { + visited.add(mn); + + // add an empty set + transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>()); + + ResolvedModule resolvedModule = configuration.findModule(mn).get(); + for (ResolvedModule dm : resolvedModule.reads()) { + String name = dm.name(); + if (!visited.contains(name)) { + deque.push(name); + } + // reverse edge + transposedGraph.computeIfAbsent(name, _k -> new HashSet<>()) + .add(mn); + } + } + } + return transposedGraph; + } + + private Path moduleToPath(String name) { + ModuleReference mref = moduleFinder.find(name).orElseThrow( + () -> new InternalError(formatMsg2("error.hash.dep",name , name))); + + URI uri = mref.location().get(); + Path path = Paths.get(uri); + String fn = path.getFileName().toString(); + if (!fn.endsWith(".jar")) { + throw new UnsupportedOperationException(path + " is not a modular JAR"); + } + return path; + } } } diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties index a880d9f1592..0b21bca8c06 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties @@ -57,7 +57,7 @@ error.create.tempfile=\ error.hash.dep=\ Hashing module {0} dependences, unable to find module {1} on module path error.module.options.without.info=\ - One of --module-version or --hash-dependencies without module-info.class + One of --module-version or --hash-modules without module-info.class error.unexpected.module-info=\ Unexpected module descriptor {0} error.module.descriptor.not.found=\ @@ -178,11 +178,11 @@ main.help.opt.create.update.no-manifest=\ main.help.opt.create.update.module-version=\ \ --module-version=VERSION The module version, when creating a modular\n\ \ jar, or updating a non-modular jar -main.help.opt.create.update.hash-dependencies=\ -\ --hash-dependencies=PATTERN Compute and record the hashes of module\n\ -\ dependencies matched by the given pattern, when\n\ -\ creating a modular jar, or updating a non-modular\n\ -\ jar +main.help.opt.create.update.hash-modules=\ +\ --hash-modules=PATTERN Compute and record the hashes of modules \n\ +\ matched by the given pattern and that depend upon\n\ +\ directly or indirectly on a modular jar being\n\ +\ created or a non-modular jar being updated main.help.opt.create.update.modulepath=\ \ --modulepath Location of module dependence for generating \ the hash @@ -201,7 +201,7 @@ main.help.postopt=\ \ located in the root of the given directories, or the root of the jar archive\n\ \ itself. The following operations are only valid when creating a modular jar,\n\ \ or updating an existing non-modular jar: '--module-version',\n\ -\ '--hash-dependencies', and '--modulepath'.\n\ +\ '--hash-modules', and '--modulepath'.\n\ \n\ \ Mandatory or optional arguments to long options are also mandatory or optional\n\ \ for any corresponding short options. \ No newline at end of file diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java index eb1e057d182..a3943145c06 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java @@ -95,27 +95,23 @@ public class DefaultImageBuilder implements ImageBuilder { private final Path root; private final Path mdir; - private final boolean genBom; private final Set modules = new HashSet<>(); /** * Default image builder constructor. * - * @param genBom true, generates a bom file. * @param root The image root directory. * @throws IOException */ - public DefaultImageBuilder(boolean genBom, Path root) throws IOException { + public DefaultImageBuilder(Path root) throws IOException { Objects.requireNonNull(root); - this.genBom = genBom; - this.root = root; this.mdir = root.resolve("lib"); Files.createDirectories(mdir); } - private void storeFiles(Set modules, String bom, Properties release) throws IOException { + private void storeFiles(Set modules, Properties release) throws IOException { if (release != null) { addModules(release, modules); File r = new File(root.toFile(), "release"); @@ -123,11 +119,6 @@ public class DefaultImageBuilder implements ImageBuilder { release.store(fo, null); } } - // Generate bom - if (genBom) { - File bomFile = new File(root.toFile(), "bom"); - createUtf8File(bomFile, bom); - } } private void addModules(Properties release, Set modules) throws IOException { @@ -144,7 +135,7 @@ public class DefaultImageBuilder implements ImageBuilder { } @Override - public void storeFiles(Pool files, String bom, Properties release) { + public void storeFiles(Pool files, Properties release) { try { for (ModuleData f : files.getContent()) { if (!f.getType().equals(Pool.ModuleDataType.CLASS_OR_RESOURCE)) { @@ -161,7 +152,7 @@ public class DefaultImageBuilder implements ImageBuilder { modules.add(m.getName()); } } - storeFiles(modules, bom, release); + storeFiles(modules, release); if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) { // launchers in the bin directory need execute permission @@ -190,8 +181,8 @@ public class DefaultImageBuilder implements ImageBuilder { } @Override - public void storeFiles(Pool files, String bom) { - storeFiles(files, bom, new Properties()); + public void storeFiles(Pool files) { + storeFiles(files, new Properties()); } /** @@ -213,28 +204,48 @@ public class DefaultImageBuilder implements ImageBuilder { mainClass = ModuleDescriptor.read(stream).mainClass(); if (mainClass.isPresent()) { Path cmd = root.resolve("bin").resolve(module); - if (!Files.exists(cmd)) { - StringBuilder sb = new StringBuilder(); - sb.append("#!/bin/sh") - .append("\n"); - sb.append("JLINK_VM_OPTIONS=") - .append("\n"); - sb.append("DIR=`dirname $0`") - .append("\n"); - sb.append("$DIR/java $JLINK_VM_OPTIONS -m ") + // generate shell script for Unix platforms + StringBuilder sb = new StringBuilder(); + sb.append("#!/bin/sh") + .append("\n"); + sb.append("JLINK_VM_OPTIONS=") + .append("\n"); + sb.append("DIR=`dirname $0`") + .append("\n"); + sb.append("$DIR/java $JLINK_VM_OPTIONS -m ") + .append(module).append('/') + .append(mainClass.get()) + .append(" $@\n"); + + try (BufferedWriter writer = Files.newBufferedWriter(cmd, + StandardCharsets.ISO_8859_1, + StandardOpenOption.CREATE_NEW)) { + writer.write(sb.toString()); + } + if (Files.getFileStore(root.resolve("bin")) + .supportsFileAttributeView(PosixFileAttributeView.class)) { + setExecutable(cmd); + } + // generate .bat file for Windows + if (isWindows()) { + Path bat = root.resolve("bin").resolve(module + ".bat"); + sb = new StringBuilder(); + sb.append("@echo off") + .append("\r\n"); + sb.append("set JLINK_VM_OPTIONS=") + .append("\r\n"); + sb.append("set DIR=%~dp0") + .append("\r\n"); + sb.append("\"%DIR%\\java\" %JLINK_VM_OPTIONS% -m ") .append(module).append('/') .append(mainClass.get()) - .append(" $@\n"); + .append(" %*\r\n"); - try (BufferedWriter writer = Files.newBufferedWriter(cmd, + try (BufferedWriter writer = Files.newBufferedWriter(bat, StandardCharsets.ISO_8859_1, StandardOpenOption.CREATE_NEW)) { writer.write(sb.toString()); } - if (Files.getFileStore(root.resolve("bin")) - .supportsFileAttributeView(PosixFileAttributeView.class)) { - setExecutable(cmd); - } } } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java index 5942bd64c85..dc0bf71c535 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java @@ -42,22 +42,20 @@ public interface ImageBuilder { * Store the external files. * * @param content Pool of module content. - * @param bom The options used to build the image file. * @param release the release properties * @throws PluginException */ - public default void storeFiles(Pool content, String bom, Properties release) { - storeFiles(content, bom); + public default void storeFiles(Pool content, Properties release) { + storeFiles(content); } /** * Store the external files. * * @param content Pool of module content. - * @param bom The options used to build the image file. * @throws PluginException */ - public default void storeFiles(Pool content, String bom) { + public default void storeFiles(Pool content) { throw new UnsupportedOperationException("storeFiles"); } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java index 6246e29afc2..e0347e52a21 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java @@ -88,7 +88,7 @@ public final class ImageFileCreator { ByteOrder byteOrder) throws IOException { return ImageFileCreator.create(archives, byteOrder, - new ImagePluginStack(null)); + new ImagePluginStack()); } public static ExecutableImage create(Set archives, diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java index ac96a796f5b..7bd631a8c72 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginConfiguration.java @@ -68,20 +68,13 @@ public final class ImagePluginConfiguration { private ImagePluginConfiguration() { } - public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration plugins) - throws Exception { - return parseConfiguration(plugins, null); - } - /* * Create a stack of plugins from a a configuration. - * */ - public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration pluginsConfiguration, - String bom) + public static ImagePluginStack parseConfiguration(Jlink.PluginsConfiguration pluginsConfiguration) throws Exception { if (pluginsConfiguration == null) { - return new ImagePluginStack(bom); + return new ImagePluginStack(); } Map> plugins = new LinkedHashMap<>(); for (Plugin.CATEGORY cat : CATEGORIES_ORDER) { @@ -150,7 +143,7 @@ public final class ImagePluginConfiguration { } @Override - public void storeFiles(Pool files, String bom) { + public void storeFiles(Pool files) { throw new PluginException("No directory setup to store files"); } }; @@ -158,6 +151,6 @@ public final class ImagePluginConfiguration { PluginContext ctxt = pluginsConfiguration.getPluginContext(); return new ImagePluginStack(builder, transformerPlugins, - lastSorter, postProcessingPlugins, ctxt, bom); + lastSorter, postProcessingPlugins, ctxt); } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java index 646cc5ce558..6a5db82ccdf 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java @@ -167,28 +167,25 @@ public final class ImagePluginStack { private final ImageBuilder imageBuilder; private final Properties release; - private final String bom; - public ImagePluginStack(String bom) { + public ImagePluginStack() { this(null, Collections.emptyList(), null, - Collections.emptyList(), null, bom); + Collections.emptyList(), null); } public ImagePluginStack(ImageBuilder imageBuilder, List contentPlugins, Plugin lastSorter, - List postprocessingPlugins, - String bom) { + List postprocessingPlugins) { this(imageBuilder, contentPlugins, lastSorter, - postprocessingPlugins, null, bom); + postprocessingPlugins, null); } public ImagePluginStack(ImageBuilder imageBuilder, List contentPlugins, Plugin lastSorter, List postprocessingPlugins, - PluginContext ctxt, - String bom) { + PluginContext ctxt) { Objects.requireNonNull(contentPlugins); this.lastSorter = lastSorter; for (TransformerPlugin p : contentPlugins) { @@ -204,7 +201,6 @@ public final class ImagePluginStack { } this.imageBuilder = imageBuilder; this.release = ctxt != null? ctxt.getReleaseProperties() : new Properties(); - this.bom = bom; } public void operate(ImageProvider provider) throws Exception { @@ -479,7 +475,7 @@ public final class ImagePluginStack { } catch (Exception ignored) { } - imageBuilder.storeFiles(new LastPool(transformed), bom, release); + imageBuilder.storeFiles(new LastPool(transformed), release); } public ExecutableImage getExecutableImage() throws IOException { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index e3b225ff305..a5b4ba6e4a9 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -70,6 +70,7 @@ import jdk.tools.jlink.plugin.Plugin; * ## Should use jdk.joptsimple some day. */ public class JlinkTask { + private static final boolean DEBUG = Boolean.getBoolean("jlink.debug"); private static void fail(Class type, String format, @@ -142,9 +143,6 @@ public class JlinkTask { } task.options.packagedModulesPath = path; }, true, "--keep-packaged-modules"), - new Option(false, (task, opt, arg) -> { - task.options.genbom = true; - }, true, "--genbom"), new Option(true, (task, opt, arg) -> { task.options.saveoptsfile = arg; }, "--saveopts"), @@ -175,7 +173,6 @@ public class JlinkTask { static class OptionsValues { boolean help; - boolean genbom; String saveoptsfile; boolean version; boolean fullVersion; @@ -219,18 +216,24 @@ public class JlinkTask { } return EXIT_OK; - } catch (UncheckedIOException | PluginException | IOException | ResolutionException e) { + } catch (UncheckedIOException | PluginException | IllegalArgumentException | + IOException | ResolutionException e) { log.println(taskHelper.getMessage("error.prefix") + " " + e.getMessage()); - log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + if (DEBUG) { + e.printStackTrace(log); + } return EXIT_ERROR; } catch (BadArgs e) { taskHelper.reportError(e.key, e.args); if (e.showUsage) { log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); } + if (DEBUG) { + e.printStackTrace(log); + } return EXIT_CMDERR; } catch (Throwable x) { - log.println(taskHelper.getMessage("main.msg.bug")); + log.println(taskHelper.getMessage("error.prefix") + " " + x.getMessage()); x.printStackTrace(log); return EXIT_ABNORMAL; } finally { @@ -238,16 +241,6 @@ public class JlinkTask { } } - private static Map modulesToPath(Configuration cf) { - Map modPaths = new HashMap<>(); - for (ResolvedModule resolvedModule : cf.modules()) { - ModuleReference mref = resolvedModule.reference(); - URI uri = mref.location().get(); - modPaths.put(mref.descriptor().name(), Paths.get(uri)); - } - return modPaths; - } - /* * Jlink API entry point. */ @@ -275,8 +268,7 @@ public class JlinkTask { null); // Then create the Plugin Stack - ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins, - genBOMContent(config, plugins)); + ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins); //Ask the stack to proceed; stack.operate(imageProvider); @@ -297,7 +289,7 @@ public class JlinkTask { } private void postProcessOnly(Path existingImage) throws Exception { - PluginsConfiguration config = taskHelper.getPluginsConfig(null, false); + PluginsConfiguration config = taskHelper.getPluginsConfig(null); ExecutableImage img = DefaultImageBuilder.getExecutableImage(existingImage); if (img == null) { throw taskHelper.newBadArgs("err.existing.image.invalid"); @@ -327,8 +319,7 @@ public class JlinkTask { // Then create the Plugin Stack ImagePluginStack stack = ImagePluginConfiguration. - parseConfiguration(taskHelper.getPluginsConfig(options.output, options.genbom), - genBOMContent()); + parseConfiguration(taskHelper.getPluginsConfig(options.output)); //Ask the stack to proceed stack.operate(imageProvider); @@ -358,6 +349,15 @@ public class JlinkTask { return finder; } + + private static Path toPathLocation(ResolvedModule m) { + Optional ouri = m.reference().location(); + if (!ouri.isPresent()) + throw new InternalError(m + " does not have a location"); + URI uri = ouri.get(); + return Paths.get(uri); + } + private static ImageProvider createImageProvider(ModuleFinder finder, Set addMods, Set limitMods, @@ -374,7 +374,8 @@ public class JlinkTask { ModuleFinder.empty(), addMods); - Map mods = modulesToPath(cf); + Map mods = cf.modules().stream() + .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation)); return new ImageHelper(cf, mods, order, retainModulesPath); } @@ -399,21 +400,15 @@ public class JlinkTask { map.put(mref.descriptor().name(), mref); }); + // add the other modules + otherMods.stream() + .map(finder::find) + .flatMap(Optional::stream) + .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref)); + // set of modules that are observable Set mrefs = new HashSet<>(map.values()); - // add the other modules - for (String mod : otherMods) { - Optional omref = finder.find(mod); - if (omref.isPresent()) { - ModuleReference mref = omref.get(); - map.putIfAbsent(mod, mref); - mrefs.add(mref); - } else { - // no need to fail - } - } - return new ModuleFinder() { @Override public Optional find(String name) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index 11df906f292..31064ab79d6 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -337,8 +337,8 @@ public final class TaskHelper { return null; } - private PluginsConfiguration getPluginsConfig(Path output, - boolean genbom) throws IOException, BadArgs { + private PluginsConfiguration getPluginsConfig(Path output + ) throws IOException, BadArgs { if (output != null) { if (Files.exists(output)) { throw new PluginException(PluginsResourceBundle. @@ -367,7 +367,7 @@ public final class TaskHelper { // recreate or postprocessing don't require an output directory. ImageBuilder builder = null; if (output != null) { - builder = new DefaultImageBuilder(genbom, output); + builder = new DefaultImageBuilder(output); } return new Jlink.PluginsConfiguration(pluginsList, @@ -676,9 +676,9 @@ public final class TaskHelper { + bundleHelper.getMessage(key, args)); } - public PluginsConfiguration getPluginsConfig(Path output, boolean genbom) + public PluginsConfiguration getPluginsConfig(Path output) throws IOException, BadArgs { - return pluginOptions.getPluginsConfig(output, genbom); + return pluginOptions.getPluginsConfig(output); } public Path getExistingImage() { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java new file mode 100644 index 00000000000..e448acd0b1d --- /dev/null +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java @@ -0,0 +1,146 @@ +/* + * 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.tools.jlink.internal.packager; + + +import jdk.tools.jlink.Jlink; +import jdk.tools.jlink.builder.ImageBuilder; +import jdk.tools.jlink.plugin.Plugin; +import jdk.tools.jlink.builder.*; +import jdk.tools.jlink.plugin.Pool; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; +import java.util.stream.Collectors; + +/** + * AppRuntimeImageBuilder is a private API used only by the Java Packager to generate + * a Java runtime image using jlink. AppRuntimeImageBuilder encapsulates the + * arguments that jlink requires to generate this image. To create the image call the + * build() method. + */ +public final class AppRuntimeImageBuilder { + private Path outputDir = null; + private List modulePath = null; + private Set addModules = null; + private Set limitModules = null; + private String excludeFileList = null; + private Map userArguments = null; + private Boolean stripNativeCommands = null; + + public AppRuntimeImageBuilder() {} + + public void setOutputDir(Path value) { + outputDir = value; + } + + public void setModulePath(List value) { + modulePath = value; + } + + public void setAddModules(Set value) { + addModules = value; + } + + public void setLimitModules(Set value) { + limitModules = value; + } + + public void setExcludeFileList(String value) { + excludeFileList = value; + } + + public void setStripNativeCommands(boolean value) { + stripNativeCommands = value; + } + + public void setUserArguments(Map value) { + userArguments = value; + } + + public void build() throws IOException { + // jlink main arguments + Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration( + new File("").toPath(), // Unused + modulePath, addModules, limitModules); + + // plugin configuration + List plugins = new ArrayList(); + + if (stripNativeCommands) { + plugins.add(Jlink.newPlugin( + "strip-native-commands", + Collections.singletonMap("strip-native-commands", "on"), + null)); + } + + if (excludeFileList != null && !excludeFileList.isEmpty()) { + plugins.add(Jlink.newPlugin( + "exclude-files", + Collections.singletonMap("exclude-files", excludeFileList), + null)); + } + + // add user supplied jlink arguments + for (Map.Entry entry : userArguments.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + plugins.add(Jlink.newPlugin(key, + Collections.singletonMap(key, value), + null)); + } + + plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null)); + + // build the image + Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration( + plugins, new DefaultImageBuilder(outputDir), null); + Jlink jlink = new Jlink(); + jlink.build(jlinkConfig, pluginConfig); + } +} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java index e29f42eb6a2..aa068f1136e 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/DefaultCompressPlugin.java @@ -125,7 +125,7 @@ public final class DefaultCompressPlugin implements TransformerPlugin, ResourceP zip = new ZipPlugin(resFilter); break; default: - throw new PluginException("Invalid level " + level); + throw new IllegalArgumentException("Invalid compression level " + level); } } else { ss = new StringSharingPlugin(resFilter); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java index 185906d4c82..4d502904c37 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java @@ -208,7 +208,7 @@ public final class ExcludeVMPlugin implements TransformerPlugin { break; } default: { - throw new PluginException("Unknown option " + value); + throw new IllegalArgumentException("Unknown exclude VM option: " + value); } } predicate = new ResourceFilter(Utils.listParser.apply(exclude), true); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java index 4630d0992eb..c67a378b8e0 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java @@ -164,7 +164,7 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr try { return new Locale.LanguageRange(s); } catch (IllegalArgumentException iae) { - throw new PluginException(String.format( + throw new IllegalArgumentException(String.format( PluginsResourceBundle.getMessage(NAME + ".invalidtag"), s)); } }) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java index bd0a9a74f4b..4f8e5eade53 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java @@ -273,7 +273,7 @@ public final class OptimizationPlugin extends AsmPlugin { } else if (s.equals(FORNAME_REMOVAL)) { optimizers.add(new ForNameFolding()); } else { - throw new PluginException("Unknown optimization"); + throw new IllegalArgumentException("Unknown optimization: " + s); } } String f = config.get(LOG); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java index edf6475cb4b..f4cba7607ea 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java @@ -39,6 +39,8 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import jdk.internal.misc.JavaLangModuleAccess; +import jdk.internal.misc.SharedSecrets; import jdk.internal.module.Checks; import jdk.internal.module.ModuleInfoExtender; import jdk.internal.module.SystemModules; @@ -50,6 +52,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.plugin.Pool; import jdk.tools.jlink.plugin.TransformerPlugin; +import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*; /** * Jlink plugin to reconstitute module descriptors for installed modules. @@ -63,6 +66,8 @@ import jdk.tools.jlink.plugin.TransformerPlugin; * @see SystemModules */ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { + private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); + // TODO: packager has the dependency on the plugin name // Keep it as "--installed-modules" until packager removes such // dependency (should not need to specify this plugin since it @@ -118,7 +123,8 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { Pool.ModuleData data = module.get("module-info.class"); if (data == null) { // automatic module not supported yet - throw new PluginException("module-info.class not found for " + module.getName() + " module"); + throw new PluginException("module-info.class not found for " + + module.getName() + " module"); } assert module.getName().equals(data.getModule()); try { @@ -126,15 +132,20 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { ModuleDescriptor md = ModuleDescriptor.read(bain); validateNames(md); - Builder.ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages()); + ModuleDescriptorBuilder mbuilder = builder.module(md, module.getAllPackages()); + int packages = md.exports().size() + md.conceals().size(); if (md.conceals().isEmpty() && - (md.exports().size() + md.conceals().size()) != module.getAllPackages().size()) { + packages != module.getAllPackages().size()) { // add ConcealedPackages attribute if not exist bain.reset(); - ModuleInfoRewriter minfoWriter = new ModuleInfoRewriter(bain, mbuilder.conceals()); + ModuleInfoRewriter minfoWriter = + new ModuleInfoRewriter(bain, mbuilder.conceals()); // replace with the overridden version - data = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(), - minfoWriter.stream(), minfoWriter.size()); + data = new Pool.ModuleData(data.getModule(), + data.getPath(), + data.getType(), + minfoWriter.stream(), + minfoWriter.size()); } out.add(data); } catch (IOException e) { @@ -151,8 +162,12 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { if (builder.isOverriddenClass(data.getPath())) { byte[] bytes = cwriter.toByteArray(); - Pool.ModuleData ndata = new Pool.ModuleData(data.getModule(), data.getPath(), data.getType(), - new ByteArrayInputStream(bytes), bytes.length); + Pool.ModuleData ndata = + new Pool.ModuleData(data.getModule(), + data.getPath(), + data.getType(), + new ByteArrayInputStream(bytes), + bytes.length); out.add(ndata); } else { out.add(data); @@ -230,6 +245,7 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { // static variables in SystemModules class private static final String MODULE_NAMES = "MODULE_NAMES"; + private static final String MODULES_TO_HASH = "MODULES_TO_HASH"; private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER"; private static final int BUILDER_VAR = 0; @@ -246,6 +262,9 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { // list of all ModuleDescriptorBuilders, invoked in turn when building. private final List builders = new ArrayList<>(); + // module name to hash + private final Map modulesToHash = new HashMap<>(); + // map Set to a specialized builder to allow them to be // deduplicated as they are requested private final Map, StringSetBuilder> stringSets = new HashMap<>(); @@ -268,6 +287,11 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { "[Ljava/lang/String;", null, null) .visitEnd(); + // public static String[] MODULES_TO_HASH = new String[] {....}; + cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, MODULES_TO_HASH, + "[Ljava/lang/String;", null, null) + .visitEnd(); + // public static int PACKAGES_IN_BOOT_LAYER; cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, PACKAGE_COUNT, "I", null, numPackages) @@ -283,15 +307,35 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { int index = 0; for (ModuleDescriptorBuilder builder : builders) { - mv.visitInsn(DUP); // arrayref + mv.visitInsn(DUP); // arrayref pushInt(index++); - mv.visitLdcInsn(builder.md.name()); // value + mv.visitLdcInsn(builder.md.name()); // value mv.visitInsn(AASTORE); } mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULE_NAMES, "[Ljava/lang/String;"); + // create the MODULES_TO_HASH array + pushInt(numModules); + mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); + + index = 0; + for (ModuleDescriptorBuilder builder : builders) { + String mn = builder.md.name(); + String recordedHash = modulesToHash.get(mn); + if (recordedHash != null) { + mv.visitInsn(DUP); // arrayref + pushInt(index); + mv.visitLdcInsn(recordedHash); // value + mv.visitInsn(AASTORE); + } + index++; + } + + mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULES_TO_HASH, + "[Ljava/lang/String;"); + mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); @@ -315,15 +359,19 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { } } - // provides + // provides (preserve iteration order) for (ModuleDescriptor.Provides p : md.provides().values()) { - stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s)) + stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s, true)) .increment(); } // uses stringSets.computeIfAbsent(md.uses(), s -> new StringSetBuilder(s)) .increment(); + + // hashes + JLMA.hashes(md).ifPresent(mh -> modulesToHash.putAll(mh.hashes())); + return builder; } @@ -484,13 +532,17 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { conceals(pn); } - if (md.version().isPresent()) { - version(md.version().get()); - } + // version + md.version().ifPresent(this::version); - if (md.mainClass().isPresent()) { - mainClass(md.mainClass().get()); - } + // main class + md.mainClass().ifPresent(this::mainClass); + + // hashes + JLMA.hashes(md).ifPresent(mh -> { + algorithm(mh.algorithm()); + mh.names().forEach(mn -> moduleHash(mn, mh.hashFor(mn))); + }); putModuleDescriptor(); } @@ -603,7 +655,7 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { /* * Invoke Builder.provides(String service, Set providers) * - * Set providers = new HashSet<>(); + * Set providers = new LinkedHashSet<>(); * providers.add(impl); * : * : @@ -652,6 +704,22 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { mv.visitInsn(POP); } + void algorithm(String alg) { + mv.visitVarInsn(ALOAD, BUILDER_VAR); + mv.visitLdcInsn(alg); + mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, + "algorithm", STRING_SIG, false); + mv.visitInsn(POP); + } + + void moduleHash(String name, String hashString) { + mv.visitVarInsn(ALOAD, BUILDER_VAR); + mv.visitLdcInsn(name); + mv.visitLdcInsn(hashString); + mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, + "moduleHash", STRING_STRING_SIG, false); + mv.visitInsn(POP); + } } /* @@ -663,10 +731,17 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { */ class StringSetBuilder { final Set names; + final boolean linked; int refCount; int localVarIndex; - StringSetBuilder(Set names) { + + StringSetBuilder(Set names, boolean linked) { this.names = names; + this.linked = linked; + } + + StringSetBuilder(Set names) { + this(names, false); } void increment() { @@ -704,11 +779,11 @@ public final class SystemModuleDescriptorPlugin implements TransformerPlugin { "singleton", "(Ljava/lang/Object;)Ljava/util/Set;", false); mv.visitVarInsn(ASTORE, index); } else { - mv.visitTypeInsn(NEW, "java/util/HashSet"); + String cn = linked ? "java/util/LinkedHashSet" : "java/util/HashSet"; + mv.visitTypeInsn(NEW, cn); mv.visitInsn(DUP); pushInt(initialCapacity(names.size())); - mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashSet", - "", "(I)V", false); + mv.visitMethodInsn(INVOKESPECIAL, cn, "", "(I)V", false); mv.visitVarInsn(ASTORE, index); for (String t : names) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java index 6027866d438..56e51bc9bc5 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Plugin.java @@ -201,6 +201,8 @@ public interface Plugin { * This method is called prior to invoke the plugin. * * @param config The plugin configuration. + * @throws IllegalArgumentException if a mandatory argument is missing or + * if an argument has invalid value. */ public default void configure(Map config) { } @@ -211,6 +213,9 @@ public interface Plugin { * * @param config The plugin configuration. * @param ctx The plugin context + * @throws IllegalArgumentException if a mandatory argument is missing or + * if an argument has invalid value. + * */ public default void configure(Map config, PluginContext ctx) { configure(config); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties index c97dc206d11..1aa33439525 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties @@ -33,9 +33,6 @@ main.command.files=\ main.opt.endian=\ \ --endian Byte order of generated jimage (default:native) -main.opt.genbom=\ -\ --genbom Generate a bom file containing jlink info - main.opt.saveopts=\ \ --saveopts Save jlink options in the given file diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index 2d13cda8747..5cc8a8f649e 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -26,6 +26,7 @@ package jdk.tools.jmod; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -34,14 +35,17 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.UncheckedIOException; -import java.lang.module.FindException; +import java.lang.module.Configuration; +import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; import java.lang.module.ModuleFinder; -import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Exports; +import java.lang.module.ModuleDescriptor.Provides; +import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Version; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.lang.module.ResolutionException; +import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; @@ -51,13 +55,16 @@ import java.nio.file.Path; import java.nio.file.PathMatcher; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.text.MessageFormat; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Formatter; +import java.util.Comparator; +import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -68,6 +75,7 @@ import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.jar.JarEntry; @@ -89,16 +97,14 @@ import jdk.internal.joptsimple.OptionParser; import jdk.internal.joptsimple.OptionSet; import jdk.internal.joptsimple.OptionSpec; import jdk.internal.joptsimple.ValueConverter; +import jdk.internal.misc.JavaLangModuleAccess; +import jdk.internal.misc.SharedSecrets; import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; -import jdk.internal.module.Hasher; -import jdk.internal.module.Hasher.DependencyHashes; +import jdk.internal.module.ModuleHashes; import jdk.internal.module.ModuleInfoExtender; -import static java.util.function.Function.identity; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toMap; /** * Implementation for the jmod tool. @@ -127,21 +133,6 @@ public class JmodTask { } } - static void fail(Class type, - String format, - Object... args) throws T { - String msg = new Formatter().format(format, args).toString(); - try { - T t = type.getConstructor(String.class).newInstance(msg); - throw t; - } catch (InstantiationException | - InvocationTargetException | - NoSuchMethodException | - IllegalAccessException e) { - throw new InternalError("Unable to create an instance of " + type, e); - } - } - private static final String PROGNAME = "jmod"; private static final String MODULE_INFO = "module-info.class"; @@ -161,7 +152,8 @@ public class JmodTask { enum Mode { CREATE, LIST, - DESCRIBE + DESCRIBE, + HASH }; static class Options { @@ -179,7 +171,8 @@ public class JmodTask { String osName; String osArch; String osVersion; - Pattern dependenciesToHash; + Pattern modulesToHash; + boolean dryrun; List excludes; } @@ -211,6 +204,9 @@ public class JmodTask { case DESCRIBE: ok = describe(); break; + case HASH: + ok = hashModules(); + break; default: throw new AssertionError("Unknown mode: " + options.mode.name()); } @@ -248,26 +244,8 @@ public class JmodTask { } } - private Map modulesToPath(Set modules) { - ModuleFinder finder = options.moduleFinder; - - Map modPaths = new HashMap<>(); - for (ModuleDescriptor m : modules) { - String name = m.name(); - - Optional omref = finder.find(name); - if (!omref.isPresent()) { - // this should not happen, module path bug? - fail(InternalError.class, - "Selected module %s not on module path", - name); - } - - URI uri = omref.get().location().get(); - modPaths.put(name, Paths.get(uri)); - - } - return modPaths; + private boolean hashModules() { + return new Hasher(options.moduleFinder).run(); } private boolean describe() throws IOException { @@ -297,6 +275,8 @@ public class JmodTask { .collect(joining(" ")); } + private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); + private boolean printModuleDescriptor(InputStream in) throws IOException { @@ -311,74 +291,45 @@ public class JmodTask { StringBuilder sb = new StringBuilder(); sb.append("\n").append(md.toNameAndVersion()); - List requires = md.requires().stream().sorted().collect(toList()); - if (!requires.isEmpty()) { - requires.forEach(r -> { - sb.append("\n requires "); - if (!r.modifiers().isEmpty()) - sb.append(toString(r.modifiers())).append(" "); - sb.append(r.name()); - }); - } + md.requires().stream() + .sorted(Comparator.comparing(Requires::name)) + .forEach(r -> { + sb.append("\n requires "); + if (!r.modifiers().isEmpty()) + sb.append(toString(r.modifiers())).append(" "); + sb.append(r.name()); + }); - List l = md.uses().stream().sorted().collect(toList()); - if (!l.isEmpty()) { - l.forEach(sv -> sb.append("\n uses ").append(sv)); - } + md.uses().stream().sorted() + .forEach(s -> sb.append("\n uses ").append(s)); - List exports = sortExports(md.exports()); - if (!exports.isEmpty()) { - exports.forEach(ex -> sb.append("\n exports ").append(ex)); - } + md.exports().stream() + .sorted(Comparator.comparing(Exports::source)) + .forEach(p -> sb.append("\n exports ").append(p)); - l = md.conceals().stream().sorted().collect(toList()); - if (!l.isEmpty()) { - l.forEach(p -> sb.append("\n conceals ").append(p)); - } + md.conceals().stream().sorted() + .forEach(p -> sb.append("\n conceals ").append(p)); - Map provides = md.provides(); - if (!provides.isEmpty()) { - provides.values().forEach(p -> - sb.append("\n provides ").append(p.service()) - .append(" with ") - .append(toString(p.providers()))); - } + md.provides().values().stream() + .sorted(Comparator.comparing(Provides::service)) + .forEach(p -> sb.append("\n provides ").append(p.service()) + .append(" with ") + .append(toString(p.providers()))); - Optional mc = md.mainClass(); - if (mc.isPresent()) - sb.append("\n main-class " + mc.get()); + md.mainClass().ifPresent(v -> sb.append("\n main-class " + v)); + md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v)); + md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v)); - Optional osname = md.osName(); - if (osname.isPresent()) - sb.append("\n operating-system-name " + osname.get()); + md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v)); - Optional osarch = md.osArch(); - if (osarch.isPresent()) - sb.append("\n operating-system-architecture " + osarch.get()); + JLMA.hashes(md).ifPresent( + hashes -> hashes.names().stream().sorted().forEach( + mod -> sb.append("\n hashes ").append(mod).append(" ") + .append(hashes.algorithm()).append(" ") + .append(hashes.hashFor(mod)))); - Optional osversion = md.osVersion(); - if (osversion.isPresent()) - sb.append("\n operating-system-version " + osversion.get()); - - try { - Method m = ModuleDescriptor.class.getDeclaredMethod("hashes"); - m.setAccessible(true); - @SuppressWarnings("unchecked") - Optional optHashes = - (Optional) m.invoke(md); - - if (optHashes.isPresent()) { - Hasher.DependencyHashes hashes = optHashes.get(); - hashes.names().stream().forEach(mod -> - sb.append("\n hashes ").append(mod).append(" ") - .append(hashes.algorithm()).append(" ") - .append(hashes.hashFor(mod))); - } - } catch (ReflectiveOperationException x) { - throw new InternalError(x); - } out.println(sb.toString()); return true; } @@ -387,21 +338,6 @@ public class JmodTask { return false; } - static List sortExports(Set exports) { - Map map = - exports.stream() - .collect(toMap(ModuleDescriptor.Exports::source, - identity())); - List sources = exports.stream() - .map(ModuleDescriptor.Exports::source) - .sorted() - .collect(toList()); - - List l = new ArrayList<>(); - sources.forEach(e -> l.add(map.get(e))); - return l; - } - private boolean create() throws IOException { JmodFileWriter jmod = new JmodFileWriter(); @@ -410,8 +346,9 @@ public class JmodTask { Path target = options.jmodFile; Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp"); try { - try (OutputStream out = Files.newOutputStream(tempTarget)) { - jmod.write(out); + try (OutputStream out = Files.newOutputStream(tempTarget); + BufferedOutputStream bos = new BufferedOutputStream(out)) { + jmod.write(bos); } Files.move(tempTarget, target); } catch (Exception e) { @@ -428,7 +365,6 @@ public class JmodTask { } private class JmodFileWriter { - final ModuleFinder moduleFinder = options.moduleFinder; final List cmds = options.cmds; final List libs = options.libs; final List configs = options.configs; @@ -438,8 +374,8 @@ public class JmodTask { final String osName = options.osName; final String osArch = options.osArch; final String osVersion = options.osVersion; - final Pattern dependenciesToHash = options.dependenciesToHash; final List excludes = options.excludes; + final Hasher hasher = hasher(); JmodFileWriter() { } @@ -545,11 +481,13 @@ public class JmodTask { if (moduleVersion != null) extender.version(moduleVersion); - // --hash-dependencies - if (dependenciesToHash != null) { - String name = descriptor.name(); - Set dependences = descriptor.requires(); - extender.hashes(hashDependences(name, dependences)); + if (hasher != null) { + ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name()); + if (moduleHashes != null) { + extender.hashes(moduleHashes); + } else { + warning("warn.no.module.hashes", descriptor.name()); + } } // write the (possibly extended or modified) module-info.class @@ -561,38 +499,56 @@ public class JmodTask { } } - /** - * Examines the module dependences of the given module - * and computes the hash of any module that matches the - * pattern {@code dependenciesToHash}. + /* + * Hasher resolves a module graph using the --hash-modules PATTERN + * as the roots. + * + * The jmod file is being created and does not exist in the + * given modulepath. */ - DependencyHashes hashDependences(String name, Set moduleDependences) - throws IOException - { - Set descriptors = new HashSet<>(); - for (Requires md: moduleDependences) { - String dn = md.name(); - if (dependenciesToHash.matcher(dn).find()) { - try { - Optional omref = moduleFinder.find(dn); - if (!omref.isPresent()) { - throw new RuntimeException("Hashing module " + name - + " dependencies, unable to find module " + dn - + " on module path"); - } - descriptors.add(omref.get().descriptor()); - } catch (FindException x) { - throw new IOException("error reading module path", x); - } - } - } - - Map map = modulesToPath(descriptors); - if (map.size() == 0) { + private Hasher hasher() { + if (options.modulesToHash == null) return null; - } else { - // use SHA-256 for now, easy to make this configurable if needed - return Hasher.generate(map, "SHA-256"); + + try { + Supplier miSupplier = newModuleInfoSupplier(); + if (miSupplier == null) { + throw new IOException(MODULE_INFO + " not found"); + } + + ModuleDescriptor descriptor; + try (InputStream in = miSupplier.get()) { + descriptor = ModuleDescriptor.read(in); + } + + URI uri = options.jmodFile.toUri(); + ModuleReference mref = new ModuleReference(descriptor, uri, new Supplier<>() { + @Override + public ModuleReader get() { + throw new UnsupportedOperationException(); + } + }); + + // compose a module finder with the module path and also + // a module finder that can find the jmod file being created + ModuleFinder finder = ModuleFinder.compose(options.moduleFinder, + new ModuleFinder() { + @Override + public Optional find(String name) { + if (descriptor.name().equals(name)) + return Optional.of(mref); + else return Optional.empty(); + } + + @Override + public Set findAll() { + return Collections.singleton(mref); + } + }); + + return new Hasher(finder); + } catch (IOException e) { + throw new UncheckedIOException(e); } } @@ -765,6 +721,273 @@ public class JmodTask { } } + /** + * Compute and record hashes + */ + private class Hasher { + final ModuleFinder moduleFinder; + final Map moduleNameToPath; + final Set modules; + final Configuration configuration; + final boolean dryrun = options.dryrun; + Hasher(ModuleFinder finder) { + this.moduleFinder = finder; + // Determine the modules that matches the pattern {@code modulesToHash} + this.modules = moduleFinder.findAll().stream() + .map(mref -> mref.descriptor().name()) + .filter(mn -> options.modulesToHash.matcher(mn).find()) + .collect(Collectors.toSet()); + + // a map from a module name to Path of the packaged module + this.moduleNameToPath = moduleFinder.findAll().stream() + .map(mref -> mref.descriptor().name()) + .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn))); + + // get a resolved module graph + Configuration config = null; + try { + config = Configuration.empty() + .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules); + } catch (ResolutionException e) { + warning("warn.module.resolution.fail", e.getMessage()); + } + this.configuration = config; + } + + /** + * This method is for jmod hash command. + * + * Identify the base modules in the module graph, i.e. no outgoing edge + * to any of the modules to be hashed. + * + * For each base module M, compute the hashes of all modules that depend + * upon M directly or indirectly. Then update M's module-info.class + * to record the hashes. + */ + boolean run() { + if (configuration == null) + return false; + + // transposed graph containing the the packaged modules and + // its transitive dependences matching --hash-modules + Map> graph = new HashMap<>(); + for (String root : modules) { + Deque deque = new ArrayDeque<>(); + deque.add(root); + Set visited = new HashSet<>(); + while (!deque.isEmpty()) { + String mn = deque.pop(); + if (!visited.contains(mn)) { + visited.add(mn); + + if (modules.contains(mn)) + graph.computeIfAbsent(mn, _k -> new HashSet<>()); + + ResolvedModule resolvedModule = configuration.findModule(mn).get(); + for (ResolvedModule dm : resolvedModule.reads()) { + String name = dm.name(); + if (!visited.contains(name)) { + deque.push(name); + } + + // reverse edge + if (modules.contains(name) && modules.contains(mn)) { + graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn); + } + } + } + } + } + + if (dryrun) + out.println("Dry run:"); + + // each node in a transposed graph is a matching packaged module + // in which the hash of the modules that depend upon it is recorded + graph.entrySet().stream() + .filter(e -> !e.getValue().isEmpty()) + .forEach(e -> { + String mn = e.getKey(); + Map modulesForHash = e.getValue().stream() + .collect(Collectors.toMap(Function.identity(), + moduleNameToPath::get)); + ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256"); + if (dryrun) { + out.format("%s%n", mn); + hashes.names().stream() + .sorted() + .forEach(name -> out.format(" hashes %s %s %s%n", + name, hashes.algorithm(), hashes.hashFor(name))); + } else { + try { + updateModuleInfo(mn, hashes); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + }); + return true; + } + + /** + * Compute hashes of the specified module. + * + * It records the hashing modules that depend upon the specified + * module directly or indirectly. + */ + ModuleHashes computeHashes(String name) { + if (configuration == null) + return null; + + // the transposed graph includes all modules in the resolved graph + Map> graph = transpose(); + + // find the modules that transitively depend upon the specified name + Deque deque = new ArrayDeque<>(); + deque.add(name); + Set mods = visitNodes(graph, deque); + + // filter modules matching the pattern specified --hash-modules + // as well as itself as the jmod file is being generated + Map modulesForHash = mods.stream() + .filter(mn -> !mn.equals(name) && modules.contains(mn)) + .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get)); + + if (modulesForHash.isEmpty()) + return null; + + return ModuleHashes.generate(modulesForHash, "SHA-256"); + } + + /** + * Returns all nodes traversed from the given roots. + */ + private Set visitNodes(Map> graph, + Deque roots) { + Set visited = new HashSet<>(); + while (!roots.isEmpty()) { + String mn = roots.pop(); + if (!visited.contains(mn)) { + visited.add(mn); + // the given roots may not be part of the graph + if (graph.containsKey(mn)) { + for (String dm : graph.get(mn)) { + if (!visited.contains(dm)) { + roots.push(dm); + } + } + } + } + } + return visited; + } + + /** + * Returns a transposed graph from the resolved module graph. + */ + private Map> transpose() { + Map> transposedGraph = new HashMap<>(); + Deque deque = new ArrayDeque<>(modules); + + Set visited = new HashSet<>(); + while (!deque.isEmpty()) { + String mn = deque.pop(); + if (!visited.contains(mn)) { + visited.add(mn); + + transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>()); + + ResolvedModule resolvedModule = configuration.findModule(mn).get(); + for (ResolvedModule dm : resolvedModule.reads()) { + String name = dm.name(); + if (!visited.contains(name)) { + deque.push(name); + } + + // reverse edge + transposedGraph.computeIfAbsent(name, _k -> new HashSet<>()) + .add(mn); + } + } + } + return transposedGraph; + } + + /** + * Reads the given input stream of module-info.class and write + * the extended module-info.class with the given ModuleHashes + * + * @param in InputStream of module-info.class + * @param out OutputStream to write the extended module-info.class + * @param hashes ModuleHashes + */ + private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes) + throws IOException + { + ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in); + extender.hashes(hashes); + extender.write(out); + } + + private void updateModuleInfo(String name, ModuleHashes moduleHashes) + throws IOException + { + Path target = moduleNameToPath.get(name); + Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp"); + ZipFile zip = new ZipFile(target.toFile()); + try { + try (OutputStream out = Files.newOutputStream(tempTarget); + ZipOutputStream zos = new ZipOutputStream(out)) { + zip.stream().forEach(e -> { + try { + InputStream in = zip.getInputStream(e); + if (e.getName().equals(MODULE_INFO) || + e.getName().equals(Section.CLASSES.jmodDir() + "/" + MODULE_INFO)) { + ZipEntry ze = new ZipEntry(e.getName()); + ze.setTime(System.currentTimeMillis()); + zos.putNextEntry(ze); + recordHashes(in, zos, moduleHashes); + zos.closeEntry(); + } else { + zos.putNextEntry(e); + zos.write(in.readAllBytes()); + zos.closeEntry(); + } + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + } catch (IOException|RuntimeException e) { + if (Files.exists(tempTarget)) { + try { + Files.delete(tempTarget); + } catch (IOException ioe) { + e.addSuppressed(ioe); + } + } + throw e; + } finally { + zip.close(); + } + out.println(getMessage("module.hashes.recorded", name)); + Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING); + } + + private Path moduleToPath(String name) { + ModuleReference mref = moduleFinder.find(name).orElseThrow( + () -> new InternalError("Selected module " + name + " not on module path")); + + URI uri = mref.location().get(); + Path path = Paths.get(uri); + String fn = path.getFileName().toString(); + if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) { + throw new InternalError(path + " is not a modular JAR or jmod file"); + } + return path; + } + } + enum Section { NATIVE_LIBS("native"), NATIVE_CMDS("bin"), @@ -921,7 +1144,8 @@ public class JmodTask { builder.append("\n").append(" Main operation modes:\n "); builder.append(getMessage("main.opt.mode.create")).append("\n "); builder.append(getMessage("main.opt.mode.list")).append("\n "); - builder.append(getMessage("main.opt.mode.describe")).append("\n\n"); + builder.append(getMessage("main.opt.mode.describe")).append("\n "); + builder.append(getMessage("main.opt.mode.hash")).append("\n\n"); String cmdfile = null; String[] lines = content.split("\n"); @@ -964,13 +1188,16 @@ public class JmodTask { .withValuesSeparatedBy(File.pathSeparatorChar) .withValuesConvertedBy(DirPathConverter.INSTANCE); + OptionSpec dryrun + = parser.accepts("dry-run", getMessage("main.opt.dry-run")); + OptionSpec excludes = parser.accepts("exclude", getMessage("main.opt.exclude")) .withRequiredArg() .withValuesConvertedBy(new GlobConverter()); - OptionSpec hashDependencies - = parser.accepts("hash-dependencies", getMessage("main.opt.hash-dependencies")) + OptionSpec hashModules + = parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) .withRequiredArg() .withValuesConvertedBy(new PatternConverter()); @@ -1049,6 +1276,8 @@ public class JmodTask { options.cmds = opts.valuesOf(cmds); if (opts.has(config)) options.configs = opts.valuesOf(config); + if (opts.has(dryrun)) + options.dryrun = true; if (opts.has(excludes)) options.excludes = opts.valuesOf(excludes); if (opts.has(libs)) @@ -1069,27 +1298,39 @@ public class JmodTask { options.osArch = opts.valueOf(osArch); if (opts.has(osVersion)) options.osVersion = opts.valueOf(osVersion); - if (opts.has(hashDependencies)) { - options.dependenciesToHash = opts.valueOf(hashDependencies); - // if storing hashes of dependencies then the module path is required + if (opts.has(hashModules)) { + options.modulesToHash = opts.valueOf(hashModules); + // if storing hashes then the module path is required if (options.moduleFinder == null) - throw new CommandException("err.modulepath.must.be.specified").showUsage(true); + throw new CommandException("err.modulepath.must.be.specified") + .showUsage(true); } - if (words.size() <= 1) - throw new CommandException("err.jmod.must.be.specified").showUsage(true); - Path path = Paths.get(words.get(1)); - if (options.mode.equals(Mode.CREATE) && Files.exists(path)) - throw new CommandException("err.file.already.exists", path); - else if ((options.mode.equals(Mode.LIST) || - options.mode.equals(Mode.DESCRIBE)) - && Files.notExists(path)) - throw new CommandException("err.jmod.not.found", path); - options.jmodFile = path; + if (options.mode.equals(Mode.HASH)) { + if (options.moduleFinder == null || options.modulesToHash == null) + throw new CommandException("err.modulepath.must.be.specified") + .showUsage(true); + } else { + if (words.size() <= 1) + throw new CommandException("err.jmod.must.be.specified").showUsage(true); + Path path = Paths.get(words.get(1)); - if (words.size() > 2) - throw new CommandException("err.unknown.option", - words.subList(2, words.size())).showUsage(true); + if (options.mode.equals(Mode.CREATE) && Files.exists(path)) + throw new CommandException("err.file.already.exists", path); + else if ((options.mode.equals(Mode.LIST) || + options.mode.equals(Mode.DESCRIBE)) + && Files.notExists(path)) + throw new CommandException("err.jmod.not.found", path); + + if (options.dryrun) { + throw new CommandException("err.invalid.dryrun.option"); + } + options.jmodFile = path; + + if (words.size() > 2) + throw new CommandException("err.unknown.option", + words.subList(2, words.size())).showUsage(true); + } if (options.mode.equals(Mode.CREATE) && options.classpath == null) throw new CommandException("err.classpath.must.be.specified").showUsage(true); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties index 98e0f6fd7d9..555adb03b8f 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties @@ -1,9 +1,9 @@ main.usage.summary=\ -Usage: {0} (create|list|describe) \n\ +Usage: {0} (create|list|describe|hash) \n\ use --help for a list of possible options main.usage=\ -Usage: {0} (create|list|describe) +Usage: {0} (create|list|describe|hash) error.prefix=Error: warn.prefix=Warning: @@ -14,6 +14,8 @@ main.opt.mode.list=\ \list - Prints the names of all the entries main.opt.mode.describe=\ \describe - Prints the module details +main.opt.mode.hash=\ +\hash - Records hashes of tied modules. main.opt.help=Print this usage message main.opt.version=Version information @@ -21,9 +23,9 @@ main.opt.class-path=Application jar files|dir containing classes main.opt.libs=Location of native libraries main.opt.cmds=Location of native commands main.opt.config=Location of user-editable config files +main.opt.dry-run=Dry run of hash mode main.opt.exclude=Exclude files, given as a PATTERN main.opt.module-version= Module version -main.opt.modulepath=Module path main.opt.main-class=Main class main.opt.main-class.arg=class-name main.opt.os-name=Operating system name @@ -32,18 +34,25 @@ main.opt.os-arch=Operating system architecture main.opt.os-arch.arg=os-arch main.opt.os-version=Operating system version main.opt.os-version.arg=os-version -main.opt.hash-dependencies=Compute and record hashes of dependencies matched by the pattern +main.opt.modulepath=Module path +main.opt.hash-modules=Compute and record hashes to tie a packaged module\ +\ with modules matching the given pattern and depending upon it directly\ +\ or indirectly. The hashes are recorded in the JMOD file being created, or\ +\ a JMOD file or modular JAR on the module path specified the jmod hash command. + main.opt.cmdfile=Read options from the specified file -err.missing.mode=one of create, list, or describe must be specified -err.invalid.mode=mode must be one of create, list, or describe: {0} +module.hashes.recorded=Hashes are recorded in module {0} + +err.missing.mode=one of create, list, describe, or hash must be specified +err.invalid.mode=mode must be one of create, list, describe, or hash: {0} err.classpath.must.be.specified=--class-path must be specified err.jmod.must.be.specified=jmod-file must be specified err.invalid.version=invalid module version {0} -err.output.must.be.specified:--output must be specified -err.mods.must.be.specified:--mods must be specified -err.modulepath.must.be.specified:--module-path must be specified when hashing dependencies -err.invalid.main-class:invalid main-class name: {0} +err.output.must.be.specified=--output must be specified +err.mods.must.be.specified=--mods must be specified +err.modulepath.must.be.specified=--module-path must be specified when hashing modules +err.invalid.main-class=invalid main-class name: {0} err.path.not.found=path not found: {0} err.path.not.valid=invalid path: {0} err.path.not.a.dir=path must be a directory: {0} @@ -54,5 +63,9 @@ err.bad.pattern=bad pattern {0} err.unknown.option=unknown option(s): {0} err.missing.arg=no value given for {0} err.internal.error=internal error: {0} {1} {2} +err.invalid.dryrun.option=--dry-run can only be used with hash mode err.module.descriptor.not.found=Module descriptor not found warn.invalid.arg=Invalid classname or pathname not exist: {0} +warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0} +warn.module.resolution.fail=No hashes recorded: {0} + diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index 78c24d3b053..4b9b756fd75 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -26,9 +26,12 @@ groups=TEST.groups [closed/TEST.groups] # Allow querying of sun.arch.data.model in @requires clauses requires.properties=sun.arch.data.model -# Tests using jtreg 4.2 b01 features -requiredVersion=4.2 b01 +# Tests using jtreg 4.2 b02 features +requiredVersion=4.2 b02 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them external.lib.roots = ../../ + +# Use new form of -Xpatch +useNewXpatch=true diff --git a/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh b/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh index e8b4365b68f..0ecd30a4de5 100644 --- a/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh +++ b/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh @@ -81,9 +81,9 @@ cp ${TESTSRC}${FS}JavaBug.java bug chmod -fR 777 bug -${COMPILEJAVA}${FS}bin${FS}javac -d . bug${FS}*.java +${COMPILEJAVA}${FS}bin${FS}javac -addmods java.corba -d . bug${FS}*.java -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp . bug/JavaBug > test.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -addmods java.corba -cp . bug/JavaBug > test.out 2>&1 grep "NullPointerException" test.out diff --git a/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java b/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java index 6130a83420d..ccc84df74bc 100644 --- a/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java +++ b/jdk/test/com/sun/corba/7130985/CorbaExceptionsCompileTest.java @@ -27,7 +27,8 @@ * @summary Four helper classes missing in Sun JDK * @library /lib/testlibrary * @build jdk.testlibrary.* - * @run main CorbaExceptionsCompileTest + * @compile -addmods java.corba CorbaExceptionsCompileTest.java + * @run main/othervm -addmods java.corba CorbaExceptionsCompileTest */ import java.io.*; diff --git a/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java b/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java index cd7c50bdd37..4791c63f2ef 100644 --- a/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java +++ b/jdk/test/com/sun/corba/se/impl/io/HookPutFieldsTest.java @@ -25,6 +25,8 @@ * @test * @bug 7095856 * @summary OutputStreamHook doesn't handle null values + * @compile -addmods java.corba HookPutFieldsTest.java + * @run main/othervm -addmods java.corba HookPutFieldsTest */ import java.net.InetAddress; diff --git a/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java b/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java index d5fa81cb2f5..49b0a5d9f6f 100644 --- a/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java +++ b/jdk/test/com/sun/corba/se/impl/orb/SetDefaultORBTest.java @@ -25,7 +25,8 @@ * @test * @bug 8028215 * @summary SetDefaultORBTest setting ORB impl via properties test - * @run main/othervm SetDefaultORBTest + * @compile -addmods java.corba SetDefaultORBTest.java + * @run main/othervm -addmods java.corba SetDefaultORBTest * */ diff --git a/jdk/test/com/sun/net/httpserver/bugs/B6373555.java b/jdk/test/com/sun/net/httpserver/bugs/B6373555.java index cef94781975..4fa703234e1 100644 --- a/jdk/test/com/sun/net/httpserver/bugs/B6373555.java +++ b/jdk/test/com/sun/net/httpserver/bugs/B6373555.java @@ -29,7 +29,6 @@ import java.net.*; import java.io.*; -import javax.xml.soap.*; import java.util.*; import com.sun.net.httpserver.*; import java.util.concurrent.*; diff --git a/jdk/test/java/lang/invoke/VarargsArrayTest.java b/jdk/test/java/lang/invoke/VarargsArrayTest.java index 98e069835a7..dad164dcccc 100644 --- a/jdk/test/java/lang/invoke/VarargsArrayTest.java +++ b/jdk/test/java/lang/invoke/VarargsArrayTest.java @@ -37,7 +37,7 @@ import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor; * @library /lib/testlibrary /lib/testlibrary/jsr292 * @compile/module=java.base java/lang/invoke/MethodHandleHelper.java * @run main/bootclasspath VarargsArrayTest - * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250 + * @run main/bootclasspath/othervm -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250 * VarargsArrayTest */ diff --git a/jdk/test/java/lang/module/ModuleFinderTest.java b/jdk/test/java/lang/module/ModuleFinderTest.java index 2306ba3a2f9..3270dfd4085 100644 --- a/jdk/test/java/lang/module/ModuleFinderTest.java +++ b/jdk/test/java/lang/module/ModuleFinderTest.java @@ -340,7 +340,7 @@ public class ModuleFinderTest { */ public void testOfWithUnrecognizedEntry() throws Exception { Path dir = Files.createTempDirectory(USER_DIR, "mods"); - Path mod = Files.createTempFile(dir, "m", "mod"); + Path mod = Files.createTempFile(dir, "m", ".junk"); ModuleFinder finder = ModuleFinder.of(mod); try { @@ -360,6 +360,48 @@ public class ModuleFinderTest { } + /** + * Test ModuleFinder.of with a file path to a directory containing a file + * that will not be recognized as a module. + */ + public void testOfWithUnrecognizedEntryInDirectory() throws Exception { + Path dir = Files.createTempDirectory(USER_DIR, "mods"); + Files.createTempFile(dir, "m", ".junk"); + + ModuleFinder finder = ModuleFinder.of(dir); + try { + finder.find("java.rhubarb"); + assertTrue(false); + } catch (FindException e) { + // expected + } + + finder = ModuleFinder.of(dir); + try { + finder.findAll(); + assertTrue(false); + } catch (FindException e) { + // expected + } + } + + + /** + * Test ModuleFinder.of with a file path to a directory containing a file + * starting with ".", the file should be ignored. + */ + public void testOfWithHiddenEntryInDirectory() throws Exception { + Path dir = Files.createTempDirectory(USER_DIR, "mods"); + Files.createTempFile(dir, ".marker", ""); + + ModuleFinder finder = ModuleFinder.of(dir); + assertFalse(finder.find("java.rhubarb").isPresent()); + + finder = ModuleFinder.of(dir); + assertTrue(finder.findAll().isEmpty()); + } + + /** * Test ModuleFinder.of with a directory that contains two * versions of the same module diff --git a/jdk/test/tools/launcher/modules/addmods/src/app/Main.java b/jdk/test/java/lang/reflect/WeakPairMap/Driver.java similarity index 78% rename from jdk/test/tools/launcher/modules/addmods/src/app/Main.java rename to jdk/test/java/lang/reflect/WeakPairMap/Driver.java index be903e510ac..f84956d687e 100644 --- a/jdk/test/tools/launcher/modules/addmods/src/app/Main.java +++ b/jdk/test/java/lang/reflect/WeakPairMap/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,12 +21,15 @@ * questions. */ -package app; - -import jdk.lib.Util; - -public class Main { +/** + * @test + * @bug 8888888 + * @summary Functional test for WeakPairMap + * @build java.base/java.lang.reflect.WeakPairMapTest + * @run main Driver + */ +public class Driver { public static void main(String[] args) { - Object obj = Util.makeObject(); + java.lang.reflect.WeakPairMapTest.main(args); } } diff --git a/jdk/test/java/lang/reflect/WeakPairMap/java.base/java/lang/reflect/WeakPairMapTest.java b/jdk/test/java/lang/reflect/WeakPairMap/java.base/java/lang/reflect/WeakPairMapTest.java new file mode 100644 index 00000000000..3247bb317ac --- /dev/null +++ b/jdk/test/java/lang/reflect/WeakPairMap/java.base/java/lang/reflect/WeakPairMapTest.java @@ -0,0 +1,175 @@ +/* + * 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 java.lang.reflect; + +import java.lang.ref.Reference; +import java.util.Objects; + +/** + * Functional test for WeakPairMap + * + * @author Peter Levart + */ +public class WeakPairMapTest { + public static void main(String[] args) { + WeakPairMap pm = new WeakPairMap<>(); + Object key1 = new Object(); + Object key2 = new Object(); + + // check for emptiness + assertEquals(pm.containsKeyPair(key1, key2), false); + assertEquals(pm.get(key1, key2), null); + + // check for NPE(s) + for (Object k1 : new Object[]{null, key1}) { + for (Object k2 : new Object[]{null, key2}) { + for (String v : new String[]{null, "abc"}) { + + if (k1 != null && k2 != null && v != null) { + // skip non-null args + continue; + } + + try { + pm.put(k1, k2, v); + throw new AssertionError("Unexpected code path, k1=" + + k1 + ", k2=" + k2 + ", v=" + v); + } catch (NullPointerException e) { + // expected + } + + try { + pm.putIfAbsent(k1, k2, v); + throw new AssertionError("Unexpected code path, k1=" + + k1 + ", k2=" + k2 + ", v=" + v); + } catch (NullPointerException e) { + // expected + } + + if (k1 != null && k2 != null) { + // skip non-null args + continue; + } + + try { + pm.computeIfAbsent(k1, k2, (_k1, _k2) -> v); + throw new AssertionError("Unexpected code path, k1=" + + k1 + ", k2=" + k2 + ", v=" + v); + } catch (NullPointerException e) { + // expected + } + + try { + pm.containsKeyPair(k1, k2); + throw new AssertionError("Unexpected code path, k1=" + + k1 + ", k2=" + k2); + } catch (NullPointerException e) { + // expected + } + + try { + pm.get(k1, k2); + throw new AssertionError("Unexpected code path, k1=" + + k1 + ", k2=" + k2); + } catch (NullPointerException e) { + // expected + } + } + } + } + + // how much to wait when it is expected for entry to be retained + final long retentionTimeout = 500L; + // how much to wait when it is expected for entry to be removed + final long cleanupTimeout = 30_000L; + + // check insertion + assertEquals(pm.putIfAbsent(key1, key2, "abc"), null); + assertEquals(pm.get(key1, key2), "abc"); + + // check retention while both keys are still reachable + assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false); + assertEquals(pm.get(key1, key2), "abc"); + + // check cleanup when both keys are unreachable + key1 = null; + key2 = null; + assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true); + + // new insertion + key1 = new Object(); + key2 = new Object(); + assertEquals(pm.putIfAbsent(key1, key2, "abc"), null); + assertEquals(pm.get(key1, key2), "abc"); + + // check retention while both keys are still reachable + assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false); + assertEquals(pm.get(key1, key2), "abc"); + + // check cleanup when 1st key is unreachable + key1 = null; + assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true); + Reference.reachabilityFence(key2); + + // new insertion + key1 = new Object(); + key2 = new Object(); + assertEquals(pm.putIfAbsent(key1, key2, "abc"), null); + assertEquals(pm.get(key1, key2), "abc"); + + // check retention while both keys are still reachable + assertEquals(gcAndWaitRemoved(pm, "abc", retentionTimeout), false); + assertEquals(pm.get(key1, key2), "abc"); + + // check cleanup when 2nd key is unreachable + key2 = null; + assertEquals(gcAndWaitRemoved(pm, "abc", cleanupTimeout), true); + Reference.reachabilityFence(key1); + } + + /** + * Trigger GC and wait for at most {@code millis} ms for given value to + * be removed from given WeakPairMap. + * + * @return true if element has been removed or false if not + */ + static boolean gcAndWaitRemoved(WeakPairMap pm, V value, + long millis) { + System.gc(); + for (int i = 0; i < (millis + 99) / 100 && pm.values().contains(value); i++) { + try { + Thread.sleep(100L); + } catch (InterruptedException e) { + throw new AssertionError("Interrupted"); + } + } + return !pm.values().contains(value); + } + + static void assertEquals(Object actual, Object expected) { + if (!Objects.equals(actual, expected)) { + throw new AssertionError("Expected: " + expected + ", actual: " + actual); + } + } +} diff --git a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh index 62bc96cdba9..c2ce46ec3c3 100644 --- a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh +++ b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh @@ -68,7 +68,7 @@ cd ${PATCHDIR}/java.desktop ${TESTJAVA}/bin/jar xf ${TESTSRC}/awtres.jar echo -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:${PATCHDIR} \ +${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.desktop=${PATCHDIR}/java.desktop \ -cp ${TESTCLASSES} Bug6299235Test if [ $? -ne 0 ] diff --git a/jdk/test/javax/crypto/Cipher/CipherStreamClose.java b/jdk/test/javax/crypto/Cipher/CipherStreamClose.java index 1e8ff16331d..304c887dea1 100644 --- a/jdk/test/javax/crypto/Cipher/CipherStreamClose.java +++ b/jdk/test/javax/crypto/Cipher/CipherStreamClose.java @@ -27,6 +27,8 @@ * @summary Make sure Cipher IO streams doesn't call extra doFinal if close() * is called multiple times. Additionally, verify the input and output streams * match with encryption and decryption with non-stream crypto. + * @compile -addmods java.xml.bind CipherStreamClose.java + * @run main/othervm -addmods java.xml.bind CipherStreamClose */ import java.io.*; diff --git a/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java b/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java index d69cbe42f9c..52079aa359b 100644 --- a/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java +++ b/jdk/test/javax/rmi/PortableRemoteObject/ConcurrentHashMapTest.java @@ -27,8 +27,10 @@ * @summary test RMI-IIOP call with ConcurrentHashMap as an argument * @library /lib/testlibrary * @build jdk.testlibrary.* - * @build Test HelloInterface HelloServer HelloClient HelloImpl _HelloImpl_Tie _HelloInterface_Stub ConcurrentHashMapTest - * @run main/othervm -Djava.naming.provider.url=iiop://localhost:1050 -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory ConcurrentHashMapTest + * @compile -addmods java.corba Test.java HelloInterface.java HelloServer.java HelloClient.java + * HelloImpl.java _HelloImpl_Tie.java _HelloInterface_Stub.java ConcurrentHashMapTest.java + * @run main/othervm -addmods java.corba -Djava.naming.provider.url=iiop://localhost:1050 + * -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory ConcurrentHashMapTest * @key intermittent */ @@ -101,6 +103,8 @@ public class ConcurrentHashMapTest { // -Djava.naming.provider.url=iiop://localhost:1050 HelloServer List commands = new ArrayList<>(); commands.add(ConcurrentHashMapTest.JAVA); + commands.add("-addmods"); + commands.add("java.corba"); commands.add("-Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory"); commands.add("-Djava.naming.provider.url=iiop://localhost:1050"); commands.add("-cp"); diff --git a/jdk/test/javax/smartcardio/CommandAPDUTest.java b/jdk/test/javax/smartcardio/CommandAPDUTest.java index a6ce5c69d41..72c5a474590 100644 --- a/jdk/test/javax/smartcardio/CommandAPDUTest.java +++ b/jdk/test/javax/smartcardio/CommandAPDUTest.java @@ -26,7 +26,8 @@ * @bug 8049021 * @summary Test different constructors for CommandAPDU and check CLA,INS,NC,NE, * P1,and P2 - * @run testng CommandAPDUTest + * @compile -addmods java.smartcardio CommandAPDUTest.java + * @run testng/othervm -addmods java.smartcardio CommandAPDUTest */ import java.nio.ByteBuffer; import javax.smartcardio.CommandAPDU; diff --git a/jdk/test/javax/smartcardio/HistoricalBytes.java b/jdk/test/javax/smartcardio/HistoricalBytes.java index 35af338cd09..eebaf8dd671 100644 --- a/jdk/test/javax/smartcardio/HistoricalBytes.java +++ b/jdk/test/javax/smartcardio/HistoricalBytes.java @@ -26,7 +26,9 @@ * @bug 6445367 * @summary Verify that ATR.getHistoricalBytes() works * @author Andreas Sterbenz -**/ + * @compile -addmods java.smartcardio HistoricalBytes.java + * @run main/othervm -addmods java.smartcardio HistoricalBytes + */ import java.util.Arrays; diff --git a/jdk/test/javax/smartcardio/ResponseAPDUTest.java b/jdk/test/javax/smartcardio/ResponseAPDUTest.java index 995cd1241cf..c885c2b827c 100644 --- a/jdk/test/javax/smartcardio/ResponseAPDUTest.java +++ b/jdk/test/javax/smartcardio/ResponseAPDUTest.java @@ -25,7 +25,8 @@ * @test * @bug 8049021 * @summary Construct ResponseAPDU from byte array and check NR< SW, SW1 and SW2 - * @run testng ResponseAPDUTest + * @compile -addmods java.smartcardio ResponseAPDUTest.java + * @run testng/othervm -addmods java.smartcardio ResponseAPDUTest */ import javax.smartcardio.ResponseAPDU; import static org.testng.Assert.*; diff --git a/jdk/test/javax/smartcardio/Serialize.java b/jdk/test/javax/smartcardio/Serialize.java index ac572369276..a7eac0e242c 100644 --- a/jdk/test/javax/smartcardio/Serialize.java +++ b/jdk/test/javax/smartcardio/Serialize.java @@ -26,6 +26,8 @@ * @bug 6445367 * @summary make sure serialization works * @author Andreas Sterbenz + * @compile -addmods java.smartcardio Serialize.java + * @run main/othervm -addmods java.smartcardio Serialize */ import java.io.*; diff --git a/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java b/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java index cec4c4443e4..881cc7250b8 100644 --- a/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java +++ b/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java @@ -25,7 +25,8 @@ * @test * @bug 8049021 * @summary Test if we can write new provider for smart card - * @run main/othervm/policy=policy TerminalFactorySpiTest + * @compile -addmods java.smartcardio TerminalFactorySpiTest.java + * @run main/othervm/policy=policy -addmods java.smartcardio TerminalFactorySpiTest */ import java.security.Provider; import java.security.Security; diff --git a/jdk/test/javax/smartcardio/TestCardPermission.java b/jdk/test/javax/smartcardio/TestCardPermission.java index 24db1fb4b0c..7c31da6a9d7 100644 --- a/jdk/test/javax/smartcardio/TestCardPermission.java +++ b/jdk/test/javax/smartcardio/TestCardPermission.java @@ -26,6 +26,8 @@ * @bug 6293767 * @summary Test for the CardPermission class * @author Andreas Sterbenz + * @compile -addmods java.smartcardio TestCardPermission.java + * @run main/othervm -addmods java.smartcardio TestCardPermission */ import javax.smartcardio.*; diff --git a/jdk/test/javax/smartcardio/TestCommandAPDU.java b/jdk/test/javax/smartcardio/TestCommandAPDU.java index 543fcea2487..34421590dcb 100644 --- a/jdk/test/javax/smartcardio/TestCommandAPDU.java +++ b/jdk/test/javax/smartcardio/TestCommandAPDU.java @@ -27,6 +27,8 @@ * @summary Test for the CommandAPDU class * @author Andreas Sterbenz * @key randomness + * @compile -addmods java.smartcardio TestCommandAPDU.java + * @run main/othervm -addmods java.smartcardio TestCommandAPDU */ import java.util.*; diff --git a/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java b/jdk/test/javax/transaction/testng/Driver.java similarity index 55% rename from jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java rename to jdk/test/javax/transaction/testng/Driver.java index eb71f80b451..3f5e9ec1bc7 100644 --- a/jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java +++ b/jdk/test/javax/transaction/testng/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,12 +21,16 @@ * questions. */ -package org.not_matched; - -public class Name { - private Name() { } - - public static String name() { - return "new_module"; - } -} +/** + * @test + * @compile -addmods java.transaction + * test/transaction/InvalidTransactionExceptionTests.java + * test/transaction/TransactionRequiredExceptionTests.java + * test/transaction/TransactionRolledbackExceptionTests.java + * test/transaction/XAExceptionTests.java + * util/SerializedTransactionExceptions.java + * @run testng/othervm -addmods java.transaction test.transaction.InvalidTransactionExceptionTests + * @run testng/othervm -addmods java.transaction test.transaction.TransactionRequiredExceptionTests + * @run testng/othervm -addmods java.transaction test.transaction.TransactionRolledbackExceptionTests + * @run testng/othervm -addmods java.transaction util.SerializedTransactionExceptions + */ diff --git a/jdk/test/javax/transaction/testng/TEST.properties b/jdk/test/javax/transaction/testng/TEST.properties deleted file mode 100644 index f9e4addcabe..00000000000 --- a/jdk/test/javax/transaction/testng/TEST.properties +++ /dev/null @@ -1,4 +0,0 @@ -# JDBC unit tests uses TestNG -TestNG.dirs= . -othervm.dirs= . - diff --git a/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java b/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java index 1fb8e868634..4a556efce13 100644 --- a/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java +++ b/jdk/test/javax/xml/bind/xjc/8032884/XjcOptionalPropertyTest.java @@ -26,6 +26,7 @@ * @bug 8032884 * @summary Globalbindings optionalProperty="primitive" does not work when minOccurs=0 * @run shell compile-schema.sh + * @compile -addmods java.xml.bind XjcOptionalPropertyTest.java * @run main/othervm XjcOptionalPropertyTest */ diff --git a/jdk/test/javax/xml/jaxp/common/8035437/run.sh b/jdk/test/javax/xml/jaxp/common/8035437/run.sh index 2ebe7ce4296..5dbcff7f18a 100644 --- a/jdk/test/javax/xml/jaxp/common/8035437/run.sh +++ b/jdk/test/javax/xml/jaxp/common/8035437/run.sh @@ -34,12 +34,12 @@ $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ -d compile/java.xml -Xmodule:java.xml $TESTSRC/Document.java $TESTSRC/Node.java || exit 1 $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ - -d exec/java.xml -Xpatch:compile -Xmodule:java.xml $TESTSRC/DocumentImpl.java || exit 2 + -d exec/java.xml -Xpatch:java.xml=compile/java.xml -Xmodule:java.xml $TESTSRC/DocumentImpl.java || exit 2 $COMPILEJAVA/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \ $TESTSRC/AbstractMethodErrorTest.java -d exec || exit 3 -$TESTJAVA/bin/java ${TESTVMOPTS} -Xpatch:exec -cp exec AbstractMethodErrorTest || exit 4 +$TESTJAVA/bin/java ${TESTVMOPTS} -Xpatch:java.xml=exec -cp exec AbstractMethodErrorTest || exit 4 exit 0 diff --git a/jdk/test/javax/xml/soap/XmlTest.java b/jdk/test/javax/xml/soap/XmlTest.java index fedd52d59da..37aed906037 100644 --- a/jdk/test/javax/xml/soap/XmlTest.java +++ b/jdk/test/javax/xml/soap/XmlTest.java @@ -38,6 +38,8 @@ import java.util.Iterator; /* * @test + * @compile -addmods java.xml.ws XmlTest.java + * @run main/othervm -addmods java.xml.ws XmlTest * @summary tests JAF DataHandler can be instantiated; test serialize and * deserialize SOAP message containing xml attachment */ diff --git a/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java b/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java index 1cf8e8e6b0a..b36c356f25d 100644 --- a/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java +++ b/jdk/test/javax/xml/soap/spi/SAAJFactoryTest.java @@ -49,29 +49,29 @@ import java.nio.file.StandardOpenOption; * run main/othervm SAAJFactoryTest saaj.factory.Valid - * scenario14 javax.xml.soap.MessageFactory=saaj.factory.Valid saaj.factory.Valid2 - * - * @build saaj.factory.* + * @compile -addmods java.xml.ws saaj/factory/Invalid.java saaj/factory/Valid.java + * saaj/factory/Valid2.java saaj/factory/Valid3.java SAAJFactoryTest.java * - * @run main/othervm SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - - * scenario2 - - - * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.Valid SAAJFactoryTest saaj.factory.Valid - - * scenario5 - - - * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.NonExisting SAAJFactoryTest - * - javax.xml.soap.SOAPException - * scenario6 - - - * @run main/othervm -Djavax.xml.soap.MessageFactory=saaj.factory.Invalid SAAJFactoryTest - javax.xml.soap.SOAPException - * scenario7 - - - * @run main/othervm SAAJFactoryTest saaj.factory.Valid - - * scenario8 - saaj.factory.Valid - * @run main/othervm SAAJFactoryTest saaj.factory.Valid - - * scenario9 - saaj.factory.Valid - * @run main/othervm SAAJFactoryTest - javax.xml.soap.SOAPException - * scenario10 - saaj.factory.NonExisting - * @run main/othervm SAAJFactoryTest - javax.xml.soap.SOAPException - * scenario11 - saaj.factory.Invalid - * @run main/othervm SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - - * scenario12 - - - * @run main/othervm SAAJFactoryTest saaj.factory.Valid - - * scenario15 - saaj.factory.Valid + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - scenario2 - - + * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.Valid + * SAAJFactoryTest saaj.factory.Valid - scenario5 - - + * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.NonExisting + * SAAJFactoryTest - javax.xml.soap.SOAPException scenario6 - - + * @run main/othervm -addmods java.xml.ws -Djavax.xml.soap.MessageFactory=saaj.factory.Invalid + * SAAJFactoryTest - javax.xml.soap.SOAPException scenario7 - - + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest saaj.factory.Valid - scenario8 - saaj.factory.Valid + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest saaj.factory.Valid - scenario9 - saaj.factory.Valid + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest - javax.xml.soap.SOAPException scenario10 - saaj.factory.NonExisting + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest - javax.xml.soap.SOAPException scenario11 - saaj.factory.Invalid scenario11 - saaj.factory.Invalid + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl - scenario12 - - + * @run main/othervm -addmods java.xml.ws + * SAAJFactoryTest saaj.factory.Valid - scenario15 - saaj.factory.Valid */ public class SAAJFactoryTest { diff --git a/jdk/test/javax/xml/ws/8043129/MailTest.java b/jdk/test/javax/xml/ws/8043129/MailTest.java index 3d32a7d4dd8..73b0959a379 100644 --- a/jdk/test/javax/xml/ws/8043129/MailTest.java +++ b/jdk/test/javax/xml/ws/8043129/MailTest.java @@ -27,8 +27,8 @@ * @summary JAF initialisation in SAAJ clashing with the one in javax.mail * @author mkos * @library javax.mail.jar - * @build MailTest - * @run main MailTest + * @compile -addmods java.xml.ws MailTest.java + * @run main/othervm -addmods java.xml.ws MailTest */ import javax.activation.CommandMap; diff --git a/jdk/test/javax/xml/ws/clientjar/TestWsImport.java b/jdk/test/javax/xml/ws/clientjar/TestWsImport.java index dadceb34295..bc048e84b08 100644 --- a/jdk/test/javax/xml/ws/clientjar/TestWsImport.java +++ b/jdk/test/javax/xml/ws/clientjar/TestWsImport.java @@ -25,7 +25,8 @@ * @test * @bug 8016271 8026405 * @summary wsimport -clientjar does not create portable jar on windows due to hardcoded '\' - * @run main/othervm TestWsImport + * @compile -addmods java.xml.ws TestWsImport.java + * @run main/othervm -addmods java.xml.ws TestWsImport */ import javax.xml.namespace.QName; diff --git a/jdk/test/javax/xml/ws/publish/WSTest.java b/jdk/test/javax/xml/ws/publish/WSTest.java index 539f2d4b53b..651d2fbdaff 100644 --- a/jdk/test/javax/xml/ws/publish/WSTest.java +++ b/jdk/test/javax/xml/ws/publish/WSTest.java @@ -25,7 +25,8 @@ * @test * @bug 8146086 * @summary Publishing two webservices on same port fails with "java.net.BindException: Address already in use" - * @run main/othervm WSTest + * @compile -addmods java.xml.ws WSTest.java + * @run main/othervm -addmods java.xml.ws WSTest */ import javax.jws.WebMethod; import javax.jws.WebService; diff --git a/jdk/test/javax/xml/ws/xsanymixed/Test.java b/jdk/test/javax/xml/ws/xsanymixed/Test.java index 4287d8c08c5..a4f5476220d 100644 --- a/jdk/test/javax/xml/ws/xsanymixed/Test.java +++ b/jdk/test/javax/xml/ws/xsanymixed/Test.java @@ -27,7 +27,8 @@ * @summary the content of xs:any content:mixed should remain as is, * no white space changes and no changes to namespace prefixes * @run shell compile-wsdl.sh - * @run main/othervm Test + * @compile -addmods java.xml.ws Test.java + * @run main/othervm -addmods java.xml.ws Test */ import com.sun.net.httpserver.HttpServer; diff --git a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java index 4f80a59d290..4b2b2093ed2 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java +++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java @@ -26,7 +26,6 @@ import java.util.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; -import javax.xml.bind.DatatypeConverter; public class SecretKeysBasic extends PKCS11Test { @@ -131,8 +130,11 @@ public class SecretKeysBasic extends PKCS11Test { System.out.println(info + "> " + key); System.out.println("\tALGO=" + key.getAlgorithm()); if (key.getFormat() != null) { - System.out.println("\t[" + key.getFormat() + "] VALUE=" + - DatatypeConverter.printHexBinary(key.getEncoded())); + StringBuilder sb = new StringBuilder(); + for (byte b : key.getEncoded()) { + sb.append(String.format("%02x", b & 0xff)); + } + System.out.println("\t[" + key.getFormat() + "] VALUE=" + sb); } else { System.out.println("\tVALUE=n/a"); } diff --git a/jdk/test/sun/security/provider/PolicyFile/Modules.java b/jdk/test/sun/security/provider/PolicyFile/Modules.java index 5cd7f3dca58..855441e036a 100644 --- a/jdk/test/sun/security/provider/PolicyFile/Modules.java +++ b/jdk/test/sun/security/provider/PolicyFile/Modules.java @@ -25,7 +25,9 @@ * @test * @bug 8047771 * @summary check permissions and principals from various modules - * @run main/othervm/java.security.policy==modules.policy Modules + * @compile -addmods java.xml.ws,java.smartcardio Modules.java + * @run main/othervm/java.security.policy==modules.policy + * -addmods java.xml.ws,java.smartcardio Modules */ import java.security.AccessController; diff --git a/jdk/test/tools/jar/modularJar/Basic.java b/jdk/test/tools/jar/modularJar/Basic.java index 40829ec9280..417f71a2f5e 100644 --- a/jdk/test/tools/jar/modularJar/Basic.java +++ b/jdk/test/tools/jar/modularJar/Basic.java @@ -340,43 +340,43 @@ public class Basic { "--file=" + modularJar.toString()) .assertSuccess() .resultChecker(r -> { - // Expect similar output: "Name:bar, Requires: foo,... - // Conceals: jdk.test.foo, jdk.test.foo.internal" - Pattern p = Pattern.compile("\\s+Name:\\s+bar\\s+Requires:\\s+foo"); + // Expect similar output: "bar, requires mandated foo, ... + // conceals jdk.test.foo, conceals jdk.test.foo.internal" + Pattern p = Pattern.compile("\\s+bar\\s+requires\\s++foo"); assertTrue(p.matcher(r.output).find(), - "Expecting to find \"Name: bar, Requires: foo,...\"", + "Expecting to find \"bar, requires foo,...\"", "in output, but did not: [" + r.output + "]"); p = Pattern.compile( - "Conceals:\\s+jdk.test.foo\\s+jdk.test.foo.internal"); + "conceals\\s+jdk.test.foo\\s+conceals\\s+jdk.test.foo.internal"); assertTrue(p.matcher(r.output).find(), - "Expecting to find \"Conceals: jdk.test.foo,...\"", + "Expecting to find \"conceals jdk.test.foo,...\"", "in output, but did not: [" + r.output + "]"); }); } @Test - public void dependencesFooBar() throws IOException { + public void hashBarInFooModule() throws IOException { Path mp = Paths.get("dependencesFooBar"); createTestDir(mp); - Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName); - Path modularJar = mp.resolve(FOO.moduleName + ".jar"); - jar("--create", - "--file=" + modularJar.toString(), - "--main-class=" + FOO.mainClass, - "--module-version=" + FOO.version, - "--no-manifest", - "-C", modClasses.toString(), ".") - .assertSuccess(); - - modClasses = MODULE_CLASSES.resolve(BAR.moduleName); - modularJar = mp.resolve(BAR.moduleName + ".jar"); + Path modClasses = MODULE_CLASSES.resolve(BAR.moduleName); + Path modularJar = mp.resolve(BAR.moduleName + ".jar"); jar("--create", "--file=" + modularJar.toString(), "--main-class=" + BAR.mainClass, "--module-version=" + BAR.version, + "--no-manifest", + "-C", modClasses.toString(), ".") + .assertSuccess(); + + modClasses = MODULE_CLASSES.resolve(FOO.moduleName); + modularJar = mp.resolve(FOO.moduleName + ".jar"); + jar("--create", + "--file=" + modularJar.toString(), + "--main-class=" + FOO.mainClass, + "--module-version=" + FOO.version, "--modulepath=" + mp.toString(), - "--hash-dependencies=" + "foo", // dependency on foo + "--hash-modules=" + "bar", "--no-manifest", "-C", modClasses.toString(), ".") .assertSuccess(); @@ -392,49 +392,49 @@ public class Basic { } @Test - public void badDependencyFooBar() throws IOException { + public void invalidHashInFooModule() throws IOException { Path mp = Paths.get("badDependencyFooBar"); createTestDir(mp); - Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName); - Path fooJar = mp.resolve(FOO.moduleName + ".jar"); - jar("--create", - "--file=" + fooJar.toString(), - "--main-class=" + FOO.mainClass, - "--module-version=" + FOO.version, - "--no-manifest", - "-C", fooClasses.toString(), ".").assertSuccess(); - Path barClasses = MODULE_CLASSES.resolve(BAR.moduleName); Path barJar = mp.resolve(BAR.moduleName + ".jar"); jar("--create", "--file=" + barJar.toString(), "--main-class=" + BAR.mainClass, "--module-version=" + BAR.version, - "--modulepath=" + mp.toString(), - "--hash-dependencies=" + "foo", // dependency on foo "--no-manifest", "-C", barClasses.toString(), ".").assertSuccess(); - // Rebuild foo.jar with a change that will cause its hash to be different - FileUtils.deleteFileWithRetry(fooJar); + Path fooClasses = MODULE_CLASSES.resolve(FOO.moduleName); + Path fooJar = mp.resolve(FOO.moduleName + ".jar"); jar("--create", "--file=" + fooJar.toString(), "--main-class=" + FOO.mainClass, - "--module-version=" + FOO.version + ".1", // a newer version + "--module-version=" + FOO.version, + "--modulepath=" + mp.toString(), + "--hash-modules=" + "bar", "--no-manifest", "-C", fooClasses.toString(), ".").assertSuccess(); + // Rebuild bar.jar with a change that will cause its hash to be different + FileUtils.deleteFileWithRetry(barJar); + jar("--create", + "--file=" + barJar.toString(), + "--main-class=" + BAR.mainClass, + "--module-version=" + BAR.version + ".1", // a newer version + "--no-manifest", + "-C", barClasses.toString(), ".").assertSuccess(); + java(mp, BAR.moduleName + "/" + BAR.mainClass, "-XaddExports:java.base/jdk.internal.module=bar") .assertFailure() .resultChecker(r -> { // Expect similar output: "java.lang.module.ResolutionException: Hash - // of foo (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to + // of bar (WdktSIQSkd4+CEacpOZoeDrCosMATNrIuNub9b5yBeo=) differs to // expected hash (iepvdv8xTeVrFgMtUhcFnmetSub6qQHCHc92lSaSEg0=)" - Pattern p = Pattern.compile(".*Hash of foo.*differs to expected hash.*"); + Pattern p = Pattern.compile(".*Hash of bar.*differs to expected hash.*"); assertTrue(p.matcher(r.output).find(), - "Expecting error message containing \"Hash of foo ... differs to" + "Expecting error message containing \"Hash of bar ... differs to" + " expected hash...\" but got: [", r.output + "]"); }); } @@ -454,7 +454,7 @@ public class Basic { jar("--create", "--file=" + modularJar.toString(), - "--hash-dependencies=" + ".*", // no module-info.class + "--hash-modules=" + ".*", // no module-info.class "-C", modClasses.toString(), "jdk") .assertFailure(); // TODO: expected failure message } diff --git a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java index 7d768fc15d2..181491ab601 100644 --- a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java +++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java @@ -30,7 +30,7 @@ import java.lang.reflect.Method; import java.util.Optional; import java.util.StringJoiner; -import jdk.internal.module.Hasher; +import jdk.internal.module.ModuleHashes; import jdk.test.bar.internal.Message; public class Bar { @@ -43,10 +43,11 @@ public class Bar { Method m = ModuleDescriptor.class.getDeclaredMethod("hashes"); m.setAccessible(true); - Optional optHashes = - (Optional) m.invoke(md); + ModuleDescriptor foo = jdk.test.foo.Foo.class.getModule().getDescriptor(); + Optional oHashes = + (Optional) m.invoke(foo); - System.out.println("hashes:" + optHashes.get().hashFor("foo")); + System.out.println("hashes:" + oHashes.get().hashFor("bar")); StringJoiner sj = new StringJoiner(","); md.conceals().forEach(sj::add); diff --git a/jdk/test/tools/jlink/ImageFileCreatorTest.java b/jdk/test/tools/jlink/ImageFileCreatorTest.java index a674925b223..449d950d04d 100644 --- a/jdk/test/tools/jlink/ImageFileCreatorTest.java +++ b/jdk/test/tools/jlink/ImageFileCreatorTest.java @@ -214,14 +214,12 @@ public class ImageFileCreatorTest { } @Override - public void storeFiles(Pool content, String bom) { - + public void storeFiles(Pool content) { } - }; ImagePluginStack stack = new ImagePluginStack(noopBuilder, Collections.emptyList(), - null, Collections.emptyList(), ""); + null, Collections.emptyList()); ImageFileCreator.create(archives, ByteOrder.nativeOrder(), stack); } diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java index 05c61207b7d..951c16cff74 100644 --- a/jdk/test/tools/jlink/IntegrationTest.java +++ b/jdk/test/tools/jlink/IntegrationTest.java @@ -241,7 +241,7 @@ public class IntegrationTest { lst.add(new MyPostProcessor()); } // Image builder - DefaultImageBuilder builder = new DefaultImageBuilder(true, output); + DefaultImageBuilder builder = new DefaultImageBuilder(output); PluginsConfiguration plugins = new Jlink.PluginsConfiguration(lst, builder, null); @@ -254,10 +254,6 @@ public class IntegrationTest { if (!jimage.exists()) { throw new AssertionError("jimage not generated"); } - File bom = new File(output.toString(), "bom"); - if (!bom.exists()) { - throw new AssertionError("bom not generated"); - } File release = new File(output.toString(), "release"); if (!release.exists()) { throw new AssertionError("release not generated"); @@ -311,7 +307,7 @@ public class IntegrationTest { } // Image builder - DefaultImageBuilder builder = new DefaultImageBuilder(false, output); + DefaultImageBuilder builder = new DefaultImageBuilder(output); PluginsConfiguration plugins = new Jlink.PluginsConfiguration(lst, builder, null); @@ -359,7 +355,7 @@ public class IntegrationTest { } // Image builder - DefaultImageBuilder builder = new DefaultImageBuilder(false, output); + DefaultImageBuilder builder = new DefaultImageBuilder(output); PluginsConfiguration plugins = new Jlink.PluginsConfiguration(lst, builder, null); boolean failed = false; diff --git a/jdk/test/tools/jlink/JLink2Test.java b/jdk/test/tools/jlink/JLink2Test.java index d68242590ce..8106fadee32 100644 --- a/jdk/test/tools/jlink/JLink2Test.java +++ b/jdk/test/tools/jlink/JLink2Test.java @@ -66,8 +66,6 @@ public class JLink2Test { // This test case must be first one, the JlinkTask is clean // and reveals possible bug related to plugin options in defaults - // e. g.: --genbom - testBomFile(helper); testSameNames(helper); testModulePath(helper); testOptions(); @@ -136,35 +134,6 @@ public class JLink2Test { validator.validate(); } - private static void testBomFile(Helper helper) throws Exception { - String[] userOptions = { - "--compress", - "2", - "--addmods", - "bomzip", - "--strip-debug", - "--genbom", - "--exclude-resources", - "*.jcov,*/META-INF/*"}; - String moduleName = "bomzip"; - helper.generateDefaultJModule(moduleName, "composite2"); - Path imgDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess(); - helper.checkImage(imgDir, moduleName, userOptions, null, null); - File bom = new File(imgDir.toFile(), "bom"); - if (!bom.exists()) { - throw new RuntimeException(bom.getAbsolutePath() + " not generated"); - } - String bomcontent = new String(Files.readAllBytes(bom.toPath())); - if (!bomcontent.contains("--strip-debug") - || !bomcontent.contains("--compress") - || !bomcontent.contains("--genbom") - || !bomcontent.contains("--exclude-resources *.jcov," - + "*/META-INF/*") - || !bomcontent.contains("--addmods bomzip")) { - throw new Exception("Not expected content in " + bom); - } - } - private static void testOptions() throws Exception { List builtInPlugins = new ArrayList<>(); builtInPlugins.addAll(PluginRepository.getPlugins(Layer.boot())); diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java index e37b9023f41..9f7749df72d 100644 --- a/jdk/test/tools/jlink/JLinkTest.java +++ b/jdk/test/tools/jlink/JLinkTest.java @@ -204,7 +204,7 @@ public class JLinkTest { String[] userOptions = {"--compress", "invalid"}; String moduleName = "invalidCompressLevel"; helper.generateDefaultJModule(moduleName, "composite2"); - helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid level invalid"); + helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid"); } // @file diff --git a/jdk/test/tools/jlink/hashes/HashesTest.java b/jdk/test/tools/jlink/hashes/HashesTest.java deleted file mode 100644 index 8060bd9d466..00000000000 --- a/jdk/test/tools/jlink/hashes/HashesTest.java +++ /dev/null @@ -1,160 +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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test the recording and checking of dependency hashes - * @author Andrei Eremeev - * @library /lib/testlibrary - * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink - * jdk.jlink/jdk.tools.jmod - * jdk.compiler - * @ignore - * @build jdk.testlibrary.ProcessTools jdk.testlibrary.OutputAnalyzer CompilerUtils - * @run main HashesTest - */ - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import jdk.testlibrary.OutputAnalyzer; -import jdk.testlibrary.ProcessTools; - -public class HashesTest { - - private final Path jdkHome = Paths.get(System.getProperty("test.jdk")); - private final Path stdJmods = jdkHome.resolve("jmods"); - private final Path testSrc = Paths.get(System.getProperty("test.src")); - private final Path modSrc = testSrc.resolve("src"); - private final Path newModSrc = testSrc.resolve("newsrc"); - private final Path classes = Paths.get("classes"); - private final Path jmods = Paths.get("jmods"); - - public static void main(String[] args) throws Exception { - new HashesTest().run(); - } - - private void run() throws Exception { - if (!Files.exists(stdJmods)) { - return; - } - Files.createDirectories(jmods); - Path m1Classes = classes.resolve("m1"); - Path m2Classes = classes.resolve("m2"); - Path m3Classes = classes.resolve("not_matched"); - // build the second module - compileClasses(modSrc, m2Classes); - runJmod(m2Classes.toString(), m2Classes.getFileName().toString()); - - // build the third module - compileClasses(modSrc, m3Classes); - runJmod(m3Classes.toString(), m3Classes.getFileName().toString()); - - compileClasses(modSrc, m1Classes, "-mp", jmods.toString()); - runJmod(m1Classes.toString(), m1Classes.getFileName().toString(), - "--modulepath", jmods.toString(), "--hash-dependencies", "m2"); - runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main"); - - deleteDirectory(m3Classes); - Files.delete(jmods.resolve("not_matched.jmod")); - - // build the new third module - compileClasses(newModSrc, m3Classes); - runJmod(m3Classes.toString(), m3Classes.getFileName().toString()); - runJava(0, "-mp", jmods.toString(), "-m", "m1/org.m1.Main"); - - deleteDirectory(m2Classes); - Files.delete(jmods.resolve("m2.jmod")); - - compileClasses(newModSrc, m2Classes); - runJmod(m2Classes.toString(), m2Classes.getFileName().toString()); - - runJava(1, "-mp", jmods.toString(), "-m", "m1/org.m1.Main"); - - if (jdk.tools.jlink.internal.Main.run(new String[]{ - "--modulepath", stdJmods.toString() + File.pathSeparator + jmods.toString(), - "--addmods", "m1", "--output", "myimage"}, new PrintWriter(System.out)) == 0) { - throw new AssertionError("Expected failure. rc = 0"); - } - } - - private void deleteDirectory(Path dir) throws IOException { - Files.walkFileTree(dir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } - - private void runJava(int expectedExitCode, String... args) throws Exception { - OutputAnalyzer analyzer = ProcessTools.executeTestJava(args); - if (analyzer.getExitValue() != expectedExitCode) { - throw new AssertionError("Expected exit code: " + expectedExitCode + - ", got: " + analyzer.getExitValue()); - } - } - - private void compileClasses(Path src, Path output, String... options) throws IOException { - List args = new ArrayList<>(); - Collections.addAll(args, options); - Collections.addAll(args, "-d", output.toString()); - args.add(src.toString()); - System.out.println("javac options: " + args.stream().collect(Collectors.joining(" "))); - if (!CompilerUtils.compile(src.resolve(output.getFileName()), output, options)) { - throw new AssertionError("Compilation failure. See log."); - } - } - - private void runJmod(String cp, String modName, String... options) { - List args = new ArrayList<>(); - args.add("create"); - Collections.addAll(args, options); - Collections.addAll(args, "--class-path", cp, - jmods + File.separator + modName + ".jmod"); - int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out); - System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" "))); - if (rc != 0) { - throw new AssertionError("Jmod failed: rc = " + rc); - } - } -} diff --git a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java index 69388e7f6e9..5fecfec388b 100644 --- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java +++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java @@ -101,9 +101,8 @@ public class FileCopierPluginTest { } Path root = new File(".").toPath(); - DefaultImageBuilder imgbuilder = new DefaultImageBuilder(false, - root); - imgbuilder.storeFiles(pool, ""); + DefaultImageBuilder imgbuilder = new DefaultImageBuilder(root); + imgbuilder.storeFiles(pool); if (lic.exists()) { File license = new File(root.toFile(), "LICENSE"); diff --git a/jdk/test/tools/jmod/JmodNegativeTest.java b/jdk/test/tools/jmod/JmodNegativeTest.java index 5469726a318..9149dc001d9 100644 --- a/jdk/test/tools/jmod/JmodNegativeTest.java +++ b/jdk/test/tools/jmod/JmodNegativeTest.java @@ -76,7 +76,7 @@ public class JmodNegativeTest { jmod() .assertFailure() .resultChecker(r -> - assertContains(r.output, "Error: one of create, list, or describe must be specified") + assertContains(r.output, "Error: one of create, list, describe, or hash must be specified") ); } @@ -85,7 +85,7 @@ public class JmodNegativeTest { jmod("badAction") .assertFailure() .resultChecker(r -> - assertContains(r.output, "Error: mode must be one of create, list, or describe") + assertContains(r.output, "Error: mode must be one of create, list, describe, or hash") ); jmod("--badOption") @@ -170,14 +170,14 @@ public class JmodNegativeTest { } @Test - public void testHashDependenciesModulePathNotSpecified() { + public void testHashModulesModulePathNotSpecified() { jmod("create", - "--hash-dependencies", "anyPattern.*", + "--hash-modules", "anyPattern.*", "output.jmod") .assertFailure() .resultChecker(r -> assertContains(r.output, "Error: --module-path must be " - +"specified when hashing dependencies") + +"specified when hashing modules") ); } @@ -317,7 +317,7 @@ public class JmodNegativeTest { } @Test - public void testDependencyNotFound() throws IOException { + public void testNoModuleHash() throws IOException { Path jmod = MODS_DIR.resolve("output.jmod"); FileUtils.deleteFileIfExistsWithRetry(jmod); Path emptyDir = Paths.get("empty"); @@ -328,13 +328,12 @@ public class JmodNegativeTest { jmod("create", "--class-path", cp, - "--hash-dependencies", ".*", + "--hash-modules", ".*", "--modulepath", emptyDir.toString(), jmod.toString()) - .assertFailure() .resultChecker(r -> - assertContains(r.output, "Hashing module foo dependencies, " - + "unable to find module java.base on module path") + assertContains(r.output, "No hashes recorded: " + + "no module specified for hashing depends on foo") ); } @@ -350,13 +349,10 @@ public class JmodNegativeTest { jmod("create", "--class-path", cp, - "--hash-dependencies", ".*", + "--hash-modules", ".*", "--modulepath", MODS_DIR.toString(), jmod.toString()) - .assertFailure() - .resultChecker(r -> - assertContains(r.output, "Error: error reading module path") - ); + .assertFailure(); } finally { FileUtils.deleteFileWithRetry(empty); } @@ -371,7 +367,7 @@ public class JmodNegativeTest { Files.createFile(file); jmod("create", - "--hash-dependencies", ".*", + "--hash-modules", ".*", "--modulepath", file.toString(), jmod.toString()) .assertFailure() @@ -388,7 +384,7 @@ public class JmodNegativeTest { List> tasks = Arrays.asList( () -> jmod("create", - "--hash-dependencies", "anyPattern", + "--hash-modules", "anyPattern", "--modulepath", "doesNotExist", "output.jmod"), () -> jmod("create", @@ -436,7 +432,7 @@ public class JmodNegativeTest { List> tasks = Arrays.asList( () -> jmod("create", - "--hash-dependencies", "anyPattern", + "--hash-modules", "anyPattern", "--modulepath","empty" + pathSeparator + "doesNotExist", "output.jmod"), () -> jmod("create", diff --git a/jdk/test/tools/jmod/hashes/HashesTest.java b/jdk/test/tools/jmod/hashes/HashesTest.java new file mode 100644 index 00000000000..243ecbd8190 --- /dev/null +++ b/jdk/test/tools/jmod/hashes/HashesTest.java @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test the recording and checking of module hashes + * @author Andrei Eremeev + * @library /lib/testlibrary + * @modules java.base/jdk.internal.module + * jdk.jlink/jdk.tools.jlink.internal + * jdk.jlink/jdk.tools.jmod + * jdk.compiler + * @build CompilerUtils + * @run testng HashesTest + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.lang.reflect.Method; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import jdk.internal.module.ConfigurableModuleFinder; +import jdk.internal.module.ModuleHashes; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +public class HashesTest { + + private final Path testSrc = Paths.get(System.getProperty("test.src")); + private final Path modSrc = testSrc.resolve("src"); + private final Path mods = Paths.get("mods"); + private final Path jmods = Paths.get("jmods"); + private final String[] modules = new String[] { "m1", "m2", "m3"}; + + private static Method hashesMethod; + @BeforeTest + private void setup() throws Exception { + if (Files.exists(jmods)) { + deleteDirectory(jmods); + } + Files.createDirectories(jmods); + + // build m2, m3 required by m1 + compileModule("m2", modSrc); + jmod("m2"); + + compileModule("m3", modSrc); + jmod("m3"); + + // build m1 + compileModule("m1", modSrc); + // no hash is recorded since m1 has outgoing edges + jmod("m1", "--modulepath", jmods.toString(), "--hash-modules", ".*"); + + // compile org.bar and org.foo + compileModule("org.bar", modSrc); + compileModule("org.foo", modSrc); + + try { + hashesMethod = ModuleDescriptor.class.getDeclaredMethod("hashes"); + hashesMethod.setAccessible(true); + } catch (ReflectiveOperationException x) { + throw new InternalError(x); + } + } + + @Test + public void test() throws Exception { + for (String mn : modules) { + assertFalse(hashes(mn).isPresent()); + } + + // hash m1 in m2 + jmod("m2", "--modulepath", jmods.toString(), "--hash-modules", "m1"); + checkHashes(hashes("m2").get(), "m1"); + + // hash m1 in m2 + jmod("m2", "--modulepath", jmods.toString(), "--hash-modules", ".*"); + checkHashes(hashes("m2").get(), "m1"); + + // create m2.jmod with no hash + jmod("m2"); + // run jmod hash command to hash m1 in m2 and m3 + runJmod(Arrays.asList("hash", "--modulepath", jmods.toString(), + "--hash-modules", ".*")); + checkHashes(hashes("m2").get(), "m1"); + checkHashes(hashes("m3").get(), "m1"); + + jmod("org.bar"); + jmod("org.foo"); + + jmod("org.bar", "--modulepath", jmods.toString(), "--hash-modules", "org.*"); + checkHashes(hashes("org.bar").get(), "org.foo"); + + jmod("m3", "--modulepath", jmods.toString(), "--hash-modules", ".*"); + checkHashes(hashes("m3").get(), "org.foo", "org.bar", "m1"); + } + + private void checkHashes(ModuleHashes hashes, String... hashModules) { + assertTrue(hashes.names().equals(Set.of(hashModules))); + } + + private Optional hashes(String name) throws Exception { + ModuleFinder finder = ModuleFinder.of(jmods.resolve(name + ".jmod")); + if (finder instanceof ConfigurableModuleFinder) { + ((ConfigurableModuleFinder) finder) + .configurePhase(ConfigurableModuleFinder.Phase.LINK_TIME); + } + ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new); + ModuleReader reader = mref.open(); + try (InputStream in = reader.open("module-info.class").get()) { + ModuleDescriptor md = ModuleDescriptor.read(in); + Optional hashes = + (Optional) hashesMethod.invoke(md); + System.out.format("hashes in module %s %s%n", name, + hashes.isPresent() ? "present" : "absent"); + if (hashes.isPresent()) { + hashes.get().names().stream() + .sorted() + .forEach(n -> System.out.format(" %s %s%n", n, hashes.get().hashFor(n))); + } + return hashes; + } finally { + reader.close(); + } + } + + private void deleteDirectory(Path dir) throws IOException { + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException + { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException + { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + + private void compileModule(String moduleName, Path src) throws IOException { + Path msrc = src.resolve(moduleName); + assertTrue(CompilerUtils.compile(msrc, mods, "-modulesourcepath", src.toString())); + } + + private void jmod(String moduleName, String... options) throws IOException { + Path mclasses = mods.resolve(moduleName); + Path outfile = jmods.resolve(moduleName + ".jmod"); + List args = new ArrayList<>(); + args.add("create"); + Collections.addAll(args, options); + Collections.addAll(args, "--class-path", mclasses.toString(), + outfile.toString()); + + if (Files.exists(outfile)) + Files.delete(outfile); + + runJmod(args); + } + + private void runJmod(List args) { + int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out); + System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" "))); + if (rc != 0) { + throw new AssertionError("Jmod failed: rc = " + rc); + } + } +} diff --git a/jdk/test/tools/jlink/hashes/src/m1/module-info.java b/jdk/test/tools/jmod/hashes/src/m1/module-info.java similarity index 97% rename from jdk/test/tools/jlink/hashes/src/m1/module-info.java rename to jdk/test/tools/jmod/hashes/src/m1/module-info.java index 8268cd84662..be3af51bf37 100644 --- a/jdk/test/tools/jlink/hashes/src/m1/module-info.java +++ b/jdk/test/tools/jmod/hashes/src/m1/module-info.java @@ -23,5 +23,5 @@ module m1 { requires m2; - requires not_matched; + requires m3; } diff --git a/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java b/jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java similarity index 97% rename from jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java rename to jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java index 5b1d2f0c8e3..4108327b1fe 100644 --- a/jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java +++ b/jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java @@ -24,7 +24,7 @@ package org.m1; import org.m2.Util; -import org.not_matched.Name; +import org.m3.Name; public class Main { public static void main(String[] args) { diff --git a/jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java b/jdk/test/tools/jmod/hashes/src/m2/module-info.java similarity index 100% rename from jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java rename to jdk/test/tools/jmod/hashes/src/m2/module-info.java diff --git a/jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java b/jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java similarity index 100% rename from jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java rename to jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java diff --git a/jdk/test/tools/jlink/hashes/src/m2/module-info.java b/jdk/test/tools/jmod/hashes/src/m3/module-info.java similarity index 97% rename from jdk/test/tools/jlink/hashes/src/m2/module-info.java rename to jdk/test/tools/jmod/hashes/src/m3/module-info.java index 4489049b402..a39d7ba860e 100644 --- a/jdk/test/tools/jlink/hashes/src/m2/module-info.java +++ b/jdk/test/tools/jmod/hashes/src/m3/module-info.java @@ -21,6 +21,6 @@ * questions. */ -module m2 { - exports org.m2; +module m3 { + exports org.m3; } diff --git a/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java b/jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java similarity index 95% rename from jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java rename to jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java index d17333408cb..62040eb55b2 100644 --- a/jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java +++ b/jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java @@ -21,12 +21,12 @@ * questions. */ -package org.not_matched; +package org.m3; public class Name { private Name() { } public static String name() { - return "old_module"; + return "m3"; } } diff --git a/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java b/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java similarity index 89% rename from jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java rename to jdk/test/tools/jmod/hashes/src/org.bar/module-info.java index a72988ae6ae..a269fd5ea8c 100644 --- a/jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java +++ b/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,6 +21,6 @@ * questions. */ -module not_matched { - exports org.not_matched; +module org.bar { + requires public m1; } diff --git a/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java b/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java similarity index 89% rename from jdk/test/tools/jlink/hashes/src/not_matched/module-info.java rename to jdk/test/tools/jmod/hashes/src/org.foo/module-info.java index a72988ae6ae..b143d5b0ece 100644 --- a/jdk/test/tools/jlink/hashes/src/not_matched/module-info.java +++ b/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,6 +21,6 @@ * questions. */ -module not_matched { - exports org.not_matched; +module org.foo { + requires public org.bar; } diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java index a0f67d24203..4b4a32bde2b 100644 --- a/jdk/test/tools/launcher/ToolsOpts.java +++ b/jdk/test/tools/launcher/ToolsOpts.java @@ -151,29 +151,26 @@ public class ToolsOpts extends TestHelper { init(); TestResult tr; int jpos = -1; + String xPatch = "-J-Xpatch:jdk.compiler=jdk.compiler"; for (String arg[] : optionPatterns) { jpos = indexOfJoption(arg); //Build a cmd string for output in results reporting. - String cmdString = javacCmd + " -J-Xpatch:."; + String cmdString = javacCmd + " " + xPatch; for (String opt : arg) { cmdString = cmdString.concat(" " + opt); } switch (arg.length) { case 1: - tr = doExec(javacCmd, "-J-Xpatch:.", - arg[0]); + tr = doExec(javacCmd, xPatch, arg[0]); break; case 2: - tr = doExec(javacCmd, "-J-Xpatch:.", - arg[0], arg[1]); + tr = doExec(javacCmd, xPatch, arg[0], arg[1]); break; case 3: - tr = doExec(javacCmd, "-J-Xpatch:.", - arg[0], arg[1], arg[2]); + tr = doExec(javacCmd, xPatch, arg[0], arg[1], arg[2]); break; case 4: - tr = doExec(javacCmd, "-J-Xpatch:.", - arg[0], arg[1], arg[2], arg[3]); + tr = doExec(javacCmd, xPatch, arg[0], arg[1], arg[2], arg[3]); break; default: tr = null; diff --git a/jdk/test/tools/launcher/modules/addmods/AddModsTest.java b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java index a65c3d4eb81..b1fe43c9a29 100644 --- a/jdk/test/tools/launcher/modules/addmods/AddModsTest.java +++ b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java @@ -47,120 +47,179 @@ public class AddModsTest { 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 MODS_DIR = Paths.get("mods"); + private static final Path MODS1_DIR = Paths.get("mods1"); + private static final Path MODS2_DIR = Paths.get("mods2"); - // the module name of the library module - private static final String LIB_MODULE = "lib"; + // test module / main class + private static final String TEST_MODULE = "test"; + private static final String TEST_MAIN_CLASS = "test.Main"; + private static final String TEST_MID = TEST_MODULE + "/" + TEST_MAIN_CLASS; - // application source directory - private static final String APP_SRC = "app"; - - // application is compiled to classes - private static final Path CLASSES_DIR = Paths.get("classes"); - - // application main class - private static final String MAIN_CLASS = "app.Main"; + // logger module + private static final String LOGGER_MODULE = "logger"; @BeforeTest public void compile() throws Exception { - - // javac -d mods/$LIB_MODULE src/$LIB_MODULE/** + // javac -d mods1/test src/test/** boolean compiled = CompilerUtils.compile( - SRC_DIR.resolve(LIB_MODULE), - MODS_DIR.resolve(LIB_MODULE) + SRC_DIR.resolve(TEST_MODULE), + MODS1_DIR.resolve(TEST_MODULE) ); - assertTrue(compiled, "library module did not compile"); + assertTrue(compiled, "test did not compile"); - // javac -d classes -mp mods src/$APP_DIR/** - compiled = CompilerUtils.compile( - SRC_DIR.resolve(APP_SRC), - CLASSES_DIR, - "-mp", MODS_DIR.toString(), - "-addmods", LIB_MODULE + // javac -d mods1/logger src/logger/** + compiled= CompilerUtils.compile( + SRC_DIR.resolve(LOGGER_MODULE), + MODS2_DIR.resolve(LOGGER_MODULE) ); - assertTrue(compiled, "app did not compile"); + assertTrue(compiled, "test did not compile"); } /** - * Basic test of -addmods ALL-SYSTEM, using the output of -listmods to - * check that the a sample of the system modules are resolved. + * Basic test of -addmods ALL-DEFAULT. Module java.sql should be + * resolved and the types in that module should be visible. + */ + public void testAddDefaultModules1() throws Exception { + + // java -addmods ALL-DEFAULT -mp mods1 -m test ... + int exitValue + = executeTestJava("-mp", MODS1_DIR.toString(), + "-addmods", "ALL-DEFAULT", + "-m", TEST_MID, + "java.sql.Connection") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /** + * Basic test of -addmods ALL-DEFAULT. Module java.annotations.common + * should not resolved and so the types in that module should not be + * visible. + */ + public void testAddDefaultModules2() throws Exception { + + // java -addmods ALL-DEFAULT -mp mods1 -m test ... + int exitValue + = executeTestJava("-mp", MODS1_DIR.toString(), + "-addmods", "ALL-DEFAULT", + "-m", TEST_MID, + "javax.annotation.Generated") + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("ClassNotFoundException") + .getExitValue(); + + assertTrue(exitValue != 0); + } + + /** + * Basic test of -addmods ALL-SYSTEM. All system modules should be resolved + * and thus all types in those modules should be visible. */ public void testAddSystemModules() throws Exception { - executeTestJava("-addmods", "ALL-SYSTEM", - "-listmods", - "-m", "java.base") - .outputTo(System.out) - .errorTo(System.out) - .shouldContain("java.sql") - .shouldContain("java.corba"); + // java -addmods ALL-SYSTEM -mp mods1 -m test ... + int exitValue + = executeTestJava("-mp", MODS1_DIR.toString(), + "-addmods", "ALL-SYSTEM", + "-m", TEST_MID, + "java.sql.Connection", + "javax.annotation.Generated") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); - // no exit value to check as -m java.base will likely fail + assertTrue(exitValue == 0); } /** - * Run application on class path that makes use of module on the - * application module path. Uses {@code -addmods lib} + * Run test on class path to load a type in a module on the application + * module path, uses {@code -addmods logger}. */ public void testRunWithAddMods() throws Exception { - // java -mp mods -addmods lib -cp classes app.Main + // java -mp mods -addmods logger -cp classes test.Main + String classpath = MODS1_DIR.resolve(TEST_MODULE).toString(); + String modulepath = MODS2_DIR.toString(); int exitValue - = executeTestJava("-mp", MODS_DIR.toString(), - "-addmods", LIB_MODULE, - "-cp", CLASSES_DIR.toString(), - MAIN_CLASS) + = executeTestJava("-mp", modulepath, + "-addmods", LOGGER_MODULE, + "-cp", classpath, + TEST_MAIN_CLASS, + "logger.Logger") .outputTo(System.out) .errorTo(System.out) .getExitValue(); assertTrue(exitValue == 0); - } + /** + * Run application on class path that makes use of module on the + * application module path. Does not use -addmods and so should + * fail at run-time. + */ + public void testRunMissingAddMods() throws Exception { + + // java -mp mods -cp classes test.Main + String classpath = MODS1_DIR.resolve(TEST_MODULE).toString(); + String modulepath = MODS1_DIR.toString(); + int exitValue + = executeTestJava("-mp", modulepath, + "-cp", classpath, + TEST_MAIN_CLASS, + "logger.Logger") + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("ClassNotFoundException") + .getExitValue(); + + assertTrue(exitValue != 0); + } + + /** - * Run application on class path that makes use of module on the - * application module path. Uses {@code -addmods ALL-MODULE-PATH}. + * Run test on class path to load a type in a module on the application + * module path, uses {@code -addmods ALL-MODULE-PATH}. */ public void testAddAllModulePath() throws Exception { - // java -mp mods -addmods lib -cp classes app.Main + // java -mp mods -addmods ALL-MODULE-PATH -cp classes test.Main + String classpath = MODS1_DIR.resolve(TEST_MODULE).toString(); + String modulepath = MODS1_DIR.toString(); int exitValue - = executeTestJava("-mp", MODS_DIR.toString(), + = executeTestJava("-mp", modulepath, "-addmods", "ALL-MODULE-PATH", - "-cp", CLASSES_DIR.toString(), - MAIN_CLASS) + "-cp", classpath, + TEST_MAIN_CLASS) .outputTo(System.out) .errorTo(System.out) .getExitValue(); assertTrue(exitValue == 0); - } /** - * Run application on class path that makes use of module on the - * application module path. Does not use -addmods and so will - * fail at run-time. + * Test {@code -addmods ALL-MODULE-PATH} without {@code -modulepath}. */ - public void testRunMissingAddMods() throws Exception { + public void testAddAllModulePathWithNoModulePath() throws Exception { - // java -mp mods -cp classes app.Main + // java -addmods ALL-MODULE-PATH -version int exitValue - = executeTestJava("-mp", MODS_DIR.toString(), - "-cp", CLASSES_DIR.toString(), - MAIN_CLASS) + = executeTestJava("-addmods", "ALL-MODULE-PATH", + "-version") .outputTo(System.out) .errorTo(System.out) .getExitValue(); - // CNFE or other error/exception - assertTrue(exitValue != 0); - + assertTrue(exitValue == 0); } @@ -169,18 +228,17 @@ public class AddModsTest { */ public void testRunWithBadAddMods() throws Exception { - // java -mp mods -addmods,DoesNotExist lib -cp classes app.Main + // java -mp mods -addmods DoesNotExist -m test ... int exitValue - = executeTestJava("-mp", MODS_DIR.toString(), - "-addmods", LIB_MODULE + ",DoesNotExist", - "-cp", CLASSES_DIR.toString(), - MAIN_CLASS) + = executeTestJava("-mp", MODS1_DIR.toString(), + "-addmods", "DoesNotExist", + "-m", TEST_MID) .outputTo(System.out) .errorTo(System.out) + .shouldContain("DoesNotExist") .getExitValue(); assertTrue(exitValue != 0); - } } diff --git a/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java b/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java deleted file mode 100644 index 682a22921f3..00000000000 --- a/jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 jdk.lib; - -public class Util { - private Util() { } - - public static Object makeObject() { - return new Object(); - } -} diff --git a/jdk/test/tools/launcher/modules/addmods/src/logger/logger/Logger.java b/jdk/test/tools/launcher/modules/addmods/src/logger/logger/Logger.java new file mode 100644 index 00000000000..0cb0c293263 --- /dev/null +++ b/jdk/test/tools/launcher/modules/addmods/src/logger/logger/Logger.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. + */ + +package logger; + +/** + * No-op user module for use by the {@code java -addmods} tests. + */ +public class Logger { +} diff --git a/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java b/jdk/test/tools/launcher/modules/addmods/src/logger/module-info.java similarity index 90% rename from jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java rename to jdk/test/tools/launcher/modules/addmods/src/logger/module-info.java index 16dae96e170..fc5a8257db4 100644 --- a/jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java +++ b/jdk/test/tools/launcher/modules/addmods/src/logger/module-info.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +/** + * 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 @@ -21,6 +21,4 @@ * questions. */ -module lib { - exports jdk.lib; -} +module logger { } diff --git a/jdk/test/tools/launcher/modules/addmods/src/test/module-info.java b/jdk/test/tools/launcher/modules/addmods/src/test/module-info.java new file mode 100644 index 00000000000..335d0bc1a12 --- /dev/null +++ b/jdk/test/tools/launcher/modules/addmods/src/test/module-info.java @@ -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. + */ + +module test { } diff --git a/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java b/jdk/test/tools/launcher/modules/addmods/src/test/test/Main.java similarity index 71% rename from jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java rename to jdk/test/tools/launcher/modules/addmods/src/test/test/Main.java index b7e0b62fc77..c6ca7a1be1b 100644 --- a/jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java +++ b/jdk/test/tools/launcher/modules/addmods/src/test/test/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,12 +21,17 @@ * questions. */ -package org.m2; +package test; -public class Util { - private Util() { } - - public static String timeOfDay() { - return "Time for a beer"; +/** + * Invoked by tests for the {@code java -addmods} option to check that types + * are visible. + */ +public class Main { + public static void main(String[] args) throws Exception { + for (String cn : args) { + Class c = Class.forName(cn); + System.out.println("Loaded: " + c); + } } } diff --git a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java index 3bcf4bfa50c..82d0c383f7a 100644 --- a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java +++ b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java @@ -25,7 +25,7 @@ * @test * @library /lib/testlibrary * @modules jdk.compiler - * @build AddReadsTest CompilerUtils jdk.testlibrary.* + * @build AddReadsTest CompilerUtils JarUtils jdk.testlibrary.* * @run testng AddReadsTest * @summary Basic tests for java -XaddReads */ diff --git a/jdk/test/tools/launcher/modules/patch/PatchTest.java b/jdk/test/tools/launcher/modules/patch/PatchTest.java index ba0ce877145..971362061ab 100644 --- a/jdk/test/tools/launcher/modules/patch/PatchTest.java +++ b/jdk/test/tools/launcher/modules/patch/PatchTest.java @@ -25,7 +25,7 @@ * @test * @library /lib/testlibrary * @modules jdk.compiler - * @build PatchTest CompilerUtils jdk.testlibrary.* + * @build PatchTest CompilerUtils JarUtils jdk.testlibrary.* * @run testng PatchTest * @summary Basic test for -Xpatch */ @@ -72,6 +72,9 @@ public class PatchTest { private static final Path SRC2_DIR = Paths.get(TEST_SRC, "src2"); private static final Path PATCHES2_DIR = Paths.get("patches2"); + // destination directory for patches packaged as JAR files + private static final Path PATCHES_DIR = Paths.get("patches"); + // the classes overridden or added with -Xpatch private static final String[] CLASSES = { @@ -95,7 +98,7 @@ public class PatchTest { @BeforeTest - public void compile() throws Exception { + public void setup() throws Exception { // javac -d mods/test src/test/** boolean compiled= CompilerUtils.compile(SRC_DIR.resolve("test"), @@ -103,36 +106,40 @@ public class PatchTest { assertTrue(compiled, "classes did not compile"); // javac -Xmodule:$MODULE -d patches1/$MODULE patches1/$MODULE/** + // jar cf patches/$MODULE-1.jar -C patches1/$MODULE . for (Path src : Files.newDirectoryStream(SRC1_DIR)) { Path output = PATCHES1_DIR.resolve(src.getFileName()); String mn = src.getFileName().toString(); compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn); assertTrue(compiled, "classes did not compile"); + JarUtils.createJarFile(PATCHES_DIR.resolve(mn + "-1.jar"), output); } // javac -Xmodule:$MODULE -d patches2/$MODULE patches2/$MODULE/** + // jar cf patches/$MODULE-2.jar -C patches2/$MODULE . for (Path src : Files.newDirectoryStream(SRC2_DIR)) { Path output = PATCHES2_DIR.resolve(src.getFileName()); String mn = src.getFileName().toString(); compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn); assertTrue(compiled, "classes did not compile"); + JarUtils.createJarFile(PATCHES_DIR.resolve(mn + "-2.jar"), output); } } /** - * Run the test with -Xpatch + * Run test with patches to java.base, jdk.naming.dns and jdk.compiler */ - public void testRunWithXPatch() throws Exception { - - // value for -Xpatch - String patchPath = PATCHES1_DIR + File.pathSeparator + PATCHES2_DIR; - + void runTest(String basePatches, String dnsPatches, String compilerPatches) + throws Exception + { // the argument to the test is the list of classes overridden or added String arg = Stream.of(CLASSES).collect(Collectors.joining(",")); int exitValue - = executeTestJava("-Xpatch:" + patchPath, + = executeTestJava("-Xpatch:java.base=" + basePatches, + "-Xpatch:jdk.naming.dns=" + dnsPatches, + "-Xpatch:jdk.compiler=" + compilerPatches, "-XaddExports:java.base/java.lang2=test", "-XaddExports:jdk.naming.dns/com.sun.jndi.dns=test", "-XaddExports:jdk.naming.dns/com.sun.jndi.dns2=test", @@ -145,6 +152,44 @@ public class PatchTest { .getExitValue(); assertTrue(exitValue == 0); + } + + + /** + * Run test with -Xpatch and exploded patches + */ + public void testWithExplodedPatches() throws Exception { + + // patches1/java.base:patches2/java.base + String basePatches = PATCHES1_DIR.resolve("java.base") + + File.pathSeparator + PATCHES2_DIR.resolve("java.base"); + + String dnsPatches = PATCHES1_DIR.resolve("jdk.naming.dns") + + File.pathSeparator + PATCHES2_DIR.resolve("jdk.naming.dns"); + + String compilerPatches = PATCHES1_DIR.resolve("jdk.compiler") + + File.pathSeparator + PATCHES2_DIR.resolve("jdk.compiler"); + + runTest(basePatches, dnsPatches, compilerPatches); + } + + + /** + * Run test with -Xpatch and patches in JAR files + */ + public void testWitJarPatches() throws Exception { + + // patches/java.base-1.jar:patches/java-base-2.jar + String basePatches = PATCHES_DIR.resolve("java.base-1.jar") + + File.pathSeparator + PATCHES_DIR.resolve("java.base-2.jar"); + + String dnsPatches = PATCHES_DIR.resolve("jdk.naming.dns-1.jar") + + File.pathSeparator + PATCHES_DIR.resolve("jdk.naming.dns-2.jar"); + + String compilerPatches = PATCHES_DIR.resolve("jdk.compiler-1.jar") + + File.pathSeparator + PATCHES_DIR.resolve("jdk.compiler-2.jar"); + + runTest(basePatches, dnsPatches, compilerPatches); } diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index c75164b69cc..a836e818243 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -113,7 +113,7 @@ public class JImageGenerator { private static final String CMDS_OPTION = "--cmds"; private static final String CONFIG_OPTION = "--config"; - private static final String HASH_DEPENDENCIES_OPTION = "--hash-dependencies"; + private static final String HASH_MODULES_OPTION = "--hash-modules"; private static final String LIBS_OPTION = "--libs"; private static final String MODULE_VERSION_OPTION = "--module-version"; @@ -347,7 +347,7 @@ public class JImageGenerator { private final List jmods = new ArrayList<>(); private final List options = new ArrayList<>(); private Path output; - private String hashDependencies; + private String hashModules; private String mainClass; private String moduleVersion; @@ -356,8 +356,8 @@ public class JImageGenerator { return this; } - public JModTask hashDependencies(String hash) { - this.hashDependencies = hash; + public JModTask hashModules(String hash) { + this.hashModules = hash; return this; } @@ -430,9 +430,9 @@ public class JImageGenerator { options.add(CONFIG_OPTION); options.add(toPath(config)); } - if (hashDependencies != null) { - options.add(HASH_DEPENDENCIES_OPTION); - options.add(hashDependencies); + if (hashModules != null) { + options.add(HASH_MODULES_OPTION); + options.add(hashModules); } if (mainClass != null) { options.add(MAIN_CLASS_OPTION); From 3a647e6b88a3c4fb200b5ddafebfb2c6b52eb571 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:36:12 +0200 Subject: [PATCH 209/225] Added tag jdk-9+115 for changeset 8d78fb40648d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0eced0f9e0d..3aec595d887 100644 --- a/.hgtags +++ b/.hgtags @@ -357,3 +357,4 @@ a6614ff7bf09da74be1d0ef3d9755090d244697a jdk-9+111 7359994942f8d8e723b584d66a3a92c2e9e95e5c jdk-9+112 6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 +8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115 From 1117b02a8eff96ef0ce97911c6f8b3b42e495ed3 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 21:38:13 +0200 Subject: [PATCH 210/225] Added tag jdk-9+116 for changeset 84aba7335005 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 3aec595d887..f293837b51c 100644 --- a/.hgtags +++ b/.hgtags @@ -358,3 +358,4 @@ a6614ff7bf09da74be1d0ef3d9755090d244697a jdk-9+111 6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115 +84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116 From e8cd76568da1b32b26491e80f498cff1409336b7 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Tue, 3 May 2016 15:50:54 +0200 Subject: [PATCH 211/225] 8155775: Re-examine naming of privileged methods to access System properties Reviewed-by: mullan --- .../sun/nio/fs/LinuxFileSystemProvider.java | 2 +- .../sun/nio/ch/KQueueArrayWrapper.java | 3 ++- .../classes/sun/nio/fs/MacOSXFileSystem.java | 2 -- .../sun/nio/fs/MacOSXFileSystemProvider.java | 4 ++-- .../java.base/share/classes/java/io/File.java | 2 +- .../classes/java/lang/ProcessBuilder.java | 2 +- .../classes/java/lang/StackStreamFactory.java | 10 ++------- .../invoke/InnerClassLambdaMetafactory.java | 2 +- .../java/lang/invoke/MethodHandleStatics.java | 2 +- .../java/lang/invoke/StringConcatFactory.java | 2 +- .../classes/java/lang/reflect/Proxy.java | 2 +- .../net/AbstractPlainDatagramSocketImpl.java | 3 ++- .../share/classes/java/net/InetAddress.java | 4 ++-- .../classes/java/net/SocksSocketImpl.java | 4 ++-- .../java.base/share/classes/java/net/URL.java | 2 +- .../share/classes/java/net/URLConnection.java | 2 +- .../share/classes/java/net/URLEncoder.java | 2 +- .../classes/java/nio/charset/Charset.java | 7 +++--- .../classes/java/nio/file/TempFileHelper.java | 2 +- .../share/classes/java/util/Locale.java | 4 ++-- .../java/util/PropertyResourceBundle.java | 5 ++--- .../share/classes/java/util/TimeZone.java | 14 +++++------- .../share/classes/java/util/jar/JarFile.java | 4 ++-- .../share/classes/java/util/jar/Pack200.java | 2 +- .../util/regex/PatternSyntaxException.java | 2 +- .../java/util/zip/ZipOutputStream.java | 2 +- .../javax/net/ssl/SSLSocketFactory.java | 2 +- .../java.base/share/classes/jdk/Version.java | 3 ++- .../jdk/internal/loader/URLClassPath.java | 2 +- .../internal/logger/LoggerFinderLoader.java | 4 ++-- .../internal/logger/SimpleConsoleLogger.java | 6 ++--- .../jdk/internal/reflect/Reflection.java | 4 ++-- .../internal/reflect/ReflectionFactory.java | 2 +- .../classes/sun/net/ResourceManager.java | 4 ++-- .../share/classes/sun/net/sdp/SdpSupport.java | 2 +- .../classes/sun/net/smtp/SmtpClient.java | 4 ++-- .../classes/sun/net/www/MimeLauncher.java | 2 +- .../classes/sun/net/www/http/HttpClient.java | 2 +- .../www/protocol/ftp/FtpURLConnection.java | 2 +- .../protocol/http/AuthenticationHeader.java | 2 +- .../www/protocol/http/HttpURLConnection.java | 14 ++++++------ .../net/www/protocol/https/HttpsClient.java | 7 +++--- .../jrt/JavaRuntimeURLConnection.java | 2 +- .../sun/net/www/protocol/netdoc/Handler.java | 4 ++-- .../classes/sun/nio/ch/FileChannelImpl.java | 2 +- .../share/classes/sun/nio/ch/Net.java | 8 +++---- .../share/classes/sun/nio/ch/Util.java | 6 +++-- .../sun/nio/cs/StandardCharsets.java.template | 7 +----- .../share/classes/sun/nio/fs/Util.java | 2 +- .../sun/security/action/GetIntegerAction.java | 15 +++++++++++-- .../security/action/GetPropertyAction.java | 22 ++++++++++++++++--- .../sun/security/provider/DSAKeyFactory.java | 2 +- .../provider/certpath/RevocationChecker.java | 1 - .../sun/security/rsa/RSAKeyFactory.java | 2 +- .../ssl/ClientKeyExchangeService.java | 2 +- .../share/classes/sun/security/ssl/Debug.java | 6 ++--- .../sun/security/ssl/SSLContextImpl.java | 3 ++- .../sun/security/ssl/ServerHandshaker.java | 4 ++-- .../security/ssl/StatusResponseManager.java | 4 ++-- .../classes/sun/security/util/Debug.java | 6 ++--- .../util/calendar/LocalGregorianCalendar.java | 2 +- .../sun/util/calendar/ZoneInfoFile.java | 2 +- .../provider/LocaleProviderAdapter.java | 2 +- .../classes/sun/nio/fs/SolarisFileSystem.java | 2 +- .../sun/nio/fs/SolarisFileSystemProvider.java | 2 +- .../unix/classes/java/io/UnixFileSystem.java | 2 +- .../unix/classes/java/lang/ProcessImpl.java | 4 ++-- .../net/DefaultDatagramSocketImplFactory.java | 2 +- .../unix/classes/sun/net/NetHooks.java | 3 --- .../unix/classes/sun/net/sdp/SdpProvider.java | 15 ++++++------- .../http/ntlm/NTLMAuthentication.java | 4 ++-- .../DefaultAsynchronousChannelProvider.java | 2 +- .../ch/UnixAsynchronousSocketChannelImpl.java | 4 ++-- .../sun/nio/fs/DefaultFileSystemProvider.java | 2 +- .../classes/sun/nio/fs/UnixFileSystem.java | 2 +- .../classes/java/io/WinNTFileSystem.java | 2 +- .../net/DefaultDatagramSocketImplFactory.java | 2 +- .../http/ntlm/NTLMAuthentication.java | 4 ++-- .../sun/nio/ch/FileDispatcherImpl.java | 2 +- .../sun/nio/fs/WindowsFileAttributes.java | 4 ++-- 80 files changed, 164 insertions(+), 152 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 8a2307d2ff6..46b2a8a7eb2 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,7 +102,7 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - String userHome = GetPropertyAction.getProperty("user.home"); + String userHome = GetPropertyAction.privilegedGetProperty("user.home"); Path userMimeTypes = Paths.get(userHome, ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); 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 7598cf9e37f..d85434504d6 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 @@ -84,7 +84,8 @@ class KQueueArrayWrapper { static { IOUtil.load(); initStructSizes(); - String datamodel = GetPropertyAction.getProperty("sun.arch.data.model"); + String datamodel = + GetPropertyAction.privilegedGetProperty("sun.arch.data.model"); is64bit = "64".equals(datamodel); } diff --git a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java index 0305171589d..fb88c794e5f 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java @@ -29,8 +29,6 @@ import java.nio.file.*; import java.io.IOException; import java.util.*; import java.util.regex.Pattern; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; import static sun.nio.fs.MacOSXNativeDispatcher.*; 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 6b9a56a9fa7..43a40283c80 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 @@ -46,8 +46,8 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get( - GetPropertyAction.getProperty("user.home"), ".mime.types"); + Path userMimeTypes = Paths.get(GetPropertyAction + .privilegedGetProperty("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 7f23340920b..41eff3eb92d 100644 --- a/jdk/src/java.base/share/classes/java/io/File.java +++ b/jdk/src/java.base/share/classes/java/io/File.java @@ -1896,7 +1896,7 @@ public class File // temporary directory location private static final File tmpdir = new File( - GetPropertyAction.getProperty("java.io.tmpdir")); + GetPropertyAction.privilegedGetProperty("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 638be0e9f72..31406459d93 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -468,7 +468,7 @@ public final class ProcessBuilder */ public abstract static class Redirect { private static final File NULL_FILE = new File( - (GetPropertyAction.getProperty("os.name") + (GetPropertyAction.privilegedGetProperty("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 73446062bea..7f7a3d80e68 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -78,7 +78,8 @@ final class StackStreamFactory { * Performance work and extensive testing is needed to replace the * VM built-in backtrace filled in Throwable with the StackWalker. */ - final static boolean isDebug = getProperty("stackwalk.debug", false); + final static boolean isDebug = + "true".equals(GetPropertyAction.privilegedGetProperty("stackwalk.debug")); static StackFrameTraverser makeStackTraverser(StackWalker walker, Function, ? extends T> function) @@ -988,11 +989,4 @@ final class StackStreamFactory { c.getName().startsWith("java.lang.invoke.LambdaForm"); } - private static boolean getProperty(String key, boolean value) { - String s = GetPropertyAction.getProperty(key); - if (s != null) { - 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 a0df622f501..0c814bdd470 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,7 +88,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; static { final String key = "jdk.internal.lambda.dumpProxyClasses"; - String path = GetPropertyAction.getProperty(key); + String path = GetPropertyAction.privilegedGetProperty(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 4fbc1d84671..bfaba660776 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 @@ -53,7 +53,7 @@ import sun.security.action.GetPropertyAction; static final boolean VAR_HANDLE_GUARDS; static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean( props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES")); DUMP_CLASS_FILES = Boolean.parseBoolean( 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 f302c75af79..0d965ed5a54 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 @@ -197,7 +197,7 @@ public final class StringConcatFactory { // DEBUG = false; // implied // DUMPER = null; // implied - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); final String strategy = props.getProperty("java.lang.invoke.stringConcat"); CACHE_ENABLE = Boolean.parseBoolean( 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 8802abeda76..450930fb929 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 @@ -582,7 +582,7 @@ public class Proxy implements java.io.Serializable { } private static final String DEBUG = - GetPropertyAction.getProperty("jdk.proxy.debug", ""); + GetPropertyAction.privilegedGetProperty("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 debc60f74b9..a295d862ada 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -52,7 +52,8 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl protected InetAddress connectedAddress = null; private int connectedPort = -1; - private static final String os = GetPropertyAction.getProperty("os.name"); + private static final String os = + GetPropertyAction.privilegedGetProperty("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 e79c5115413..e7fbf134353 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -1124,7 +1124,7 @@ class InetAddress implements java.io.Serializable { private static NameService createNameService() { String hostsFileName = - GetPropertyAction.getProperty("jdk.net.hosts.file"); + GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file"); NameService theNameService; if (hostsFileName != null) { theNameService = new HostsFileNameService(hostsFileName); @@ -1643,7 +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 = GetPropertyAction.getProperty("impl.prefix", ""); + String prefix = GetPropertyAction.privilegedGetProperty("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 c3a0d1c675a..f8ea9ce6c16 100644 --- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java @@ -178,7 +178,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = pw.getUserName(); password = new String(pw.getPassword()); } else { - userName = GetPropertyAction.getProperty("user.name"); + userName = GetPropertyAction.privilegedGetProperty("user.name"); } if (userName == null) return false; @@ -1088,7 +1088,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = System.getProperty("user.name"); } catch (SecurityException se) { /* swallow Exception */ } } else { - userName = GetPropertyAction.getProperty("user.name"); + userName = GetPropertyAction.privilegedGetProperty("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 099e8b9e0c8..2aeb2ec9c19 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -1212,7 +1212,7 @@ public final class URL implements java.io.Serializable { private static URLStreamHandler lookupViaProperty(String protocol) { String packagePrefixList = - GetPropertyAction.getProperty(protocolPathProp); + GetPropertyAction.privilegedGetProperty(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 459a820bcde..c707eaeed45 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -1397,7 +1397,7 @@ public abstract class URLConnection { */ private String getContentHandlerPkgPrefixes() { String packagePrefixList = - GetPropertyAction.getProperty(contentPathProp, ""); + GetPropertyAction.privilegedGetProperty(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 2f2c3e6c9c4..91bc9ecf273 100644 --- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java +++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java @@ -133,7 +133,7 @@ public class URLEncoder { dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); - dfltEncName = GetPropertyAction.getProperty("file.encoding"); + dfltEncName = GetPropertyAction.privilegedGetProperty("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 de49a8c6271..81209891bb4 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 = - GetPropertyAction.getProperty("sun.nio.cs.bugLevel", ""); + bugLevel = level = GetPropertyAction + .privilegedGetProperty("sun.nio.cs.bugLevel", ""); } return level.equals(bl); } @@ -609,7 +609,8 @@ public abstract class Charset public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { - String csn = GetPropertyAction.getProperty("file.encoding"); + String csn = GetPropertyAction + .privilegedGetProperty("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 a6af1a15b1f..03d431d80e1 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 @@ -46,7 +46,7 @@ class TempFileHelper { // temporary directory location private static final Path tmpdir = - Paths.get(GetPropertyAction.getProperty("java.io.tmpdir")); + Paths.get(GetPropertyAction.privilegedGetProperty("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 e05904f6f6b..dfe71769d11 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -858,7 +858,7 @@ public final class Locale implements Cloneable, Serializable { private static Locale initDefault() { String language, region, script, country, variant; - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); language = props.getProperty("user.language", "en"); // for compatibility, check for old user.region property region = props.getProperty("user.region"); @@ -883,7 +883,7 @@ public final class Locale implements Cloneable, Serializable { } private static Locale initDefault(Locale.Category category) { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); return getInstance( props.getProperty(category.languageKey, defaultLocale.getLanguage()), 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 9c20a680733..3a481035c92 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -140,9 +140,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 = - GetPropertyAction - .getProperty("java.util.PropertyResourceBundle.encoding", "") + private static final String encoding = GetPropertyAction + .privilegedGetProperty("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 22c382cb0a2..1180d38c491 100644 --- a/jdk/src/java.base/share/classes/java/util/TimeZone.java +++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java @@ -42,6 +42,7 @@ import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import java.time.ZoneId; +import java.util.Properties; import sun.security.action.GetPropertyAction; import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfoFile; @@ -660,12 +661,13 @@ 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 = GetPropertyAction.getProperty("user.timezone"); + Properties props = GetPropertyAction.privilegedGetProperties(); + String zoneID = props.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 = GetPropertyAction.getProperty("java.home"); + String javaHome = props.getProperty("java.home"); try { zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { @@ -693,13 +695,7 @@ public abstract class TimeZone implements Serializable, Cloneable { assert tz != null; final String id = zoneID; - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Void run() { - System.setProperty("user.timezone", id); - return null; - } - }); + props.setProperty("user.timezone", id); defaultTimeZone = tz; return tz; 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 ff26faad4f4..e1516e50c63 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 @@ -155,7 +155,7 @@ class JarFile extends ZipFile { BASE_VERSION = 8; // one less than lowest version for versioned entries int runtimeVersion = jdk.Version.current().major(); String jarVersion = - GetPropertyAction.getProperty("jdk.util.jar.version"); + GetPropertyAction.privilegedGetProperty("jdk.util.jar.version"); if (jarVersion != null) { int jarVer = Integer.parseInt(jarVersion); runtimeVersion = (jarVer > runtimeVersion) @@ -163,7 +163,7 @@ class JarFile extends ZipFile { } RUNTIME_VERSION = runtimeVersion; String enableMultiRelease = GetPropertyAction - .getProperty("jdk.util.jar.enableMultiRelease", "true"); + .privilegedGetProperty("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 ac47ad12032..492571f7ff8 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 @@ -695,7 +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 = GetPropertyAction.getProperty(prop,""); + implName = GetPropertyAction.privilegedGetProperty(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 f7768da27da..adaf261b745 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,7 +94,7 @@ public class PatternSyntaxException } private static final String nl = - GetPropertyAction.getProperty("line.separator"); + GetPropertyAction.privilegedGetProperty("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 ff76017651b..10a0d8a0be0 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 @@ -55,7 +55,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { */ private static final boolean inhibitZip64 = Boolean.parseBoolean( - GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64")); + GetPropertyAction.privilegedGetProperty("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 b436414308f..5f0e2dea0b0 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,7 +51,7 @@ public abstract class SSLSocketFactory extends SocketFactory static final boolean DEBUG; static { - String s = GetPropertyAction.getProperty("javax.net.debug", "") + String s = GetPropertyAction.privilegedGetProperty("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 756af9ec051..8afccfba6a8 100644 --- a/jdk/src/java.base/share/classes/jdk/Version.java +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -273,7 +273,8 @@ public final class Version */ public static Version current() { if (current == null) { - current = parse(GetPropertyAction.getProperty("java.version")); + current = parse( + GetPropertyAction.privilegedGetProperty("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 234a86a9271..d7b60ecff5d 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 @@ -85,7 +85,7 @@ public class URLClassPath { private static final boolean DISABLE_JAR_CHECKING; static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); JAVA_VERSION = props.getProperty("java.version"); DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); 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 58f235d6ccd..1009968046a 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 @@ -81,7 +81,7 @@ public final class LoggerFinderLoader { // Get configuration error policy private static ErrorPolicy configurationErrorPolicy() { String errorPolicy = - GetPropertyAction.getProperty("jdk.logger.finder.error"); + GetPropertyAction.privilegedGetProperty("jdk.logger.finder.error"); if (errorPolicy == null || errorPolicy.isEmpty()) { return ErrorPolicy.WARNING; } @@ -96,7 +96,7 @@ public final class LoggerFinderLoader { // This is further submitted to the configuration error policy. private static boolean ensureSingletonProvider() { return Boolean.parseBoolean( - GetPropertyAction.getProperty("jdk.logger.finder.singleton")); + GetPropertyAction.privilegedGetProperty("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 c90a7b24e38..fb0ffe64426 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 @@ -56,7 +56,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration static Level getDefaultLevel() { String levelName = GetPropertyAction - .getProperty("jdk.system.logger.level", "INFO"); + .privilegedGetProperty("jdk.system.logger.level", "INFO"); try { return Level.valueOf(levelName); } catch (IllegalArgumentException iae) { @@ -426,7 +426,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration static private final String[] skips; static { String additionalPkgs = - GetPropertyAction.getProperty("jdk.logger.packages"); + GetPropertyAction.privilegedGetProperty("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 = GetPropertyAction.getProperty(key); + String format = GetPropertyAction.privilegedGetProperty(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 636b0940345..63c688ca171 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 @@ -343,8 +343,8 @@ public class Reflection { private static void printStackTraceIfNeeded(Throwable e) { if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) { - String s = GetPropertyAction - .getProperty("sun.reflect.debugModuleAccessChecks"); + String s = GetPropertyAction.privilegedGetProperty( + "sun.reflect.debugModuleAccessChecks"); printStackWhenAccessFails = (s != null && !s.equalsIgnoreCase("false")); printStackWhenAccessFailsSet = true; 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 b40c584efcd..a18437d0ed1 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 @@ -398,7 +398,7 @@ public class ReflectionFactory { return; } - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String val = props.getProperty("sun.reflect.noInflation"); if (val != null && val.equals("true")) { noInflation = true; 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 9c68d7c6bed..fb19671578b 100644 --- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java +++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java @@ -53,8 +53,8 @@ public class ResourceManager { private static final AtomicInteger numSockets; static { - String prop = - GetPropertyAction.getProperty("sun.net.maxDatagramSockets"); + String prop = GetPropertyAction + .privilegedGetProperty("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 797bc7fed50..d5bdc6e4b93 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 @@ -40,7 +40,7 @@ import sun.security.action.GetPropertyAction; */ public final class SdpSupport { - private static final String os = GetPropertyAction.getProperty("os.name"); + private static final String os = GetPropertyAction.privilegedGetProperty("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 ac3f7b8a43f..93451253f0a 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 @@ -157,7 +157,7 @@ public class SmtpClient extends TransferProtocolClient { } try { String s; - mailhost = GetPropertyAction.getProperty("mail.host"); + mailhost = GetPropertyAction.privilegedGetProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; @@ -183,7 +183,7 @@ public class SmtpClient extends TransferProtocolClient { setConnectTimeout(to); try { String s; - mailhost = GetPropertyAction.getProperty("mail.host"); + mailhost = GetPropertyAction.privilegedGetProperty("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 ba26f96e52e..a2cfefab33c 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 @@ -183,7 +183,7 @@ class MimeLauncher extends Thread { } String execPathList; - execPathList = GetPropertyAction.getProperty("exec.path"); + execPathList = GetPropertyAction.privilegedGetProperty("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 392d9ea52dc..580842b2faf 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 @@ -145,7 +145,7 @@ public class HttpClient extends NetworkClient { } static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String keepAlive = props.getProperty("http.keepAlive"); String retryPost = props.getProperty("sun.net.http.retryPost"); 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 b397ba1243f..6abb4de2778 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 @@ -278,7 +278,7 @@ public class FtpURLConnection extends URLConnection { if (user == null) { user = "anonymous"; - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String vers = props.getProperty("java.version"); password = props.getProperty("ftp.protocol.user", "Java" + vers + "@"); 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 b6168d0c2c5..6bcd152fdd1 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 @@ -94,7 +94,7 @@ public class AuthenticationHeader { } static { - authPref = GetPropertyAction.getProperty("http.auth.preference"); + authPref = GetPropertyAction.privilegedGetProperty("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 ebabc26182e..923fbe4d66c 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 @@ -207,9 +207,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }; static { - Properties props = GetPropertyAction.getProperties(); - maxRedirects = GetIntegerAction.getProperty("http.maxRedirects", - defaultmaxRedirects); + Properties props = GetPropertyAction.privilegedGetProperties(); + maxRedirects = GetIntegerAction.privilegedGetProperty( + "http.maxRedirects", defaultmaxRedirects); version = props.getProperty("java.version"); String agent = props.getProperty("http.agent"); if (agent == null) { @@ -225,14 +225,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { enableESBuffer = Boolean.parseBoolean( props.getProperty("sun.net.http.errorstream.enableBuffering")); - timeout4ESBuffer = GetIntegerAction - .getProperty("sun.net.http.errorstream.timeout", 300); + timeout4ESBuffer = GetIntegerAction.privilegedGetProperty( + "sun.net.http.errorstream.timeout", 300); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } - bufSize4ES = GetIntegerAction - .getProperty("sun.net.http.errorstream.bufferSize", 4096); + bufSize4ES = GetIntegerAction.privilegedGetProperty( + "sun.net.http.errorstream.bufferSize", 4096); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default } 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 437c3969148..eadd290e215 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 @@ -139,7 +139,7 @@ final class HttpsClient extends HttpClient // String ciphers []; String cipherString = - GetPropertyAction.getProperty("https.cipherSuites"); + GetPropertyAction.privilegedGetProperty("https.cipherSuites"); if (cipherString == null || "".equals(cipherString)) { ciphers = null; @@ -163,7 +163,7 @@ final class HttpsClient extends HttpClient // String protocols []; String protocolString = - GetPropertyAction.getProperty("https.protocols"); + GetPropertyAction.privilegedGetProperty("https.protocols"); if (protocolString == null || "".equals(protocolString)) { protocols = null; @@ -183,7 +183,8 @@ final class HttpsClient extends HttpClient } private String getUserAgent() { - String userAgent = GetPropertyAction.getProperty("https.agent"); + String userAgent = + GetPropertyAction.privilegedGetProperty("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 f58ce457f7a..88e6f5b7caa 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 @@ -161,7 +161,7 @@ public class JavaRuntimeURLConnection extends URLConnection { public Permission getPermission() throws IOException { Permission p = permission; if (p == null) { - String home = GetPropertyAction.getProperty("java.home"); + String home = GetPropertyAction.privilegedGetProperty("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 81139707655..5e441e8550b 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 @@ -56,9 +56,9 @@ public class Handler extends URLStreamHandler { URL ru; boolean localonly = Boolean.parseBoolean( - GetPropertyAction.getProperty("newdoc.localonly")); + GetPropertyAction.privilegedGetProperty("newdoc.localonly")); - String docurl = GetPropertyAction.getProperty("doc.url"); + String docurl = GetPropertyAction.privilegedGetProperty("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 8a287bc2839..deefc8529f9 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,7 +1019,7 @@ public class FileChannelImpl if (!propertyChecked) { synchronized (FileChannelImpl.class) { if (!propertyChecked) { - String value = GetPropertyAction.getProperty( + String value = GetPropertyAction.privilegedGetProperty( "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 59d3167745b..f222dbc8ae3 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 @@ -374,8 +374,8 @@ public class Net { } public static boolean isFastTcpLoopbackRequested() { - String loopbackProp = - GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback"); + String loopbackProp = GetPropertyAction + .privilegedGetProperty("jdk.net.useFastTcpLoopback"); boolean enable; if ("".equals(loopbackProp)) { enable = true; @@ -633,8 +633,8 @@ public class Net { static { int availLevel = isExclusiveBindAvailable(); if (availLevel >= 0) { - String exclBindProp = - GetPropertyAction.getProperty("sun.net.useExclusiveBind"); + String exclBindProp = GetPropertyAction + .privilegedGetProperty("sun.net.useExclusiveBind"); if (exclBindProp != null) { exclusiveBind = exclBindProp.isEmpty() ? true : Boolean.parseBoolean(exclBindProp); 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 e71e628ede1..5a5e51d71ef 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,7 +64,8 @@ public class Util { * for potential future-proofing. */ private static long getMaxCachedBufferSize() { - String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize"); + String s = GetPropertyAction + .privilegedGetProperty("jdk.nio.maxCachedBufferSize"); if (s != null) { try { long m = Long.parseLong(s); @@ -465,7 +466,8 @@ public class Util { if (bugLevel == null) { if (!jdk.internal.misc.VM.isBooted()) return false; - String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel"); + String value = GetPropertyAction + .privilegedGetProperty("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 2ad055e50ec..ac8bc19e892 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 @@ -164,7 +164,7 @@ public class StandardCharsets extends CharsetProvider { return; initialized = true; - String map = getProperty("sun.nio.cs.map"); + String map = GetPropertyAction.privilegedGetProperty("sun.nio.cs.map"); if (map != null) { String[] maps = map.split(","); for (int i = 0; i < maps.length; i++) { @@ -199,9 +199,4 @@ public class StandardCharsets extends CharsetProvider { } } - private static String getProperty(String 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 45d90b99222..94a5def1e85 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 @@ -38,7 +38,7 @@ class Util { private Util() { } private static final Charset jnuEncoding = Charset.forName( - GetPropertyAction.getProperty("sun.jnu.encoding")); + GetPropertyAction.privilegedGetProperty("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 c454b431861..0c8f9413820 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 @@ -118,9 +118,14 @@ public class GetIntegerAction * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. */ - public static Integer getProperty(String theProp) { + public static Integer privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return Integer.getInteger(theProp); } else { @@ -134,10 +139,16 @@ public class GetIntegerAction * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. * @param defaultVal the default value. */ - public static Integer getProperty(String theProp, int defaultVal) { + public static Integer privilegedGetProperty(String theProp, + int defaultVal) { Integer value; if (System.getSecurityManager() == null) { value = Integer.getInteger(theProp); 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 bba172b06bc..44ec16f89dc 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 @@ -93,9 +93,14 @@ public class GetPropertyAction implements PrivilegedAction { * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. */ - public static String getProperty(String theProp) { + public static String privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return System.getProperty(theProp); } else { @@ -109,10 +114,16 @@ public class GetPropertyAction implements PrivilegedAction { * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. * @param defaultVal the default value. */ - public static String getProperty(String theProp, String defaultVal) { + public static String privilegedGetProperty(String theProp, + String defaultVal) { if (System.getSecurityManager() == null) { return System.getProperty(theProp, defaultVal); } else { @@ -126,8 +137,13 @@ public class GetPropertyAction implements PrivilegedAction { * 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. + * + * Note that this method performs a privileged action, and callers of + * this method should take care to ensure that the returned properties + * are not made accessible to untrusted code since it may contain + * sensitive information. */ - public static Properties getProperties() { + public static Properties privilegedGetProperties() { if (System.getSecurityManager() == null) { return System.getProperties(); } else { 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 731f6b13e45..0dc0a614d51 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,7 +70,7 @@ public class DSAKeyFactory extends KeyFactorySpi { * By default this is false. * This incompatibility was introduced by 4532506. */ - String prop = GetPropertyAction.getProperty(SERIAL_PROP); + String prop = GetPropertyAction.privilegedGetProperty(SERIAL_PROP); SERIAL_INTEROP = "true".equalsIgnoreCase(prop); } diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java index 3955dc6566d..002a6c37776 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/RevocationChecker.java @@ -43,7 +43,6 @@ import javax.security.auth.x500.X500Principal; import static sun.security.provider.certpath.OCSP.*; import static sun.security.provider.certpath.PKIX.*; -import sun.security.action.GetPropertyAction; import sun.security.x509.*; import static sun.security.x509.PKIXExtensions.*; import sun.security.util.Debug; 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 d3497aea557..067187f0573 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,7 +84,7 @@ public final class RSAKeyFactory extends KeyFactorySpi { public static final int MAX_RESTRICTED_EXPLEN = 64; private static final boolean restrictExpLen = - "true".equalsIgnoreCase(GetPropertyAction.getProperty( + "true".equalsIgnoreCase(GetPropertyAction.privilegedGetProperty( "sun.security.rsa.restrictRSAExponent", "true")); // instance used for static translateKey(); 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 8f849f8d54f..266ceab62ad 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,7 +50,7 @@ public interface ClientKeyExchangeService { providers = new HashMap<>(); static { - String path = GetPropertyAction.getProperty("java.home"); + String path = GetPropertyAction.privilegedGetProperty("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 c05505edf4a..4748330e4d6 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 @@ -45,7 +45,7 @@ public class Debug { private static String args; static { - args = GetPropertyAction.getProperty("javax.net.debug", ""); + args = GetPropertyAction.privilegedGetProperty("javax.net.debug", ""); args = args.toLowerCase(Locale.ENGLISH); if (args.equals("help")) { Help(); @@ -178,11 +178,11 @@ public class Debug { /** * Return the value of the boolean System property propName. * - * Note use of doPrivileged(). Do make accessible to applications. + * Note use of privileged action. Do NOT make accessible to applications. */ static boolean getBooleanProperty(String propName, boolean defaultValue) { // if set, require value of either true or false - String b = GetPropertyAction.getProperty(propName); + String b = GetPropertyAction.privilegedGetProperty(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 f3384c5b746..3eb4ae86d4c 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,7 +656,8 @@ public abstract class SSLContextImpl extends SSLContextSpi { // the provider service. Instead, please handle the initialization // exception in the caller's constructor. static { - String property = GetPropertyAction.getProperty(PROPERTY_NAME); + String property = GetPropertyAction + .privilegedGetProperty(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 5ce147a3af3..8a036d6db66 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 = - GetPropertyAction.getProperty("jdk.tls.ephemeralDHKeySize"); + String property = GetPropertyAction + .privilegedGetProperty("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 3e21616e48e..0cc7cec686e 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 = - GetPropertyAction.getProperty("jdk.tls.stapling.responderURI"); + String uriStr = GetPropertyAction + .privilegedGetProperty("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 514608dc73c..4596b853a01 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 @@ -43,10 +43,10 @@ public class Debug { private static String args; static { - args = GetPropertyAction.getProperty("java.security.debug"); + args = GetPropertyAction.privilegedGetProperty("java.security.debug"); - String args2 = - GetPropertyAction.getProperty("java.security.auth.debug"); + String args2 = GetPropertyAction + .privilegedGetProperty("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 90389c73252..6830000d22f 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 @@ -144,7 +144,7 @@ public class LocalGregorianCalendar extends BaseCalendar { // Append an era to the predefined eras if it's given by the property. String prop = GetPropertyAction - .getProperty("jdk.calendar.japanese.supplemental.era"); + .privilegedGetProperty("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 58c0c5bbe01..659567caf63 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 @@ -246,7 +246,7 @@ public final class ZoneInfoFile { static { String oldmapping = GetPropertyAction - .getProperty("sun.timezone.ids.oldmapping", "false") + .privilegedGetProperty("sun.timezone.ids.oldmapping", "false") .toLowerCase(Locale.ROOT); USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true")); AccessController.doPrivileged(new PrivilegedAction() { 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 75f235c73e7..9a592fa42c9 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 @@ -116,7 +116,7 @@ public abstract class LocaleProviderAdapter { adapterCache = new ConcurrentHashMap<>(); static { - String order = GetPropertyAction.getProperty("java.locale.providers"); + String order = GetPropertyAction.privilegedGetProperty("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 140473283c8..5d58058398d 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 @@ -42,7 +42,7 @@ class SolarisFileSystem extends UnixFileSystem { super(provider, dir); // check os.version - String osversion = GetPropertyAction.getProperty("os.version"); + String osversion = GetPropertyAction.privilegedGetProperty("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 affdfb96c7f..c50b4a8b7f0 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 @@ -85,7 +85,7 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { Path userMimeTypes = Paths.get( - GetPropertyAction.getProperty("user.home"), ".mime.types"); + GetPropertyAction.privilegedGetProperty("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 c829994cc85..20370e13d4b 100644 --- a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java +++ b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java @@ -36,7 +36,7 @@ class UnixFileSystem extends FileSystem { private final String javaHome; public UnixFileSystem() { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); 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 8a1b8ca085e..cdf144411d5 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -125,7 +125,7 @@ final class ProcessImpl extends Process { } String helperPath() { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); return helperPath(props.getProperty("java.home"), props.getProperty("os.arch")); } @@ -159,7 +159,7 @@ final class ProcessImpl extends Process { } static Platform get() { - String osName = GetPropertyAction.getProperty("os.name"); + String osName = GetPropertyAction.privilegedGetProperty("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 dd1a6548d6a..a30232f16f5 100644 --- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -40,7 +40,7 @@ class DefaultDatagramSocketImplFactory { static { String prefix = null; try { - prefix = GetPropertyAction.getProperty("impl.prefix", null); + prefix = GetPropertyAction.privilegedGetProperty("impl.prefix"); if (prefix != null) prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); } catch (Exception e) { diff --git a/jdk/src/java.base/unix/classes/sun/net/NetHooks.java b/jdk/src/java.base/unix/classes/sun/net/NetHooks.java index 92cb4eaf4d1..b64e638f46a 100644 --- a/jdk/src/java.base/unix/classes/sun/net/NetHooks.java +++ b/jdk/src/java.base/unix/classes/sun/net/NetHooks.java @@ -28,9 +28,6 @@ package sun.net; import java.net.InetAddress; import java.io.FileDescriptor; import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetPropertyAction; /** * Defines static methods to be invoked prior to binding or connecting TCP sockets. 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 a9f15a617f0..6cc4b0094b9 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 @@ -55,8 +55,9 @@ public class SdpProvider extends NetHooks.Provider { private PrintStream log; public SdpProvider() { + Properties props = GetPropertyAction.privilegedGetProperties(); // if this property is not defined then there is nothing to do. - String file = GetPropertyAction.getProperty("com.sun.sdp.conf"); + String file = props.getProperty("com.sun.sdp.conf"); if (file == null) { this.enabled = false; this.rules = null; @@ -65,17 +66,15 @@ public class SdpProvider extends NetHooks.Provider { // load configuration file List list = null; - if (file != null) { - try { - list = loadRulesFromFile(file); - } catch (IOException e) { - fail("Error reading %s: %s", file, e.getMessage()); - } + try { + list = loadRulesFromFile(file); + } catch (IOException e) { + fail("Error reading %s: %s", file, e.getMessage()); } // check if debugging is enabled PrintStream out = null; - String logfile = GetPropertyAction.getProperty("com.sun.sdp.debug"); + String logfile = props.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 f205eaf7545..85bbd53ad43 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 @@ -76,7 +76,7 @@ public class NTLMAuthentication extends AuthenticationInfo { private String hostname; /* Domain to use if not specified by user */ private static String defaultDomain = - GetPropertyAction.getProperty("http.auth.ntlm.domain", ""); + GetPropertyAction.privilegedGetProperty("http.auth.ntlm.domain", ""); public static boolean supportsTransparentAuth () { return false; @@ -141,7 +141,7 @@ public class NTLMAuthentication extends AuthenticationInfo { password = pw.getPassword(); init0(); try { - String version = GetPropertyAction.getProperty("ntlm.version"); + String version = GetPropertyAction.privilegedGetProperty("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 9018f0fe6a0..afaff78f7eb 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 @@ -59,7 +59,7 @@ public class DefaultAsynchronousChannelProvider { * Returns the default AsynchronousChannelProvider. */ public static AsynchronousChannelProvider create() { - String osname = GetPropertyAction.getProperty("os.name"); + String osname = GetPropertyAction.privilegedGetProperty("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 f8c31b5ac94..558a58a2513 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 @@ -46,8 +46,8 @@ class UnixAsynchronousSocketChannelImpl private static final boolean disableSynchronousRead; static { - String propValue = GetPropertyAction - .getProperty("sun.nio.ch.disableSynchronousRead", "false"); + String propValue = GetPropertyAction.privilegedGetProperty( + "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 62f6d5ce145..c4cd69726da 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 @@ -54,7 +54,7 @@ public class DefaultFileSystemProvider { * Returns the default FileSystemProvider. */ public static FileSystemProvider create() { - String osname = GetPropertyAction.getProperty("os.name"); + String osname = GetPropertyAction.privilegedGetProperty("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 7cf295b0d6d..96225f08d6f 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 @@ -57,7 +57,7 @@ abstract class UnixFileSystem // process working directory then paths must be resolved against the // default directory. String propValue = GetPropertyAction - .getProperty("sun.nio.fs.chdirAllowed", "false"); + .privilegedGetProperty("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 50ccacc3d1e..edd756bf3bf 100644 --- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java +++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java @@ -42,7 +42,7 @@ class WinNTFileSystem extends FileSystem { private final char semicolon; public WinNTFileSystem() { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); 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 c12378da67d..1691e15abf8 100644 --- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -56,7 +56,7 @@ class DefaultDatagramSocketImplFactory static { Class prefixImplClassLocal = null; - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); preferIPv4Stack = Boolean.parseBoolean( props.getProperty("java.net.preferIPv4Stack")); 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 5583842d0cb..50e056862c9 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 @@ -53,8 +53,8 @@ public class NTLMAuthentication extends AuthenticationInfo { private static String defaultDomain; /* Domain to use if not specified by user */ static { - defaultDomain = GetPropertyAction.getProperty("http.auth.ntlm.domain", - "domain"); + defaultDomain = GetPropertyAction + .privilegedGetProperty("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 5390b55a3ab..42bc1327c88 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 @@ -120,7 +120,7 @@ class FileDispatcherImpl extends FileDispatcher { static boolean isFastFileTransferRequested() { String fileTransferProp = GetPropertyAction - .getProperty("jdk.nio.enableFastFileTransfer"); + .privilegedGetProperty("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 4d2d3e97c4c..bba794e21a7 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 @@ -114,8 +114,8 @@ class WindowsFileAttributes // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; static { - String propValue = GetPropertyAction - .getProperty("sun.nio.fs.ensureAccurateMetadata", "false"); + String propValue = GetPropertyAction.privilegedGetProperty( + "sun.nio.fs.ensureAccurateMetadata", "false"); ensureAccurateMetadata = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); } From 01ee88c8ae3b3215858d70207913db7f96de6e73 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 3 May 2016 10:40:54 -0700 Subject: [PATCH 212/225] 6850612: Deprecate Class.newInstance since it violates the checked exception language contract Reviewed-by: lancea, mullan, dfuchs --- .../share/classes/java/lang/Class.java | 3 +- .../share/classes/java/net/InetAddress.java | 8 +++- .../share/classes/java/net/ProxySelector.java | 4 +- .../java.base/share/classes/java/net/URL.java | 9 +++-- .../share/classes/java/net/URLConnection.java | 4 +- .../spi/AsynchronousChannelProvider.java | 7 ++-- .../nio/channels/spi/SelectorProvider.java | 7 ++-- .../share/classes/java/security/Policy.java | 5 ++- .../java/time/zone/ZoneRulesProvider.java | 1 + .../classes/java/util/ServiceLoader.java | 4 +- .../java/util/concurrent/ForkJoinPool.java | 1 + .../share/classes/java/util/jar/Pack200.java | 4 +- .../javax/net/ssl/SSLServerSocketFactory.java | 1 + .../javax/net/ssl/SSLSocketFactory.java | 1 + .../security/auth/login/Configuration.java | 4 +- .../security/auth/login/LoginContext.java | 9 +++-- .../internal/jrtfs/JrtFileSystemProvider.java | 4 +- .../reflect/MethodAccessorGenerator.java | 1 + .../sun/net/ftp/FtpClientProvider.java | 5 ++- .../share/classes/sun/nio/ch/ThreadPool.java | 13 +++---- .../sun/nio/cs/FastCharsetProvider.java | 7 ++-- .../sun/nio/cs/StandardCharsets.java.template | 9 +++-- .../sun/security/jca/ProviderConfig.java | 5 ++- .../classes/sun/security/pkcs/PKCS8Key.java | 5 +-- .../sun/security/tools/keytool/Main.java | 1 + .../sun/security/util/KeyStoreDelegator.java | 17 ++++++--- .../classes/sun/security/x509/X509Key.java | 5 +-- .../sun/util/calendar/CalendarSystem.java | 5 ++- .../provider/LocaleProviderAdapter.java | 5 ++- .../provider/SPILocaleProviderAdapter.java | 2 +- .../net/DefaultDatagramSocketImplFactory.java | 4 +- .../DefaultAsynchronousChannelProvider.java | 4 +- .../sun/nio/fs/DefaultFileSystemProvider.java | 4 +- .../classes/java/net/http/FilterFactory.java | 4 +- .../classes/java/util/logging/LogManager.java | 38 +++++++++++-------- .../java/util/logging/MemoryHandler.java | 4 +- .../DefaultMXBeanMappingFactory.java | 8 +++- .../javax/management/MBeanServerFactory.java | 1 + .../remote/JMXConnectorFactory.java | 4 +- .../naming/internal/FactoryEnumeration.java | 4 +- .../sun/naming/internal/ResourceManager.java | 4 +- .../javax/naming/ldap/StartTlsRequest.java | 16 +++----- .../javax/naming/spi/NamingManager.java | 9 +++-- .../classes/java/util/prefs/Preferences.java | 23 ++++++----- .../java/rmi/activation/ActivationID.java | 1 + .../java/rmi/server/RMIClassLoader.java | 4 +- .../classes/java/rmi/server/RemoteObject.java | 10 ++--- .../classes/sun/rmi/server/Activation.java | 4 +- .../javax/smartcardio/TerminalFactory.java | 5 ++- .../com/sun/rowset/CachedRowSetImpl.java | 8 +++- .../rowset/internal/CachedRowSetWriter.java | 4 +- .../javax/sql/rowset/RowSetProvider.java | 6 ++- .../javax/sql/rowset/serial/SQLInputImpl.java | 4 +- .../javax/sql/rowset/spi/SyncFactory.java | 10 ++--- .../algorithms/SignatureAlgorithm.java | 4 +- .../internal/security/c14n/Canonicalizer.java | 4 +- .../keys/keyresolver/KeyResolver.java | 6 ++- .../keys/keyresolver/KeyResolverSpi.java | 4 +- .../security/transforms/Transform.java | 8 +++- .../utils/resolver/ResourceResolver.java | 7 +++- .../java/accessibility/util/Translator.java | 1 + .../nio/cs/ext/AbstractCharsetProvider.java | 1 + .../classes/sun/security/pkcs11/P11Util.java | 5 ++- .../sun/security/pkcs11/SunPKCS11.java | 4 +- .../httpserver/spi/HttpServerProvider.java | 7 ++-- .../jdk/internal/jline/TerminalFactory.java | 4 +- .../jline/console/internal/ConsoleRunner.java | 1 + .../tools/jdi/ProcessAttachingConnector.java | 4 +- .../sun/tools/jdi/RawCommandLineLauncher.java | 14 ++++--- .../sun/tools/jdi/SunCommandLineLauncher.java | 14 ++++--- .../provider/LocaleDataProvider.java | 2 +- 71 files changed, 272 insertions(+), 157 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 3ea9467a45f..2327b7699d7 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -470,7 +470,7 @@ public final class Class implements java.io.Serializable, * expression with an empty argument list. The class is initialized if it * has not already been initialized. * - *

          Note that this method propagates any exception thrown by the + * @deprecated This method propagates any exception thrown by the * nullary constructor, including a checked exception. Use of * this method effectively bypasses the compile-time exception * checking that would otherwise be performed by the compiler. @@ -500,6 +500,7 @@ public final class Class implements java.io.Serializable, * of this class. */ @CallerSensitive + @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException { 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 e7fbf134353..e45b590200a 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -1645,7 +1645,9 @@ class InetAddress implements java.io.Serializable { */ String prefix = GetPropertyAction.privilegedGetProperty("impl.prefix", ""); try { - impl = Class.forName("java.net." + prefix + implName).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName("java.net." + prefix + implName).newInstance(); + impl = tmp; } catch (ClassNotFoundException e) { System.err.println("Class not found: java.net." + prefix + implName + ":\ncheck impl.prefix property " + @@ -1662,7 +1664,9 @@ class InetAddress implements java.io.Serializable { if (impl == null) { try { - impl = Class.forName(implName).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(implName).newInstance(); + impl = tmp; } catch (Exception e) { throw new Error("System property impl.prefix incorrect"); } diff --git a/jdk/src/java.base/share/classes/java/net/ProxySelector.java b/jdk/src/java.base/share/classes/java/net/ProxySelector.java index 04c675cedc8..9b293379b59 100644 --- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java +++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java @@ -71,7 +71,9 @@ public abstract class ProxySelector { try { Class c = Class.forName("sun.net.spi.DefaultProxySelector"); if (c != null && ProxySelector.class.isAssignableFrom(c)) { - theProxySelector = (ProxySelector) c.newInstance(); + @SuppressWarnings("deprecation") + ProxySelector tmp = (ProxySelector) c.newInstance(); + theProxySelector = tmp; } } catch (Exception e) { theProxySelector = null; 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 2aeb2ec9c19..f071d3ad695 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -1198,8 +1198,9 @@ public final class URL implements java.io.Serializable { public URLStreamHandler createURLStreamHandler(String protocol) { String name = PREFIX + "." + protocol + ".Handler"; try { - Class c = Class.forName(name); - return (URLStreamHandler)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(name).newInstance(); + return (URLStreamHandler)o; } catch (ClassNotFoundException x) { // ignore } catch (Exception e) { @@ -1234,7 +1235,9 @@ public final class URL implements java.io.Serializable { } } if (cls != null) { - handler = (URLStreamHandler)cls.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = cls.newInstance(); + handler = (URLStreamHandler)tmp; } } catch (Exception e) { // any number of exceptions can get thrown here 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 c707eaeed45..4ad051cafe2 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -1323,7 +1323,9 @@ public abstract class URLConnection { } } if (cls != null) { - return (ContentHandler) cls.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = cls.newInstance(); + return (ContentHandler) tmp; } } catch(Exception ignored) { } } diff --git a/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java b/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java index f720261d03b..6a77d3db966 100644 --- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java +++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java @@ -94,9 +94,10 @@ public abstract class AsynchronousChannelProvider { if (cn == null) return null; try { - Class c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); - return (AsynchronousChannelProvider)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()).newInstance(); + return (AsynchronousChannelProvider)tmp; } catch (ClassNotFoundException x) { throw new ServiceConfigurationError(null, x); } catch (IllegalAccessException x) { diff --git a/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java b/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java index cfe444a0041..c162eed8ed6 100644 --- a/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java +++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java @@ -95,9 +95,10 @@ public abstract class SelectorProvider { if (cn == null) return false; try { - Class c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); - provider = (SelectorProvider)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()).newInstance(); + provider = (SelectorProvider)tmp; return true; } catch (ClassNotFoundException x) { throw new ServiceConfigurationError(null, x); diff --git a/jdk/src/java.base/share/classes/java/security/Policy.java b/jdk/src/java.base/share/classes/java/security/Policy.java index 79ecf9c688d..33f766f3082 100644 --- a/jdk/src/java.base/share/classes/java/security/Policy.java +++ b/jdk/src/java.base/share/classes/java/security/Policy.java @@ -222,8 +222,9 @@ public abstract class Policy { public Policy run() { try { ClassLoader scl = ClassLoader.getSystemClassLoader(); - Class c = Class.forName(policyProvider, true, scl); - return (Policy)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(policyProvider, true, scl).newInstance(); + return (Policy)o; } catch (Exception e) { if (debug != null) { debug.println("policy provider " + policyProvider + diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java index 0905d9c3957..8e91eae0bbd 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java @@ -147,6 +147,7 @@ public abstract class ZoneRulesProvider { if (prop != null) { try { Class c = Class.forName(prop, true, ClassLoader.getSystemClassLoader()); + @SuppressWarnings("deprecation") ZoneRulesProvider provider = ZoneRulesProvider.class.cast(c.newInstance()); registerProvider(provider); loaded.add(provider); diff --git a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java index 08deac0ed2f..081b96158ff 100644 --- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java @@ -811,7 +811,9 @@ public final class ServiceLoader } S p = null; try { - p = service.cast(c.newInstance()); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + p = service.cast(tmp); } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated", diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index bcb6d59fcad..6ec5e6cba7e 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -3507,6 +3507,7 @@ public class ForkJoinPool extends AbstractExecutorService { * Creates and returns the common pool, respecting user settings * specified via system properties. */ + @SuppressWarnings("deprecation") // Class.newInstance static ForkJoinPool makeCommonPool() { int parallelism = -1; ForkJoinWorkerThreadFactory factory = null; 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 492571f7ff8..01df2638039 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 @@ -704,7 +704,9 @@ public abstract class Pack200 { impl = com.sun.java.util.jar.pack.UnpackerImpl.class; } // We have a class. Now instantiate it. - return impl.newInstance(); + @SuppressWarnings("deprecation") + Object result = impl.newInstance(); + return result; } catch (ClassNotFoundException e) { throw new Error("Class not found: " + implName + ":\ncheck property " + prop + diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java index a992a07f3d1..fea47ba0cd3 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -97,6 +97,7 @@ public abstract class SSLServerSocketFactory extends ServerSocketFactory } } log("class " + clsName + " is loaded"); + @SuppressWarnings("deprecation") SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance(); log("instantiated an instance of class " + clsName); theFactory = fac; 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 5f0e2dea0b0..6375a52a1b0 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 @@ -106,6 +106,7 @@ public abstract class SSLSocketFactory extends SocketFactory } } log("class " + clsName + " is loaded"); + @SuppressWarnings("deprecation") SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance(); log("instantiated an instance of class " + clsName); theFactory = fac; diff --git a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java index 8db88e0c0d3..c1844d523eb 100644 --- a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java +++ b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java @@ -250,7 +250,9 @@ public abstract class Configuration { finalClass, false, Thread.currentThread().getContextClassLoader() ).asSubclass(Configuration.class); - return implClass.newInstance(); + @SuppressWarnings("deprecation") + Configuration result = implClass.newInstance(); + return result; } }); AccessController.doPrivileged( diff --git a/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java b/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java index e266c4706f0..af46b200701 100644 --- a/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java +++ b/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java @@ -304,7 +304,9 @@ public class LoginContext { Class c = Class.forName( defaultHandler, true, finalLoader).asSubclass(CallbackHandler.class); - return c.newInstance(); + @SuppressWarnings("deprecation") + CallbackHandler result = c.newInstance(); + return result; } }); } catch (java.security.PrivilegedActionException pae) { @@ -697,8 +699,9 @@ public class LoginContext { if (moduleStack[i].module == null) { try { - moduleStack[i].module = (LoginModule) Class.forName( - name, false, contextClassLoader).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(name, false, contextClassLoader).newInstance(); + moduleStack[i].module = (LoginModule) tmp; if (debug != null) { debug.println(name + " loaded via reflection"); } 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 746d61a273c..512a3462ba7 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 @@ -124,7 +124,9 @@ public final class JrtFileSystemProvider extends FileSystemProvider { ClassLoader cl = newJrtFsLoader(jrtfs); try { Class c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl); - return ((FileSystemProvider)c.newInstance()).newFileSystem(uri, newEnv); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + return ((FileSystemProvider)tmp).newFileSystem(uri, newEnv); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java index 8efa2a9d4e6..c4acdffe4d6 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java @@ -392,6 +392,7 @@ class MethodAccessorGenerator extends AccessorGenerator { // matter. return AccessController.doPrivileged( new PrivilegedAction() { + @SuppressWarnings("deprecation") // Class.newInstance public MagicAccessorImpl run() { try { return (MagicAccessorImpl) diff --git a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java index bbdb1cde5bd..511f9995713 100644 --- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java +++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java @@ -67,8 +67,9 @@ public abstract class FtpClientProvider { return false; } try { - Class c = Class.forName(cm, true, null); - provider = (FtpClientProvider) c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(cm, true, null).newInstance(); + provider = (FtpClientProvider)o; return true; } catch (ClassNotFoundException | IllegalAccessException | diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java b/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java index ac03d386f08..4cdd47864a9 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java @@ -165,14 +165,11 @@ public class ThreadPool { GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); if (propValue != null) { try { - Class c = Class - .forName(propValue, true, ClassLoader.getSystemClassLoader()); - return ((ThreadFactory)c.newInstance()); - } catch (ClassNotFoundException x) { - throw new Error(x); - } catch (InstantiationException x) { - throw new Error(x); - } catch (IllegalAccessException x) { + @SuppressWarnings("deprecation") + Object tmp = Class + .forName(propValue, true, ClassLoader.getSystemClassLoader()).newInstance(); + return (ThreadFactory)tmp; + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException x) { throw new Error(x); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java b/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java index c9fceab6ee4..d0eae762e71 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java @@ -115,10 +115,11 @@ public class FastCharsetProvider // Instantiate the charset and cache it try { - Class c = Class.forName(packagePrefix + "." + cln, + @SuppressWarnings("deprecation") + Object o= Class.forName(packagePrefix + "." + cln, true, - this.getClass().getClassLoader()); - cs = (Charset)c.newInstance(); + this.getClass().getClassLoader()).newInstance(); + cs = (Charset)o; cache.put(csn, cs); return cs; } catch (ClassNotFoundException | 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 ac8bc19e892..f2eeaaafdc3 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 @@ -110,10 +110,11 @@ public class StandardCharsets extends CharsetProvider { // Instantiate the charset and cache it try { - Class c = Class.forName(packagePrefix + "." + cln, - true, - this.getClass().getClassLoader()); - cs = (Charset)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(packagePrefix + "." + cln, + true, + this.getClass().getClassLoader()).newInstance(); + cs = (Charset)o; cache.put(csn, cs); return cs; } catch (ClassNotFoundException | 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 bf65180af6f..c12f7f3bc5f 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 @@ -185,7 +185,9 @@ final class ProviderConfig { try { Class c = Class.forName("apple.security.AppleProvider"); if (Provider.class.isAssignableFrom(c)) { - return (Provider) c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + return (Provider) tmp; } else { return null; } @@ -386,6 +388,7 @@ final class ProviderConfig { Provider p = AccessController.doPrivileged (new PrivilegedExceptionAction() { + @SuppressWarnings("deprecation") // Class.newInstance public Provider run() throws Exception { return (Provider) provClass.newInstance(); } diff --git a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java index 8173bd266ad..7cdc167fd52 100644 --- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java +++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java @@ -218,11 +218,10 @@ public class PKCS8Key implements PrivateKey { } } - Object inst = null; + @SuppressWarnings("deprecation") + Object inst = (keyClass != null) ? keyClass.newInstance() : null; PKCS8Key result; - if (keyClass != null) - inst = keyClass.newInstance(); if (inst instanceof PKCS8Key) { result = (PKCS8Key) inst; result.algid = algid; diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 15cc364b540..94969b84196 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -728,6 +728,7 @@ public final class Main { provClass = Class.forName(provName); } + @SuppressWarnings("deprecation") Object obj = provClass.newInstance(); if (!(obj instanceof Provider)) { MessageFormat form = new MessageFormat diff --git a/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java b/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java index b43aa234833..c8c08c5eff8 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java +++ b/jdk/src/java.base/share/classes/sun/security/util/KeyStoreDelegator.java @@ -196,8 +196,9 @@ public class KeyStoreDelegator extends KeyStoreSpi { // A new keystore is always created in the primary keystore format if (stream == null) { try { - keystore = primaryKeyStore.newInstance(); - + @SuppressWarnings("deprecation") + KeyStoreSpi tmp = primaryKeyStore.newInstance(); + keystore = tmp; } catch (InstantiationException | IllegalAccessException e) { // can safely ignore } @@ -214,7 +215,9 @@ public class KeyStoreDelegator extends KeyStoreSpi { bufferedStream.mark(Integer.MAX_VALUE); try { - keystore = primaryKeyStore.newInstance(); + @SuppressWarnings("deprecation") + KeyStoreSpi tmp = primaryKeyStore.newInstance(); + keystore = tmp; type = primaryType; keystore.engineLoad(bufferedStream, password); @@ -232,7 +235,9 @@ public class KeyStoreDelegator extends KeyStoreSpi { throw e; } - keystore = secondaryKeyStore.newInstance(); + @SuppressWarnings("deprecation") + KeyStoreSpi tmp= secondaryKeyStore.newInstance(); + keystore = tmp; type = secondaryType; bufferedStream.reset(); keystore.engineLoad(bufferedStream, password); @@ -284,7 +289,9 @@ public class KeyStoreDelegator extends KeyStoreSpi { boolean result = false; try { - keystore = primaryKeyStore.newInstance(); + @SuppressWarnings("deprecation") + KeyStoreSpi tmp = primaryKeyStore.newInstance(); + keystore = tmp; type = primaryType; result = keystore.engineProbe(stream); diff --git a/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java b/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java index 5384ac785ae..a11fa27dff8 100644 --- a/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java +++ b/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java @@ -255,11 +255,10 @@ public class X509Key implements PublicKey { } } - Object inst = null; + @SuppressWarnings("deprecation") + Object inst = (keyClass != null) ? keyClass.newInstance() : null; X509Key result; - if (keyClass != null) - inst = keyClass.newInstance(); if (inst instanceof X509Key) { result = (X509Key) inst; result.algid = algid; diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java index 59fae3b7c0e..71c7212c644 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java @@ -157,8 +157,9 @@ public abstract class CalendarSystem { cal = LocalGregorianCalendar.getLocalGregorianCalendar(calendarName); } else { try { - Class cl = Class.forName(className); - cal = (CalendarSystem) cl.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(className).newInstance(); + cal = (CalendarSystem) tmp; } catch (Exception e) { throw new InternalError(e); } 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 9a592fa42c9..a5ab411adb4 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 @@ -171,8 +171,9 @@ public abstract class LocaleProviderAdapter { if (cached == null) { try { // lazily load adapters here - adapter = (LocaleProviderAdapter)Class.forName(type.getAdapterClassName()) - .newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(type.getAdapterClassName()).newInstance(); + adapter = (LocaleProviderAdapter)tmp; cached = adapterInstances.putIfAbsent(type, adapter); if (cached != null) { adapter = cached; diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java index 9cd8c0d1a2f..4066fcdabfd 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java @@ -73,7 +73,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { try { return AccessController.doPrivileged(new PrivilegedExceptionAction

          () { @Override - @SuppressWarnings("unchecked") + @SuppressWarnings(value={"unchecked", "deprecation"}) public P run() { P delegate = null; 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 a30232f16f5..706a14eb046 100644 --- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -61,7 +61,9 @@ class DefaultDatagramSocketImplFactory { throws SocketException { if (prefixImplClass != null) { try { - return (DatagramSocketImpl)prefixImplClass.newInstance(); + @SuppressWarnings("deprecation") + DatagramSocketImpl result = (DatagramSocketImpl)prefixImplClass.newInstance(); + return result; } catch (Exception e) { throw new SocketException("can't instantiate DatagramSocketImpl"); } 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 afaff78f7eb..248c6a154d2 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 @@ -48,7 +48,9 @@ public class DefaultAsynchronousChannelProvider { throw new AssertionError(x); } try { - return c.newInstance(); + @SuppressWarnings("deprecation") + AsynchronousChannelProvider result = c.newInstance(); + return result; } catch (IllegalAccessException | InstantiationException x) { throw new AssertionError(x); } 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 c4cd69726da..42064456453 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 @@ -44,7 +44,9 @@ public class DefaultFileSystemProvider { throw new AssertionError(x); } try { - return c.newInstance(); + @SuppressWarnings("deprecation") + FileSystemProvider result = c.newInstance(); + return result; } catch (IllegalAccessException | InstantiationException x) { throw new AssertionError(x); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java index cf67771331a..840eacaa64a 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java @@ -39,7 +39,9 @@ class FilterFactory { List l = new LinkedList<>(); for (Class clazz : filterClasses) { try { - l.add(clazz.newInstance()); + @SuppressWarnings("deprecation") + HeaderFilter headerFilter = clazz.newInstance(); + l.add(headerFilter); } catch (ReflectiveOperationException e) { throw new InternalError(e); } 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 6d0cc8de4d6..bc06286e8da 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 @@ -231,13 +231,15 @@ public class LogManager { cname = System.getProperty("java.util.logging.manager"); if (cname != null) { try { - Class clz = ClassLoader.getSystemClassLoader() - .loadClass(cname); - mgr = (LogManager) clz.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = ClassLoader.getSystemClassLoader() + .loadClass(cname).newInstance(); + mgr = (LogManager) tmp; } catch (ClassNotFoundException ex) { - Class clz = Thread.currentThread() - .getContextClassLoader().loadClass(cname); - mgr = (LogManager) clz.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Thread.currentThread() + .getContextClassLoader().loadClass(cname).newInstance(); + mgr = (LogManager) tmp; } } } catch (Exception ex) { @@ -991,8 +993,9 @@ public class LogManager { List handlers = new ArrayList<>(names.length); for (String type : names) { try { - Class clz = ClassLoader.getSystemClassLoader().loadClass(type); - Handler hdl = (Handler) clz.newInstance(); + @SuppressWarnings("deprecation") + Object o = ClassLoader.getSystemClassLoader().loadClass(type).newInstance(); + Handler hdl = (Handler) o; // Check if there is a property defining the // this handler's level. String levs = getProperty(type + ".level"); @@ -1330,11 +1333,13 @@ public class LogManager { // calling readConfiguration(InputStream) with a suitable stream. try { Class clz = ClassLoader.getSystemClassLoader().loadClass(cname); - clz.newInstance(); + @SuppressWarnings("deprecation") + Object witness = clz.newInstance(); return; } catch (ClassNotFoundException ex) { Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname); - clz.newInstance(); + @SuppressWarnings("deprecation") + Object witness = clz.newInstance(); return; } } catch (Exception ex) { @@ -1561,7 +1566,8 @@ public class LogManager { for (String word : names) { try { Class clz = ClassLoader.getSystemClassLoader().loadClass(word); - clz.newInstance(); + @SuppressWarnings("deprecation") + Object witness = clz.newInstance(); } catch (Exception ex) { System.err.println("Can't load config class \"" + word + "\""); System.err.println("" + ex); @@ -2307,8 +2313,9 @@ public class LogManager { String val = getProperty(name); try { if (val != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(val); - return (Filter) clz.newInstance(); + @SuppressWarnings("deprecation") + Object o = ClassLoader.getSystemClassLoader().loadClass(val).newInstance(); + return (Filter) o; } } catch (Exception ex) { // We got one of a variety of exceptions in creating the @@ -2328,8 +2335,9 @@ public class LogManager { String val = getProperty(name); try { if (val != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(val); - return (Formatter) clz.newInstance(); + @SuppressWarnings("deprecation") + Object o = ClassLoader.getSystemClassLoader().loadClass(val).newInstance(); + return (Formatter) o; } } catch (Exception ex) { // We got one of a variety of exceptions in creating the diff --git a/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java b/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java index 1f9fe727be7..34053937630 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/MemoryHandler.java @@ -117,7 +117,9 @@ public class MemoryHandler extends Handler { Class clz; try { clz = ClassLoader.getSystemClassLoader().loadClass(targetName); - target = (Handler) clz.newInstance(); + @SuppressWarnings("deprecation") + Object o = clz.newInstance(); + target = (Handler) o; } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e); } diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java index c322ed4f028..e2c94815d60 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java @@ -655,7 +655,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { final Object[] openArray = (Object[]) openValue; final Collection valueCollection; try { - valueCollection = cast(collectionClass.newInstance()); + @SuppressWarnings("deprecation") + Collection tmp = collectionClass.newInstance(); + valueCollection = cast(tmp); } catch (Exception e) { throw invalidObjectException("Cannot create collection", e); } @@ -1114,7 +1116,9 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { try { final Class targetClass = getTargetClass(); ReflectUtil.checkPackageAccess(targetClass); - o = targetClass.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = targetClass.newInstance(); + o = tmp; for (int i = 0; i < itemNames.length; i++) { if (cd.containsKey(itemNames[i])) { Object openItem = cd.get(itemNames[i]); diff --git a/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java b/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java index 7eade40ba1d..756811a072f 100644 --- a/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java +++ b/jdk/src/java.management/share/classes/javax/management/MBeanServerFactory.java @@ -458,6 +458,7 @@ public class MBeanServerFactory { **/ private static MBeanServerBuilder newBuilder(Class builderClass) { try { + @SuppressWarnings("deprecation") final Object abuilder = builderClass.newInstance(); return (MBeanServerBuilder)abuilder; } catch (RuntimeException x) { diff --git a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java index 1458aca4c3b..4c6479e12b5 100644 --- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java +++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java @@ -531,7 +531,9 @@ public class JMXConnectorFactory { // We have just proved that this cast is correct Class providerClassT = Util.cast(providerClass); try { - return providerClassT.newInstance(); + @SuppressWarnings("deprecation") + T result = providerClassT.newInstance(); + return result; } catch (Exception e) { final String msg = "Exception when instantiating provider [" + className + diff --git a/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java b/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java index 0fe4864d967..8b0e852bad3 100644 --- a/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java +++ b/jdk/src/java.naming/share/classes/com/sun/naming/internal/FactoryEnumeration.java @@ -86,7 +86,9 @@ public final class FactoryEnumeration { answer = cls; } // Instantiate Class to get factory - answer = ((Class) answer).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = ((Class) answer).newInstance(); + answer = tmp; ref = new NamedWeakReference<>(answer, className); factories.set(posn-1, ref); // replace Class object or null return answer; diff --git a/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java b/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java index 7db51ea5cce..8292846733c 100644 --- a/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java +++ b/jdk/src/java.naming/share/classes/com/sun/naming/internal/ResourceManager.java @@ -399,7 +399,9 @@ public final class ResourceManager { className = parser.nextToken() + classSuffix; try { // System.out.println("loading " + className); - factory = helper.loadClass(className, loader).newInstance(); + @SuppressWarnings("deprecation") // Class.newInstance + Object tmp = helper.loadClass(className, loader).newInstance(); + factory = tmp; } catch (InstantiationException e) { NamingException ne = new NamingException("Cannot instantiate " + className); diff --git a/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java b/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java index 4c81bf6247c..bbe3915dbae 100644 --- a/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java +++ b/jdk/src/java.naming/share/classes/javax/naming/ldap/StartTlsRequest.java @@ -192,18 +192,12 @@ public class StartTlsRequest implements ExtendedRequest { } try { VersionHelper helper = VersionHelper.getVersionHelper(); - Class clas = helper.loadClass( - "com.sun.jndi.ldap.ext.StartTlsResponseImpl"); + @SuppressWarnings("deprecation") + Object o = helper.loadClass( + "com.sun.jndi.ldap.ext.StartTlsResponseImpl").newInstance(); + resp = (StartTlsResponse) o; - resp = (StartTlsResponse) clas.newInstance(); - - } catch (IllegalAccessException e) { - throw wrapException(e); - - } catch (InstantiationException e) { - throw wrapException(e); - - } catch (ClassNotFoundException e) { + } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) { throw wrapException(e); } diff --git a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java index 6a13625cabc..6e60b6bffa9 100644 --- a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java +++ b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java @@ -159,7 +159,9 @@ public class NamingManager { } } - return (clas != null) ? (ObjectFactory) clas.newInstance() : null; + @SuppressWarnings("deprecation") // Class.newInstance + ObjectFactory result = (clas != null) ? (ObjectFactory) clas.newInstance() : null; + return result; } @@ -710,8 +712,9 @@ public class NamingManager { if (factory == null) { try { - factory = (InitialContextFactory) - helper.loadClass(className).newInstance(); + @SuppressWarnings("deprecation") + Object o = helper.loadClass(className).newInstance(); + factory = (InitialContextFactory) o; } catch (Exception e) { NoInitialContextException ne = new NoInitialContextException( diff --git a/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java b/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java index 67394641c9d..b6e53c4cb8a 100644 --- a/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java +++ b/jdk/src/java.prefs/share/classes/java/util/prefs/Preferences.java @@ -238,10 +238,11 @@ public abstract class Preferences { // dependent on the invoking thread. // Checking AllPermission also seems wrong. try { - return (PreferencesFactory) - Class.forName(factoryName, false, - ClassLoader.getSystemClassLoader()) + @SuppressWarnings("deprecation") + Object result =Class.forName(factoryName, false, + ClassLoader.getSystemClassLoader()) .newInstance(); + return (PreferencesFactory)result; } catch (Exception ex) { try { // workaround for javaws, plugin, @@ -250,11 +251,12 @@ public abstract class Preferences { if (sm != null) { sm.checkPermission(new java.security.AllPermission()); } - return (PreferencesFactory) - Class.forName(factoryName, false, - Thread.currentThread() - .getContextClassLoader()) + @SuppressWarnings("deprecation") + Object result = Class.forName(factoryName, false, + Thread.currentThread() + .getContextClassLoader()) .newInstance(); + return (PreferencesFactory) result; } catch (Exception e) { throw new InternalError( "Can't instantiate Preferences factory " @@ -299,9 +301,10 @@ public abstract class Preferences { platformFactory = "java.util.prefs.FileSystemPreferencesFactory"; } try { - return (PreferencesFactory) - Class.forName(platformFactory, false, - Preferences.class.getClassLoader()).newInstance(); + @SuppressWarnings("deprecation") + Object result = Class.forName(platformFactory, false, + Preferences.class.getClassLoader()).newInstance(); + return (PreferencesFactory) result; } catch (Exception e) { throw new InternalError( "Can't instantiate platform default Preferences factory " diff --git a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java index 120a15ade34..13b3a0689c8 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationID.java @@ -272,6 +272,7 @@ public class ActivationID implements Serializable { Class refClass = Class.forName(RemoteRef.packagePrefix + "." + in.readUTF()) .asSubclass(RemoteRef.class); + @SuppressWarnings("deprecation") RemoteRef ref = refClass.newInstance(); ref.readExternal(in); activator = (Activator) diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java index 59e29d5f597..a47ff2a706e 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java @@ -681,7 +681,9 @@ public class RMIClassLoader { Class.forName(providerClassName, false, ClassLoader.getSystemClassLoader()) .asSubclass(RMIClassLoaderSpi.class); - return providerClass.newInstance(); + @SuppressWarnings("deprecation") + RMIClassLoaderSpi result = providerClass.newInstance(); + return result; } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); diff --git a/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java b/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java index 86967ebd8da..db358dad895 100644 --- a/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java +++ b/jdk/src/java.rmi/share/classes/java/rmi/server/RemoteObject.java @@ -439,18 +439,16 @@ public abstract class RemoteObject implements Remote, java.io.Serializable { RemoteRef.packagePrefix + "." + refClassName; Class refClass = Class.forName(internalRefClassName); try { - ref = (RemoteRef) refClass.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = refClass.newInstance(); + ref = (RemoteRef) tmp; /* * If this step fails, assume we found an internal * class that is not meant to be a serializable ref * type. */ - } catch (InstantiationException e) { - throw new ClassNotFoundException(internalRefClassName, e); - } catch (IllegalAccessException e) { - throw new ClassNotFoundException(internalRefClassName, e); - } catch (ClassCastException e) { + } catch (InstantiationException | IllegalAccessException | ClassCastException e) { throw new ClassNotFoundException(internalRefClassName, e); } ref.readExternal(in); diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java index 407601f2f98..d1f73305a2d 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java @@ -2066,7 +2066,9 @@ public class Activation implements Serializable { try { Class execPolicyClass = getRMIClass(execPolicyClassName); - execPolicy = execPolicyClass.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = execPolicyClass.newInstance(); + execPolicy = tmp; execPolicyMethod = execPolicyClass.getMethod("checkExecCommand", ActivationGroupDesc.class, diff --git a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java index 8ded0720b46..0e810845f24 100644 --- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java +++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java @@ -111,8 +111,9 @@ public final class TerminalFactory { type = "PC/SC"; Provider sun = Security.getProvider("SunPCSC"); if (sun == null) { - Class clazz = Class.forName("sun.security.smartcardio.SunPCSC"); - sun = (Provider)clazz.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName("sun.security.smartcardio.SunPCSC").newInstance(); + sun = (Provider)o; } factory = TerminalFactory.getInstance(type, null, sun); } catch (Exception e) { 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 55179670edb..0326f57639c 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 @@ -2962,7 +2962,9 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern SQLData obj = null; try { ReflectUtil.checkPackageAccess(c); - obj = (SQLData) c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + obj = (SQLData) tmp; } catch(Exception ex) { throw new SQLException("Unable to Instantiate: ", ex); } @@ -5710,7 +5712,9 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern SQLData obj = null; try { ReflectUtil.checkPackageAccess(c); - obj = (SQLData) c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + obj = (SQLData) tmp; } catch(Exception ex) { throw new SQLException("Unable to Instantiate: ", ex); } diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java index 07865ac0775..60f6ad0ff9d 100644 --- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java @@ -574,7 +574,9 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { SQLData obj = null; try { ReflectUtil.checkPackageAccess(c); - obj = (SQLData)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + obj = (SQLData)tmp; } catch (Exception ex) { throw new SQLException("Unable to Instantiate: ", ex); } diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java index 02863b233a4..8cbccd4782b 100644 --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetProvider.java @@ -136,8 +136,9 @@ public class RowSetProvider { } // getFactoryClass takes care of adding the read edge if // necessary - Class c = getFactoryClass(factoryClassName, null, false); - factory = (RowSetFactory) c.newInstance(); + @SuppressWarnings("deprecation") + Object o = getFactoryClass(factoryClassName, null, false).newInstance(); + factory = (RowSetFactory) o; } } catch (Exception e) { throw new SQLException( "RowSetFactory: " + factoryClassName + @@ -202,6 +203,7 @@ public class RowSetProvider { // getFactoryClass takes care of adding the read edge if // necessary Class providerClass = getFactoryClass(factoryClassName, cl, false); + @SuppressWarnings("deprecation") RowSetFactory instance = (RowSetFactory) providerClass.newInstance(); if (debug) { trace("Created new instance of " + providerClass + diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java index 41332f59189..421d4943763 100644 --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java @@ -478,7 +478,9 @@ public class SQLInputImpl implements SQLInput { SQLData obj = null; try { ReflectUtil.checkPackageAccess(c); - obj = (SQLData)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + obj = (SQLData)tmp; } catch (Exception ex) { throw new SQLException("Unable to Instantiate: ", ex); } diff --git a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java index 8aeccdfe7e3..a38cd2b41c6 100644 --- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java +++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java @@ -582,14 +582,12 @@ public class SyncFactory { * there. **/ c = Class.forName(providerID, true, cl); - return (SyncProvider) c.newInstance(); + @SuppressWarnings("deprecation") + Object result = c.newInstance(); + return (SyncProvider)result; - } catch (IllegalAccessException e) { + } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) { throw new SyncFactoryException("IllegalAccessException: " + e.getMessage()); - } catch (InstantiationException e) { - throw new SyncFactoryException("InstantiationException: " + e.getMessage()); - } catch (ClassNotFoundException e) { - throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage()); } } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java index 253e35ca864..e597f724793 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java @@ -152,7 +152,9 @@ public class SignatureAlgorithm extends Algorithm { log.log(java.util.logging.Level.FINE, "Create URI \"" + algorithmURI + "\" class \"" + implementingClass + "\""); } - return implementingClass.newInstance(); + @SuppressWarnings("deprecation") + SignatureAlgorithmSpi result = implementingClass.newInstance(); + return result; } catch (IllegalAccessException ex) { Object exArgs[] = { algorithmURI, ex.getMessage() }; throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs, ex); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java index ae33b72c91d..7c04f870c42 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java @@ -115,7 +115,9 @@ public class Canonicalizer { Class implementingClass = canonicalizerHash.get(algorithmURI); - canonicalizerSpi = implementingClass.newInstance(); + @SuppressWarnings("deprecation") + CanonicalizerSpi tmp = implementingClass.newInstance(); + canonicalizerSpi = tmp; canonicalizerSpi.reset = true; } catch (Exception e) { Object exArgs[] = { algorithmURI }; diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index e8622d938b6..2263e352944 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -182,6 +182,7 @@ public class KeyResolver { public static void register(String className, boolean globalResolver) throws ClassNotFoundException, IllegalAccessException, InstantiationException { JavaUtils.checkRegisterPermission(); + @SuppressWarnings("deprecation") KeyResolverSpi keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); keyResolverSpi.setGlobalResolver(globalResolver); @@ -207,7 +208,9 @@ public class KeyResolver { KeyResolverSpi keyResolverSpi = null; Exception ex = null; try { - keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(className).newInstance(); + keyResolverSpi = (KeyResolverSpi) tmp; } catch (ClassNotFoundException e) { ex = e; } catch (IllegalAccessException e) { @@ -272,6 +275,7 @@ public class KeyResolver { JavaUtils.checkRegisterPermission(); List keyResolverList = new ArrayList(classNames.size()); for (String className : classNames) { + @SuppressWarnings("deprecation") KeyResolverSpi keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); keyResolverSpi.setGlobalResolver(false); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java index 78622d79336..685f0108247 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolverSpi.java @@ -110,7 +110,9 @@ public abstract class KeyResolverSpi { KeyResolverSpi tmp = this; if (globalResolver) { try { - tmp = getClass().newInstance(); + @SuppressWarnings("deprecation") + KeyResolverSpi krs = getClass().newInstance(); + tmp = krs; } catch (InstantiationException e) { throw new KeyResolverException("", e); } catch (IllegalAccessException e) { diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java index 3fc1d21bb9c..112ba1578af 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java @@ -160,7 +160,9 @@ public final class Transform extends SignatureElementProxy { throw new InvalidTransformException("signature.Transform.UnknownTransform", exArgs); } try { - transformSpi = transformSpiClass.newInstance(); + @SuppressWarnings("deprecation") + TransformSpi tmp = transformSpiClass.newInstance(); + transformSpi = tmp; } catch (InstantiationException ex) { Object exArgs[] = { algorithmURI }; throw new InvalidTransformException( @@ -345,7 +347,9 @@ public final class Transform extends SignatureElementProxy { } TransformSpi newTransformSpi = null; try { - newTransformSpi = transformSpiClass.newInstance(); + @SuppressWarnings("deprecation") + TransformSpi tmp = transformSpiClass.newInstance(); + newTransformSpi = tmp; } catch (InstantiationException ex) { Object exArgs[] = { algorithmURI }; throw new InvalidTransformException( diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java index 012d2fb8bc4..8617ac090d4 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java @@ -99,8 +99,10 @@ public class ResourceResolver { ResourceResolver resolverTmp = resolver; if (!resolver.resolverSpi.engineIsThreadSafe()) { try { - resolverTmp = - new ResourceResolver(resolver.resolverSpi.getClass().newInstance()); + @SuppressWarnings("deprecation") + ResourceResolver tmp = new ResourceResolver(resolver.resolverSpi.getClass().newInstance()); + resolverTmp = tmp; + ; } catch (InstantiationException e) { throw new ResourceResolverException("", e, context.attr, context.baseUri); } catch (IllegalAccessException e) { @@ -246,6 +248,7 @@ public class ResourceResolver { public static void register(Class className, boolean start) { JavaUtils.checkRegisterPermission(); try { + @SuppressWarnings("deprecation") ResourceResolverSpi resourceResolverSpi = className.newInstance(); register(resourceResolverSpi, start); } catch (IllegalAccessException e) { 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 bb762ad0b42..0382620b1c0 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 @@ -121,6 +121,7 @@ public class Translator extends AccessibleContext Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { + @SuppressWarnings("deprecation") Translator t = (Translator)translatorClass.newInstance(); t.setSource(o); a = t; diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java index 1c60443415b..b15b58080a5 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java @@ -148,6 +148,7 @@ public class AbstractCharsetProvider true, this.getClass().getClassLoader()); + @SuppressWarnings("deprecation") Charset cs = (Charset)c.newInstance(); cache.put(csn, new SoftReference(cs)); return cs; diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java index b5787a712f9..c7b1e3850c0 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Util.java @@ -88,8 +88,9 @@ public final class P11Util { p = Security.getProvider(providerName); if (p == null) { try { - Class clazz = Class.forName(className); - p = (Provider)clazz.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(className).newInstance(); + p = (Provider)o; } catch (Exception e) { throw new ProviderException ("Could not find provider " + providerName, e); 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 890587ad790..3aaf88e2e04 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 @@ -1446,7 +1446,9 @@ public final class SunPKCS11 extends AuthProvider { } return null; } - return (CallbackHandler)c.newInstance(); + @SuppressWarnings("deprecation") + Object result = c.newInstance(); + return (CallbackHandler)result; } }); // save it diff --git a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java index df3efc92e63..f791c5c9646 100644 --- a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java +++ b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java @@ -89,9 +89,10 @@ public abstract class HttpServerProvider { if (cn == null) return false; try { - Class c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); - provider = (HttpServerProvider)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()).newInstance(); + provider = (HttpServerProvider)o; return true; } catch (ClassNotFoundException | IllegalAccessException | diff --git a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java index ec7b91ead94..9065d2caebe 100644 --- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java @@ -82,7 +82,9 @@ public class TerminalFactory } else { try { - t = (Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance(); + @SuppressWarnings("deprecation") + Object o = Thread.currentThread().getContextClassLoader().loadClass(type).newInstance(); + t = (Terminal) o; } catch (Exception e) { throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e); diff --git a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java index 0ac8d4b69b4..0abbc55eb12 100644 --- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java @@ -61,6 +61,7 @@ public class ConsoleRunner List completorList = new ArrayList(); for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) { + @SuppressWarnings("deprecation") Object obj = Class.forName(tok.nextToken()).newInstance(); completorList.add((Completer) obj); } diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java index 35d209a690f..bd70473ceae 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java @@ -128,7 +128,9 @@ public class ProcessAttachingConnector if (lib.equals("dt_shmem")) { try { Class c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService"); - ts = (TransportService)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + ts = (TransportService)tmp; } catch (Exception x) { } } } diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java index 525a8404fd4..255fa173646 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/RawCommandLineLauncher.java @@ -53,17 +53,19 @@ public class RawCommandLineLauncher extends AbstractLauncher implements Launchin super(); try { - Class c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService"); - transportService = (TransportService)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = + Class.forName("com.sun.tools.jdi.SharedMemoryTransportService").newInstance(); + transportService = (TransportService)o; transport = new Transport() { public String name() { return "dt_shmem"; } }; - } catch (ClassNotFoundException x) { - } catch (UnsatisfiedLinkError x) { - } catch (InstantiationException x) { - } catch (IllegalAccessException x) { + } catch (ClassNotFoundException | + UnsatisfiedLinkError | + InstantiationException | + IllegalAccessException x) { }; if (transportService == null) { diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java index 84a14557b30..9996c07353b 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java @@ -64,18 +64,20 @@ public class SunCommandLineLauncher extends AbstractLauncher implements Launchin * transport or the socket transport */ try { - Class c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService"); - transportService = (TransportService)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = + Class.forName("com.sun.tools.jdi.SharedMemoryTransportService").newInstance(); + transportService = (TransportService)o; transport = new Transport() { public String name() { return "dt_shmem"; } }; usingSharedMemory = true; - } catch (ClassNotFoundException x) { - } catch (UnsatisfiedLinkError x) { - } catch (InstantiationException x) { - } catch (IllegalAccessException x) { + } catch (ClassNotFoundException | + UnsatisfiedLinkError | + InstantiationException | + IllegalAccessException x) { }; if (transportService == null) { transportService = new SocketTransportService(); diff --git a/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java index 2513237f7bf..ed9f5b826d9 100644 --- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java +++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java @@ -46,7 +46,7 @@ public class LocaleDataProvider extends LocaleData.CommonResourceBundleProvider Class c = Class.forName(LocaleDataProvider.class.getModule(), bundleName); if (c != null && ResourceBundle.class.isAssignableFrom(c)) { try { - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) ResourceBundle rb = ((Class) c).newInstance(); return rb; } catch (InstantiationException | IllegalAccessException e) { From bd838767a7d2ff1b89757d0ce9618c0a58a7a00e Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 3 May 2016 12:18:50 -0700 Subject: [PATCH 213/225] 8155963: Fix deprecation warning in windows java.net implementation Reviewed-by: prr --- .../classes/java/net/DefaultDatagramSocketImplFactory.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 1691e15abf8..a85e701efc2 100644 --- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -90,7 +90,9 @@ class DefaultDatagramSocketImplFactory throws SocketException { if (prefixImplClass != null) { try { - return (DatagramSocketImpl) prefixImplClass.newInstance(); + @SuppressWarnings("deprecation") + Object result = prefixImplClass.newInstance(); + return (DatagramSocketImpl) result; } catch (Exception e) { throw new SocketException("can't instantiate DatagramSocketImpl"); } From 766b4949799f95452ae214ada24506d94f6e4dbc Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 3 May 2016 16:17:12 -0700 Subject: [PATCH 214/225] 4943627: Deprecate rounding mode integer constants in BigDecimal and their uses Reviewed-by: bpb --- .../share/classes/java/math/BigDecimal.java | 33 +++++++++++++++++-- .../share/classes/java/math/RoundingMode.java | 3 +- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index 5c93cc291e9..557c5cc2e35 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -1536,7 +1536,7 @@ public class BigDecimal extends Number implements Comparable { * be performed to generate a result with the specified scale, the * specified rounding mode is applied. * - *

          The new {@link #divide(BigDecimal, int, RoundingMode)} method + * @deprecated The method {@link #divide(BigDecimal, int, RoundingMode)} * should be used in preference to this legacy method. * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -1558,6 +1558,7 @@ public class BigDecimal extends Number implements Comparable { * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) { if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); @@ -1602,7 +1603,7 @@ public class BigDecimal extends Number implements Comparable { * rounding must be performed to generate a result with the given * scale, the specified rounding mode is applied. * - *

          The new {@link #divide(BigDecimal, RoundingMode)} method + * @deprecated The method {@link #divide(BigDecimal, RoundingMode)} * should be used in preference to this legacy method. * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -1623,6 +1624,7 @@ public class BigDecimal extends Number implements Comparable { * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal divide(BigDecimal divisor, int roundingMode) { return this.divide(divisor, scale, roundingMode); } @@ -2267,14 +2269,20 @@ public class BigDecimal extends Number implements Comparable { * Rounding mode to round away from zero. Always increments the * digit prior to a nonzero discarded fraction. Note that this rounding * mode never decreases the magnitude of the calculated value. + * + * @deprecated Use {@link RoundingMode#UP} instead. */ + @Deprecated(since="9") public static final int ROUND_UP = 0; /** * Rounding mode to round towards zero. Never increments the digit * prior to a discarded fraction (i.e., truncates). Note that this * rounding mode never increases the magnitude of the calculated value. + * + * @deprecated Use {@link RoundingMode#DOWN} instead. */ + @Deprecated(since="9") public static final int ROUND_DOWN = 1; /** @@ -2283,7 +2291,10 @@ public class BigDecimal extends Number implements Comparable { * {@code ROUND_UP}; if negative, behaves as for * {@code ROUND_DOWN}. Note that this rounding mode never * decreases the calculated value. + * + * @deprecated Use {@link RoundingMode#CEILING} instead. */ + @Deprecated(since="9") public static final int ROUND_CEILING = 2; /** @@ -2292,7 +2303,10 @@ public class BigDecimal extends Number implements Comparable { * {@code ROUND_DOWN}; if negative, behave as for * {@code ROUND_UP}. Note that this rounding mode never * increases the calculated value. + * + * @deprecated Use {@link RoundingMode#FLOOR} instead. */ + @Deprecated(since="9") public static final int ROUND_FLOOR = 3; /** @@ -2302,7 +2316,10 @@ public class BigDecimal extends Number implements Comparable { * ≥ 0.5; otherwise, behaves as for {@code ROUND_DOWN}. Note * that this is the rounding mode that most of us were taught in * grade school. + * + * @deprecated Use {@link RoundingMode#HALF_UP} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_UP = 4; /** @@ -2311,7 +2328,10 @@ public class BigDecimal extends Number implements Comparable { * down. Behaves as for {@code ROUND_UP} if the discarded * fraction is {@literal >} 0.5; otherwise, behaves as for * {@code ROUND_DOWN}. + * + * @deprecated Use {@link RoundingMode#HALF_DOWN} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_DOWN = 5; /** @@ -2323,7 +2343,10 @@ public class BigDecimal extends Number implements Comparable { * {@code ROUND_HALF_DOWN} if it's even. Note that this is the * rounding mode that minimizes cumulative error when applied * repeatedly over a sequence of calculations. + * + * @deprecated Use {@link RoundingMode#HALF_EVEN} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_EVEN = 6; /** @@ -2331,7 +2354,10 @@ public class BigDecimal extends Number implements Comparable { * result, hence no rounding is necessary. If this rounding mode is * specified on an operation that yields an inexact result, an * {@code ArithmeticException} is thrown. + * + * @deprecated Use {@link RoundingMode#UNNECESSARY} instead. */ + @Deprecated(since="9") public static final int ROUND_UNNECESSARY = 7; @@ -2408,7 +2434,7 @@ public class BigDecimal extends Number implements Comparable { * Instead, {@code setScale} returns an object with the proper * scale; the returned object may or may not be newly allocated. * - *

          The new {@link #setScale(int, RoundingMode)} method should + * @deprecated The method {@link #setScale(int, RoundingMode)} should * be used in preference to this legacy method. * * @param newScale scale of the {@code BigDecimal} value to be returned. @@ -2431,6 +2457,7 @@ public class BigDecimal extends Number implements Comparable { * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal setScale(int newScale, int roundingMode) { if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); diff --git a/jdk/src/java.base/share/classes/java/math/RoundingMode.java b/jdk/src/java.base/share/classes/java/math/RoundingMode.java index 3a4fe97f4ab..a4a1c1aa460 100644 --- a/jdk/src/java.base/share/classes/java/math/RoundingMode.java +++ b/jdk/src/java.base/share/classes/java/math/RoundingMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, 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 @@ -90,6 +90,7 @@ package java.math; * @author Joseph D. Darcy * @since 1.5 */ +@SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal public enum RoundingMode { /** From 35e6b00ee082c73e5e1fc54d7ad2b0edfc10b584 Mon Sep 17 00:00:00 2001 From: Steve Drach Date: Mon, 2 May 2016 09:03:38 -0700 Subject: [PATCH 215/225] 8151542: URL resources for multi-release jar files have a #runtime fragment appended to them Reviewed-by: alanb, chegar, psandoz, sherman --- .../share/classes/java/util/jar/JarFile.java | 35 ++++- .../java/util/jar/JavaUtilJarAccessImpl.java | 4 + .../jdk/internal/loader/URLClassPath.java | 21 ++- .../jdk/internal/misc/JavaUtilJarAccess.java | 1 + .../MultiReleaseJarHttpProperties.java | 48 +------ .../java/util/jar/SimpleHttpServer.java | 74 ++++++++++ .../jar/MultiReleaseJarURLConnection.java | 129 ++++++++++++++++-- 7 files changed, 239 insertions(+), 73 deletions(-) create mode 100644 jdk/test/lib/testlibrary/java/util/jar/SimpleHttpServer.java 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 e1516e50c63..5f08db7b1c4 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 @@ -658,6 +658,28 @@ class JarFile extends ZipFile { return vze == null ? ze : vze; } + /** + * Returns the real name of a {@code JarEntry}. If this {@code JarFile} is + * a multi-release jar file and is configured to be processed as such, the + * name returned by this method is the path name of the versioned entry + * that the {@code JarEntry} represents, rather than the path name of the + * base entry that {@link JarEntry#getName()} returns. If the + * {@code JarEntry} does not represent a versioned entry, or the + * jar file is not a multi-release jar file or {@code JarFile} is not + * configured for processing a multi-release jar file, this method returns + * the same name that {@link JarEntry#getName()} returns. + * + * @param entry the JarEntry + * @return the real name of the JarEntry + * @since 9 + */ + String getRealName(JarEntry entry) { + if (entry instanceof JarFileEntry) { + return ((JarFileEntry)entry).realName(); + } + return entry.getName(); + } + private class JarFileEntry extends JarEntry { final private String name; @@ -684,7 +706,7 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (certs == null && jv != null) { - certs = jv.getCerts(JarFile.this, reifiedEntry()); + certs = jv.getCerts(JarFile.this, realEntry()); } return certs == null ? null : certs.clone(); } @@ -695,17 +717,20 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (signers == null && jv != null) { - signers = jv.getCodeSigners(JarFile.this, reifiedEntry()); + signers = jv.getCodeSigners(JarFile.this, realEntry()); } return signers == null ? null : signers.clone(); } - JarFileEntry reifiedEntry() { + JarFileEntry realEntry() { if (isMultiRelease()) { String entryName = super.getName(); return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); } return this; } + String realName() { + return super.getName(); + } @Override public String getName() { @@ -876,11 +901,11 @@ class JarFile extends ZipFile { private JarEntry verifiableEntry(ZipEntry ze) { if (ze instanceof JarFileEntry) { // assure the name and entry match for verification - return ((JarFileEntry)ze).reifiedEntry(); + return ((JarFileEntry)ze).realEntry(); } ze = getJarEntry(ze.getName()); if (ze instanceof JarFileEntry) { - return ((JarFileEntry)ze).reifiedEntry(); + return ((JarFileEntry)ze).realEntry(); } return (JarEntry)ze; } diff --git a/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java b/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java index 0844b9171d1..a8c5cf73aea 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java @@ -60,4 +60,8 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess { public List getManifestDigests(JarFile jar) { return jar.getManifestDigests(); } + + public String getRealName(JarFile jar, JarEntry entry) { + return jar.getRealName(entry); + } } 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 d7b60ecff5d..aa2722c5e63 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 @@ -372,9 +372,15 @@ public class URLClassPath { return java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<>() { public Loader run() throws IOException { + String protocol = url.getProtocol(); // lower cased in URL String file = url.getFile(); - if (file != null && file.endsWith("/")) { - if ("file".equals(url.getProtocol())) { + if ("jar".equals(protocol) + && file != null && (file.indexOf("!/") == file.length() - 2)) { + // extract the nested URL + URL nestedUrl = new URL(file.substring(0, file.length() - 2)); + return new JarLoader(nestedUrl, jarHandler, lmap); + } else if (file != null && file.endsWith("/")) { + if ("file".equals(protocol)) { return new FileLoader(url); } else { return new Loader(url); @@ -718,13 +724,13 @@ public class URLClassPath { final URL url; try { + String nm; if (jar.isMultiRelease()) { - // add #runtime fragment to tell JarURLConnection to use - // runtime versioning if the underlying jar file is multi-release - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); + nm = SharedSecrets.javaUtilJarAccess().getRealName(jar, entry); } else { - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + nm = name; } + url = new URL(getBaseURL(), ParseUtil.encodePath(nm, false)); if (check) { URLClassPath.check(url); } @@ -940,7 +946,8 @@ public class URLClassPath { ensureOpen(); - if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { // Only get manifest when necessary + // Only get manifest when necessary + if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { Manifest man = jar.getManifest(); if (man != null) { Attributes attr = man.getMainAttributes(); diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java index bf59351dee6..f1f7d8be2c0 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java @@ -41,4 +41,5 @@ public interface JavaUtilJarAccess { public Enumeration entries2(JarFile jar); public void setEagerValidation(JarFile jar, boolean eager); public List getManifestDigests(JarFile jar); + public String getRealName(JarFile jar, JarEntry entry); } diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java index f80991d09d5..50cec677ee6 100644 --- a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java @@ -26,7 +26,7 @@ * @bug 8132734 * @summary Test the System properties for JarFile that support multi-release jar files * @library /lib/testlibrary/java/util/jar - * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer * @run testng MultiReleaseJarHttpProperties * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties @@ -43,8 +43,6 @@ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties */ -import com.sun.net.httpserver.*; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -73,7 +71,7 @@ public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { @Override protected void initializeClassLoader() throws Exception { URL[] urls = new URL[]{ - new URL("http://localhost:" + server.getPort() + "/multi-release-jar") + new URL("http://localhost:" + server.getPort() + "/multi-release.jar") }; cldr = new URLClassLoader(urls); // load any class, Main is convenient and in the root entries @@ -112,45 +110,3 @@ public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { getResource(rootClass, resource); } } - -/** - * Extremely simple server that only performs one task. The server listens for - * requests on the ephemeral port. If it sees a request that begins with - * "/multi-release-jar", it consumes the request and returns a stream of bytes - * representing the jar file multi-release.jar found in "userdir". - */ -class SimpleHttpServer { - private static final String userdir = System.getProperty("user.dir", "."); - private static final Path multirelease = Paths.get(userdir, "multi-release.jar"); - - private final HttpServer server; - - public SimpleHttpServer() throws IOException { - server = HttpServer.create(); - } - - public void start() throws IOException { - server.bind(new InetSocketAddress(0), 0); - server.createContext("/multi-release-jar", t -> { - try (InputStream is = t.getRequestBody()) { - is.readAllBytes(); // probably not necessary to consume request - byte[] bytes = Files.readAllBytes(multirelease); - t.sendResponseHeaders(200, bytes.length); - try (OutputStream os = t.getResponseBody()) { - os.write(bytes); - } - } - }); - server.setExecutor(null); // creates a default executor - server.start(); - } - - public void stop() { - server.stop(0); - } - - int getPort() { - return server.getAddress().getPort(); - } -} - diff --git a/jdk/test/lib/testlibrary/java/util/jar/SimpleHttpServer.java b/jdk/test/lib/testlibrary/java/util/jar/SimpleHttpServer.java new file mode 100644 index 00000000000..b79423ab051 --- /dev/null +++ b/jdk/test/lib/testlibrary/java/util/jar/SimpleHttpServer.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +import com.sun.net.httpserver.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Extremely simple server that only performs one task. The server listens for + * requests on the ephemeral port. If it sees a request that begins with + * "/multi-release.jar", it consumes the request and returns a stream of bytes + * representing the jar file multi-release.jar found in "userdir". + */ +class SimpleHttpServer { + private static final String userdir = System.getProperty("user.dir", "."); + private static final Path multirelease = Paths.get(userdir, "multi-release.jar"); + + private final HttpServer server; + + public SimpleHttpServer() throws IOException { + server = HttpServer.create(); + } + + public void start() throws IOException { + server.bind(new InetSocketAddress(0), 0); + server.createContext("/multi-release.jar", t -> { + try (InputStream is = t.getRequestBody()) { + is.readAllBytes(); // probably not necessary to consume request + byte[] bytes = Files.readAllBytes(multirelease); + t.sendResponseHeaders(200, bytes.length); + try (OutputStream os = t.getResponseBody()) { + os.write(bytes); + } + } + }); + server.setExecutor(null); // creates a default executor + server.start(); + } + + public void stop() { + server.stop(0); + } + + int getPort() { + return server.getAddress().getPort(); + } +} + diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java index aeca6c6b50d..0f5545707a4 100644 --- a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -26,19 +26,25 @@ * @bug 8132734 * @summary Test that URL connections to multi-release jars can be runtime versioned * @library /lib/testlibrary/java/util/jar - * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @build Compiler JarBuilder CreateMultiReleaseTestJars SimpleHttpServer * @run testng MultiReleaseJarURLConnection */ import java.io.IOException; import java.io.InputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.net.JarURLConnection; import java.net.URL; +import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Paths; import java.util.jar.JarFile; +import jdk.Version; + import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -47,46 +53,78 @@ import org.testng.annotations.Test; public class MultiReleaseJarURLConnection { String userdir = System.getProperty("user.dir","."); - String file = userdir + "/signed-multi-release.jar"; + String unversioned = userdir + "/unversioned.jar"; + String unsigned = userdir + "/multi-release.jar"; + String signed = userdir + "/signed-multi-release.jar"; + SimpleHttpServer server; @BeforeClass public void initialize() throws Exception { CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); creator.compileEntries(); + creator.buildUnversionedJar(); creator.buildMultiReleaseJar(); creator.buildSignedMultiReleaseJar(); + + server = new SimpleHttpServer(); + server.start(); + } @AfterClass public void close() throws IOException { - Files.delete(Paths.get(userdir, "multi-release.jar")); - Files.delete(Paths.get(userdir, "signed-multi-release.jar")); + // Windows requires server to stop before file is deleted + if (server != null) + server.stop(); + Files.delete(Paths.get(unversioned)); + Files.delete(Paths.get(unsigned)); + Files.delete(Paths.get(signed)); } @DataProvider(name = "data") public Object[][] createData() { return new Object[][]{ - {"unsigned file", userdir + "/multi-release.jar"}, - {"signed file", userdir + "/signed-multi-release.jar"}, + {"unversioned", unversioned}, + {"unsigned", unsigned}, + {"signed", signed} }; } @Test(dataProvider = "data") - public void testRuntimeVersioning(String ignore, String file) throws Exception { + public void testRuntimeVersioning(String style, String file) throws Exception { String urlFile = "jar:file:" + file + "!/"; - String urlEntry = urlFile + "version/Version.java"; + String baseUrlEntry = urlFile + "version/Version.java"; + String rtreturn = "return " + Version.current().major(); - Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); - // #runtime is "magic" - Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9")); + Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8")); + // #runtime is "magic" for a multi-release jar, but not for unversioned jar + Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#runtime"), + style.equals("unversioned") ? "return 8" : rtreturn)); // #fragment or any other fragment is not magic - Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8")); + Assert.assertTrue(readAndCompare(new URL(baseUrlEntry + "#fragment"), "return 8")); // cached entities not affected - Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + Assert.assertTrue(readAndCompare(new URL(baseUrlEntry), "return 8")); + + // the following tests will not work with unversioned jars + if (style.equals("unversioned")) return; + + // direct access to versioned entry + String versUrlEntry = urlFile + "META-INF/versions/" + Version.current().major() + + "/version/Version.java"; + Assert.assertTrue(readAndCompare(new URL(versUrlEntry), rtreturn)); + // adding any fragment does not change things + Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), rtreturn)); + Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), rtreturn)); + + // it really doesn't change things + versUrlEntry = urlFile + "META-INF/versions/10/version/Version.java"; + Assert.assertTrue(readAndCompare(new URL(versUrlEntry), "return 10")); + Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#runtime"), "return 10")); + Assert.assertTrue(readAndCompare(new URL(versUrlEntry + "#fragment"), "return 10")); } @Test(dataProvider = "data") - public void testCachedJars(String ignore, String file) throws Exception { + public void testCachedJars(String style, String file) throws Exception { String urlFile = "jar:file:" + file + "!/"; URL rootUrl = new URL(urlFile); @@ -98,7 +136,11 @@ public class MultiReleaseJarURLConnection { juc = (JarURLConnection)runtimeUrl.openConnection(); JarFile runtimeJar = juc.getJarFile(); JarFile.Release runtime = runtimeJar.getVersion(); - Assert.assertNotEquals(root, runtime); + if (style.equals("unversioned")) { + Assert.assertEquals(root, runtime); + } else { + Assert.assertNotEquals(root, runtime); + } juc = (JarURLConnection)rootUrl.openConnection(); JarFile jar = juc.getJarFile(); @@ -115,6 +157,63 @@ public class MultiReleaseJarURLConnection { jar.close(); // probably not needed } + @DataProvider(name = "resourcedata") + public Object[][] createResourceData() throws Exception { + return new Object[][]{ + {"unversioned", Paths.get(unversioned).toUri().toURL()}, + {"unsigned", Paths.get(unsigned).toUri().toURL()}, + {"signed", Paths.get(signed).toUri().toURL()}, + {"unversioned", new URL("file:" + unversioned)}, + {"unsigned", new URL("file:" + unsigned)}, + {"signed", new URL("file:" + signed)}, + {"unversioned", new URL("jar:file:" + unversioned + "!/")}, + {"unsigned", new URL("jar:file:" + unsigned + "!/")}, + {"signed", new URL("jar:file:" + signed + "!/")}, + // external jar received via http protocol + {"http", new URL("jar:http://localhost:" + server.getPort() + "/multi-release.jar!/")}, + {"http", new URL("http://localhost:" + server.getPort() + "/multi-release.jar")}, + + }; + } + + @Test(dataProvider = "resourcedata") + public void testResources(String style, URL url) throws Throwable { + //System.out.println(" testing " + style + " url: " + url); + URL[] urls = {url}; + URLClassLoader cldr = new URLClassLoader(urls); + Class vcls = cldr.loadClass("version.Version"); + + // verify we are loading a runtime versioned class + MethodType mt = MethodType.methodType(int.class); + MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); + Assert.assertEquals((int)mh.invoke(vcls.newInstance()), + style.equals("unversioned") ? 8 : Version.current().major()); + + // now get a resource and verify that we don't have a fragment attached + URL vclsUrl = vcls.getResource("/version/Version.class"); + String fragment = vclsUrl.getRef(); + Assert.assertNull(fragment); + + // and verify that the the url is a reified pointer to the runtime entry + String rep = vclsUrl.toString(); + //System.out.println(" getResource(\"/version/Version.class\") returned: " + rep); + if (style.equals("http")) { + Assert.assertTrue(rep.startsWith("jar:http:")); + } else { + Assert.assertTrue(rep.startsWith("jar:file:")); + } + String suffix; + if (style.equals("unversioned")) { + suffix = ".jar!/version/Version.class"; + } else { + suffix = ".jar!/META-INF/versions/" + Version.current().major() + + "/version/Version.class"; + } + Assert.assertTrue(rep.endsWith(suffix)); + cldr.close(); + } + + private boolean readAndCompare(URL url, String match) throws Exception { boolean result; // necessary to do it this way, instead of openStream(), so we can From 191e61e18410efab09ab0488f056d3d8bf93df7e Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Wed, 4 May 2016 10:56:01 +0800 Subject: [PATCH 216/225] 8154911: Move GCDuringIteration.java back to tier1 Reviewed-by: darcy, martin --- jdk/test/TEST.groups | 2 -- 1 file changed, 2 deletions(-) diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 673b0862d5c..3f5461582e5 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -29,7 +29,6 @@ tier1 = \ :jdk_lang \ -java/lang/ProcessHandle/TreeTest.java \ :jdk_util \ - -java/util/WeakHashMap/GCDuringIteration.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ sun/nio/cs/ISO8859x.java \ @@ -39,7 +38,6 @@ tier1 = \ tier2 = \ java/lang/ProcessHandle/TreeTest.java \ - java/util/WeakHashMap/GCDuringIteration.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ :jdk_io \ From 6191c997a37b7ec8254a9c00cedc0a53ad47d38c Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 4 May 2016 16:41:07 +0300 Subject: [PATCH 217/225] 8145984: [macosx] sun.lwawt.macosx.CAccessible leaks Reviewed-by: serb, ptbrunet --- .../sun/lwawt/macosx/CAccessibility.java | 31 +++- .../sun/lwawt/macosx/CAccessibleText.java | 4 +- .../macosx/native/libawt_lwawt/awt/AWTView.h | 4 +- .../macosx/native/libawt_lwawt/awt/AWTView.m | 58 +++++- .../awt/JavaAccessibilityAction.m | 31 +++- .../awt/JavaAccessibilityUtilities.m | 18 +- .../awt/JavaComponentAccessibility.m | 173 ++++++++++++++---- .../libawt_lwawt/awt/JavaTextAccessibility.m | 37 ++-- .../libawt_lwawt/java2d/opengl/CGLLayer.h | 8 +- .../libawt_lwawt/java2d/opengl/CGLLayer.m | 20 +- 10 files changed, 296 insertions(+), 88 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 3bf3cf8f44e..652875738b7 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.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 @@ -25,12 +25,15 @@ package sun.lwawt.macosx; +import sun.lwawt.LWWindowPeer; + import java.awt.*; import java.beans.*; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.Callable; +import sun.awt.AWTAccessor; import javax.accessibility.*; import javax.swing.*; @@ -421,6 +424,8 @@ class CAccessibility implements PropertyChangeListener { } public static AccessibleAction getAccessibleAction(final Accessible a, final Component c) { + if (a == null) return null; + return invokeAndWait(new Callable() { public AccessibleAction call() throws Exception { final AccessibleContext ac = a.getAccessibleContext(); @@ -667,4 +672,28 @@ class CAccessibility implements PropertyChangeListener { } }, c); } + + /** + * @return AWTView ptr, a peer of the CPlatformView associated with the toplevel container of the Accessible, if any + */ + private static long getAWTView(Accessible a) { + Accessible ax = CAccessible.getSwingAccessible(a); + if (!(ax instanceof Component)) return 0; + + return invokeAndWait(new Callable() { + public Long call() throws Exception { + Component cont = (Component) ax; + while (cont != null && !(cont instanceof Window)) { + cont = cont.getParent(); + } + if (cont != null) { + LWWindowPeer peer = (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(cont); + if (peer != null) { + return ((CPlatformWindow) peer.getPlatformWindow()).getContentView().getAWTView(); + } + } + return 0L; + } + }, (Component)ax); + } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java index 0237ef92d66..6abf06ecd08 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibleText.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 @@ -264,6 +264,8 @@ class CAccessibleText { final double localY = boundsUnion.getY(); final Point componentLocation = ac.getAccessibleComponent().getLocationOnScreen(); + if (componentLocation == null) return ret; + final double screenX = componentLocation.getX() + localX; final double screenY = componentLocation.getY() + localY; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h index 0344aebfe44..9f64001212c 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.h @@ -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 @@ -62,6 +62,8 @@ - (void) deliverJavaMouseEvent: (NSEvent *) event; - (jobject) awtComponent:(JNIEnv *)env; ++ (AWTView *) awtView:(JNIEnv *)env ofAccessible:(jobject)jaccessible; + // Input method-related events - (void)setInputMethod:(jobject)inputMethod; - (void)abandonInput; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index 67115418d38..119056ed562 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -29,6 +29,7 @@ #import "AWTWindow.h" #import "JavaComponentAccessibility.h" #import "JavaTextAccessibility.h" +#import "JavaAccessibilityUtilities.h" #import "GeomUtilities.h" #import "OSVersion.h" #import "ThreadUtilities.h" @@ -129,7 +130,7 @@ static BOOL shouldUsePressAndHold() { self.cglLayer = nil; JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - (*env)->DeleteGlobalRef(env, m_cPlatformView); + (*env)->DeleteWeakGlobalRef(env, m_cPlatformView); m_cPlatformView = NULL; if (fInputMethodLOCKABLE != NULL) @@ -396,7 +397,11 @@ static BOOL shouldUsePressAndHold() { static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); static JNF_MEMBER_CACHE(jm_deliverMouseEvent, jc_PlatformView, "deliverMouseEvent", "(Lsun/lwawt/macosx/NSEvent;)V"); - JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent); + jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); + if (!(*env)->IsSameObject(env, jlocal, NULL)) { + JNFCallVoidMethod(env, jlocal, jm_deliverMouseEvent, jEvent); + (*env)->DeleteLocalRef(env, jlocal); + } (*env)->DeleteLocalRef(env, jEvent); } @@ -459,8 +464,11 @@ static BOOL shouldUsePressAndHold() { static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); static JNF_MEMBER_CACHE(jm_deliverKeyEvent, jc_PlatformView, "deliverKeyEvent", "(Lsun/lwawt/macosx/NSEvent;)V"); - JNFCallVoidMethod(env, m_cPlatformView, jm_deliverKeyEvent, jEvent); - + jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); + if (!(*env)->IsSameObject(env, jlocal, NULL)) { + JNFCallVoidMethod(env, jlocal, jm_deliverKeyEvent, jEvent); + (*env)->DeleteLocalRef(env, jlocal); + } if (characters != NULL) { (*env)->DeleteLocalRef(env, characters); } @@ -475,7 +483,12 @@ static BOOL shouldUsePressAndHold() { JNIEnv *env = [ThreadUtilities getJNIEnv]; static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); static JNF_MEMBER_CACHE(jm_deliverResize, jc_PlatformView, "deliverResize", "(IIII)V"); - JNFCallVoidMethod(env, m_cPlatformView, jm_deliverResize, x,y,w,h); + + jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); + if (!(*env)->IsSameObject(env, jlocal, NULL)) { + JNFCallVoidMethod(env, jlocal, jm_deliverResize, x,y,w,h); + (*env)->DeleteLocalRef(env, jlocal); + } } @@ -504,7 +517,11 @@ static BOOL shouldUsePressAndHold() { */ static JNF_CLASS_CACHE(jc_CPlatformView, "sun/lwawt/macosx/CPlatformView"); static JNF_MEMBER_CACHE(jm_deliverWindowDidExposeEvent, jc_CPlatformView, "deliverWindowDidExposeEvent", "()V"); - JNFCallVoidMethod(env, m_cPlatformView, jm_deliverWindowDidExposeEvent); + jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); + if (!(*env)->IsSameObject(env, jlocal, NULL)) { + JNFCallVoidMethod(env, jlocal, jm_deliverWindowDidExposeEvent); + (*env)->DeleteLocalRef(env, jlocal); + } /* } */ @@ -541,7 +558,13 @@ static BOOL shouldUsePressAndHold() { } return NULL; } - jobject peer = JNFGetObjectField(env, m_cPlatformView, jf_Peer); + + jobject peer = NULL; + jobject jlocal = (*env)->NewLocalRef(env, m_cPlatformView); + if (!(*env)->IsSameObject(env, jlocal, NULL)) { + peer = JNFGetObjectField(env, jlocal, jf_Peer); + (*env)->DeleteLocalRef(env, jlocal); + } static JNF_CLASS_CACHE(jc_LWWindowPeer, "sun/lwawt/LWWindowPeer"); static JNF_MEMBER_CACHE(jf_Target, jc_LWWindowPeer, "target", "Ljava/awt/Component;"); if (peer == NULL) { @@ -549,12 +572,27 @@ static BOOL shouldUsePressAndHold() { JNFDumpJavaStack(env); return NULL; } - return JNFGetObjectField(env, peer, jf_Target); + jobject comp = JNFGetObjectField(env, peer, jf_Target); + (*env)->DeleteLocalRef(env, peer); + return comp; +} + ++ (AWTView *) awtView:(JNIEnv*)env ofAccessible:(jobject)jaccessible +{ + static JNF_STATIC_MEMBER_CACHE(jm_getAWTView, sjc_CAccessibility, "getAWTView", "(Ljavax/accessibility/Accessible;)J"); + + jlong jptr = JNFCallStaticLongMethod(env, jm_getAWTView, jaccessible); + if (jptr == 0) return nil; + + return (AWTView *)jlong_to_ptr(jptr); } - (id)getAxData:(JNIEnv*)env { - return [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:[self awtComponent:env] withIndex:-1 withView:self withJavaRole:nil] autorelease]; + jobject jcomponent = [self awtComponent:env]; + id ax = [[[JavaComponentAccessibility alloc] initWithParent:self withEnv:env withAccessible:jcomponent withIndex:-1 withView:self withJavaRole:nil] autorelease]; + (*env)->DeleteLocalRef(env, jcomponent); + return ax; } - (NSArray *)accessibilityAttributeNames @@ -1299,7 +1337,7 @@ Java_sun_lwawt_macosx_CPlatformView_nativeCreateView JNF_COCOA_ENTER(env); NSRect rect = NSMakeRect(originX, originY, width, height); - jobject cPlatformView = (*env)->NewGlobalRef(env, obj); + jobject cPlatformView = (*env)->NewWeakGlobalRef(env, obj); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m index d0f8b871004..523000c76b4 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m @@ -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 @@ -35,9 +35,9 @@ { self = [super init]; if (self) { - fAccessibleAction = JNFNewGlobalRef(env, accessibleAction); + fAccessibleAction = JNFNewWeakGlobalRef(env, accessibleAction); fIndex = index; - fComponent = JNFNewGlobalRef(env, component); + fComponent = JNFNewWeakGlobalRef(env, component); } return self; } @@ -46,10 +46,10 @@ { JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - JNFDeleteGlobalRef(env, fAccessibleAction); + JNFDeleteWeakGlobalRef(env, fAccessibleAction); fAccessibleAction = NULL; - JNFDeleteGlobalRef(env, fComponent); + JNFDeleteWeakGlobalRef(env, fComponent); fComponent = NULL; [super dealloc]; @@ -61,7 +61,18 @@ JNIEnv* env = [ThreadUtilities getJNIEnv]; - return JNFJavaToNSString(env, JNFCallStaticObjectMethod(env, jm_getAccessibleActionDescription, fAccessibleAction, fIndex, fComponent)); // AWT_THREADING Safe (AWTRunLoopMode) + jobject fCompLocal = (*env)->NewLocalRef(env, fComponent); + if ((*env)->IsSameObject(env, fCompLocal, NULL)) { + return @"unknown"; + } + NSString *str = nil; + jobject jstr = JNFCallStaticObjectMethod(env, jm_getAccessibleActionDescription, fAccessibleAction, fIndex, fCompLocal); + if (jstr != NULL) { + NSString *str = JNFJavaToNSString(env, jstr); // AWT_THREADING Safe (AWTRunLoopMode) + (*env)->DeleteLocalRef(env, jstr); + } + (*env)->DeleteLocalRef(env, fCompLocal); + return str == nil ? @"unknown" : str; } - (void)perform @@ -82,9 +93,9 @@ { self = [super init]; if (self) { - fTabGroup = JNFNewGlobalRef(env, tabGroup); + fTabGroup = JNFNewWeakGlobalRef(env, tabGroup); fIndex = index; - fComponent = JNFNewGlobalRef(env, component); + fComponent = JNFNewWeakGlobalRef(env, component); } return self; } @@ -93,10 +104,10 @@ { JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - JNFDeleteGlobalRef(env, fTabGroup); + JNFDeleteWeakGlobalRef(env, fTabGroup); fTabGroup = NULL; - JNFDeleteGlobalRef(env, fComponent); + JNFDeleteWeakGlobalRef(env, fComponent); fComponent = NULL; [super dealloc]; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m index 081c7f7b431..2b999368cb1 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m @@ -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 @@ -77,7 +77,9 @@ NSString *getJavaRole(JNIEnv *env, jobject axComponent, jobject component) jobject axRole = JNFCallStaticObjectMethod(env, sjm_getAccessibleRole, axComponent, component); // AWT_THREADING Safe (AWTRunLoopMode) if (axRole == NULL) return @"unknown"; - return JNFJavaToNSString(env, axRole); + NSString* str = JNFJavaToNSString(env, axRole); + (*env)->DeleteLocalRef(env, axRole); + return str; } jobject getAxSelection(JNIEnv *env, jobject axContext, jobject component) @@ -126,21 +128,27 @@ BOOL isVertical(JNIEnv *env, jobject axContext, jobject component) { static JNF_STATIC_MEMBER_CACHE(jm_VERTICAL, sjc_AccessibleState, "VERTICAL", "Ljavax/accessibility/AccessibleState;"); jobject axVertState = JNFGetStaticObjectField(env, jm_VERTICAL); - return containsAxState(env, axContext, axVertState, component); + BOOL vertical = containsAxState(env, axContext, axVertState, component); + (*env)->DeleteLocalRef(env, axVertState); + return vertical; } BOOL isHorizontal(JNIEnv *env, jobject axContext, jobject component) { static JNF_STATIC_MEMBER_CACHE(jm_HORIZONTAL, sjc_AccessibleState, "HORIZONTAL", "Ljavax/accessibility/AccessibleState;"); jobject axHorizState = JNFGetStaticObjectField(env, jm_HORIZONTAL); - return containsAxState(env, axContext, axHorizState, component); + BOOL horizontal = containsAxState(env, axContext, axHorizState, component); + (*env)->DeleteLocalRef(env, axHorizState); + return horizontal; } BOOL isShowing(JNIEnv *env, jobject axContext, jobject component) { static JNF_STATIC_MEMBER_CACHE(jm_SHOWING, sjc_AccessibleState, "SHOWING", "Ljavax/accessibility/AccessibleState;"); jobject axVisibleState = JNFGetStaticObjectField(env, jm_SHOWING); - return containsAxState(env, axContext, axVisibleState, component); + BOOL showing = containsAxState(env, axContext, axVisibleState, component); + (*env)->DeleteLocalRef(env, axVisibleState); + return showing; } NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component) diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m index 1b3ec43a9fe..b740d05895c 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, 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 @@ -75,7 +75,6 @@ static jobject sAccessibilityClass = NULL; static NSMutableDictionary *sAttributeNamesForRoleCache = nil; static NSObject *sAttributeNamesLOCK = nil; - @interface TabGroupAccessibility : JavaComponentAccessibility { NSInteger _numTabs; } @@ -137,8 +136,11 @@ static NSObject *sAttributeNamesLOCK = nil; fView = [view retain]; fJavaRole = [javaRole retain]; - fAccessible = JNFNewGlobalRef(env, accessible); - fComponent = JNFNewGlobalRef(env, [(AWTView *)fView awtComponent:env]); + fAccessible = (*env)->NewWeakGlobalRef(env, accessible); + + jobject jcomponent = [(AWTView *)fView awtComponent:env]; + fComponent = (*env)->NewWeakGlobalRef(env, jcomponent); + (*env)->DeleteLocalRef(env, jcomponent); fIndex = index; @@ -166,10 +168,10 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - JNFDeleteGlobalRef(env, fAccessible); + (*env)->DeleteWeakGlobalRef(env, fAccessible); fAccessible = NULL; - JNFDeleteGlobalRef(env, fComponent); + (*env)->DeleteWeakGlobalRef(env, fComponent); fComponent = NULL; [fParent release]; @@ -279,7 +281,7 @@ static NSObject *sAttributeNamesLOCK = nil; + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored { - jobjectArray jchildrenAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) + jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) if (jchildrenAndRoles == NULL) return nil; jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles); @@ -294,14 +296,21 @@ static NSObject *sAttributeNamesLOCK = nil; NSString *childJavaRole = nil; if (jchildJavaRole != NULL) { - childJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jchildJavaRole, sjf_key)); + jobject jkey = JNFGetObjectField(env, jchildJavaRole, sjf_key); + childJavaRole = JNFJavaToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); } JavaComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView]; + + (*env)->DeleteLocalRef(env, jchild); + (*env)->DeleteLocalRef(env, jchildJavaRole); + [children addObject:child]; childIndex++; } - + (*env)->DeleteLocalRef(env, jchildrenAndRoles); + return children; } @@ -310,7 +319,7 @@ static NSObject *sAttributeNamesLOCK = nil; jobject jcomponent = [(AWTView *)view awtComponent:env]; jint index = JNFCallStaticIntMethod(env, sjm_getAccessibleIndexInParent, jaccessible, jcomponent); NSString *javaRole = getJavaRole(env, jaccessible, jcomponent); - + (*env)->DeleteLocalRef(env, jcomponent); return [self createWithAccessible:jaccessible role:javaRole index:index withEnv:env withView:view]; } @@ -325,7 +334,10 @@ static NSObject *sAttributeNamesLOCK = nil; jobject jCAX = [JavaComponentAccessibility getCAccessible:jaccessible withEnv:env]; if (jCAX == NULL) return nil; JavaComponentAccessibility *value = (JavaComponentAccessibility *) jlong_to_ptr(JNFGetLongField(env, jCAX, jf_ptr)); - if (value != nil) return [[value retain] autorelease]; + if (value != nil) { + (*env)->DeleteLocalRef(env, jCAX); + return [[value retain] autorelease]; + } // otherwise, create a new instance JavaComponentAccessibility *newChild = nil; @@ -348,6 +360,7 @@ static NSObject *sAttributeNamesLOCK = nil; // must hard retain pointer poked into Java object [newChild retain]; JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild)); + (*env)->DeleteLocalRef(env, jCAX); // return autoreleased instance return [newChild autorelease]; @@ -380,7 +393,7 @@ static NSObject *sAttributeNamesLOCK = nil; // Get all the other accessibility attributes states we need in one swell foop. // javaRole isn't pulled in because we need protected access to AccessibleRole.key - jbooleanArray attributeStates = JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jbooleanArray attributeStates = (jbooleanArray)JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (attributeStates == NULL) return nil; jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0); if (attributeStatesArray == NULL) { @@ -475,6 +488,7 @@ static NSObject *sAttributeNamesLOCK = nil; JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:0 withComponent:fComponent]; [fActions setObject:action forKey:[self isMenu] ? NSAccessibilityPickAction : NSAccessibilityPressAction]; [action release]; + (*env)->DeleteLocalRef(env, axAction); } } @@ -485,7 +499,9 @@ static NSObject *sAttributeNamesLOCK = nil; - (id)parent { + static JNF_CLASS_CACHE(sjc_Window, "java/awt/Window"); static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleParent, sjc_CAccessibility, "getAccessibleParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;"); + static JNF_STATIC_MEMBER_CACHE(sjm_getSwingAccessible, sjc_CAccessible, "getSwingAccessible", "(Ljavax/accessibility/Accessible;)Ljavax/accessibility/Accessible;"); if(fParent == nil) { JNIEnv* env = [ThreadUtilities getJNIEnv]; @@ -495,10 +511,21 @@ static NSObject *sAttributeNamesLOCK = nil; if (jparent == NULL) { fParent = fView; } else { - fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:fView]; + AWTView *view = fView; + jobject jax = JNFCallStaticObjectMethod(env, sjm_getSwingAccessible, fAccessible); + + if (JNFIsInstanceOf(env, jax, &sjc_Window)) { + // In this case jparent is an owner toplevel and we should retrieve its own view + view = [AWTView awtView:env ofAccessible:jparent]; + } + if (view != nil) { + fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:view]; + } if (fParent == nil) { fParent = fView; } + (*env)->DeleteLocalRef(env, jparent); + (*env)->DeleteLocalRef(env, jax ); } [fParent retain]; } @@ -546,7 +573,10 @@ static NSObject *sAttributeNamesLOCK = nil; return NO; } - return isShowing(env, [self axContextWithEnv:env], fComponent); + jobject axContext = [self axContextWithEnv:env]; + BOOL showing = isShowing(env, axContext, fComponent); + (*env)->DeleteLocalRef(env, axContext); + return showing; } // the array of names for each role is cached in the sAttributeNamesForRoleCache @@ -723,7 +753,12 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return JNFJavaToNSString(env, val); + if (val == NULL) { + return @"unknown"; + } + NSString* str = JNFJavaToNSString(env, val); + (*env)->DeleteLocalRef(env, val); + return str; } - (BOOL)accessibilityIsHelpAttributeSettable @@ -739,7 +774,12 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject axValue = JNFCallStaticObjectMethod(env, jm_getMaximumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return JNFJavaToNSNumber(env, axValue); + if (axValue == NULL) { + return [NSNumber numberWithInt:0]; + } + NSNumber* num = JNFJavaToNSNumber(env, axValue); + (*env)->DeleteLocalRef(env, axValue); + return num; } - (BOOL)accessibilityIsMaxValueAttributeSettable @@ -755,7 +795,12 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject axValue = JNFCallStaticObjectMethod(env, jm_getMinimumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return JNFJavaToNSNumber(env, axValue); + if (axValue == NULL) { + return [NSNumber numberWithInt:0]; + } + NSNumber* num = JNFJavaToNSNumber(env, axValue); + (*env)->DeleteLocalRef(env, axValue); + return num; } - (BOOL)accessibilityIsMinValueAttributeSettable @@ -770,13 +815,16 @@ static NSObject *sAttributeNamesLOCK = nil; // cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz if (isVertical(env, axContext, fComponent)) { + (*env)->DeleteLocalRef(env, axContext); return NSAccessibilityVerticalOrientationValue; } if (isHorizontal(env, axContext, fComponent)) { + (*env)->DeleteLocalRef(env, axContext); return NSAccessibilityHorizontalOrientationValue; } + (*env)->DeleteLocalRef(env, axContext); return nil; } @@ -808,6 +856,7 @@ static NSObject *sAttributeNamesLOCK = nil; // Get the java screen coords, and make a NSPoint of the bottom left of the AxComponent. NSSize size = getAxComponentSize(env, axComponent, fComponent); NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent); + (*env)->DeleteLocalRef(env, axComponent); point.y += size.height; @@ -857,8 +906,9 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent); - if(axRole != NULL) { + if (axRole != NULL) { value = JNFJavaToNSString(env, axRole); + (*env)->DeleteLocalRef(env, axRole); } else { value = @"unknown"; } @@ -893,7 +943,9 @@ static NSObject *sAttributeNamesLOCK = nil; - (NSValue *)accessibilitySizeAttribute { JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)]; + NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)]; + (*env)->DeleteLocalRef(env, axComponent); + return size; } - (BOOL)accessibilityIsSizeAttributeSettable @@ -952,7 +1004,12 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return JNFJavaToNSString(env, val); + if (val == NULL) { + return @"unknown"; + } + NSString* str = JNFJavaToNSString(env, val); + (*env)->DeleteLocalRef(env, val); + return str; } - (BOOL)accessibilityIsTitleAttributeSettable @@ -984,8 +1041,20 @@ static NSObject *sAttributeNamesLOCK = nil; // a text value is taken care of in JavaTextAccessibility // cmcnote should coalesce these calls into one java call + NSNumber *num = nil; jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return JNFJavaToNSNumber(env, JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent)); // AWT_THREADING Safe (AWTRunLoop) + if (axValue != NULL) { + jobject str = JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent); + if (str != NULL) { + num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop) + (*env)->DeleteLocalRef(env, str); + } + (*env)->DeleteLocalRef(env, axValue); + } + if (num == nil) { + num = [NSNumber numberWithInt:0]; + } + return num; } - (BOOL)accessibilityIsValueAttributeSettable @@ -1084,7 +1153,10 @@ static NSObject *sAttributeNamesLOCK = nil; id value = nil; if (JNFIsInstanceOf(env, jparent, &jc_Container)) { jobject jaccessible = JNFCallStaticObjectMethod(env, jm_accessibilityHitTest, jparent, (jfloat)point.x, (jfloat)point.y); // AWT_THREADING Safe (AWTRunLoop) - value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView]; + if (jaccessible != NULL) { + value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView]; + (*env)->DeleteLocalRef(env, jaccessible); + } } if (value == nil) { @@ -1116,6 +1188,7 @@ static NSObject *sAttributeNamesLOCK = nil; if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; } + (*env)->DeleteLocalRef(env, focused); } if (value == nil) { @@ -1222,38 +1295,46 @@ JNF_COCOA_EXIT(env); for (i = 0; i < _numTabs; i++) { aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i]; if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) { + (*env)->DeleteLocalRef(env, selAccessible); return aTab; } } - + (*env)->DeleteLocalRef(env, selAccessible); return nil; } - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored { - jobjectArray jtabsAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) + jobjectArray jtabsAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) if(jtabsAndRoles == NULL) return nil; jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles); - if (arrayLen == 0) return nil; - + if (arrayLen == 0) { + (*env)->DeleteLocalRef(env, jtabsAndRoles); + return nil; + } NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)]; // all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1. - if (jtabJavaRole == NULL) return nil; - - NSString *tabJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jtabJavaRole, sjf_key)); + if (jtabJavaRole == NULL) { + (*env)->DeleteLocalRef(env, jtabsAndRoles); + return nil; + } + jobject jkey = JNFGetObjectField(env, jtabJavaRole, sjf_key); + NSString *tabJavaRole = JNFJavaToNSString(env, jkey); + (*env)->DeleteLocalRef(env, jkey); NSInteger i; NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly for(i = 0; i < arrayLen; i+=2) { jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i); JavaComponentAccessibility *tab = [[[TabGroupControlAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease]; + (*env)->DeleteLocalRef(env, jtab); [tabs addObject:tab]; tabIndex++; } - + (*env)->DeleteLocalRef(env, jtabsAndRoles); return tabs; } @@ -1272,7 +1353,9 @@ JNF_COCOA_EXIT(env); { JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axContext = [self axContextWithEnv:env]; - return [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + id tabs = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + (*env)->DeleteLocalRef(env, axContext); + return tabs; } - (BOOL)accessibilityIsTabsAttributeSettable @@ -1292,7 +1375,9 @@ JNF_COCOA_EXIT(env); { JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axContext = [self axContextWithEnv:env]; - return [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO]; + (*env)->DeleteLocalRef(env, axContext); + return cont; } - (BOOL)accessibilityIsContentsAttributeSettable @@ -1305,7 +1390,9 @@ JNF_COCOA_EXIT(env); { JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axContext = [self axContextWithEnv:env]; - return [self currentTabWithEnv:env withAxContext:axContext]; + id val = [self currentTabWithEnv:env withAxContext:axContext]; + (*env)->DeleteLocalRef(env, axContext); + return val; } - (BOOL)accessibilityIsValueAttributeSettable @@ -1322,6 +1409,7 @@ JNF_COCOA_EXIT(env); JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axContext = [self axContextWithEnv:env]; setAxContextSelection(env, axContext, fIndex, fComponent); + (*env)->DeleteLocalRef(env, axContext); } - (NSArray *)accessibilityChildrenAttribute @@ -1357,6 +1445,7 @@ JNF_COCOA_EXIT(env); result = children; } } + (*env)->DeleteLocalRef(env, axContext); } else { result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount]; } @@ -1375,7 +1464,7 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole]; if (self) { if (tabGroup != NULL) { - fTabGroupAxContext = JNFNewGlobalRef(env, tabGroup); + fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroup); } else { fTabGroupAxContext = NULL; } @@ -1388,7 +1477,7 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; if (fTabGroupAxContext != NULL) { - JNFDeleteGlobalRef(env, fTabGroupAxContext); + JNFDeleteWeakGlobalRef(env, fTabGroupAxContext); fTabGroupAxContext = NULL; } @@ -1399,9 +1488,14 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); { JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axContext = [self axContextWithEnv:env]; + jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent); // Returns the current selection of the page tab list - return [NSNumber numberWithBool:ObjectEquals(env, axContext, getAxContextSelection(env, [self tabGroup], fIndex, fComponent), fComponent)]; + id val = [NSNumber numberWithBool:ObjectEquals(env, axContext, selAccessible, fComponent)]; + + (*env)->DeleteLocalRef(env, selAccessible); + (*env)->DeleteLocalRef(env, axContext); + return val; } - (void)getActionsWithEnv:(JNIEnv *)env @@ -1416,7 +1510,8 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); if (fTabGroupAxContext == NULL) { JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env]; - fTabGroupAxContext = JNFNewGlobalRef(env, tabGroupAxContext); + fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroupAxContext); + (*env)->DeleteLocalRef(env, tabGroupAxContext); } return fTabGroupAxContext; } @@ -1451,8 +1546,10 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) { jobject elementAxContext = [aElement axContextWithEnv:env]; if (isHorizontal(env, elementAxContext, fComponent)) { + (*env)->DeleteLocalRef(env, elementAxContext); return aElement; } + (*env)->DeleteLocalRef(env, elementAxContext); } } @@ -1478,8 +1575,10 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component); if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) { jobject elementAxContext = [aElement axContextWithEnv:env]; if (isVertical(env, elementAxContext, fComponent)) { + (*env)->DeleteLocalRef(env, elementAxContext); return aElement; } + (*env)->DeleteLocalRef(env, elementAxContext); } } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m index 2809d8bcbf5..f7e17b0e96f 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m @@ -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 @@ -112,7 +112,9 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { // if it's static text, the AppKit AXValue is the java accessibleName jobject axName = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (axName != NULL) { - return JNFJavaToNSString(env, axName); + NSString* str = JNFJavaToNSString(env, axName); + (*env)->DeleteLocalRef(env, axName); + return str; } // value is still nil if no accessibleName for static text. Below, try to get the accessibleText. } @@ -120,12 +122,18 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923 jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (axText == NULL) return nil; - + (*env)->DeleteLocalRef(env, axText); + jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (axEditableText == NULL) return nil; static JNF_STATIC_MEMBER_CACHE(jm_getTextRange, sjc_CAccessibleText, "getTextRange", "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;"); - NSString *string = JNFJavaToNSString(env, JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent)); // AWT_THREADING Safe (AWTRunLoop) + jobject jrange = JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent); + NSString *string = JNFJavaToNSString(env, jrange); // AWT_THREADING Safe (AWTRunLoop) + + (*env)->DeleteLocalRef(env, jrange); + (*env)->DeleteLocalRef(env, axEditableText); + if (string == nil) string = @""; return string; } @@ -139,6 +147,7 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { JNIEnv* env = [ThreadUtilities getJNIEnv]; jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (axEditableText == NULL) return NO; + (*env)->DeleteLocalRef(env, axEditableText); return YES; } @@ -157,7 +166,9 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { static JNF_STATIC_MEMBER_CACHE(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;"); jobject axText = JNFCallStaticObjectMethod(env, jm_getSelectedText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) if (axText == NULL) return @""; - return JNFJavaToNSString(env, axText); + NSString* str = JNFJavaToNSString(env, axText); + (*env)->DeleteLocalRef(env, axText); + return str; } - (BOOL)accessibilityIsSelectedTextAttributeSettable @@ -220,7 +231,9 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead JNIEnv *env = [ThreadUtilities getJNIEnv]; jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) - return [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)]; + NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)]; + (*env)->DeleteLocalRef(env, axText); + return num; } - (BOOL)accessibilityIsNumberOfCharactersAttributeSettable @@ -285,7 +298,7 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { JNIEnv *env = [ThreadUtilities getJNIEnv]; static JNF_STATIC_MEMBER_CACHE(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D"); - jdoubleArray axBounds = JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) + jdoubleArray axBounds = (jdoubleArray)JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) if (axBounds == NULL) return nil; // We cheat because we know that the array is 4 elements long (x, y, width, height) @@ -324,7 +337,7 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { JNIEnv *env = [ThreadUtilities getJNIEnv]; static JNF_STATIC_MEMBER_CACHE(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I"); - jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop) + jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop) if (axTextRange == NULL) return nil; return javaIntArrayToNSRangeValue(env,axTextRange); @@ -350,10 +363,12 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { JNIEnv *env = [ThreadUtilities getJNIEnv]; static JNF_STATIC_MEMBER_CACHE(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;"); - jstring jstringForRange = JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) + jstring jstringForRange = (jstring)JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) if (jstringForRange == NULL) return @""; - return JNFJavaToNSString(env, jstringForRange); + NSString* str = JNFJavaToNSString(env, jstringForRange); + (*env)->DeleteLocalRef(env, jstringForRange); + return str; } // @@ -406,7 +421,7 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) { JNIEnv *env = [ThreadUtilities getJNIEnv]; static JNF_STATIC_MEMBER_CACHE(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I"); - jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop) + jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop) if (axTextRange == NULL) return nil; return javaIntArrayToNSRangeValue(env, axTextRange); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h index 4a34dda953c..843de484813 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h @@ -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 @@ -31,7 +31,7 @@ @interface CGLLayer : CAOpenGLLayer { @private - JNFJObjectWrapper *javaLayer; + JNFWeakJObjectWrapper *javaLayer; // intermediate buffer, used the RQ lock to synchronize GLuint textureID; @@ -45,7 +45,7 @@ #endif /* REMOTELAYER */ } -@property (nonatomic, retain) JNFJObjectWrapper *javaLayer; +@property (nonatomic, retain) JNFWeakJObjectWrapper *javaLayer; @property (readwrite, assign) GLuint textureID; @property (readwrite, assign) GLenum target; @property (readwrite, assign) float textureWidth; @@ -57,7 +57,7 @@ @property (nonatomic, retain) NSObject *jrsRemoteLayer; #endif -- (id) initWithJavaLayer:(JNFJObjectWrapper *)javaLayer; +- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)javaLayer; - (void) blitTexture; @end diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m index f300ea404c4..87dcf1d351c 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, 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 @@ -46,7 +46,7 @@ extern NSOpenGLContext *sharedContext; @synthesize jrsRemoteLayer; #endif -- (id) initWithJavaLayer:(JNFJObjectWrapper *)layer; +- (id) initWithJavaLayer:(JNFWeakJObjectWrapper *)layer; { AWT_ASSERT_APPKIT_THREAD; // Initialize ourselves @@ -133,6 +133,15 @@ AWT_ASSERT_APPKIT_THREAD; { AWT_ASSERT_APPKIT_THREAD; + JNIEnv *env = [ThreadUtilities getJNIEnv]; + static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer"); + static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V"); + + jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env]; + if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) { + return; + } + // Set the current context to the one given to us. CGLSetCurrentContext(glContext); @@ -141,12 +150,7 @@ AWT_ASSERT_APPKIT_THREAD; glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, textureWidth, textureHeight); - - JNIEnv *env = [ThreadUtilities getJNIEnv]; - static JNF_CLASS_CACHE(jc_JavaLayer, "sun/java2d/opengl/CGLLayer"); - static JNF_MEMBER_CACHE(jm_drawInCGLContext, jc_JavaLayer, "drawInCGLContext", "()V"); - jobject javaLayerLocalRef = [self.javaLayer jObjectWithEnv:env]; JNFCallVoidMethod(env, javaLayerLocalRef, jm_drawInCGLContext); (*env)->DeleteLocalRef(env, javaLayerLocalRef); @@ -171,7 +175,7 @@ Java_sun_java2d_opengl_CGLLayer_nativeCreateLayer JNF_COCOA_ENTER(env); - JNFJObjectWrapper *javaLayer = [JNFJObjectWrapper wrapperWithJObject:obj withEnv:env]; + JNFWeakJObjectWrapper *javaLayer = [JNFWeakJObjectWrapper wrapperWithJObject:obj withEnv:env]; [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ AWT_ASSERT_APPKIT_THREAD; From ab72d795f4c9a1a407dda4fb97c4d4741ec770cc Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 4 May 2016 16:55:03 +0200 Subject: [PATCH 218/225] 8155939: sun.launcher.LauncherHelper INSTANCE is unused Reviewed-by: rriggs, ksrini --- .../share/classes/sun/launcher/LauncherHelper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java index e8a4b78cff5..b1b761eb452 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -84,8 +84,10 @@ import java.util.jar.Manifest; import jdk.internal.misc.VM; -public enum LauncherHelper { - INSTANCE; +public final class LauncherHelper { + + // No instantiation + private LauncherHelper() {} // used to identify JavaFX applications private static final String JAVAFX_APPLICATION_MARKER = From 5106d55d5569b13fd331dcb262394acaa4171e61 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 4 May 2016 08:04:22 -0700 Subject: [PATCH 219/225] 8153192: (se) Selector.select(long) uses wrong timeout after EINTR (lnx) Pass what remains of the initial timeout to epoll_wait(2) (Linux) and ioctl(7d) (Solaris) instead of the original un-decremented timeout value. Reviewed-by: alanb, rriggs --- jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c | 4 ++-- .../java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c b/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c index c7b391f930a..12b1c8524bc 100644 --- a/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c +++ b/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, 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 @@ -53,7 +53,7 @@ iepoll(int epfd, struct epoll_event *events, int numfds, jlong timeout) start = t.tv_sec * 1000 + t.tv_usec / 1000; for (;;) { - int res = epoll_wait(epfd, events, numfds, timeout); + int res = epoll_wait(epfd, events, numfds, remaining); if (res < 0 && errno == EINTR) { if (remaining >= 0) { gettimeofday(&t, NULL); diff --git a/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c b/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c index 962f5e49263..6860a167bbc 100644 --- a/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c +++ b/jdk/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.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 @@ -94,6 +94,7 @@ idevpoll(jint wfd, int dpctl, struct dvpoll a) return 0; } start = now; + a.dp_timeout = remaining; } } else { return res; From bd9c092ecc48ed32fe60e182d7b7170c59472c52 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 4 May 2016 08:53:09 -0700 Subject: [PATCH 220/225] 8155649: IncludeLocalesPlugin throws NPE when jdk.localedata not resolved Reviewed-by: alanb, mchung --- .../plugins/IncludeLocalesPlugin.java | 38 +++++++------- .../tools/jlink/resources/plugins.properties | 3 ++ .../plugins/IncludeLocalesPluginTest.java | 51 +++++++++++++++---- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java index c67a378b8e0..b8b7aa46cc1 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java @@ -177,24 +177,28 @@ public final class IncludeLocalesPlugin implements TransformerPlugin, ResourcePr Pool.Module module = resources.getModule(MODULENAME); // jdk.localedata module validation - Set packages = module.getAllPackages(); - if (!packages.containsAll(LOCALEDATA_PACKAGES)) { - throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") + - LOCALEDATA_PACKAGES.stream() - .filter(pn -> !packages.contains(pn)) - .collect(Collectors.joining(",\n\t"))); + if (module != null) { + Set packages = module.getAllPackages(); + if (!packages.containsAll(LOCALEDATA_PACKAGES)) { + throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") + + LOCALEDATA_PACKAGES.stream() + .filter(pn -> !packages.contains(pn)) + .collect(Collectors.joining(",\n\t"))); + } + + available = Stream.concat(module.getContent().stream() + .map(md -> p.matcher(md.getPath())) + .filter(m -> m.matches()) + .map(m -> m.group("tag").replaceAll("_", "-")), + Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag))) + .distinct() + .sorted() + .map(IncludeLocalesPlugin::tagToLocale) + .collect(Collectors.toList()); + } else { + // jdk.localedata is not added. + throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".localedatanotfound")); } - - available = Stream.concat(module.getContent().stream() - .map(md -> p.matcher(md.getPath())) - .filter(m -> m.matches()) - .map(m -> m.group("tag").replaceAll("_", "-")), - Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag))) - .distinct() - .sorted() - .map(IncludeLocalesPlugin::tagToLocale) - .collect(Collectors.toList()); - filtered = filterLocales(available); if (filtered.isEmpty()) { diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 73143b8ef79..6edcf645063 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -89,6 +89,9 @@ No matching locales found for \"%s\". Check the specified pattern. include-locales.invalidtag=\ Invalid language tag: %s +include-locales.localedatanotfound=\ +jdk.localedata module was not specified with --addmods option + main.status.ok=Functional. main.status.not.ok= Not functional. diff --git a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java index e109e6c496f..357541a3144 100644 --- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java +++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java @@ -36,6 +36,7 @@ import tests.Result; /* * @test + * @bug 8152143 8152704 8155649 * @summary IncludeLocalesPlugin tests * @author Naoto Sato * @library ../../lib @@ -55,15 +56,17 @@ public class IncludeLocalesPluginTest { private final static String moduleName = "IncludeLocalesTest"; private static Helper helper; private final static int INCLUDE_LOCALES_OPTION = 0; - private final static int EXPECTED_LOCATIONS = 1; - private final static int UNEXPECTED_PATHS = 2; - private final static int AVAILABLE_LOCALES = 3; - private final static int ERROR_MESSAGE = 4; + private final static int ADDMODS_OPTION = 1; + private final static int EXPECTED_LOCATIONS = 2; + private final static int UNEXPECTED_PATHS = 3; + private final static int AVAILABLE_LOCALES = 4; + private final static int ERROR_MESSAGE = 5; private final static Object[][] testData = { // without --include-locales option: should include all locales { "", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", @@ -144,6 +147,7 @@ public class IncludeLocalesPluginTest { // All English/Japanese locales { "--include-locales=en,ja", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class", "/jdk.localedata/sun/text/resources/ext/FormatData_ja.class", @@ -174,6 +178,7 @@ public class IncludeLocalesPluginTest { // All locales in India { "--include-locales=*-IN", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_en_IN.class", "/jdk.localedata/sun/text/resources/ext/FormatData_hi_IN.class", @@ -201,7 +206,9 @@ public class IncludeLocalesPluginTest { }, // Thai - {"--include-locales=th", + { + "--include-locales=th", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/thai_dict", @@ -221,7 +228,9 @@ public class IncludeLocalesPluginTest { }, // Hong Kong - {"--include-locales=zh-HK", + { + "--include-locales=zh-HK", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_zh.class", "/jdk.localedata/sun/text/resources/ext/FormatData_zh_HK.class", @@ -244,7 +253,9 @@ public class IncludeLocalesPluginTest { }, // Norwegian - {"--include-locales=nb,nn,no", + { + "--include-locales=nb,nn,no", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_no.class", "/jdk.localedata/sun/text/resources/ext/FormatData_no_NO.class", @@ -268,7 +279,9 @@ public class IncludeLocalesPluginTest { }, // Hebrew/Indonesian/Yiddish - {"--include-locales=he,id,yi", + { + "--include-locales=he,id,yi", + "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/FormatData_in.class", "/jdk.localedata/sun/text/resources/ext/FormatData_in_ID.class", @@ -294,7 +307,9 @@ public class IncludeLocalesPluginTest { }, // Error case: No matching locales - {"--include-locales=xyz", + { + "--include-locales=xyz", + "jdk.localedata", null, null, null, @@ -304,7 +319,9 @@ public class IncludeLocalesPluginTest { }, // Error case: Invalid argument - {"--include-locales=en,zh_HK", + { + "--include-locales=en,zh_HK", + "jdk.localedata", null, null, null, @@ -312,6 +329,18 @@ public class IncludeLocalesPluginTest { PluginsResourceBundle.getMessage("include-locales.invalidtag"), "zh_HK")) .getMessage(), }, + + // Error case: jdk.localedata is not added + { + "--include-locales=en-US", + "java.base", + null, + null, + null, + new PluginException( + PluginsResourceBundle.getMessage("include-locales.localedatanotfound")) + .getMessage(), + }, }; public static void main(String[] args) throws Exception { @@ -328,7 +357,7 @@ public class IncludeLocalesPluginTest { Result result = JImageGenerator.getJLinkTask() .modulePath(helper.defaultModulePath()) .output(helper.createNewImageDir(moduleName)) - .addMods("jdk.localedata") + .addMods((String)data[ADDMODS_OPTION]) .option((String)data[INCLUDE_LOCALES_OPTION]) .call(); From 182152c38568d5f73b469d37e7b663677620d50d Mon Sep 17 00:00:00 2001 From: Harsha Wardhana B Date: Thu, 5 May 2016 01:52:03 -0700 Subject: [PATCH 221/225] 8154166: java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java fails with RuntimeException Fix the RuntimeException issue Reviewed-by: jbachorik --- .../management/MemoryMXBean/ResetPeakMemoryUsage.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java index b1f6e781044..dc85eb6bb03 100644 --- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java +++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java @@ -36,9 +36,13 @@ * @modules java.management * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil * @run main ResetPeakMemoryUsage + * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" + * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true" + * @requires vm.opt.DisableExplicitGC != "true" */ import java.lang.management.*; +import java.lang.ref.WeakReference; import java.util.*; public class ResetPeakMemoryUsage { @@ -100,6 +104,7 @@ public class ResetPeakMemoryUsage { printMemoryUsage(usage0, peak0); obj = new Object[largeArraySize]; + WeakReference weakRef = new WeakReference<>(obj); MemoryUsage usage1 = mpool.getUsage(); MemoryUsage peak1 = mpool.getPeakUsage(); @@ -124,7 +129,11 @@ public class ResetPeakMemoryUsage { // The object is now garbage and do a GC // memory usage should drop obj = null; - mbean.gc(); + + //This will cause sure shot GC unlike Runtime.gc() invoked by mbean.gc() + while(weakRef.get() != null) { + mbean.gc(); + } MemoryUsage usage2 = mpool.getUsage(); MemoryUsage peak2 = mpool.getPeakUsage(); From 0cf5c574548c3faba733cf2d73c8071c7d0a2f9f Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 5 May 2016 11:37:18 +0100 Subject: [PATCH 222/225] 8155928: Remove hardcoded port numbers from httpclient/Security.java test Reviewed-by: chegar, rriggs --- .../share/classes/java/net/http/Utils.java | 2 +- .../java/net/httpclient/security/0.policy | 3 +- .../java/net/httpclient/security/1.policy | 5 +- .../java/net/httpclient/security/10.policy | 5 +- .../java/net/httpclient/security/11.policy | 7 +- .../java/net/httpclient/security/12.policy | 7 +- .../java/net/httpclient/security/14.policy | 23 +++ .../java/net/httpclient/security/15.policy | 4 +- .../java/net/httpclient/security/2.policy | 3 +- .../java/net/httpclient/security/3.policy | 3 +- .../java/net/httpclient/security/4.policy | 3 +- .../java/net/httpclient/security/5.policy | 3 +- .../java/net/httpclient/security/6.policy | 3 +- .../java/net/httpclient/security/7.policy | 3 +- .../java/net/httpclient/security/8.policy | 3 +- .../java/net/httpclient/security/9.policy | 3 +- .../java/net/httpclient/security/Driver.java | 139 ++++++++++++++++++ .../net/httpclient/security/Security.java | 59 ++++---- 18 files changed, 215 insertions(+), 63 deletions(-) create mode 100644 jdk/test/java/net/httpclient/security/14.policy create mode 100644 jdk/test/java/net/httpclient/security/Driver.java diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java index d16248d4b6b..302b39d9f40 100644 --- a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java @@ -146,7 +146,7 @@ final class Utils { } else { sb.append(uri.getScheme()) .append("://") - .append(uri.getHost()) + .append(uri.getAuthority()) .append(uri.getPath()); urlstring = sb.toString(); diff --git a/jdk/test/java/net/httpclient/security/0.policy b/jdk/test/java/net/httpclient/security/0.policy index 918766e425d..16276a7e5f9 100644 --- a/jdk/test/java/net/httpclient/security/0.policy +++ b/jdk/test/java/net/httpclient/security/0.policy @@ -2,8 +2,7 @@ grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/1.policy b/jdk/test/java/net/httpclient/security/1.policy index b9be27e884c..8e44d212d69 100644 --- a/jdk/test/java/net/httpclient/security/1.policy +++ b/jdk/test/java/net/httpclient/security/1.policy @@ -1,8 +1,7 @@ // Policy 1 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; @@ -13,7 +12,7 @@ grant { // permissions specific to this test - permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET"; + permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET"; }; // For proxy only. Not being tested diff --git a/jdk/test/java/net/httpclient/security/10.policy b/jdk/test/java/net/httpclient/security/10.policy index e6341878348..2be99f876b7 100644 --- a/jdk/test/java/net/httpclient/security/10.policy +++ b/jdk/test/java/net/httpclient/security/10.policy @@ -1,8 +1,7 @@ // Policy 10 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; @@ -12,7 +11,7 @@ grant { permission java.lang.RuntimePermission "createClassLoader"; // permissions specific to this test - permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*"; + permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*"; }; // For proxy only. Not being tested diff --git a/jdk/test/java/net/httpclient/security/11.policy b/jdk/test/java/net/httpclient/security/11.policy index 016d090bc65..16d9b48791d 100644 --- a/jdk/test/java/net/httpclient/security/11.policy +++ b/jdk/test/java/net/httpclient/security/11.policy @@ -1,8 +1,7 @@ // Policy 11 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; @@ -12,8 +11,8 @@ grant { permission java.lang.RuntimePermission "createClassLoader"; // permissions specific to this test - permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*"; - permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT"; + permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*"; + permission java.net.URLPermission "socket://127.0.0.1:${port.number1}", "CONNECT"; }; diff --git a/jdk/test/java/net/httpclient/security/12.policy b/jdk/test/java/net/httpclient/security/12.policy index 016d090bc65..16d9b48791d 100644 --- a/jdk/test/java/net/httpclient/security/12.policy +++ b/jdk/test/java/net/httpclient/security/12.policy @@ -1,8 +1,7 @@ // Policy 11 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; @@ -12,8 +11,8 @@ grant { permission java.lang.RuntimePermission "createClassLoader"; // permissions specific to this test - permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*"; - permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT"; + permission java.net.URLPermission "http://127.0.0.1:${port.number}/files/foo.txt", "GET:*"; + permission java.net.URLPermission "socket://127.0.0.1:${port.number1}", "CONNECT"; }; diff --git a/jdk/test/java/net/httpclient/security/14.policy b/jdk/test/java/net/httpclient/security/14.policy new file mode 100644 index 00000000000..85b0d4943e4 --- /dev/null +++ b/jdk/test/java/net/httpclient/security/14.policy @@ -0,0 +1,23 @@ +// Policy 14 +grant { + // permissions common to all tests + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; + permission java.net.NetPermission "getDefaultHttpClient"; + permission java.lang.RuntimePermission "modifyThread"; + permission java.util.logging.LoggingPermission "control", ""; + permission java.net.SocketPermission "localhost:1024-", "accept,listen"; + permission java.io.FilePermission "${test.src}${/}docs${/}-", "read"; + permission java.lang.RuntimePermission "createClassLoader"; + + + // permissions specific to this test + permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET"; +}; + +// For proxy only. Not being tested +grant codebase "file:${test.classes}/proxydir/-" { + permission java.net.SocketPermission "localhost:1024-", "accept,listen,connect"; + permission java.net.SocketPermission "127.0.0.1:1024-", "connect,resolve"; +}; + diff --git a/jdk/test/java/net/httpclient/security/15.policy b/jdk/test/java/net/httpclient/security/15.policy index f2f02c90b9e..923b2deed35 100644 --- a/jdk/test/java/net/httpclient/security/15.policy +++ b/jdk/test/java/net/httpclient/security/15.policy @@ -1,8 +1,7 @@ // Policy 11 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; @@ -13,7 +12,6 @@ grant { // permissions specific to this test permission java.net.URLPermission "http://127.0.0.1:*/files/foo.txt", "GET:*"; - permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT"; // Test checks for this explicitly permission java.net.RuntimePermission "foobar"; diff --git a/jdk/test/java/net/httpclient/security/2.policy b/jdk/test/java/net/httpclient/security/2.policy index 8a19314f3d0..7c7e50013a1 100644 --- a/jdk/test/java/net/httpclient/security/2.policy +++ b/jdk/test/java/net/httpclient/security/2.policy @@ -1,8 +1,7 @@ // Policy 2 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/3.policy b/jdk/test/java/net/httpclient/security/3.policy index 075a5be3e80..85f3e59a216 100644 --- a/jdk/test/java/net/httpclient/security/3.policy +++ b/jdk/test/java/net/httpclient/security/3.policy @@ -1,8 +1,7 @@ // Policy 3 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/4.policy b/jdk/test/java/net/httpclient/security/4.policy index 8248caf46da..6d67b89cdd7 100644 --- a/jdk/test/java/net/httpclient/security/4.policy +++ b/jdk/test/java/net/httpclient/security/4.policy @@ -1,8 +1,7 @@ // Policy 4 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/5.policy b/jdk/test/java/net/httpclient/security/5.policy index ba63e335919..5eb739a6e81 100644 --- a/jdk/test/java/net/httpclient/security/5.policy +++ b/jdk/test/java/net/httpclient/security/5.policy @@ -1,8 +1,7 @@ // Policy 5 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/6.policy b/jdk/test/java/net/httpclient/security/6.policy index 4b29da739c3..55bbd1ac30c 100644 --- a/jdk/test/java/net/httpclient/security/6.policy +++ b/jdk/test/java/net/httpclient/security/6.policy @@ -1,8 +1,7 @@ // Policy 6 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/7.policy b/jdk/test/java/net/httpclient/security/7.policy index 80345ba1610..7859e8df5e6 100644 --- a/jdk/test/java/net/httpclient/security/7.policy +++ b/jdk/test/java/net/httpclient/security/7.policy @@ -1,8 +1,7 @@ // Policy 7 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/8.policy b/jdk/test/java/net/httpclient/security/8.policy index bc298b19fd6..774b0ae47ed 100644 --- a/jdk/test/java/net/httpclient/security/8.policy +++ b/jdk/test/java/net/httpclient/security/8.policy @@ -1,8 +1,7 @@ // Policy 8 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/9.policy b/jdk/test/java/net/httpclient/security/9.policy index d11c412f274..e4ff37dd01f 100644 --- a/jdk/test/java/net/httpclient/security/9.policy +++ b/jdk/test/java/net/httpclient/security/9.policy @@ -1,8 +1,7 @@ // Policy 9 grant { // permissions common to all tests - permission java.util.PropertyPermission "test.src", "read"; - permission java.util.PropertyPermission "test.classes", "read"; + permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "${test.classes}${/}-", "read,write,delete"; permission java.net.NetPermission "getDefaultHttpClient"; permission java.lang.RuntimePermission "modifyThread"; diff --git a/jdk/test/java/net/httpclient/security/Driver.java b/jdk/test/java/net/httpclient/security/Driver.java new file mode 100644 index 00000000000..078be5f5e51 --- /dev/null +++ b/jdk/test/java/net/httpclient/security/Driver.java @@ -0,0 +1,139 @@ +/* + * 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 + */ + +/** + * @test + * @bug 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext jdk.testlibrary.Utils + * @compile ../../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../../com/sun/net/httpserver/FileServerHandler.java + * @compile ../ProxyServer.java + * @build Security + * + * @run driver/timeout=60 Driver + */ + +/** + * driver required for allocating free portnumbers and putting this number + * into security policy file used in some tests. + * + * The tests are in Security.java and port number supplied in -Dport.number + * and -Dport.number1 for tests that require a second free port + */ +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.io.*; +import java.net.*; + +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.Utils; + +/** + * Driver for tests + */ +public class Driver { + + public static void main(String[] args) throws Throwable { + System.out.println("Starting Driver"); + runtest("1.policy", "1"); + runtest("10.policy", "10"); + runtest("11.policy", "11"); + runtest("12.policy", "12"); + System.out.println("DONE"); + } + + static class Logger extends Thread { + private final OutputStream ps; + private final InputStream stdout; + + Logger(String cmdLine, Process p, String dir) throws IOException { + super(); + setDaemon(true); + cmdLine = "Command line = [" + cmdLine + "]"; + stdout = p.getInputStream(); + File f = File.createTempFile("debug", ".txt", new File(dir)); + ps = new FileOutputStream(f); + ps.write(cmdLine.getBytes()); + ps.flush(); + } + + public void run() { + try { + byte[] buf = new byte[128]; + int c; + while ((c = stdout.read(buf)) != -1) { + ps.write(buf, 0, c); + ps.flush(); + } + ps.close(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + public static void runtest(String policy, String testnum) throws Throwable { + + String testJdk = System.getProperty("test.jdk", "?"); + String testSrc = System.getProperty("test.src", "?"); + String testClassPath = System.getProperty("test.class.path", "?"); + String testClasses = System.getProperty("test.classes", "?"); + String sep = System.getProperty("file.separator", "?"); + String javaCmd = testJdk + sep + "bin" + sep + "java"; + int retval = 10; // 10 is special exit code denoting a bind error + // in which case, we retry + while (retval == 10) { + List cmd = new ArrayList<>(); + cmd.add(javaCmd); + cmd.add("-Dtest.jdk=" + testJdk); + cmd.add("-Dtest.src=" + testSrc); + cmd.add("-Dtest.classes=" + testClasses); + cmd.add("-Djava.security.manager"); + cmd.add("-Djava.security.policy=" + testSrc + sep + policy); + cmd.add("-Dport.number=" + Integer.toString(Utils.getFreePort())); + cmd.add("-Dport.number1=" + Integer.toString(Utils.getFreePort())); + cmd.add("-cp"); + cmd.add(testClassPath); + cmd.add("Security"); + cmd.add(testnum); + + ProcessBuilder processBuilder = new ProcessBuilder(cmd) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectErrorStream(true); + + String cmdLine = cmd.stream().collect(Collectors.joining(" ")); + Process child = processBuilder.start(); + Logger log = new Logger(cmdLine, child, testClasses); + log.start(); + retval = child.waitFor(); + System.out.println("retval = " + retval); + } + if (retval != 0) { + Thread.sleep(2000); + throw new RuntimeException("Non zero return value"); + } + } +} diff --git a/jdk/test/java/net/httpclient/security/Security.java b/jdk/test/java/net/httpclient/security/Security.java index adfa8f71f65..185b8a7be26 100644 --- a/jdk/test/java/net/httpclient/security/Security.java +++ b/jdk/test/java/net/httpclient/security/Security.java @@ -32,7 +32,6 @@ * @compile ../ProxyServer.java * * @run main/othervm/secure=java.lang.SecurityManager/policy=0.policy Security 0 - * @run main/othervm/secure=java.lang.SecurityManager/policy=1.policy Security 1 * @run main/othervm/secure=java.lang.SecurityManager/policy=2.policy Security 2 * @run main/othervm/secure=java.lang.SecurityManager/policy=3.policy Security 3 * @run main/othervm/secure=java.lang.SecurityManager/policy=4.policy Security 4 @@ -41,14 +40,13 @@ * @run main/othervm/secure=java.lang.SecurityManager/policy=7.policy Security 7 * @run main/othervm/secure=java.lang.SecurityManager/policy=8.policy Security 8 * @run main/othervm/secure=java.lang.SecurityManager/policy=9.policy Security 9 - * @run main/othervm/secure=java.lang.SecurityManager/policy=10.policy Security 10 - * @run main/othervm/secure=java.lang.SecurityManager/policy=11.policy Security 11 - * @run main/othervm/secure=java.lang.SecurityManager/policy=12.policy Security 12 * @run main/othervm/secure=java.lang.SecurityManager/policy=0.policy Security 13 - * @run main/othervm/secure=java.lang.SecurityManager/policy=1.policy Security 14 + * @run main/othervm/secure=java.lang.SecurityManager/policy=14.policy Security 14 * @run main/othervm/secure=java.lang.SecurityManager/policy=15.policy Security 15 */ +// Tests 1, 10, 11 and 12 executed from Driver + import com.sun.net.httpserver.*; import java.io.IOException; import java.io.InputStream; @@ -78,7 +76,7 @@ public class Security { static HttpServer s1 = null; static ExecutorService executor=null; - static int port; + static int port, proxyPort; static HttpClient client; static String httproot, fileuri, fileroot, redirectroot; static List clients = new LinkedList<>(); @@ -136,6 +134,9 @@ public class Security { if (!dest.toFile().exists()) { System.out.printf("moving %s to %s\n", src.toString(), dest.toString()); Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING); + } else if (src.toFile().exists()) { + System.out.printf("%s exists, deleting %s\n", dest.toString(), src.toString()); + Files.delete(src); } else { System.out.printf("NOT moving %s to %s\n", src.toString(), dest.toString()); } @@ -225,15 +226,15 @@ public class Security { }), // (10) policy has permission for destination URL but not for proxy test(false, () -> { //Policy 10 - directProxyTest(27208, true); + directProxyTest(proxyPort, true); }), // (11) policy has permission for both destination URL and proxy test(true, () -> { //Policy 11 - directProxyTest(27301, true); + directProxyTest(proxyPort, true); }), // (12) policy has permission for both destination URL and proxy test(false, () -> { //Policy 11 - directProxyTest(28301, false); + directProxyTest(proxyPort, false); }), // (13) async version of test 0 test(false, () -> { // Policy 0 @@ -350,6 +351,8 @@ public class Security { throw new RuntimeException("Failed"); } System.out.println (policy + " succeeded as expected"); + } catch (BindException e) { + System.exit(10); } catch (SecurityException e) { if (succeeds) { System.out.println("FAILED"); @@ -362,8 +365,12 @@ public class Security { } public static void main(String[] args) throws Exception { - initServer(); - setupProxy(); + try { + initServer(); + setupProxy(); + } catch (BindException e) { + System.exit(10); + } fileroot = System.getProperty ("test.src")+ "/docs"; int testnum = Integer.parseInt(args[0]); String policy = args[0]; @@ -382,33 +389,25 @@ public class Security { runtest(tr.test, policy, tr.result); } finally { s1.stop(0); - //executor.shutdownNow(); + executor.shutdownNow(); for (HttpClient client : clients) client.executorService().shutdownNow(); } } - // create Http Server on port range below. So, we can - HttpServer createServer() { - HttpServer server; - for (int i=25800; i<26800; i++) { - InetSocketAddress a = new InetSocketAddress(i); - try { - server = HttpServer.create(a, 0); - return server; - } catch (IOException e) {} - } - return null; - } - public static void initServer() throws Exception { + String portstring = System.getProperty("port.number"); + port = portstring != null ? Integer.parseInt(portstring) : 0; + portstring = System.getProperty("port.number1"); + proxyPort = portstring != null ? Integer.parseInt(portstring) : 0; + Logger logger = Logger.getLogger("com.sun.net.httpserver"); ConsoleHandler ch = new ConsoleHandler(); logger.setLevel(Level.ALL); ch.setLevel(Level.ALL); logger.addHandler(ch); String root = System.getProperty ("test.src")+ "/docs"; - InetSocketAddress addr = new InetSocketAddress (0); + InetSocketAddress addr = new InetSocketAddress (port); s1 = HttpServer.create (addr, 0); if (s1 instanceof HttpsServer) { throw new RuntimeException ("should not be httpsserver"); @@ -423,7 +422,13 @@ public class Security { s1.setExecutor (executor); s1.start(); - port = s1.getAddress().getPort(); + if (port == 0) + port = s1.getAddress().getPort(); + else { + if (s1.getAddress().getPort() != port) + throw new RuntimeException("Error wrong port"); + System.out.println("Port was assigned by Driver"); + } System.out.println("HTTP server port = " + port); httproot = "http://127.0.0.1:" + port + "/files/"; redirectroot = "http://127.0.0.1:" + port + "/redirect/"; From b52c5bbd676a3d78caf1cee59abfa4846f540c9c Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Thu, 5 May 2016 11:44:01 -0700 Subject: [PATCH 223/225] 8147039: Incorrect locals and operands in compiled frames Implement stack walking using javaVFrame instead of vframeStream Reviewed-by: mchung, vlivanov --- .../lang/StackWalker/CountLocalSlots.java | 61 +++ .../lang/StackWalker/LocalsAndOperands.java | 378 ++++++++++++++---- .../java/lang/StackWalker/LocalsCrash.java | 74 ++++ 3 files changed, 439 insertions(+), 74 deletions(-) create mode 100644 jdk/test/java/lang/StackWalker/CountLocalSlots.java create mode 100644 jdk/test/java/lang/StackWalker/LocalsCrash.java diff --git a/jdk/test/java/lang/StackWalker/CountLocalSlots.java b/jdk/test/java/lang/StackWalker/CountLocalSlots.java new file mode 100644 index 00000000000..c78a4cb7bf4 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/CountLocalSlots.java @@ -0,0 +1,61 @@ +/* + * 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 8147039 + * @summary Confirm locals[] always has expected length, even for "dead" locals + * @compile LocalsAndOperands.java + * @run testng/othervm -Xcomp CountLocalSlots + */ + +import org.testng.annotations.Test; +import java.lang.StackWalker.StackFrame; + +public class CountLocalSlots { + final static boolean debug = true; + + @Test(dataProvider = "provider", dataProviderClass = LocalsAndOperands.class) + public void countLocalSlots(StackFrame... frames) { + for (StackFrame frame : frames) { + if (debug) { + System.out.println("Running countLocalSlots"); + LocalsAndOperands.dumpStackWithLocals(frames); + } + // Confirm expected number of locals + String methodName = frame.getMethodName(); + Integer expectedObj = (Integer) LocalsAndOperands.Tester.NUM_LOCALS.get(methodName); + if (expectedObj == null) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException("No NUM_LOCALS entry for " + + methodName + "(). Update test?"); + } + Object[] locals = (Object[]) LocalsAndOperands.invokeGetLocals(frame); + if (locals.length != expectedObj) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException(methodName + "(): number of locals (" + + locals.length + ") did not match expected (" + expectedObj + ")"); + } + } + } +} diff --git a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java index 63a6731a164..b253ab27e81 100644 --- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java +++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.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 @@ -23,17 +23,20 @@ /* * @test - * @bug 8020968 - * @summary Sanity test for locals and operands - * @run main LocalsAndOperands + * @bug 8020968 8147039 + * @summary Tests for locals and operands + * @run testng LocalsAndOperands */ +import org.testng.annotations.*; import java.lang.StackWalker.StackFrame; import java.lang.reflect.*; -import java.util.List; -import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; public class LocalsAndOperands { + static final boolean debug = true; + static Class liveStackFrameClass; static Class primitiveValueClass; static StackWalker extendedWalker; @@ -41,92 +44,319 @@ public class LocalsAndOperands { static Method getOperands; static Method getMonitors; static Method primitiveType; - public static void main(String... args) throws Exception { - liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); - primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); - getLocals.setAccessible(true); + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); - getOperands.setAccessible(true); + getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); + getLocals.setAccessible(true); - getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); - getMonitors.setAccessible(true); + getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); + getOperands.setAccessible(true); - primitiveType = primitiveValueClass.getDeclaredMethod("type"); - primitiveType.setAccessible(true); + getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); + getMonitors.setAccessible(true); - Method method = liveStackFrameClass.getMethod("getStackWalker"); - method.setAccessible(true); - extendedWalker = (StackWalker) method.invoke(null); - new LocalsAndOperands(extendedWalker, true).test(); + primitiveType = primitiveValueClass.getDeclaredMethod("type"); + primitiveType.setAccessible(true); - // no access to local and operands. - new LocalsAndOperands(StackWalker.getInstance(), false).test(); + Method method = liveStackFrameClass.getMethod("getStackWalker"); + method.setAccessible(true); + extendedWalker = (StackWalker) method.invoke(null); + } catch (Throwable t) { throw new RuntimeException(t); } } - private final StackWalker walker; - private final boolean extended; - LocalsAndOperands(StackWalker walker, boolean extended) { - this.walker = walker; - this.extended = extended; + /** Helper method to return a StackFrame's locals */ + static Object[] invokeGetLocals(StackFrame arg) { + try { + return (Object[]) getLocals.invoke(arg); + } catch (Exception e) { throw new RuntimeException(e); } } - synchronized void test() throws Exception { - int x = 10; - char c = 'z'; - String hi = "himom"; - long l = 1000000L; - double d = 3.1415926; + /***************** + * DataProviders * + *****************/ - List frames = walker.walk(s -> s.collect(Collectors.toList())); - if (extended) { - for (StackWalker.StackFrame f : frames) { - System.out.println("frame: " + f); - Object[] locals = (Object[]) getLocals.invoke(f); + /** Calls testLocals() and provides LiveStackFrames for testLocals* methods */ + @DataProvider + public static StackFrame[][] provider() { + return new StackFrame[][] { + new Tester().testLocals() + }; + } + + /** + * Calls testLocalsKeepAlive() and provides LiveStackFrames for testLocals* methods. + * Local variables in testLocalsKeepAlive() are ensured to not become dead. + */ + @DataProvider + public static StackFrame[][] keepAliveProvider() { + return new StackFrame[][] { + new Tester().testLocalsKeepAlive() + }; + } + + /** + * Provides StackFrames from a StackWalker without the LOCALS_AND_OPERANDS + * option. + */ + @DataProvider + public static StackFrame[][] noLocalsProvider() { + // Use default StackWalker + return new StackFrame[][] { + new Tester(StackWalker.getInstance(), true).testLocals() + }; + } + + /** + * Calls testLocals() and provides LiveStackFrames for *all* called methods, + * including test infrastructure (jtreg, testng, etc) + * + */ + @DataProvider + public static StackFrame[][] unfilteredProvider() { + return new StackFrame[][] { + new Tester(extendedWalker, false).testLocals() + }; + } + + /**************** + * Test methods * + ****************/ + + /** + * Check for expected local values and types in the LiveStackFrame + */ + @Test(dataProvider = "keepAliveProvider") + public static void checkLocalValues(StackFrame... frames) { + if (debug) { + System.out.println("Running checkLocalValues"); + dumpStackWithLocals(frames); + } + Arrays.stream(frames).filter(f -> f.getMethodName() + .equals("testLocalsKeepAlive")) + .forEach( + f -> { + Object[] locals = invokeGetLocals(f); for (int i = 0; i < locals.length; i++) { - System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + // Value + String expected = Tester.LOCAL_VALUES[i]; + Object observed = locals[i]; + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed.toString())) { + System.err.println("Local value mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " value is " + + observed + ", expected " + expected); + } - // check for non-null locals in LocalsAndOperands.test() - if (f.getClassName().equals("LocalsAndOperands") && - f.getMethodName().equals("test")) { - if (locals[i] == null) { - throw new RuntimeException("kept-alive locals should not be null"); - } + // Type + expected = Tester.LOCAL_TYPES[i]; + observed = type(locals[i]); + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed)) { + System.err.println("Local type mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " type is " + + observed + ", expected " + expected); } } - - Object[] operands = (Object[]) getOperands.invoke(f); - for (int i = 0; i < operands.length; i++) { - System.out.format(" operand %d: %s type %s%n", i, operands[i], - type(operands[i])); - } - - Object[] monitors = (Object[]) getMonitors.invoke(f); - for (int i = 0; i < monitors.length; i++) { - System.out.format(" monitor %d: %s%n", i, monitors[i]); - } } - } else { - for (StackFrame f : frames) { - if (liveStackFrameClass.isInstance(f)) { - throw new RuntimeException("should not be LiveStackFrame"); - } - } - } - // Use local variables so they stay alive - System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + ); } - String type(Object o) throws Exception { - if (o == null) { - return "null"; - } else if (primitiveValueClass.isInstance(o)) { - char c = (char)primitiveType.invoke(o); - return String.valueOf(c); - } else { - return o.getClass().getName(); + /** + * Basic sanity check for locals and operands + */ + @Test(dataProvider = "provider") + public static void sanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running sanityCheck"); } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(LocalsAndOperands::printLocals); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Sanity check for locals and operands, including testng/jtreg frames + */ + @Test(dataProvider = "unfilteredProvider") + public static void unfilteredSanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running unfilteredSanityCheck"); + } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(f -> { System.out.println(f + ": " + + invokeGetLocals(f).length + " locals"); } ); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Test that LiveStackFrames are not provided with the default StackWalker + * options. + */ + @Test(dataProvider = "noLocalsProvider") + public static void withoutLocalsAndOperands(StackFrame... frames) { + for (StackFrame frame : frames) { + if (liveStackFrameClass.isInstance(frame)) { + throw new RuntimeException("should not be LiveStackFrame"); + } + } + } + + static class Tester { + private StackWalker walker; + private boolean filter = true; // Filter out testng/jtreg/etc frames? + + Tester() { + this.walker = extendedWalker; + } + + Tester(StackWalker walker, boolean filter) { + this.walker = walker; + this.filter = filter; + } + + /** + * Perform stackwalk without keeping local variables alive and return an + * array of the collected StackFrames + */ + private synchronized StackFrame[] testLocals() { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + if (filter) { + return walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } else { + return walker.walk(s -> s.collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } + } + + /** + * Perform stackwalk, keeping local variables alive, and return a list of + * the collected StackFrames + */ + private synchronized StackFrame[] testLocalsKeepAlive() { + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + List frames; + if (filter) { + frames = walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())); + } else { + frames = walker.walk(s -> s.collect(Collectors.toList())); + } + + // Use local variables so they stay alive + System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + return frames.toArray(new StackFrame[0]); // FIXME: convert to Array here + } + + // Expected values for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real values instead of Strings, rebuild doubles & floats, etc + private final static String[] LOCAL_VALUES = new String[] { + null, // skip, LocalsAndOperands$Tester@XXX identity is different each run + "10", + "122", + "himom", + "0", + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + "0" + }; + + // Expected types for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real types + private final static String[] LOCAL_TYPES = new String[] { + null, // skip + "I", + "I", + "java.lang.String", + "I", + "I", + "I", + "I", + "I" + }; + + final static Map NUM_LOCALS = Map.of("testLocals", 8, + "testLocalsKeepAlive", + LOCAL_VALUES.length); + private final static Collection TEST_METHODS = NUM_LOCALS.keySet(); + } + + /** + * Print stack trace with locals + */ + public static void dumpStackWithLocals(StackFrame...frames) { + Arrays.stream(frames).forEach(LocalsAndOperands::printLocals); + } + + /** + * Print the StackFrame and an indexed list of its locals + */ + public static void printLocals(StackWalker.StackFrame frame) { + try { + System.out.println(frame); + Object[] locals = (Object[]) getLocals.invoke(frame); + for (int i = 0; i < locals.length; i++) { + System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + } + + Object[] operands = (Object[]) getOperands.invoke(frame); + for (int i = 0; i < operands.length; i++) { + System.out.format(" operand %d: %s type %s%n", i, operands[i], + type(operands[i])); + } + + Object[] monitors = (Object[]) getMonitors.invoke(frame); + for (int i = 0; i < monitors.length; i++) { + System.out.format(" monitor %d: %s%n", i, monitors[i]); + } + } catch (Exception e) { throw new RuntimeException(e); } + } + + private static String type(Object o) { + try { + if (o == null) { + return "null"; + } else if (primitiveValueClass.isInstance(o)) { + char c = (char)primitiveType.invoke(o); + return String.valueOf(c); + } else { + return o.getClass().getName(); + } + } catch(Exception e) { throw new RuntimeException(e); } } } diff --git a/jdk/test/java/lang/StackWalker/LocalsCrash.java b/jdk/test/java/lang/StackWalker/LocalsCrash.java new file mode 100644 index 00000000000..b50dd263f00 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/LocalsCrash.java @@ -0,0 +1,74 @@ +/* + * 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 8147039 + * @summary Test for -Xcomp crash that happened before 8147039 fix + * @run testng/othervm -Xcomp LocalsCrash + */ + +import org.testng.annotations.*; +import java.lang.reflect.*; +import java.util.List; +import java.util.stream.Collectors; + +public class LocalsCrash { + static Class liveStackFrameClass; + static Method getStackWalker; + + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + getStackWalker = liveStackFrameClass.getMethod("getStackWalker"); + getStackWalker.setAccessible(true); + } catch (Throwable t) { throw new RuntimeException(t); } + } + + private StackWalker walker; + + LocalsCrash() { + try { + walker = (StackWalker) getStackWalker.invoke(null); + } catch (Exception e) { throw new RuntimeException(e); } + } + + @Test + public void test00() { doStackWalk(); } + + @Test + public void test01() { doStackWalk(); } + + private synchronized List doStackWalk() { + try { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + return walker.walk(s -> s.collect(Collectors.toList())); + } catch (Exception e) { throw new RuntimeException(e); } + } +} From 096e59e6c9d39e1704fb182a61c5debe748cc3e5 Mon Sep 17 00:00:00 2001 From: Sharath Ballal Date: Fri, 6 May 2016 11:47:45 +0300 Subject: [PATCH 224/225] 8154144: Tests in com/sun/jdi fails intermittently with "jdb input stream closed prematurely" Don't print stream closed message during shutdown Reviewed-by: dcubed, sla, dsamersoff --- .../tools/example/debug/tty/EventHandler.java | 6 +++++- .../com/sun/tools/example/debug/tty/TTY.java | 20 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java index fe6dd070f0d..cd416ccf24e 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, 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 @@ -133,6 +133,10 @@ public class EventHandler implements Runnable { if (!vmDied) { vmDisconnectEvent(event); } + /* + * Inform jdb command line processor that jdb is being shutdown. JDK-8154144. + */ + ((TTY)notifier).setShuttingDown(true); Env.shutdown(shutdownMessageKey); return false; } else { diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index 0bd403af2b9..ee716a55dcb 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, 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 @@ -56,6 +56,16 @@ public class TTY implements EventNotifier { */ private static final String progname = "jdb"; + private volatile boolean shuttingDown = false; + + public void setShuttingDown(boolean s) { + shuttingDown = s; + } + + public boolean isShuttingDown() { + return shuttingDown; + } + @Override public void vmStartEvent(VMStartEvent se) { Thread.yield(); // fetch output @@ -750,7 +760,13 @@ public class TTY implements EventNotifier { while (true) { String ln = in.readLine(); if (ln == null) { - MessageOutput.println("Input stream closed."); + /* + * Jdb is being shutdown because debuggee exited, ignore any 'null' + * returned by readLine() during shutdown. JDK-8154144. + */ + if (!isShuttingDown()) { + MessageOutput.println("Input stream closed."); + } ln = "quit"; } From 2b1fdef17a5fffe8ce0076a5e2d1b0e70aafd3ae Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 6 May 2016 15:59:27 -0700 Subject: [PATCH 225/225] 8150921: Update Unsafe getters/setters to use double-register variants Reviewed-by: dholmes, shade, psandoz, jrose --- .../classes/jdk/internal/misc/Unsafe.java | 213 ++++++++++++------ 1 file changed, 146 insertions(+), 67 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 735d1b86143..c7ee6a2f44f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -33,6 +33,7 @@ import jdk.internal.reflect.Reflection; import jdk.internal.misc.VM; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.vm.annotation.ForceInline; /** @@ -209,46 +210,103 @@ public final class Unsafe { /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native byte getByte(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native short getShort(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native char getChar(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native long getLong(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native float getFloat(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native double getDouble(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putDouble(Object o, long offset, double x); + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + *

          If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address may be determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + * @see #getInt(Object, long) + */ + @ForceInline + public long getAddress(Object o, long offset) { + if (ADDRESS_SIZE == 4) { + return Integer.toUnsignedLong(getInt(o, offset)); + } else { + return getLong(o, offset); + } + } + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + *

          The number of bytes actually written at the target address may be + * determined by consulting {@link #addressSize}. + * + * @see #allocateMemory + * @see #putInt(Object, long, int) + */ + @ForceInline + public void putAddress(Object o, long offset, long x) { + if (ADDRESS_SIZE == 4) { + putInt(o, offset, (int)x); + } else { + putLong(o, offset, x); + } + } + // These read VM internal data. /** @@ -287,8 +345,10 @@ public final class Unsafe { * * @see #allocateMemory */ - @HotSpotIntrinsicCandidate - public native byte getByte(long address); + @ForceInline + public byte getByte(long address) { + return getByte(null, address); + } /** * Stores a value into a given memory address. If the address is zero, or @@ -297,75 +357,94 @@ public final class Unsafe { * * @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native void putByte(long address, byte x); + @ForceInline + public void putByte(long address, byte x) { + putByte(null, address, x); + } /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native short getShort(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putShort(long address, short x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native char getChar(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putChar(long address, char x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native int getInt(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putInt(long address, int x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native long getLong(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putLong(long address, long x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native float getFloat(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putFloat(long address, float x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native double getDouble(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putDouble(long address, double x); + @ForceInline + public short getShort(long address) { + return getShort(null, address); + } - /** - * Fetches a native pointer from a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - *

          If the native pointer is less than 64 bits wide, it is extended as - * an unsigned number to a Java long. The pointer may be indexed by any - * given byte offset, simply by adding that offset (as a simple integer) to - * the long representing the pointer. The number of bytes actually read - * from the target address may be determined by consulting {@link - * #addressSize}. - * - * @see #allocateMemory - */ - @HotSpotIntrinsicCandidate - public native long getAddress(long address); + /** @see #putByte(long, byte) */ + @ForceInline + public void putShort(long address, short x) { + putShort(null, address, x); + } - /** - * Stores a native pointer into a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - *

          The number of bytes actually written at the target address may be - * determined by consulting {@link #addressSize}. - * - * @see #getAddress(long) - */ - @HotSpotIntrinsicCandidate - public native void putAddress(long address, long x); + /** @see #getByte(long) */ + @ForceInline + public char getChar(long address) { + return getChar(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putChar(long address, char x) { + putChar(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public int getInt(long address) { + return getInt(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putInt(long address, int x) { + putInt(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public long getLong(long address) { + return getLong(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putLong(long address, long x) { + putLong(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public float getFloat(long address) { + return getFloat(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putFloat(long address, float x) { + putFloat(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public double getDouble(long address) { + return getDouble(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putDouble(long address, double x) { + putDouble(null, address, x); + } + + /** @see #getAddress(Object, long) */ + @ForceInline + public long getAddress(long address) { + return getAddress(null, address); + } + + /** @see #putAddress(Object, long, long) */ + @ForceInline + public void putAddress(long address, long x) { + putAddress(null, address, x); + }