diff --git a/.hgtags b/.hgtags index 6e63513e173..2336f25130c 100644 --- a/.hgtags +++ b/.hgtags @@ -1,3 +1,5 @@ +e2b70be325bd10dae4c06f74c46d70d480854916 jdk-9+179 +5b16a1c3ccffff2a82c88bb7ea894c4ff1c9ebde jdk-9+180 43bf6f30fcba031ecf0cc7e511efe3a8179d0f77 jdk-9+176 d9f6bc6ba599d0487dc18b2fbdb6c34eedf6f958 jdk-9+177 bc9df7dd63ec76f50fafeb4acc44465044662f0a jdk-9+178 @@ -438,3 +440,4 @@ e6d70017f5b9adbb2ec82d826973d0251800a3c3 jdk-10+12 9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14 878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15 4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16 +7db699468b4f84abbcc01647e5a964409737411a jdk-10+17 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 127576bce0c..8faa13d434f 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -437,3 +437,6 @@ d67a3f1f057f7e31e12f33ebe3667cb73d252268 jdk-10+13 a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177 a6c830ee8a6798b186730475e700027cdf4598aa jdk-10+15 2fe66ca1e2b3c361f949de9cb2894661dc0a3fa2 jdk-10+16 +ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178 +252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179 +a133a7d1007b1456bc62824382fd8ac93b45d329 jdk-10+17 diff --git a/corba/.hgtags b/corba/.hgtags index b2131f7d5a7..ae9a9aab2e5 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -437,3 +437,6 @@ dc78a3dd6b3a4f11cdae8a3e3d160e6a78bc7838 jdk-9+175 c72e9d3823f04cb3ef3166646dfea9e4c2769133 jdk-9+177 15f59cfc6fbe9387423fb173e962265c7b5d357e jdk-10+15 b82b62ed5debda2d98dda597506ef29cf947fbae jdk-10+16 +9c1e9712648921ae389d623042d22561fad82d75 jdk-9+178 +24390da83c5ee9e23ceafbcaff4460a01e37bb3a jdk-9+179 +50ff1fd66362f212a8db6de76089d9d0ffa4df0f jdk-10+17 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 7ca2b94dc77..93330098b14 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -597,3 +597,6 @@ e920b4d008d914f3414bd4630b58837cf0b7f08d jdk-10+14 1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177 c1f3649a3a42f124b418a5a916dbad13d059b757 jdk-10+15 2fe2a593e8ebf3a9e4dcd9ba3333a7b43126589d jdk-10+16 +9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178 +d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179 +73e2cb8700bfa51304bd4b02f224620859a3f600 jdk-10+17 diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index cf3fd216364..cd2174a67c3 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -14394,7 +14394,7 @@ instruct compL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2) ins_pipe(icmp_reg_reg); %} -instruct compL_reg_immI0(rFlagsReg cr, iRegL op1, immI0 zero) +instruct compL_reg_immL0(rFlagsReg cr, iRegL op1, immL0 zero) %{ match(Set cr (CmpL op1 zero)); @@ -14436,6 +14436,62 @@ instruct compL_reg_immL(rFlagsReg cr, iRegL op1, immL op2) ins_pipe(icmp_reg_imm); %} +instruct compUL_reg_reg(rFlagsRegU cr, iRegL op1, iRegL op2) +%{ + match(Set cr (CmpUL op1 op2)); + + effect(DEF cr, USE op1, USE op2); + + ins_cost(INSN_COST); + format %{ "cmp $op1, $op2" %} + + ins_encode(aarch64_enc_cmp(op1, op2)); + + ins_pipe(icmp_reg_reg); +%} + +instruct compUL_reg_immL0(rFlagsRegU cr, iRegL op1, immL0 zero) +%{ + match(Set cr (CmpUL op1 zero)); + + effect(DEF cr, USE op1); + + ins_cost(INSN_COST); + format %{ "tst $op1" %} + + ins_encode(aarch64_enc_cmp_imm_addsub(op1, zero)); + + ins_pipe(icmp_reg_imm); +%} + +instruct compUL_reg_immLAddSub(rFlagsRegU cr, iRegL op1, immLAddSub op2) +%{ + match(Set cr (CmpUL op1 op2)); + + effect(DEF cr, USE op1); + + ins_cost(INSN_COST); + format %{ "cmp $op1, $op2" %} + + ins_encode(aarch64_enc_cmp_imm_addsub(op1, op2)); + + ins_pipe(icmp_reg_imm); +%} + +instruct compUL_reg_immL(rFlagsRegU cr, iRegL op1, immL op2) +%{ + match(Set cr (CmpUL op1 op2)); + + effect(DEF cr, USE op1); + + ins_cost(INSN_COST * 2); + format %{ "cmp $op1, $op2" %} + + ins_encode(aarch64_enc_cmp_imm(op1, op2)); + + ins_pipe(icmp_reg_imm); +%} + instruct compP_reg_reg(rFlagsRegU cr, iRegP op1, iRegP op2) %{ match(Set cr (CmpP op1 op2)); @@ -14920,7 +14976,7 @@ instruct cmpUI_imm0_branch(cmpOpUEqNeLtGe cmp, iRegIorL2I op1, immI0 op2, label %} instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{ - match(If cmp (CmpU op1 op2)); + match(If cmp (CmpUL op1 op2)); effect(USE labl); ins_cost(BRANCH_COST); diff --git a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp index 5a5d8ac4f95..e477b8c3a48 100644 --- a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp @@ -49,12 +49,11 @@ define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FLOATPRESSURE, 64); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); -define_pd_global(intx, INTPRESSURE, 25); +define_pd_global(intx, INTPRESSURE, 24); define_pd_global(intx, InteriorEntryAlignment, 16); define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); -define_pd_global(intx, PostLoopMultiversioning, false); // InitialCodeCacheSize derived from specjbb2000 run. define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize define_pd_global(intx, CodeCacheExpansionSize, 64*K); diff --git a/hotspot/src/cpu/arm/vm/arm.ad b/hotspot/src/cpu/arm/vm/arm.ad index ef84124ef43..f4e5bd324cd 100644 --- a/hotspot/src/cpu/arm/vm/arm.ad +++ b/hotspot/src/cpu/arm/vm/arm.ad @@ -2695,6 +2695,30 @@ operand flagsRegL_LEGT() %{ format %{ "apsr_L_LEGT" %} interface(REG_INTER); %} + +operand flagsRegUL_LTGE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + + format %{ "apsr_UL_LTGE" %} + interface(REG_INTER); +%} + +operand flagsRegUL_EQNE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + + format %{ "apsr_UL_EQNE" %} + interface(REG_INTER); +%} + +operand flagsRegUL_LEGT() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + + format %{ "apsr_UL_LEGT" %} + interface(REG_INTER); +%} #endif // Condition Code Register, floating comparisons, unordered same as "less". @@ -3249,6 +3273,39 @@ operand cmpOpL_commute() %{ %} %} +operand cmpOpUL() %{ + match(Bool); + + format %{ "UL" %} + interface(COND_INTER) %{ + equal(0x0); + not_equal(0x1); + less(0x3); + greater_equal(0x2); + less_equal(0x9); + greater(0x8); + overflow(0x0); // unsupported/unimplemented + no_overflow(0x0); // unsupported/unimplemented + %} +%} + +operand cmpOpUL_commute() %{ + match(Bool); + + format %{ "UL" %} + interface(COND_INTER) %{ + equal(0x0); + not_equal(0x1); + less(0x8); + greater_equal(0x9); + less_equal(0x2); + greater(0x3); + overflow(0x0); // unsupported/unimplemented + no_overflow(0x0); // unsupported/unimplemented + %} +%} + + //----------OPERAND CLASSES---------------------------------------------------- // Operand Classes are groups of operands that are used to simplify // instruction definitions by not requiring the AD writer to specify separate @@ -10467,6 +10524,17 @@ instruct compL_reg_reg(flagsReg xcc, iRegL op1, iRegL op2) %} ins_pipe(ialu_cconly_reg_reg); %} + +instruct compUL_iReg(flagsRegU xcc, iRegL op1, iRegL op2) %{ + match(Set xcc (CmpUL op1 op2)); + + size(4); + format %{ "CMP $op1,$op2\t! unsigned long" %} + ins_encode %{ + __ cmp($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_cconly_reg_reg); +%} #else instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ match(Set xcc (CmpL op1 op2)); @@ -10481,6 +10549,20 @@ instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %} ins_pipe(ialu_cconly_reg_reg); %} + +instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2, TEMP tmp); + + size(8); + format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t" + "SBCS $tmp,$op1.hi,$op2.hi" %} + ins_encode %{ + __ subs($tmp$$Register, $op1$$Register, $op2$$Register); + __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor()); + %} + ins_pipe(ialu_cconly_reg_reg); +%} #endif #ifdef AARCH64 @@ -10496,6 +10578,19 @@ instruct compL_reg_con(flagsReg xcc, iRegL op1, aimmL con) %{ ins_pipe(ialu_cconly_reg_imm); %} + +instruct compUL_reg_con(flagsRegU xcc, iRegL op1, aimmL con) %{ + match(Set xcc (CmpUL op1 con)); + effect(DEF xcc, USE op1, USE con); + + size(8); + format %{ "CMP $op1,$con\t\t! unsigned long" %} + ins_encode %{ + __ cmp($op1$$Register, $con$$constant); + %} + + ins_pipe(ialu_cconly_reg_imm); +%} #else instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{ match(Set xcc (CmpL op1 op2)); @@ -10575,6 +10670,85 @@ instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL ins_pipe(ialu_cconly_reg_reg); %} + +instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2); + + size(8); + format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t" + "TEQ.eq $op1.lo,$op2.lo" %} + ins_encode %{ + __ teq($op1$$Register->successor(), $op2$$Register->successor()); + __ teq($op1$$Register, $op2$$Register, eq); + %} + ins_pipe(ialu_cconly_reg_reg); +%} + +instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2, TEMP tmp); + + size(8); + format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t" + "SBCS $tmp,$op2.hi,$op1.hi" %} + ins_encode %{ + __ subs($tmp$$Register, $op2$$Register, $op1$$Register); + __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor()); + %} + ins_pipe(ialu_cconly_reg_reg); +%} + +// TODO: try immLRot2 instead, (0, $con$$constant) becomes +// (hi($con$$constant), lo($con$$constant)) becomes +instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ + match(Set xcc (CmpUL op1 con)); + effect(DEF xcc, USE op1, USE con, TEMP tmp); + + size(8); + format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" + "SBCS $tmp,$op1.hi,0" %} + ins_encode %{ + __ subs($tmp$$Register, $op1$$Register, $con$$constant); + __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0); + %} + + ins_pipe(ialu_cconly_reg_reg); +%} + +// TODO: try immLRot2 instead, (0, $con$$constant) becomes +// (hi($con$$constant), lo($con$$constant)) becomes +instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{ + match(Set xcc (CmpUL op1 con)); + effect(DEF xcc, USE op1, USE con); + + size(8); + format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t" + "TEQ.eq $op1.lo,$con" %} + ins_encode %{ + __ teq($op1$$Register->successor(), 0); + __ teq($op1$$Register, $con$$constant, eq); + %} + + ins_pipe(ialu_cconly_reg_reg); +%} + +// TODO: try immLRot2 instead, (0, $con$$constant) becomes +// (hi($con$$constant), lo($con$$constant)) becomes +instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{ + match(Set xcc (CmpUL op1 con)); + effect(DEF xcc, USE op1, USE con, TEMP tmp); + + size(8); + format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t" + "RSCS $tmp,$op1.hi,0" %} + ins_encode %{ + __ rsbs($tmp$$Register, $op1$$Register, $con$$constant); + __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0); + %} + + ins_pipe(ialu_cconly_reg_reg); +%} #endif /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */ @@ -11126,6 +11300,48 @@ instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{ %} ins_pipe(br_cc); %} + +instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{ + match(If cmp xcc); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + + size(4); + ins_cost(BRANCH_COST); + format %{ "B$cmp $xcc,$labl" %} + ins_encode %{ + __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(br_cc); +%} + +instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{ + match(If cmp xcc); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + + size(4); + ins_cost(BRANCH_COST); + format %{ "B$cmp $xcc,$labl" %} + ins_encode %{ + __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(br_cc); +%} + +instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{ + match(If cmp xcc); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); + + size(4); + ins_cost(BRANCH_COST); + format %{ "B$cmp $xcc,$labl" %} + ins_encode %{ + __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode)); + %} + ins_pipe(br_cc); +%} #endif instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{ diff --git a/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp b/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp index 4b424ed0af1..2c0919660b9 100644 --- a/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp +++ b/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp @@ -70,7 +70,6 @@ define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1 define_pd_global(intx, LoopPercentProfileLimit, 10); -define_pd_global(intx, PostLoopMultiversioning, false); define_pd_global(intx, MinJumpTableSize, 16); // Peephole and CISC spilling both break the graph, and so makes the diff --git a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp index e755e982b9e..fd61e5ddb56 100644 --- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp @@ -55,7 +55,6 @@ define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); -define_pd_global(intx, PostLoopMultiversioning, false); // Peephole and CISC spilling both break the graph, and so make the // scheduler sick. diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 6c3d9cf1fda..f9534b65bff 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -11048,6 +11048,29 @@ instruct cmpL_reg_imm16(flagsReg crx, iRegLsrc src1, immL16 src2) %{ ins_pipe(pipe_class_compare); %} +// Added CmpUL for LoopPredicate. +instruct cmpUL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{ + match(Set crx (CmpUL src1 src2)); + format %{ "CMPLD $crx, $src1, $src2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); + __ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +instruct cmpUL_reg_imm16(flagsReg crx, iRegLsrc src1, uimmL16 src2) %{ + match(Set crx (CmpUL src1 src2)); + format %{ "CMPLDI $crx, $src1, $src2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmpli); + __ cmpldi($crx$$CondRegister, $src1$$Register, $src2$$constant); + %} + ins_pipe(pipe_class_compare); +%} + instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zero) %{ match(Set cr0 (CmpL (AndL src1 src2) zero)); // r0 is killed diff --git a/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp b/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp index 2c00ec86521..86a1d102e21 100644 --- a/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp +++ b/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp @@ -56,7 +56,6 @@ define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); -define_pd_global(intx, PostLoopMultiversioning, false); define_pd_global(intx, MinJumpTableSize, 18); // Peephole and CISC spilling both break the graph, and so makes the diff --git a/hotspot/src/cpu/s390/vm/s390.ad b/hotspot/src/cpu/s390/vm/s390.ad index fd188525c46..7daf348c0af 100644 --- a/hotspot/src/cpu/s390/vm/s390.ad +++ b/hotspot/src/cpu/s390/vm/s390.ad @@ -8475,6 +8475,24 @@ instruct compL_reg_memI(iRegL dst, memory src, flagsReg cr)%{ %} // LONG unsigned +// Added CmpUL for LoopPredicate. +instruct compUL_reg_reg(flagsReg cr, iRegL op1, iRegL op2) %{ + match(Set cr (CmpUL op1 op2)); + size(4); + format %{ "CLGR $op1,$op2\t # long" %} + opcode(CLGR_ZOPC); + ins_encode(z_rreform(op1, op2)); + ins_pipe(pipe_class_dummy); +%} + +instruct compUL_reg_imm32(flagsReg cr, iRegL op1, uimmL32 con) %{ + match(Set cr (CmpUL op1 con)); + size(6); + format %{ "CLGFI $op1,$con" %} + opcode(CLGFI_ZOPC); + ins_encode(z_rilform_unsigned(op1, con)); + ins_pipe(pipe_class_dummy); +%} // PTR unsigned diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 10e6799f21e..7e7cddc54da 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -53,7 +53,6 @@ define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1 define_pd_global(intx, LoopPercentProfileLimit, 10); -define_pd_global(intx, PostLoopMultiversioning, false); define_pd_global(intx, MinJumpTableSize, 5); // Peephole and CISC spilling both break the graph, and so makes the diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index fa0bedae739..35e90204b68 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -3403,6 +3403,16 @@ operand immU12() %{ interface(CONST_INTER); %} +// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13) +operand immUL12() %{ + predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long())); + match(ConL); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Integer Immediate non-negative operand immU31() %{ @@ -3936,6 +3946,15 @@ operand flagsRegL() %{ interface(REG_INTER); %} +// Condition Code Register, unsigned long comparisons. +operand flagsRegUL() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + + format %{ "xcc_UL" %} + interface(REG_INTER); +%} + // Condition Code Register, floating comparisons, unordered same as "less". operand flagsRegF() %{ constraint(ALLOC_IN_RC(float_flags)); @@ -8797,6 +8816,17 @@ instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ ins_pipe(ialu_cconly_reg_reg); %} +instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2); + + size(4); + format %{ "CMP $op1,$op2\t! unsigned long" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0)); + ins_pipe(ialu_cconly_reg_reg); +%} + instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{ match(Set icc (CmpI op1 op2)); effect( DEF icc, USE op1 ); @@ -8883,6 +8913,17 @@ instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{ ins_pipe(ialu_cconly_reg_imm); %} +instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2); + + size(4); + format %{ "CMP $op1,$op2\t! unsigned long" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0)); + ins_pipe(ialu_cconly_reg_imm); +%} + // Compare Pointers instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ match(Set pcc (CmpP op1 op2)); @@ -9256,6 +9297,44 @@ instruct cmpU_imm_branch(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU ins_pipe(cmp_br_reg_imm); %} +instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + effect(USE labl, KILL xcc); + + size(12); + ins_cost(BRANCH_COST); + format %{ "CMP $op1,$op2\t! unsigned long\n\t" + "BP$cmp $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + __ cmp($op1$$Register, $op2$$Register); + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_pipe(cmp_br_reg_reg); +%} + +instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + effect(USE labl, KILL xcc); + + size(12); + ins_cost(BRANCH_COST); + format %{ "CMP $op1,$op2\t! unsigned long\n\t" + "BP$cmp $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + __ cmp($op1$$Register, $op2$$constant); + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_pipe(cmp_br_reg_imm); +%} + instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{ match(If cmp (CmpL op1 op2)); effect(USE labl, KILL xcc); @@ -9484,6 +9563,42 @@ instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, fla ins_pipe(cbcond_reg_imm); %} +instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + predicate(UseCBCond); + effect(USE labl, KILL xcc); + + size(4); + ins_cost(BRANCH_COST); + format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %} + ins_encode %{ + Label* L = $labl$$label; + assert(__ use_cbcond(*L), "back to back cbcond"); + __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L); + %} + ins_short_branch(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); + ins_pipe(cbcond_reg_reg); +%} + +instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + predicate(UseCBCond); + effect(USE labl, KILL xcc); + + size(4); + ins_cost(BRANCH_COST); + format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %} + ins_encode %{ + Label* L = $labl$$label; + assert(__ use_cbcond(*L), "back to back cbcond"); + __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L); + %} + ins_short_branch(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); + ins_pipe(cbcond_reg_imm); +%} + instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{ match(If cmp (CmpL op1 op2)); predicate(UseCBCond); @@ -9722,6 +9837,25 @@ instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ ins_pipe(br_cc); %} +instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{ + match(If cmp xcc); + effect(USE labl); + + size(8); + ins_cost(BRANCH_COST); + format %{ "BP$cmp $xcc,$labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_avoid_back_to_back(AVOID_BEFORE); + ins_pipe(br_cc); +%} + // Manifest a CmpL3 result in an integer register. Very painful. // This is the test to avoid. instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index c193029ea73..e805cad0c1a 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, LoopPercentProfileLimit, 30); -define_pd_global(intx, PostLoopMultiversioning, true); #ifdef AMD64 define_pd_global(intx, INTPRESSURE, 13); define_pd_global(intx, FLOATPRESSURE, 14); diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 5673abb4448..748a1af0326 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -116,7 +116,7 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseStoreImmI16, true, \ "Use store immediate 16-bits value instruction on x86") \ \ - product(intx, UseAVX, 99, \ + product(intx, UseAVX, 2, \ "Highest supported AVX instructions set on x86/x64") \ range(0, 99) \ \ diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index e82361ba810..3f045554ba2 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -4030,6 +4030,26 @@ operand flagsReg_long_LEGT() %{ interface(REG_INTER); %} +// Condition Code Register used by unsigned long compare +operand flagsReg_ulong_LTGE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_LTGE" %} + interface(REG_INTER); +%} +operand flagsReg_ulong_EQNE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_EQNE" %} + interface(REG_INTER); +%} +operand flagsReg_ulong_LEGT() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_LEGT" %} + interface(REG_INTER); +%} + // Float register operands operand regDPR() %{ predicate( UseSSE < 2 ); @@ -4588,7 +4608,7 @@ operand cmpOp_fcmov() %{ %} %} -// Comparision Code used in long compares +// Comparison Code used in long compares operand cmpOp_commute() %{ match(Bool); @@ -4605,6 +4625,23 @@ operand cmpOp_commute() %{ %} %} +// Comparison Code used in unsigned long compares +operand cmpOpU_commute() %{ + match(Bool); + + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x7, "nbe"); + greater_equal(0x6, "be"); + less_equal(0x3, "nb"); + greater(0x2, "b"); + overflow(0x0, "o"); + no_overflow(0x1, "no"); + %} +%} + //----------OPERAND CLASSES---------------------------------------------------- // Operand Classes are groups of operands that are used as to simplify // instruction definitions by not requiring the AD writer to specify separate @@ -12639,6 +12676,44 @@ instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for LT or GE +// compares. Can be used for LE or GT compares by reversing arguments. +// NOT GOOD FOR EQ/NE tests. +instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{ + match(Set flags (CmpUL src zero)); + ins_cost(100); + format %{ "TEST $src.hi,$src.hi" %} + opcode(0x85); + ins_encode(OpcP, RegReg_Hi2(src, src)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Manifest a CmpUL result in the normal flags. Only good for LT or GE +// compares. Can be used for LE or GT compares by reversing arguments. +// NOT GOOD FOR EQ/NE tests. +instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{ + match(Set flags (CmpUL src1 src2)); + effect(TEMP tmp); + ins_cost(300); + format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t" + "MOV $tmp,$src1.hi\n\t" + "SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %} + ins_encode(long_cmp_flags2(src1, src2, tmp)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compares reg < zero/req OR reg >= zero/req. +// Just a wrapper for a normal branch, plus the predicate test. +instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + expand %{ + jmpCon(cmp, flags, labl); // JLT or JGE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); @@ -12767,6 +12842,41 @@ instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares. +instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{ + match(Set flags (CmpUL src zero)); + effect(TEMP tmp); + ins_cost(200); + format %{ "MOV $tmp,$src.lo\n\t" + "OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %} + ins_encode(long_cmp_flags0(src, tmp)); + ins_pipe(ialu_reg_reg_long); +%} + +// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares. +instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{ + match(Set flags (CmpUL src1 src2)); + ins_cost(200+300); + format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t" + "JNE,s skip\n\t" + "CMP $src1.hi,$src2.hi\n\t" + "skip:\t" %} + ins_encode(long_cmp_flags1(src1, src2)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compare reg == zero/reg OR reg != zero/reg +// Just a wrapper for a normal branch, plus the predicate test. +instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + expand %{ + jmpCon(cmp, flags, labl); // JEQ or JNE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); @@ -12900,6 +13010,46 @@ instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares. +// Same as cmpUL_reg_flags_LEGT except must negate src +instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{ + match(Set flags (CmpUL src zero)); + effect(TEMP tmp); + ins_cost(300); + format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t" + "CMP $tmp,$src.lo\n\t" + "SBB $tmp,$src.hi\n\t" %} + ins_encode(long_cmp_flags3(src, tmp)); + ins_pipe(ialu_reg_reg_long); +%} + +// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares. +// Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands +// requires a commuted test to get the same result. +instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{ + match(Set flags (CmpUL src1 src2)); + effect(TEMP tmp); + ins_cost(300); + format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t" + "MOV $tmp,$src2.hi\n\t" + "SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %} + ins_encode(long_cmp_flags2( src2, src1, tmp)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compares reg < zero/req OR reg >= zero/req. +// Just a wrapper for a normal branch, plus the predicate test +instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); + ins_cost(300); + expand %{ + jmpCon(cmp, flags, labl); // JGT or JLE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 99ae5f5f738..41e3ab1fb9f 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -11518,6 +11518,48 @@ instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags) ins_pipe(pipe_slow); %} +// Unsigned long compare Instructions; really, same as signed long except they +// produce an rFlagsRegU instead of rFlagsReg. +instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2) +%{ + match(Set cr (CmpUL op1 op2)); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x3B); /* Opcode 3B /r */ + ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2)); + ins_pipe(ialu_cr_reg_reg); +%} + +instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2) +%{ + match(Set cr (CmpUL op1 op2)); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x81, 0x07); /* Opcode 81 /7 */ + ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2)); + ins_pipe(ialu_cr_reg_imm); +%} + +instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2) +%{ + match(Set cr (CmpUL op1 (LoadL op2))); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x3B); /* Opcode 3B /r */ + ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2)); + ins_pipe(ialu_cr_reg_mem); +%} + +instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero) +%{ + match(Set cr (CmpUL src zero)); + + format %{ "testq $src, $src\t# unsigned" %} + opcode(0x85); + ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src)); + ins_pipe(ialu_cr_reg_imm); +%} + //----------Max and Min-------------------------------------------------------- // Min Instructions diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index abae7a39549..ba759b73abb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.hotspot; import java.util.Formatter; +import java.util.Objects; /** * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API @@ -37,10 +38,11 @@ import java.util.Formatter; class JVMCIVersionCheck { private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 23; + private static final int JVMCI8_MIN_MINOR_VERSION = 26; - // Will be updated once an ea build with the required JVMCI API is available. - private static final int JVMCI9_MIN_EA_BUILD = 143; + // MAX_VALUE indicates that no current EA version is compatible with Graal. + // Note: Keep README.md in sync with the EA version support checked here. + private static final int JVMCI9_MIN_EA_BUILD = 176; private static void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); @@ -77,13 +79,27 @@ class JVMCIVersionCheck { start += "-jvmci-".length(); int end = vmVersion.indexOf('.', start); if (end > 0) { - int major = Integer.parseInt(vmVersion.substring(start, end)); + int major; + try { + major = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion); + return; + } start = end + 1; end = start; while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { end++; } - int minor = Integer.parseInt(vmVersion.substring(start, end)); + int minor; + try { + minor = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion); + return; + } if (major >= JVMCI8_MIN_MAJOR_VERSION && minor >= JVMCI8_MIN_MINOR_VERSION) { return; } @@ -96,7 +112,7 @@ class JVMCIVersionCheck { "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion); } else { if (vmVersion.contains("SNAPSHOT")) { - // The snapshot of http://hg.openjdk.java.net/jdk9/hs tip is expected to work + // The snapshot of http://hg.openjdk.java.net/jdk9/dev tip is expected to work return; } if (vmVersion.contains("internal")) { @@ -104,23 +120,36 @@ class JVMCIVersionCheck { return; } // http://openjdk.java.net/jeps/223 - // Only support EA builds until GA is available - if (vmVersion.startsWith("9-ea+")) { - int start = "9-ea+".length(); + if (vmVersion.startsWith("9+")) { + int start = "9+".length(); int end = start; end = start; while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { end++; } - int build = Integer.parseInt(vmVersion.substring(start, end)); + int build; + try { + build = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion); + return; + } if (build >= JVMCI9_MIN_EA_BUILD) { return; } - failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + // Using Object.equals suppresses Eclipse's "Dead code" warning. + // Unfortunately @SuppressWarnings("unused") can only be applied at method level. + if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) { + failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n"); + } else { + failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + } return; + } else { + // Graal will be compatible with all JDK versions as of 9 GA + // until a JVMCI API change is made in a 9u or later release. } - failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + - "Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion); } } diff --git a/hotspot/src/share/vm/adlc/archDesc.cpp b/hotspot/src/share/vm/adlc/archDesc.cpp index 18cfeb43ccd..56a888224bb 100644 --- a/hotspot/src/share/vm/adlc/archDesc.cpp +++ b/hotspot/src/share/vm/adlc/archDesc.cpp @@ -1166,6 +1166,7 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) { || strcmp(idealName,"CmpP") == 0 || strcmp(idealName,"CmpN") == 0 || strcmp(idealName,"CmpL") == 0 + || strcmp(idealName,"CmpUL") == 0 || strcmp(idealName,"CmpD") == 0 || strcmp(idealName,"CmpF") == 0 || strcmp(idealName,"FastLock") == 0 diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 49bcbf42ae8..3ae2e20e146 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -181,7 +181,7 @@ "Map number of unrolls for main loop via " \ "Superword Level Parallelism analysis") \ \ - diagnostic_pd(bool, PostLoopMultiversioning, \ + experimental(bool, PostLoopMultiversioning, false, \ "Multi versioned post loops to eliminate range checks") \ \ notproduct(bool, TraceSuperWordLoopUnrollAnalysis, false, \ diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 06d754ffd78..06afc1f1e30 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -81,6 +81,7 @@ macro(CmpL3) macro(CmpLTMask) macro(CmpP) macro(CmpU) +macro(CmpUL) macro(CompareAndSwapB) macro(CompareAndSwapS) macro(CompareAndSwapI) diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp index 7f10a7d980a..243b20d0173 100644 --- a/hotspot/src/share/vm/opto/loopPredicate.cpp +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp @@ -29,6 +29,7 @@ #include "opto/connode.hpp" #include "opto/convertnode.hpp" #include "opto/loopnode.hpp" +#include "opto/matcher.hpp" #include "opto/mulnode.hpp" #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" @@ -629,45 +630,138 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari // max(scale*i + offset) = scale*init + offset BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl, int scale, Node* offset, - Node* init, Node* limit, Node* stride, - Node* range, bool upper) { + Node* init, Node* limit, jint stride, + Node* range, bool upper, bool &overflow) { + jint con_limit = limit->is_Con() ? limit->get_int() : 0; + jint con_init = init->is_Con() ? init->get_int() : 0; + jint con_offset = offset->is_Con() ? offset->get_int() : 0; + stringStream* predString = NULL; if (TraceLoopPredicate) { predString = new stringStream(); predString->print("rc_predicate "); } - Node* max_idx_expr = init; - int stride_con = stride->get_int(); - if ((stride_con > 0) == (scale > 0) == upper) { - // Limit is not exact. - // Calculate exact limit here. - // Note, counted loop's test is '<' or '>'. - limit = exact_limit(loop); - max_idx_expr = new SubINode(limit, stride); + overflow = false; + Node* max_idx_expr = NULL; + const TypeInt* idx_type = TypeInt::INT; + if ((stride > 0) == (scale > 0) == upper) { + if (TraceLoopPredicate) { + predString->print(limit->is_Con() ? "(%d " : "(limit ", con_limit); + predString->print("- %d) ", stride); + } + // Check if (limit - stride) may overflow + const TypeInt* limit_type = _igvn.type(limit)->isa_int(); + jint limit_lo = limit_type->_lo; + jint limit_hi = limit_type->_hi; + if ((stride > 0 && (java_subtract(limit_lo, stride) < limit_lo)) || + (stride < 0 && (java_subtract(limit_hi, stride) > limit_hi))) { + // No overflow possible + ConINode* con_stride = _igvn.intcon(stride); + set_ctrl(con_stride, C->root()); + max_idx_expr = new SubINode(limit, con_stride); + idx_type = TypeInt::make(limit_lo - stride, limit_hi - stride, limit_type->_widen); + } else { + // May overflow + overflow = true; + limit = new ConvI2LNode(limit); + register_new_node(limit, ctrl); + ConLNode* con_stride = _igvn.longcon(stride); + set_ctrl(con_stride, C->root()); + max_idx_expr = new SubLNode(limit, con_stride); + } register_new_node(max_idx_expr, ctrl); - if (TraceLoopPredicate) predString->print("(limit - stride) "); } else { - if (TraceLoopPredicate) predString->print("init "); + if (TraceLoopPredicate) { + predString->print(init->is_Con() ? "%d " : "init ", con_init); + } + idx_type = _igvn.type(init)->isa_int(); + max_idx_expr = init; } if (scale != 1) { ConNode* con_scale = _igvn.intcon(scale); set_ctrl(con_scale, C->root()); - max_idx_expr = new MulINode(max_idx_expr, con_scale); + if (TraceLoopPredicate) { + predString->print("* %d ", scale); + } + // Check if (scale * max_idx_expr) may overflow + const TypeInt* scale_type = TypeInt::make(scale); + MulINode* mul = new MulINode(max_idx_expr, con_scale); + idx_type = (TypeInt*)mul->mul_ring(idx_type, scale_type); + if (overflow || TypeInt::INT->higher_equal(idx_type)) { + // May overflow + mul->destruct(); + if (!overflow) { + max_idx_expr = new ConvI2LNode(max_idx_expr); + register_new_node(max_idx_expr, ctrl); + } + overflow = true; + con_scale = _igvn.longcon(scale); + set_ctrl(con_scale, C->root()); + max_idx_expr = new MulLNode(max_idx_expr, con_scale); + } else { + // No overflow possible + max_idx_expr = mul; + } register_new_node(max_idx_expr, ctrl); - if (TraceLoopPredicate) predString->print("* %d ", scale); } - if (offset && (!offset->is_Con() || offset->get_int() != 0)){ - max_idx_expr = new AddINode(max_idx_expr, offset); + if (offset && (!offset->is_Con() || con_offset != 0)){ + if (TraceLoopPredicate) { + predString->print(offset->is_Con() ? "+ %d " : "+ offset", con_offset); + } + // Check if (max_idx_expr + offset) may overflow + const TypeInt* offset_type = _igvn.type(offset)->isa_int(); + jint lo = java_add(idx_type->_lo, offset_type->_lo); + jint hi = java_add(idx_type->_hi, offset_type->_hi); + if (overflow || (lo > hi) || + ((idx_type->_lo & offset_type->_lo) < 0 && lo >= 0) || + ((~(idx_type->_hi | offset_type->_hi)) < 0 && hi < 0)) { + // May overflow + if (!overflow) { + max_idx_expr = new ConvI2LNode(max_idx_expr); + register_new_node(max_idx_expr, ctrl); + } + overflow = true; + offset = new ConvI2LNode(offset); + register_new_node(offset, ctrl); + max_idx_expr = new AddLNode(max_idx_expr, offset); + } else { + // No overflow possible + max_idx_expr = new AddINode(max_idx_expr, offset); + } register_new_node(max_idx_expr, ctrl); - if (TraceLoopPredicate) - if (offset->is_Con()) predString->print("+ %d ", offset->get_int()); - else predString->print("+ offset "); } - CmpUNode* cmp = new CmpUNode(max_idx_expr, range); + CmpNode* cmp = NULL; + if (overflow) { + // Integer expressions may overflow, do long comparison + range = new ConvI2LNode(range); + register_new_node(range, ctrl); + if (!Matcher::has_match_rule(Op_CmpUL)) { + // We don't support unsigned long comparisons. Set 'max_idx_expr' + // to max_julong if < 0 to make the signed comparison fail. + ConINode* sign_pos = _igvn.intcon(BitsPerLong - 1); + set_ctrl(sign_pos, C->root()); + Node* sign_bit_mask = new RShiftLNode(max_idx_expr, sign_pos); + register_new_node(sign_bit_mask, ctrl); + // OR with sign bit to set all bits to 1 if negative (otherwise no change) + max_idx_expr = new OrLNode(max_idx_expr, sign_bit_mask); + register_new_node(max_idx_expr, ctrl); + // AND with 0x7ff... to unset the sign bit + ConLNode* remove_sign_mask = _igvn.longcon(max_jlong); + set_ctrl(remove_sign_mask, C->root()); + max_idx_expr = new AndLNode(max_idx_expr, remove_sign_mask); + register_new_node(max_idx_expr, ctrl); + + cmp = new CmpLNode(max_idx_expr, range); + } else { + cmp = new CmpULNode(max_idx_expr, range); + } + } else { + cmp = new CmpUNode(max_idx_expr, range); + } register_new_node(cmp, ctrl); BoolNode* bol = new BoolNode(cmp, BoolTest::lt); register_new_node(bol, ctrl); @@ -814,28 +908,30 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { assert(ok, "must be index expression"); Node* init = cl->init_trip(); - Node* limit = cl->limit(); - Node* stride = cl->stride(); + // Limit is not exact. + // Calculate exact limit here. + // Note, counted loop's test is '<' or '>'. + Node* limit = exact_limit(loop); + int stride = cl->stride()->get_int(); // Build if's for the upper and lower bound tests. The // lower_bound test will dominate the upper bound test and all // cloned or created nodes will use the lower bound test as // their declared control. - ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode()); - ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode()); - assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); - Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); // Perform cloning to keep Invariance state correct since the // late schedule will place invariant things in the loop. + Node *ctrl = predicate_proj->in(0)->as_If()->in(0); rng = invar.clone(rng, ctrl); if (offset && offset != zero) { assert(invar.is_invariant(offset), "offset must be loop invariant"); offset = invar.clone(offset, ctrl); } + // If predicate expressions may overflow in the integer range, longs are used. + bool overflow = false; // Test the lower bound - BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false); + BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow); // Negate test if necessary bool negated = false; if (proj->_con != predicate_proj->_con) { @@ -843,19 +939,22 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { register_new_node(lower_bound_bol, ctrl); negated = true; } + ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode()); IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); _igvn.hash_delete(lower_bound_iff); lower_bound_iff->set_req(1, lower_bound_bol); if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx); // Test the upper bound - BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true); + BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow); negated = false; if (proj->_con != predicate_proj->_con) { upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate()); register_new_node(upper_bound_bol, ctrl); negated = true; } + ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode()); + assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); _igvn.hash_delete(upper_bound_iff); upper_bound_iff->set_req(1, upper_bound_bol); diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index 3419b786e03..70168186cca 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -983,8 +983,8 @@ public: // Construct a range check for a predicate if BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl, int scale, Node* offset, - Node* init, Node* limit, Node* stride, - Node* range, bool upper); + Node* init, Node* limit, jint stride, + Node* range, bool upper, bool &overflow); // Implementation of the loop predication to promote checks outside the loop bool loop_predication_impl(IdealLoopTree *loop); diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index e0164274f2d..cf9e4cf7323 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -1982,6 +1982,7 @@ void Scheduling::AddNodeToAvailableList(Node *n) { if( last->is_MachIf() && last->in(1) == n && ( op == Op_CmpI || op == Op_CmpU || + op == Op_CmpUL || op == Op_CmpP || op == Op_CmpF || op == Op_CmpD || diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index 2e2597f6076..694dda17367 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.cpp @@ -738,6 +738,60 @@ const Type *CmpLNode::sub( const Type *t1, const Type *t2 ) const { return TypeInt::CC; // else use worst case results } + +// Simplify a CmpUL (compare 2 unsigned longs) node, based on local information. +// If both inputs are constants, compare them. +const Type* CmpULNode::sub(const Type* t1, const Type* t2) const { + assert(!t1->isa_ptr(), "obsolete usage of CmpUL"); + + // comparing two unsigned longs + const TypeLong* r0 = t1->is_long(); // Handy access + const TypeLong* r1 = t2->is_long(); + + // Current installed version + // Compare ranges for non-overlap + julong lo0 = r0->_lo; + julong hi0 = r0->_hi; + julong lo1 = r1->_lo; + julong hi1 = r1->_hi; + + // If either one has both negative and positive values, + // it therefore contains both 0 and -1, and since [0..-1] is the + // full unsigned range, the type must act as an unsigned bottom. + bool bot0 = ((jlong)(lo0 ^ hi0) < 0); + bool bot1 = ((jlong)(lo1 ^ hi1) < 0); + + if (bot0 || bot1) { + // All unsigned values are LE -1 and GE 0. + if (lo0 == 0 && hi0 == 0) { + return TypeInt::CC_LE; // 0 <= bot + } else if ((jlong)lo0 == -1 && (jlong)hi0 == -1) { + return TypeInt::CC_GE; // -1 >= bot + } else if (lo1 == 0 && hi1 == 0) { + return TypeInt::CC_GE; // bot >= 0 + } else if ((jlong)lo1 == -1 && (jlong)hi1 == -1) { + return TypeInt::CC_LE; // bot <= -1 + } + } else { + // We can use ranges of the form [lo..hi] if signs are the same. + assert(lo0 <= hi0 && lo1 <= hi1, "unsigned ranges are valid"); + // results are reversed, '-' > '+' for unsigned compare + if (hi0 < lo1) { + return TypeInt::CC_LT; // smaller + } else if (lo0 > hi1) { + return TypeInt::CC_GT; // greater + } else if (hi0 == lo1 && lo0 == hi1) { + return TypeInt::CC_EQ; // Equal results + } else if (lo0 >= hi1) { + return TypeInt::CC_GE; + } else if (hi0 <= lo1) { + return TypeInt::CC_LE; + } + } + + return TypeInt::CC; // else use worst case results +} + //============================================================================= //------------------------------sub-------------------------------------------- // Simplify an CmpP (compare 2 pointers) node, based on local information. diff --git a/hotspot/src/share/vm/opto/subnode.hpp b/hotspot/src/share/vm/opto/subnode.hpp index 63bcd3cc2b4..a4adbcf5a47 100644 --- a/hotspot/src/share/vm/opto/subnode.hpp +++ b/hotspot/src/share/vm/opto/subnode.hpp @@ -198,6 +198,15 @@ public: virtual const Type *sub( const Type *, const Type * ) const; }; +//------------------------------CmpULNode--------------------------------------- +// Compare 2 unsigned long values, returning condition codes (-1, 0 or 1). +class CmpULNode : public CmpNode { +public: + CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { } + virtual int Opcode() const; + virtual const Type* sub(const Type*, const Type*) const; +}; + //------------------------------CmpL3Node-------------------------------------- // Compare 2 long values, returning integer value (-1, 0 or 1). class CmpL3Node : public CmpLNode { diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index dffb9198f3f..d8f0282fc88 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2013,6 +2013,7 @@ typedef RehashableHashtable RehashableSymbolHashtable; declare_c2_type(CmpPNode, CmpNode) \ declare_c2_type(CmpNNode, CmpNode) \ declare_c2_type(CmpLNode, CmpNode) \ + declare_c2_type(CmpULNode, CmpNode) \ declare_c2_type(CmpL3Node, CmpLNode) \ declare_c2_type(CmpFNode, CmpNode) \ declare_c2_type(CmpF3Node, CmpFNode) \ diff --git a/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java b/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java index 2c1b5e99bbf..c55a9add80f 100644 --- a/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java +++ b/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java @@ -26,7 +26,7 @@ * @bug 8154763 * @summary Tests PostLoopMultiversioning with RangeCheckElimination disabled. * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+PostLoopMultiversioning -XX:-RangeCheckElimination + * -XX:+UnlockExperimentalVMOptions -XX:+PostLoopMultiversioning -XX:-RangeCheckElimination * compiler.rangechecks.TestRangeCheckEliminationDisabled */ diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 2260afc0d68..f2420478bb0 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -437,3 +437,6 @@ ff293e39e83366c40a5687dacd1ccb2305ed2c1e jdk-10+12 332ad9f92632f56f337b8c40edef9a95a42b26bc jdk-9+177 02a876781a3a6193140591d92db7b95ca743eac2 jdk-10+15 d109d55cf642bf2b438624e81f94c18c168f9178 jdk-10+16 +0983b2dbe17ba4fed3af34e0512ca77a9845fe8a jdk-9+178 +87243a3131f79e8b3903eaca6b629abc48f08ace jdk-9+179 +97d6f14334cfd766f57c296a5a707c8a709aeff0 jdk-10+17 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMConfigurationException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMConfigurationException.java deleted file mode 100644 index dffbc9891a0..00000000000 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMConfigurationException.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * 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 - * - * 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, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.sun.org.apache.xml.internal.dtm; - -import javax.xml.transform.SourceLocator; - -/** - * Indicates a serious configuration error. - */ -public class DTMConfigurationException extends DTMException { - static final long serialVersionUID = -4607874078818418046L; - - /** - * Create a new DTMConfigurationException with no - * detail message. - */ - public DTMConfigurationException() { - super("Configuration Error"); - } - - /** - * Create a new DTMConfigurationException with - * the String specified as an error message. - * - * @param msg The error message for the exception. - */ - public DTMConfigurationException(String msg) { - super(msg); - } - - /** - * Create a new DTMConfigurationException with a - * given Exception base cause of the error. - * - * @param e The exception to be encapsulated in a - * DTMConfigurationException. - */ - public DTMConfigurationException(Throwable e) { - super(e); - } - - /** - * Create a new DTMConfigurationException with the - * given Exception base cause and detail message. - * - * @param msg The detail message. - * @param e The exception to be wrapped in a DTMConfigurationException - */ - public DTMConfigurationException(String msg, Throwable e) { - super(msg, e); - } - - /** - * Create a new DTMConfigurationException from a message and a Locator. - * - *

