--- a/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14
878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15
4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16
+7db699468b4f84abbcc01647e5a964409737411a jdk-10+17
--- a/.hgtags-top-repo Mon Aug 07 10:02:39 2017 +0530
+++ b/.hgtags-top-repo Mon Aug 07 09:45:38 2017 -0700
@@ -437,3 +437,6 @@
a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177
a6c830ee8a6798b186730475e700027cdf4598aa jdk-10+15
2fe66ca1e2b3c361f949de9cb2894661dc0a3fa2 jdk-10+16
+ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178
+252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179
+a133a7d1007b1456bc62824382fd8ac93b45d329 jdk-10+17
--- a/corba/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/corba/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -437,3 +437,6 @@
c72e9d3823f04cb3ef3166646dfea9e4c2769133 jdk-9+177
15f59cfc6fbe9387423fb173e962265c7b5d357e jdk-10+15
b82b62ed5debda2d98dda597506ef29cf947fbae jdk-10+16
+9c1e9712648921ae389d623042d22561fad82d75 jdk-9+178
+24390da83c5ee9e23ceafbcaff4460a01e37bb3a jdk-9+179
+50ff1fd66362f212a8db6de76089d9d0ffa4df0f jdk-10+17
--- a/hotspot/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -597,3 +597,6 @@
1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177
c1f3649a3a42f124b418a5a916dbad13d059b757 jdk-10+15
2fe2a593e8ebf3a9e4dcd9ba3333a7b43126589d jdk-10+16
+9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178
+d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179
+73e2cb8700bfa51304bd4b02f224620859a3f600 jdk-10+17
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Aug 07 09:45:38 2017 -0700
@@ -14394,7 +14394,7 @@
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 @@
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 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);
--- a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -49,12 +49,11 @@
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);
--- a/hotspot/src/cpu/arm/vm/arm.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/arm/vm/arm.ad Mon Aug 07 09:45:38 2017 -0700
@@ -2695,6 +2695,30 @@
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 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 @@
%}
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 @@
%}
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 @@
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 @@
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 @@
%}
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) %{
--- a/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/arm/vm/c2_globals_arm.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -70,7 +70,6 @@
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
--- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -55,7 +55,6 @@
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.
--- a/hotspot/src/cpu/ppc/vm/ppc.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad Mon Aug 07 09:45:38 2017 -0700
@@ -11048,6 +11048,29 @@
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
--- a/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/s390/vm/c2_globals_s390.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -56,7 +56,6 @@
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
--- a/hotspot/src/cpu/s390/vm/s390.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/s390/vm/s390.ad Mon Aug 07 09:45:38 2017 -0700
@@ -8475,6 +8475,24 @@
%}
// 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
--- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -53,7 +53,6 @@
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
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Mon Aug 07 09:45:38 2017 -0700
@@ -3403,6 +3403,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 ) %{
--- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -47,7 +47,6 @@
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);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -116,7 +116,7 @@
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) \
\
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Mon Aug 07 09:45:38 2017 -0700
@@ -4030,6 +4030,26 @@
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 @@
%}
%}
-// Comparision Code used in long compares
+// Comparison Code used in long compares
operand cmpOp_commute() %{
match(Bool);
@@ -4605,6 +4625,23 @@
%}
%}
+// 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 @@
%}
%}
+//======
+// 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 @@
%}
%}
+//======
+// 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 @@
%}
%}
+//======
+// 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)));
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Mon Aug 07 09:45:38 2017 -0700
@@ -11518,6 +11518,48 @@
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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
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 @@
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 @@
"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 @@
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);
}
}
--- a/hotspot/src/share/vm/adlc/archDesc.cpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/adlc/archDesc.cpp Mon Aug 07 09:45:38 2017 -0700
@@ -1166,6 +1166,7 @@
|| 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
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -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, \
--- a/hotspot/src/share/vm/opto/classes.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/classes.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -81,6 +81,7 @@
macro(CmpLTMask)
macro(CmpP)
macro(CmpU)
+macro(CmpUL)
macro(CompareAndSwapB)
macro(CompareAndSwapS)
macro(CompareAndSwapI)
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
// 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 @@
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 @@
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);
--- a/hotspot/src/share/vm/opto/loopnode.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -983,8 +983,8 @@
// 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);
--- a/hotspot/src/share/vm/opto/output.cpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/output.cpp Mon Aug 07 09:45:38 2017 -0700
@@ -1982,6 +1982,7 @@
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 ||
--- a/hotspot/src/share/vm/opto/subnode.cpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/subnode.cpp Mon Aug 07 09:45:38 2017 -0700
@@ -738,6 +738,60 @@
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.
--- a/hotspot/src/share/vm/opto/subnode.hpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/opto/subnode.hpp Mon Aug 07 09:45:38 2017 -0700
@@ -198,6 +198,15 @@
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 {
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Aug 07 09:45:38 2017 -0700
@@ -2013,6 +2013,7 @@
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) \
--- a/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java Mon Aug 07 10:02:39 2017 +0530
+++ b/hotspot/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java Mon Aug 07 09:45:38 2017 -0700
@@ -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
*/
--- a/jaxp/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -437,3 +437,6 @@
332ad9f92632f56f337b8c40edef9a95a42b26bc jdk-9+177
02a876781a3a6193140591d92db7b95ca743eac2 jdk-10+15
d109d55cf642bf2b438624e81f94c18c168f9178 jdk-10+16
+0983b2dbe17ba4fed3af34e0512ca77a9845fe8a jdk-9+178
+87243a3131f79e8b3903eaca6b629abc48f08ace jdk-9+179
+97d6f14334cfd766f57c296a5a707c8a709aeff0 jdk-10+17
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMConfigurationException.java Mon Aug 07 10:02:39 2017 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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 <code>DTMConfigurationException</code> with no
- * detail message.
- */
- public DTMConfigurationException() {
- super("Configuration Error");
- }
-
- /**
- * Create a new <code>DTMConfigurationException</code> with
- * the <code>String </code> specified as an error message.
- *
- * @param msg The error message for the exception.
- */
- public DTMConfigurationException(String msg) {
- super(msg);
- }
-
- /**
- * Create a new <code>DTMConfigurationException</code> with a
- * given <code>Exception</code> base cause of the error.
- *
- * @param e The exception to be encapsulated in a
- * DTMConfigurationException.
- */
- public DTMConfigurationException(Throwable e) {
- super(e);
- }
-
- /**
- * Create a new <code>DTMConfigurationException</code> with the
- * given <code>Exception</code> 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.
- *
- * <p>This constructor is especially useful when an application is
- * creating its own exception from within a DocumentHandler
- * callback.</p>
- *
- * @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);
- }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMException.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 <code>null</code> 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 <i>cause</i> of this throwable to the specified value.
- * (The cause is the throwable that caused this throwable to get thrown.)
- *
- * <p>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 <tt>null</tt> value is
- * permitted, and indicates that the cause is nonexistent or
- * unknown.)
- * @return a reference to this <code>Throwable</code> instance.
- * @throws IllegalArgumentException if <code>cause</code> 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 @@
* @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 @@
* @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;
- }
-
- /**
- * Create a new DTMException from a message and a Locator.
- *
- * <p>This constructor is especially useful when an application is
- * creating its own exception from within a DocumentHandler
- * callback.</p>
- *
- * @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();
+ super(message, e);
}
-
- /**
- * 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) {}
-
- }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/DTMManager.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
*
* @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 @@
// -------------------- 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 @@
{
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;
- } // <init>(String,Exception)
-
- //
- // Public methods
- //
-
- /** Returns the exception associated to this error. */
- Exception getException() {
- return exception;
- } // getException():Exception
-
- } // class ConfigurationError
-
}
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Mon Aug 07 09:45:38 2017 -0700
@@ -34,7 +34,7 @@
* The CatalogFeatures holds a collection of features and properties.
*
*
- * <table class="plain">
+ * <table class="plain" id="CatalogFeatures">
* <caption>Catalog Features</caption>
* <thead>
* <tr>
@@ -55,7 +55,7 @@
* <tbody>
*
* <tr>
- * <th scope="row" style="font-weight:normal">FILES</th>
+ * <th scope="row" style="font-weight:normal" id="FILES">FILES</th>
* <td>A 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.
* </td>
@@ -71,7 +71,7 @@
* </tr>
*
* <tr>
- * <th rowspan="2" scope="row" style="font-weight:normal">PREFER</th>
+ * <th rowspan="2" scope="row" style="font-weight:normal" id="PREFER">PREFER</th>
* <td rowspan="2">Indicates the preference between the public and system
* identifiers. The default value is public [3].</td>
* <td rowspan="2">javax.xml.catalog.prefer</td>
@@ -91,7 +91,7 @@
* </tr>
*
* <tr>
- * <th rowspan="2" scope="row" style="font-weight:normal">DEFER</th>
+ * <th rowspan="2" scope="row" style="font-weight:normal" id="DEFER">DEFER</th>
* <td rowspan="2">Indicates that the alternative catalogs including those
* specified in delegate entries or nextCatalog are not read until they are
* needed. The default value is true.</td>
@@ -111,7 +111,7 @@
* </tr>
*
* <tr>
- * <th rowspan="3" scope="row" style="font-weight:normal">RESOLVE</th>
+ * <th rowspan="3" scope="row" style="font-weight:normal" id="RESOLVE">RESOLVE</th>
* <td rowspan="3">Determines the action if there is no matching entry found after
* all of the specified catalogs are exhausted. The default is strict.</td>
* <td rowspan="3">javax.xml.catalog.resolve [4]</td>
--- a/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java Mon Aug 07 09:45:38 2017 -0700
@@ -34,7 +34,7 @@
/**
* Factory that creates new {@code javax.xml.datatype} {@code Object}s that map XML to/from Java {@code Object}s.
- * <p>
+ * <p id="DatatypeFactory.newInstance">
* 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:
* <ol>
--- a/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/javax/xml/datatype/package-info.java Mon Aug 07 09:45:38 2017 -0700
@@ -149,23 +149,13 @@
* <li>xs:unsignedShort</li>
* </ul>
*
- * <hr>
- *
- * <ul>
- * <li>Author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a></li>
- * <li>See <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">
+ * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">
* W3C XML Schema 1.0 Part 2, Section 3.2.7-14</a>
- * </li>
- * <li>See <a href="http://www.w3.org/TR/xpath-datamodel#dt-dayTimeDuration">
+ * @see <a href="http://www.w3.org/TR/xpath-datamodel#dt-dayTimeDuration">
* XQuery 1.0 and XPath 2.0 Data Model, xdt:dayTimeDuration</a>
- * </li>
- * <li>See <a href="http://www.w3.org/TR/xpath-datamodel#dt-yearMonthDuration">
+ * @see <a href="http://www.w3.org/TR/xpath-datamodel#dt-yearMonthDuration">
* XQuery 1.0 and XPath 2.0 Data Model, xdt:yearMonthDuration</a>
- * </li>
- * <li>Since 1.5</li>
- * </ul>
- *
- * <hr>
* @since 1.5
*/
--- a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerConfigurationException.java Mon Aug 07 09:45:38 2017 -0700
@@ -32,6 +32,8 @@
*/
public class TransformerConfigurationException extends TransformerException {
+ private static final long serialVersionUID = 1285547467942875745L;
+
/**
* Create a new <code>TransformerConfigurationException</code> with no
* detail message.
--- a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerException.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
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 @@
* Returns the cause of this throwable or <code>null</code> 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 @@
* {@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 @@
* @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 @@
* @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 @@
* @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 @@
* @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 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 @@
* 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 @@
* 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<String>) () ->
+ 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 @@
}
return sbuffer.toString();
- } else {
- return null;
- }
}
/**
@@ -291,6 +280,7 @@
* 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 @@
* 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 @@
* 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 @@
} 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 @@
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);
}
+}
--- a/jaxws/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxws/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -440,3 +440,6 @@
b44a721aee3d3b2537754e559fe9ecccadea548b jdk-9+177
6d17fd0a5133a0dd916c77a9a24ae7f0ca402876 jdk-10+15
bc8289ce1ed3ed5fff62152ed46da3be0b60b7c3 jdk-10+16
+d0190aaf1816081d9b2e0577b65b793804896d1e jdk-9+178
+56ac1831ac5924b5092a53a85d6fc68749501fb8 jdk-9+179
+4c07d366c2e177edba7aa54c4b015e4dbf12bc83 jdk-10+17
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Mon Aug 07 09:45:38 2017 -0700
@@ -84,6 +84,14 @@
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 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 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;
}
--- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java Mon Aug 07 09:45:38 2017 -0700
@@ -112,29 +112,13 @@
this.entityResolver = entityResolver;
this.errorReceiver = errReceiver;
this.logic = logic;
- 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);
+ // secure xml processing can be switched off if input requires it
+ boolean disableXmlSecurity = options == null ? false : options.disableXmlSecurity;
- 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());
- }
- }
-
+ DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(disableXmlSecurity);
+ this.parserFactory = XmlUtil.newSAXParserFactory(disableXmlSecurity);
+ try {
+ this.documentBuilder = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new AssertionError(e);
}
--- a/jdk/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -439,3 +439,5 @@
3281b964ab104002623d744e8b77a12269b70acd jdk-10+16
443025bee731eb2225371b92c1c74b519b7baf33 jdk-9+178
06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179
+d93f2fd542b7d7855c2cd49ae15ebcc3d441a83b jdk-10+17
+c4b709bad6c5d29294124de5e74e1e2ac84fcf1f jdk-10+18
--- a/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java Mon Aug 07 09:45:38 2017 -0700
@@ -50,7 +50,12 @@
/**
* 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 @@
if (closed) {
return;
}
- closed = true;
+ synchronized (closeLock) {
+ if (closed) {
+ return;
+ }
+ closed = true;
+ }
Throwable flushException = null;
try {
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Mon Aug 07 09:45:38 2017 -0700
@@ -364,9 +364,9 @@
// 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 @@
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<ClassLoader> pa = module::getClassLoader;
+ cl = AccessController.doPrivileged(pa);
+ } else {
+ cl = module.getClassLoader();
}
- PrivilegedAction<ClassLoader> pa = module::getClassLoader;
- ClassLoader cl = AccessController.doPrivileged(pa);
if (cl != null) {
return cl.loadClass(module, name);
} else {
--- a/jdk/src/java.base/share/classes/java/lang/Module.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/Module.java Mon Aug 07 09:45:38 2017 -0700
@@ -246,7 +246,6 @@
return null;
}
-
// --
// special Module to mean "all unnamed modules"
@@ -257,17 +256,38 @@
private static final Module EVERYONE_MODULE = new Module(null);
private static final Set<Module> 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<Module, Module, Boolean> 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<Module, Module, Map<String, Boolean>> exports =
+ new WeakPairMap<>();
+
+ /**
+ * A module (1st key) uses a service (2nd key)
+ */
+ static final WeakPairMap<Module, Class<?>, Boolean> uses =
+ new WeakPairMap<>();
+ }
+
// -- readability --
// the modules that this module reads
private volatile Set<Module> reads;
- // additional module (2nd key) that some module (1st key) reflectively reads
- private static final WeakPairMap<Module, Module, Boolean> 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 @@
}
// 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 @@
}
// add reflective read
- reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
+ ReflectionData.reads.putIfAbsent(this, other, Boolean.TRUE);
}
}
@@ -408,13 +428,6 @@
// if the value contains EVERYONE_MODULE then the package is exported to all
private volatile Map<String, Set<Module>> 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<Module, Module, Map<String, Boolean>>
- reflectivelyExports = new WeakPairMap<>();
-
-
/**
* Returns {@code true} if this module exports the given package to at
* least the given module.
@@ -600,7 +613,7 @@
*/
private boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) {
// exported or open to all modules
- Map<String, Boolean> exports = reflectivelyExports.get(this, EVERYONE_MODULE);
+ Map<String, Boolean> exports = ReflectionData.exports.get(this, EVERYONE_MODULE);
if (exports != null) {
Boolean b = exports.get(pn);
if (b != null) {
@@ -612,7 +625,7 @@
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 @@
// 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 @@
}
}
- // add package name to reflectivelyExports if absent
- Map<String, Boolean> map = reflectivelyExports
+ // add package name to exports if absent
+ Map<String, Boolean> map = ReflectionData.exports
.computeIfAbsent(this, other,
(m1, m2) -> new ConcurrentHashMap<>());
if (open) {
@@ -932,10 +945,6 @@
// -- services --
- // additional service type (2nd key) that some module (1st key) uses
- private static final WeakPairMap<Module, Class<?>, 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 @@
*/
void implAddUses(Class<?> service) {
if (!canUse(service)) {
- reflectivelyUses.putIfAbsent(this, service, Boolean.TRUE);
+ ReflectionData.uses.putIfAbsent(this, service, Boolean.TRUE);
}
}
@@ -1011,7 +1020,7 @@
return true;
// uses added via addUses
- return reflectivelyUses.containsKeyPair(this, service);
+ return ReflectionData.uses.containsKeyPair(this, service);
}
@@ -1060,8 +1069,11 @@
Function<String, ClassLoader> clf,
ModuleLayer layer)
{
- Map<String, Module> nameToModule = new HashMap<>();
- Map<String, ClassLoader> moduleToLoader = new HashMap<>();
+ boolean isBootLayer = (ModuleLayer.boot() == null);
+
+ int cap = (int)(cf.modules().size() / 0.75f + 1.0f);
+ Map<String, Module> nameToModule = new HashMap<>(cap);
+ Map<String, ClassLoader> nameToLoader = new HashMap<>(cap);
Set<ClassLoader> loaders = new HashSet<>();
boolean hasPlatformModules = false;
@@ -1070,7 +1082,7 @@
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 @@
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 @@
}
// 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 @@
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 @@
return nameToModule;
}
-
/**
* Find the runtime Module corresponding to the given ResolvedModule
* in the given parent layer (or its parents).
@@ -1201,25 +1222,55 @@
.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<String, Module> nameToModule) {
+ Map<String, Set<Module>> exportedPackages = new HashMap<>();
+
+ for (Exports exports : m.getDescriptor().exports()) {
+ String source = exports.source();
+ if (exports.isQualified()) {
+ // qualified exports
+ Set<Module> 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<String, Module> nameToSource,
Map<String, Module> nameToModule,
List<ModuleLayer> 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<String, Set<Module>> openPackages = new HashMap<>();
Map<String, Set<Module>> exportedPackages = new HashMap<>();
@@ -1272,7 +1323,6 @@
if (!targets.isEmpty()) {
exportedPackages.put(source, targets);
}
-
} else {
// unqualified exports
addExportsToAll0(m, source);
--- a/jdk/src/java.base/share/classes/java/lang/System.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Mon Aug 07 09:45:38 2017 -0700
@@ -313,6 +313,10 @@
* @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");
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Aug 07 09:45:38 2017 -0700
@@ -2476,7 +2476,7 @@
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) {
--- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Mon Aug 07 09:45:38 2017 -0700
@@ -31,6 +31,7 @@
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.stream.Collectors;
import java.util.stream.Stream;
+import jdk.internal.module.ModuleReferenceImpl;
+import jdk.internal.module.ModuleTarget;
+
/**
* A configuration that is the result of <a href="package-summary.html#resolution">
* resolution</a> or resolution with <a href="#service-binding">service binding</a>.
@@ -121,11 +125,8 @@
this.targetPlatform = null;
}
- private Configuration(List<Configuration> parents,
- Resolver resolver,
- boolean check)
- {
- Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
+ private Configuration(List<Configuration> parents, Resolver resolver) {
+ Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this);
@SuppressWarnings(value = {"rawtypes", "unchecked"})
Entry<String, ResolvedModule>[] nameEntries
@@ -147,6 +148,62 @@
}
/**
+ * 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<String, Set<String>> map) {
+ int moduleCount = map.size();
+
+ // create map of name -> ResolvedModule
+ @SuppressWarnings(value = {"rawtypes", "unchecked"})
+ Entry<String, ResolvedModule>[] nameEntries
+ = (Entry<String, ResolvedModule>[])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<String, ResolvedModule> nameToModule = Map.ofEntries(nameEntries);
+
+ // create entries for readability graph
+ @SuppressWarnings(value = {"rawtypes", "unchecked"})
+ Entry<ResolvedModule, Set<ResolvedModule>>[] moduleEntries
+ = (Entry<ResolvedModule, Set<ResolvedModule>>[])new Entry[moduleCount];
+ i = 0;
+ for (ResolvedModule resolvedModule : moduleArray) {
+ Set<String> 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
* specified by the static {@link
@@ -233,24 +290,20 @@
/**
* 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<String> roots,
- boolean check,
PrintStream traceOutput)
{
List<Configuration> 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 @@
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 @@
Resolver resolver = new Resolver(before, parentList, after, null);
resolver.resolve(roots).bind();
- return new Configuration(parentList, resolver, true);
+ return new Configuration(parentList, resolver);
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Mon Aug 07 09:45:38 2017 -0700
@@ -2728,10 +2728,15 @@
@Override
public Configuration resolveAndBind(ModuleFinder finder,
Collection<String> 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<String, Set<String>> graph) {
+ return new Configuration(finder, graph);
}
});
}
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java Mon Aug 07 09:45:38 2017 -0700
@@ -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.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,53 +153,14 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("accessSystemModules"));
- PrivilegedAction<ModuleFinder> pa = ModuleFinder::privilegedOfSystem;
+ PrivilegedAction<ModuleFinder> pa = SystemModuleFinders::ofSystem;
return AccessController.doPrivileged(pa);
} else {
- return privilegedOfSystem();
- }
- }
-
- /**
- * 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");
- }
+ return SystemModuleFinders.ofSystem();
}
}
/**
- * 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<ModuleReference> find(String name) {
- PrivilegedAction<Optional<ModuleReference>> pa = () -> finder.find(name);
- return AccessController.doPrivileged(pa);
- }
- @Override
- public Set<ModuleReference> findAll() {
- PrivilegedAction<Set<ModuleReference>> 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.
*
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Mon Aug 07 09:45:38 2017 -0700
@@ -353,25 +353,13 @@
/**
* 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<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf,
- boolean check)
- {
- if (check) {
- detectCycles();
- checkHashes();
- }
-
+ Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf) {
+ detectCycles();
+ checkHashes();
Map<ResolvedModule, Set<ResolvedModule>> graph = makeGraph(cf);
-
- if (check) {
- checkExportSuppliers(graph);
- }
-
+ checkExportSuppliers(graph);
return graph;
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Mon Aug 07 09:45:38 2017 -0700
@@ -453,7 +453,7 @@
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);
--- a/jdk/src/java.base/share/classes/java/net/URL.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/net/URL.java Mon Aug 07 09:45:38 2017 -0700
@@ -409,7 +409,7 @@
}
}
- protocol = protocol.toLowerCase(Locale.ROOT);
+ protocol = toLowerCase(protocol);
this.protocol = protocol;
if (host != null) {
@@ -585,7 +585,7 @@
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 @@
}
}
+ /**
+ * 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"
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java Mon Aug 07 09:45:38 2017 -0700
@@ -70,7 +70,7 @@
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;
--- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java Mon Aug 07 09:45:38 2017 -0700
@@ -57,7 +57,7 @@
* and catching the CloneNotSupportedException:
*
* <pre>{@code
- * MessageDigest md = MessageDigest.getInstance("SHA");
+ * MessageDigest md = MessageDigest.getInstance("SHA-256");
*
* try {
* md.update(toChapter1);
@@ -496,7 +496,7 @@
/**
* 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 <a href=
* "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
* Java Security Standard Algorithm Names Specification</a>
--- a/jdk/src/java.base/share/classes/java/security/Signature.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/security/Signature.java Mon Aug 07 09:45:38 2017 -0700
@@ -51,11 +51,10 @@
* authentication and integrity assurance of digital data.
*
* <p> 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.
*
* <p> A Signature object can be used to generate and verify digital
--- a/jdk/src/java.base/share/classes/java/security/SignedObject.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/security/SignedObject.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
* verification in an attempt to bypass a security check.
*
* <p> 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.
*
* <p> The name of the Cryptography Package Provider is designated
--- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Mon Aug 07 09:45:38 2017 -0700
@@ -667,11 +667,11 @@
* <tr><td>{@code \p{Alpha}}</td>
* <td>An alphabetic character:{@code \p{IsAlphabetic}}</td></tr>
* <tr><td>{@code \p{Digit}}</td>
- * <td>A decimal digit character:{@code p{IsDigit}}</td></tr>
+ * <td>A decimal digit character:{@code \p{IsDigit}}</td></tr>
* <tr><td>{@code \p{Alnum}}</td>
* <td>An alphanumeric character:{@code [\p{IsAlphabetic}\p{IsDigit}]}</td></tr>
* <tr><td>{@code \p{Punct}}</td>
- * <td>A punctuation character:{@code p{IsPunctuation}}</td></tr>
+ * <td>A punctuation character:{@code \p{IsPunctuation}}</td></tr>
* <tr><td>{@code \p{Graph}}</td>
* <td>A visible character: {@code [^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]}</td></tr>
* <tr><td>{@code \p{Print}}</td>
--- a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java Mon Aug 07 09:45:38 2017 -0700
@@ -59,7 +59,7 @@
* <p>A <i>transformation</i> 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., <i>DES</i>), and may be followed by a feedback mode and
+ * algorithm (e.g., <i>AES</i>), and may be followed by a feedback mode and
* padding scheme.
*
* <p> A transformation is of the form:
@@ -75,17 +75,19 @@
* For example, the following is a valid transformation:
*
* <pre>
- * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
+ * Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>");
* </pre>
*
* 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.
* <p>
@@ -308,7 +310,7 @@
/*
* 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 @@
// 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 @@
}
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<Transform> 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 @@
* {@link Security#getProviders() Security.getProviders()}.
*
* @param transformation the name of the transformation, e.g.,
- * <i>DES/CBC/PKCS5Padding</i>.
+ * <i>AES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
* Java Security Standard Algorithm Names Specification</a>
@@ -566,7 +568,7 @@
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param transformation the name of the transformation,
- * e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * e.g., <i>AES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
* Java Security Standard Algorithm Names Specification</a>
@@ -626,7 +628,7 @@
* does not have to be registered in the provider list.
*
* @param transformation the name of the transformation,
- * e.g., <i>DES/CBC/PKCS5Padding</i>.
+ * e.g., <i>AES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
* Java Security Standard Algorithm Names Specification</a>
--- a/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/javax/crypto/CipherSpi.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
* <p>A <i>transformation</i> 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., <i>DES</i>), and may be followed by a feedback mode and
+ * algorithm (e.g., <i>AES</i>), and may be followed by a feedback mode and
* padding scheme.
*
* <p> A transformation is of the form:
@@ -75,7 +75,7 @@
* For example, the following is a valid transformation:
*
* <pre>
- * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
+ * Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>");
* </pre>
*
* <p>A provider may supply a separate class for each combination
@@ -125,32 +125,32 @@
* </ul>
*
* <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
- * that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
- * <i>DES/CBC/PKCS5Padding</i>, one that implements
- * <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
- * <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
+ * that implements <i>AES/ECB/PKCS5Padding</i>, one that implements
+ * <i>AES/CBC/PKCS5Padding</i>, one that implements
+ * <i>AES/CFB/PKCS5Padding</i>, and yet another one that implements
+ * <i>AES/OFB/PKCS5Padding</i>. That provider would have the following
* <code>Cipher</code> properties in its master class:
*
* <ul>
*
* <li>
* <pre>
- * <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
+ * <code>Cipher.</code><i>AES/ECB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
- * <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
+ * <code>Cipher.</code><i>AES/CBC/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
- * <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
+ * <code>Cipher.</code><i>AES/CFB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
- * <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
+ * <code>Cipher.</code><i>AES/OFB/PKCS5Padding</i>
* </pre>
*
* </ul>
@@ -158,7 +158,7 @@
* <p>Another provider may implement a class for each of the above modes
* (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
* and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
- * and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
+ * and a generic <i>AES</i> class that subclasses from <code>CipherSpi</code>.
* That provider would have the following
* <code>Cipher</code> properties in its master class:
*
@@ -166,7 +166,7 @@
*
* <li>
* <pre>
- * <code>Cipher.</code><i>DES</i>
+ * <code>Cipher.</code><i>AES</i>
* </pre>
*
* </ul>
--- a/jdk/src/java.base/share/classes/javax/crypto/Mac.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/javax/crypto/Mac.java Mon Aug 07 09:45:38 2017 -0700
@@ -50,7 +50,7 @@
*
* <p> 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.
*
* <p> Every implementation of the Java platform is required to support
--- a/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/javax/crypto/SealedObject.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
* <p> 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.
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Mon Aug 07 09:45:38 2017 -0700
@@ -55,13 +55,13 @@
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 @@
// maps package name to loaded module for modules in the boot layer
private static final Map<String, LoadedModule> packageToModule
- = new ConcurrentHashMap<>(SystemModules.PACKAGES_IN_BOOT_LAYER);
+ = new ConcurrentHashMap<>(1024);
// maps a module name to a module reference
private final Map<String, ModuleReference> nameToModule;
@@ -946,9 +946,16 @@
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 @@
// -- 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<ModuleReference, ModuleReader> 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;
}
/**
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Mon Aug 07 09:45:38 2017 -0700
@@ -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.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 @@
*/
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 <working directory>
// 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 @@
* @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
*/
void appendToClassPathForInstrumentation(String path) {
- addClassPathToUCP(path, ucp);
+ ucp.addFile(path);
}
/**
@@ -220,40 +225,11 @@
}
/**
- * 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 @@
return null;
}
}
-
}
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Mon Aug 07 09:45:38 2017 -0700
@@ -46,6 +46,7 @@
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.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 @@
}
/* The original search path of URLs. */
- private ArrayList<URL> path = new ArrayList<>();
+ private final List<URL> path;
/* The stack of unopened URLs */
- Stack<URL> urls = new Stack<>();
+ private final Stack<URL> urls = new Stack<>();
/* The resulting search path of Loaders */
- ArrayList<Loader> loaders = new ArrayList<>();
+ private final ArrayList<Loader> loaders = new ArrayList<>();
/* Map of each URL opened to its corresponding Loader */
- HashMap<String, Loader> lmap = new HashMap<>();
+ private final HashMap<String, Loader> 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 URLClassPath(URL[] urls,
URLStreamHandlerFactory factory,
AccessControlContext acc) {
- for (int i = 0; i < urls.length; i++) {
- path.add(urls[i]);
+ List<URL> 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,16 +154,50 @@
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);
}
- 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<URL> 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<IOException> closeLoaders() {
@@ -198,6 +236,28 @@
}
/**
+ * 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.
*/
public URL[] getURLs() {
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
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());
}
});
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Mon Aug 07 09:45:38 2017 -0700
@@ -34,16 +34,10 @@
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 @@
/**
* 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<String> roots,
- boolean check,
PrintStream traceOutput);
+ /**
+ * Creates a configuration from a pre-generated readability graph.
+ */
+ Configuration newConfiguration(ModuleFinder finder,
+ Map<String, Set<String>> graph);
+
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java Mon Aug 07 09:45:38 2017 -0700
@@ -124,11 +124,11 @@
}
/**
- * 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();
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java Mon Aug 07 09:45:38 2017 -0700
@@ -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<String> compute(ModuleFinder systemModuleFinder, ModuleFinder finder) {
+ Set<String> 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<String> compute(ModuleFinder finder) {
+ return compute(finder, finder);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java Mon Aug 07 09:45:38 2017 -0700
@@ -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<String, Set<String>> moduleReads() {
+ throw new InternalError();
+ }
+
+ @Override
+ public Map<String, Set<String>> concealedPackagesToOpen() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<String, Set<String>> exportedPackagesToOpen() {
+ return Collections.emptyMap();
+ }
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Mon Aug 07 09:45:38 2017 -0700
@@ -40,16 +40,20 @@
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 @@
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 @@
// 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 @@
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 @@
*
* @see java.lang.System#initPhase2()
*/
- public static ModuleLayer boot() {
+ public static ModuleLayer boot() throws Exception {
+
+ // 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();
- // Step 1: Locate system modules (may be patched)
+ String mainModule = System.getProperty("jdk.module.main");
+ Set<String> addModules = addModules();
+ Set<String> 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 @@
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 @@
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<String> 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 module finder: [--upgrade-module-path] system [--module-path]
+ if (appModulePath != null) {
+ finder = ModuleFinder.compose(systemModuleFinder, appModulePath);
+ } else {
+ finder = systemModuleFinder;
+ }
- // The root modules to resolve
- Set<String> 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);
+ // The root modules to resolve
+ roots = new HashSet<>();
- // 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);
- }
- }
+ // launcher -m option to specify the main/initial module
+ if (mainModule != null)
+ roots.add(mainModule);
- // --limit-modules
- unlimitedFinder = finder;
- propValue = getAndRemoveProperty("jdk.module.limitmods");
- if (propValue != null) {
- Set<String> mods = new HashSet<>();
- for (String mod: propValue.split(",")) {
- mods.add(mod);
- }
- finder = limitFinder(finder, mods, roots);
- }
- limitedFinder = finder;
-
- // 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);
+ // 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;
+ // --limit-modules
+ savedModuleFinder = finder;
+ if (!limitModules.isEmpty()) {
+ finder = limitFinder(finder, limitModules, roots);
+ }
- if (ModuleResolution.doNotResolveByDefault(mref))
- continue;
+ // 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));
+ }
- // 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;
- }
- }
- }
+ // 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<String, Set<String>> 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 @@
// 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 @@
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 @@
Configuration cf = SharedSecrets.getJavaLangModuleAccess()
.resolveAndBind(ModuleFinder.ofSystem(),
Set.of(JAVA_BASE),
- false,
null);
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
@@ -439,7 +474,6 @@
}
}
}
-
}
}
@@ -489,7 +523,7 @@
* 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 @@
*/
private static ModulePatcher initModulePatcher() {
Map<String, List<String>> 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<String> getExtraAddModules() {
+ private static Set<String> 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();
+ } else {
+ Set<String> modules = new HashSet<>();
+ while (value != null) {
+ for (String s : value.split(",")) {
+ if (s.length() > 0) modules.add(s);
+ }
+ index++;
+ value = getAndRemoveProperty(prefix + index);
+ }
+ return modules;
}
+ }
- Set<String> modules = new HashSet<>();
- while (value != null) {
- for (String s : value.split(",")) {
- if (s.length() > 0) modules.add(s);
+ /**
+ * Returns the set of module names specified by --limit-modules.
+ */
+ private static Set<String> limitModules() {
+ String value = getAndRemoveProperty("jdk.module.limitmods");
+ if (value == null) {
+ return Collections.emptySet();
+ } else {
+ Set<String> names = new HashSet<>();
+ for (String name : value.split(",")) {
+ if (name.length() > 0) names.add(name);
}
- index++;
- value = getAndRemoveProperty(prefix + index);
+ return names;
}
-
- return modules;
}
/**
@@ -676,8 +723,9 @@
* 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 @@
IllegalAccessLogger.Builder builder
= new IllegalAccessLogger.Builder(mode, System.err);
- Map<String, Set<String>> map1 = SystemModules.concealedPackagesToOpen();
- Map<String, Set<String>> map2 = SystemModules.exportedPackagesToOpen();
+ Map<String, Set<String>> map1 = systemModules.concealedPackagesToOpen();
+ Map<String, Set<String>> 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 @@
}
}
+ /**
+ * Returns an iterator that yields all elements of the first iterator
+ * followed by all the elements of the second iterator.
+ */
static <T> Iterator<T> concat(Iterator<T> iterator1, Iterator<T> iterator2) {
return new Iterator<T>() {
@Override
@@ -921,23 +973,76 @@
};
}
- 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<ModuleReference> mrefs;
+ private volatile Map<String, ModuleReference> nameToModule;
+
+ SafeModuleFinder(ModuleFinder finder) {
+ this.mrefs = Collections.unmodifiableSet(finder.findAll());
+ }
+ @Override
+ public Optional<ModuleReference> find(String name) {
+ Objects.requireNonNull(name);
+ Map<String, ModuleReference> 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<ModuleReference> findAll() {
+ return mrefs;
+ }
+ }
- 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");
+ /**
+ * Counters for startup performance analysis.
+ */
+ static class Counters {
+ private static final boolean PUBLISH_COUNTERS;
+ private static final boolean PRINT_COUNTERS;
+ private static Map<String, Long> 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<String, Long> 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);
+ }
+ }
+ }
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Mon Aug 07 09:45:38 2017 -0700
@@ -200,10 +200,10 @@
}
/**
- * 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();
}
/*
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferenceImpl.java Mon Aug 07 09:45:38 2017 -0700
@@ -68,14 +68,14 @@
/**
* Constructs a new instance of this class.
*/
- ModuleReferenceImpl(ModuleDescriptor descriptor,
- URI location,
- Supplier<ModuleReader> readerSupplier,
- ModulePatcher patcher,
- ModuleTarget target,
- ModuleHashes recordedHashes,
- ModuleHashes.HashSupplier hasher,
- ModuleResolution moduleResolution)
+ public ModuleReferenceImpl(ModuleDescriptor descriptor,
+ URI location,
+ Supplier<ModuleReader> readerSupplier,
+ ModulePatcher patcher,
+ ModuleTarget target,
+ ModuleHashes recordedHashes,
+ ModuleHashes.HashSupplier hasher,
+ ModuleResolution moduleResolution)
{
super(descriptor, Objects.requireNonNull(location));
this.location = location;
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java Mon Aug 07 10:02:39 2017 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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<ModuleReference> modules;
-
- // maps module name to module reference
- private final Map<String, ModuleReference> nameToModule;
-
- // module name to hashes
- private final Map<String, byte[]> 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<String, byte[]> 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<String, ModuleReference>[] map
- = (Entry<String, ModuleReference>[])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<ModuleReference> find(String name) {
- Objects.requireNonNull(name);
- return Optional.ofNullable(nameToModule.get(name));
- }
-
- @Override
- public Set<ModuleReference> 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<ModuleReader> 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<URI> 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<InputStream> 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<ByteBuffer> 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<String> list() throws IOException {
- if (closed)
- throw new IOException("ModuleReader is closed");
-
- Spliterator<String> 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<String> {
- final String moduleRoot;
- final Deque<ImageReader.Node> stack;
- Iterator<ImageReader.Node> 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<? super String> 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<String> trySplit() {
- return null;
- }
-
- @Override
- public int characteristics() {
- return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE;
- }
-
- @Override
- public long estimateSize() {
- return Long.MAX_VALUE;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java Mon Aug 07 09:45:38 2017 -0700
@@ -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<String, ModuleReference>[] map
+ = (Map.Entry<String, ModuleReference>[])new Map.Entry[moduleCount];
+
+ Map<String, byte[]> 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<ModuleReference> find(String name) {
+ PrivilegedAction<Optional<ModuleReference>> pa = () -> f.find(name);
+ return AccessController.doPrivileged(pa);
+ }
+ @Override
+ public Set<ModuleReference> findAll() {
+ PrivilegedAction<Set<ModuleReference>> 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<String, ModuleInfo.Attributes> nameToAttributes = new HashMap<>();
+ Map<String, byte[]> 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<ModuleReference> mrefs = new HashSet<>();
+ Map<String, ModuleReference> nameToModule = new HashMap<>();
+ for (Map.Entry<String, ModuleInfo.Attributes> 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<ModuleReference> mrefs;
+ final Map<String, ModuleReference> nameToModule;
+
+ SystemModuleFinder(ModuleReference[] array,
+ Map.Entry<String, ModuleReference>[] map) {
+ this.mrefs = Set.of(array);
+ this.nameToModule = Map.ofEntries(map);
+ }
+
+ SystemModuleFinder(Set<ModuleReference> mrefs,
+ Map<String, ModuleReference> nameToModule) {
+ this.mrefs = Collections.unmodifiableSet(mrefs);
+ this.nameToModule = Collections.unmodifiableMap(nameToModule);
+ }
+
+ @Override
+ public Optional<ModuleReference> find(String name) {
+ Objects.requireNonNull(name);
+ return Optional.ofNullable(nameToModule.get(name));
+ }
+
+ @Override
+ public Set<ModuleReference> 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<ModuleReader> 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<String, byte[]> generateNameToHash(ModuleHashes[] recordedHashes) {
+ Map<String, byte[]> 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<String, byte[]> 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<URI> 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<InputStream> 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<ByteBuffer> 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<String> list() throws IOException {
+ if (closed)
+ throw new IOException("ModuleReader is closed");
+
+ Spliterator<String> 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<String> {
+ final String moduleRoot;
+ final Deque<ImageReader.Node> stack;
+ Iterator<ImageReader.Node> 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<? super String> 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<String> trySplit() {
+ return null;
+ }
+
+ @Override
+ public int characteristics() {
+ return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE;
+ }
+
+ @Override
+ public long estimateSize() {
+ return Long.MAX_VALUE;
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Mon Aug 07 09:45:38 2017 -0700
@@ -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.
+ * 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.
*
- * 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.
- *
+ * @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 false if the modules reconstituted by this SystemModules object
+ * do not include any incubator modules. Returns true if there are
+ * incubating modules or unknown.
+ */
+ boolean hasIncubatorModules();
/**
- * Return true if there are no split packages in the run-time image.
+ * Returns the non-empty array of ModuleDescriptor objects.
*/
- public static boolean hasSplitPackages() {
- return true;
- }
+ ModuleDescriptor[] moduleDescriptors();
/**
- * 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 array of ModuleTarget objects. The array elements correspond
+ * to the array of ModuleDescriptor objects.
*/
- public static ModuleDescriptor[] descriptors() {
- throw new InternalError("expected to be overridden at link time");
- }
+ ModuleTarget[] moduleTargets();
/**
- * 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 ModuleHashes 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");
- }
+ ModuleHashes[] moduleHashes();
/**
- * 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 ModuleResolution 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");
- }
+ ModuleResolution[] moduleResolutions();
/**
- * Returns a non-empty array of ModuleResolutions in the run-time image.
+ * Returns the map representing readability graph for the modules reconstituted
+ * by this SystemModules object.
*/
- public static ModuleResolution[] moduleResolutions() {
- throw new InternalError("expected to be overridden at link time");
- }
+ Map<String, Set<String>> 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<String, Set<String>> concealedPackagesToOpen() {
- return Collections.emptyMap();
- }
+ Map<String, Set<String>> 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<String, Set<String>> exportedPackagesToOpen() {
- return Collections.emptyMap();
- }
+ Map<String, Set<String>> exportedPackagesToOpen();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java Mon Aug 07 09:45:38 2017 -0700
@@ -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
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Mon Aug 07 09:45:38 2017 -0700
@@ -316,8 +316,7 @@
*/
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;
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
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<SelectionKey> keys() {
- if (!isOpen() && !Util.atBugLevel("1.4"))
+ if (!isOpen())
throw new ClosedSelectorException();
return publicKeys;
}
public Set<SelectionKey> selectedKeys() {
- if (!isOpen() && !Util.atBugLevel("1.4"))
+ if (!isOpen())
throw new ClosedSelectorException();
return publicSelectedKeys;
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
}
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);
- }
-
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Mon Aug 07 09:45:38 2017 -0700
@@ -79,6 +79,9 @@
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 @@
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);
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Mon Aug 07 09:45:38 2017 -0700
@@ -1034,6 +1034,12 @@
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) {
--- a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
* must not be null; the behavior is unspecified if it is.</p>
*
* <p>Class loading aspects are detailed in the
- * <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- * JMX Specification, version 1.4</a> PDF document.</p>
+ * <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ * JMX Specification, version 1.4</a></p>
*
* <p>Most methods in this interface parallel methods in the {@link
* MBeanServerConnection} interface. Where an aspect of the behavior
--- a/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>RMI connector</title>
<!--
-Copyright (c) 2002, 2015, 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
@@ -316,19 +316,8 @@
<p>If an RMI connector client or server receives from its peer an
instance of a class that it does not know, and if dynamic code
downloading is active for the RMI connection, then the class can
- be downloaded from a codebase specified by the peer. The
- article <a
- href="{@docRoot}/../technotes/guides/rmi/codebase.html"><em>Dynamic
- code downloading using Java RMI</em></a> explains this in more
- detail.</p>
-
-
- @see <a href="{@docRoot}/../technotes/guides/rmi/index.html">
- Java™ Remote Method
- Invocation (RMI)</a>
-
- @see <a href="{@docRoot}/../technotes/guides/jndi/index.html">
- Java Naming and Directory Interface™ (JNDI)</a>
+ be downloaded from a codebase specified by the peer.
+ {@extLink rmi_guide Java RMI Guide} explains this in more detail.</p>
@see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045,
section 6.8, "Base64 Content-Transfer-Encoding"</a>
--- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Mon Aug 07 09:45:38 2017 -0700
@@ -588,8 +588,8 @@
Class<T> mxbeanInterface)
throws java.io.IOException {
- // Only allow MXBean interfaces from rt.jar loaded by the
- // bootstrap class loader
+ // Only allow MXBean interfaces from the platform modules loaded by the
+ // bootstrap or platform class loader
final Class<?> cls = mxbeanInterface;
ClassLoader loader =
AccessController.doPrivileged(
--- a/jdk/src/java.management/share/classes/javax/management/loading/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/loading/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management.loading package</title>
<!--
-Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1999, 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
@@ -67,11 +67,8 @@
<code>PrivateClassLoader</code>.</p>
<p id="spec">
- @see <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>,
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- JMX Specification, version 1.4(pdf).</a>
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ JMX Specification, version 1.4</a>
@since 1.5
</BODY>
--- a/jdk/src/java.management/share/classes/javax/management/modelmbean/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/modelmbean/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management.modelmbean package</title>
<!--
-Copyright (c) 2000, 2011, 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
@@ -114,9 +114,8 @@
<ul>
<li>See the <i>JMX 1.4 Specification</i>
- PDF document available from the
- <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>
+ <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ JMX Specification, version 1.4</a>
</ul>
@since 1.5
--- a/jdk/src/java.management/share/classes/javax/management/monitor/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/monitor/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management.monitor package</title>
<!--
-Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1999, 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
@@ -184,11 +184,8 @@
</li>
</ul>
<p id="spec">
- @see <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>,
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- JMX Specification, version 1.4(pdf).</a>
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ JMX Specification, version 1.4</a>
@since 1.5
</BODY>
--- a/jdk/src/java.management/share/classes/javax/management/openmbean/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/openmbean/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management.openmbean package</title>
<!--
-Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2001, 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
@@ -142,10 +142,7 @@
then {@code minValue} must not be greater than {@code maxValue}.
</ul>
- @see <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>,
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
JMX Specification, version 1.4</a>
@since 1.5
--- a/jdk/src/java.management/share/classes/javax/management/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management package</title>
<!--
-Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1999, 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
@@ -389,11 +389,8 @@
</ul>
<p id="spec">
- @see <a href="{@docRoot}/../technotes/guides/jmx/index.html">
- Java Platform documentation on JMX technology</a>
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- JMX Specification, version 1.4(pdf).</a>
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ JMX Specification, version 1.4</a>
@since 1.5
--- a/jdk/src/java.management/share/classes/javax/management/relation/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/relation/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>javax.management.relation package</title>
<!--
-Copyright (c) 2000, 2011, 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
@@ -136,10 +136,7 @@
// Set of ObjectName containing moduleB
</pre>
- @see <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>,
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
JMX Specification, version 1.4</a>
@since 1.5
--- a/jdk/src/java.management/share/classes/javax/management/remote/package.html Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.management/share/classes/javax/management/remote/package.html Mon Aug 07 09:45:38 2017 -0700
@@ -2,7 +2,7 @@
<head>
<title>JMX™ Remote API.</title>
<!--
-Copyright (c) 2002, 2014, 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
@@ -32,8 +32,8 @@
This package defines the essential interfaces for making a JMX
MBean server manageable remotely. The specification of this
functionality is completed by Part III of the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- JMX Specification, version 1.4</a> PDF document.</p>
+ <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
+ JMX Specification, version 1.4</a></p>
<p>The JMX specification defines the notion of <b>connectors</b>.
A connector is attached to a JMX API MBean server and makes it
@@ -194,10 +194,7 @@
connector server.</p>
- @see <a href="{@docRoot}/../technotes/guides/jmx/">
- Java Platform documentation on JMX technology</a>,
- in particular the
- <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
+ @see <a href="https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html">
JMX Specification, version 1.4</a>
@since 1.5
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardException.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardException.java Mon Aug 07 09:45:38 2017 -0700
@@ -48,7 +48,7 @@
/**
* Constructs a new CardException with the specified cause and a detail message
- * of <code>(cause==null ? null : cause.toString())</code>.
+ * of {@code (cause==null ? null : cause.toString())}.
*
* @param cause the cause of this exception or null
*/
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardNotPresentException.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardNotPresentException.java Mon Aug 07 09:45:38 2017 -0700
@@ -48,7 +48,7 @@
/**
* Constructs a new CardNotPresentException with the specified cause and a detail message
- * of <code>(cause==null ? null : cause.toString())</code>.
+ * of {@code (cause==null ? null : cause.toString())}.
*
* @param cause the cause of this exception or null
*/
--- a/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/AttachPermission.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.attach/share/classes/com/sun/tools/attach/AttachPermission.java Mon Aug 07 09:45:38 2017 -0700
@@ -42,14 +42,16 @@
*
* <table class="striped"><caption style="display:none">Table shows permission
* target name, what the permission allows, and associated risks</caption>
+ * <thead>
* <tr>
- * <th>Permission Target Name</th>
- * <th>What the Permission Allows</th>
- * <th>Risks of Allowing this Permission</th>
+ * <th scope="col">Permission Target Name</th>
+ * <th scope="col">What the Permission Allows</th>
+ * <th scope="col">Risks of Allowing this Permission</th>
* </tr>
- *
+ * </thead>
+ * <tbody>
* <tr>
- * <td>attachVirtualMachine</td>
+ * <th scope="row">attachVirtualMachine</th>
* <td>Ability to attach to another Java virtual machine and load agents
* into that VM.
* </td>
@@ -59,14 +61,14 @@
* </tr>
*
* <tr>
- * <td>createAttachProvider</td>
+ * <th scope="row">createAttachProvider</th>
* <td>Ability to create an <code>AttachProvider</code> instance.
* </td>
* <td>This allows an attacker to create an AttachProvider which can
* potentially be used to attach to other Java virtual machines.
* </td>
* </tr>
-
+ * </tbody>
*
* </table>
--- a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java Mon Aug 07 09:45:38 2017 -0700
@@ -59,21 +59,29 @@
* Paths are matched literally, which means that the strings are compared
* case sensitively, and with no conversion to or from any encoded forms.
* For example. Given a HttpServer with the following HttpContexts configured.
- * <table><caption style="display:none">description</caption>
- * <tr><td><i>Context</i></td><td><i>Context path</i></td></tr>
- * <tr><td>ctx1</td><td>"/"</td></tr>
- * <tr><td>ctx2</td><td>"/apps/"</td></tr>
- * <tr><td>ctx3</td><td>"/apps/foo/"</td></tr>
+ * <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
+ * <tr><th scope="col"><i>Context</i></th><th scope="col"><i>Context path</i></th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">ctx1</th><td>"/"</td></tr>
+ * <tr><th scope="row">ctx2</th><td>"/apps/"</td></tr>
+ * <tr><th scope="row">ctx3</th><td>"/apps/foo/"</td></tr>
+ * </tbody>
* </table>
* <p>
* the following table shows some request URIs and which, if any context they would
* match with.
- * <table><caption style="display:none">description</caption>
- * <tr><td><i>Request URI</i></td><td><i>Matches context</i></td></tr>
- * <tr><td>"http://foo.com/apps/foo/bar"</td><td>ctx3</td></tr>
- * <tr><td>"http://foo.com/apps/Foo/bar"</td><td>no match, wrong case</td></tr>
- * <tr><td>"http://foo.com/apps/app1"</td><td>ctx2</td></tr>
- * <tr><td>"http://foo.com/foo"</td><td>ctx1</td></tr>
+ * <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
+ * <tr><th scope="col"><i>Request URI</i></th><th scope="col"><i>Matches context</i></th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">"http://foo.com/apps/foo/bar"</th><td>ctx3</td></tr>
+ * <tr><th scope="row">"http://foo.com/apps/Foo/bar"</th><td>no match, wrong case</td></tr>
+ * <tr><th scope="row">"http://foo.com/apps/app1"</th><td>ctx2</td></tr>
+ * <tr><th scope="row">"http://foo.com/foo"</th><td>ctx1</td></tr>
+ * </tbody>
* </table>
* <p>
* <b>Note about socket backlogs</b><p>
--- a/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpResponse.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpResponse.java Mon Aug 07 09:45:38 2017 -0700
@@ -618,7 +618,7 @@
* on one of the given {@code CompletableFuture<Void}s which themselves complete
* after all individual responses associated with the multi response
* have completed, or after all push promises have been received.
- * <p>
+ *
* @implNote Implementations might follow the pattern shown below
* <pre>
* {@code
@@ -633,7 +633,6 @@
* }
* }
* </pre>
- * <p>
*
* @param onComplete a CompletableFuture which completes after all
* responses have been received relating to this multi request.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/SocketTransportService.java Mon Aug 07 09:45:38 2017 -0700
@@ -275,6 +275,12 @@
sa = new InetSocketAddress(localaddress, port);
}
ServerSocket ss = new ServerSocket();
+ if (port == 0) {
+ // Only need SO_REUSEADDR if we're using a fixed port. If we
+ // start seeing EADDRINUSE due to collisions in free ports
+ // then we should retry the bind() a few times.
+ ss.setReuseAddress(false);
+ }
ss.bind(sa);
return new SocketListenKey(ss);
}
--- a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -119,8 +119,26 @@
return (char *)dbgsysTlsGet(tlsIndex);
}
+/* Set options common to client and server sides */
static jdwpTransportError
-setOptions(int fd)
+setOptionsCommon(int fd)
+{
+ jvalue dontcare;
+ int err;
+
+ dontcare.i = 0; /* keep compiler happy */
+
+ err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
+ if (err < 0) {
+ RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
+ }
+
+ return JDWPTRANSPORT_ERROR_NONE;
+}
+
+/* Set the SO_REUSEADDR option */
+static jdwpTransportError
+setReuseAddrOption(int fd)
{
jvalue dontcare;
int err;
@@ -132,11 +150,6 @@
RETURN_IO_ERROR("setsockopt SO_REUSEADDR failed");
}
- err = dbgsysSetSocketOption(fd, TCP_NODELAY, JNI_TRUE, dontcare);
- if (err < 0) {
- RETURN_IO_ERROR("setsockopt TCPNODELAY failed");
- }
-
return JDWPTRANSPORT_ERROR_NONE;
}
@@ -350,10 +363,21 @@
RETURN_IO_ERROR("socket creation failed");
}
- err = setOptions(serverSocketFD);
+ err = setOptionsCommon(serverSocketFD);
if (err) {
return err;
}
+ if (sa.sin_port != 0) {
+ /*
+ * Only need SO_REUSEADDR if we're using a fixed port. If we
+ * start seeing EADDRINUSE due to collisions in free ports
+ * then we should retry the dbgsysBind() a few times.
+ */
+ err = setReuseAddrOption(serverSocketFD);
+ if (err) {
+ return err;
+ }
+ }
err = dbgsysBind(serverSocketFD, (struct sockaddr *)&sa, sizeof(sa));
if (err < 0) {
@@ -510,12 +534,18 @@
RETURN_IO_ERROR("unable to create socket");
}
- err = setOptions(socketFD);
+ err = setOptionsCommon(socketFD);
if (err) {
return err;
}
/*
+ * We don't call setReuseAddrOption() for the non-server socket
+ * case. If we start seeing EADDRINUSE due to collisions in free
+ * ports then we should retry the dbgsysConnect() a few times.
+ */
+
+ /*
* To do a timed connect we make the socket non-blocking
* and poll with a timeout;
*/
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Mon Aug 07 09:45:38 2017 -0700
@@ -28,6 +28,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
@@ -37,12 +38,15 @@
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -50,18 +54,20 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.function.IntSupplier;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import jdk.internal.module.Checks;
import jdk.internal.module.ClassFileAttributes;
import jdk.internal.module.ClassFileConstants;
+import jdk.internal.module.DefaultRoots;
import jdk.internal.module.IllegalAccessMaps;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.module.ModuleInfoExtender;
+import jdk.internal.module.ModuleReferenceImpl;
import jdk.internal.module.ModuleResolution;
import jdk.internal.module.ModuleTarget;
-import jdk.internal.module.SystemModules;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
@@ -72,33 +78,42 @@
import static jdk.internal.org.objectweb.asm.Opcodes.*;
import jdk.tools.jlink.internal.ModuleSorter;
+import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool;
-import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
/**
- * Jlink plugin to reconstitute module descriptors for system modules.
- * It will extend module-info.class with ModulePackages attribute,
- * if not present. It also determines the number of packages of
- * the boot layer at link time.
+ * Jlink plugin to reconstitute module descriptors and other attributes for system
+ * modules. The plugin generates implementations of SystemModules to avoid parsing
+ * module-info.class files at startup. It also generates SystemModulesMap to return
+ * the SystemModules implementation for a specific initial module.
*
- * This plugin will override jdk.internal.module.SystemModules class
+ * As a side effect, the plugin adds the ModulePackages class file attribute to the
+ * module-info.class files that don't have the attribute.
*
- * @see jdk.internal.module.SystemModuleFinder
- * @see SystemModules
+ * @see jdk.internal.module.SystemModuleFinders
+ * @see jdk.internal.module.SystemModules
*/
+
public final class SystemModulesPlugin implements Plugin {
private static final String NAME = "system-modules";
private static final String DESCRIPTION =
- PluginsResourceBundle.getDescription(NAME);
+ PluginsResourceBundle.getDescription(NAME);
+ private static final String SYSTEM_MODULES_MAP_CLASS =
+ "jdk/internal/module/SystemModulesMap";
+ private static final String SYSTEM_MODULES_CLASS_PREFIX =
+ "jdk/internal/module/SystemModules$";
+ private static final String ALL_SYSTEM_MODULES_CLASS =
+ SYSTEM_MODULES_CLASS_PREFIX + "all";
+ private static final String DEFAULT_SYSTEM_MODULES_CLASS =
+ SYSTEM_MODULES_CLASS_PREFIX + "default";
private boolean enabled;
- private boolean retainModuleTarget;
+
public SystemModulesPlugin() {
this.enabled = true;
- this.retainModuleTarget = false;
}
@Override
@@ -131,11 +146,7 @@
public void configure(Map<String, String> config) {
String arg = config.get(NAME);
if (arg != null) {
- if (arg.equals("retainModuleTarget")) {
- retainModuleTarget = true;
- } else {
- throw new IllegalArgumentException(NAME + ": " + arg);
- }
+ throw new IllegalArgumentException(NAME + ": " + arg);
}
}
@@ -145,25 +156,56 @@
throw new PluginException(NAME + " was set");
}
- SystemModulesClassGenerator generator =
- new SystemModulesClassGenerator(retainModuleTarget);
+ // validate, transform (if needed), and add the module-info.class files
+ List<ModuleInfo> moduleInfos = transformModuleInfos(in, out);
+
+ // generate and add the SystemModuleMap and SystemModules classes
+ Set<String> generated = genSystemModulesClasses(moduleInfos, out);
+
+ // pass through all other resources
+ in.entries()
+ .filter(data -> !data.path().endsWith("/module-info.class")
+ && !generated.contains(data.path()))
+ .forEach(data -> out.add(data));
- // generate the byte code to create ModuleDescriptors
- // such that the modules linked in the image would skip parsing
- // of module-info.class and also skip name check
+ return out.build();
+ }
+
+ /**
+ * Validates and transforms the module-info.class files in the modules, adding
+ * the ModulePackages class file attribute if needed.
+ *
+ * @return the list of ModuleInfo objects, the first element is java.base
+ */
+ List<ModuleInfo> transformModuleInfos(ResourcePool in, ResourcePoolBuilder out) {
+ List<ModuleInfo> moduleInfos = new ArrayList<>();
// Sort modules in the topological order so that java.base is always first.
new ModuleSorter(in.moduleView()).sorted().forEach(module -> {
ResourcePoolEntry data = module.findEntry("module-info.class").orElseThrow(
- // automatic module not supported yet
+ // automatic modules not supported
() -> new PluginException("module-info.class not found for " +
- module.name() + " module")
+ module.name() + " module")
);
assert module.name().equals(data.moduleName());
+
try {
- // validate the module and add to system modules
- data = generator.buildModuleInfo(data, module.packages());
+ byte[] content = data.contentBytes();
+ Set<String> packages = module.packages();
+ ModuleInfo moduleInfo = new ModuleInfo(content, packages);
+
+ // link-time validation
+ moduleInfo.validateNames();
+
+ // check if any exported or open package is not present
+ moduleInfo.validatePackages();
+
+ // module-info.class may be overridden to add ModulePackages
+ if (moduleInfo.shouldRewrite()) {
+ data = data.copyWithContent(moduleInfo.getBytes());
+ }
+ moduleInfos.add(moduleInfo);
// add resource pool entry
out.add(data);
@@ -172,37 +214,134 @@
}
});
- // Generate the new class
- ClassWriter cwriter = generator.getClassWriter();
- in.entries().forEach(data -> {
- if (data.path().endsWith("module-info.class"))
- return;
- if (generator.isOverriddenClass(data.path())) {
- byte[] bytes = cwriter.toByteArray();
- ResourcePoolEntry ndata = data.copyWithContent(bytes);
- out.add(ndata);
- } else {
- out.add(data);
+ return moduleInfos;
+ }
+
+ /**
+ * Generates the SystemModules classes (at least one) and the SystemModulesMap
+ * class to map initial modules to a SystemModules class.
+ *
+ * @return the resource names of the resources added to the pool
+ */
+ private Set<String> genSystemModulesClasses(List<ModuleInfo> moduleInfos,
+ ResourcePoolBuilder out) {
+ int moduleCount = moduleInfos.size();
+ ModuleFinder finder = finderOf(moduleInfos);
+ assert finder.findAll().size() == moduleCount;
+
+ // map of initial module name to SystemModules class name
+ Map<String, String> map = new LinkedHashMap<>();
+
+ // the names of resources written to the pool
+ Set<String> generated = new HashSet<>();
+
+ // generate the SystemModules implementation to reconstitute all modules
+ Set<String> allModuleNames = moduleInfos.stream()
+ .map(ModuleInfo::moduleName)
+ .collect(Collectors.toSet());
+ String rn = genSystemModulesClass(moduleInfos,
+ resolve(finder, allModuleNames),
+ ALL_SYSTEM_MODULES_CLASS,
+ out);
+ generated.add(rn);
+
+ // generate, if needed, a SystemModules class to reconstitute the modules
+ // needed for the case that the initial module is the unnamed module.
+ String defaultSystemModulesClassName;
+ Configuration cf = resolve(finder, DefaultRoots.compute(finder));
+ if (cf.modules().size() == moduleCount) {
+ // all modules are resolved so no need to generate a class
+ defaultSystemModulesClassName = ALL_SYSTEM_MODULES_CLASS;
+ } else {
+ defaultSystemModulesClassName = DEFAULT_SYSTEM_MODULES_CLASS;
+ rn = genSystemModulesClass(sublist(moduleInfos, cf),
+ cf,
+ defaultSystemModulesClassName,
+ out);
+ generated.add(rn);
+ }
+
+ // Generate a SystemModules class for each module with a main class
+ int suffix = 0;
+ for (ModuleInfo mi : moduleInfos) {
+ if (mi.descriptor().mainClass().isPresent()) {
+ String moduleName = mi.moduleName();
+ cf = resolve(finder, Set.of(moduleName));
+ if (cf.modules().size() == moduleCount) {
+ // resolves all modules so no need to generate a class
+ map.put(moduleName, ALL_SYSTEM_MODULES_CLASS);
+ } else {
+ String cn = SYSTEM_MODULES_CLASS_PREFIX + (suffix++);
+ rn = genSystemModulesClass(sublist(moduleInfos, cf), cf, cn, out);
+ map.put(moduleName, cn);
+ generated.add(rn);
+ }
}
- });
+ }
+
+ // generate SystemModulesMap
+ rn = genSystemModulesMapClass(ALL_SYSTEM_MODULES_CLASS,
+ defaultSystemModulesClassName,
+ map,
+ out);
+ generated.add(rn);
+
+ // return the resource names of the generated classes
+ return generated;
+ }
+
+ /**
+ * Resolves a collection of root modules, with service binding, to create
+ * configuration.
+ */
+ private Configuration resolve(ModuleFinder finder, Set<String> roots) {
+ return Configuration.empty().resolveAndBind(finder, ModuleFinder.of(), roots);
+ }
- return out.build();
+ /**
+ * Returns the list of ModuleInfo objects that correspond to the modules in
+ * the given configuration.
+ */
+ private List<ModuleInfo> sublist(List<ModuleInfo> moduleInfos, Configuration cf) {
+ Set<String> names = cf.modules()
+ .stream()
+ .map(ResolvedModule::name)
+ .collect(Collectors.toSet());
+ return moduleInfos.stream()
+ .filter(mi -> names.contains(mi.moduleName()))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Generate a SystemModules implementation class and add it as a resource.
+ *
+ * @return the name of the class resource added to the pool
+ */
+ private String genSystemModulesClass(List<ModuleInfo> moduleInfos,
+ Configuration cf,
+ String className,
+ ResourcePoolBuilder out) {
+ SystemModulesClassGenerator generator
+ = new SystemModulesClassGenerator(className, moduleInfos);
+ byte[] bytes = generator.getClassWriter(cf).toByteArray();
+ String rn = "/java.base/" + className + ".class";
+ ResourcePoolEntry e = ResourcePoolEntry.create(rn, bytes);
+ out.add(e);
+ return rn;
}
static class ModuleInfo {
- private final ByteArrayInputStream bain;
+ private final ByteArrayInputStream bais;
private final Attributes attrs;
private final Set<String> packages;
- private final boolean dropModuleTarget;
private final boolean addModulePackages;
private ModuleDescriptor descriptor; // may be different that the original one
- ModuleInfo(byte[] bytes, Set<String> packages, boolean dropModuleTarget)
- throws IOException
- {
- this.bain = new ByteArrayInputStream(bytes);
+ ModuleInfo(byte[] bytes, Set<String> packages) throws IOException {
+ this.bais = new ByteArrayInputStream(bytes);
this.packages = packages;
- this.attrs = jdk.internal.module.ModuleInfo.read(bain, null);
+ this.attrs = jdk.internal.module.ModuleInfo.read(bais, null);
+
// If ModulePackages attribute is present, the packages from this
// module descriptor returns the packages in that attribute.
// If it's not present, ModuleDescriptor::packages only contains
@@ -215,14 +354,6 @@
// add ModulePackages attribute if this module contains some packages
// and ModulePackages is not present
this.addModulePackages = packages.size() > 0 && !hasModulePackages();
-
- // drop target attribute only if any OS property is present
- ModuleTarget target = attrs.target();
- if (dropModuleTarget && target != null) {
- this.dropModuleTarget = (target.targetPlatform() != null);
- } else {
- this.dropModuleTarget = false;
- }
}
String moduleName() {
@@ -233,7 +364,6 @@
return descriptor;
}
-
Set<String> packages() {
return packages;
}
@@ -283,7 +413,6 @@
}
}
-
/**
* Validates if exported and open packages are present
*/
@@ -328,17 +457,15 @@
}
/**
- * Returns true if module-info.class should be written
- * 1. add ModulePackages attribute if not present; or
- * 2. drop ModuleTarget attribute except java.base
+ * Returns true if module-info.class should be rewritten to add the
+ * ModulePackages attribute.
*/
boolean shouldRewrite() {
- return addModulePackages || dropModuleTarget;
+ return addModulePackages;
}
/**
- * Returns the bytes for the module-info.class with ModulePackages
- * attribute added and/or with ModuleTarget attribute dropped.
+ * Returns the bytes for the (possibly updated) module-info.class.
*/
byte[] getBytes() throws IOException {
try (InputStream in = getInputStream()) {
@@ -347,13 +474,10 @@
if (addModulePackages) {
rewriter.addModulePackages(packages);
}
- if (dropModuleTarget) {
- rewriter.dropModuleTarget();
- }
// rewritten module descriptor
byte[] bytes = rewriter.getBytes();
- try (ByteArrayInputStream bain = new ByteArrayInputStream(bytes)) {
- this.descriptor = ModuleDescriptor.read(bain);
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
+ this.descriptor = ModuleDescriptor.read(bais);
}
return bytes;
} else {
@@ -366,8 +490,8 @@
* Returns the input stream of the module-info.class
*/
InputStream getInputStream() {
- bain.reset();
- return bain;
+ bais.reset();
+ return bais;
}
class ModuleInfoRewriter extends ByteArrayOutputStream {
@@ -383,10 +507,6 @@
}
}
- void dropModuleTarget() {
- extender.targetPlatform("");
- }
-
byte[] getBytes() throws IOException {
extender.write(this);
return buf;
@@ -395,12 +515,10 @@
}
/**
- * ClassWriter of a new jdk.internal.module.SystemModules class
- * to reconstitute ModuleDescriptor of the system modules.
+ * Generates a SystemModules class to reconstitute the ModuleDescriptor
+ * and other attributes of system modules.
*/
static class SystemModulesClassGenerator {
- private static final String CLASSNAME =
- "jdk/internal/module/SystemModules";
private static final String MODULE_DESCRIPTOR_BUILDER =
"jdk/internal/module/Builder";
private static final String MODULE_DESCRIPTOR_ARRAY_SIGNATURE =
@@ -422,10 +540,6 @@
private static final String MODULE_RESOLUTIONS_ARRAY_SIGNATURE =
"[Ljdk/internal/module/ModuleResolution;";
- // static variables in SystemModules class
- private static final String MODULE_NAMES = "MODULE_NAMES";
- private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER";
-
private static final int MAX_LOCAL_VARS = 256;
private final int BUILDER_VAR = 0;
@@ -434,14 +548,14 @@
private final int MH_VAR = 1; // variable for ModuleHashes
private int nextLocalVar = 2; // index to next local variable
- private final ClassWriter cw;
- private boolean dropModuleTarget;
-
// Method visitor for generating the SystemModules::modules() method
private MethodVisitor mv;
+ // name of class to generate
+ private final String className;
+
// list of all ModuleDescriptorBuilders, invoked in turn when building.
- private final List<ModuleInfo> moduleInfos = new ArrayList<>();
+ private final List<ModuleInfo> moduleInfos;
// A builder to create one single Set instance for a given set of
// names or modifiers to reduce the footprint
@@ -449,10 +563,11 @@
private final DedupSetBuilder dedupSetBuilder
= new DedupSetBuilder(this::getNextLocalVar);
- public SystemModulesClassGenerator(boolean retainModuleTarget) {
- this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS +
- ClassWriter.COMPUTE_FRAMES);
- this.dropModuleTarget = !retainModuleTarget;
+ public SystemModulesClassGenerator(String className,
+ List<ModuleInfo> moduleInfos) {
+ this.className = className;
+ this.moduleInfos = moduleInfos;
+ moduleInfos.forEach(mi -> dedups(mi.descriptor()));
}
private int getNextLocalVar() {
@@ -460,105 +575,10 @@
}
/*
- * static initializer initializing the static fields
- *
- * static Map<String, ModuleDescriptor> map = new HashMap<>();
- */
- private void clinit(int numModules, int numPackages,
- boolean hasSplitPackages) {
- cw.visit(Opcodes.V1_8, ACC_PUBLIC+ACC_FINAL+ACC_SUPER, CLASSNAME,
- null, "java/lang/Object", null);
-
- // public static String[] MODULE_NAMES = new String[] {....};
- cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, MODULE_NAMES,
- "[Ljava/lang/String;", null, null)
- .visitEnd();
-
- // public static int PACKAGES_IN_BOOT_LAYER;
- cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, PACKAGE_COUNT,
- "I", null, numPackages)
- .visitEnd();
-
- MethodVisitor clinit =
- cw.visitMethod(ACC_STATIC, "<clinit>", "()V",
- null, null);
- clinit.visitCode();
-
- // create the MODULE_NAMES array
- pushInt(clinit, numModules);
- clinit.visitTypeInsn(ANEWARRAY, "java/lang/String");
-
- int index = 0;
- for (ModuleInfo minfo : moduleInfos) {
- clinit.visitInsn(DUP); // arrayref
- pushInt(clinit, index++);
- clinit.visitLdcInsn(minfo.moduleName()); // value
- clinit.visitInsn(AASTORE);
- }
-
- clinit.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULE_NAMES,
- "[Ljava/lang/String;");
-
- clinit.visitInsn(RETURN);
- clinit.visitMaxs(0, 0);
- clinit.visitEnd();
-
- // public static boolean hasSplitPackages();
- MethodVisitor split =
- cw.visitMethod(ACC_PUBLIC+ACC_STATIC, "hasSplitPackages",
- "()Z", null, null);
- split.visitCode();
- split.visitInsn(hasSplitPackages ? ICONST_1 : ICONST_0);
- split.visitInsn(IRETURN);
- split.visitMaxs(0, 0);
- split.visitEnd();
-
- }
-
- /*
* Adds the given ModuleDescriptor to the system module list.
* It performs link-time validation and prepares mapping from various
* Sets to SetBuilders to emit an optimized number of sets during build.
*/
- public ResourcePoolEntry buildModuleInfo(ResourcePoolEntry entry,
- Set<String> packages)
- throws IOException
- {
- if (moduleInfos.isEmpty() && !entry.moduleName().equals("java.base")) {
- throw new InternalError("java.base must be the first module to process");
- }
-
- ModuleInfo moduleInfo;
- if (entry.moduleName().equals("java.base")) {
- moduleInfo = new ModuleInfo(entry.contentBytes(), packages, false);
- ModuleDescriptor md = moduleInfo.descriptor;
- // drop ModuleTarget attribute if java.base has all OS properties
- ModuleTarget target = moduleInfo.target();
- if (dropModuleTarget && target.targetPlatform() != null) {
- dropModuleTarget = true;
- } else {
- dropModuleTarget = false;
- }
- } else {
- moduleInfo = new ModuleInfo(entry.contentBytes(), packages, dropModuleTarget);
- }
-
- // link-time validation
- moduleInfo.validateNames();
- // check if any exported or open package is not present
- moduleInfo.validatePackages();
-
- // module-info.class may be overridden for optimization
- // 1. update ModuleTarget attribute to drop targetPlartform
- // 2. add/update ModulePackages attribute
- if (moduleInfo.shouldRewrite()) {
- entry = entry.copyWithContent(moduleInfo.getBytes());
- }
- moduleInfos.add(moduleInfo);
- dedups(moduleInfo.descriptor());
- return entry;
- }
-
private void dedups(ModuleDescriptor md) {
// exports
for (Exports e : md.exports()) {
@@ -581,47 +601,123 @@
dedupSetBuilder.stringSet(md.uses());
}
- /*
- * Generate bytecode for SystemModules
+ /**
+ * Generate SystemModules class
*/
- public ClassWriter getClassWriter() {
- int numModules = moduleInfos.size();
- Set<String> allPackages = new HashSet<>();
- int packageCount = 0;
- for (ModuleInfo minfo : moduleInfos) {
- allPackages.addAll(minfo.packages);
- packageCount += minfo.packages.size();
- }
+ public ClassWriter getClassWriter(Configuration cf) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ + ClassWriter.COMPUTE_FRAMES);
+ cw.visit(Opcodes.V1_8,
+ ACC_FINAL+ACC_SUPER,
+ className,
+ null,
+ "java/lang/Object",
+ new String[] { "jdk/internal/module/SystemModules" });
- int numPackages = allPackages.size();
- boolean hasSplitPackages = (numPackages < packageCount);
- clinit(numModules, numPackages, hasSplitPackages);
+ // generate <init>
+ genConstructor(cw);
+
+ // generate hasSplitPackages
+ genHasSplitPackages(cw);
- // generate SystemModules::descriptors
- genDescriptorsMethod();
+ // generate hasIncubatorModules
+ genIncubatorModules(cw);
- // generate SystemModules::targets
- genTargetsMethod();
+ // generate moduleDescriptors
+ genModuleDescriptorsMethod(cw);
+
+ // generate moduleTargets
+ genModuleTargetsMethod(cw);
- // generate SystemModules::hashes
- genHashesMethod();
+ // generate moduleHashes
+ genModuleHashesMethod(cw);
+
+ // generate moduleResolutions
+ genModuleResolutionsMethod(cw);
- // generate SystemModules::moduleResolutions
- genModuleResolutionsMethod();
+ // generate moduleReads
+ genModuleReads(cw, cf);
- // generate SystemModules::concealedPackagesToOpen and
- // SystemModules::exportedPackagesToOpen
- genXXXPackagesToOpenMethods();
+ // generate concealedPackagesToOpen and exportedPackagesToOpen
+ genXXXPackagesToOpenMethods(cw);
return cw;
}
/**
- * Generate bytecode for SystemModules::descriptors method
+ * Generate byteccode for no-arg constructor
+ */
+ private void genConstructor(ClassWriter cw) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ "java/lang/Object",
+ "<init>",
+ "()V",
+ false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ /**
+ * Generate bytecode for hasSplitPackages method
*/
- private void genDescriptorsMethod() {
- this.mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
- "descriptors",
+ private void genHasSplitPackages(ClassWriter cw) {
+ boolean distinct = moduleInfos.stream()
+ .map(ModuleInfo::packages)
+ .flatMap(Set::stream)
+ .allMatch(new HashSet<>()::add);
+ boolean hasSplitPackages = !distinct;
+
+ mv = cw.visitMethod(ACC_PUBLIC,
+ "hasSplitPackages",
+ "()Z",
+ "()Z",
+ null);
+ mv.visitCode();
+ if (hasSplitPackages) {
+ mv.visitInsn(ICONST_1);
+ } else {
+ mv.visitInsn(ICONST_0);
+ }
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ /**
+ * Generate bytecode for hasIncubatorModules method
+ */
+ private void genIncubatorModules(ClassWriter cw) {
+ boolean hasIncubatorModules = moduleInfos.stream()
+ .map(ModuleInfo::moduleResolution)
+ .filter(mres -> (mres != null && mres.hasIncubatingWarning()))
+ .findFirst()
+ .isPresent();
+
+ mv = cw.visitMethod(ACC_PUBLIC,
+ "hasIncubatorModules",
+ "()Z",
+ "()Z",
+ null);
+ mv.visitCode();
+ if (hasIncubatorModules) {
+ mv.visitInsn(ICONST_1);
+ } else {
+ mv.visitInsn(ICONST_0);
+ }
+ mv.visitInsn(IRETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ /**
+ * Generate bytecode for moduleDescriptors method
+ */
+ private void genModuleDescriptorsMethod(ClassWriter cw) {
+ this.mv = cw.visitMethod(ACC_PUBLIC,
+ "moduleDescriptors",
"()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
"()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE,
null);
@@ -643,11 +739,11 @@
}
/**
- * Generate bytecode for SystemModules::targets method
+ * Generate bytecode for moduleTargets method
*/
- private void genTargetsMethod() {
- MethodVisitor mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
- "targets",
+ private void genModuleTargetsMethod(ClassWriter cw) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC,
+ "moduleTargets",
"()" + MODULE_TARGET_ARRAY_SIGNATURE,
"()" + MODULE_TARGET_ARRAY_SIGNATURE,
null);
@@ -656,18 +752,34 @@
mv.visitTypeInsn(ANEWARRAY, MODULE_TARGET_CLASSNAME);
mv.visitVarInsn(ASTORE, MT_VAR);
- for (int index=0; index < moduleInfos.size(); index++) {
+
+ // if java.base has a ModuleTarget attribute then generate the array
+ // with one element, all other elements will be null.
+
+ ModuleInfo base = moduleInfos.get(0);
+ if (!base.moduleName().equals("java.base"))
+ throw new InternalError("java.base should be first module in list");
+ ModuleTarget target = base.target();
+
+ int count;
+ if (target != null && target.targetPlatform() != null) {
+ count = 1;
+ } else {
+ count = moduleInfos.size();
+ }
+
+ for (int index = 0; index < count; index++) {
ModuleInfo minfo = moduleInfos.get(index);
- if (minfo.target() != null && !minfo.dropModuleTarget) {
+ if (minfo.target() != null) {
mv.visitVarInsn(ALOAD, MT_VAR);
pushInt(mv, index);
- // new ModuleTarget(String, String)
+ // new ModuleTarget(String)
mv.visitTypeInsn(NEW, MODULE_TARGET_CLASSNAME);
mv.visitInsn(DUP);
mv.visitLdcInsn(minfo.target().targetPlatform());
mv.visitMethodInsn(INVOKESPECIAL, MODULE_TARGET_CLASSNAME,
- "<init>", "(Ljava/lang/String;)V", false);
+ "<init>", "(Ljava/lang/String;)V", false);
mv.visitInsn(AASTORE);
}
@@ -680,12 +792,12 @@
}
/**
- * Generate bytecode for SystemModules::hashes method
+ * Generate bytecode for moduleHashes method
*/
- private void genHashesMethod() {
+ private void genModuleHashesMethod(ClassWriter cw) {
MethodVisitor hmv =
- cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
- "hashes",
+ cw.visitMethod(ACC_PUBLIC,
+ "moduleHashes",
"()" + MODULE_HASHES_ARRAY_SIGNATURE,
"()" + MODULE_HASHES_ARRAY_SIGNATURE,
null);
@@ -710,11 +822,11 @@
}
/**
- * Generate bytecode for SystemModules::methodResoultions method
+ * Generate bytecode for moduleResolutions method
*/
- private void genModuleResolutionsMethod() {
+ private void genModuleResolutionsMethod(ClassWriter cw) {
MethodVisitor mresmv =
- cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
+ cw.visitMethod(ACC_PUBLIC,
"moduleResolutions",
"()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
"()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE,
@@ -746,75 +858,88 @@
}
/**
- * Generate SystemModules::concealedPackagesToOpen and
- * SystemModules::exportedPackagesToOpen methods.
+ * Generate bytecode for moduleReads method
*/
- private void genXXXPackagesToOpenMethods() {
- List<ModuleDescriptor> descriptors = moduleInfos.stream()
- .map(ModuleInfo::descriptor)
- .collect(Collectors.toList());
- ModuleFinder finder = finderOf(descriptors);
- IllegalAccessMaps maps = IllegalAccessMaps.generate(finder);
- generate("concealedPackagesToOpen", maps.concealedPackagesToOpen());
- generate("exportedPackagesToOpen", maps.exportedPackagesToOpen());
+ private void genModuleReads(ClassWriter cw, Configuration cf) {
+ // module name -> names of modules that it reads
+ Map<String, Set<String>> map = cf.modules().stream()
+ .collect(Collectors.toMap(
+ ResolvedModule::name,
+ m -> m.reads().stream()
+ .map(ResolvedModule::name)
+ .collect(Collectors.toSet())));
+ generate(cw, "moduleReads", map, true);
}
/**
- * Generate SystemModules:XXXPackagesToOpen
+ * Generate concealedPackagesToOpen and exportedPackagesToOpen methods.
*/
- private void generate(String methodName, Map<String, Set<String>> map) {
- // Map<String, Set<String>> XXXPackagesToOpen()
- MethodVisitor mv = cw.visitMethod(ACC_PUBLIC+ACC_STATIC,
+ private void genXXXPackagesToOpenMethods(ClassWriter cw) {
+ ModuleFinder finder = finderOf(moduleInfos);
+ IllegalAccessMaps maps = IllegalAccessMaps.generate(finder);
+ generate(cw, "concealedPackagesToOpen", maps.concealedPackagesToOpen(), false);
+ generate(cw, "exportedPackagesToOpen", maps.exportedPackagesToOpen(), false);
+ }
+
+ /**
+ * Generate method to return {@code Map<String, Set<String>>}.
+ *
+ * If {@code dedup} is true then the values are de-duplicated.
+ */
+ private void generate(ClassWriter cw,
+ String methodName,
+ Map<String, Set<String>> map,
+ boolean dedup) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC,
methodName,
"()Ljava/util/Map;",
"()Ljava/util/Map;",
null);
mv.visitCode();
- // new Map$Entry[moduleCount]
+ // map of Set -> local
+ Map<Set<String>, Integer> locals;
+
+ // generate code to create the sets that are duplicated
+ if (dedup) {
+ Collection<Set<String>> values = map.values();
+ Set<Set<String>> duplicateSets = values.stream()
+ .distinct()
+ .filter(s -> Collections.frequency(values, s) > 1)
+ .collect(Collectors.toSet());
+ locals = new HashMap<>();
+ int index = 1;
+ for (Set<String> s : duplicateSets) {
+ genImmutableSet(mv, s);
+ mv.visitVarInsn(ASTORE, index);
+ locals.put(s, index);
+ if (++index >= MAX_LOCAL_VARS) {
+ break;
+ }
+ }
+ } else {
+ locals = Map.of();
+ }
+
+ // new Map$Entry[size]
pushInt(mv, map.size());
mv.visitTypeInsn(ANEWARRAY, "java/util/Map$Entry");
int index = 0;
for (Map.Entry<String, Set<String>> e : map.entrySet()) {
- String moduleName = e.getKey();
- Set<String> packages = e.getValue();
- int packageCount = packages.size();
+ String name = e.getKey();
+ Set<String> s = e.getValue();
mv.visitInsn(DUP);
pushInt(mv, index);
- mv.visitLdcInsn(moduleName);
+ mv.visitLdcInsn(name);
- // use Set.of(Object[]) when there are more than 2 packages
- // use Set.of(Object) or Set.of(Object, Object) when fewer packages
- if (packageCount > 2) {
- pushInt(mv, packageCount);
- mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
- int i = 0;
- for (String pn : packages) {
- mv.visitInsn(DUP);
- pushInt(mv, i);
- mv.visitLdcInsn(pn);
- mv.visitInsn(AASTORE);
- i++;
- }
- mv.visitMethodInsn(INVOKESTATIC,
- "java/util/Set",
- "of",
- "([Ljava/lang/Object;)Ljava/util/Set;",
- true);
+ // if de-duplicated then load the local, otherwise generate code
+ Integer varIndex = locals.get(s);
+ if (varIndex == null) {
+ genImmutableSet(mv, s);
} else {
- StringBuilder sb = new StringBuilder("(");
- for (String pn : packages) {
- mv.visitLdcInsn(pn);
- sb.append("Ljava/lang/Object;");
- }
- sb.append(")Ljava/util/Set;");
- mv.visitMethodInsn(INVOKESTATIC,
- "java/util/Set",
- "of",
- sb.toString(),
- true);
+ mv.visitVarInsn(ALOAD, varIndex);
}
String desc = "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map$Entry;";
@@ -835,19 +960,42 @@
mv.visitEnd();
}
- public boolean isOverriddenClass(String path) {
- return path.equals("/java.base/" + CLASSNAME + ".class");
- }
+ /**
+ * Generate code to generate an immutable set.
+ */
+ private void genImmutableSet(MethodVisitor mv, Set<String> set) {
+ int size = set.size();
- void pushInt(MethodVisitor mv, int num) {
- if (num <= 5) {
- mv.visitInsn(ICONST_0 + num);
- } else if (num < Byte.MAX_VALUE) {
- mv.visitIntInsn(BIPUSH, num);
- } else if (num < Short.MAX_VALUE) {
- mv.visitIntInsn(SIPUSH, num);
+ // use Set.of(Object[]) when there are more than 2 elements
+ // use Set.of(Object) or Set.of(Object, Object) when fewer
+ if (size > 2) {
+ pushInt(mv, size);
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+ int i = 0;
+ for (String element : set) {
+ mv.visitInsn(DUP);
+ pushInt(mv, i);
+ mv.visitLdcInsn(element);
+ mv.visitInsn(AASTORE);
+ i++;
+ }
+ mv.visitMethodInsn(INVOKESTATIC,
+ "java/util/Set",
+ "of",
+ "([Ljava/lang/Object;)Ljava/util/Set;",
+ true);
} else {
- throw new IllegalArgumentException("exceed limit: " + num);
+ StringBuilder sb = new StringBuilder("(");
+ for (String element : set) {
+ mv.visitLdcInsn(element);
+ sb.append("Ljava/lang/Object;");
+ }
+ sb.append(")Ljava/util/Set;");
+ mv.visitMethodInsn(INVOKESTATIC,
+ "java/util/Set",
+ "of",
+ sb.toString(),
+ true);
}
}
@@ -1564,18 +1712,159 @@
}
}
- static ModuleFinder finderOf(Iterable<ModuleDescriptor> descriptors) {
+ /**
+ * Generate SystemModulesMap and add it as a resource.
+ *
+ * @return the name of the class resource added to the pool
+ */
+ private String genSystemModulesMapClass(String allSystemModulesClassName,
+ String defaultSystemModulesClassName,
+ Map<String, String> map,
+ ResourcePoolBuilder out) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ + ClassWriter.COMPUTE_FRAMES);
+ cw.visit(Opcodes.V1_8,
+ ACC_FINAL+ACC_SUPER,
+ SYSTEM_MODULES_MAP_CLASS,
+ null,
+ "java/lang/Object",
+ null);
+
+ // <init>
+ MethodVisitor mv = cw.visitMethod(0, "<init>", "()V", null, null);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ "java/lang/Object",
+ "<init>",
+ "()V",
+ false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // allSystemModules()
+ mv = cw.visitMethod(ACC_STATIC,
+ "allSystemModules",
+ "()Ljdk/internal/module/SystemModules;",
+ "()Ljdk/internal/module/SystemModules;",
+ null);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, allSystemModulesClassName);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ allSystemModulesClassName,
+ "<init>",
+ "()V",
+ false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // defaultSystemModules()
+ mv = cw.visitMethod(ACC_STATIC,
+ "defaultSystemModules",
+ "()Ljdk/internal/module/SystemModules;",
+ "()Ljdk/internal/module/SystemModules;",
+ null);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, defaultSystemModulesClassName);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL,
+ defaultSystemModulesClassName,
+ "<init>",
+ "()V",
+ false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // moduleNames()
+ mv = cw.visitMethod(ACC_STATIC,
+ "moduleNames",
+ "()[Ljava/lang/String;",
+ "()[Ljava/lang/String;",
+ null);
+ mv.visitCode();
+ pushInt(mv, map.size());
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+
+ int index = 0;
+ for (String moduleName : map.keySet()) {
+ mv.visitInsn(DUP); // arrayref
+ pushInt(mv, index);
+ mv.visitLdcInsn(moduleName);
+ mv.visitInsn(AASTORE);
+ index++;
+ }
+
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // classNames()
+ mv = cw.visitMethod(ACC_STATIC,
+ "classNames",
+ "()[Ljava/lang/String;",
+ "()[Ljava/lang/String;",
+ null);
+ mv.visitCode();
+ pushInt(mv, map.size());
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+
+ index = 0;
+ for (String className : map.values()) {
+ mv.visitInsn(DUP); // arrayref
+ pushInt(mv, index);
+ mv.visitLdcInsn(className.replace('/', '.'));
+ mv.visitInsn(AASTORE);
+ index++;
+ }
+
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // write the class file to the pool as a resource
+ String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASS + ".class";
+ ResourcePoolEntry e = ResourcePoolEntry.create(rn, cw.toByteArray());
+ out.add(e);
+
+ return rn;
+ }
+
+ /**
+ * Pushes an int constant
+ */
+ private static void pushInt(MethodVisitor mv, int value) {
+ if (value <= 5) {
+ mv.visitInsn(ICONST_0 + value);
+ } else if (value < Byte.MAX_VALUE) {
+ mv.visitIntInsn(BIPUSH, value);
+ } else if (value < Short.MAX_VALUE) {
+ mv.visitIntInsn(SIPUSH, value);
+ } else {
+ throw new IllegalArgumentException("exceed limit: " + value);
+ }
+ }
+
+ /**
+ * Returns a module finder that finds all modules in the given list
+ */
+ private static ModuleFinder finderOf(Collection<ModuleInfo> moduleInfos) {
+ Supplier<ModuleReader> readerSupplier = () -> null;
Map<String, ModuleReference> namesToReference = new HashMap<>();
- for (ModuleDescriptor descriptor : descriptors) {
- String name = descriptor.name();
- URI uri = URI.create("module:/" + name);
- ModuleReference mref = new ModuleReference(descriptor, uri) {
- @Override
- public ModuleReader open() {
- throw new UnsupportedOperationException();
- }
- };
- namesToReference.putIfAbsent(name, mref);
+ for (ModuleInfo mi : moduleInfos) {
+ String name = mi.moduleName();
+ ModuleReference mref
+ = new ModuleReferenceImpl(mi.descriptor(),
+ URI.create("jrt:/" + name),
+ readerSupplier,
+ null,
+ mi.target(),
+ null,
+ null,
+ mi.moduleResolution());
+ namesToReference.put(name, mref);
}
return new ModuleFinder() {
--- a/jdk/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Mon Aug 07 09:45:38 2017 -0700
@@ -107,35 +107,38 @@
* diagnostic command are described in the table below:
*
* <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
* <tr>
- * <th>Name</th><th>Type</th><th>Description</th>
+ * <th scope="col">Name</th><th scope="col">Type</th><th scope="col">Description</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>dcmd.name</td><td>String</td>
+ * <th scope="row">dcmd.name</th><td>String</td>
* <td>The original diagnostic command name (not the operation name)</td>
* </tr>
* <tr>
- * <td>dcmd.description</td><td>String</td>
+ * <th scope="row">dcmd.description</th><td>String</td>
* <td>The diagnostic command description</td>
* </tr>
* <tr>
- * <td>dcmd.help</td><td>String</td>
+ * <th scope="row">dcmd.help</th><td>String</td>
* <td>The full help message for this diagnostic command (same output as
* the one produced by the 'help' command)</td>
* </tr>
* <tr>
- * <td>dcmd.vmImpact</td><td>String</td>
+ * <th scope="row">dcmd.vmImpact</th><td>String</td>
* <td>The impact of the diagnostic command,
* this value is the same as the one printed in the 'impact'
* section of the help message of the diagnostic command, and it
* is different from the getImpact() of the MBeanOperationInfo</td>
* </tr>
* <tr>
- * <td>dcmd.enabled</td><td>boolean</td>
+ * <th scope="row">dcmd.enabled</th><td>boolean</td>
* <td>True if the diagnostic command is enabled, false otherwise</td>
* </tr>
* <tr>
- * <td>dcmd.permissionClass</td><td>String</td>
+ * <th scope="row">dcmd.permissionClass</th><td>String</td>
* <td>Some diagnostic command might require a specific permission to be
* executed, in addition to the MBeanPermission to invoke their
* associated MBean operation. This field returns the fully qualified
@@ -143,22 +146,23 @@
* </td>
* </tr>
* <tr>
- * <td>dcmd.permissionName</td><td>String</td>
+ * <th scope="row">dcmd.permissionName</th><td>String</td>
* <td>The fist argument of the permission required to execute this
* diagnostic command or null if no permission is required</td>
* </tr>
* <tr>
- * <td>dcmd.permissionAction</td><td>String</td>
+ * <th scope="row">dcmd.permissionAction</th><td>String</td>
* <td>The second argument of the permission required to execute this
* diagnostic command or null if the permission constructor has only
* one argument (like the ManagementPermission) or if no permission
* is required</td>
* </tr>
* <tr>
- * <td>dcmd.arguments</td><td>Descriptor</td>
+ * <th scope="row">dcmd.arguments</th><td>Descriptor</td>
* <td>A Descriptor instance containing the descriptions of options and
* arguments supported by the diagnostic command (see below)</td>
* </tr>
+ * </tbody>
* </table>
*
* <p>The description of parameters (options or arguments) of a diagnostic
@@ -168,37 +172,41 @@
* instance are described in the table below:
*
* <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
* <tr>
- * <th>Name</th><th>Type</th><th>Description</th>
+ * <th scope="col">Name</th><th scope="col">Type</th><th scope="col">Description</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>dcmd.arg.name</td><td>String</td>
+ * <th scope="row">dcmd.arg.name</th><td>String</td>
* <td>The name of the parameter</td>
* </tr>
* <tr>
- * <td>dcmd.arg.type</td><td>String</td>
+ * <th scope="row">dcmd.arg.type</th><td>String</td>
* <td>The type of the parameter. The returned String is the name of a type
* recognized by the diagnostic command parser. These types are not
* Java types and are implementation dependent.
* </td>
* </tr>
* <tr>
- * <td>dcmd.arg.description</td><td>String</td>
+ * <th scope="row">dcmd.arg.description</th><td>String</td>
* <td>The parameter description</td>
* </tr>
* <tr>
- * <td>dcmd.arg.isMandatory</td><td>boolean</td>
+ * <th scope="row">dcmd.arg.isMandatory</th><td>boolean</td>
* <td>True if the parameter is mandatory, false otherwise</td>
* </tr>
* <tr>
- * <td>dcmd.arg.isOption</td><td>boolean</td>
+ * <th scope="row">dcmd.arg.isOption</th><td>boolean</td>
* <td>True if the parameter is an option, false if it is an argument</td>
* </tr>
* <tr>
- * <td>dcmd.arg.isMultiple</td><td>boolean</td>
+ * <th scope="row">dcmd.arg.isMultiple</th><td>boolean</td>
* <td>True if the parameter can be specified several times, false
* otherwise</td>
* </tr>
+ * </tbody>
* </table>
*
* <p>When the set of diagnostic commands currently supported by the Java
--- a/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java Mon Aug 07 09:45:38 2017 -0700
@@ -182,26 +182,30 @@
* the following attributes:
* <blockquote>
* <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
* <tr>
- * <th style="text-align:left">Attribute Name</th>
- * <th style="text-align:left">Type</th>
+ * <th scope="col" style="text-align:left">Attribute Name</th>
+ * <th scope="col" style="text-align:left">Type</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>gcName</td>
+ * <th scope="row">gcName</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>gcAction</td>
+ * <th scope="row">gcAction</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>gcCause</td>
+ * <th scope="row">gcCause</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>gcInfo</td>
+ * <th scope="row">gcInfo</th>
* <td>{@code javax.management.openmbean.CompositeData}</td>
* </tr>
+ * </tbody>
* </table>
* </blockquote>
*
--- a/jdk/src/jdk.management/share/classes/com/sun/management/GcInfo.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/GcInfo.java Mon Aug 07 09:45:38 2017 -0700
@@ -184,30 +184,34 @@
*
* <blockquote>
* <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
* <tr>
- * <th style="text-align:left">Attribute Name</th>
- * <th style="text-align:left">Type</th>
+ * <th scope="col" style="text-align:left">Attribute Name</th>
+ * <th scope="col" style="text-align:left">Type</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>index</td>
+ * <th scope="row">index</th>
* <td>{@code java.lang.Long}</td>
* </tr>
* <tr>
- * <td>startTime</td>
+ * <th scope="row">startTime</th>
* <td>{@code java.lang.Long}</td>
* </tr>
* <tr>
- * <td>endTime</td>
+ * <th scope="row">endTime</th>
* <td>{@code java.lang.Long}</td>
* </tr>
* <tr>
- * <td>memoryUsageBeforeGc</td>
+ * <th scope="row">memoryUsageBeforeGc</th>
* <td>{@code javax.management.openmbean.TabularData}</td>
* </tr>
* <tr>
- * <td>memoryUsageAfterGc</td>
+ * <th scope="row">memoryUsageAfterGc</th>
* <td>{@code javax.management.openmbean.TabularData}</td>
* </tr>
+ * </tbody>
* </table>
* </blockquote>
*
--- a/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java Mon Aug 07 09:45:38 2017 -0700
@@ -191,26 +191,30 @@
*
* <blockquote>
* <table class="striped"><caption style="display:none">description</caption>
+ * <thead>
* <tr>
- * <th style="text-align:left">Attribute Name</th>
- * <th style="text-align:left">Type</th>
+ * <th scope="col" style="text-align:left">Attribute Name</th>
+ * <th scope="col" style="text-align:left">Type</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>name</td>
+ * <th scope="row">name</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>value</td>
+ * <th scope="row">value</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>origin</td>
+ * <th scope="row">origin</th>
* <td>{@code java.lang.String}</td>
* </tr>
* <tr>
- * <td>writeable</td>
+ * <th scope="row">writeable</th>
* <td>{@code java.lang.Boolean}</td>
* </tr>
+ * </tbody>
* </table>
* </blockquote>
*
--- a/jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java Mon Aug 07 09:45:38 2017 -0700
@@ -36,25 +36,30 @@
*
* <table class="striped"><caption style="display:none">permission target name,
* what the target allows,and associated risks</caption>
+ * <thead>
* <tr>
- * <th>Permission Target Name</th>
- * <th>What the Permission Allows</th>
- * <th>Risks of Allowing this Permission</th>
+ * <th scope="col">Permission Target Name</th>
+ * <th scope="col">What the Permission Allows</th>
+ * <th scope="col">Risks of Allowing this Permission</th>
* </tr>
+ * </thead>
+ * <tbody>
* <tr>
- * <td>setOption.SO_FLOW_SLA</td>
+ * <th scope="row">setOption.SO_FLOW_SLA</th>
* <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option
* on any socket that supports it</td>
* <td>allows caller to set a higher priority or bandwidth allocation
* to sockets it creates, than they might otherwise be allowed.</td>
* </tr>
* <tr>
- * <td>getOption.SO_FLOW_SLA</td>
+ * <th scope="row">getOption.SO_FLOW_SLA</th>
* <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA}
* setting from any socket that supports the option</td>
* <td>allows caller access to SLA information that it might not
* otherwise have</td>
- * </tr></table>
+ * </tr>
+ * </tbody>
+ * </table>
*
* @see jdk.net.ExtendedSocketOptions
*
--- a/jdk/test/java/lang/ClassLoader/getResource/GetResource.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/lang/ClassLoader/getResource/GetResource.java Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -21,11 +21,45 @@
* questions.
*/
+/*
+ * @test
+ * @bug 6760902
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.ProcessTools
+ * @run testng GetResource
+ * @summary Empty path on bootclasspath is not default to current working
+ * directory for both class lookup and resource lookup whereas
+ * empty path on classpath is default to current working directory.
+ */
+
+import java.io.File;
+import java.io.IOException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.JDKToolFinder;
+import static jdk.testlibrary.ProcessTools.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
public class GetResource {
+ private static final Path CWD = Paths.get(System.getProperty("user.dir"));
+ private static final String DIR_A = "a";
+ private static final String DIR_B = "b";
+
private static final String RESOURCE_NAME = "test.properties";
- public static void main(String[] args) {
+ private static final String GETRESOURCE_CLASS = "GetResource.class";
+
+ public static void main(String... args) {
String expect = args[0] + "/" + RESOURCE_NAME;
URL url = GetResource.class.getResource(RESOURCE_NAME);
System.out.println("getResource found: " + url);
@@ -39,4 +73,98 @@
throw new RuntimeException(url + " != expected resource " + expect);
}
}
+
+ @BeforeTest
+ public void setup() throws IOException {
+ // setup two directories "a" and "b"
+ // each directory contains both test.properties and this test class
+ Path testSrc = Paths.get(System.getProperty("test.src"));
+ Path testClasses = Paths.get(System.getProperty("test.classes"));
+
+ Files.createDirectories(Paths.get(DIR_A));
+ Files.createDirectories(Paths.get(DIR_B));
+
+ Files.copy(testSrc.resolve(RESOURCE_NAME),
+ Paths.get(DIR_A, RESOURCE_NAME));
+ Files.copy(testSrc.resolve(RESOURCE_NAME),
+ Paths.get(DIR_B, RESOURCE_NAME));
+
+ Files.copy(testClasses.resolve(GETRESOURCE_CLASS),
+ Paths.get(DIR_A, GETRESOURCE_CLASS));
+ Files.copy(testClasses.resolve(GETRESOURCE_CLASS),
+ Paths.get(DIR_B, GETRESOURCE_CLASS));
+ }
+
+ private String concat(String... dirs) {
+ return Stream.of(dirs).collect(Collectors.joining(File.pathSeparator));
+ }
+
+ @DataProvider
+ public Object[][] options() {
+ return new Object[][] {
+ new Object[] { List.of("-Xbootclasspath/a:a"), "a"},
+ new Object[] { List.of("-Xbootclasspath/a:b"), "b"},
+ new Object[] { List.of("-Xbootclasspath/a:" + concat("a", "b")), "a"},
+ new Object[] { List.of("-Xbootclasspath/a:" + concat("b", "a")), "b"},
+
+ new Object[] { List.of("-cp", "a"), "a"},
+ new Object[] { List.of("-cp", "b"), "b"},
+ new Object[] { List.of("-cp", concat("a", "b")), "a"},
+ new Object[] { List.of("-cp", concat("b", "a")), "b"},
+ };
+ }
+
+ @Test(dataProvider = "options")
+ public void test(List<String> options, String expected) throws Throwable {
+ runTest(CWD, options, expected);
+ }
+
+ @DataProvider
+ public Object[][] dirA() {
+ String dirB = ".." + File.separator + "b";
+ return new Object[][] {
+ new Object[] { List.of("-Xbootclasspath/a:."), "a"},
+
+ new Object[] { List.of("-Xbootclasspath/a:" + dirB), "b"},
+ // empty path in first element
+ new Object[] { List.of("-Xbootclasspath/a:" + File.pathSeparator + dirB), "b"},
+
+ new Object[] { List.of("-cp", File.pathSeparator), "a"},
+ new Object[] { List.of("-cp", dirB), "b"},
+ new Object[] { List.of("-cp", File.pathSeparator + dirB), "a"},
+ };
+ }
+
+ @Test(dataProvider = "dirA")
+ public void testCurrentDirA(List<String> options, String expected) throws Throwable {
+ // current working directory is "a"
+ runTest(CWD.resolve(DIR_A), options, expected);
+ }
+
+ private void runTest(Path dir, List<String> options, String expected)
+ throws Throwable
+ {
+ String javapath = JDKToolFinder.getJDKTool("java");
+
+ List<String> cmdLine = new ArrayList<>();
+ cmdLine.add(javapath);
+ options.forEach(cmdLine::add);
+
+ cmdLine.add("GetResource");
+ cmdLine.add(expected);
+
+ System.out.println("Command line: " + cmdLine);
+ ProcessBuilder pb =
+ new ProcessBuilder(cmdLine.stream().toArray(String[]::new));
+
+ // change working directory
+ pb.directory(dir.toFile());
+
+ // remove CLASSPATH environment variable
+ Map<String,String> env = pb.environment();
+ String value = env.remove("CLASSPATH");
+
+ executeCommand(pb).shouldHaveExitValue(0);
+ }
+
}
--- a/jdk/test/java/lang/ClassLoader/getResource/GetResource.sh Mon Aug 07 10:02:39 2017 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6760902
-# @summary Empty path on bootclasspath is not default to current working
-# directory for both class lookup and resource lookup whereas
-# empty path on classpath is default to current working directory.
-#
-# @run shell GetResource.sh
-
-if [ -z "$TESTJAVA" ]; then
- if [ $# -lt 1 ]; then exit 1; fi
- TESTJAVA="$1"; shift
- COMPILEJAVA="${TESTJAVA}"
- TESTSRC="`pwd`"
- TESTCLASSES="`pwd`"
-fi
-
-# set platform-specific variables
-OS=`uname -s`
-case "$OS" in
- Windows*)
- PS=";"
- ;;
- CYGWIN* )
- PS=";"
- TESTCLASSES=`/usr/bin/cygpath -a -s -m ${TESTCLASSES}`
- ;;
- * )
- PS=":"
- ;;
-esac
-
-echo TESTSRC=${TESTSRC}
-echo TESTCLASSES=${TESTCLASSES}
-echo TESTJAVA=${TESTJAVA}
-echo ""
-
-${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
- -d ${TESTCLASSES} \
- ${TESTSRC}/GetResource.java || exit 10
-
-setup() {
- dest=${TESTCLASSES}/$1
- rm -rf $dest
- mkdir $dest
- cp ${TESTSRC}/test.properties $dest
- cp ${TESTCLASSES}/GetResource.class $dest
-}
-
-
-count=0
-runTest() {
- expected=$1;
- vmoption=$2; shift; shift
- count=`expr $count+1`
- echo "Test $count : $vmoption $@"
- ${TESTJAVA}/bin/java ${TESTVMOPTS} "$vmoption" $@ \
- GetResource $expected || exit $count
-}
-
-# run test
-setup "a"
-setup "b"
-
-cd ${TESTCLASSES}
-DIR=`pwd`
-
-# Expected -classpath
-runTest "a" -cp a
-runTest "a" -cp "a${PS}b"
-runTest "b" -cp b
-runTest "b" -cp "b${PS}a"
-
-cd ${DIR}/a
-
-# no -classpath
-runTest "a" -cp "${PS}"
-runTest "b" -cp "../b"
-
-# Test empty path in classpath default to current working directory
-runTest "a" -cp "${PS}../b"
-
--- a/jdk/test/java/net/httpclient/security/0.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/0.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/1.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/1.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/10.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/10.policy Mon Aug 07 09:45:38 2017 -0700
@@ -22,6 +22,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/11.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/11.policy Mon Aug 07 09:45:38 2017 -0700
@@ -24,6 +24,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/12.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/12.policy Mon Aug 07 09:45:38 2017 -0700
@@ -24,6 +24,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/14.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/14.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/15.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/15.policy Mon Aug 07 09:45:38 2017 -0700
@@ -26,6 +26,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/2.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/2.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/3.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/3.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/4.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/4.policy Mon Aug 07 09:45:38 2017 -0700
@@ -24,6 +24,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/5.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/5.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/6.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/6.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/7.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/7.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/8.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/8.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/9.policy Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/9.policy Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
grant codeBase "jrt:/jdk.incubator.httpclient" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.net";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.net.util";
permission java.lang.RuntimePermission "accessClassInPackage.sun.net.www";
permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc";
--- a/jdk/test/java/net/httpclient/security/Driver.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/net/httpclient/security/Driver.java Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -34,7 +34,7 @@
* @compile ../ProxyServer.java
* @build Security
*
- * @run driver/timeout=60 Driver
+ * @run driver/timeout=90 Driver
*/
/**
--- a/jdk/test/java/nio/channels/Selector/KeySets.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/nio/channels/Selector/KeySets.java Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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,34 +26,25 @@
* @summary Check various properties of key and selected-key sets
*
* @run main KeySets
- * @run main/othervm -Dsun.nio.ch.bugLevel=1.4 KeySets
*/
import java.io.*;
import java.nio.channels.*;
import java.util.*;
-
public class KeySets {
- static boolean compat;
-
static abstract class Catch {
abstract void go() throws Exception;
Catch(Class xc) throws Exception {
try {
go();
} catch (Exception x) {
- if (compat)
- throw new Exception("Exception thrown", x);
if (xc.isInstance(x))
return;
throw new Exception("Wrong exception", x);
}
- if (compat)
- return;
- throw new Exception("Not thrown as expected: "
- + xc.getName());
+ throw new Exception("Not thrown as expected: " + xc.getName());
}
}
@@ -74,7 +65,6 @@
void go() throws Exception {
sel.selectedKeys();
}};
-
}
static void testNoAddition(final Set s) throws Exception {
@@ -174,14 +164,10 @@
sel.selectedKeys().clear();
if (!sel.selectedKeys().isEmpty())
throw new Exception("clear failed");
-
}
public static void main(String[] args) throws Exception {
- String bl = System.getProperty("sun.nio.ch.bugLevel");
- compat = (bl != null) && bl.equals("1.4");
testClose();
testMutability();
}
-
}
--- a/jdk/test/java/rmi/testlibrary/TestSocketFactory.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/rmi/testlibrary/TestSocketFactory.java Mon Aug 07 09:45:38 2017 -0700
@@ -512,9 +512,8 @@
} else {
if (matchIndex > 0) {
// mismatch, write out any that matched already
- if (matchIndex > 0) // Only non-trivial matches
- DEBUG( "Partial match %s matched %d bytes at offset: %d (0x%04x), expected: x%02x, actual: x%02x%n",
- name, matchIndex, bytesOut, bytesOut, matchBytes[matchIndex], b);
+ DEBUG("Partial match %s matched %d bytes at offset: %d (0x%04x), expected: x%02x, actual: x%02x%n",
+ name, matchIndex, bytesOut, bytesOut, matchBytes[matchIndex], b);
out.write(matchBytes, 0, matchIndex);
log.write(matchBytes, 0, matchIndex);
bytesOut += matchIndex;
@@ -530,6 +529,19 @@
}
}
+ public void flush() throws IOException {
+ if (matchIndex > 0) {
+ // write out any that matched already to avoid consumer hang.
+ // Match/replace across a flush is not supported.
+ DEBUG( "Flush partial match %s matched %d bytes at offset: %d (0x%04x)%n",
+ name, matchIndex, bytesOut, bytesOut);
+ out.write(matchBytes, 0, matchIndex);
+ log.write(matchBytes, 0, matchIndex);
+ bytesOut += matchIndex;
+ matchIndex = 0;
+ }
+ }
+
@Override
public String toString() {
return String.format("%s: Out: (%d)", name, bytesOut);
--- a/jdk/test/java/util/ResourceBundle/modules/layer/run.sh Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/java/util/ResourceBundle/modules/layer/run.sh Mon Aug 07 09:45:38 2017 -0700
@@ -22,7 +22,7 @@
#
# @test
-# @bug 8180375
+# @bug 8180375 8185251
# @summary Tests resource bundles are correctly loaded from
# modules through "<packageName>.spi.<simpleName>Provider" types.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/modules/layer/src/m1/p/resources/MyResource_en.properties Mon Aug 07 09:45:38 2017 -0700
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+# Purposely empty resource bundle
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java Mon Aug 07 09:45:38 2017 -0700
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+//
+// This test case relies on updated static security property, no way to re-use
+// security property in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8180643
+ * @summary Illegal handshake message
+ *
+ * @run main/othervm IllegalHandshakeMessage
+ */
+
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.security.*;
+import java.nio.*;
+
+public class IllegalHandshakeMessage {
+
+ public static void main(String args[]) throws Exception {
+ SSLContext context = SSLContext.getDefault();
+
+ SSLEngine cliEngine = context.createSSLEngine();
+ cliEngine.setUseClientMode(true);
+ SSLEngine srvEngine = context.createSSLEngine();
+ srvEngine.setUseClientMode(false);
+
+ SSLSession session = cliEngine.getSession();
+ int netBufferMax = session.getPacketBufferSize();
+ int appBufferMax = session.getApplicationBufferSize();
+
+ ByteBuffer cliToSrv = ByteBuffer.allocateDirect(netBufferMax);
+ ByteBuffer srvToCli = ByteBuffer.allocateDirect(netBufferMax);
+ ByteBuffer srvIBuff = ByteBuffer.allocateDirect(appBufferMax + 50);
+ ByteBuffer cliOBuff = ByteBuffer.wrap("I'm client".getBytes());
+ ByteBuffer srvOBuff = ByteBuffer.wrap("I'm server".getBytes());
+
+
+ System.out.println("client hello (handshake type(0xAB))");
+ SSLEngineResult cliRes = cliEngine.wrap(cliOBuff, cliToSrv);
+ System.out.println("Client wrap result: " + cliRes);
+ cliToSrv.flip();
+ if (cliToSrv.limit() > 7) {
+ cliToSrv.put(5, (byte)0xAB); // use illegal handshake type
+ cliToSrv.put(7, (byte)0x80); // use illegal message length
+ } else {
+ // unlikely
+ throw new Exception("No handshage message generated.");
+ }
+
+ try {
+ SSLEngineResult srvRes = srvEngine.unwrap(cliToSrv, srvIBuff);
+ System.out.println("Server unwrap result: " + srvRes);
+ runDelegatedTasks(srvRes, srvEngine);
+
+ srvRes = srvEngine.wrap(srvOBuff, srvToCli);
+ System.out.println("Server wrap result: " + srvRes);
+
+ throw new Exception(
+ "Unsupported handshake message is not handled properly.");
+ } catch (SSLException e) {
+ // get the expected exception
+ System.out.println("Expected exception: " + e);
+ }
+ }
+
+ private static void runDelegatedTasks(SSLEngineResult result,
+ SSLEngine engine) throws Exception {
+
+ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable runnable;
+ while ((runnable = engine.getDelegatedTask()) != null) {
+ System.out.println("\trunning delegated task...");
+ runnable.run();
+ }
+ HandshakeStatus hsStatus = engine.getHandshakeStatus();
+ if (hsStatus == HandshakeStatus.NEED_TASK) {
+ throw new Exception(
+ "handshake shouldn't need additional tasks");
+ }
+ System.out.println("\tnew HandshakeStatus: " + hsStatus);
+ }
+ }
+}
+
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Mon Aug 07 09:45:38 2017 -0700
@@ -111,16 +111,10 @@
private void checkAttributes(ModuleReference modRef) {
try {
- if (modRef.descriptor().name().equals("java.base")) {
- ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
- String[] values = mt.targetPlatform().split("-");
- assertTrue(checkOSName(values[0]));
- assertTrue(checkOSArch(values[1]));
- } else {
- // target platform attribute is dropped by jlink plugin for other modules
- ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
- assertTrue(mt == null || mt.targetPlatform() == null);
- }
+ ModuleTargetHelper.ModuleTarget mt = ModuleTargetHelper.read(modRef);
+ String[] values = mt.targetPlatform().split("-");
+ assertTrue(checkOSName(values[0]));
+ assertTrue(checkOSArch(values[1]));
} catch (IOException exp) {
throw new UncheckedIOException(exp);
}
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Mon Aug 07 09:45:38 2017 -0700
@@ -284,7 +284,6 @@
Set<String> modules = Set.of("m1", "m4");
assertTrue(JLINK_TOOL.run(System.out, System.out,
"--output", dir.toString(),
- "--system-modules", "retainModuleTarget",
"--exclude-resources", "m4/p4/dummy/*",
"--add-modules", modules.stream().collect(Collectors.joining(",")),
"--module-path", mp) == 0);
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java Mon Aug 07 09:45:38 2017 -0700
@@ -32,7 +32,7 @@
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import jdk.internal.module.ClassFileAttributes;
@@ -67,8 +67,7 @@
}
private static boolean hasModuleTarget(String modName) throws IOException {
- FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
- Collections.emptyMap());
+ FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Map.of());
Path path = fs.getPath("/", "modules", modName, "module-info.class");
try (InputStream in = Files.newInputStream(path)) {
return hasModuleTarget(in);
@@ -86,8 +85,8 @@
expectModuleTarget = true;
}
- // java.base is packaged with osName/osArch/osVersion
- if (! hasModuleTarget("java.base")) {
+ // java.base is packaged with ModuleTarget
+ if (!hasModuleTarget("java.base")) {
throw new RuntimeException("ModuleTarget absent for java.base");
}
@@ -109,8 +108,7 @@
}
// verify ModuleDescriptor from module-info.class read from jimage
- FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
- Collections.emptyMap());
+ FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Map.of());
Path path = fs.getPath("/", "modules", mn, "module-info.class");
checkModuleDescriptor(ModuleDescriptor.read(Files.newInputStream(path)), packages);
}
@@ -121,16 +119,9 @@
throw new RuntimeException(md.mainClass().toString());
}
- if (expectModuleTarget) {
- // ModuleTarget attribute is retained
- if (! hasModuleTarget(md.name())) {
- throw new RuntimeException("ModuleTarget missing for " + md.name());
- }
- } else {
- // by default ModuleTarget attribute is dropped
- if (hasModuleTarget(md.name())) {
- throw new RuntimeException("ModuleTarget present for " + md.name());
- }
+ // ModuleTarget attribute should be present
+ if (!hasModuleTarget(md.name())) {
+ throw new RuntimeException("ModuleTarget missing for " + md.name());
}
Set<String> pkgs = md.packages();
--- a/jdk/test/tools/launcher/modules/illegalaccess/IllegalAccessTest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/jdk/test/tools/launcher/modules/illegalaccess/IllegalAccessTest.java Mon Aug 07 09:45:38 2017 -0700
@@ -23,6 +23,7 @@
/**
* @test
+ * @requires vm.compMode != "Xcomp"
* @modules java.base/jdk.internal.misc
* java.base/sun.security.x509
* java.activation
--- a/jdk/test/tools/launcher/modules/patch/systemmodules/src1/java.base/jdk/internal/modules/SystemModules.java Mon Aug 07 10:02:39 2017 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.module;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-/*
- * Test --patch-module java.base=jdk/modules/java.base to override
- * java.base with an exploded image
- */
-public final class SystemModules {
- public static final String[] MODULE_NAMES = new String[0];
-
- public static int PACKAGES_IN_BOOT_LAYER = 1024;
-
- public static boolean hasSplitPackages() {
- return true;
- }
-
- public static Map<String, Set<String>> concealedPackagesToOpen() {
- return Collections.emptyMap();
- }
-
- public static Map<String, Set<String>> exportedPackagesToOpen() {
- return Collections.emptyMap();
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/patch/systemmodules/src1/java.base/jdk/internal/modules/SystemModulesMap.java Mon Aug 07 09:45:38 2017 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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 jdk.internal.module;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/*
+ * Test --patch-module java.base=jdk/modules/java.base to override
+ * java.base with an exploded image
+ */
+class SystemModulesMap {
+ static SystemModules allSystemModules() {
+ return null;
+ }
+ static SystemModules defaultSystemModules() {
+ return null;
+ }
+ static String[] moduleNames() {
+ return new String[0];
+ }
+ static String[] classNames() {
+ return new String[0];
+ }
+}
--- a/langtools/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -437,3 +437,6 @@
2f01728210c1405ef459e69d9c7247b5df6abb78 jdk-9+177
2b9273266ea629ca686239c416a7ff8a592d822a jdk-10+15
4070d214e88729006184a4abbe8f494fcec6afb6 jdk-10+16
+849e366ef175012e6dedc3ca151da416716e0ea9 jdk-9+178
+b653b1b2ea883593596bc18e9af73a9b369eeb0a jdk-9+179
+41028d8c0a71c6beaf1886ca095e703fbb1513ec jdk-10+17
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/javadoc/Doclet.java Mon Aug 07 09:45:38 2017 -0700
@@ -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
@@ -30,7 +30,7 @@
* showing the entry-point methods. A starting class must
* import com.sun.javadoc.* and implement the
* {@code start(RootDoc)} method, as described in the
- * <a href="package-summary.html#package_description">package
+ * <a href="package-summary.html#package.description">package
* description</a>. If the doclet takes command line options,
* it must also implement {@code optionLength} and
* {@code validOptions}.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/Doclet.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/Doclet.java Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -33,7 +33,7 @@
/**
* The user doclet must implement this interface, as described in the
- * <a href="package-summary.html#package_description">package description</a>.
+ * <a href="package-summary.html#package.description">package description</a>.
* Each implementation of a Doclet must provide a public no-argument constructor
* to be used by tools to instantiate the doclet. The tool infrastructure will
* interact with classes implementing this interface as follows:
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java Mon Aug 07 09:45:38 2017 -0700
@@ -40,10 +40,12 @@
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
@@ -162,6 +164,11 @@
public boolean createtree = true;
/**
+ * The META charset tag used for cross-platform viewing.
+ */
+ public String charset = null;
+
+ /**
* True if command line option "-nodeprecated" is used. Default value is
* false.
*/
@@ -797,4 +804,23 @@
oset.addAll(super.getSupportedOptions());
return oset;
}
+
+ @Override
+ protected boolean finishOptionSettings0() throws DocletException {
+ if (docencoding == null) {
+ if (charset == null) {
+ docencoding = charset = (encoding == null) ? HtmlConstants.HTML_DEFAULT_CHARSET : encoding;
+ } else {
+ docencoding = charset;
+ }
+ } else {
+ if (charset == null) {
+ charset = docencoding;
+ } else if (!charset.equals(docencoding)) {
+ reporter.print(ERROR, getText("doclet.Option_conflict", "-charset", "-docencoding"));
+ return false;
+ }
+ }
+ return super.finishOptionSettings0();
+ }
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Aug 07 09:45:38 2017 -0700
@@ -446,9 +446,7 @@
Content head = new HtmlTree(HtmlTag.HEAD);
head.addContent(getGeneratedBy(!configuration.notimestamp));
head.addContent(getTitle());
- Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE,
- (configuration.charset.length() > 0) ?
- configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET);
+ Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
head.addContent(meta);
if (!configuration.notimestamp) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Mon Aug 07 09:45:38 2017 -0700
@@ -78,9 +78,7 @@
Content windowTitle = HtmlTree.TITLE(new StringContent(title));
head.addContent(windowTitle);
- Content metaContentType = HtmlTree.META("Content", CONTENT_TYPE,
- (configuration.charset.length() > 0) ?
- configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET);
+ Content metaContentType = HtmlTree.META("Content", CONTENT_TYPE, configuration.charset);
head.addContent(metaContentType);
String topFilePath = configuration.topFile.getPath();
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java Mon Aug 07 09:45:38 2017 -0700
@@ -1007,8 +1007,7 @@
? getHyperLink(SectionName.PACKAGES, contents.navPackages)
: contents.navPackages);
addNavGap(liNav);
- liNav.addContent((display(uses) || (moduleMode == ModuleMode.API && display(usesTrees))
- || display(provides) || (moduleMode == ModuleMode.API && display(providesTrees)))
+ liNav.addContent((displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees))
? getHyperLink(SectionName.SERVICES, contents.navServices)
: contents.navServices);
ulNav.addContent(liNav);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java Mon Aug 07 09:45:38 2017 -0700
@@ -247,6 +247,7 @@
public void addPackageDescription(Content packageContentTree) {
if (!utils.getBody(packageElement).isEmpty()) {
Content tree = configuration.allowTag(HtmlTag.SECTION) ? sectionTree : packageContentTree;
+ tree.addContent(getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION));
addDeprecationInfo(tree);
addInlineComment(packageElement, tree);
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Mon Aug 07 09:45:38 2017 -0700
@@ -328,9 +328,7 @@
head.addContent(getGeneratedBy(!configuration.notimestamp));
Content windowTitle = HtmlTree.TITLE(new StringContent(title));
head.addContent(windowTitle);
- Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE,
- (configuration.charset.length() > 0) ?
- configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET);
+ Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
head.addContent(meta);
head.addContent(getStyleSheetProperties(configuration));
head.addContent(getFramesJavaScript());
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Mon Aug 07 09:45:38 2017 -0700
@@ -55,6 +55,7 @@
import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
import jdk.javadoc.internal.doclets.toolkit.util.TypeElementCatalog;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.GetterSetter;
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
@@ -66,11 +67,11 @@
* BaseConfiguration, to configure and add their own options. This class contains
* all user options which are supported by the 1.1 doclet and the standard
* doclet.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
+ * <p>
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
*
* @author Robert Field.
* @author Atul Dambalkar.
@@ -142,11 +143,6 @@
public boolean backwardCompatibility = true;
/**
- * The META charset tag used for cross-platform viewing.
- */
- public String charset = "";
-
- /**
* True if user wants to add member names as meta keywords.
* Set to false because meta keywords are ignored in general
* by most Internet search engines.
@@ -240,7 +236,6 @@
/**
* Sourcepath from where to read the source files. Default is classpath.
- *
*/
public String sourcepath = "";
@@ -266,7 +261,7 @@
* True if user wants to suppress time stamp in output.
* Default is false.
*/
- public boolean notimestamp= false;
+ public boolean notimestamp = false;
/**
* The package grouping instance.
@@ -278,7 +273,7 @@
*/
public final Extern extern = new Extern(this);
- public Reporter reporter;
+ public Reporter reporter;
public Locale locale;
@@ -287,21 +282,21 @@
*/
public boolean quiet = false;
- private String urlForLink;
-
- private String pkglistUrlForLink;
+ // A list containing urls
+ private final List<String> linkList = new ArrayList<>();
- private String urlForLinkOffline;
+ // A list of pairs containing urls and package list
+ private final List<Pair<String, String>> linkOfflineList = new ArrayList<>();
- private String pkglistUrlForLinkOffline;
public boolean dumpOnError = false;
- private List<GroupContainer> groups;
+ private List<Pair<String, String>> groupPairs;
private final Map<TypeElement, EnumMap<Kind, Reference<VisibleMemberMap>>> typeElementMemberCache;
public abstract Messages getMessages();
+
public abstract Resources getResources();
/**
@@ -342,15 +337,17 @@
*/
public SortedMap<ModuleElement, Set<PackageElement>> modulePackages;
- /**
- * The list of known modules, that should be documented.
- */
+ /**
+ * The list of known modules, that should be documented.
+ */
public SortedSet<ModuleElement> modules;
protected static final String sharedResourceBundleName =
"jdk.javadoc.internal.doclets.toolkit.resources.doclets";
+
/**
* Constructs the configurations needed by the doclet.
+ *
* @param doclet the doclet that created this configuration
*/
public BaseConfiguration(Doclet doclet) {
@@ -359,7 +356,7 @@
excludedQualifiers = new HashSet<>();
setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
metakeywords = new MetaKeywords(this);
- groups = new ArrayList<>(0);
+ groupPairs = new ArrayList<>(0);
typeElementMemberCache = new HashMap<>();
}
@@ -400,31 +397,37 @@
}
private Set<ModuleElement> specifiedModuleElements;
+
public Set<ModuleElement> getSpecifiedModuleElements() {
return specifiedModuleElements;
}
private Set<PackageElement> specifiedPackageElements;
+
public Set<PackageElement> getSpecifiedPackageElements() {
return specifiedPackageElements;
}
private Set<TypeElement> specifiedTypeElements;
+
public Set<TypeElement> getSpecifiedTypeElements() {
return specifiedTypeElements;
}
private Set<ModuleElement> includedModuleElements;
+
public Set<ModuleElement> getIncludedModuleElements() {
return includedModuleElements;
}
private Set<PackageElement> includedPackageElements;
+
public Set<PackageElement> getIncludedPackageElements() {
return includedPackageElements;
}
private Set<TypeElement> includedTypeElements;
+
public Set<TypeElement> getIncludedTypeElements() {
return includedTypeElements;
}
@@ -435,7 +438,7 @@
modules.addAll(getSpecifiedModuleElements());
modulePackages = new TreeMap<>(utils.makeModuleComparator());
- for (PackageElement p: packages) {
+ for (PackageElement p : packages) {
ModuleElement mdle = docEnv.getElementUtils().getModuleOf(p);
if (mdle != null && !mdle.isUnnamed()) {
Set<PackageElement> s = modulePackages
@@ -444,7 +447,7 @@
}
}
- for (PackageElement p: getIncludedPackageElements()) {
+ for (PackageElement p : getIncludedPackageElements()) {
ModuleElement mdle = docEnv.getElementUtils().getModuleOf(p);
if (mdle != null && !mdle.isUnnamed()) {
Set<PackageElement> s = modulePackages
@@ -474,207 +477,205 @@
public Set<Doclet.Option> getSupportedOptions() {
Resources resources = getResources();
Doclet.Option[] options = {
- new Option(resources, "-author") {
- @Override
- public boolean process(String opt, List<String> args) {
- showauthor = true;
- return true;
- }
- },
- new Option(resources, "-d", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- destDirName = addTrailingFileSep(args.get(0));
- return true;
- }
- },
- new Option(resources, "-docencoding", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- docencoding = args.get(0);
- return true;
- }
- },
- new Option(resources, "-docfilessubdirs") {
- @Override
- public boolean process(String opt, List<String> args) {
- copydocfilesubdirs = true;
- return true;
- }
- },
- new Hidden(resources, "-encoding", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- encoding = args.get(0);
- return true;
- }
- },
- new Option(resources, "-excludedocfilessubdir", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- addToSet(excludedDocFileDirs, args.get(0));
- return true;
- }
- },
- new Option(resources, "-group", 2) {
- @Override
- public boolean process(String opt, List<String> args) {
- groups.add(new GroupContainer(args.get(0), args.get(1)));
- return true;
- }
- },
- new Option(resources, "--javafx -javafx") {
- @Override
- public boolean process(String opt, List<String> args) {
- javafx = true;
- return true;
- }
- },
- new Option(resources, "-keywords") {
- @Override
- public boolean process(String opt, List<String> args) {
- keywords = true;
- return true;
- }
- },
- new Option(resources, "-link", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- urlForLink = args.get(0);
- pkglistUrlForLink = urlForLink;
- return true;
- }
- },
- new Option(resources, "-linksource") {
- @Override
- public boolean process(String opt, List<String> args) {
- linksource = true;
- return true;
- }
- },
- new Option(resources, "-linkoffline", 2) {
- @Override
- public boolean process(String opt, List<String> args) {
- urlForLinkOffline = args.get(0);
- pkglistUrlForLinkOffline = args.get(1);
- return true;
- }
- },
- new Option(resources, "-nocomment") {
- @Override
- public boolean process(String opt, List<String> args) {
- nocomment = true;
- return true;
- }
- },
- new Option(resources, "-nodeprecated") {
- @Override
- public boolean process(String opt, List<String> args) {
- nodeprecated = true;
- return true;
+ new Option(resources, "-author") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ showauthor = true;
+ return true;
+ }
+ },
+ new Option(resources, "-d", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ destDirName = addTrailingFileSep(args.get(0));
+ return true;
+ }
+ },
+ new Option(resources, "-docencoding", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ docencoding = args.get(0);
+ return true;
+ }
+ },
+ new Option(resources, "-docfilessubdirs") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ copydocfilesubdirs = true;
+ return true;
+ }
+ },
+ new Hidden(resources, "-encoding", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ encoding = args.get(0);
+ return true;
+ }
+ },
+ new Option(resources, "-excludedocfilessubdir", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ addToSet(excludedDocFileDirs, args.get(0));
+ return true;
+ }
+ },
+ new Option(resources, "-group", 2) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ groupPairs.add(new Pair<>(args.get(0), args.get(1)));
+ return true;
+ }
+ },
+ new Option(resources, "--javafx -javafx") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ javafx = true;
+ return true;
+ }
+ },
+ new Option(resources, "-keywords") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ keywords = true;
+ return true;
+ }
+ },
+ new Option(resources, "-link", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ linkList.add(args.get(0));
+ return true;
+ }
+ },
+ new Option(resources, "-linksource") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ linksource = true;
+ return true;
+ }
+ },
+ new Option(resources, "-linkoffline", 2) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ linkOfflineList.add(new Pair<String, String>(args.get(0), args.get(1)));
+ return true;
+ }
+ },
+ new Option(resources, "-nocomment") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ nocomment = true;
+ return true;
+ }
+ },
+ new Option(resources, "-nodeprecated") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ nodeprecated = true;
+ return true;
+ }
+ },
+ new Option(resources, "-nosince") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ nosince = true;
+ return true;
+ }
+ },
+ new Option(resources, "-notimestamp") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ notimestamp = true;
+ return true;
+ }
+ },
+ new Option(resources, "-noqualifier", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ addToSet(excludedQualifiers, args.get(0));
+ return true;
+ }
+ },
+ new Hidden(resources, "-quiet") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ quiet = true;
+ return true;
+ }
+ },
+ new Option(resources, "-serialwarn") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ serialwarn = true;
+ return true;
+ }
+ },
+ new Option(resources, "-sourcetab", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ linksource = true;
+ try {
+ setTabWidth(Integer.parseInt(args.get(0)));
+ } catch (NumberFormatException e) {
+ //Set to -1 so that warning will be printed
+ //to indicate what is valid argument.
+ sourcetab = -1;
+ }
+ if (sourcetab <= 0) {
+ getMessages().warning("doclet.sourcetab_warning");
+ setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
+ }
+ return true;
+ }
+ },
+ new Option(resources, "-tag", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ ArrayList<String> list = new ArrayList<>();
+ list.add(opt);
+ list.add(args.get(0));
+ customTagStrs.add(list);
+ return true;
+ }
+ },
+ new Option(resources, "-taglet", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ ArrayList<String> list = new ArrayList<>();
+ list.add(opt);
+ list.add(args.get(0));
+ customTagStrs.add(list);
+ return true;
+ }
+ },
+ new Option(resources, "-tagletpath", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ tagletpath = args.get(0);
+ return true;
+ }
+ },
+ new Option(resources, "-version") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ showversion = true;
+ return true;
+ }
+ },
+ new Hidden(resources, "--dump-on-error") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ dumpOnError = true;
+ return true;
+ }
+ },
+ new Option(resources, "--allow-script-in-comments") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ allowScriptInComments = true;
+ return true;
+ }
}
- },
- new Option(resources, "-nosince") {
- @Override
- public boolean process(String opt, List<String> args) {
- nosince = true;
- return true;
- }
- },
- new Option(resources, "-notimestamp") {
- @Override
- public boolean process(String opt, List<String> args) {
- notimestamp = true;
- return true;
- }
- },
- new Option(resources, "-noqualifier", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- addToSet(excludedQualifiers, args.get(0));
- return true;
- }
- },
- new Hidden(resources, "-quiet") {
- @Override
- public boolean process(String opt, List<String> args) {
- quiet = true;
- return true;
- }
- },
- new Option(resources, "-serialwarn") {
- @Override
- public boolean process(String opt, List<String> args) {
- serialwarn = true;
- return true;
- }
- },
- new Option(resources, "-sourcetab", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- linksource = true;
- try {
- setTabWidth(Integer.parseInt(args.get(0)));
- } catch (NumberFormatException e) {
- //Set to -1 so that warning will be printed
- //to indicate what is valid argument.
- sourcetab = -1;
- }
- if (sourcetab <= 0) {
- getMessages().warning("doclet.sourcetab_warning");
- setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
- }
- return true;
- }
- },
- new Option(resources, "-tag", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- ArrayList<String> list = new ArrayList<>();
- list.add(opt);
- list.add(args.get(0));
- customTagStrs.add(list);
- return true;
- }
- },
- new Option(resources, "-taglet", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- ArrayList<String> list = new ArrayList<>();
- list.add(opt);
- list.add(args.get(0));
- customTagStrs.add(list);
- return true;
- }
- },
- new Option(resources, "-tagletpath", 1) {
- @Override
- public boolean process(String opt, List<String> args) {
- tagletpath = args.get(0);
- return true;
- }
- },
- new Option(resources, "-version") {
- @Override
- public boolean process(String opt, List<String> args) {
- showversion = true;
- return true;
- }
- },
- new Hidden(resources, "--dump-on-error") {
- @Override
- public boolean process(String opt, List<String> args) {
- dumpOnError = true;
- return true;
- }
- },
- new Option(resources, "--allow-script-in-comments") {
- @Override
- public boolean process(String opt, List<String> args) {
- allowScriptInComments = true;
- return true;
- }
- }
};
Set<Doclet.Option> set = new TreeSet<>();
set.addAll(Arrays.asList(options));
@@ -687,24 +688,24 @@
* when this is called all the option have been set, this method,
* initializes certain components before anything else is started.
*/
- private void finishOptionSettings0() throws DocletException {
+ protected boolean finishOptionSettings0() throws DocletException {
initDestDirectory();
- if (urlForLink != null && pkglistUrlForLink != null)
- extern.link(urlForLink, pkglistUrlForLink, reporter, false);
- if (urlForLinkOffline != null && pkglistUrlForLinkOffline != null)
- extern.link(urlForLinkOffline, pkglistUrlForLinkOffline, reporter, true);
- if (docencoding == null) {
- docencoding = encoding;
+ for (String link : linkList) {
+ extern.link(link, reporter);
+ }
+ for (Pair<String, String> linkOfflinePair : linkOfflineList) {
+ extern.link(linkOfflinePair.first, linkOfflinePair.second, reporter);
}
typeElementCatalog = new TypeElementCatalog(includedTypeElements, this);
initTagletManager(customTagStrs);
- groups.stream().forEach((grp) -> {
+ groupPairs.stream().forEach((grp) -> {
if (showModules) {
- group.checkModuleGroups(grp.value1, grp.value2);
+ group.checkModuleGroups(grp.first, grp.second);
} else {
- group.checkPackageGroups(grp.value1, grp.value2);
+ group.checkPackageGroups(grp.first, grp.second);
}
});
+ return true;
}
/**
@@ -716,8 +717,7 @@
public boolean setOptions() throws DocletException {
initPackages();
initModules();
- finishOptionSettings0();
- if (!finishOptionSettings())
+ if (!finishOptionSettings0() || !finishOptionSettings())
return false;
return true;
@@ -748,12 +748,12 @@
* be in the following format: "[tag name]:[location str]:[heading]".
*
* @param customTagStrs the set two dimensional arrays of strings. These arrays contain
- * either -tag or -taglet arguments.
+ * either -tag or -taglet arguments.
*/
private void initTagletManager(Set<List<String>> customTagStrs) {
tagletManager = tagletManager == null ?
- new TagletManager(nosince, showversion, showauthor, javafx, this) :
- tagletManager;
+ new TagletManager(nosince, showversion, showauthor, javafx, this) :
+ tagletManager;
for (List<String> args : customTagStrs) {
if (args.get(0).equals("-taglet")) {
tagletManager.addCustomTag(args.get(1), getFileManager(), tagletpath);
@@ -793,12 +793,11 @@
* @param maxTokens the maximum number of tokens returned. If the
* max is reached, the remaining part of s is appended
* to the end of the last token.
- *
* @return an array of tokens.
*/
private List<String> tokenize(String s, char separator, int maxTokens) {
List<String> tokens = new ArrayList<>();
- StringBuilder token = new StringBuilder ();
+ StringBuilder token = new StringBuilder();
boolean prevIsEscapeChar = false;
for (int i = 0; i < s.length(); i += Character.charCount(i)) {
int currentChar = s.codePointAt(i);
@@ -806,7 +805,7 @@
// Case 1: escaped character
token.appendCodePoint(currentChar);
prevIsEscapeChar = false;
- } else if (currentChar == separator && tokens.size() < maxTokens-1) {
+ } else if (currentChar == separator && tokens.size() < maxTokens - 1) {
// Case 2: separator
tokens.add(token.toString());
token = new StringBuilder();
@@ -824,10 +823,10 @@
return tokens;
}
- private void addToSet(Set<String> s, String str){
+ private void addToSet(Set<String> s, String str) {
StringTokenizer st = new StringTokenizer(str, ":");
String current;
- while(st.hasMoreTokens()){
+ while (st.hasMoreTokens()) {
current = st.nextToken();
s.add(current);
}
@@ -847,7 +846,7 @@
int indexDblfs;
while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
path = path.substring(0, indexDblfs) +
- path.substring(indexDblfs + fs.length());
+ path.substring(indexDblfs + fs.length());
}
if (!path.endsWith(fs))
path += fs;
@@ -855,7 +854,6 @@
}
/**
- *
* This checks for the validity of the options used by the user.
* As of this writing, this checks only docencoding.
*
@@ -883,7 +881,7 @@
* @param reporter used to report errors.
*/
private boolean checkOutputFileEncoding(String docencoding) {
- OutputStream ost= new ByteArrayOutputStream();
+ OutputStream ost = new ByteArrayOutputStream();
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(ost, docencoding);
@@ -908,7 +906,7 @@
* @param docfilesubdir the doc-files subdirectory to check.
* @return true if the directory is excluded.
*/
- public boolean shouldExcludeDocFileDir(String docfilesubdir){
+ public boolean shouldExcludeDocFileDir(String docfilesubdir) {
return excludedDocFileDirs.contains(docfilesubdir);
}
@@ -918,10 +916,10 @@
* @param qualifier the qualifier to check.
* @return true if the qualifier should be excluded
*/
- public boolean shouldExcludeQualifier(String qualifier){
+ public boolean shouldExcludeQualifier(String qualifier) {
if (excludedQualifiers.contains("all") ||
- excludedQualifiers.contains(qualifier) ||
- excludedQualifiers.contains(qualifier + ".*")) {
+ excludedQualifiers.contains(qualifier) ||
+ excludedQualifiers.contains(qualifier + ".*")) {
return true;
} else {
int index = -1;
@@ -956,7 +954,7 @@
* @param key the key for the desired string
* @return the string for the given key
* @throws MissingResourceException if the key is not found in either
- * bundle.
+ * bundle.
*/
public abstract String getText(String key);
@@ -965,11 +963,11 @@
* {@link Resources resources}.
* Equivalent to <code>getResources.getText(key, args);</code>.
*
- * @param key the key for the desired string
+ * @param key the key for the desired string
* @param args values to be substituted into the resulting string
* @return the string for the given key
* @throws MissingResourceException if the key is not found in either
- * bundle.
+ * bundle.
*/
public abstract String getText(String key, String... args);
@@ -997,8 +995,8 @@
* {@link Resources resources} as a {@code Content} object.
*
* @param key the key for the desired string
- * @param o1 resource argument
- * @param o2 resource argument
+ * @param o1 resource argument
+ * @param o2 resource argument
* @return a content tree for the text
*/
public abstract Content getContent(String key, Object o1, Object o2);
@@ -1045,8 +1043,8 @@
*/
public InputStream getBuilderXML() throws DocFileIOException {
return builderXMLPath == null ?
- BaseConfiguration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
- DocFile.createFileForInput(this, builderXMLPath).openInputStream();
+ BaseConfiguration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
+ DocFile.createFileForInput(this, builderXMLPath).openInputStream();
}
/**
@@ -1203,18 +1201,6 @@
}
/*
- * Stores a pair of Strings.
- */
- protected static class GroupContainer {
- final String value1;
- final String value2;
- public GroupContainer(String value1, String value2) {
- this.value1 = value1;
- this.value2 = value2;
- }
- }
-
- /*
* Splits the elements in a collection to its individual
* collection.
*/
@@ -1267,6 +1253,7 @@
/**
* Returns whether or not to allow JavaScript in comments.
* Default is off; can be set true from a command line option.
+ *
* @return the allowScriptInComments
*/
public boolean isAllowScriptInComments() {
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java Mon Aug 07 09:45:38 2017 -0700
@@ -170,6 +170,36 @@
}
/**
+ * Build the extern package list from given URL or the directory path,
+ * as specified with the "-link" flag.
+ * Flag error if the "-link" or "-linkoffline" option is already used.
+ *
+ * @param url URL or Directory path.
+ * @param reporter The <code>DocErrorReporter</code> used to report errors.
+ * @return true if successful, false otherwise
+ * @throws DocFileIOException if there is a problem reading a package list file
+ */
+ public boolean link(String url, Reporter reporter) throws DocFileIOException {
+ return link(url, url, reporter, false);
+ }
+
+ /**
+ * Build the extern package list from given URL or the directory path,
+ * as specified with the "-linkoffline" flag.
+ * Flag error if the "-link" or "-linkoffline" option is already used.
+ *
+ * @param url URL or Directory path.
+ * @param pkglisturl This can be another URL for "package-list" or ordinary
+ * file.
+ * @param reporter The <code>DocErrorReporter</code> used to report errors.
+ * @return true if successful, false otherwise
+ * @throws DocFileIOException if there is a problem reading a package list file
+ */
+ public boolean link(String url, String pkglisturl, Reporter reporter) throws DocFileIOException {
+ return link(url, pkglisturl, reporter, true);
+ }
+
+ /*
* Build the extern package list from given URL or the directory path.
* Flag error if the "-link" or "-linkoffline" option is already used.
*
@@ -181,7 +211,7 @@
* @return true if successful, false otherwise
* @throws DocFileIOException if there is a problem reading a package list file
*/
- public boolean link(String url, String pkglisturl, Reporter reporter, boolean linkoffline)
+ private boolean link(String url, String pkglisturl, Reporter reporter, boolean linkoffline)
throws DocFileIOException {
this.linkoffline = linkoffline;
try {
@@ -245,8 +275,7 @@
readPackageList(link.openStream(), urlpath, false);
} catch (URISyntaxException | MalformedURLException exc) {
throw new Fault(configuration.getText("doclet.MalformedURL", pkglisturlpath.toString()), exc);
- }
- catch (IOException exc) {
+ } catch (IOException exc) {
throw new Fault(configuration.getText("doclet.URL_error", pkglisturlpath.toString()), exc);
}
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java Mon Aug 07 09:45:38 2017 -0700
@@ -202,11 +202,7 @@
try {
OutputStream out = getFileObjectForOutput(path).openOutputStream();
- if (configuration.docencoding == null) {
- return new BufferedWriter(new OutputStreamWriter(out));
- } else {
- return new BufferedWriter(new OutputStreamWriter(out, configuration.docencoding));
- }
+ return new BufferedWriter(new OutputStreamWriter(out, configuration.docencoding));
} catch (IOException e) {
throw new DocFileIOException(this, DocFileIOException.Mode.WRITE, e);
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Mon Aug 07 09:45:38 2017 -0700
@@ -679,10 +679,11 @@
}
}
- /**
+ /**
* Get the signature. It is the parameter list, type is qualified.
* For instance, for a method {@code mymethod(String x, int y)},
* it will return {@code(java.lang.String,int)}.
+ *
* @param e
* @return String
*/
@@ -1674,19 +1675,24 @@
}
}
+ private Comparator<Element> moduleComparator = null;
/**
* Comparator for ModuleElements, simply compares the fully qualified names
* @return a Comparator
*/
public Comparator<Element> makeModuleComparator() {
- return new Utils.ElementComparator<Element>() {
- @Override
- public int compare(Element mod1, Element mod2) {
- return compareFullyQualifiedNames(mod1, mod2);
- }
- };
+ if (moduleComparator == null) {
+ moduleComparator = new Utils.ElementComparator() {
+ @Override
+ public int compare(Element mod1, Element mod2) {
+ return compareFullyQualifiedNames(mod1, mod2);
+ }
+ };
+ }
+ return moduleComparator;
}
+ private Comparator<Element> allClassesComparator = null;
/**
* Returns a Comparator for all classes, compares the simple names of
* TypeElement, if equal then the fully qualified names.
@@ -1694,42 +1700,53 @@
* @return Comparator
*/
public Comparator<Element> makeAllClassesComparator() {
- return new Utils.ElementComparator<Element>() {
- @Override
- public int compare(Element e1, Element e2) {
- int result = compareNames(e1, e2);
- if (result == 0)
- result = compareFullyQualifiedNames(e1, e2);
-
- return result;
- }
- };
+ if (allClassesComparator == null) {
+ allClassesComparator = new Utils.ElementComparator() {
+ @Override
+ public int compare(Element e1, Element e2) {
+ int result = compareNames(e1, e2);
+ if (result == 0)
+ result = compareFullyQualifiedNames(e1, e2);
+
+ return result;
+ }
+ };
+ }
+ return allClassesComparator;
}
+ private Comparator<Element> packageComparator = null;
/**
* Returns a Comparator for packages, by comparing the fully qualified names.
*
* @return a Comparator
*/
public Comparator<Element> makePackageComparator() {
- return new Utils.ElementComparator<Element>() {
- @Override
- public int compare(Element pkg1, Element pkg2) {
- return compareFullyQualifiedNames(pkg1, pkg2);
- }
- };
+ if (packageComparator == null) {
+ packageComparator = new Utils.ElementComparator() {
+ @Override
+ public int compare(Element pkg1, Element pkg2) {
+ return compareFullyQualifiedNames(pkg1, pkg2);
+ }
+ };
+ }
+ return packageComparator;
}
+ private Comparator<SerialFieldTree> serialFieldTreeComparator = null;
/**
* Returns a Comparator for SerialFieldTree.
* @return a Comparator
*/
public Comparator<SerialFieldTree> makeSerialFieldTreeComparator() {
- return (SerialFieldTree o1, SerialFieldTree o2) -> {
- String s1 = o1.getName().toString();
- String s2 = o2.getName().toString();
- return s1.compareTo(s2);
- };
+ if (serialFieldTreeComparator == null) {
+ serialFieldTreeComparator = (SerialFieldTree o1, SerialFieldTree o2) -> {
+ String s1 = o1.getName().toString();
+ String s2 = o2.getName().toString();
+ return s1.compareTo(s2);
+ };
+ }
+ return serialFieldTreeComparator;
}
/**
@@ -1740,6 +1757,7 @@
return makeClassUseComparator();
}
+ private Comparator<Element> overrideUseComparator = null;
/**
* Returns a Comparator for overrides and implements,
* used primarily on methods, compares the name first,
@@ -1748,33 +1766,38 @@
* @return a Comparator
*/
public Comparator<Element> makeOverrideUseComparator() {
- return new Utils.ElementComparator<Element>() {
- @Override
- public int compare(Element o1, Element o2) {
- int result = compareStrings(getSimpleName(o1), getSimpleName(o2));
- if (result != 0) {
- return result;
- }
- if (!isTypeElement(o1) && !isTypeElement(o2) && !isPackage(o1) && !isPackage(o2)) {
- TypeElement t1 = getEnclosingTypeElement(o1);
- TypeElement t2 = getEnclosingTypeElement(o2);
- result = compareStrings(getSimpleName(t1), getSimpleName(t2));
+ if (overrideUseComparator == null) {
+ overrideUseComparator = new Utils.ElementComparator() {
+ @Override
+ public int compare(Element o1, Element o2) {
+ int result = compareStrings(getSimpleName(o1), getSimpleName(o2));
+ if (result != 0) {
+ return result;
+ }
+ if (!isTypeElement(o1) && !isTypeElement(o2) && !isPackage(o1) && !isPackage(o2)) {
+ TypeElement t1 = getEnclosingTypeElement(o1);
+ TypeElement t2 = getEnclosingTypeElement(o2);
+ result = compareStrings(getSimpleName(t1), getSimpleName(t2));
+ if (result != 0)
+ return result;
+ }
+ result = compareStrings(getFullyQualifiedName(o1), getFullyQualifiedName(o2));
if (result != 0)
return result;
+ return compareElementTypeKinds(o1, o2);
}
- result = compareStrings(getFullyQualifiedName(o1), getFullyQualifiedName(o2));
- if (result != 0)
- return result;
- return compareElementTypeKinds(o1, o2);
- }
- };
+ };
+ }
+ return overrideUseComparator;
}
+ private Comparator<Element> indexUseComparator = null;
/**
- * Returns a Comparator for index file presentations, and are sorted as follows.
- * If comparing modules and packages then simply compare the qualified names, if comparing a module
- * or a package with a type/member then compare the FullyQualifiedName of the module or a package
- * with the SimpleName of the entity, otherwise
+ * Returns a Comparator for index file presentations, and are sorted as follows.
+ * If comparing modules and/or packages then simply compare the qualified names,
+ * if comparing a module or a package with a type/member then compare the
+ * FullyQualifiedName of the module or a package with the SimpleName of the entity,
+ * otherwise:
* 1. compare the ElementKind ex: Module, Package, Interface etc.
* 2a. if equal and if the type is of ExecutableElement(Constructor, Methods),
* a case insensitive comparison of parameter the type signatures
@@ -1783,73 +1806,76 @@
* @return a comparator for index file use
*/
public Comparator<Element> makeIndexUseComparator() {
- return new Utils.ElementComparator<Element>() {
- /**
- * Compare two given elements, if comparing two modules or two packages, return the
- * comparison of FullyQualifiedName, if comparing a module or a package with a
- * type/member then compare the FullyQualifiedName of the module or the package
- * with the SimpleName of the entity, then sort on the kinds, then on
- * the parameters only if the type is an ExecutableElement,
- * the parameters are compared and finally the qualified names.
- *
- * @param e1 - an element.
- * @param e2 - an element.
- * @return a negative integer, zero, or a positive integer as the first
- * argument is less than, equal to, or greater than the second.
- */
- @Override
- public int compare(Element e1, Element e2) {
- int result = 0;
- if ((isModule(e1) || isPackage(e1)) && (isModule(e2) || isPackage(e2))) {
- result = compareFullyQualifiedNames(e1, e2);
+ if (indexUseComparator == null) {
+ indexUseComparator = new Utils.ElementComparator() {
+ /**
+ * Compares two elements.
+ *
+ * @param e1 - an element.
+ * @param e2 - an element.
+ * @return a negative integer, zero, or a positive integer as the first
+ * argument is less than, equal to, or greater than the second.
+ */
+ @Override
+ public int compare(Element e1, Element e2) {
+ int result;
+ // first, compare names as appropriate
+ if ((isModule(e1) || isPackage(e1)) && (isModule(e2) || isPackage(e2))) {
+ result = compareFullyQualifiedNames(e1, e2);
+ } else if (isModule(e1) || isPackage(e1)) {
+ result = compareStrings(getFullyQualifiedName(e1), getSimpleName(e2));
+ } else if (isModule(e2) || isPackage(e2)) {
+ result = compareStrings(getSimpleName(e1), getFullyQualifiedName(e2));
+ } else {
+ result = compareNames(e1, e2);
+ }
if (result != 0) {
return result;
}
- return compareElementTypeKinds(e1, e2);
- }
- if (isModule(e1) || isPackage(e1)) {
- result = compareStrings(getFullyQualifiedName(e1), getSimpleName(e2));
- } else if (isModule(e2) || isPackage(e2)) {
- result = compareStrings(getSimpleName(e1), getFullyQualifiedName(e2));
- } else {
- result = compareNames(e1, e2);
- }
- if (result != 0) {
- return result;
- }
- result = compareElementTypeKinds(e1, e2);
- if (result != 0) {
- return result;
- }
- if (hasParameters(e1)) {
- List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
- List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
- result = compareParameters(false, parameters1, parameters2);
+ // if names are the same, compare element kinds
+ result = compareElementTypeKinds(e1, e2);
if (result != 0) {
return result;
}
- result = compareParameters(true, parameters1, parameters2);
- if (result != 0) {
- return result;
+ // if element kinds are the same, and are methods,
+ // compare the method parameters
+ if (hasParameters(e1)) {
+ List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
+ List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
+ result = compareParameters(false, parameters1, parameters2);
+ if (result != 0) {
+ return result;
+ }
+ result = compareParameters(true, parameters1, parameters2);
+ if (result != 0) {
+ return result;
+ }
}
+ // else fall back on fully qualified names
+ return compareFullyQualifiedNames(e1, e2);
}
- return compareFullyQualifiedNames(e1, e2);
- }
- };
+ };
+ }
+ return indexUseComparator;
}
+ private Comparator<TypeMirror> typeMirrorClassUseComparator = null;
/**
* Compares the FullyQualifiedNames of two TypeMirrors
* @return
*/
public Comparator<TypeMirror> makeTypeMirrorClassUseComparator() {
- return (TypeMirror type1, TypeMirror type2) -> {
- String s1 = getQualifiedTypeName(type1);
- String s2 = getQualifiedTypeName(type2);
- return compareStrings(s1, s2);
- };
+ if (typeMirrorClassUseComparator == null) {
+ typeMirrorClassUseComparator = (TypeMirror type1, TypeMirror type2) -> {
+ String s1 = getQualifiedTypeName(type1);
+ String s2 = getQualifiedTypeName(type2);
+ return compareStrings(s1, s2);
+ };
+ }
+ return typeMirrorClassUseComparator;
}
+ private Comparator<TypeMirror> typeMirrorIndexUseComparator = null;
/**
* Compares the SimpleNames of TypeMirrors if equal then the
* FullyQualifiedNames of TypeMirrors.
@@ -1857,12 +1883,15 @@
* @return
*/
public Comparator<TypeMirror> makeTypeMirrorIndexUseComparator() {
- return (TypeMirror t1, TypeMirror t2) -> {
- int result = compareStrings(getTypeName(t1, false), getTypeName(t2, false));
- if (result != 0)
- return result;
- return compareStrings(getQualifiedTypeName(t1), getQualifiedTypeName(t2));
- };
+ if (typeMirrorIndexUseComparator == null) {
+ typeMirrorIndexUseComparator = (TypeMirror t1, TypeMirror t2) -> {
+ int result = compareStrings(getTypeName(t1, false), getTypeName(t2, false));
+ if (result != 0)
+ return result;
+ return compareStrings(getQualifiedTypeName(t1), getQualifiedTypeName(t2));
+ };
+ }
+ return typeMirrorIndexUseComparator;
}
/**
@@ -1936,6 +1965,7 @@
}.visit(e);
}
+ private Comparator<Element> classUseComparator = null;
/**
* Comparator for ClassUse presentations, and sorts as follows:
* 1. member names
@@ -1945,51 +1975,52 @@
* @return a comparator to sort classes and members for class use
*/
public Comparator<Element> makeClassUseComparator() {
- return new Utils.ElementComparator<Element>() {
- /**
- * Compare two Elements, first sort on simple name, and if
- * applicable on the fully qualified name, and finally if applicable
- * on the parameter types.
- * @param e1 - an element.
- * @param e2 - an element.
- * @return a negative integer, zero, or a positive integer as the first
- * argument is less than, equal to, or greater than the second.
- */
- @Override
- public int compare(Element e1, Element e2) {
- int result = compareNames(e1, e2);
- if (result != 0) {
- return result;
- }
- result = compareFullyQualifiedNames(e1, e2);
- if (result != 0) {
- return result;
- }
- if (hasParameters(e1) && hasParameters(e2)) {
- @SuppressWarnings("unchecked")
- List<VariableElement> parameters1 = (List<VariableElement>) ((ExecutableElement)e1).getParameters();
- @SuppressWarnings("unchecked")
- List<VariableElement> parameters2 = (List<VariableElement>) ((ExecutableElement)e2).getParameters();
- result = compareParameters(false, parameters1, parameters2);
+ if (classUseComparator == null) {
+ classUseComparator = new Utils.ElementComparator() {
+ /**
+ * Compares two Elements.
+ *
+ * @param e1 - an element.
+ * @param e2 - an element.
+ * @return a negative integer, zero, or a positive integer as the first
+ * argument is less than, equal to, or greater than the second.
+ */
+ @Override
+ public int compare(Element e1, Element e2) {
+ int result = compareNames(e1, e2);
+ if (result != 0) {
+ return result;
+ }
+ result = compareFullyQualifiedNames(e1, e2);
if (result != 0) {
return result;
}
- result = compareParameters(true, parameters1, parameters2);
+ if (hasParameters(e1) && hasParameters(e2)) {
+ @SuppressWarnings("unchecked")
+ List<VariableElement> parameters1 = (List<VariableElement>)((ExecutableElement)e1).getParameters();
+ @SuppressWarnings("unchecked")
+ List<VariableElement> parameters2 = (List<VariableElement>)((ExecutableElement)e2).getParameters();
+ result = compareParameters(false, parameters1, parameters2);
+ if (result != 0) {
+ return result;
+ }
+ result = compareParameters(true, parameters1, parameters2);
+ }
+ if (result != 0) {
+ return result;
+ }
+ return compareElementTypeKinds(e1, e2);
}
- if (result != 0) {
- return result;
- }
- return compareElementTypeKinds(e1, e2);
- }
- };
+ };
+ }
+ return classUseComparator;
}
/**
* A general purpose comparator to sort Element entities, basically provides the building blocks
* for creating specific comparators for an use-case.
- * @param <T> an Element
*/
- private abstract class ElementComparator<T extends Element> implements Comparator<Element> {
+ private abstract class ElementComparator implements Comparator<Element> {
/**
* compares two parameter arrays by first comparing the length of the arrays, and
* then each Type of the parameter in the array.
@@ -2097,8 +2128,6 @@
/**
* The fully qualified names of the entities, used solely by the comparator.
*
- * @param p1 the first Element.
- * @param p2 the first Element.
* @return a negative integer, zero, or a positive integer as the first argument is less
* than, equal to, or greater than the second.
*/
@@ -3299,4 +3328,19 @@
return out;
}
}
+
+ /**
+ * A simple pair container.
+ * @param <K> first a value
+ * @param <L> second another value
+ */
+ public static class Pair<K, L> {
+ public final K first;
+ public final L second;
+
+ public Pair(K first, L second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
}
--- a/langtools/test/TEST.groups Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/test/TEST.groups Mon Aug 07 09:45:38 2017 -0700
@@ -27,11 +27,13 @@
jdk \
lib \
tools \
+ -jdk/jshell/ExternalEditorTest.java \
-jdk/jshell/ToolReloadTest.java \
-jdk/jshell/ToolLocaleMessageTest.java
# (Almost) no langtools tests are tier 2.
tier2 = \
+ jdk/jshell/ExternalEditorTest.java \
jdk/jshell/ToolReloadTest.java \
jdk/jshell/ToolLocaleMessageTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testCharsetDocencodingOptions/TestCharsetDocencodingOptions.java Mon Aug 07 09:45:38 2017 -0700
@@ -0,0 +1,116 @@
+/*
+ * 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 8183582
+ * @summary Rationalize doclet -docencoding and -charset options.
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester
+ * @run main TestCharsetDocencodingOptions
+ */
+
+public class TestCharsetDocencodingOptions extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestCharsetDocencodingOptions tester = new TestCharsetDocencodingOptions();
+ tester.runTests();
+ }
+
+ @Test
+ void testWithNoOptions() {
+ javadoc("-d", "out",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutputFileEncoding("utf-8");
+ }
+
+ @Test
+ void testWithDocencoding() {
+ javadoc("-d", "out-1",
+ "-docencoding", "ISO-8859-1",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutputFileEncoding("ISO-8859-1");
+ }
+
+ @Test
+ void testWithCharset() {
+ javadoc("-d", "out-2",
+ "-charset", "ISO-8859-1",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutputFileEncoding("ISO-8859-1");
+ }
+
+ @Test
+ void testDocencodingWithCharsetSimilar() {
+ javadoc("-d", "out-3",
+ "-docencoding", "ISO-8859-1",
+ "-charset", "ISO-8859-1",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutputFileEncoding("ISO-8859-1");
+ }
+
+ @Test
+ void testDocencodingWithCharsetDifferent() {
+ javadoc("-d", "out-4",
+ "-charset", "UTF-8",
+ "-docencoding", "ISO-8859-1",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.ERROR);
+
+ checkOutput(Output.OUT, true,
+ "javadoc: error - Option -charset conflicts with -docencoding");
+ }
+
+ @Test
+ void testWithEncoding() {
+ javadoc("-d", "out-5",
+ "-sourcepath", testSrc,
+ "-encoding", "ISO-8859-1",
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutputFileEncoding("ISO-8859-1");
+ }
+
+
+ void checkOutputFileEncoding(String charset) {
+ checkOutput("index.html", true,
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + charset + "\">");
+ checkOutput("pkg/Foo.html", true,
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + charset + "\">");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testCharsetDocencodingOptions/pkg/Foo.java Mon Aug 07 09:45:38 2017 -0700
@@ -0,0 +1,26 @@
+/*
+ * 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 Foo {}
--- a/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java Mon Aug 07 09:45:38 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -106,7 +106,9 @@
checkExit(Exit.OK);
checkOutput("pkg3/package-summary.html", true,
- "<div class=\"contentContainer\">\n"
+ "<div class=\"contentContainer\"><a name=\"package.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ "<div class=\"block\"><p>This is the first line."
+ " Note the newlines before the <p> is relevant.</div>");
--- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Mon Aug 07 09:45:38 2017 -0700
@@ -161,7 +161,9 @@
+ "<!-- ========= START OF TOP NAVBAR ======= -->",
"<main role=\"main\">\n"
+ "<div class=\"header\">",
- "<section role=\"region\">\n"
+ "<section role=\"region\"><a id=\"package.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ "<div class=\"block\">Test package.</div>",
"<footer role=\"contentinfo\">\n"
+ "<nav role=\"navigation\">\n"
@@ -1107,7 +1109,9 @@
"<a name=\"navbar.top.firstrow\">\n"
+ "<!-- -->\n"
+ "</a>",
- "<div class=\"contentContainer\">\n"
+ "<div class=\"contentContainer\"><a name=\"package.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ "<div class=\"block\">Test package.</div>",
"<table class=\"typeSummary\" summary=\"Interface Summary table, listing interfaces, and an explanation\">",
"<table class=\"typeSummary\" summary=\"Class Summary table, listing classes, and an explanation\">",
--- a/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
// 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,
+ "<pre>public class <span class=\"typeNameLabel\">A</span>\n"
+ + "extends java.lang.Object</pre>\n"
+ + "<div class=\"block\">Test links.\n"
+ + " <br>\n"
+ + " <a href=\"../../out2/pkg2/C2.html?is-external=true\" "
+ + "title=\"class or interface in pkg2\"><code>link to pkg2.C2</code></a>\n"
+ + " <br>\n"
+ + " <a href=\"../../out1/mylib/lang/StringBuilderChild.html?is-external=true\" "
+ + "title=\"class or interface in mylib.lang\">"
+ + "<code>link to mylib.lang.StringBuilderChild</code></a>.</div>\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,
+ "<pre>public class <span class=\"typeNameLabel\">A</span>\n"
+ + "extends java.lang.Object</pre>\n"
+ + "<div class=\"block\">Test links.\n"
+ + " <br>\n"
+ + " <a href=\"../../copy/out2/pkg2/C2.html?is-external=true\" "
+ + "title=\"class or interface in pkg2\"><code>link to pkg2.C2</code></a>\n"
+ + " <br>\n"
+ + " <a href=\"../../copy/out1/mylib/lang/StringBuilderChild.html?is-external=true\" "
+ + "title=\"class or interface in mylib.lang\">"
+ + "<code>link to mylib.lang.StringBuilderChild</code></a>.</div>\n"
+ );
}
/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testLinkOption/pkg3/A.java Mon Aug 07 09:45:38 2017 -0700
@@ -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.
+ * <br>
+ * {@link pkg2.C2 link to pkg2.C2}
+ * <br>
+ * {@link mylib.lang.StringBuilderChild link to mylib.lang.StringBuilderChild}.
+ */
+
+public class A {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModuleServicesLink.java Mon Aug 07 09:45:38 2017 -0700
@@ -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,
+ "<a href=\"#module.description\">Description</a> |"
+ + " Modules |"
+ + " <a href=\"#packages.summary\">Packages</a> |"
+ + " <a href=\"#services.summary\">Services</a>");
+
+ }
+
+ @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,
+ "<a href=\"#module.description\">Description</a> |"
+ + " Modules |"
+ + " <a href=\"#packages.summary\">Packages</a> |"
+ + " <a href=\"#services.summary\">Services</a>");
+
+ }
+
+ @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 |"
+ + " <a href=\"#packages.summary\">Packages</a> |"
+ + " Services");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/TestPackageDescription.java Mon Aug 07 09:45:38 2017 -0700
@@ -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,
+ "<a id=\"package.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">package description</div>\n");
+ }
+
+ @Test
+ void test2() {
+ javadoc("-d", "out-2",
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutput("pkg/package-summary.html", true,
+ "<a name=\"package.description\">\n"
+ + "<!-- -->\n"
+ + "</a>\n"
+ + "<div class=\"block\">package description</div>\n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/A.java Mon Aug 07 09:45:38 2017 -0700
@@ -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() {
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testPackageDescription/pkg/package-info.java Mon Aug 07 09:45:38 2017 -0700
@@ -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;
--- a/langtools/test/jdk/jshell/ExternalEditorTest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/langtools/test/jdk/jshell/ExternalEditorTest.java Mon Aug 07 09:45:38 2017 -0700
@@ -28,6 +28,7 @@
* @modules jdk.jshell/jdk.internal.jshell.tool
* @build ReplToolTesting CustomEditor EditorTestBase
* @run testng ExternalEditorTest
+ * @key intermittent
*/
import java.io.BufferedWriter;
--- a/nashorn/.hgtags Mon Aug 07 10:02:39 2017 +0530
+++ b/nashorn/.hgtags Mon Aug 07 09:45:38 2017 -0700
@@ -428,3 +428,6 @@
aa7404e062b95f679018f25eaaf933dcf0cf3f2b jdk-9+177
f8a0c4895b2abe64a8c55af6117ffda192e34d30 jdk-10+15
f456f59dad3f6b74bcc3c668a56d51f5955cfb28 jdk-10+16
+7497ad85759ff010f44344b553223d1647fb6eba jdk-9+178
+3adfb547e3e49e304ffc82d8c6489cb830b74d62 jdk-9+179
+6ac0ca441ccb9ccc49c5007248dc1f3af8076a71 jdk-10+17
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Aug 07 10:02:39 2017 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Aug 07 09:45:38 2017 -0700
@@ -90,9 +90,9 @@
@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 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 @@
}
/**
- * 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 @@
/** 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 @@
}
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 @@
}
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 @@
* @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 @@
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) {
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java Mon Aug 07 10:02:39 2017 +0530
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java Mon Aug 07 09:45:38 2017 -0700
@@ -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 @@
} 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