This constructor is especially useful when an application is - * creating its own exception from within a DocumentHandler - * callback.

- * - * @param message The error or warning message. - * @param locator The locator object for the error or warning. - */ - public DTMConfigurationException(String message, - SourceLocator locator) { - super(message, locator); - } - - /** - * Wrap an existing exception in a DTMConfigurationException. - * - * @param message The error or warning message, or null to - * use the message from the embedded exception. - * @param locator The locator object for the error or warning. - * @param e Any exception. - */ - public DTMConfigurationException(String message, - SourceLocator locator, - Throwable e) { - super(message, locator, e); - } -} diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java index 9e8f68ecb46..584827b795f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,124 +20,20 @@ package com.sun.org.apache.xml.internal.dtm; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.xml.transform.SourceLocator; - -import com.sun.org.apache.xml.internal.res.XMLErrorResources; -import com.sun.org.apache.xml.internal.res.XMLMessages; - - /** - * This class specifies an exceptional condition that occured + * This class specifies an exceptional condition that occurred * in the DTM module. */ public class DTMException extends RuntimeException { static final long serialVersionUID = -775576419181334734L; - /** Field locator specifies where the error occured. - * @serial */ - SourceLocator locator; - - /** - * Method getLocator retrieves an instance of a SourceLocator - * object that specifies where an error occured. - * - * @return A SourceLocator object, or null if none was specified. - */ - public SourceLocator getLocator() { - return locator; - } - - /** - * Method setLocator sets an instance of a SourceLocator - * object that specifies where an error occured. - * - * @param location A SourceLocator object, or null to clear the location. - */ - public void setLocator(SourceLocator location) { - locator = location; - } - - /** Field containedException specifies a wrapped exception. May be null. - * @serial */ - Throwable containedException; - - /** - * This method retrieves an exception that this exception wraps. - * - * @return An Throwable object, or null. - * @see #getCause - */ - public Throwable getException() { - return containedException; - } - - /** - * Returns the cause of this throwable or null if the - * cause is nonexistent or unknown. (The cause is the throwable that - * caused this throwable to get thrown.) - */ - public Throwable getCause() { - - return ((containedException == this) - ? null - : containedException); - } - - /** - * Initializes the cause of this throwable to the specified value. - * (The cause is the throwable that caused this throwable to get thrown.) - * - *

This method can be called at most once. It is generally called from - * within the constructor, or immediately after creating the - * throwable. If this throwable was created - * with {@link #DTMException(Throwable)} or - * {@link #DTMException(String,Throwable)}, this method cannot be called - * even once. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @return a reference to this Throwable instance. - * @throws IllegalArgumentException if cause is this - * throwable. (A throwable cannot - * be its own cause.) - * @throws IllegalStateException if this throwable was - * created with {@link #DTMException(Throwable)} or - * {@link #DTMException(String,Throwable)}, or this method has already - * been called on this throwable. - */ - public synchronized Throwable initCause(Throwable cause) { - - if ((this.containedException == null) && (cause != null)) { - throw new IllegalStateException(XMLMessages.createXMLMessage(XMLErrorResources.ER_CANNOT_OVERWRITE_CAUSE, null)); //"Can't overwrite cause"); - } - - if (cause == this) { - throw new IllegalArgumentException( - XMLMessages.createXMLMessage(XMLErrorResources.ER_SELF_CAUSATION_NOT_PERMITTED, null)); //"Self-causation not permitted"); - } - - this.containedException = cause; - - return this; - } - /** * Create a new DTMException. * * @param message The error or warning message. */ public DTMException(String message) { - super(message); - - this.containedException = null; - this.locator = null; } /** @@ -147,11 +42,7 @@ public class DTMException extends RuntimeException { * @param e The exception to be wrapped. */ public DTMException(Throwable e) { - - super(e.getMessage()); - - this.containedException = e; - this.locator = null; + super(e); } /** @@ -165,162 +56,6 @@ public class DTMException extends RuntimeException { * @param e Any exception */ public DTMException(String message, Throwable e) { - - super(((message == null) || (message.length() == 0)) - ? e.getMessage() - : message); - - this.containedException = e; - this.locator = null; + super(message, e); } - - /** - * Create a new DTMException from a message and a Locator. - * - *

This constructor is especially useful when an application is - * creating its own exception from within a DocumentHandler - * callback.

- * - * @param message The error or warning message. - * @param locator The locator object for the error or warning. - */ - public DTMException(String message, SourceLocator locator) { - - super(message); - - this.containedException = null; - this.locator = locator; } - - /** - * Wrap an existing exception in a DTMException. - * - * @param message The error or warning message, or null to - * use the message from the embedded exception. - * @param locator The locator object for the error or warning. - * @param e Any exception - */ - public DTMException(String message, SourceLocator locator, - Throwable e) { - - super(message); - - this.containedException = e; - this.locator = locator; - } - - /** - * Get the error message with location information - * appended. - */ - public String getMessageAndLocation() { - - StringBuffer sbuffer = new StringBuffer(); - String message = super.getMessage(); - - if (null != message) { - sbuffer.append(message); - } - - if (null != locator) { - String systemID = locator.getSystemId(); - int line = locator.getLineNumber(); - int column = locator.getColumnNumber(); - - if (null != systemID) { - sbuffer.append("; SystemID: "); - sbuffer.append(systemID); - } - - if (0 != line) { - sbuffer.append("; Line#: "); - sbuffer.append(line); - } - - if (0 != column) { - sbuffer.append("; Column#: "); - sbuffer.append(column); - } - } - - return sbuffer.toString(); - } - - /** - * Get the location information as a string. - * - * @return A string with location info, or null - * if there is no location information. - */ - public String getLocationAsString() { - - if (null != locator) { - StringBuffer sbuffer = new StringBuffer(); - String systemID = locator.getSystemId(); - int line = locator.getLineNumber(); - int column = locator.getColumnNumber(); - - if (null != systemID) { - sbuffer.append("; SystemID: "); - sbuffer.append(systemID); - } - - if (0 != line) { - sbuffer.append("; Line#: "); - sbuffer.append(line); - } - - if (0 != column) { - sbuffer.append("; Column#: "); - sbuffer.append(column); - } - - return sbuffer.toString(); - } else { - return null; - } - } - - /** - * Print the the trace of methods from where the error - * originated. This will trace all nested exception - * objects, as well as this object. - */ - public void printStackTrace() { - printStackTrace(new java.io.PrintWriter(System.err, true)); - } - - /** - * Print the the trace of methods from where the error - * originated. This will trace all nested exception - * objects, as well as this object. - * @param s The stream where the dump will be sent to. - */ - public void printStackTrace(java.io.PrintStream s) { - printStackTrace(new java.io.PrintWriter(s)); - } - - /** - * Print the the trace of methods from where the error - * originated. This will trace all nested exception - * objects, as well as this object. - * @param s The writer where the dump will be sent to. - */ - public void printStackTrace(java.io.PrintWriter s) { - - if (s == null) { - s = new java.io.PrintWriter(System.err, true); - } - - try { - String locInfo = getLocationAsString(); - - if (null != locInfo) { - s.println(locInfo); - } - - super.printStackTrace(s); - } catch (Throwable e) {} - - } -} diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java index 052dea8cf97..e2719e8e487 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,12 +20,8 @@ package com.sun.org.apache.xml.internal.dtm; -import com.sun.org.apache.xml.internal.res.XMLErrorResources; -import com.sun.org.apache.xml.internal.res.XMLMessages; import com.sun.org.apache.xml.internal.utils.PrefixResolver; import com.sun.org.apache.xml.internal.utils.XMLStringFactory; -import com.sun.org.apache.xalan.internal.utils.ObjectFactory; -import com.sun.org.apache.xalan.internal.utils.SecuritySupport; /** * A DTMManager instance can be used to create DTM and @@ -99,11 +94,11 @@ public abstract class DTMManager * * @return new DTMManager instance, never null. * - * @throws DTMConfigurationException + * @throws DTMException * if the implementation is not available or cannot be instantiated. */ public static DTMManager newInstance(XMLStringFactory xsf) - throws DTMConfigurationException + throws DTMException { final DTMManager factoryImpl = new com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault(); factoryImpl.setXMLStringFactory(xsf); @@ -315,20 +310,6 @@ public abstract class DTMManager // -------------------- private methods -------------------- - /** - * Temp debug code - this will be removed after we test everything - */ - private static boolean debug; - - static - { - try - { - debug = SecuritySupport.getSystemProperty("dtm.debug") != null; - } - catch (SecurityException ex){} - } - /** This value, set at compile time, controls how many bits of the * DTM node identifier numbers are used to identify a node within a * document, and thus sets the maximum number of nodes per @@ -394,47 +375,4 @@ public abstract class DTMManager { return IDENT_NODE_DEFAULT; } - - // - // Classes - // - - /** - * A configuration error. - * Originally in ObjectFactory. This is the only portion used in this package - */ - static class ConfigurationError - extends Error { - static final long serialVersionUID = 5122054096615067992L; - // - // Data - // - - /** Exception. */ - private Exception exception; - - // - // Constructors - // - - /** - * Construct a new instance with the specified detail string and - * exception. - */ - ConfigurationError(String msg, Exception x) { - super(msg); - this.exception = x; - } // (String,Exception) - - // - // Public methods - // - - /** Returns the exception associated to this error. */ - Exception getException() { - return exception; - } // getException():Exception - - } // class ConfigurationError - } 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 17961e79620..b84949d9ce3 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 @@ -34,7 +34,7 @@ import jdk.xml.internal.SecuritySupport; * The CatalogFeatures holds a collection of features and properties. * * - * + *
* * * @@ -55,7 +55,7 @@ import jdk.xml.internal.SecuritySupport; * * * - * + * * @@ -71,7 +71,7 @@ import jdk.xml.internal.SecuritySupport; * * * - * + * * * @@ -91,7 +91,7 @@ import jdk.xml.internal.SecuritySupport; * * * - * + * * @@ -111,7 +111,7 @@ import jdk.xml.internal.SecuritySupport; * * * - * + * * * diff --git a/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java index afa1d1809a9..21ed157f3bb 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java @@ -34,7 +34,7 @@ import com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl; /** * Factory that creates new {@code javax.xml.datatype} {@code Object}s that map XML to/from Java {@code Object}s. - *

+ *

* A new instance of the {@code DatatypeFactory} is created through the {@link #newInstance()} method * that uses the following implementation resolution mechanisms to determine an implementation: *

    diff --git a/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java b/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java index 3a440a5eafb..15c427e67ee 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java @@ -149,23 +149,13 @@ *
  1. xs:unsignedShort
  2. * * - *
    - * - * - * - *
    * @since 1.5 */ diff --git a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java index a81fde2989c..a90e29121a8 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java @@ -32,6 +32,8 @@ package javax.xml.transform; */ public class TransformerConfigurationException extends TransformerException { + private static final long serialVersionUID = 1285547467942875745L; + /** * Create a new TransformerConfigurationException with no * detail message. diff --git a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java index 78a058c322d..b5e7657dccf 100644 --- a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java +++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * 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,36 +27,47 @@ package javax.xml.transform; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.CodeSigner; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.Objects; /** - * This class specifies an exceptional condition that occured + * This class specifies an exceptional condition that occurred * during the transformation process. * * @since 1.4 */ public class TransformerException extends Exception { - /** Field locator specifies where the error occured */ + private static final long serialVersionUID = 975798773772956428L; + + /** Field locator specifies where the error occurred */ SourceLocator locator; /** * Method getLocator retrieves an instance of a SourceLocator - * object that specifies where an error occured. + * object that specifies where an error occurred. * * @return A SourceLocator object, or null if none was specified. */ public SourceLocator getLocator() { - return locator; + return this.locator; } /** * Method setLocator sets an instance of a SourceLocator - * object that specifies where an error occured. + * object that specifies where an error occurred. * * @param location A SourceLocator object, or null to clear the location. */ public void setLocator(SourceLocator location) { - locator = location; + this.locator = location; } /** Field containedException specifies a wrapped exception. May be null. */ @@ -76,7 +87,9 @@ public class TransformerException extends Exception { * Returns the cause of this throwable or null if the * cause is nonexistent or unknown. (The cause is the throwable that * caused this throwable to get thrown.) + * @return the cause, or null if unknown */ + @Override public Throwable getCause() { return ((containedException == this) @@ -108,6 +121,7 @@ public class TransformerException extends Exception { * {@link #TransformerException(String,Throwable)}, or this method has already * been called on this throwable. */ + @Override public synchronized Throwable initCause(Throwable cause) { // TransformerException doesn't set its cause (probably @@ -136,11 +150,7 @@ public class TransformerException extends Exception { * @param message The error or warning message. */ public TransformerException(String message) { - - super(message); - - this.containedException = null; - this.locator = null; + this(message, null, null); } /** @@ -149,11 +159,7 @@ public class TransformerException extends Exception { * @param e The exception to be wrapped. */ public TransformerException(Throwable e) { - - super(e.toString()); - - this.containedException = e; - this.locator = null; + this(null, null, e); } /** @@ -167,13 +173,7 @@ public class TransformerException extends Exception { * @param e Any exception */ public TransformerException(String message, Throwable e) { - - super(((message == null) || (message.length() == 0)) - ? e.toString() - : message); - - this.containedException = e; - this.locator = null; + this(message, null, e); } /** @@ -187,11 +187,7 @@ public class TransformerException extends Exception { * @param locator The locator object for the error or warning. */ public TransformerException(String message, SourceLocator locator) { - - super(message); - - this.containedException = null; - this.locator = locator; + this(message, locator, null); } /** @@ -204,8 +200,9 @@ public class TransformerException extends Exception { */ public TransformerException(String message, SourceLocator locator, Throwable e) { - - super(message); + super(((message == null) || (message.length() == 0)) + ? ((e == null) ? "" : e.toString()) + : message); this.containedException = e; this.locator = locator; @@ -219,34 +216,9 @@ public class TransformerException extends Exception { * location information appended. */ public String getMessageAndLocation() { - - StringBuffer sbuffer = new StringBuffer(); - String message = super.getMessage(); - - if (null != message) { - sbuffer.append(message); - } - - if (null != locator) { - String systemID = locator.getSystemId(); - int line = locator.getLineNumber(); - int column = locator.getColumnNumber(); - - if (null != systemID) { - sbuffer.append("; SystemID: "); - sbuffer.append(systemID); - } - - if (0 != line) { - sbuffer.append("; Line#: "); - sbuffer.append(line); - } - - if (0 != column) { - sbuffer.append("; Column#: "); - sbuffer.append(column); - } - } + StringBuilder sbuffer = new StringBuilder(); + sbuffer.append(Objects.toString(super.getMessage(), "")); + sbuffer.append(Objects.toString(getLocationAsString(), "")); return sbuffer.toString(); } @@ -258,9 +230,29 @@ public class TransformerException extends Exception { * if there is no location information. */ public String getLocationAsString() { + if (locator == null) { + return null; + } - if (null != locator) { - StringBuffer sbuffer = new StringBuffer(); + if (System.getSecurityManager() == null) { + return getLocationString(); + } else { + return AccessController.doPrivileged((PrivilegedAction) () -> + getLocationString(), + new AccessControlContext(new ProtectionDomain[] {getNonPrivDomain()})); + } + } + + /** + * Constructs the location string. + * @return the location string + */ + private String getLocationString() { + if (locator == null) { + return null; + } + + StringBuilder sbuffer = new StringBuilder(); String systemID = locator.getSystemId(); int line = locator.getLineNumber(); int column = locator.getColumnNumber(); @@ -281,9 +273,6 @@ public class TransformerException extends Exception { } return sbuffer.toString(); - } else { - return null; - } } /** @@ -291,6 +280,7 @@ public class TransformerException extends Exception { * originated. This will trace all nested exception * objects, as well as this object. */ + @Override public void printStackTrace() { printStackTrace(new java.io.PrintWriter(System.err, true)); } @@ -301,6 +291,7 @@ public class TransformerException extends Exception { * objects, as well as this object. * @param s The stream where the dump will be sent to. */ + @Override public void printStackTrace(java.io.PrintStream s) { printStackTrace(new java.io.PrintWriter(s)); } @@ -311,6 +302,7 @@ public class TransformerException extends Exception { * objects, as well as this object. * @param s The writer where the dump will be sent to. */ + @Override public void printStackTrace(java.io.PrintWriter s) { if (s == null) { @@ -358,11 +350,8 @@ public class TransformerException extends Exception { } else { exception = null; } - } catch (InvocationTargetException ite) { - exception = null; - } catch (IllegalAccessException iae) { - exception = null; - } catch (NoSuchMethodException nsme) { + } catch (InvocationTargetException | IllegalAccessException + | NoSuchMethodException e) { exception = null; } } @@ -371,4 +360,14 @@ public class TransformerException extends Exception { s.flush(); } } + + /** + * Creates a ProtectionDomain that has no permission. + * @return a ProtectionDomain + */ + private ProtectionDomain getNonPrivDomain() { + CodeSource nullSource = new CodeSource(null, (CodeSigner[]) null); + PermissionCollection noPermission = new Permissions(); + return new ProtectionDomain(nullSource, noPermission); +} } diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 477b7ca454a..2ab93a9d847 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -440,3 +440,6 @@ ea819b6009d33a72e6672bab6c101d51db0cfb4c jdk-9+176 b44a721aee3d3b2537754e559fe9ecccadea548b jdk-9+177 6d17fd0a5133a0dd916c77a9a24ae7f0ca402876 jdk-10+15 bc8289ce1ed3ed5fff62152ed46da3be0b60b7c3 jdk-10+16 +d0190aaf1816081d9b2e0577b65b793804896d1e jdk-9+178 +56ac1831ac5924b5092a53a85d6fc68749501fb8 jdk-9+179 +4c07d366c2e177edba7aa54c4b015e4dbf12bc83 jdk-10+17 diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java index 213b584b15a..8a63b73cee1 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java @@ -84,6 +84,14 @@ public class XmlUtil { private final static String LEXICAL_HANDLER_PROPERTY = "http://xml.org/sax/properties/lexical-handler"; + private static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl"; + + private static final String EXTERNAL_GE = "http://xml.org/sax/features/external-general-entities"; + + private static final String EXTERNAL_PE = "http://xml.org/sax/features/external-parameter-entities"; + + private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; + private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName()); private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity"; @@ -327,10 +335,24 @@ public class XmlUtil { public static DocumentBuilderFactory newDocumentBuilderFactory(boolean disableSecurity) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING; try { - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity)); + boolean securityOn = !xmlSecurityDisabled(disableSecurity); + factory.setFeature(featureToSet, securityOn); + factory.setNamespaceAware(true); + if (securityOn) { + factory.setExpandEntityReferences(false); + featureToSet = DISALLOW_DOCTYPE_DECL; + factory.setFeature(featureToSet, true); + featureToSet = EXTERNAL_GE; + factory.setFeature(featureToSet, false); + featureToSet = EXTERNAL_PE; + factory.setFeature(featureToSet, false); + featureToSet = LOAD_EXTERNAL_DTD; + factory.setFeature(featureToSet, false); + } } catch (ParserConfigurationException e) { - LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } ); + LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[] {factory.getClass().getName()} ); } return factory; } @@ -347,10 +369,23 @@ public class XmlUtil { public static SAXParserFactory newSAXParserFactory(boolean disableSecurity) { SAXParserFactory factory = SAXParserFactory.newInstance(); + String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING; try { - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity)); + boolean securityOn = !xmlSecurityDisabled(disableSecurity); + factory.setFeature(featureToSet, securityOn); + factory.setNamespaceAware(true); + if (securityOn) { + featureToSet = DISALLOW_DOCTYPE_DECL; + factory.setFeature(featureToSet, true); + featureToSet = EXTERNAL_GE; + factory.setFeature(featureToSet, false); + featureToSet = EXTERNAL_PE; + factory.setFeature(featureToSet, false); + featureToSet = LOAD_EXTERNAL_DTD; + factory.setFeature(featureToSet, false); + } } catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) { - LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()}); + LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[]{factory.getClass().getName()}); } return factory; } diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java index e105d2f386c..c7d9aeec1d7 100644 --- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java +++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java @@ -112,29 +112,13 @@ public class DOMForest { this.entityResolver = entityResolver; this.errorReceiver = errReceiver; this.logic = logic; + // secure xml processing can be switched off if input requires it + boolean disableXmlSecurity = options == null ? false : options.disableXmlSecurity; + + DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(disableXmlSecurity); + this.parserFactory = XmlUtil.newSAXParserFactory(disableXmlSecurity); try { - // secure xml processing can be switched off if input requires it - boolean secureProcessingEnabled = options == null || !options.disableXmlSecurity; - DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(!secureProcessingEnabled); - dbf.setNamespaceAware(true); this.documentBuilder = dbf.newDocumentBuilder(); - - this.parserFactory = XmlUtil.newSAXParserFactory(secureProcessingEnabled); - this.parserFactory.setNamespaceAware(true); - - if(secureProcessingEnabled){ - dbf.setExpandEntityReferences(false); - try { - parserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); - parserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); - parserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); - } catch (SAXNotRecognizedException e){ - throw new ParserConfigurationException(e.getMessage()); - } catch (SAXNotSupportedException e) { - throw new ParserConfigurationException(e.getMessage()); - } - } - } catch (ParserConfigurationException e) { throw new AssertionError(e); } diff --git a/jdk/.hgtags b/jdk/.hgtags index 2520b0ff926..012f8dd2e2a 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -439,3 +439,5 @@ e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15 3281b964ab104002623d744e8b77a12269b70acd jdk-10+16 443025bee731eb2225371b92c1c74b519b7baf33 jdk-9+178 06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179 +d93f2fd542b7d7855c2cd49ae15ebcc3d441a83b jdk-10+17 +c4b709bad6c5d29294124de5e74e1e2ac84fcf1f jdk-10+18 diff --git a/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java b/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java index 8030979cdaa..55abe739196 100644 --- a/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java @@ -50,7 +50,12 @@ public class FilterOutputStream extends OutputStream { /** * Whether the stream is closed; implicitly initialized to false. */ - private boolean closed; + private volatile boolean closed; + + /** + * Object used to prevent a race on the 'closed' instance variable. + */ + private final Object closeLock = new Object(); /** * Creates an output stream filter built on top of the specified @@ -165,7 +170,12 @@ public class FilterOutputStream extends OutputStream { if (closed) { return; } - closed = true; + synchronized (closeLock) { + if (closed) { + return; + } + closed = true; + } Throwable flushException = null; try { 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 679c0fa1066..81dd846c26a 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -364,9 +364,9 @@ public final class Class implements java.io.Serializable, // Reflective call to get caller class is only needed if a security manager // is present. Avoid the overhead of making this call otherwise. caller = Reflection.getCallerClass(); - if (VM.isSystemDomainLoader(loader)) { + if (loader == null) { ClassLoader ccl = ClassLoader.getClassLoader(caller); - if (!VM.isSystemDomainLoader(ccl)) { + if (ccl != null) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } @@ -432,18 +432,21 @@ public final class Class implements java.io.Serializable, Objects.requireNonNull(module); Objects.requireNonNull(name); - Class caller = Reflection.getCallerClass(); - if (caller != null && caller.getModule() != module) { - // if caller is null, Class.forName is the last java frame on the stack. - // java.base has all permissions - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { + ClassLoader cl; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + Class caller = Reflection.getCallerClass(); + if (caller != null && caller.getModule() != module) { + // if caller is null, Class.forName is the last java frame on the stack. + // java.base has all permissions sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } + PrivilegedAction pa = module::getClassLoader; + cl = AccessController.doPrivileged(pa); + } else { + cl = module.getClassLoader(); } - PrivilegedAction pa = module::getClassLoader; - ClassLoader cl = AccessController.doPrivileged(pa); if (cl != null) { return cl.loadClass(module, name); } else { diff --git a/jdk/src/java.base/share/classes/java/lang/Module.java b/jdk/src/java.base/share/classes/java/lang/Module.java index 2b1e0ed74a6..40cfdd3747f 100644 --- a/jdk/src/java.base/share/classes/java/lang/Module.java +++ b/jdk/src/java.base/share/classes/java/lang/Module.java @@ -246,7 +246,6 @@ public final class Module implements AnnotatedElement { return null; } - // -- // special Module to mean "all unnamed modules" @@ -257,17 +256,38 @@ public final class Module implements AnnotatedElement { private static final Module EVERYONE_MODULE = new Module(null); private static final Set EVERYONE_SET = Set.of(EVERYONE_MODULE); + /** + * The holder of data structures to support readability, exports, and + * service use added at runtime with the reflective APIs. + */ + private static class ReflectionData { + /** + * A module (1st key) reads another module (2nd key) + */ + static final WeakPairMap reads = + new WeakPairMap<>(); + + /** + * A module (1st key) exports or opens a package to another module + * (2nd key). The map value is a map of package name to a boolean + * that indicates if the package is opened. + */ + static final WeakPairMap> exports = + new WeakPairMap<>(); + + /** + * A module (1st key) uses a service (2nd key) + */ + static final WeakPairMap, Boolean> uses = + new WeakPairMap<>(); + } + // -- readability -- // the modules that this module reads private volatile Set reads; - // additional module (2nd key) that some module (1st key) reflectively reads - private static final WeakPairMap reflectivelyReads - = new WeakPairMap<>(); - - /** * Indicates if this module reads the given module. This method returns * {@code true} if invoked to test if this module reads itself. It also @@ -300,13 +320,13 @@ public final class Module implements AnnotatedElement { } // check if this module reads the other module reflectively - if (reflectivelyReads.containsKeyPair(this, other)) + if (ReflectionData.reads.containsKeyPair(this, other)) return true; // if other is an unnamed module then check if this module reads // all unnamed modules if (!other.isNamed() - && reflectivelyReads.containsKeyPair(this, ALL_UNNAMED_MODULE)) + && ReflectionData.reads.containsKeyPair(this, ALL_UNNAMED_MODULE)) return true; return false; @@ -393,7 +413,7 @@ public final class Module implements AnnotatedElement { } // add reflective read - reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE); + ReflectionData.reads.putIfAbsent(this, other, Boolean.TRUE); } } @@ -408,13 +428,6 @@ public final class Module implements AnnotatedElement { // if the value contains EVERYONE_MODULE then the package is exported to all private volatile Map> exportedPackages; - // additional exports or opens added at run-time - // this module (1st key), other module (2nd key) - // (package name, open?) (value) - private static final WeakPairMap> - reflectivelyExports = new WeakPairMap<>(); - - /** * Returns {@code true} if this module exports the given package to at * least the given module. @@ -600,7 +613,7 @@ public final class Module implements AnnotatedElement { */ private boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) { // exported or open to all modules - Map exports = reflectivelyExports.get(this, EVERYONE_MODULE); + Map exports = ReflectionData.exports.get(this, EVERYONE_MODULE); if (exports != null) { Boolean b = exports.get(pn); if (b != null) { @@ -612,7 +625,7 @@ public final class Module implements AnnotatedElement { if (other != EVERYONE_MODULE) { // exported or open to other - exports = reflectivelyExports.get(this, other); + exports = ReflectionData.exports.get(this, other); if (exports != null) { Boolean b = exports.get(pn); if (b != null) { @@ -623,7 +636,7 @@ public final class Module implements AnnotatedElement { // other is an unnamed module && exported or open to all unnamed if (!other.isNamed()) { - exports = reflectivelyExports.get(this, ALL_UNNAMED_MODULE); + exports = ReflectionData.exports.get(this, ALL_UNNAMED_MODULE); if (exports != null) { Boolean b = exports.get(pn); if (b != null) { @@ -886,8 +899,8 @@ public final class Module implements AnnotatedElement { } } - // add package name to reflectivelyExports if absent - Map map = reflectivelyExports + // add package name to exports if absent + Map map = ReflectionData.exports .computeIfAbsent(this, other, (m1, m2) -> new ConcurrentHashMap<>()); if (open) { @@ -932,10 +945,6 @@ public final class Module implements AnnotatedElement { // -- services -- - // additional service type (2nd key) that some module (1st key) uses - private static final WeakPairMap, Boolean> reflectivelyUses - = new WeakPairMap<>(); - /** * If the caller's module is this module then update this module to add a * service dependence on the given service type. This method is intended @@ -980,7 +989,7 @@ public final class Module implements AnnotatedElement { */ void implAddUses(Class service) { if (!canUse(service)) { - reflectivelyUses.putIfAbsent(this, service, Boolean.TRUE); + ReflectionData.uses.putIfAbsent(this, service, Boolean.TRUE); } } @@ -1011,7 +1020,7 @@ public final class Module implements AnnotatedElement { return true; // uses added via addUses - return reflectivelyUses.containsKeyPair(this, service); + return ReflectionData.uses.containsKeyPair(this, service); } @@ -1060,8 +1069,11 @@ public final class Module implements AnnotatedElement { Function clf, ModuleLayer layer) { - Map nameToModule = new HashMap<>(); - Map moduleToLoader = new HashMap<>(); + boolean isBootLayer = (ModuleLayer.boot() == null); + + int cap = (int)(cf.modules().size() / 0.75f + 1.0f); + Map nameToModule = new HashMap<>(cap); + Map nameToLoader = new HashMap<>(cap); Set loaders = new HashSet<>(); boolean hasPlatformModules = false; @@ -1070,7 +1082,7 @@ public final class Module implements AnnotatedElement { for (ResolvedModule resolvedModule : cf.modules()) { String name = resolvedModule.name(); ClassLoader loader = clf.apply(name); - moduleToLoader.put(name, loader); + nameToLoader.put(name, loader); if (loader == null || loader == ClassLoaders.platformClassLoader()) { if (!(clf instanceof ModuleLoaderMap.Mapper)) { throw new IllegalArgumentException("loader can't be 'null'" @@ -1087,20 +1099,19 @@ public final class Module implements AnnotatedElement { ModuleReference mref = resolvedModule.reference(); ModuleDescriptor descriptor = mref.descriptor(); String name = descriptor.name(); - URI uri = mref.location().orElse(null); - ClassLoader loader = moduleToLoader.get(resolvedModule.name()); + ClassLoader loader = nameToLoader.get(name); Module m; if (loader == null && name.equals("java.base")) { // java.base is already defined to the VM m = Object.class.getModule(); } else { + URI uri = mref.location().orElse(null); m = new Module(layer, loader, descriptor, uri); } nameToModule.put(name, m); - moduleToLoader.put(name, loader); } - // setup readability and exports + // setup readability and exports/opens for (ResolvedModule resolvedModule : cf.modules()) { ModuleReference mref = resolvedModule.reference(); ModuleDescriptor descriptor = mref.descriptor(); @@ -1146,7 +1157,18 @@ public final class Module implements AnnotatedElement { } // exports and opens - initExportsAndOpens(m, nameToSource, nameToModule, layer.parents()); + if (descriptor.isOpen() || descriptor.isAutomatic()) { + // The VM doesn't special case open or automatic modules yet + // so need to export all packages + for (String source : descriptor.packages()) { + addExportsToAll0(m, source); + } + } else if (isBootLayer && descriptor.opens().isEmpty()) { + // no open packages, no qualified exports to modules in parent layers + initExports(m, nameToModule); + } else { + initExportsAndOpens(m, nameToSource, nameToModule, layer.parents()); + } } // if there are modules defined to the boot or platform class loaders @@ -1161,7 +1183,7 @@ public final class Module implements AnnotatedElement { if (!descriptor.provides().isEmpty()) { String name = descriptor.name(); Module m = nameToModule.get(name); - ClassLoader loader = moduleToLoader.get(name); + ClassLoader loader = nameToLoader.get(name); if (loader == null) { bootCatalog.register(m); } else if (loader == pcl) { @@ -1179,7 +1201,6 @@ public final class Module implements AnnotatedElement { return nameToModule; } - /** * Find the runtime Module corresponding to the given ResolvedModule * in the given parent layer (or its parents). @@ -1201,25 +1222,55 @@ public final class Module implements AnnotatedElement { .orElse(null); } + /** + * Initialize/setup a module's exports. + * + * @param m the module + * @param nameToModule map of module name to Module (for qualified exports) + */ + private static void initExports(Module m, Map nameToModule) { + Map> exportedPackages = new HashMap<>(); + + for (Exports exports : m.getDescriptor().exports()) { + String source = exports.source(); + if (exports.isQualified()) { + // qualified exports + Set targets = new HashSet<>(); + for (String target : exports.targets()) { + Module m2 = nameToModule.get(target); + if (m2 != null) { + addExports0(m, source, m2); + targets.add(m2); + } + } + if (!targets.isEmpty()) { + exportedPackages.put(source, targets); + } + } else { + // unqualified exports + addExportsToAll0(m, source); + exportedPackages.put(source, EVERYONE_SET); + } + } + + if (!exportedPackages.isEmpty()) + m.exportedPackages = exportedPackages; + } /** - * Initialize the maps of exported and open packages for module m. + * Initialize/setup a module's exports. + * + * @param m the module + * @param nameToSource map of module name to Module for modules that m reads + * @param nameToModule map of module name to Module for modules in the layer + * under construction + * @param parents the parent layers */ private static void initExportsAndOpens(Module m, Map nameToSource, Map nameToModule, List parents) { - // The VM doesn't special case open or automatic modules so need to - // export all packages ModuleDescriptor descriptor = m.getDescriptor(); - if (descriptor.isOpen() || descriptor.isAutomatic()) { - assert descriptor.opens().isEmpty(); - for (String source : descriptor.packages()) { - addExportsToAll0(m, source); - } - return; - } - Map> openPackages = new HashMap<>(); Map> exportedPackages = new HashMap<>(); @@ -1272,7 +1323,6 @@ public final class Module implements AnnotatedElement { if (!targets.isEmpty()) { exportedPackages.put(source, targets); } - } else { // unqualified exports addExportsToAll0(m, source); 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 4e0169ccd7a..995b2c4e90f 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -313,6 +313,10 @@ public final class System { * @see java.lang.RuntimePermission */ public static void setSecurityManager(final SecurityManager s) { + if (security == null) { + // ensure image reader is initialized + Object.class.getResource("java/lang/ANY"); + } if (s != null) { try { s.checkPackageAccess("java.lang"); 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 2bd64edb0e5..45ccb909490 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 @@ -2476,7 +2476,7 @@ return mh1; return false; } ClassLoader loader = defc.getClassLoader(); - if (!jdk.internal.misc.VM.isSystemDomainLoader(loader)) { + if (loader != null) { ClassLoader sysl = ClassLoader.getSystemClassLoader(); boolean found = false; while (sysl != null) { 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 f989aae7fe6..371620add35 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 @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Deque; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -41,6 +42,9 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.module.ModuleReferenceImpl; +import jdk.internal.module.ModuleTarget; + /** * A configuration that is the result of * resolution or resolution with service binding. @@ -121,11 +125,8 @@ public final class Configuration { this.targetPlatform = null; } - private Configuration(List parents, - Resolver resolver, - boolean check) - { - Map> g = resolver.finish(this, check); + private Configuration(List parents, Resolver resolver) { + Map> g = resolver.finish(this); @SuppressWarnings(value = {"rawtypes", "unchecked"}) Entry[] nameEntries @@ -146,6 +147,62 @@ public final class Configuration { this.targetPlatform = resolver.targetPlatform(); } + /** + * Creates the Configuration for the boot layer from a pre-generated + * readability graph. + * + * @apiNote This method is coded for startup performance. + */ + Configuration(ModuleFinder finder, Map> map) { + int moduleCount = map.size(); + + // create map of name -> ResolvedModule + @SuppressWarnings(value = {"rawtypes", "unchecked"}) + Entry[] nameEntries + = (Entry[])new Entry[moduleCount]; + ResolvedModule[] moduleArray = new ResolvedModule[moduleCount]; + String targetPlatform = null; + int i = 0; + for (String name : map.keySet()) { + ModuleReference mref = finder.find(name).orElse(null); + assert mref != null; + + if (targetPlatform == null && mref instanceof ModuleReferenceImpl) { + ModuleTarget target = ((ModuleReferenceImpl)mref).moduleTarget(); + if (target != null) { + targetPlatform = target.targetPlatform(); + } + } + + ResolvedModule resolvedModule = new ResolvedModule(this, mref); + moduleArray[i] = resolvedModule; + nameEntries[i] = Map.entry(name, resolvedModule); + i++; + } + Map nameToModule = Map.ofEntries(nameEntries); + + // create entries for readability graph + @SuppressWarnings(value = {"rawtypes", "unchecked"}) + Entry>[] moduleEntries + = (Entry>[])new Entry[moduleCount]; + i = 0; + for (ResolvedModule resolvedModule : moduleArray) { + Set names = map.get(resolvedModule.name()); + ResolvedModule[] readsArray = new ResolvedModule[names.size()]; + int j = 0; + for (String name : names) { + readsArray[j++] = nameToModule.get(name); + } + moduleEntries[i++] = Map.entry(resolvedModule, Set.of(readsArray)); + } + + this.parents = List.of(empty()); + this.graph = Map.ofEntries(moduleEntries); + this.modules = Set.of(moduleArray); + this.nameToModule = nameToModule; + this.targetPlatform = targetPlatform; + } + /** * Resolves a collection of root modules, with this configuration as its * parent, to create a new configuration. This method works exactly as @@ -233,24 +290,20 @@ public final class Configuration { /** * Resolves a collection of root modules, with service binding, and with - * the empty configuration as its parent. The consistency checks - * are optionally run. + * the empty configuration as its parent. * * This method is used to create the configuration for the boot layer. */ static Configuration resolveAndBind(ModuleFinder finder, Collection roots, - boolean check, PrintStream traceOutput) { List parents = List.of(empty()); Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput); resolver.resolve(roots).bind(); - - return new Configuration(parents, resolver, check); + return new Configuration(parents, resolver); } - /** * Resolves a collection of root modules to create a configuration. * @@ -356,7 +409,7 @@ public final class Configuration { Resolver resolver = new Resolver(before, parentList, after, null); resolver.resolve(roots); - return new Configuration(parentList, resolver, true); + return new Configuration(parentList, resolver); } /** @@ -427,7 +480,7 @@ public final class Configuration { Resolver resolver = new Resolver(before, parentList, after, null); resolver.resolve(roots).bind(); - return new Configuration(parentList, resolver, true); + return new Configuration(parentList, resolver); } 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 20d198b46ee..ea77af72d51 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 @@ -2728,10 +2728,15 @@ public class ModuleDescriptor @Override public Configuration resolveAndBind(ModuleFinder finder, Collection roots, - boolean check, PrintStream traceOutput) { - return Configuration.resolveAndBind(finder, roots, check, traceOutput); + return Configuration.resolveAndBind(finder, roots, traceOutput); + } + + @Override + public Configuration newConfiguration(ModuleFinder finder, + Map> graph) { + return new Configuration(finder, graph); } }); } 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 5a8b8cb63f3..b85b2e179da 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 @@ -25,9 +25,7 @@ package java.lang.module; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; @@ -40,10 +38,8 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import jdk.internal.module.ModuleBootstrap; -import jdk.internal.module.ModulePatcher; import jdk.internal.module.ModulePath; -import jdk.internal.module.SystemModuleFinder; +import jdk.internal.module.SystemModuleFinders; /** * A finder of modules. A {@code ModuleFinder} is used to find modules during @@ -157,52 +153,13 @@ public interface ModuleFinder { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("accessSystemModules")); - PrivilegedAction pa = ModuleFinder::privilegedOfSystem; + PrivilegedAction pa = SystemModuleFinders::ofSystem; return AccessController.doPrivileged(pa); } else { - return privilegedOfSystem(); + return SystemModuleFinders.ofSystem(); } } - /** - * Returns a module finder that locates the system modules. This method - * assumes it has permissions to access the runtime image. - */ - private static ModuleFinder privilegedOfSystem() { - String home = System.getProperty("java.home"); - Path modules = Paths.get(home, "lib", "modules"); - if (Files.isRegularFile(modules)) { - return SystemModuleFinder.getInstance(); - } else { - Path dir = Paths.get(home, "modules"); - if (Files.isDirectory(dir)) { - return privilegedOf(ModuleBootstrap.patcher(), dir); - } else { - throw new InternalError("Unable to detect the run-time image"); - } - } - } - - /** - * Returns a module finder that locates the system modules in an exploded - * image. The image may be patched. - */ - private static ModuleFinder privilegedOf(ModulePatcher patcher, Path dir) { - ModuleFinder finder = ModulePath.of(patcher, dir); - return new ModuleFinder() { - @Override - public Optional find(String name) { - PrivilegedAction> pa = () -> finder.find(name); - return AccessController.doPrivileged(pa); - } - @Override - public Set findAll() { - PrivilegedAction> pa = finder::findAll; - return AccessController.doPrivileged(pa); - } - }; - } - /** * Returns a module finder that locates modules on the file system by * searching a sequence of directories and/or packaged modules. 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 a723e638abe..04faaa9340d 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 @@ -353,25 +353,13 @@ 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 + * modules as a map. */ - Map> finish(Configuration cf, - boolean check) - { - if (check) { - detectCycles(); - checkHashes(); - } - + Map> finish(Configuration cf) { + detectCycles(); + checkHashes(); Map> graph = makeGraph(cf); - - if (check) { - checkExportSuppliers(graph); - } - + checkExportSuppliers(graph); return graph; } 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 e2a950ed1c1..ee3395b6080 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 @@ -453,7 +453,7 @@ public class Proxy implements java.io.Serializable { SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader ccl = caller.getClassLoader(); - if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) { + if (loader == null && ccl != null) { sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } ReflectUtil.checkProxyPackageAccess(ccl, interfaces); 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 1ac1437ab96..2917be133bd 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -409,7 +409,7 @@ public final class URL implements java.io.Serializable { } } - protocol = protocol.toLowerCase(Locale.ROOT); + protocol = toLowerCase(protocol); this.protocol = protocol; if (host != null) { @@ -585,7 +585,7 @@ public final class URL implements java.io.Serializable { for (i = start ; !aRef && (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) { if (c == ':') { - String s = spec.substring(start, i).toLowerCase(Locale.ROOT); + String s = toLowerCase(spec.substring(start, i)); if (isValidProtocol(s)) { newProtocol = s; start = i + 1; @@ -1318,6 +1318,17 @@ public final class URL implements java.io.Serializable { } } + /** + * Returns the protocol in lower case. Special cases known protocols + * to avoid loading locale classes during startup. + */ + static String toLowerCase(String protocol) { + if (protocol.equals("jrt") || protocol.equals("file") || protocol.equals("jar")) { + return protocol; + } else { + return protocol.toLowerCase(Locale.ROOT); + } + } /** * Non-overrideable protocols: "jrt" and "file" diff --git a/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java b/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java index 3c4eda99dc7..5d710bd832e 100644 --- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java +++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java @@ -70,7 +70,7 @@ public abstract class AbstractSelector extends Selector { - private AtomicBoolean selectorOpen = new AtomicBoolean(true); + private final AtomicBoolean selectorOpen = new AtomicBoolean(true); // The provider that created this selector private final SelectorProvider provider; diff --git a/jdk/src/java.base/share/classes/java/security/MessageDigest.java b/jdk/src/java.base/share/classes/java/security/MessageDigest.java index be163c179f9..4f4987ceb46 100644 --- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java +++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java @@ -57,7 +57,7 @@ import javax.crypto.SecretKey; * and catching the CloneNotSupportedException: * *
    {@code
    - * MessageDigest md = MessageDigest.getInstance("SHA");
    + * MessageDigest md = MessageDigest.getInstance("SHA-256");
      *
      * try {
      *     md.update(toChapter1);
    @@ -496,7 +496,7 @@ public abstract class MessageDigest extends MessageDigestSpi {
         /**
          * Returns a string that identifies the algorithm, independent of
          * implementation details. The name should be a standard
    -     * Java Security name (such as "SHA", "MD5", and so on).
    +     * Java Security name (such as "SHA-256").
          * See the MessageDigest section in the 
          * Java Security Standard Algorithm Names Specification
    diff --git a/jdk/src/java.base/share/classes/java/security/Signature.java b/jdk/src/java.base/share/classes/java/security/Signature.java
    index c7c25831a35..3f0a9d96771 100644
    --- a/jdk/src/java.base/share/classes/java/security/Signature.java
    +++ b/jdk/src/java.base/share/classes/java/security/Signature.java
    @@ -51,11 +51,10 @@ import sun.security.jca.GetInstance.Instance;
      * authentication and integrity assurance of digital data.
      *
      * 

    The signature algorithm can be, among others, the NIST standard - * DSA, using DSA and SHA-1. The DSA algorithm using the - * SHA-1 message digest algorithm can be specified as {@code SHA1withDSA}. - * In the case of RSA, there are multiple choices for the message digest - * algorithm, so the signing algorithm could be specified as, for example, - * {@code MD2withRSA}, {@code MD5withRSA}, or {@code SHA1withRSA}. + * DSA, using DSA and SHA-256. The DSA algorithm using the + * SHA-256 message digest algorithm can be specified as {@code SHA256withDSA}. + * In the case of RSA the signing algorithm could be specified as, for example, + * {@code SHA256withRSA}. * The algorithm name must be specified, as there is no default. * *

    A Signature object can be used to generate and verify digital diff --git a/jdk/src/java.base/share/classes/java/security/SignedObject.java b/jdk/src/java.base/share/classes/java/security/SignedObject.java index 810c5706579..7ef3eca5583 100644 --- a/jdk/src/java.base/share/classes/java/security/SignedObject.java +++ b/jdk/src/java.base/share/classes/java/security/SignedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,13 +81,12 @@ import java.io.*; * verification in an attempt to bypass a security check. * *

    The signature algorithm can be, among others, the NIST standard - * DSA, using DSA and SHA-1. The algorithm is specified using the + * DSA, using DSA and SHA-256. The algorithm is specified using the * same convention as that for signatures. The DSA algorithm using the - * SHA-1 message digest algorithm can be specified, for example, as - * "SHA/DSA" or "SHA-1/DSA" (they are equivalent). In the case of - * RSA, there are multiple choices for the message digest algorithm, - * so the signing algorithm could be specified as, for example, - * "MD2/RSA", "MD5/RSA" or "SHA-1/RSA". The algorithm name must be + * SHA-256 message digest algorithm can be specified, for example, as + * "SHA256withDSA". In the case of + * RSA the signing algorithm could be specified as, for example, + * "SHA256withRSA". The algorithm name must be * specified, as there is no default. * *

    The name of the Cryptography Package Provider is designated diff --git a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java index 4390fb7ba1a..0100895f3ee 100644 --- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java @@ -667,11 +667,11 @@ import java.util.stream.StreamSupport; *

* * - * + * * * * - * + * * * * diff --git a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java index 4982a87bbe1..cd603f22312 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java +++ b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java @@ -59,7 +59,7 @@ import sun.security.jca.*; *

A transformation is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic - * algorithm (e.g., DES), and may be followed by a feedback mode and + * algorithm (e.g., AES), and may be followed by a feedback mode and * padding scheme. * *

A transformation is of the form: @@ -75,17 +75,19 @@ import sun.security.jca.*; * For example, the following is a valid transformation: * *

- *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ *     Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
  * 
* * Using modes such as {@code CFB} and {@code OFB}, block * ciphers can encrypt data in units smaller than the cipher's actual * block size. When requesting such a mode, you may optionally specify * the number of bits to be processed at a time by appending this number - * to the mode name as shown in the "{@code DES/CFB8/NoPadding}" and - * "{@code DES/OFB32/PKCS5Padding}" transformations. If no such - * number is specified, a provider-specific default is used. (For - * example, the SunJCE provider uses a default of 64 bits for DES.) + * to the mode name as shown in the "{@code AES/CFB8/NoPadding}" and + * "{@code AES/OFB32/PKCS5Padding}" transformations. If no such + * number is specified, a provider-specific default is used. + * (See the + * {@extLink security_guide_jdk_providers JDK Providers Documentation} + * for the JDK Providers default values.) * Thus, block ciphers can be turned into byte-oriented stream ciphers by * using an 8 bit mode such as CFB8 or OFB8. *

@@ -308,7 +310,7 @@ public class Cipher { /* * array containing the components of a Cipher transformation: * - * index 0: algorithm component (e.g., DES) + * index 0: algorithm component (e.g., AES) * index 1: feedback component (e.g., CFB) * index 2: padding component (e.g., PKCS5Padding) */ @@ -354,8 +356,8 @@ public class Cipher { // transform string to lookup in the provider final String transform; // the mode/padding suffix in upper case. for example, if the algorithm - // to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING" - // if loopup is "DES", suffix is the empty string + // to lookup is "AES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING" + // if lookup is "AES", suffix is the empty string // needed because aliases prevent straight transform.equals() final String suffix; // value to pass to setMode() or null if no such call required @@ -440,11 +442,11 @@ public class Cipher { } if ((mode == null) && (pad == null)) { - // DES + // AES Transform tr = new Transform(alg, "", null, null); return Collections.singletonList(tr); } else { // if ((mode != null) && (pad != null)) { - // DES/CBC/PKCS5Padding + // AES/CBC/PKCS5Padding List list = new ArrayList<>(4); list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); list.add(new Transform(alg, "/" + mode, null, pad)); @@ -488,7 +490,7 @@ public class Cipher { * {@link Security#getProviders() Security.getProviders()}. * * @param transformation the name of the transformation, e.g., - * DES/CBC/PKCS5Padding. + * AES/CBC/PKCS5Padding. * See the Cipher section in the * Java Security Standard Algorithm Names Specification @@ -566,7 +568,7 @@ public class Cipher { * the {@link Security#getProviders() Security.getProviders()} method. * * @param transformation the name of the transformation, - * e.g., DES/CBC/PKCS5Padding. + * e.g., AES/CBC/PKCS5Padding. * See the Cipher section in the * Java Security Standard Algorithm Names Specification @@ -626,7 +628,7 @@ public class Cipher { * does not have to be registered in the provider list. * * @param transformation the name of the transformation, - * e.g., DES/CBC/PKCS5Padding. + * e.g., AES/CBC/PKCS5Padding. * See the Cipher section in the * Java Security Standard Algorithm Names Specification diff --git a/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java b/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java index ce7258157d5..72bfa803bd5 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java +++ b/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * 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,7 @@ import java.nio.ByteBuffer; *

A transformation is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic - * algorithm (e.g., DES), and may be followed by a feedback mode and + * algorithm (e.g., AES), and may be followed by a feedback mode and * padding scheme. * *

A transformation is of the form: @@ -75,7 +75,7 @@ import java.nio.ByteBuffer; * For example, the following is a valid transformation: * *

- *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ *     Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
  * 
* *

A provider may supply a separate class for each combination @@ -125,32 +125,32 @@ import java.nio.ByteBuffer; * * *

For example, a provider may supply a subclass of CipherSpi - * that implements DES/ECB/PKCS5Padding, one that implements - * DES/CBC/PKCS5Padding, one that implements - * DES/CFB/PKCS5Padding, and yet another one that implements - * DES/OFB/PKCS5Padding. That provider would have the following + * that implements AES/ECB/PKCS5Padding, one that implements + * AES/CBC/PKCS5Padding, one that implements + * AES/CFB/PKCS5Padding, and yet another one that implements + * AES/OFB/PKCS5Padding. That provider would have the following * Cipher properties in its master class: * *

@@ -158,7 +158,7 @@ import java.nio.ByteBuffer; *

Another provider may implement a class for each of the above modes * (i.e., one class for ECB, one for CBC, one for CFB, * and one for OFB), one class for PKCS5Padding, - * and a generic DES class that subclasses from CipherSpi. + * and a generic AES class that subclasses from CipherSpi. * That provider would have the following * Cipher properties in its master class: * @@ -166,7 +166,7 @@ import java.nio.ByteBuffer; * *

  • *
    - *     Cipher.DES
    + *     Cipher.AES
      * 
    * * diff --git a/jdk/src/java.base/share/classes/javax/crypto/Mac.java b/jdk/src/java.base/share/classes/javax/crypto/Mac.java index 245f12f6934..ad7dae88913 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/Mac.java +++ b/jdk/src/java.base/share/classes/javax/crypto/Mac.java @@ -50,7 +50,7 @@ import sun.security.jca.GetInstance.Instance; * *

    A MAC mechanism that is based on cryptographic hash functions is * referred to as HMAC. HMAC can be used with any cryptographic hash function, - * e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is + * e.g., SHA256 or SHA384, in combination with a secret shared key. HMAC is * specified in RFC 2104. * *

    Every implementation of the Java platform is required to support diff --git a/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java b/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java index 743125bf0f7..3d657423aa4 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java +++ b/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import java.security.NoSuchProviderException; *

    Given any Serializable object, one can create a SealedObject * that encapsulates the original object, in serialized * format (i.e., a "deep copy"), and seals (encrypts) its serialized contents, - * using a cryptographic algorithm such as DES, to protect its + * using a cryptographic algorithm such as AES, to protect its * confidentiality. The encrypted content can later be decrypted (with * the corresponding algorithm using the correct decryption key) and * de-serialized, yielding the original object. 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 95b65f646d8..8679132127b 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 @@ -55,13 +55,13 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.stream.Stream; import jdk.internal.misc.VM; import jdk.internal.module.ModulePatcher.PatchedModuleReader; -import jdk.internal.module.SystemModules; import jdk.internal.module.Resources; @@ -139,7 +139,7 @@ public class BuiltinClassLoader // maps package name to loaded module for modules in the boot layer private static final Map packageToModule - = new ConcurrentHashMap<>(SystemModules.PACKAGES_IN_BOOT_LAYER); + = new ConcurrentHashMap<>(1024); // maps a module name to a module reference private final Map nameToModule; @@ -946,9 +946,16 @@ public class BuiltinClassLoader URL url = cs.getLocation(); if (url == null) return perms; - Permission p = null; + + // avoid opening connection when URL is to resource in run-time image + if (url.getProtocol().equals("jrt")) { + perms.add(new RuntimePermission("accessSystemModules")); + return perms; + } + + // open connection to determine the permission needed try { - p = url.openConnection().getPermission(); + Permission p = url.openConnection().getPermission(); if (p != null) { // for directories then need recursive access if (p instanceof FilePermission) { @@ -969,23 +976,26 @@ public class BuiltinClassLoader // -- miscellaneous supporting methods /** - * Returns the ModuleReader for the given module. + * Returns the ModuleReader for the given module, creating it if needed */ private ModuleReader moduleReaderFor(ModuleReference mref) { - return moduleToReader.computeIfAbsent(mref, BuiltinClassLoader::createModuleReader); - } - - /** - * Creates a ModuleReader for the given module. - */ - private static ModuleReader createModuleReader(ModuleReference mref) { - try { - return mref.open(); - } catch (IOException e) { - // Return a null module reader to avoid a future class load - // attempting to open the module again. - return new NullModuleReader(); + ModuleReader reader = moduleToReader.get(mref); + if (reader == null) { + // avoid method reference during startup + Function create = new Function<>() { + public ModuleReader apply(ModuleReference moduleReference) { + try { + return mref.open(); + } catch (IOException e) { + // Return a null module reader to avoid a future class + // load attempting to open the module again. + return new NullModuleReader(); + } + } + }; + reader = moduleToReader.computeIfAbsent(mref, create); } + return reader; } /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index d976aab1cd7..921c292c7be 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -25,7 +25,6 @@ package jdk.internal.loader; -import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.file.InvalidPathException; @@ -38,7 +37,6 @@ import jdk.internal.misc.JavaLangAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.VM; - /** * Creates and provides access to the built-in platform and application class * loaders. It also creates the class loader that is used to locate resources @@ -61,23 +59,30 @@ public class ClassLoaders { */ static { - // -Xbootclasspth/a or -javaagent Boot-Class-Path + // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute URLClassPath bcp = null; String s = VM.getSavedProperty("jdk.boot.class.path.append"); if (s != null && s.length() > 0) - bcp = toURLClassPath(s); + bcp = new URLClassPath(s, true); // we have a class path if -cp is specified or -m is not specified. // If neither is specified then default to -cp // If -cp is not specified and -m is specified, the value of // java.class.path is an empty string, then no class path. - URLClassPath ucp = new URLClassPath(new URL[0]); String mainMid = System.getProperty("jdk.module.main"); String cp = System.getProperty("java.class.path"); - if (cp == null) - cp = ""; - if (mainMid == null || cp.length() > 0) - addClassPathToUCP(cp, ucp); + if (mainMid == null) { + // no main module specified so class path required + if (cp == null) { + cp = ""; + } + } else { + // main module specified, ignore empty class path + if (cp != null && cp.length() == 0) { + cp = null; + } + } + URLClassPath ucp = new URLClassPath(cp, false); // create the class loaders BOOT_LOADER = new BootClassLoader(bcp); @@ -198,7 +203,7 @@ public class ClassLoaders { * @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch */ void appendToClassPathForInstrumentation(String path) { - addClassPathToUCP(path, ucp); + ucp.addFile(path); } /** @@ -219,41 +224,12 @@ public class ClassLoaders { } } - /** - * Returns a {@code URLClassPath} of file URLs to each of the elements in - * the given class path. - */ - private static URLClassPath toURLClassPath(String cp) { - URLClassPath ucp = new URLClassPath(new URL[0]); - addClassPathToUCP(cp, ucp); - return ucp; - } - - /** - * Converts the elements in the given class path to file URLs and adds - * them to the given URLClassPath. - */ - private static void addClassPathToUCP(String cp, URLClassPath ucp) { - int off = 0; - int next; - while ((next = cp.indexOf(File.pathSeparator, off)) != -1) { - URL url = toFileURL(cp.substring(off, next)); - if (url != null) - ucp.addURL(url); - off = next + 1; - } - - // remaining - URL url = toFileURL(cp.substring(off)); - if (url != null) - ucp.addURL(url); - } - /** * Attempts to convert the given string to a file URL. * * @apiNote This is called by the VM */ + @Deprecated private static URL toFileURL(String s) { try { // Use an intermediate File object to construct a URI/URL without @@ -265,5 +241,4 @@ public class ClassLoaders { return null; } } - } 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 d343f8fdcbe..fdce4bfc422 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 @@ -46,6 +46,7 @@ import java.security.Permission; import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -66,7 +67,6 @@ import java.util.jar.Attributes.Name; import java.util.zip.ZipFile; import jdk.internal.misc.JavaNetURLAccess; -import jdk.internal.misc.JavaNetURLClassLoaderAccess; import jdk.internal.misc.JavaUtilZipFileAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.util.jar.InvalidJarIndexError; @@ -100,19 +100,19 @@ public class URLClassPath { } /* The original search path of URLs. */ - private ArrayList path = new ArrayList<>(); + private final List path; /* The stack of unopened URLs */ - Stack urls = new Stack<>(); + private final Stack urls = new Stack<>(); /* The resulting search path of Loaders */ - ArrayList loaders = new ArrayList<>(); + private final ArrayList loaders = new ArrayList<>(); /* Map of each URL opened to its corresponding Loader */ - HashMap lmap = new HashMap<>(); + private final HashMap lmap = new HashMap<>(); /* The jar protocol handler to use when creating new URLs */ - private URLStreamHandler jarHandler; + private final URLStreamHandler jarHandler; /* Whether this URLClassLoader has been closed yet */ private boolean closed = false; @@ -137,12 +137,16 @@ public class URLClassPath { public URLClassPath(URL[] urls, URLStreamHandlerFactory factory, AccessControlContext acc) { - for (int i = 0; i < urls.length; i++) { - path.add(urls[i]); + List path = new ArrayList<>(urls.length); + for (URL url : urls) { + path.add(url); } + this.path = path; push(urls); if (factory != null) { jarHandler = factory.createURLStreamHandler("jar"); + } else { + jarHandler = null; } if (DISABLE_ACC_CHECKING) this.acc = null; @@ -150,18 +154,52 @@ public class URLClassPath { this.acc = acc; } - /** - * Constructs a URLClassPath with no additional security restrictions. - * Used by code that implements the class path. - */ - public URLClassPath(URL[] urls) { - this(urls, null, null); - } - public URLClassPath(URL[] urls, AccessControlContext acc) { this(urls, null, acc); } + /** + * Constructs a URLClassPath from a class path string. + * + * @param cp the class path string + * @param skipEmptyElements indicates if empty elements are ignored or + * treated as the current working directory + * + * @apiNote Used to create the application class path. + */ + URLClassPath(String cp, boolean skipEmptyElements) { + List path = new ArrayList<>(); + if (cp != null) { + // map each element of class path to a file URL + int off = 0; + int next; + while ((next = cp.indexOf(File.pathSeparator, off)) != -1) { + String element = cp.substring(off, next); + if (element.length() > 0 || !skipEmptyElements) { + URL url = toFileURL(element); + if (url != null) path.add(url); + } + off = next + 1; + } + + // remaining element + String element = cp.substring(off); + if (element.length() > 0 || !skipEmptyElements) { + URL url = toFileURL(element); + if (url != null) path.add(url); + } + + // push the URLs + for (int i = path.size() - 1; i >= 0; --i) { + urls.push(path.get(i)); + } + } + + this.path = path; + this.jarHandler = null; + this.acc = null; + } + public synchronized List closeLoaders() { if (closed) { return Collections.emptyList(); @@ -197,6 +235,28 @@ public class URLClassPath { } } + /** + * Appends the specified file path as a file URL to the search path. + */ + public void addFile(String s) { + URL url = toFileURL(s); + if (url != null) { + addURL(url); + } + } + + /** + * Returns a file URL for the given file path. + */ + private static URL toFileURL(String s) { + try { + File f = new File(s).getCanonicalFile(); + return ParseUtil.fileToEncodedURL(f); + } catch (IOException e) { + return null; + } + } + /** * Returns the original search path of URLs. */ 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 5ffd8fd7af4..986eea2c994 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 @@ -25,6 +25,8 @@ package jdk.internal.logger; +import jdk.internal.misc.VM; + import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -140,15 +142,9 @@ public class DefaultLoggerFinder extends LoggerFinder { return AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Boolean run() { - final ClassLoader moduleCL = m.getClassLoader(); - if (moduleCL == null) return true; - ClassLoader cl = ClassLoader.getPlatformClassLoader(); - while (cl != null && moduleCL != cl) { - cl = cl.getParent(); - } // returns true if moduleCL is the platform class loader // or one of its ancestors. - return moduleCL == cl; + return VM.isSystemDomainLoader(m.getClassLoader()); } }); } 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 9ad1d5cf0ef..6bdcdcfd4b2 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 @@ -34,16 +34,10 @@ 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.lang.module.ModuleReader; -import java.lang.module.ModuleReference; -import java.net.URI; -import java.nio.file.Path; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.function.Supplier; - -import jdk.internal.module.ModuleHashes; /** * Provides access to non-public methods in java.lang.module. @@ -131,12 +125,16 @@ public interface JavaLangModuleAccess { /** * Resolves a collection of root modules, with service binding - * and the empty configuration as the parent. The post resolution - * checks are optionally run. + * and the empty configuration as the parent. */ Configuration resolveAndBind(ModuleFinder finder, Collection roots, - boolean check, PrintStream traceOutput); + /** + * Creates a configuration from a pre-generated readability graph. + */ + Configuration newConfiguration(ModuleFinder finder, + Map> graph); + } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java index 95961c74584..46a2dbb5067 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -124,11 +124,11 @@ public class VM { } /** - * Returns true if the given class loader is in the system domain - * in which all permissions are granted. + * Returns true if the given class loader is the bootstrap class loader + * or the platform class loader. */ public static boolean isSystemDomainLoader(ClassLoader loader) { - return loader == null; + return loader == null || loader == ClassLoader.getPlatformClassLoader(); } /** diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java b/jdk/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java new file mode 100644 index 00000000000..b9e06bb8747 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.module; + +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.util.HashSet; +import java.util.Set; + +/** + * Defines methods to compute the default set of root modules for the unnamed + * module. + */ + +public final class DefaultRoots { + private static final String JAVA_SE = "java.se"; + + private DefaultRoots() { } + + /** + * Returns the default set of root modules for the unnamed module computed from + * the system modules observable with the given module finder. + */ + static Set compute(ModuleFinder systemModuleFinder, ModuleFinder finder) { + Set roots = new HashSet<>(); + + boolean hasJava = false; + if (systemModuleFinder.find(JAVA_SE).isPresent()) { + if (finder == systemModuleFinder || finder.find(JAVA_SE).isPresent()) { + // java.se is a system module + hasJava = true; + roots.add(JAVA_SE); + } + } + + for (ModuleReference mref : systemModuleFinder.findAll()) { + String mn = mref.descriptor().name(); + if (hasJava && mn.startsWith("java.")) { + // not a root + continue; + } + + if (ModuleResolution.doNotResolveByDefault(mref)) { + // not a root + continue; + } + + if ((finder == systemModuleFinder || finder.find(mn).isPresent())) { + // add as root if exports at least one package to all modules + ModuleDescriptor descriptor = mref.descriptor(); + for (ModuleDescriptor.Exports e : descriptor.exports()) { + if (!e.isQualified()) { + roots.add(mn); + break; + } + } + } + } + + return roots; + } + + /** + * Returns the default set of root modules for the unnamed module from the + * modules observable with the given module finder. + */ + public static Set compute(ModuleFinder finder) { + return compute(finder, finder); + } +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java b/jdk/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java new file mode 100644 index 00000000000..b424b9c0ec1 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.module; + +import java.lang.module.ModuleDescriptor; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + * A dummy SystemModules for use with exploded builds or testing. + */ + +class ExplodedSystemModules implements SystemModules { + @Override + public boolean hasSplitPackages() { + return true; // not known + } + + @Override + public boolean hasIncubatorModules() { + return true; // not known + } + + @Override + public ModuleDescriptor[] moduleDescriptors() { + throw new InternalError(); + } + + @Override + public ModuleTarget[] moduleTargets() { + throw new InternalError(); + } + + @Override + public ModuleHashes[] moduleHashes() { + throw new InternalError(); + } + + @Override + public ModuleResolution[] moduleResolutions() { + throw new InternalError(); + } + + @Override + public Map> moduleReads() { + throw new InternalError(); + } + + @Override + public Map> concealedPackagesToOpen() { + return Collections.emptyMap(); + } + + @Override + public Map> exportedPackagesToOpen() { + return Collections.emptyMap(); + } +} 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 619b03b3596..1f769f3a7b9 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 @@ -40,16 +40,20 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; 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.JavaLangAccess; +import jdk.internal.misc.JavaLangModuleAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.perf.PerfCounter; @@ -70,8 +74,6 @@ 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"; @@ -84,13 +86,13 @@ public final class ModuleBootstrap { // the token for "all modules on the module path" private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; + // access to java.lang/module + private static final JavaLangModuleAccess JLMA + = SharedSecrets.getJavaLangModuleAccess(); + // The ModulePatcher for the initial configuration private static final ModulePatcher patcher = initModulePatcher(); - // ModuleFinders for the initial configuration - private static ModuleFinder unlimitedFinder; - private static ModuleFinder limitedFinder; - /** * Returns the ModulePatcher for the initial configuration. */ @@ -98,21 +100,38 @@ public final class ModuleBootstrap { return patcher; } + // ModuleFinders for the initial configuration + private static volatile ModuleFinder unlimitedFinder; + private static volatile ModuleFinder limitedFinder; + /** - * Returns the ModuleFinder for the initial configuration before observability - * is limited by the --limit-modules command line option. + * Returns the ModuleFinder for the initial configuration before + * observability is limited by the --limit-modules command line option. + * + * @apiNote Used to support locating modules {@code java.instrument} and + * {@code jdk.management.agent} modules when they are loaded dynamically. */ public static ModuleFinder unlimitedFinder() { - assert unlimitedFinder != null; - return unlimitedFinder; + ModuleFinder finder = unlimitedFinder; + if (finder == null) { + return ModuleFinder.ofSystem(); + } else { + return finder; + } } /** * Returns the ModuleFinder for the initial configuration. + * + * @apiNote Used to support "{@code java --list-modules}". */ public static ModuleFinder limitedFinder() { - assert limitedFinder != null; - return limitedFinder; + ModuleFinder finder = limitedFinder; + if (finder == null) { + return unlimitedFinder(); + } else { + return finder; + } } /** @@ -120,13 +139,60 @@ public final class ModuleBootstrap { * * @see java.lang.System#initPhase2() */ - public static ModuleLayer boot() { + public static ModuleLayer boot() throws Exception { - // Step 1: Locate system modules (may be patched) + // Step 0: Command line options + + long t0 = System.nanoTime(); + + ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path"); + ModuleFinder appModulePath = finderFor("jdk.module.path"); + boolean isPatched = patcher.hasPatches(); + + String mainModule = System.getProperty("jdk.module.main"); + Set addModules = addModules(); + Set limitModules = limitModules(); + + PrintStream traceOutput = null; + String trace = getAndRemoveProperty("jdk.module.showModuleResolution"); + if (trace != null && Boolean.parseBoolean(trace)) + traceOutput = System.out; + + + // Step 1: The observable system modules, either all system modules + // or the system modules pre-generated for the initial module (the + // initial module may be the unnamed module). If the system modules + // are pre-generated for the initial module then resolution can be + // skipped. long t1 = System.nanoTime(); - ModuleFinder systemModules = ModuleFinder.ofSystem(); - PerfCounters.systemModulesTime.addElapsedTimeFrom(t1); + + SystemModules systemModules = null; + ModuleFinder systemModuleFinder; + + boolean haveModulePath = (appModulePath != null || upgradeModulePath != null); + boolean needResolution = true; + + if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) { + systemModules = SystemModuleFinders.systemModules(mainModule); + if (systemModules != null && !isPatched && (traceOutput == null)) { + needResolution = false; + } + } + if (systemModules == null) { + // all system modules are observable + systemModules = SystemModuleFinders.allSystemModules(); + } + if (systemModules != null) { + // images build + systemModuleFinder = SystemModuleFinders.of(systemModules); + } else { + // exploded build or testing + systemModules = new ExplodedSystemModules(); + systemModuleFinder = SystemModuleFinders.ofSystem(); + } + + Counters.add("jdk.module.boot.1.systemModulesTime", t1); // Step 2: Define and load java.base. This patches all classes loaded @@ -136,7 +202,7 @@ public final class ModuleBootstrap { long t2 = System.nanoTime(); - ModuleReference base = systemModules.find(JAVA_BASE).orElse(null); + ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null); if (base == null) throw new InternalError(JAVA_BASE + " not found"); URI baseUri = base.location().orElse(null); @@ -145,171 +211,138 @@ public final class ModuleBootstrap { BootLoader.loadModule(base); Modules.defineModule(null, base.descriptor(), baseUri); - PerfCounters.defineBaseTime.addElapsedTimeFrom(t2); + Counters.add("jdk.module.boot.2.defineBaseTime", t2); // Step 2a: If --validate-modules is specified then the VM needs to // start with only java.base, all other options are ignored. - String propValue = getAndRemoveProperty("jdk.module.minimumBoot"); - if (propValue != null) { + if (getAndRemoveProperty("jdk.module.minimumBoot") != null) { return createMinimalBootLayer(); } - // Step 3: Construct the module path and the set of root modules to - // resolve. If --limit-modules is specified then it limits the set - // modules that are observable. + // Step 3: If resolution is needed then create the module finder and + // the set of root modules to resolve. long t3 = System.nanoTime(); - // --upgrade-module-path option specified to launcher - ModuleFinder upgradeModulePath - = createModulePathFinder("jdk.module.upgrade.path"); - if (upgradeModulePath != null) - systemModules = ModuleFinder.compose(upgradeModulePath, systemModules); + ModuleFinder savedModuleFinder = null; + ModuleFinder finder; + Set roots; + if (needResolution) { - // --module-path option specified to the launcher - ModuleFinder appModulePath = createModulePathFinder("jdk.module.path"); + // upgraded modules override the modules in the run-time image + if (upgradeModulePath != null) + systemModuleFinder = ModuleFinder.compose(upgradeModulePath, + systemModuleFinder); - // The module finder: [--upgrade-module-path] system [--module-path] - ModuleFinder finder = systemModules; - if (appModulePath != null) - finder = ModuleFinder.compose(finder, appModulePath); - - // 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 --add-modules - boolean addAllDefaultModules = false; - boolean addAllSystemModules = false; - boolean addAllApplicationModules = false; - for (String mod: getExtraAddModules()) { - switch (mod) { - case ALL_DEFAULT: - addAllDefaultModules = true; - break; - case ALL_SYSTEM: - addAllSystemModules = true; - break; - case ALL_MODULE_PATH: - addAllApplicationModules = true; - break; - default : - roots.add(mod); + // The module finder: [--upgrade-module-path] system [--module-path] + if (appModulePath != null) { + finder = ModuleFinder.compose(systemModuleFinder, appModulePath); + } else { + finder = systemModuleFinder; } - } - // --limit-modules - unlimitedFinder = finder; - propValue = getAndRemoveProperty("jdk.module.limitmods"); - if (propValue != null) { - Set mods = new HashSet<>(); - for (String mod: propValue.split(",")) { - mods.add(mod); - } - finder = limitFinder(finder, mods, roots); - } - limitedFinder = finder; + // The root modules to resolve + roots = new HashSet<>(); - // 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. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT - // bit set in their ModuleResolution attribute flags are excluded from - // the default set of roots. - 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); + // launcher -m option to specify the main/initial module + if (mainModule != null) + roots.add(mainModule); + + // additional module(s) specified by --add-modules + boolean addAllDefaultModules = false; + boolean addAllSystemModules = false; + boolean addAllApplicationModules = false; + for (String mod : addModules) { + switch (mod) { + case ALL_DEFAULT: + addAllDefaultModules = true; + break; + case ALL_SYSTEM: + addAllSystemModules = true; + break; + case ALL_MODULE_PATH: + addAllApplicationModules = true; + break; + default: + roots.add(mod); } } - for (ModuleReference mref : systemModules.findAll()) { - String mn = mref.descriptor().name(); - if (hasJava && mn.startsWith("java.")) - continue; - - if (ModuleResolution.doNotResolveByDefault(mref)) - 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; - } - } - } + // --limit-modules + savedModuleFinder = finder; + if (!limitModules.isEmpty()) { + finder = limitFinder(finder, limitModules, roots); } + + // 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. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT + // bit set in their ModuleResolution attribute flags are excluded from + // the default set of roots. + if (mainModule == null || addAllDefaultModules) { + roots.addAll(DefaultRoots.compute(systemModuleFinder, finder)); + } + + // If `--add-modules ALL-SYSTEM` is specified then all observable system + // modules will be resolved. + if (addAllSystemModules) { + ModuleFinder f = finder; // observable modules + systemModuleFinder.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(mn -> f.find(mn).isPresent()) // observable + .forEach(mn -> roots.add(mn)); + } + + // If `--add-modules 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)); + } + } else { + // no resolution case + finder = systemModuleFinder; + roots = null; } - // If `--add-modules 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 `--add-modules 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(t3); - + Counters.add("jdk.module.boot.3.optionsAndRootsTime", t3); // Step 4: Resolve the root modules, with service binding, to create - // the configuration for the boot layer. + // the configuration for the boot layer. If resolution is not needed + // then create the configuration for the boot layer from the + // readability graph created at link time. long t4 = 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) - && (patcher.isEmpty())) { - needPostResolutionChecks = false; + Configuration cf; + if (needResolution) { + cf = JLMA.resolveAndBind(finder, roots, traceOutput); + } else { + Map> map = systemModules.moduleReads(); + cf = JLMA.newConfiguration(systemModuleFinder, map); } - PrintStream traceOutput = null; - propValue = getAndRemoveProperty("jdk.module.showModuleResolution"); - if (propValue != null && Boolean.parseBoolean(propValue)) - traceOutput = System.out; + // check that modules specified to --patch-module are resolved + if (isPatched) { + patcher.patchedModules() + .stream() + .filter(mn -> !cf.findModule(mn).isPresent()) + .forEach(mn -> warnUnknownModule(PATCH_MODULE, mn)); + } - // run the resolver to create the configuration - Configuration cf = SharedSecrets.getJavaLangModuleAccess() - .resolveAndBind(finder, - roots, - needPostResolutionChecks, - traceOutput); - - PerfCounters.resolveTime.addElapsedTimeFrom(t4); + Counters.add("jdk.module.boot.4.resolveTime", t4); // Step 5: Map the modules in the configuration to class loaders. @@ -326,7 +359,7 @@ public final class ModuleBootstrap { // check that all modules to be mapped to the boot loader will be // loaded from the runtime image - if (needPostResolutionChecks) { + if (haveModulePath) { for (ResolvedModule resolvedModule : cf.modules()) { ModuleReference mref = resolvedModule.reference(); String name = mref.descriptor().name(); @@ -335,51 +368,54 @@ public final class ModuleBootstrap { if (upgradeModulePath != null && upgradeModulePath.find(name).isPresent()) fail(name + ": cannot be loaded from upgrade module path"); - if (!systemModules.find(name).isPresent()) + if (!systemModuleFinder.find(name).isPresent()) fail(name + ": cannot be loaded from application module path"); } } - - // check if module specified in --patch-module is present - for (String mn: patcher.patchedModules()) { - if (!cf.findModule(mn).isPresent()) { - warnUnknownModule(PATCH_MODULE, mn); - } - } } // check for split packages in the modules mapped to the built-in loaders - if (SystemModules.hasSplitPackages() || needPostResolutionChecks) { + if (systemModules.hasSplitPackages() || isPatched || haveModulePath) { checkSplitPackages(cf, clf); } // load/register the modules with the built-in class loaders loadModules(cf, clf); - PerfCounters.loadModulesTime.addElapsedTimeFrom(t5); + Counters.add("jdk.module.boot.5.loadModulesTime", t5); // Step 6: Define all modules to the VM long t6 = System.nanoTime(); ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf); - PerfCounters.layerCreateTime.addElapsedTimeFrom(t6); + Counters.add("jdk.module.boot.6.layerCreateTime", t6); // Step 7: Miscellaneous // check incubating status - checkIncubatingStatus(cf); + if (systemModules.hasIncubatorModules() || haveModulePath) { + checkIncubatingStatus(cf); + } - // --add-reads, --add-exports/--add-opens, and -illegal-access + // --add-reads, --add-exports/--add-opens, and --illegal-access long t7 = System.nanoTime(); addExtraReads(bootLayer); boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer); - addIllegalAccess(bootLayer, upgradeModulePath, extraExportsOrOpens); - PerfCounters.adjustModulesTime.addElapsedTimeFrom(t7); + addIllegalAccess(upgradeModulePath, systemModules, bootLayer, extraExportsOrOpens); + Counters.add("jdk.module.boot.7.adjustModulesTime", t7); + + // save module finders for later use + if (savedModuleFinder != null) { + unlimitedFinder = new SafeModuleFinder(savedModuleFinder); + if (savedModuleFinder != finder) + limitedFinder = new SafeModuleFinder(finder); + } // total time to initialize - PerfCounters.bootstrapTime.addElapsedTimeFrom(t1); + Counters.add("jdk.module.boot.totalTime", t0); + Counters.publish(); return bootLayer; } @@ -391,7 +427,6 @@ public final class ModuleBootstrap { Configuration cf = SharedSecrets.getJavaLangModuleAccess() .resolveAndBind(ModuleFinder.ofSystem(), Set.of(JAVA_BASE), - false, null); Function clf = ModuleLoaderMap.mappingFunction(cf); @@ -439,7 +474,6 @@ public final class ModuleBootstrap { } } } - } } @@ -489,7 +523,7 @@ public final class ModuleBootstrap { * Creates a finder from the module path that is the value of the given * system property and optionally patched by --patch-module */ - private static ModuleFinder createModulePathFinder(String prop) { + private static ModuleFinder finderFor(String prop) { String s = System.getProperty(prop); if (s == null) { return null; @@ -510,35 +544,48 @@ public final class ModuleBootstrap { */ private static ModulePatcher initModulePatcher() { Map> map = decode("jdk.module.patch.", - File.pathSeparator, - false); + File.pathSeparator, + false); return new ModulePatcher(map); } /** - * Returns the set of module names specified via --add-modules options - * on the command line + * Returns the set of module names specified by --add-module options. */ - private static Set getExtraAddModules() { + private static Set addModules() { String prefix = "jdk.module.addmods."; int index = 0; - // the system property is removed after decoding String value = getAndRemoveProperty(prefix + index); if (value == null) { return Collections.emptySet(); - } - - Set modules = new HashSet<>(); - while (value != null) { - for (String s : value.split(",")) { - if (s.length() > 0) modules.add(s); + } else { + Set modules = new HashSet<>(); + while (value != null) { + for (String s : value.split(",")) { + if (s.length() > 0) modules.add(s); + } + index++; + value = getAndRemoveProperty(prefix + index); } - index++; - value = getAndRemoveProperty(prefix + index); + return modules; } + } - return modules; + /** + * Returns the set of module names specified by --limit-modules. + */ + private static Set limitModules() { + String value = getAndRemoveProperty("jdk.module.limitmods"); + if (value == null) { + return Collections.emptySet(); + } else { + Set names = new HashSet<>(); + for (String name : value.split(",")) { + if (name.length() > 0) names.add(name); + } + return names; + } } /** @@ -676,8 +723,9 @@ public final class ModuleBootstrap { * Process the --illegal-access option (and its default) to open packages * of system modules in the boot layer to code in unnamed modules. */ - private static void addIllegalAccess(ModuleLayer bootLayer, - ModuleFinder upgradeModulePath, + private static void addIllegalAccess(ModuleFinder upgradeModulePath, + SystemModules systemModules, + ModuleLayer bootLayer, boolean extraExportsOrOpens) { String value = getAndRemoveProperty("jdk.module.illegalAccess"); IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT; @@ -702,10 +750,10 @@ public final class ModuleBootstrap { IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder(mode, System.err); - Map> map1 = SystemModules.concealedPackagesToOpen(); - Map> map2 = SystemModules.exportedPackagesToOpen(); + Map> map1 = systemModules.concealedPackagesToOpen(); + Map> map2 = systemModules.exportedPackagesToOpen(); if (map1.isEmpty() && map2.isEmpty()) { - // need to generate maps when on exploded build + // need to generate (exploded build) IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder()); map1 = maps.concealedPackagesToOpen(); map2 = maps.exportedPackagesToOpen(); @@ -906,6 +954,10 @@ public final class ModuleBootstrap { } } + /** + * Returns an iterator that yields all elements of the first iterator + * followed by all the elements of the second iterator. + */ static Iterator concat(Iterator iterator1, Iterator iterator2) { return new Iterator() { @Override @@ -921,23 +973,76 @@ public final class ModuleBootstrap { }; } - static class PerfCounters { + /** + * Wraps a (potentially not thread safe) ModuleFinder created during startup + * for use after startup. + */ + static class SafeModuleFinder implements ModuleFinder { + private final Set mrefs; + private volatile Map nameToModule; - 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 - = PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime"); - static PerfCounter loadModulesTime - = PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime"); - static PerfCounter adjustModulesTime - = PerfCounter.newPerfCounter("jdk.module.bootstrap.adjustModulesTime"); - static PerfCounter bootstrapTime - = PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime"); + SafeModuleFinder(ModuleFinder finder) { + this.mrefs = Collections.unmodifiableSet(finder.findAll()); + } + @Override + public Optional find(String name) { + Objects.requireNonNull(name); + Map nameToModule = this.nameToModule; + if (nameToModule == null) { + this.nameToModule = nameToModule = mrefs.stream() + .collect(Collectors.toMap(m -> m.descriptor().name(), + Function.identity())); + } + return Optional.ofNullable(nameToModule.get(name)); + } + @Override + public Set findAll() { + return mrefs; + } + } + + /** + * Counters for startup performance analysis. + */ + static class Counters { + private static final boolean PUBLISH_COUNTERS; + private static final boolean PRINT_COUNTERS; + private static Map counters; + static { + String s = System.getProperty("jdk.module.boot.usePerfData"); + if (s == null) { + PUBLISH_COUNTERS = false; + PRINT_COUNTERS = false; + } else { + PUBLISH_COUNTERS = true; + PRINT_COUNTERS = s.equals("debug"); + counters = new LinkedHashMap<>(); // preserve insert order + } + } + + /** + * Add a counter + */ + static void add(String name, long start) { + if (PUBLISH_COUNTERS || PRINT_COUNTERS) { + counters.put(name, (System.nanoTime() - start)); + } + } + + /** + * Publish the counters to the instrumentation buffer or stdout. + */ + static void publish() { + if (PUBLISH_COUNTERS || PRINT_COUNTERS) { + for (Map.Entry e : counters.entrySet()) { + String name = e.getKey(); + long value = e.getValue(); + if (PUBLISH_COUNTERS) + PerfCounter.newPerfCounter(name).set(value); + if (PRINT_COUNTERS) + System.out.println(name + " = " + value); + } + } + } } } 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 c0458e0f34e..613e31fc069 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 @@ -200,10 +200,10 @@ public final class ModulePatcher { } /** - * Returns true is this module patcher has no patches. + * Returns true is this module patcher has patches. */ - public boolean isEmpty() { - return map.isEmpty(); + public boolean hasPatches() { + return !map.isEmpty(); } /* diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java index c3cf0a8beec..209131c95c3 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java @@ -68,14 +68,14 @@ public class ModuleReferenceImpl extends ModuleReference { /** * Constructs a new instance of this class. */ - ModuleReferenceImpl(ModuleDescriptor descriptor, - URI location, - Supplier readerSupplier, - ModulePatcher patcher, - ModuleTarget target, - ModuleHashes recordedHashes, - ModuleHashes.HashSupplier hasher, - ModuleResolution moduleResolution) + public ModuleReferenceImpl(ModuleDescriptor descriptor, + URI location, + Supplier readerSupplier, + ModulePatcher patcher, + ModuleTarget target, + ModuleHashes recordedHashes, + ModuleHashes.HashSupplier hasher, + ModuleResolution moduleResolution) { super(descriptor, Objects.requireNonNull(location)); this.location = location; diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java deleted file mode 100644 index 92c4c96cadb..00000000000 --- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * 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.internal.module; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleFinder; -import java.lang.module.ModuleReader; -import java.lang.module.ModuleReference; -import java.net.URI; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.Spliterator; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import jdk.internal.jimage.ImageLocation; -import jdk.internal.jimage.ImageReader; -import jdk.internal.jimage.ImageReaderFactory; -import jdk.internal.misc.JavaNetUriAccess; -import jdk.internal.misc.SharedSecrets; -import jdk.internal.module.ModuleHashes.HashSupplier; -import jdk.internal.perf.PerfCounter; - -/** - * A {@code ModuleFinder} that finds modules that are linked into the - * run-time image. - * - * The modules linked into the run-time image are assumed to have the - * Packages attribute. - */ - -public class SystemModuleFinder implements ModuleFinder { - - private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess(); - - private static final PerfCounter initTime - = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime"); - private static final PerfCounter moduleCount - = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules"); - private static final PerfCounter packageCount - = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages"); - private static final PerfCounter exportsCount - = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports"); - - // singleton finder to find modules in the run-time images - private static final SystemModuleFinder INSTANCE; - - public static SystemModuleFinder getInstance() { - return INSTANCE; - } - - /** - * For now, the module references are created eagerly on the assumption - * that service binding will require all modules to be located. - */ - static { - long t0 = System.nanoTime(); - - INSTANCE = new SystemModuleFinder(); - - initTime.addElapsedTimeFrom(t0); - } - - /** - * Holder class for the ImageReader - */ - private static class SystemImage { - static final ImageReader READER; - static { - long t0 = System.nanoTime(); - READER = ImageReaderFactory.getImageReader(); - initTime.addElapsedTimeFrom(t0); - } - - static ImageReader reader() { - return READER; - } - } - - private static boolean isFastPathSupported() { - return SystemModules.MODULE_NAMES.length > 0; - } - - private static String[] moduleNames() { - if (isFastPathSupported()) - // module names recorded at link time - return SystemModules.MODULE_NAMES; - - // this happens when java.base is patched with java.base - // from an exploded image - return SystemImage.reader().getModuleNames(); - } - - // the set of modules in the run-time image - private final Set modules; - - // maps module name to module reference - private final Map nameToModule; - - // module name to hashes - private final Map hashes; - - private SystemModuleFinder() { - String[] names = moduleNames(); - int n = names.length; - moduleCount.add(n); - - // fastpath is enabled by default. - // It can be disabled for troubleshooting purpose. - boolean disabled = - System.getProperty("jdk.system.module.finder.disabledFastPath") != null; - - ModuleDescriptor[] descriptors; - ModuleTarget[] targets; - ModuleHashes[] recordedHashes; - ModuleResolution[] moduleResolutions; - - // fast loading of ModuleDescriptor of system modules - if (isFastPathSupported() && !disabled) { - descriptors = SystemModules.descriptors(); - targets = SystemModules.targets(); - recordedHashes = SystemModules.hashes(); - moduleResolutions = SystemModules.moduleResolutions(); - } else { - // if fast loading of ModuleDescriptors is disabled - // fallback to read module-info.class - descriptors = new ModuleDescriptor[n]; - targets = new ModuleTarget[n]; - recordedHashes = new ModuleHashes[n]; - moduleResolutions = new ModuleResolution[n]; - ImageReader imageReader = SystemImage.reader(); - for (int i = 0; i < names.length; i++) { - String mn = names[i]; - ImageLocation loc = imageReader.findLocation(mn, "module-info.class"); - ModuleInfo.Attributes attrs = - ModuleInfo.read(imageReader.getResourceBuffer(loc), null); - descriptors[i] = attrs.descriptor(); - targets[i] = attrs.target(); - recordedHashes[i] = attrs.recordedHashes(); - moduleResolutions[i] = attrs.moduleResolution(); - } - } - - Map hashes = null; - boolean secondSeen = false; - // record the hashes to build HashSupplier - for (ModuleHashes mh : recordedHashes) { - if (mh != null) { - // if only one module contain ModuleHashes, use it - if (hashes == null) { - hashes = mh.hashes(); - } else { - if (!secondSeen) { - hashes = new HashMap<>(hashes); - secondSeen = true; - } - hashes.putAll(mh.hashes()); - } - } - } - this.hashes = (hashes == null) ? Map.of() : hashes; - - ModuleReference[] mods = new ModuleReference[n]; - - @SuppressWarnings(value = {"rawtypes", "unchecked"}) - Entry[] map - = (Entry[])new Entry[n]; - - for (int i = 0; i < n; i++) { - ModuleDescriptor md = descriptors[i]; - - // create the ModuleReference - ModuleReference mref = toModuleReference(md, - targets[i], - recordedHashes[i], - hashSupplier(names[i]), - moduleResolutions[i]); - mods[i] = mref; - map[i] = Map.entry(names[i], mref); - - // counters - packageCount.add(md.packages().size()); - exportsCount.add(md.exports().size()); - } - - modules = Set.of(mods); - nameToModule = Map.ofEntries(map); - } - - @Override - public Optional find(String name) { - Objects.requireNonNull(name); - return Optional.ofNullable(nameToModule.get(name)); - } - - @Override - public Set findAll() { - return modules; - } - - private ModuleReference toModuleReference(ModuleDescriptor md, - ModuleTarget target, - ModuleHashes recordedHashes, - HashSupplier hasher, - ModuleResolution mres) { - String mn = md.name(); - URI uri = JNUA.create("jrt", "/".concat(mn)); - - Supplier readerSupplier = new Supplier<>() { - @Override - public ModuleReader get() { - return new ImageModuleReader(mn, uri); - } - }; - - ModuleReference mref = new ModuleReferenceImpl(md, - uri, - readerSupplier, - null, - target, - recordedHashes, - hasher, - mres); - - // may need a reference to a patched module if --patch-module specified - mref = ModuleBootstrap.patcher().patchIfNeeded(mref); - - return mref; - } - - private HashSupplier hashSupplier(String name) { - if (!hashes.containsKey(name)) - return null; - - return new HashSupplier() { - @Override - public byte[] generate(String algorithm) { - return hashes.get(name); - } - }; - } - - /** - * A ModuleReader for reading resources from a module linked into the - * run-time image. - */ - static class ImageModuleReader implements ModuleReader { - private final String module; - private volatile boolean closed; - - /** - * If there is a security manager set then check permission to - * connect to the run-time image. - */ - private static void checkPermissionToConnect(URI uri) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - URLConnection uc = uri.toURL().openConnection(); - sm.checkPermission(uc.getPermission()); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - } - - ImageModuleReader(String module, URI uri) { - checkPermissionToConnect(uri); - this.module = module; - } - - /** - * Returns the ImageLocation for the given resource, {@code null} - * if not found. - */ - private ImageLocation findImageLocation(String name) throws IOException { - Objects.requireNonNull(name); - if (closed) - throw new IOException("ModuleReader is closed"); - ImageReader imageReader = SystemImage.reader(); - if (imageReader != null) { - return imageReader.findLocation(module, name); - } else { - // not an images build - return null; - } - } - - @Override - public Optional find(String name) throws IOException { - ImageLocation location = findImageLocation(name); - if (location != null) { - URI u = URI.create("jrt:/" + module + "/" + name); - return Optional.of(u); - } else { - return Optional.empty(); - } - } - - @Override - public Optional open(String name) throws IOException { - return read(name).map(this::toInputStream); - } - - private InputStream toInputStream(ByteBuffer bb) { // ## -> ByteBuffer? - try { - int rem = bb.remaining(); - byte[] bytes = new byte[rem]; - bb.get(bytes); - return new ByteArrayInputStream(bytes); - } finally { - release(bb); - } - } - - @Override - public Optional read(String name) throws IOException { - ImageLocation location = findImageLocation(name); - if (location != null) { - return Optional.of(SystemImage.reader().getResourceBuffer(location)); - } else { - return Optional.empty(); - } - } - - @Override - public void release(ByteBuffer bb) { - Objects.requireNonNull(bb); - ImageReader.releaseByteBuffer(bb); - } - - @Override - public Stream list() throws IOException { - if (closed) - throw new IOException("ModuleReader is closed"); - - Spliterator s = new ModuleContentSpliterator(module); - return StreamSupport.stream(s, false); - } - - @Override - public void close() { - // nothing else to do - closed = true; - } - } - - /** - * A Spliterator for traversing the resources of a module linked into the - * run-time image. - */ - static class ModuleContentSpliterator implements Spliterator { - final String moduleRoot; - final Deque stack; - Iterator iterator; - - ModuleContentSpliterator(String module) throws IOException { - moduleRoot = "/modules/" + module; - stack = new ArrayDeque<>(); - - // push the root node to the stack to get started - ImageReader.Node dir = SystemImage.reader().findNode(moduleRoot); - if (dir == null || !dir.isDirectory()) - throw new IOException(moduleRoot + " not a directory"); - stack.push(dir); - iterator = Collections.emptyIterator(); - } - - /** - * Returns the name of the next non-directory node or {@code null} if - * there are no remaining nodes to visit. - */ - private String next() throws IOException { - for (;;) { - while (iterator.hasNext()) { - ImageReader.Node node = iterator.next(); - String name = node.getName(); - if (node.isDirectory()) { - // build node - ImageReader.Node dir = SystemImage.reader().findNode(name); - assert dir.isDirectory(); - stack.push(dir); - } else { - // strip /modules/$MODULE/ prefix - return name.substring(moduleRoot.length() + 1); - } - } - - if (stack.isEmpty()) { - return null; - } else { - ImageReader.Node dir = stack.poll(); - assert dir.isDirectory(); - iterator = dir.getChildren().iterator(); - } - } - } - - @Override - public boolean tryAdvance(Consumer action) { - String next; - try { - next = next(); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - if (next != null) { - action.accept(next); - return true; - } else { - return false; - } - } - - @Override - public Spliterator trySplit() { - return null; - } - - @Override - public int characteristics() { - return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE; - } - - @Override - public long estimateSize() { - return Long.MAX_VALUE; - } - } -} diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java new file mode 100644 index 00000000000..5fba5b39ae0 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.module; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import jdk.internal.jimage.ImageLocation; +import jdk.internal.jimage.ImageReader; +import jdk.internal.jimage.ImageReaderFactory; +import jdk.internal.misc.JavaNetUriAccess; +import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.ModuleHashes.HashSupplier; + +/** + * The factory for SystemModules objects and for creating ModuleFinder objects + * that find modules in the runtime image. + * + * This class supports initializing the module system when the runtime is an + * images build, an exploded build, or an images build with java.base patched + * by an exploded java.base. It also supports a testing mode that re-parses + * the module-info.class resources in the run-time image. + */ + +public final class SystemModuleFinders { + private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess(); + + private static final boolean USE_FAST_PATH; + static { + String value = System.getProperty("jdk.system.module.finder.disableFastPath"); + if (value == null) { + USE_FAST_PATH = true; + } else { + USE_FAST_PATH = (value.length() > 0) && !Boolean.parseBoolean(value); + } + } + + // cached ModuleFinder returned from ofSystem + private static volatile ModuleFinder cachedSystemModuleFinder; + + private SystemModuleFinders() { } + + /** + * Returns the SystemModules object to reconstitute all modules. Returns + * null if this is an exploded build or java.base is patched by an exploded + * build. + */ + static SystemModules allSystemModules() { + if (USE_FAST_PATH) { + return SystemModulesMap.allSystemModules(); + } else { + return null; + } + } + + /** + * Returns a SystemModules object to reconstitute the modules for the + * given initial module. If the initial module is null then return the + * SystemModules object to reconstitute the default modules. + * + * Return null if there is no SystemModules class for the initial module, + * this is an exploded build, or java.base is patched by an exploded build. + */ + static SystemModules systemModules(String initialModule) { + if (USE_FAST_PATH) { + if (initialModule == null) { + return SystemModulesMap.defaultSystemModules(); + } + + String[] initialModules = SystemModulesMap.moduleNames(); + for (int i = 0; i < initialModules.length; i++) { + String moduleName = initialModules[i]; + if (initialModule.equals(moduleName)) { + String cn = SystemModulesMap.classNames()[i]; + try { + // one-arg Class.forName as java.base may not be defined + Constructor ctor = Class.forName(cn).getConstructor(); + return (SystemModules) ctor.newInstance(); + } catch (Exception e) { + throw new InternalError(e); + } + } + } + } + return null; + } + + /** + * Returns a ModuleFinder that is backed by the given SystemModules object. + * + * @apiNote The returned ModuleFinder is thread safe. + */ + static ModuleFinder of(SystemModules systemModules) { + ModuleDescriptor[] descriptors = systemModules.moduleDescriptors(); + ModuleTarget[] targets = systemModules.moduleTargets(); + ModuleHashes[] recordedHashes = systemModules.moduleHashes(); + ModuleResolution[] moduleResolutions = systemModules.moduleResolutions(); + + int moduleCount = descriptors.length; + ModuleReference[] mrefs = new ModuleReference[moduleCount]; + @SuppressWarnings(value = {"rawtypes", "unchecked"}) + Map.Entry[] map + = (Map.Entry[])new Map.Entry[moduleCount]; + + Map nameToHash = generateNameToHash(recordedHashes); + + for (int i = 0; i < moduleCount; i++) { + String name = descriptors[i].name(); + HashSupplier hashSupplier = hashSupplier(nameToHash, name); + ModuleReference mref = toModuleReference(descriptors[i], + targets[i], + recordedHashes[i], + hashSupplier, + moduleResolutions[i]); + mrefs[i] = mref; + map[i] = Map.entry(name, mref); + } + + return new SystemModuleFinder(mrefs, map); + } + + /** + * Returns the ModuleFinder to find all system modules. Supports both + * images and exploded builds. + * + * @apiNote Used by ModuleFinder.ofSystem() + */ + public static ModuleFinder ofSystem() { + ModuleFinder finder = cachedSystemModuleFinder; + if (finder != null) { + return finder; + } + + // probe to see if this is an images build + String home = System.getProperty("java.home"); + Path modules = Paths.get(home, "lib", "modules"); + if (Files.isRegularFile(modules)) { + if (USE_FAST_PATH) { + SystemModules systemModules = allSystemModules(); + if (systemModules != null) { + finder = of(systemModules); + } + } + + // fall back to parsing the module-info.class files in image + if (finder == null) { + finder = ofModuleInfos(); + } + + cachedSystemModuleFinder = finder; + return finder; + + } + + // exploded build (do not cache module finder) + Path dir = Paths.get(home, "modules"); + if (!Files.isDirectory(dir)) + throw new InternalError("Unable to detect the run-time image"); + ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir); + return new ModuleFinder() { + @Override + public Optional find(String name) { + PrivilegedAction> pa = () -> f.find(name); + return AccessController.doPrivileged(pa); + } + @Override + public Set findAll() { + PrivilegedAction> pa = f::findAll; + return AccessController.doPrivileged(pa); + } + }; + } + + /** + * Parses the module-info.class of all module in the runtime image and + * returns a ModuleFinder to find the modules. + * + * @apiNote The returned ModuleFinder is thread safe. + */ + private static ModuleFinder ofModuleInfos() { + // parse the module-info.class in every module + Map nameToAttributes = new HashMap<>(); + Map nameToHash = new HashMap<>(); + ImageReader reader = SystemImage.reader(); + for (String mn : reader.getModuleNames()) { + ImageLocation loc = reader.findLocation(mn, "module-info.class"); + ModuleInfo.Attributes attrs + = ModuleInfo.read(reader.getResourceBuffer(loc), null); + + nameToAttributes.put(mn, attrs); + ModuleHashes hashes = attrs.recordedHashes(); + if (hashes != null) { + for (String name : hashes.names()) { + nameToHash.computeIfAbsent(name, k -> hashes.hashFor(name)); + } + } + } + + // create a ModuleReference for each module + Set mrefs = new HashSet<>(); + Map nameToModule = new HashMap<>(); + for (Map.Entry e : nameToAttributes.entrySet()) { + String mn = e.getKey(); + ModuleInfo.Attributes attrs = e.getValue(); + HashSupplier hashSupplier = hashSupplier(nameToHash, mn); + ModuleReference mref = toModuleReference(attrs.descriptor(), + attrs.target(), + attrs.recordedHashes(), + hashSupplier, + attrs.moduleResolution()); + mrefs.add(mref); + nameToModule.put(mn, mref); + } + + return new SystemModuleFinder(mrefs, nameToModule); + } + + /** + * A ModuleFinder that finds module in an array or set of modules. + */ + private static class SystemModuleFinder implements ModuleFinder { + final Set mrefs; + final Map nameToModule; + + SystemModuleFinder(ModuleReference[] array, + Map.Entry[] map) { + this.mrefs = Set.of(array); + this.nameToModule = Map.ofEntries(map); + } + + SystemModuleFinder(Set mrefs, + Map nameToModule) { + this.mrefs = Collections.unmodifiableSet(mrefs); + this.nameToModule = Collections.unmodifiableMap(nameToModule); + } + + @Override + public Optional find(String name) { + Objects.requireNonNull(name); + return Optional.ofNullable(nameToModule.get(name)); + } + + @Override + public Set findAll() { + return mrefs; + } + } + + /** + * Creates a ModuleReference to the system module. + */ + static ModuleReference toModuleReference(ModuleDescriptor descriptor, + ModuleTarget target, + ModuleHashes recordedHashes, + HashSupplier hasher, + ModuleResolution mres) { + String mn = descriptor.name(); + URI uri = JNUA.create("jrt", "/".concat(mn)); + + Supplier readerSupplier = new Supplier<>() { + @Override + public ModuleReader get() { + return new SystemModuleReader(mn, uri); + } + }; + + ModuleReference mref = new ModuleReferenceImpl(descriptor, + uri, + readerSupplier, + null, + target, + recordedHashes, + hasher, + mres); + + // may need a reference to a patched module if --patch-module specified + mref = ModuleBootstrap.patcher().patchIfNeeded(mref); + + return mref; + } + + /** + * Generates a map of module name to hash value. + */ + static Map generateNameToHash(ModuleHashes[] recordedHashes) { + Map nameToHash = null; + + boolean secondSeen = false; + // record the hashes to build HashSupplier + for (ModuleHashes mh : recordedHashes) { + if (mh != null) { + // if only one module contain ModuleHashes, use it + if (nameToHash == null) { + nameToHash = mh.hashes(); + } else { + if (!secondSeen) { + nameToHash = new HashMap<>(nameToHash); + secondSeen = true; + } + nameToHash.putAll(mh.hashes()); + } + } + } + return (nameToHash != null) ? nameToHash : Collections.emptyMap(); + } + + /** + * Returns a HashSupplier that returns the hash of the given module. + */ + static HashSupplier hashSupplier(Map nameToHash, String name) { + byte[] hash = nameToHash.get(name); + if (hash != null) { + // avoid lambda here + return new HashSupplier() { + @Override + public byte[] generate(String algorithm) { + return hash; + } + }; + } else { + return null; + } + } + + /** + * Holder class for the ImageReader + * + * @apiNote This class must be loaded before a security manager is set. + */ + private static class SystemImage { + static final ImageReader READER = ImageReaderFactory.getImageReader(); + static ImageReader reader() { + return READER; + } + } + + /** + * A ModuleReader for reading resources from a module linked into the + * run-time image. + */ + private static class SystemModuleReader implements ModuleReader { + private final String module; + private volatile boolean closed; + + /** + * If there is a security manager set then check permission to + * connect to the run-time image. + */ + private static void checkPermissionToConnect(URI uri) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + try { + URLConnection uc = uri.toURL().openConnection(); + sm.checkPermission(uc.getPermission()); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + } + + SystemModuleReader(String module, URI uri) { + checkPermissionToConnect(uri); + this.module = module; + } + + /** + * Returns the ImageLocation for the given resource, {@code null} + * if not found. + */ + private ImageLocation findImageLocation(String name) throws IOException { + Objects.requireNonNull(name); + if (closed) + throw new IOException("ModuleReader is closed"); + ImageReader imageReader = SystemImage.reader(); + if (imageReader != null) { + return imageReader.findLocation(module, name); + } else { + // not an images build + return null; + } + } + + @Override + public Optional find(String name) throws IOException { + ImageLocation location = findImageLocation(name); + if (location != null) { + URI u = URI.create("jrt:/" + module + "/" + name); + return Optional.of(u); + } else { + return Optional.empty(); + } + } + + @Override + public Optional open(String name) throws IOException { + return read(name).map(this::toInputStream); + } + + private InputStream toInputStream(ByteBuffer bb) { // ## -> ByteBuffer? + try { + int rem = bb.remaining(); + byte[] bytes = new byte[rem]; + bb.get(bytes); + return new ByteArrayInputStream(bytes); + } finally { + release(bb); + } + } + + @Override + public Optional read(String name) throws IOException { + ImageLocation location = findImageLocation(name); + if (location != null) { + return Optional.of(SystemImage.reader().getResourceBuffer(location)); + } else { + return Optional.empty(); + } + } + + @Override + public void release(ByteBuffer bb) { + Objects.requireNonNull(bb); + ImageReader.releaseByteBuffer(bb); + } + + @Override + public Stream list() throws IOException { + if (closed) + throw new IOException("ModuleReader is closed"); + + Spliterator s = new ModuleContentSpliterator(module); + return StreamSupport.stream(s, false); + } + + @Override + public void close() { + // nothing else to do + closed = true; + } + } + + /** + * A Spliterator for traversing the resources of a module linked into the + * run-time image. + */ + private static class ModuleContentSpliterator implements Spliterator { + final String moduleRoot; + final Deque stack; + Iterator iterator; + + ModuleContentSpliterator(String module) throws IOException { + moduleRoot = "/modules/" + module; + stack = new ArrayDeque<>(); + + // push the root node to the stack to get started + ImageReader.Node dir = SystemImage.reader().findNode(moduleRoot); + if (dir == null || !dir.isDirectory()) + throw new IOException(moduleRoot + " not a directory"); + stack.push(dir); + iterator = Collections.emptyIterator(); + } + + /** + * Returns the name of the next non-directory node or {@code null} if + * there are no remaining nodes to visit. + */ + private String next() throws IOException { + for (;;) { + while (iterator.hasNext()) { + ImageReader.Node node = iterator.next(); + String name = node.getName(); + if (node.isDirectory()) { + // build node + ImageReader.Node dir = SystemImage.reader().findNode(name); + assert dir.isDirectory(); + stack.push(dir); + } else { + // strip /modules/$MODULE/ prefix + return name.substring(moduleRoot.length() + 1); + } + } + + if (stack.isEmpty()) { + return null; + } else { + ImageReader.Node dir = stack.poll(); + assert dir.isDirectory(); + iterator = dir.getChildren().iterator(); + } + } + } + + @Override + public boolean tryAdvance(Consumer action) { + String next; + try { + next = next(); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + if (next != null) { + action.accept(next); + return true; + } else { + return false; + } + } + + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public int characteristics() { + return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE; + } + + @Override + public long estimateSize() { + return Long.MAX_VALUE; + } + } +} 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 18817cc9bc5..8f6b8daa33c 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 @@ -26,94 +26,73 @@ package jdk.internal.module; import java.lang.module.ModuleDescriptor; -import java.util.Collections; import java.util.Map; import java.util.Set; /** - * SystemModules class will be generated at link time to create - * ModuleDescriptor for the system modules directly to improve - * the module descriptor reconstitution time. - * - * This will skip parsing of module-info.class file and validating - * names such as module name, package name, service and provider type names. - * It also avoids taking a defensive copy of any collection. + * A SystemModules object reconstitutes module descriptors and other modules + * attributes in an efficient way to avoid parsing module-info.class files at + * startup. Implementations of this class are generated by the "system modules" + * jlink plugin. * + * @see SystemModuleFinders * @see jdk.tools.jlink.internal.plugins.SystemModulesPlugin */ -public final class SystemModules { - /** - * Name of the system modules. - * - * 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[0]; + +interface SystemModules { /** - * 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. + * Returns false if the module reconstituted by this SystemModules object + * have no overlapping packages. Returns true if there are overlapping + * packages or unknown. */ - public static int PACKAGES_IN_BOOT_LAYER = 1024; + boolean hasSplitPackages(); /** - * Return true if there are no split packages in the run-time image. + * Return false if the modules reconstituted by this SystemModules object + * do not include any incubator modules. Returns true if there are + * incubating modules or unknown. */ - public static boolean hasSplitPackages() { - return true; - } + boolean hasIncubatorModules(); /** - * Returns a non-empty array of ModuleDescriptor objects in the run-time image. - * - * When running an exploded image it returns an empty array. + * Returns the non-empty array of ModuleDescriptor objects. */ - public static ModuleDescriptor[] descriptors() { - throw new InternalError("expected to be overridden at link time"); - } + ModuleDescriptor[] moduleDescriptors(); /** - * Returns a non-empty array of ModuleTarget objects in the run-time image. - * - * When running an exploded image it returns an empty array. + * Returns the array of ModuleTarget objects. The array elements correspond + * to the array of ModuleDescriptor objects. */ - public static ModuleTarget[] targets() { - throw new InternalError("expected to be overridden at link time"); - } + ModuleTarget[] moduleTargets(); /** - * Returns a non-empty array of ModuleHashes recorded in each module - * in the run-time image. - * - * When running an exploded image it returns an empty array. + * Returns the array of ModuleHashes objects. The array elements correspond + * to the array of ModuleDescriptor objects. */ - public static ModuleHashes[] hashes() { - throw new InternalError("expected to be overridden at link time"); - } + ModuleHashes[] moduleHashes(); /** - * Returns a non-empty array of ModuleResolutions in the run-time image. + * Returns the array of ModuleResolution objects. The array elements correspond + * to the array of ModuleDescriptor objects. */ - public static ModuleResolution[] moduleResolutions() { - throw new InternalError("expected to be overridden at link time"); - } + ModuleResolution[] moduleResolutions(); + + /** + * Returns the map representing readability graph for the modules reconstituted + * by this SystemModules object. + */ + Map> moduleReads(); /** * Returns the map of module concealed packages to open. The map key is the * module name, the value is the set of concealed packages to open. */ - public static Map> concealedPackagesToOpen() { - return Collections.emptyMap(); - } + Map> concealedPackagesToOpen(); /** * Returns the map of module exported packages to open. The map key is the * module name, the value is the set of exported packages to open. */ - public static Map> exportedPackagesToOpen() { - return Collections.emptyMap(); - } + Map> exportedPackagesToOpen(); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java new file mode 100644 index 00000000000..1c7ff8886d5 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.module; + +/** + * This class is generated/overridden at link time to return the names of the + * SystemModules classes generated at link time. + * + * @see SystemModuleFinders + * @see jdk.tools.jlink.internal.plugins.SystemModulesPlugin + */ + +class SystemModulesMap { + + /** + * Returns the SystemModules object to reconstitute all modules or null + * if this is an exploded build. + */ + static SystemModules allSystemModules() { + return null; + } + + /** + * Returns the SystemModules object to reconstitute default modules or null + * if this is an exploded build. + */ + static SystemModules defaultSystemModules() { + return null; + } + + /** + * Returns the array of initial module names identified at link time. + */ + static String[] moduleNames() { + return new String[0]; + } + + /** + * Returns the array of of SystemModules class names. The elements + * correspond to the elements in the array returned by moduleNames(). + */ + static String[] classNames() { + return new String[0]; + } +} \ No newline at end of file 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 f2670e55200..384b67734a3 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 @@ -316,8 +316,7 @@ public class Reflection { */ public static boolean isCallerSensitive(Method m) { final ClassLoader loader = m.getDeclaringClass().getClassLoader(); - if (VM.isSystemDomainLoader(loader) || - loader == ClassLoaders.platformClassLoader()) { + if (VM.isSystemDomainLoader(loader)) { return m.isAnnotationPresent(CallerSensitive.class); } return false; diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java index c4c85e425ec..3c3f5fc42f0 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * 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,18 @@ package sun.nio.ch; import java.io.IOException; -import java.nio.channels.*; -import java.nio.channels.spi.*; import java.net.SocketException; -import java.util.*; +import java.nio.channels.ClosedSelectorException; +import java.nio.channels.IllegalSelectorException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.AbstractSelector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; /** @@ -54,23 +62,18 @@ public abstract class SelectorImpl super(sp); keys = new HashSet<>(); selectedKeys = new HashSet<>(); - if (Util.atBugLevel("1.4")) { - publicKeys = keys; - publicSelectedKeys = selectedKeys; - } else { - publicKeys = Collections.unmodifiableSet(keys); - publicSelectedKeys = Util.ungrowableSet(selectedKeys); - } + publicKeys = Collections.unmodifiableSet(keys); + publicSelectedKeys = Util.ungrowableSet(selectedKeys); } public Set keys() { - if (!isOpen() && !Util.atBugLevel("1.4")) + if (!isOpen()) throw new ClosedSelectorException(); return publicKeys; } public Set selectedKeys() { - if (!isOpen() && !Util.atBugLevel("1.4")) + if (!isOpen()) throw new ClosedSelectorException(); return publicSelectedKeys; } 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 5a5e51d71ef..ba62bb34de3 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * 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,16 @@ package sun.nio.ch; -import java.lang.reflect.*; import java.io.FileDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.*; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; @@ -456,21 +459,4 @@ public class Util { } return dbb; } - - - // -- Bug compatibility -- - - private static volatile String bugLevel; - - static boolean atBugLevel(String bl) { // package-private - if (bugLevel == null) { - if (!jdk.internal.misc.VM.isBooted()) - return false; - 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/security/ssl/HandshakeMessage.java b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java index 8477456c4d5..cf3648685ba 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java @@ -79,6 +79,9 @@ public abstract class HandshakeMessage { public static final Debug debug = Debug.getInstance("ssl"); // enum HandshakeType: + // + // Please update the isUnsupported() method accordingly if the handshake + // types get updated in the future. static final byte ht_hello_request = 0; // RFC 5246 static final byte ht_client_hello = 1; // RFC 5246 static final byte ht_server_hello = 2; // RFC 5246 @@ -130,6 +133,24 @@ public abstract class HandshakeMessage { return b; } + static boolean isUnsupported(byte handshakeType) { + return (handshakeType != ht_hello_request) && + (handshakeType != ht_client_hello) && + (handshakeType != ht_server_hello) && + (handshakeType != ht_hello_verify_request) && + (handshakeType != ht_new_session_ticket) && + (handshakeType != ht_certificate) && + (handshakeType != ht_server_key_exchange) && + (handshakeType != ht_certificate_request) && + (handshakeType != ht_server_hello_done) && + (handshakeType != ht_certificate_verify) && + (handshakeType != ht_client_key_exchange) && + (handshakeType != ht_finished) && + (handshakeType != ht_certificate_url) && + (handshakeType != ht_certificate_status) && + (handshakeType != ht_supplemental_data); + } + private static byte[] genPad(int b, int count) { byte[] padding = new byte[count]; Arrays.fill(padding, (byte)b); diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java index e26495b3c5f..f2813d57dd7 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java @@ -1034,6 +1034,12 @@ abstract class Handshaker { input.mark(4); messageType = (byte)input.getInt8(); + if (HandshakeMessage.isUnsupported(messageType)) { + throw new SSLProtocolException( + "Received unsupported or unknown handshake message: " + + messageType); + } + messageLen = input.getInt24(); if (input.available() < messageLen) { diff --git a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java index bc63fba83ad..0fe51563caa 100644 --- a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java +++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,8 @@ import javax.security.auth.Subject; * must not be null; the behavior is unspecified if it is.

    * *

    Class loading aspects are detailed in the - * - * JMX Specification, version 1.4 PDF document.

    + * + * JMX Specification, version 1.4

    * *

    Most methods in this interface parallel methods in the {@link * MBeanServerConnection} interface. Where an aspect of the behavior diff --git a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html index fb58ff80547..be95841191d 100644 --- a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html +++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html @@ -2,7 +2,7 @@ RMI connector \n" + + "\n" + "

    This is the first line." + " Note the newlines before the <p> is relevant.

    "); diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java index b5ca0681671..0bfc7706a9f 100644 --- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java +++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java @@ -161,7 +161,9 @@ public class TestHtmlVersion extends JavadocTester { + "", "
    \n" + "
    ", - "
    \n" + "
    \n" + + "\n" + + "\n" + "
    Test package.
    ", "
  • Catalog Features
    FILESFILESA semicolon-delimited list of URIs to locate the catalog files. * The URIs must be absolute and have a URL protocol handler for the URI scheme. *
    PREFERPREFERIndicates the preference between the public and system * identifiers. The default value is public [3].javax.xml.catalog.prefer
    DEFERDEFERIndicates that the alternative catalogs including those * specified in delegate entries or nextCatalog are not read until they are * needed. The default value is true.
    RESOLVERESOLVEDetermines the action if there is no matching entry found after * all of the specified catalogs are exhausted. The default is strict.javax.xml.catalog.resolve [4]
    {@code \p{Alpha}}An alphabetic character:{@code \p{IsAlphabetic}}
    {@code \p{Digit}}A decimal digit character:{@code p{IsDigit}}
    A decimal digit character:{@code \p{IsDigit}}
    {@code \p{Alnum}}An alphanumeric character:{@code [\p{IsAlphabetic}\p{IsDigit}]}
    {@code \p{Punct}}A punctuation character:{@code p{IsPunctuation}}
    A punctuation character:{@code \p{IsPunctuation}}
    {@code \p{Graph}}A visible character: {@code [^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]}
    {@code \p{Print}}
    ", "
    ", diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java index a4378fc52dc..094218a4a4f 100644 --- a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java +++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * 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 4720957 5020118 8026567 8038976 + * @bug 4720957 5020118 8026567 8038976 8184969 * @summary Test to make sure that -link and -linkoffline link to * right files, and URLs with and without trailing slash are accepted. * @author jamieh @@ -135,6 +135,46 @@ public class TestLinkOption extends JavadocTester { // this is the text that is given when there is a problem with a URL checkOutput(Output.OUT, false, "warning - Error fetching URL"); + + // check multiple link options + javadoc("-d", "out5", + "-sourcepath", testSrc, + "-link", "../" + "out1", + "-link", "../" + "out2", + "pkg3"); + checkExit(Exit.OK); + checkOutput("pkg3/A.html", true, + "
    public class A\n"
    +                + "extends java.lang.Object
    \n" + + "
    Test links.\n" + + "
    \n" + + " link to pkg2.C2\n" + + "
    \n" + + " " + + "link to mylib.lang.StringBuilderChild.
    \n" + ); + + // check multiple linkoffline options + javadoc("-d", "out6", + "-sourcepath", testSrc, + "-linkoffline", "../copy/out1", "out1", + "-linkoffline", "../copy/out2", "out2", + "pkg3"); + checkExit(Exit.OK); + checkOutput("pkg3/A.html", true, + "
    public class A\n"
    +                        + "extends java.lang.Object
    \n" + + "
    Test links.\n" + + "
    \n" + + " link to pkg2.C2\n" + + "
    \n" + + " " + + "link to mylib.lang.StringBuilderChild.
    \n" + ); } /* diff --git a/langtools/test/jdk/javadoc/doclet/testLinkOption/pkg3/A.java b/langtools/test/jdk/javadoc/doclet/testLinkOption/pkg3/A.java new file mode 100644 index 00000000000..afff357ed42 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/pkg3/A.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 pkg3; + +/** + * Test links. + *
    + * {@link pkg2.C2 link to pkg2.C2} + *
    + * {@link mylib.lang.StringBuilderChild link to mylib.lang.StringBuilderChild}. + */ + +public class A {} diff --git a/langtools/test/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java b/langtools/test/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java new file mode 100644 index 00000000000..aeb9b2486ab --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 8185151 + * @summary test that navigation summary links are not linked when there are no dependencies + * @modules jdk.javadoc/jdk.javadoc.internal.api + * jdk.javadoc/jdk.javadoc.internal.tool + * @library ../lib /tools/lib + * @build toolbox.ToolBox toolbox.ModuleBuilder JavadocTester + * @run main TestModuleServicesLink + */ + +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.*; + +public class TestModuleServicesLink extends JavadocTester { + + public final ToolBox tb; + public static void main(String... args) throws Exception { + TestModuleServicesLink tester = new TestModuleServicesLink (); + tester.runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + public TestModuleServicesLink () { + tb = new ToolBox(); + } + + @Test + public void checkNavbarWithServices1(Path base) throws Exception { + ModuleBuilder mb = new ModuleBuilder(tb, "m") + .comment("module m.\n@uses p1.A") + .uses("p1.A") + .uses("p1.B") + .exports("p1") + .classes("package p1; public class A {}") + .classes("package p1; public class B {}"); + mb.write(base); + + javadoc("-d", base.toString() + "/out", + "-quiet", + "--module-source-path", base.toString(), + "--module", "m"); + checkExit(Exit.OK); + + checkOutput("m-summary.html", true, + "Description |" + + " Modules |" + + " Packages |" + + " Services"); + + } + + @Test + public void checkNavbarWithServices2(Path base) throws Exception { + ModuleBuilder mb = new ModuleBuilder(tb, "m") + .comment("module m.\n@provides p1.A") + .provides("p1.A", "p1.B") + .exports("p1") + .classes("package p1; public interface A {}") + .classes("package p1; public class B implements A {}"); + mb.write(base); + + javadoc("-d", base.toString() + "/out", + "-quiet", + "--module-source-path", base.toString(), + "--module", "m"); + checkExit(Exit.OK); + + checkOutput("m-summary.html", true, + "Description |" + + " Modules |" + + " Packages |" + + " Services"); + + } + + @Test + public void checkNavbarWithoutServices(Path base) throws Exception { + ModuleBuilder mb = new ModuleBuilder(tb, "m") + .exports("p1") + .classes("package p1; public class A {}") + .classes("package p1; public class B {}"); + mb.write(base); + + javadoc("-d", base.toString() + "/out", + "-quiet", + "--module-source-path", base.toString(), + "--module", "m"); + checkExit(Exit.OK); + + checkOutput("m-summary.html", true, + "Description | Modules |" + + " Packages |" + + " Services"); + } + +} diff --git a/langtools/test/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java b/langtools/test/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java new file mode 100644 index 00000000000..01606e32fa6 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 8185194 + * @summary Test anchor for package description in package summary page + * @library ../lib/ + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build JavadocTester TestPackageDescription + * @run main TestPackageDescription + */ + +public class TestPackageDescription extends JavadocTester { + + public static void main(String... args) throws Exception { + TestPackageDescription tester = new TestPackageDescription(); + tester.runTests(); + } + + @Test + void test1() { + javadoc("-d", "out", + "-sourcepath", testSrc, + "pkg", + "-html5"); + checkExit(Exit.OK); + + checkOutput("pkg/package-summary.html", true, + "\n" + + "\n" + + "\n" + + "
    package description
    \n"); + } + + @Test + void test2() { + javadoc("-d", "out-2", + "-sourcepath", testSrc, + "pkg"); + checkExit(Exit.OK); + + checkOutput("pkg/package-summary.html", true, + "\n" + + "\n" + + "\n" + + "
    package description
    \n"); + } +} diff --git a/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/A.java b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/A.java new file mode 100644 index 00000000000..c7157719d42 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/A.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 pkg; + +public class A { + + public A() { + } + +} diff --git a/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/package-info.java b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/package-info.java new file mode 100644 index 00000000000..b37ee3797fa --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/package-info.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 description + * + */ +package pkg; diff --git a/langtools/test/jdk/jshell/ExternalEditorTest.java b/langtools/test/jdk/jshell/ExternalEditorTest.java index 1c421e268a7..009afd87815 100644 --- a/langtools/test/jdk/jshell/ExternalEditorTest.java +++ b/langtools/test/jdk/jshell/ExternalEditorTest.java @@ -28,6 +28,7 @@ * @modules jdk.jshell/jdk.internal.jshell.tool * @build ReplToolTesting CustomEditor EditorTestBase * @run testng ExternalEditorTest + * @key intermittent */ import java.io.BufferedWriter; diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 8bb2e42e1b4..52f64b895d0 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -428,3 +428,6 @@ fed3f329875710c74f3ec1a0c4714046a79af100 jdk-10+14 aa7404e062b95f679018f25eaaf933dcf0cf3f2b jdk-9+177 f8a0c4895b2abe64a8c55af6117ffda192e34d30 jdk-10+15 f456f59dad3f6b74bcc3c668a56d51f5955cfb28 jdk-10+16 +7497ad85759ff010f44344b553223d1647fb6eba jdk-9+178 +3adfb547e3e49e304ffc82d8c6489cb830b74d62 jdk-9+179 +6ac0ca441ccb9ccc49c5007248dc1f3af8076a71 jdk-10+17 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java index dc172a88683..9a6b5eae76d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java @@ -90,9 +90,9 @@ import jdk.nashorn.tools.ShellFunctions; @ScriptClass("Global") public final class Global extends Scope { // This special value is used to flag a lazily initialized global property. - // This also serves as placeholder value used in place of a location property - // (__FILE__, __DIR__, __LINE__) private static final Object LAZY_SENTINEL = new Object(); + // This serves as placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__) + private static final Object LOCATION_PLACEHOLDER = new Object(); private static final String PACKAGE_PREFIX = "jdk.nashorn.internal.objects."; @@ -916,7 +916,7 @@ public final class Global extends Scope { public volatile Object org; /** - * Getter for the Nashorn extension: Java access - global.javaImporter. + * Getter for the Nashorn extension: Java access - global.JavaImporter. * * @param self self reference * @return the value of the JavaImporter property @@ -931,7 +931,7 @@ public final class Global extends Scope { } /** - * Setter for the Nashorn extension: Java access - global.javaImporter. + * Setter for the Nashorn extension: Java access - global.JavaImporter. * * @param self self reference * @param value value of the JavaImporter property @@ -975,15 +975,15 @@ public final class Global extends Scope { /** Nashorn extension: current script's file name */ @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public static final Object __FILE__ = LAZY_SENTINEL; + public static final Object __FILE__ = LOCATION_PLACEHOLDER; /** Nashorn extension: current script's directory */ @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public static final Object __DIR__ = LAZY_SENTINEL; + public static final Object __DIR__ = LOCATION_PLACEHOLDER; /** Nashorn extension: current source line number being executed */ @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT) - public static final Object __LINE__ = LAZY_SENTINEL; + public static final Object __LINE__ = LOCATION_PLACEHOLDER; private volatile NativeDate DEFAULT_DATE; @@ -2093,6 +2093,9 @@ public final class Global extends Scope { } private synchronized ScriptFunction getBuiltinJavaImporter() { + if (getContext().getEnv()._no_java) { + throw new IllegalStateException(); + } if (this.builtinJavaImporter == null) { this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class); } @@ -2100,6 +2103,9 @@ public final class Global extends Scope { } private synchronized ScriptObject getBuiltinJavaApi() { + if (getContext().getEnv()._no_java) { + throw new IllegalStateException(); + } if (this.builtinJavaApi == null) { this.builtinJavaApi = initConstructor("Java", ScriptObject.class); this.builtInJavaExtend = (ScriptFunction)builtinJavaApi.get("extend"); @@ -2325,7 +2331,7 @@ public final class Global extends Scope { * @return true if the value is a placeholder, false otherwise. */ public static boolean isLocationPropertyPlaceholder(final Object placeholder) { - return placeholder == LAZY_SENTINEL; + return placeholder == LOCATION_PLACEHOLDER; } /** @@ -2628,6 +2634,17 @@ public final class Global extends Scope { this.javaApi = LAZY_SENTINEL; this.javaImporter = LAZY_SENTINEL; initJavaAccess(); + } else { + // delete nasgen-created global properties related to java access + this.delete("Java", false); + this.delete("JavaImporter", false); + this.delete("Packages", false); + this.delete("com", false); + this.delete("edu", false); + this.delete("java", false); + this.delete("javafx", false); + this.delete("javax", false); + this.delete("org", false); } if (! env._no_typed_arrays) { diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java index 7f535405663..a01e223d5ae 100644 --- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java @@ -25,6 +25,7 @@ package jdk.nashorn.internal.runtime.test; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.File; import javax.script.ScriptEngine; @@ -77,6 +78,65 @@ public class ClassFilterTest { } catch (final ScriptException e) { //emtpy } + try { + engine.eval("Java"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("JavaImporter"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("Packages"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("com"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("edu"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("java"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("javafx"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("javax"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + engine.eval("org"); + fail("TypeError should have been thrown"); + } catch (final ScriptException e) { + //emtpy + } + try { + assertEquals(engine.eval("Java = this[\"__LINE__\"]; Java === this[\"__LINE__\"]"), Boolean.TRUE); + } catch (final ScriptException e) { + fail("Unexpected exception", e); + } } @Test