Merge
This commit is contained in:
commit
09f196a078
3
.hgtags
3
.hgtags
@ -1,3 +1,5 @@
|
||||
e2b70be325bd10dae4c06f74c46d70d480854916 jdk-9+179
|
||||
5b16a1c3ccffff2a82c88bb7ea894c4ff1c9ebde jdk-9+180
|
||||
43bf6f30fcba031ecf0cc7e511efe3a8179d0f77 jdk-9+176
|
||||
d9f6bc6ba599d0487dc18b2fbdb6c34eedf6f958 jdk-9+177
|
||||
bc9df7dd63ec76f50fafeb4acc44465044662f0a jdk-9+178
|
||||
@ -438,3 +440,4 @@ e6d70017f5b9adbb2ec82d826973d0251800a3c3 jdk-10+12
|
||||
9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14
|
||||
878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15
|
||||
4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16
|
||||
7db699468b4f84abbcc01647e5a964409737411a jdk-10+17
|
||||
|
@ -437,3 +437,6 @@ d67a3f1f057f7e31e12f33ebe3667cb73d252268 jdk-10+13
|
||||
a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177
|
||||
a6c830ee8a6798b186730475e700027cdf4598aa jdk-10+15
|
||||
2fe66ca1e2b3c361f949de9cb2894661dc0a3fa2 jdk-10+16
|
||||
ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178
|
||||
252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179
|
||||
a133a7d1007b1456bc62824382fd8ac93b45d329 jdk-10+17
|
||||
|
@ -437,3 +437,6 @@ dc78a3dd6b3a4f11cdae8a3e3d160e6a78bc7838 jdk-9+175
|
||||
c72e9d3823f04cb3ef3166646dfea9e4c2769133 jdk-9+177
|
||||
15f59cfc6fbe9387423fb173e962265c7b5d357e jdk-10+15
|
||||
b82b62ed5debda2d98dda597506ef29cf947fbae jdk-10+16
|
||||
9c1e9712648921ae389d623042d22561fad82d75 jdk-9+178
|
||||
24390da83c5ee9e23ceafbcaff4460a01e37bb3a jdk-9+179
|
||||
50ff1fd66362f212a8db6de76089d9d0ffa4df0f jdk-10+17
|
||||
|
@ -597,3 +597,6 @@ e920b4d008d914f3414bd4630b58837cf0b7f08d jdk-10+14
|
||||
1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177
|
||||
c1f3649a3a42f124b418a5a916dbad13d059b757 jdk-10+15
|
||||
2fe2a593e8ebf3a9e4dcd9ba3333a7b43126589d jdk-10+16
|
||||
9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178
|
||||
d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179
|
||||
73e2cb8700bfa51304bd4b02f224620859a3f600 jdk-10+17
|
||||
|
@ -14394,7 +14394,7 @@ instruct compL_reg_reg(rFlagsReg cr, iRegL op1, iRegL op2)
|
||||
ins_pipe(icmp_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compL_reg_immI0(rFlagsReg cr, iRegL op1, immI0 zero)
|
||||
instruct compL_reg_immL0(rFlagsReg cr, iRegL op1, immL0 zero)
|
||||
%{
|
||||
match(Set cr (CmpL op1 zero));
|
||||
|
||||
@ -14436,6 +14436,62 @@ instruct compL_reg_immL(rFlagsReg cr, iRegL op1, immL op2)
|
||||
ins_pipe(icmp_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_reg(rFlagsRegU cr, iRegL op1, iRegL op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
|
||||
effect(DEF cr, USE op1, USE op2);
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "cmp $op1, $op2" %}
|
||||
|
||||
ins_encode(aarch64_enc_cmp(op1, op2));
|
||||
|
||||
ins_pipe(icmp_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_immL0(rFlagsRegU cr, iRegL op1, immL0 zero)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 zero));
|
||||
|
||||
effect(DEF cr, USE op1);
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "tst $op1" %}
|
||||
|
||||
ins_encode(aarch64_enc_cmp_imm_addsub(op1, zero));
|
||||
|
||||
ins_pipe(icmp_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_immLAddSub(rFlagsRegU cr, iRegL op1, immLAddSub op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
|
||||
effect(DEF cr, USE op1);
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "cmp $op1, $op2" %}
|
||||
|
||||
ins_encode(aarch64_enc_cmp_imm_addsub(op1, op2));
|
||||
|
||||
ins_pipe(icmp_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_immL(rFlagsRegU cr, iRegL op1, immL op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
|
||||
effect(DEF cr, USE op1);
|
||||
|
||||
ins_cost(INSN_COST * 2);
|
||||
format %{ "cmp $op1, $op2" %}
|
||||
|
||||
ins_encode(aarch64_enc_cmp_imm(op1, op2));
|
||||
|
||||
ins_pipe(icmp_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compP_reg_reg(rFlagsRegU cr, iRegP op1, iRegP op2)
|
||||
%{
|
||||
match(Set cr (CmpP op1 op2));
|
||||
@ -14920,7 +14976,7 @@ instruct cmpUI_imm0_branch(cmpOpUEqNeLtGe cmp, iRegIorL2I op1, immI0 op2, label
|
||||
%}
|
||||
|
||||
instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{
|
||||
match(If cmp (CmpU op1 op2));
|
||||
match(If cmp (CmpUL op1 op2));
|
||||
effect(USE labl);
|
||||
|
||||
ins_cost(BRANCH_COST);
|
||||
|
@ -49,12 +49,11 @@ define_pd_global(intx, ConditionalMoveLimit, 3);
|
||||
define_pd_global(intx, FLOATPRESSURE, 64);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, MinJumpTableSize, 10);
|
||||
define_pd_global(intx, INTPRESSURE, 25);
|
||||
define_pd_global(intx, INTPRESSURE, 24);
|
||||
define_pd_global(intx, InteriorEntryAlignment, 16);
|
||||
define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
|
||||
define_pd_global(intx, LoopUnrollLimit, 60);
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
define_pd_global(intx, PostLoopMultiversioning, false);
|
||||
// InitialCodeCacheSize derived from specjbb2000 run.
|
||||
define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize
|
||||
define_pd_global(intx, CodeCacheExpansionSize, 64*K);
|
||||
|
@ -2695,6 +2695,30 @@ operand flagsRegL_LEGT() %{
|
||||
format %{ "apsr_L_LEGT" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand flagsRegUL_LTGE() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
|
||||
format %{ "apsr_UL_LTGE" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand flagsRegUL_EQNE() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
|
||||
format %{ "apsr_UL_EQNE" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand flagsRegUL_LEGT() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
|
||||
format %{ "apsr_UL_LEGT" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
#endif
|
||||
|
||||
// Condition Code Register, floating comparisons, unordered same as "less".
|
||||
@ -3249,6 +3273,39 @@ operand cmpOpL_commute() %{
|
||||
%}
|
||||
%}
|
||||
|
||||
operand cmpOpUL() %{
|
||||
match(Bool);
|
||||
|
||||
format %{ "UL" %}
|
||||
interface(COND_INTER) %{
|
||||
equal(0x0);
|
||||
not_equal(0x1);
|
||||
less(0x3);
|
||||
greater_equal(0x2);
|
||||
less_equal(0x9);
|
||||
greater(0x8);
|
||||
overflow(0x0); // unsupported/unimplemented
|
||||
no_overflow(0x0); // unsupported/unimplemented
|
||||
%}
|
||||
%}
|
||||
|
||||
operand cmpOpUL_commute() %{
|
||||
match(Bool);
|
||||
|
||||
format %{ "UL" %}
|
||||
interface(COND_INTER) %{
|
||||
equal(0x0);
|
||||
not_equal(0x1);
|
||||
less(0x8);
|
||||
greater_equal(0x9);
|
||||
less_equal(0x2);
|
||||
greater(0x3);
|
||||
overflow(0x0); // unsupported/unimplemented
|
||||
no_overflow(0x0); // unsupported/unimplemented
|
||||
%}
|
||||
%}
|
||||
|
||||
|
||||
//----------OPERAND CLASSES----------------------------------------------------
|
||||
// Operand Classes are groups of operands that are used to simplify
|
||||
// instruction definitions by not requiring the AD writer to specify separate
|
||||
@ -10467,6 +10524,17 @@ instruct compL_reg_reg(flagsReg xcc, iRegL op1, iRegL op2)
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_iReg(flagsRegU xcc, iRegL op1, iRegL op2) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
|
||||
size(4);
|
||||
format %{ "CMP $op1,$op2\t! unsigned long" %}
|
||||
ins_encode %{
|
||||
__ cmp($op1$$Register, $op2$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
#else
|
||||
instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
|
||||
match(Set xcc (CmpL op1 op2));
|
||||
@ -10481,6 +10549,20 @@ instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp)
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
effect(DEF xcc, USE op1, USE op2, TEMP tmp);
|
||||
|
||||
size(8);
|
||||
format %{ "SUBS $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
|
||||
"SBCS $tmp,$op1.hi,$op2.hi" %}
|
||||
ins_encode %{
|
||||
__ subs($tmp$$Register, $op1$$Register, $op2$$Register);
|
||||
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
#endif
|
||||
|
||||
#ifdef AARCH64
|
||||
@ -10496,6 +10578,19 @@ instruct compL_reg_con(flagsReg xcc, iRegL op1, aimmL con) %{
|
||||
|
||||
ins_pipe(ialu_cconly_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_con(flagsRegU xcc, iRegL op1, aimmL con) %{
|
||||
match(Set xcc (CmpUL op1 con));
|
||||
effect(DEF xcc, USE op1, USE con);
|
||||
|
||||
size(8);
|
||||
format %{ "CMP $op1,$con\t\t! unsigned long" %}
|
||||
ins_encode %{
|
||||
__ cmp($op1$$Register, $con$$constant);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_cconly_reg_imm);
|
||||
%}
|
||||
#else
|
||||
instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
|
||||
match(Set xcc (CmpL op1 op2));
|
||||
@ -10575,6 +10670,85 @@ instruct compL_reg_con_LEGT(flagsRegL_LEGT xcc, iRegL op1, immLlowRot con, iRegL
|
||||
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
effect(DEF xcc, USE op1, USE op2);
|
||||
|
||||
size(8);
|
||||
format %{ "TEQ $op1.hi,$op2.hi\t\t! unsigned long\n\t"
|
||||
"TEQ.eq $op1.lo,$op2.lo" %}
|
||||
ins_encode %{
|
||||
__ teq($op1$$Register->successor(), $op2$$Register->successor());
|
||||
__ teq($op1$$Register, $op2$$Register, eq);
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
effect(DEF xcc, USE op1, USE op2, TEMP tmp);
|
||||
|
||||
size(8);
|
||||
format %{ "SUBS $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
|
||||
"SBCS $tmp,$op2.hi,$op1.hi" %}
|
||||
ins_encode %{
|
||||
__ subs($tmp$$Register, $op2$$Register, $op1$$Register);
|
||||
__ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
|
||||
%}
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
|
||||
// (hi($con$$constant), lo($con$$constant)) becomes
|
||||
instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
|
||||
match(Set xcc (CmpUL op1 con));
|
||||
effect(DEF xcc, USE op1, USE con, TEMP tmp);
|
||||
|
||||
size(8);
|
||||
format %{ "SUBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
|
||||
"SBCS $tmp,$op1.hi,0" %}
|
||||
ins_encode %{
|
||||
__ subs($tmp$$Register, $op1$$Register, $con$$constant);
|
||||
__ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
|
||||
// (hi($con$$constant), lo($con$$constant)) becomes
|
||||
instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
|
||||
match(Set xcc (CmpUL op1 con));
|
||||
effect(DEF xcc, USE op1, USE con);
|
||||
|
||||
size(8);
|
||||
format %{ "TEQ $op1.hi,0\t\t! unsigned long\n\t"
|
||||
"TEQ.eq $op1.lo,$con" %}
|
||||
ins_encode %{
|
||||
__ teq($op1$$Register->successor(), 0);
|
||||
__ teq($op1$$Register, $con$$constant, eq);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
// TODO: try immLRot2 instead, (0, $con$$constant) becomes
|
||||
// (hi($con$$constant), lo($con$$constant)) becomes
|
||||
instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
|
||||
match(Set xcc (CmpUL op1 con));
|
||||
effect(DEF xcc, USE op1, USE con, TEMP tmp);
|
||||
|
||||
size(8);
|
||||
format %{ "RSBS $tmp,$op1.low,$con\t\t! unsigned long\n\t"
|
||||
"RSCS $tmp,$op1.hi,0" %}
|
||||
ins_encode %{
|
||||
__ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
|
||||
__ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
#endif
|
||||
|
||||
/* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
|
||||
@ -11126,6 +11300,48 @@ instruct branchConL_LEGT(cmpOpL_commute cmp, flagsRegL_LEGT xcc, label labl) %{
|
||||
%}
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
|
||||
instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
|
||||
match(If cmp xcc);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
|
||||
|
||||
size(4);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "B$cmp $xcc,$labl" %}
|
||||
ins_encode %{
|
||||
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
|
||||
%}
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
|
||||
instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
|
||||
match(If cmp xcc);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
|
||||
|
||||
size(4);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "B$cmp $xcc,$labl" %}
|
||||
ins_encode %{
|
||||
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
|
||||
%}
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
|
||||
instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
|
||||
match(If cmp xcc);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
|
||||
|
||||
size(4);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "B$cmp $xcc,$labl" %}
|
||||
ins_encode %{
|
||||
__ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
|
||||
%}
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
#endif
|
||||
|
||||
instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
|
||||
|
@ -70,7 +70,6 @@ define_pd_global(bool, UseTLAB, true);
|
||||
define_pd_global(bool, ResizeTLAB, true);
|
||||
define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
define_pd_global(intx, PostLoopMultiversioning, false);
|
||||
define_pd_global(intx, MinJumpTableSize, 16);
|
||||
|
||||
// Peephole and CISC spilling both break the graph, and so makes the
|
||||
|
@ -55,7 +55,6 @@ define_pd_global(bool, UseTLAB, true);
|
||||
define_pd_global(bool, ResizeTLAB, true);
|
||||
define_pd_global(intx, LoopUnrollLimit, 60);
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
define_pd_global(intx, PostLoopMultiversioning, false);
|
||||
|
||||
// Peephole and CISC spilling both break the graph, and so make the
|
||||
// scheduler sick.
|
||||
|
@ -11048,6 +11048,29 @@ instruct cmpL_reg_imm16(flagsReg crx, iRegLsrc src1, immL16 src2) %{
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
// Added CmpUL for LoopPredicate.
|
||||
instruct cmpUL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{
|
||||
match(Set crx (CmpUL src1 src2));
|
||||
format %{ "CMPLD $crx, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
|
||||
__ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct cmpUL_reg_imm16(flagsReg crx, iRegLsrc src1, uimmL16 src2) %{
|
||||
match(Set crx (CmpUL src1 src2));
|
||||
format %{ "CMPLDI $crx, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmpli);
|
||||
__ cmpldi($crx$$CondRegister, $src1$$Register, $src2$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_class_compare);
|
||||
%}
|
||||
|
||||
instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zero) %{
|
||||
match(Set cr0 (CmpL (AndL src1 src2) zero));
|
||||
// r0 is killed
|
||||
|
@ -56,7 +56,6 @@ define_pd_global(bool, UseTLAB, true);
|
||||
define_pd_global(bool, ResizeTLAB, true);
|
||||
define_pd_global(intx, LoopUnrollLimit, 60);
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
define_pd_global(intx, PostLoopMultiversioning, false);
|
||||
define_pd_global(intx, MinJumpTableSize, 18);
|
||||
|
||||
// Peephole and CISC spilling both break the graph, and so makes the
|
||||
|
@ -8475,6 +8475,24 @@ instruct compL_reg_memI(iRegL dst, memory src, flagsReg cr)%{
|
||||
%}
|
||||
|
||||
// LONG unsigned
|
||||
// Added CmpUL for LoopPredicate.
|
||||
instruct compUL_reg_reg(flagsReg cr, iRegL op1, iRegL op2) %{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
size(4);
|
||||
format %{ "CLGR $op1,$op2\t # long" %}
|
||||
opcode(CLGR_ZOPC);
|
||||
ins_encode(z_rreform(op1, op2));
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
instruct compUL_reg_imm32(flagsReg cr, iRegL op1, uimmL32 con) %{
|
||||
match(Set cr (CmpUL op1 con));
|
||||
size(6);
|
||||
format %{ "CLGFI $op1,$con" %}
|
||||
opcode(CLGFI_ZOPC);
|
||||
ins_encode(z_rilform_unsigned(op1, con));
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// PTR unsigned
|
||||
|
||||
|
@ -53,7 +53,6 @@ define_pd_global(bool, UseTLAB, true);
|
||||
define_pd_global(bool, ResizeTLAB, true);
|
||||
define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||
define_pd_global(intx, PostLoopMultiversioning, false);
|
||||
define_pd_global(intx, MinJumpTableSize, 5);
|
||||
|
||||
// Peephole and CISC spilling both break the graph, and so makes the
|
||||
|
@ -3403,6 +3403,16 @@ operand immU12() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13)
|
||||
operand immUL12() %{
|
||||
predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long()));
|
||||
match(ConL);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate non-negative
|
||||
operand immU31()
|
||||
%{
|
||||
@ -3936,6 +3946,15 @@ operand flagsRegL() %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Condition Code Register, unsigned long comparisons.
|
||||
operand flagsRegUL() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
|
||||
format %{ "xcc_UL" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Condition Code Register, floating comparisons, unordered same as "less".
|
||||
operand flagsRegF() %{
|
||||
constraint(ALLOC_IN_RC(float_flags));
|
||||
@ -8797,6 +8816,17 @@ instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
effect(DEF xcc, USE op1, USE op2);
|
||||
|
||||
size(4);
|
||||
format %{ "CMP $op1,$op2\t! unsigned long" %}
|
||||
opcode(Assembler::subcc_op3, Assembler::arith_op);
|
||||
ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0));
|
||||
ins_pipe(ialu_cconly_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{
|
||||
match(Set icc (CmpI op1 op2));
|
||||
effect( DEF icc, USE op1 );
|
||||
@ -8883,6 +8913,17 @@ instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{
|
||||
ins_pipe(ialu_cconly_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{
|
||||
match(Set xcc (CmpUL op1 op2));
|
||||
effect(DEF xcc, USE op1, USE op2);
|
||||
|
||||
size(4);
|
||||
format %{ "CMP $op1,$op2\t! unsigned long" %}
|
||||
opcode(Assembler::subcc_op3, Assembler::arith_op);
|
||||
ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0));
|
||||
ins_pipe(ialu_cconly_reg_imm);
|
||||
%}
|
||||
|
||||
// Compare Pointers
|
||||
instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
|
||||
match(Set pcc (CmpP op1 op2));
|
||||
@ -9256,6 +9297,44 @@ instruct cmpU_imm_branch(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU
|
||||
ins_pipe(cmp_br_reg_imm);
|
||||
%}
|
||||
|
||||
instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
|
||||
match(If cmp (CmpUL op1 op2));
|
||||
effect(USE labl, KILL xcc);
|
||||
|
||||
size(12);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "CMP $op1,$op2\t! unsigned long\n\t"
|
||||
"BP$cmp $labl" %}
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
Assembler::Predict predict_taken =
|
||||
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
|
||||
__ cmp($op1$$Register, $op2$$Register);
|
||||
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
|
||||
__ delayed()->nop();
|
||||
%}
|
||||
ins_pipe(cmp_br_reg_reg);
|
||||
%}
|
||||
|
||||
instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
|
||||
match(If cmp (CmpUL op1 op2));
|
||||
effect(USE labl, KILL xcc);
|
||||
|
||||
size(12);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "CMP $op1,$op2\t! unsigned long\n\t"
|
||||
"BP$cmp $labl" %}
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
Assembler::Predict predict_taken =
|
||||
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
|
||||
__ cmp($op1$$Register, $op2$$constant);
|
||||
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
|
||||
__ delayed()->nop();
|
||||
%}
|
||||
ins_pipe(cmp_br_reg_imm);
|
||||
%}
|
||||
|
||||
instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
|
||||
match(If cmp (CmpL op1 op2));
|
||||
effect(USE labl, KILL xcc);
|
||||
@ -9484,6 +9563,42 @@ instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, fla
|
||||
ins_pipe(cbcond_reg_imm);
|
||||
%}
|
||||
|
||||
instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
|
||||
match(If cmp (CmpUL op1 op2));
|
||||
predicate(UseCBCond);
|
||||
effect(USE labl, KILL xcc);
|
||||
|
||||
size(4);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %}
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
assert(__ use_cbcond(*L), "back to back cbcond");
|
||||
__ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L);
|
||||
%}
|
||||
ins_short_branch(1);
|
||||
ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
|
||||
ins_pipe(cbcond_reg_reg);
|
||||
%}
|
||||
|
||||
instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
|
||||
match(If cmp (CmpUL op1 op2));
|
||||
predicate(UseCBCond);
|
||||
effect(USE labl, KILL xcc);
|
||||
|
||||
size(4);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %}
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
assert(__ use_cbcond(*L), "back to back cbcond");
|
||||
__ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L);
|
||||
%}
|
||||
ins_short_branch(1);
|
||||
ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
|
||||
ins_pipe(cbcond_reg_imm);
|
||||
%}
|
||||
|
||||
instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
|
||||
match(If cmp (CmpL op1 op2));
|
||||
predicate(UseCBCond);
|
||||
@ -9722,6 +9837,25 @@ instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
|
||||
instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{
|
||||
match(If cmp xcc);
|
||||
effect(USE labl);
|
||||
|
||||
size(8);
|
||||
ins_cost(BRANCH_COST);
|
||||
format %{ "BP$cmp $xcc,$labl" %}
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
Assembler::Predict predict_taken =
|
||||
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
|
||||
|
||||
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
|
||||
__ delayed()->nop();
|
||||
%}
|
||||
ins_avoid_back_to_back(AVOID_BEFORE);
|
||||
ins_pipe(br_cc);
|
||||
%}
|
||||
|
||||
// Manifest a CmpL3 result in an integer register. Very painful.
|
||||
// This is the test to avoid.
|
||||
instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
|
||||
|
@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, MinJumpTableSize, 10);
|
||||
define_pd_global(intx, LoopPercentProfileLimit, 30);
|
||||
define_pd_global(intx, PostLoopMultiversioning, true);
|
||||
#ifdef AMD64
|
||||
define_pd_global(intx, INTPRESSURE, 13);
|
||||
define_pd_global(intx, FLOATPRESSURE, 14);
|
||||
|
@ -116,7 +116,7 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
|
||||
product(bool, UseStoreImmI16, true, \
|
||||
"Use store immediate 16-bits value instruction on x86") \
|
||||
\
|
||||
product(intx, UseAVX, 99, \
|
||||
product(intx, UseAVX, 2, \
|
||||
"Highest supported AVX instructions set on x86/x64") \
|
||||
range(0, 99) \
|
||||
\
|
||||
|
@ -4030,6 +4030,26 @@ operand flagsReg_long_LEGT() %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Condition Code Register used by unsigned long compare
|
||||
operand flagsReg_ulong_LTGE() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
format %{ "FLAGS_U_LTGE" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
operand flagsReg_ulong_EQNE() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
format %{ "FLAGS_U_EQNE" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
operand flagsReg_ulong_LEGT() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
format %{ "FLAGS_U_LEGT" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Float register operands
|
||||
operand regDPR() %{
|
||||
predicate( UseSSE < 2 );
|
||||
@ -4588,7 +4608,7 @@ operand cmpOp_fcmov() %{
|
||||
%}
|
||||
%}
|
||||
|
||||
// Comparision Code used in long compares
|
||||
// Comparison Code used in long compares
|
||||
operand cmpOp_commute() %{
|
||||
match(Bool);
|
||||
|
||||
@ -4605,6 +4625,23 @@ operand cmpOp_commute() %{
|
||||
%}
|
||||
%}
|
||||
|
||||
// Comparison Code used in unsigned long compares
|
||||
operand cmpOpU_commute() %{
|
||||
match(Bool);
|
||||
|
||||
format %{ "" %}
|
||||
interface(COND_INTER) %{
|
||||
equal(0x4, "e");
|
||||
not_equal(0x5, "ne");
|
||||
less(0x7, "nbe");
|
||||
greater_equal(0x6, "be");
|
||||
less_equal(0x3, "nb");
|
||||
greater(0x2, "b");
|
||||
overflow(0x0, "o");
|
||||
no_overflow(0x1, "no");
|
||||
%}
|
||||
%}
|
||||
|
||||
//----------OPERAND CLASSES----------------------------------------------------
|
||||
// Operand Classes are groups of operands that are used as to simplify
|
||||
// instruction definitions by not requiring the AD writer to specify separate
|
||||
@ -12639,6 +12676,44 @@ instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{
|
||||
%}
|
||||
%}
|
||||
|
||||
//======
|
||||
// Manifest a CmpUL result in the normal flags. Only good for LT or GE
|
||||
// compares. Can be used for LE or GT compares by reversing arguments.
|
||||
// NOT GOOD FOR EQ/NE tests.
|
||||
instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
|
||||
match(Set flags (CmpUL src zero));
|
||||
ins_cost(100);
|
||||
format %{ "TEST $src.hi,$src.hi" %}
|
||||
opcode(0x85);
|
||||
ins_encode(OpcP, RegReg_Hi2(src, src));
|
||||
ins_pipe(ialu_cr_reg_reg);
|
||||
%}
|
||||
|
||||
// Manifest a CmpUL result in the normal flags. Only good for LT or GE
|
||||
// compares. Can be used for LE or GT compares by reversing arguments.
|
||||
// NOT GOOD FOR EQ/NE tests.
|
||||
instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
|
||||
match(Set flags (CmpUL src1 src2));
|
||||
effect(TEMP tmp);
|
||||
ins_cost(300);
|
||||
format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
|
||||
"MOV $tmp,$src1.hi\n\t"
|
||||
"SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
|
||||
ins_encode(long_cmp_flags2(src1, src2, tmp));
|
||||
ins_pipe(ialu_cr_reg_reg);
|
||||
%}
|
||||
|
||||
// Unsigned long compares reg < zero/req OR reg >= zero/req.
|
||||
// Just a wrapper for a normal branch, plus the predicate test.
|
||||
instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
|
||||
match(If cmp flags);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
|
||||
expand %{
|
||||
jmpCon(cmp, flags, labl); // JLT or JGE...
|
||||
%}
|
||||
%}
|
||||
|
||||
// Compare 2 longs and CMOVE longs.
|
||||
instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
|
||||
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
|
||||
@ -12767,6 +12842,41 @@ instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{
|
||||
%}
|
||||
%}
|
||||
|
||||
//======
|
||||
// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
|
||||
instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
|
||||
match(Set flags (CmpUL src zero));
|
||||
effect(TEMP tmp);
|
||||
ins_cost(200);
|
||||
format %{ "MOV $tmp,$src.lo\n\t"
|
||||
"OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
|
||||
ins_encode(long_cmp_flags0(src, tmp));
|
||||
ins_pipe(ialu_reg_reg_long);
|
||||
%}
|
||||
|
||||
// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
|
||||
instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
|
||||
match(Set flags (CmpUL src1 src2));
|
||||
ins_cost(200+300);
|
||||
format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
|
||||
"JNE,s skip\n\t"
|
||||
"CMP $src1.hi,$src2.hi\n\t"
|
||||
"skip:\t" %}
|
||||
ins_encode(long_cmp_flags1(src1, src2));
|
||||
ins_pipe(ialu_cr_reg_reg);
|
||||
%}
|
||||
|
||||
// Unsigned long compare reg == zero/reg OR reg != zero/reg
|
||||
// Just a wrapper for a normal branch, plus the predicate test.
|
||||
instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
|
||||
match(If cmp flags);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
|
||||
expand %{
|
||||
jmpCon(cmp, flags, labl); // JEQ or JNE...
|
||||
%}
|
||||
%}
|
||||
|
||||
// Compare 2 longs and CMOVE longs.
|
||||
instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
|
||||
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
|
||||
@ -12900,6 +13010,46 @@ instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{
|
||||
%}
|
||||
%}
|
||||
|
||||
//======
|
||||
// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
|
||||
// Same as cmpUL_reg_flags_LEGT except must negate src
|
||||
instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
|
||||
match(Set flags (CmpUL src zero));
|
||||
effect(TEMP tmp);
|
||||
ins_cost(300);
|
||||
format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
|
||||
"CMP $tmp,$src.lo\n\t"
|
||||
"SBB $tmp,$src.hi\n\t" %}
|
||||
ins_encode(long_cmp_flags3(src, tmp));
|
||||
ins_pipe(ialu_reg_reg_long);
|
||||
%}
|
||||
|
||||
// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
|
||||
// Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands
|
||||
// requires a commuted test to get the same result.
|
||||
instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
|
||||
match(Set flags (CmpUL src1 src2));
|
||||
effect(TEMP tmp);
|
||||
ins_cost(300);
|
||||
format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
|
||||
"MOV $tmp,$src2.hi\n\t"
|
||||
"SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
|
||||
ins_encode(long_cmp_flags2( src2, src1, tmp));
|
||||
ins_pipe(ialu_cr_reg_reg);
|
||||
%}
|
||||
|
||||
// Unsigned long compares reg < zero/req OR reg >= zero/req.
|
||||
// Just a wrapper for a normal branch, plus the predicate test
|
||||
instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
|
||||
match(If cmp flags);
|
||||
effect(USE labl);
|
||||
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
|
||||
ins_cost(300);
|
||||
expand %{
|
||||
jmpCon(cmp, flags, labl); // JGT or JLE...
|
||||
%}
|
||||
%}
|
||||
|
||||
// Compare 2 longs and CMOVE longs.
|
||||
instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
|
||||
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
|
||||
|
@ -11518,6 +11518,48 @@ instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Unsigned long compare Instructions; really, same as signed long except they
|
||||
// produce an rFlagsRegU instead of rFlagsReg.
|
||||
instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
|
||||
format %{ "cmpq $op1, $op2\t# unsigned" %}
|
||||
opcode(0x3B); /* Opcode 3B /r */
|
||||
ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2));
|
||||
ins_pipe(ialu_cr_reg_reg);
|
||||
%}
|
||||
|
||||
instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 op2));
|
||||
|
||||
format %{ "cmpq $op1, $op2\t# unsigned" %}
|
||||
opcode(0x81, 0x07); /* Opcode 81 /7 */
|
||||
ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2));
|
||||
ins_pipe(ialu_cr_reg_imm);
|
||||
%}
|
||||
|
||||
instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
|
||||
%{
|
||||
match(Set cr (CmpUL op1 (LoadL op2)));
|
||||
|
||||
format %{ "cmpq $op1, $op2\t# unsigned" %}
|
||||
opcode(0x3B); /* Opcode 3B /r */
|
||||
ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2));
|
||||
ins_pipe(ialu_cr_reg_mem);
|
||||
%}
|
||||
|
||||
instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
|
||||
%{
|
||||
match(Set cr (CmpUL src zero));
|
||||
|
||||
format %{ "testq $src, $src\t# unsigned" %}
|
||||
opcode(0x85);
|
||||
ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src));
|
||||
ins_pipe(ialu_cr_reg_imm);
|
||||
%}
|
||||
|
||||
//----------Max and Min--------------------------------------------------------
|
||||
// Min Instructions
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
package org.graalvm.compiler.hotspot;
|
||||
|
||||
import java.util.Formatter;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API
|
||||
@ -37,10 +38,11 @@ import java.util.Formatter;
|
||||
class JVMCIVersionCheck {
|
||||
|
||||
private static final int JVMCI8_MIN_MAJOR_VERSION = 0;
|
||||
private static final int JVMCI8_MIN_MINOR_VERSION = 23;
|
||||
private static final int JVMCI8_MIN_MINOR_VERSION = 26;
|
||||
|
||||
// Will be updated once an ea build with the required JVMCI API is available.
|
||||
private static final int JVMCI9_MIN_EA_BUILD = 143;
|
||||
// MAX_VALUE indicates that no current EA version is compatible with Graal.
|
||||
// Note: Keep README.md in sync with the EA version support checked here.
|
||||
private static final int JVMCI9_MIN_EA_BUILD = 176;
|
||||
|
||||
private static void failVersionCheck(boolean exit, String reason, Object... args) {
|
||||
Formatter errorMessage = new Formatter().format(reason, args);
|
||||
@ -77,13 +79,27 @@ class JVMCIVersionCheck {
|
||||
start += "-jvmci-".length();
|
||||
int end = vmVersion.indexOf('.', start);
|
||||
if (end > 0) {
|
||||
int major = Integer.parseInt(vmVersion.substring(start, end));
|
||||
int major;
|
||||
try {
|
||||
major = Integer.parseInt(vmVersion.substring(start, end));
|
||||
} catch (NumberFormatException e) {
|
||||
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
start = end + 1;
|
||||
end = start;
|
||||
while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) {
|
||||
end++;
|
||||
}
|
||||
int minor = Integer.parseInt(vmVersion.substring(start, end));
|
||||
int minor;
|
||||
try {
|
||||
minor = Integer.parseInt(vmVersion.substring(start, end));
|
||||
} catch (NumberFormatException e) {
|
||||
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
if (major >= JVMCI8_MIN_MAJOR_VERSION && minor >= JVMCI8_MIN_MINOR_VERSION) {
|
||||
return;
|
||||
}
|
||||
@ -96,7 +112,7 @@ class JVMCIVersionCheck {
|
||||
"Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion);
|
||||
} else {
|
||||
if (vmVersion.contains("SNAPSHOT")) {
|
||||
// The snapshot of http://hg.openjdk.java.net/jdk9/hs tip is expected to work
|
||||
// The snapshot of http://hg.openjdk.java.net/jdk9/dev tip is expected to work
|
||||
return;
|
||||
}
|
||||
if (vmVersion.contains("internal")) {
|
||||
@ -104,23 +120,36 @@ class JVMCIVersionCheck {
|
||||
return;
|
||||
}
|
||||
// http://openjdk.java.net/jeps/223
|
||||
// Only support EA builds until GA is available
|
||||
if (vmVersion.startsWith("9-ea+")) {
|
||||
int start = "9-ea+".length();
|
||||
if (vmVersion.startsWith("9+")) {
|
||||
int start = "9+".length();
|
||||
int end = start;
|
||||
end = start;
|
||||
while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) {
|
||||
end++;
|
||||
}
|
||||
int build = Integer.parseInt(vmVersion.substring(start, end));
|
||||
int build;
|
||||
try {
|
||||
build = Integer.parseInt(vmVersion.substring(start, end));
|
||||
} catch (NumberFormatException e) {
|
||||
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion);
|
||||
return;
|
||||
}
|
||||
if (build >= JVMCI9_MIN_EA_BUILD) {
|
||||
return;
|
||||
}
|
||||
failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD);
|
||||
// Using Object.equals suppresses Eclipse's "Dead code" warning.
|
||||
// Unfortunately @SuppressWarnings("unused") can only be applied at method level.
|
||||
if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) {
|
||||
failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n");
|
||||
} else {
|
||||
failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// Graal will be compatible with all JDK versions as of 9 GA
|
||||
// until a JVMCI API change is made in a 9u or later release.
|
||||
}
|
||||
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
|
||||
"Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1166,6 +1166,7 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {
|
||||
|| strcmp(idealName,"CmpP") == 0
|
||||
|| strcmp(idealName,"CmpN") == 0
|
||||
|| strcmp(idealName,"CmpL") == 0
|
||||
|| strcmp(idealName,"CmpUL") == 0
|
||||
|| strcmp(idealName,"CmpD") == 0
|
||||
|| strcmp(idealName,"CmpF") == 0
|
||||
|| strcmp(idealName,"FastLock") == 0
|
||||
|
@ -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, \
|
||||
|
@ -81,6 +81,7 @@ macro(CmpL3)
|
||||
macro(CmpLTMask)
|
||||
macro(CmpP)
|
||||
macro(CmpU)
|
||||
macro(CmpUL)
|
||||
macro(CompareAndSwapB)
|
||||
macro(CompareAndSwapS)
|
||||
macro(CompareAndSwapI)
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "opto/connode.hpp"
|
||||
#include "opto/convertnode.hpp"
|
||||
#include "opto/loopnode.hpp"
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/mulnode.hpp"
|
||||
#include "opto/opaquenode.hpp"
|
||||
#include "opto/rootnode.hpp"
|
||||
@ -629,45 +630,138 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
|
||||
// max(scale*i + offset) = scale*init + offset
|
||||
BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
|
||||
int scale, Node* offset,
|
||||
Node* init, Node* limit, Node* stride,
|
||||
Node* range, bool upper) {
|
||||
Node* init, Node* limit, jint stride,
|
||||
Node* range, bool upper, bool &overflow) {
|
||||
jint con_limit = limit->is_Con() ? limit->get_int() : 0;
|
||||
jint con_init = init->is_Con() ? init->get_int() : 0;
|
||||
jint con_offset = offset->is_Con() ? offset->get_int() : 0;
|
||||
|
||||
stringStream* predString = NULL;
|
||||
if (TraceLoopPredicate) {
|
||||
predString = new stringStream();
|
||||
predString->print("rc_predicate ");
|
||||
}
|
||||
|
||||
Node* max_idx_expr = init;
|
||||
int stride_con = stride->get_int();
|
||||
if ((stride_con > 0) == (scale > 0) == upper) {
|
||||
// Limit is not exact.
|
||||
// Calculate exact limit here.
|
||||
// Note, counted loop's test is '<' or '>'.
|
||||
limit = exact_limit(loop);
|
||||
max_idx_expr = new SubINode(limit, stride);
|
||||
overflow = false;
|
||||
Node* max_idx_expr = NULL;
|
||||
const TypeInt* idx_type = TypeInt::INT;
|
||||
if ((stride > 0) == (scale > 0) == upper) {
|
||||
if (TraceLoopPredicate) {
|
||||
predString->print(limit->is_Con() ? "(%d " : "(limit ", con_limit);
|
||||
predString->print("- %d) ", stride);
|
||||
}
|
||||
// Check if (limit - stride) may overflow
|
||||
const TypeInt* limit_type = _igvn.type(limit)->isa_int();
|
||||
jint limit_lo = limit_type->_lo;
|
||||
jint limit_hi = limit_type->_hi;
|
||||
if ((stride > 0 && (java_subtract(limit_lo, stride) < limit_lo)) ||
|
||||
(stride < 0 && (java_subtract(limit_hi, stride) > limit_hi))) {
|
||||
// No overflow possible
|
||||
ConINode* con_stride = _igvn.intcon(stride);
|
||||
set_ctrl(con_stride, C->root());
|
||||
max_idx_expr = new SubINode(limit, con_stride);
|
||||
idx_type = TypeInt::make(limit_lo - stride, limit_hi - stride, limit_type->_widen);
|
||||
} else {
|
||||
// May overflow
|
||||
overflow = true;
|
||||
limit = new ConvI2LNode(limit);
|
||||
register_new_node(limit, ctrl);
|
||||
ConLNode* con_stride = _igvn.longcon(stride);
|
||||
set_ctrl(con_stride, C->root());
|
||||
max_idx_expr = new SubLNode(limit, con_stride);
|
||||
}
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
if (TraceLoopPredicate) predString->print("(limit - stride) ");
|
||||
} else {
|
||||
if (TraceLoopPredicate) predString->print("init ");
|
||||
if (TraceLoopPredicate) {
|
||||
predString->print(init->is_Con() ? "%d " : "init ", con_init);
|
||||
}
|
||||
idx_type = _igvn.type(init)->isa_int();
|
||||
max_idx_expr = init;
|
||||
}
|
||||
|
||||
if (scale != 1) {
|
||||
ConNode* con_scale = _igvn.intcon(scale);
|
||||
set_ctrl(con_scale, C->root());
|
||||
max_idx_expr = new MulINode(max_idx_expr, con_scale);
|
||||
if (TraceLoopPredicate) {
|
||||
predString->print("* %d ", scale);
|
||||
}
|
||||
// Check if (scale * max_idx_expr) may overflow
|
||||
const TypeInt* scale_type = TypeInt::make(scale);
|
||||
MulINode* mul = new MulINode(max_idx_expr, con_scale);
|
||||
idx_type = (TypeInt*)mul->mul_ring(idx_type, scale_type);
|
||||
if (overflow || TypeInt::INT->higher_equal(idx_type)) {
|
||||
// May overflow
|
||||
mul->destruct();
|
||||
if (!overflow) {
|
||||
max_idx_expr = new ConvI2LNode(max_idx_expr);
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
}
|
||||
overflow = true;
|
||||
con_scale = _igvn.longcon(scale);
|
||||
set_ctrl(con_scale, C->root());
|
||||
max_idx_expr = new MulLNode(max_idx_expr, con_scale);
|
||||
} else {
|
||||
// No overflow possible
|
||||
max_idx_expr = mul;
|
||||
}
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
if (TraceLoopPredicate) predString->print("* %d ", scale);
|
||||
}
|
||||
|
||||
if (offset && (!offset->is_Con() || offset->get_int() != 0)){
|
||||
max_idx_expr = new AddINode(max_idx_expr, offset);
|
||||
if (offset && (!offset->is_Con() || con_offset != 0)){
|
||||
if (TraceLoopPredicate) {
|
||||
predString->print(offset->is_Con() ? "+ %d " : "+ offset", con_offset);
|
||||
}
|
||||
// Check if (max_idx_expr + offset) may overflow
|
||||
const TypeInt* offset_type = _igvn.type(offset)->isa_int();
|
||||
jint lo = java_add(idx_type->_lo, offset_type->_lo);
|
||||
jint hi = java_add(idx_type->_hi, offset_type->_hi);
|
||||
if (overflow || (lo > hi) ||
|
||||
((idx_type->_lo & offset_type->_lo) < 0 && lo >= 0) ||
|
||||
((~(idx_type->_hi | offset_type->_hi)) < 0 && hi < 0)) {
|
||||
// May overflow
|
||||
if (!overflow) {
|
||||
max_idx_expr = new ConvI2LNode(max_idx_expr);
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
}
|
||||
overflow = true;
|
||||
offset = new ConvI2LNode(offset);
|
||||
register_new_node(offset, ctrl);
|
||||
max_idx_expr = new AddLNode(max_idx_expr, offset);
|
||||
} else {
|
||||
// No overflow possible
|
||||
max_idx_expr = new AddINode(max_idx_expr, offset);
|
||||
}
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
if (TraceLoopPredicate)
|
||||
if (offset->is_Con()) predString->print("+ %d ", offset->get_int());
|
||||
else predString->print("+ offset ");
|
||||
}
|
||||
|
||||
CmpUNode* cmp = new CmpUNode(max_idx_expr, range);
|
||||
CmpNode* cmp = NULL;
|
||||
if (overflow) {
|
||||
// Integer expressions may overflow, do long comparison
|
||||
range = new ConvI2LNode(range);
|
||||
register_new_node(range, ctrl);
|
||||
if (!Matcher::has_match_rule(Op_CmpUL)) {
|
||||
// We don't support unsigned long comparisons. Set 'max_idx_expr'
|
||||
// to max_julong if < 0 to make the signed comparison fail.
|
||||
ConINode* sign_pos = _igvn.intcon(BitsPerLong - 1);
|
||||
set_ctrl(sign_pos, C->root());
|
||||
Node* sign_bit_mask = new RShiftLNode(max_idx_expr, sign_pos);
|
||||
register_new_node(sign_bit_mask, ctrl);
|
||||
// OR with sign bit to set all bits to 1 if negative (otherwise no change)
|
||||
max_idx_expr = new OrLNode(max_idx_expr, sign_bit_mask);
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
// AND with 0x7ff... to unset the sign bit
|
||||
ConLNode* remove_sign_mask = _igvn.longcon(max_jlong);
|
||||
set_ctrl(remove_sign_mask, C->root());
|
||||
max_idx_expr = new AndLNode(max_idx_expr, remove_sign_mask);
|
||||
register_new_node(max_idx_expr, ctrl);
|
||||
|
||||
cmp = new CmpLNode(max_idx_expr, range);
|
||||
} else {
|
||||
cmp = new CmpULNode(max_idx_expr, range);
|
||||
}
|
||||
} else {
|
||||
cmp = new CmpUNode(max_idx_expr, range);
|
||||
}
|
||||
register_new_node(cmp, ctrl);
|
||||
BoolNode* bol = new BoolNode(cmp, BoolTest::lt);
|
||||
register_new_node(bol, ctrl);
|
||||
@ -814,28 +908,30 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
||||
assert(ok, "must be index expression");
|
||||
|
||||
Node* init = cl->init_trip();
|
||||
Node* limit = cl->limit();
|
||||
Node* stride = cl->stride();
|
||||
// Limit is not exact.
|
||||
// Calculate exact limit here.
|
||||
// Note, counted loop's test is '<' or '>'.
|
||||
Node* limit = exact_limit(loop);
|
||||
int stride = cl->stride()->get_int();
|
||||
|
||||
// Build if's for the upper and lower bound tests. The
|
||||
// lower_bound test will dominate the upper bound test and all
|
||||
// cloned or created nodes will use the lower bound test as
|
||||
// their declared control.
|
||||
ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode());
|
||||
ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode());
|
||||
assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
|
||||
Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
|
||||
|
||||
// Perform cloning to keep Invariance state correct since the
|
||||
// late schedule will place invariant things in the loop.
|
||||
Node *ctrl = predicate_proj->in(0)->as_If()->in(0);
|
||||
rng = invar.clone(rng, ctrl);
|
||||
if (offset && offset != zero) {
|
||||
assert(invar.is_invariant(offset), "offset must be loop invariant");
|
||||
offset = invar.clone(offset, ctrl);
|
||||
}
|
||||
// If predicate expressions may overflow in the integer range, longs are used.
|
||||
bool overflow = false;
|
||||
|
||||
// Test the lower bound
|
||||
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false);
|
||||
BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow);
|
||||
// Negate test if necessary
|
||||
bool negated = false;
|
||||
if (proj->_con != predicate_proj->_con) {
|
||||
@ -843,19 +939,22 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
||||
register_new_node(lower_bound_bol, ctrl);
|
||||
negated = true;
|
||||
}
|
||||
ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode());
|
||||
IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
|
||||
_igvn.hash_delete(lower_bound_iff);
|
||||
lower_bound_iff->set_req(1, lower_bound_bol);
|
||||
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
|
||||
|
||||
// Test the upper bound
|
||||
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true);
|
||||
BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
|
||||
negated = false;
|
||||
if (proj->_con != predicate_proj->_con) {
|
||||
upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate());
|
||||
register_new_node(upper_bound_bol, ctrl);
|
||||
negated = true;
|
||||
}
|
||||
ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode());
|
||||
assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
|
||||
IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
|
||||
_igvn.hash_delete(upper_bound_iff);
|
||||
upper_bound_iff->set_req(1, upper_bound_bol);
|
||||
|
@ -983,8 +983,8 @@ public:
|
||||
// Construct a range check for a predicate if
|
||||
BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl,
|
||||
int scale, Node* offset,
|
||||
Node* init, Node* limit, Node* stride,
|
||||
Node* range, bool upper);
|
||||
Node* init, Node* limit, jint stride,
|
||||
Node* range, bool upper, bool &overflow);
|
||||
|
||||
// Implementation of the loop predication to promote checks outside the loop
|
||||
bool loop_predication_impl(IdealLoopTree *loop);
|
||||
|
@ -1982,6 +1982,7 @@ void Scheduling::AddNodeToAvailableList(Node *n) {
|
||||
if( last->is_MachIf() && last->in(1) == n &&
|
||||
( op == Op_CmpI ||
|
||||
op == Op_CmpU ||
|
||||
op == Op_CmpUL ||
|
||||
op == Op_CmpP ||
|
||||
op == Op_CmpF ||
|
||||
op == Op_CmpD ||
|
||||
|
@ -738,6 +738,60 @@ const Type *CmpLNode::sub( const Type *t1, const Type *t2 ) const {
|
||||
return TypeInt::CC; // else use worst case results
|
||||
}
|
||||
|
||||
|
||||
// Simplify a CmpUL (compare 2 unsigned longs) node, based on local information.
|
||||
// If both inputs are constants, compare them.
|
||||
const Type* CmpULNode::sub(const Type* t1, const Type* t2) const {
|
||||
assert(!t1->isa_ptr(), "obsolete usage of CmpUL");
|
||||
|
||||
// comparing two unsigned longs
|
||||
const TypeLong* r0 = t1->is_long(); // Handy access
|
||||
const TypeLong* r1 = t2->is_long();
|
||||
|
||||
// Current installed version
|
||||
// Compare ranges for non-overlap
|
||||
julong lo0 = r0->_lo;
|
||||
julong hi0 = r0->_hi;
|
||||
julong lo1 = r1->_lo;
|
||||
julong hi1 = r1->_hi;
|
||||
|
||||
// If either one has both negative and positive values,
|
||||
// it therefore contains both 0 and -1, and since [0..-1] is the
|
||||
// full unsigned range, the type must act as an unsigned bottom.
|
||||
bool bot0 = ((jlong)(lo0 ^ hi0) < 0);
|
||||
bool bot1 = ((jlong)(lo1 ^ hi1) < 0);
|
||||
|
||||
if (bot0 || bot1) {
|
||||
// All unsigned values are LE -1 and GE 0.
|
||||
if (lo0 == 0 && hi0 == 0) {
|
||||
return TypeInt::CC_LE; // 0 <= bot
|
||||
} else if ((jlong)lo0 == -1 && (jlong)hi0 == -1) {
|
||||
return TypeInt::CC_GE; // -1 >= bot
|
||||
} else if (lo1 == 0 && hi1 == 0) {
|
||||
return TypeInt::CC_GE; // bot >= 0
|
||||
} else if ((jlong)lo1 == -1 && (jlong)hi1 == -1) {
|
||||
return TypeInt::CC_LE; // bot <= -1
|
||||
}
|
||||
} else {
|
||||
// We can use ranges of the form [lo..hi] if signs are the same.
|
||||
assert(lo0 <= hi0 && lo1 <= hi1, "unsigned ranges are valid");
|
||||
// results are reversed, '-' > '+' for unsigned compare
|
||||
if (hi0 < lo1) {
|
||||
return TypeInt::CC_LT; // smaller
|
||||
} else if (lo0 > hi1) {
|
||||
return TypeInt::CC_GT; // greater
|
||||
} else if (hi0 == lo1 && lo0 == hi1) {
|
||||
return TypeInt::CC_EQ; // Equal results
|
||||
} else if (lo0 >= hi1) {
|
||||
return TypeInt::CC_GE;
|
||||
} else if (hi0 <= lo1) {
|
||||
return TypeInt::CC_LE;
|
||||
}
|
||||
}
|
||||
|
||||
return TypeInt::CC; // else use worst case results
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------sub--------------------------------------------
|
||||
// Simplify an CmpP (compare 2 pointers) node, based on local information.
|
||||
|
@ -198,6 +198,15 @@ public:
|
||||
virtual const Type *sub( const Type *, const Type * ) const;
|
||||
};
|
||||
|
||||
//------------------------------CmpULNode---------------------------------------
|
||||
// Compare 2 unsigned long values, returning condition codes (-1, 0 or 1).
|
||||
class CmpULNode : public CmpNode {
|
||||
public:
|
||||
CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { }
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* sub(const Type*, const Type*) const;
|
||||
};
|
||||
|
||||
//------------------------------CmpL3Node--------------------------------------
|
||||
// Compare 2 long values, returning integer value (-1, 0 or 1).
|
||||
class CmpL3Node : public CmpLNode {
|
||||
|
@ -2013,6 +2013,7 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||
declare_c2_type(CmpPNode, CmpNode) \
|
||||
declare_c2_type(CmpNNode, CmpNode) \
|
||||
declare_c2_type(CmpLNode, CmpNode) \
|
||||
declare_c2_type(CmpULNode, CmpNode) \
|
||||
declare_c2_type(CmpL3Node, CmpLNode) \
|
||||
declare_c2_type(CmpFNode, CmpNode) \
|
||||
declare_c2_type(CmpF3Node, CmpFNode) \
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -437,3 +437,6 @@ ff293e39e83366c40a5687dacd1ccb2305ed2c1e jdk-10+12
|
||||
332ad9f92632f56f337b8c40edef9a95a42b26bc jdk-9+177
|
||||
02a876781a3a6193140591d92db7b95ca743eac2 jdk-10+15
|
||||
d109d55cf642bf2b438624e81f94c18c168f9178 jdk-10+16
|
||||
0983b2dbe17ba4fed3af34e0512ca77a9845fe8a jdk-9+178
|
||||
87243a3131f79e8b3903eaca6b629abc48f08ace jdk-9+179
|
||||
97d6f14334cfd766f57c296a5a707c8a709aeff0 jdk-10+17
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 @@ public class DTMException extends RuntimeException {
|
||||
* @param e The exception to be wrapped.
|
||||
*/
|
||||
public DTMException(Throwable e) {
|
||||
|
||||
super(e.getMessage());
|
||||
|
||||
this.containedException = e;
|
||||
this.locator = null;
|
||||
super(e);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,162 +56,6 @@ public class DTMException extends RuntimeException {
|
||||
* @param e Any exception
|
||||
*/
|
||||
public DTMException(String message, Throwable e) {
|
||||
|
||||
super(((message == null) || (message.length() == 0))
|
||||
? e.getMessage()
|
||||
: message);
|
||||
|
||||
this.containedException = e;
|
||||
this.locator = null;
|
||||
super(message, e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DTMException from a message and a Locator.
|
||||
*
|
||||
* <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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -21,12 +20,8 @@
|
||||
|
||||
package com.sun.org.apache.xml.internal.dtm;
|
||||
|
||||
import com.sun.org.apache.xml.internal.res.XMLErrorResources;
|
||||
import com.sun.org.apache.xml.internal.res.XMLMessages;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
|
||||
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
|
||||
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
|
||||
|
||||
/**
|
||||
* A DTMManager instance can be used to create DTM and
|
||||
@ -99,11 +94,11 @@ public abstract class DTMManager
|
||||
*
|
||||
* @return new DTMManager instance, never null.
|
||||
*
|
||||
* @throws DTMConfigurationException
|
||||
* @throws DTMException
|
||||
* if the implementation is not available or cannot be instantiated.
|
||||
*/
|
||||
public static DTMManager newInstance(XMLStringFactory xsf)
|
||||
throws DTMConfigurationException
|
||||
throws DTMException
|
||||
{
|
||||
final DTMManager factoryImpl = new com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault();
|
||||
factoryImpl.setXMLStringFactory(xsf);
|
||||
@ -315,20 +310,6 @@ public abstract class DTMManager
|
||||
|
||||
// -------------------- private methods --------------------
|
||||
|
||||
/**
|
||||
* Temp debug code - this will be removed after we test everything
|
||||
*/
|
||||
private static boolean debug;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
debug = SecuritySupport.getSystemProperty("dtm.debug") != null;
|
||||
}
|
||||
catch (SecurityException ex){}
|
||||
}
|
||||
|
||||
/** This value, set at compile time, controls how many bits of the
|
||||
* DTM node identifier numbers are used to identify a node within a
|
||||
* document, and thus sets the maximum number of nodes per
|
||||
@ -394,47 +375,4 @@ public abstract class DTMManager
|
||||
{
|
||||
return IDENT_NODE_DEFAULT;
|
||||
}
|
||||
|
||||
//
|
||||
// Classes
|
||||
//
|
||||
|
||||
/**
|
||||
* A configuration error.
|
||||
* Originally in ObjectFactory. This is the only portion used in this package
|
||||
*/
|
||||
static class ConfigurationError
|
||||
extends Error {
|
||||
static final long serialVersionUID = 5122054096615067992L;
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
/** Exception. */
|
||||
private Exception exception;
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
|
||||
/**
|
||||
* Construct a new instance with the specified detail string and
|
||||
* exception.
|
||||
*/
|
||||
ConfigurationError(String msg, Exception x) {
|
||||
super(msg);
|
||||
this.exception = x;
|
||||
} // <init>(String,Exception)
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
|
||||
/** Returns the exception associated to this error. */
|
||||
Exception getException() {
|
||||
return exception;
|
||||
} // getException():Exception
|
||||
|
||||
} // class ConfigurationError
|
||||
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import jdk.xml.internal.SecuritySupport;
|
||||
* 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 @@ import jdk.xml.internal.SecuritySupport;
|
||||
* <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 @@ import jdk.xml.internal.SecuritySupport;
|
||||
* </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 @@ import jdk.xml.internal.SecuritySupport;
|
||||
* </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 @@ import jdk.xml.internal.SecuritySupport;
|
||||
* </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>
|
||||
|
@ -34,7 +34,7 @@ import com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl;
|
||||
|
||||
/**
|
||||
* Factory that creates new {@code javax.xml.datatype} {@code Object}s that map XML to/from Java {@code Object}s.
|
||||
* <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>
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -32,6 +32,8 @@ package javax.xml.transform;
|
||||
*/
|
||||
public class TransformerConfigurationException extends TransformerException {
|
||||
|
||||
private static final long serialVersionUID = 1285547467942875745L;
|
||||
|
||||
/**
|
||||
* Create a new <code>TransformerConfigurationException</code> with no
|
||||
* detail message.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,36 +27,47 @@ package javax.xml.transform;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSigner;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PermissionCollection;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class specifies an exceptional condition that occured
|
||||
* This class specifies an exceptional condition that occurred
|
||||
* during the transformation process.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public class TransformerException extends Exception {
|
||||
|
||||
/** Field locator specifies where the error occured */
|
||||
private static final long serialVersionUID = 975798773772956428L;
|
||||
|
||||
/** Field locator specifies where the error occurred */
|
||||
SourceLocator locator;
|
||||
|
||||
/**
|
||||
* Method getLocator retrieves an instance of a SourceLocator
|
||||
* object that specifies where an error occured.
|
||||
* object that specifies where an error occurred.
|
||||
*
|
||||
* @return A SourceLocator object, or null if none was specified.
|
||||
*/
|
||||
public SourceLocator getLocator() {
|
||||
return locator;
|
||||
return this.locator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setLocator sets an instance of a SourceLocator
|
||||
* object that specifies where an error occured.
|
||||
* object that specifies where an error occurred.
|
||||
*
|
||||
* @param location A SourceLocator object, or null to clear the location.
|
||||
*/
|
||||
public void setLocator(SourceLocator location) {
|
||||
locator = location;
|
||||
this.locator = location;
|
||||
}
|
||||
|
||||
/** Field containedException specifies a wrapped exception. May be null. */
|
||||
@ -76,7 +87,9 @@ public class TransformerException extends Exception {
|
||||
* Returns the cause of this throwable or <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 @@ public class TransformerException extends Exception {
|
||||
* {@link #TransformerException(String,Throwable)}, or this method has already
|
||||
* been called on this throwable.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Throwable initCause(Throwable cause) {
|
||||
|
||||
// TransformerException doesn't set its cause (probably
|
||||
@ -136,11 +150,7 @@ public class TransformerException extends Exception {
|
||||
* @param message The error or warning message.
|
||||
*/
|
||||
public TransformerException(String message) {
|
||||
|
||||
super(message);
|
||||
|
||||
this.containedException = null;
|
||||
this.locator = null;
|
||||
this(message, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,11 +159,7 @@ public class TransformerException extends Exception {
|
||||
* @param e The exception to be wrapped.
|
||||
*/
|
||||
public TransformerException(Throwable e) {
|
||||
|
||||
super(e.toString());
|
||||
|
||||
this.containedException = e;
|
||||
this.locator = null;
|
||||
this(null, null, e);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,13 +173,7 @@ public class TransformerException extends Exception {
|
||||
* @param e Any exception
|
||||
*/
|
||||
public TransformerException(String message, Throwable e) {
|
||||
|
||||
super(((message == null) || (message.length() == 0))
|
||||
? e.toString()
|
||||
: message);
|
||||
|
||||
this.containedException = e;
|
||||
this.locator = null;
|
||||
this(message, null, e);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,11 +187,7 @@ public class TransformerException extends Exception {
|
||||
* @param locator The locator object for the error or warning.
|
||||
*/
|
||||
public TransformerException(String message, SourceLocator locator) {
|
||||
|
||||
super(message);
|
||||
|
||||
this.containedException = null;
|
||||
this.locator = locator;
|
||||
this(message, locator, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,8 +200,9 @@ public class TransformerException extends Exception {
|
||||
*/
|
||||
public TransformerException(String message, SourceLocator locator,
|
||||
Throwable e) {
|
||||
|
||||
super(message);
|
||||
super(((message == null) || (message.length() == 0))
|
||||
? ((e == null) ? "" : e.toString())
|
||||
: message);
|
||||
|
||||
this.containedException = e;
|
||||
this.locator = locator;
|
||||
@ -219,34 +216,9 @@ public class TransformerException extends Exception {
|
||||
* location information appended.
|
||||
*/
|
||||
public String getMessageAndLocation() {
|
||||
|
||||
StringBuffer sbuffer = new StringBuffer();
|
||||
String message = super.getMessage();
|
||||
|
||||
if (null != message) {
|
||||
sbuffer.append(message);
|
||||
}
|
||||
|
||||
if (null != locator) {
|
||||
String systemID = locator.getSystemId();
|
||||
int line = locator.getLineNumber();
|
||||
int column = locator.getColumnNumber();
|
||||
|
||||
if (null != systemID) {
|
||||
sbuffer.append("; SystemID: ");
|
||||
sbuffer.append(systemID);
|
||||
}
|
||||
|
||||
if (0 != line) {
|
||||
sbuffer.append("; Line#: ");
|
||||
sbuffer.append(line);
|
||||
}
|
||||
|
||||
if (0 != column) {
|
||||
sbuffer.append("; Column#: ");
|
||||
sbuffer.append(column);
|
||||
}
|
||||
}
|
||||
StringBuilder sbuffer = new StringBuilder();
|
||||
sbuffer.append(Objects.toString(super.getMessage(), ""));
|
||||
sbuffer.append(Objects.toString(getLocationAsString(), ""));
|
||||
|
||||
return sbuffer.toString();
|
||||
}
|
||||
@ -258,9 +230,29 @@ public class TransformerException extends Exception {
|
||||
* if there is no location information.
|
||||
*/
|
||||
public String getLocationAsString() {
|
||||
if (locator == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null != locator) {
|
||||
StringBuffer sbuffer = new StringBuffer();
|
||||
if (System.getSecurityManager() == null) {
|
||||
return getLocationString();
|
||||
} else {
|
||||
return AccessController.doPrivileged((PrivilegedAction<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 @@ public class TransformerException extends Exception {
|
||||
}
|
||||
|
||||
return sbuffer.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,6 +280,7 @@ public class TransformerException extends Exception {
|
||||
* originated. This will trace all nested exception
|
||||
* objects, as well as this object.
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace() {
|
||||
printStackTrace(new java.io.PrintWriter(System.err, true));
|
||||
}
|
||||
@ -301,6 +291,7 @@ public class TransformerException extends Exception {
|
||||
* objects, as well as this object.
|
||||
* @param s The stream where the dump will be sent to.
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace(java.io.PrintStream s) {
|
||||
printStackTrace(new java.io.PrintWriter(s));
|
||||
}
|
||||
@ -311,6 +302,7 @@ public class TransformerException extends Exception {
|
||||
* objects, as well as this object.
|
||||
* @param s The writer where the dump will be sent to.
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace(java.io.PrintWriter s) {
|
||||
|
||||
if (s == null) {
|
||||
@ -358,11 +350,8 @@ public class TransformerException extends Exception {
|
||||
} else {
|
||||
exception = null;
|
||||
}
|
||||
} catch (InvocationTargetException ite) {
|
||||
exception = null;
|
||||
} catch (IllegalAccessException iae) {
|
||||
exception = null;
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
} catch (InvocationTargetException | IllegalAccessException
|
||||
| NoSuchMethodException e) {
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
@ -371,4 +360,14 @@ public class TransformerException extends Exception {
|
||||
s.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ProtectionDomain that has no permission.
|
||||
* @return a ProtectionDomain
|
||||
*/
|
||||
private ProtectionDomain getNonPrivDomain() {
|
||||
CodeSource nullSource = new CodeSource(null, (CodeSigner[]) null);
|
||||
PermissionCollection noPermission = new Permissions();
|
||||
return new ProtectionDomain(nullSource, noPermission);
|
||||
}
|
||||
}
|
||||
|
@ -440,3 +440,6 @@ ea819b6009d33a72e6672bab6c101d51db0cfb4c jdk-9+176
|
||||
b44a721aee3d3b2537754e559fe9ecccadea548b jdk-9+177
|
||||
6d17fd0a5133a0dd916c77a9a24ae7f0ca402876 jdk-10+15
|
||||
bc8289ce1ed3ed5fff62152ed46da3be0b60b7c3 jdk-10+16
|
||||
d0190aaf1816081d9b2e0577b65b793804896d1e jdk-9+178
|
||||
56ac1831ac5924b5092a53a85d6fc68749501fb8 jdk-9+179
|
||||
4c07d366c2e177edba7aa54c4b015e4dbf12bc83 jdk-10+17
|
||||
|
@ -84,6 +84,14 @@ public class XmlUtil {
|
||||
private final static String LEXICAL_HANDLER_PROPERTY =
|
||||
"http://xml.org/sax/properties/lexical-handler";
|
||||
|
||||
private static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
|
||||
|
||||
private static final String EXTERNAL_GE = "http://xml.org/sax/features/external-general-entities";
|
||||
|
||||
private static final String EXTERNAL_PE = "http://xml.org/sax/features/external-parameter-entities";
|
||||
|
||||
private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
|
||||
|
||||
private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity";
|
||||
@ -327,10 +335,24 @@ public class XmlUtil {
|
||||
|
||||
public static DocumentBuilderFactory newDocumentBuilderFactory(boolean disableSecurity) {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING;
|
||||
try {
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
|
||||
boolean securityOn = !xmlSecurityDisabled(disableSecurity);
|
||||
factory.setFeature(featureToSet, securityOn);
|
||||
factory.setNamespaceAware(true);
|
||||
if (securityOn) {
|
||||
factory.setExpandEntityReferences(false);
|
||||
featureToSet = DISALLOW_DOCTYPE_DECL;
|
||||
factory.setFeature(featureToSet, true);
|
||||
featureToSet = EXTERNAL_GE;
|
||||
factory.setFeature(featureToSet, false);
|
||||
featureToSet = EXTERNAL_PE;
|
||||
factory.setFeature(featureToSet, false);
|
||||
featureToSet = LOAD_EXTERNAL_DTD;
|
||||
factory.setFeature(featureToSet, false);
|
||||
}
|
||||
} catch (ParserConfigurationException e) {
|
||||
LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[] { factory.getClass().getName() } );
|
||||
LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[] {factory.getClass().getName()} );
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
@ -347,10 +369,23 @@ public class XmlUtil {
|
||||
|
||||
public static SAXParserFactory newSAXParserFactory(boolean disableSecurity) {
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
String featureToSet = XMLConstants.FEATURE_SECURE_PROCESSING;
|
||||
try {
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !xmlSecurityDisabled(disableSecurity));
|
||||
boolean securityOn = !xmlSecurityDisabled(disableSecurity);
|
||||
factory.setFeature(featureToSet, securityOn);
|
||||
factory.setNamespaceAware(true);
|
||||
if (securityOn) {
|
||||
featureToSet = DISALLOW_DOCTYPE_DECL;
|
||||
factory.setFeature(featureToSet, true);
|
||||
featureToSet = EXTERNAL_GE;
|
||||
factory.setFeature(featureToSet, false);
|
||||
featureToSet = EXTERNAL_PE;
|
||||
factory.setFeature(featureToSet, false);
|
||||
featureToSet = LOAD_EXTERNAL_DTD;
|
||||
factory.setFeature(featureToSet, false);
|
||||
}
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support secure xml processing!", new Object[]{factory.getClass().getName()});
|
||||
LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[]{factory.getClass().getName()});
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
@ -112,29 +112,13 @@ public class DOMForest {
|
||||
this.entityResolver = entityResolver;
|
||||
this.errorReceiver = errReceiver;
|
||||
this.logic = logic;
|
||||
// secure xml processing can be switched off if input requires it
|
||||
boolean disableXmlSecurity = options == null ? false : options.disableXmlSecurity;
|
||||
|
||||
DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(disableXmlSecurity);
|
||||
this.parserFactory = XmlUtil.newSAXParserFactory(disableXmlSecurity);
|
||||
try {
|
||||
// secure xml processing can be switched off if input requires it
|
||||
boolean secureProcessingEnabled = options == null || !options.disableXmlSecurity;
|
||||
DocumentBuilderFactory dbf = XmlUtil.newDocumentBuilderFactory(!secureProcessingEnabled);
|
||||
dbf.setNamespaceAware(true);
|
||||
this.documentBuilder = dbf.newDocumentBuilder();
|
||||
|
||||
this.parserFactory = XmlUtil.newSAXParserFactory(secureProcessingEnabled);
|
||||
this.parserFactory.setNamespaceAware(true);
|
||||
|
||||
if(secureProcessingEnabled){
|
||||
dbf.setExpandEntityReferences(false);
|
||||
try {
|
||||
parserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
parserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
parserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
} catch (SAXNotRecognizedException e){
|
||||
throw new ParserConfigurationException(e.getMessage());
|
||||
} catch (SAXNotSupportedException e) {
|
||||
throw new ParserConfigurationException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
@ -439,3 +439,5 @@ e069834e2c518a7bc2ffadc8c7e3cd7ec69fa8a0 jdk-10+15
|
||||
3281b964ab104002623d744e8b77a12269b70acd jdk-10+16
|
||||
443025bee731eb2225371b92c1c74b519b7baf33 jdk-9+178
|
||||
06df1ce4b9b887d05ce6a13f4def3547e434dd1a jdk-9+179
|
||||
d93f2fd542b7d7855c2cd49ae15ebcc3d441a83b jdk-10+17
|
||||
c4b709bad6c5d29294124de5e74e1e2ac84fcf1f jdk-10+18
|
||||
|
@ -50,7 +50,12 @@ public class FilterOutputStream extends OutputStream {
|
||||
/**
|
||||
* Whether the stream is closed; implicitly initialized to false.
|
||||
*/
|
||||
private boolean closed;
|
||||
private volatile boolean closed;
|
||||
|
||||
/**
|
||||
* Object used to prevent a race on the 'closed' instance variable.
|
||||
*/
|
||||
private final Object closeLock = new Object();
|
||||
|
||||
/**
|
||||
* Creates an output stream filter built on top of the specified
|
||||
@ -165,7 +170,12 @@ public class FilterOutputStream extends OutputStream {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
synchronized (closeLock) {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
Throwable flushException = null;
|
||||
try {
|
||||
|
@ -364,9 +364,9 @@ public final class Class<T> implements java.io.Serializable,
|
||||
// Reflective call to get caller class is only needed if a security manager
|
||||
// is present. Avoid the overhead of making this call otherwise.
|
||||
caller = Reflection.getCallerClass();
|
||||
if (VM.isSystemDomainLoader(loader)) {
|
||||
if (loader == null) {
|
||||
ClassLoader ccl = ClassLoader.getClassLoader(caller);
|
||||
if (!VM.isSystemDomainLoader(ccl)) {
|
||||
if (ccl != null) {
|
||||
sm.checkPermission(
|
||||
SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
@ -432,18 +432,21 @@ public final class Class<T> implements java.io.Serializable,
|
||||
Objects.requireNonNull(module);
|
||||
Objects.requireNonNull(name);
|
||||
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (caller != null && caller.getModule() != module) {
|
||||
// if caller is null, Class.forName is the last java frame on the stack.
|
||||
// java.base has all permissions
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader cl;
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
if (caller != null && caller.getModule() != module) {
|
||||
// if caller is null, Class.forName is the last java frame on the stack.
|
||||
// java.base has all permissions
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
PrivilegedAction<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 {
|
||||
|
@ -246,7 +246,6 @@ public final class Module implements AnnotatedElement {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// --
|
||||
|
||||
// special Module to mean "all unnamed modules"
|
||||
@ -257,17 +256,38 @@ public final class Module implements AnnotatedElement {
|
||||
private static final Module EVERYONE_MODULE = new Module(null);
|
||||
private static final Set<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 @@ public final class Module implements AnnotatedElement {
|
||||
}
|
||||
|
||||
// check if this module reads the other module reflectively
|
||||
if (reflectivelyReads.containsKeyPair(this, other))
|
||||
if (ReflectionData.reads.containsKeyPair(this, other))
|
||||
return true;
|
||||
|
||||
// if other is an unnamed module then check if this module reads
|
||||
// all unnamed modules
|
||||
if (!other.isNamed()
|
||||
&& reflectivelyReads.containsKeyPair(this, ALL_UNNAMED_MODULE))
|
||||
&& ReflectionData.reads.containsKeyPair(this, ALL_UNNAMED_MODULE))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -393,7 +413,7 @@ public final class Module implements AnnotatedElement {
|
||||
}
|
||||
|
||||
// add reflective read
|
||||
reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
|
||||
ReflectionData.reads.putIfAbsent(this, other, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,13 +428,6 @@ public final class Module implements AnnotatedElement {
|
||||
// if the value contains EVERYONE_MODULE then the package is exported to all
|
||||
private volatile Map<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 @@ public final class Module implements AnnotatedElement {
|
||||
*/
|
||||
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 @@ public final class Module implements AnnotatedElement {
|
||||
if (other != EVERYONE_MODULE) {
|
||||
|
||||
// exported or open to other
|
||||
exports = reflectivelyExports.get(this, other);
|
||||
exports = ReflectionData.exports.get(this, other);
|
||||
if (exports != null) {
|
||||
Boolean b = exports.get(pn);
|
||||
if (b != null) {
|
||||
@ -623,7 +636,7 @@ public final class Module implements AnnotatedElement {
|
||||
|
||||
// other is an unnamed module && exported or open to all unnamed
|
||||
if (!other.isNamed()) {
|
||||
exports = reflectivelyExports.get(this, ALL_UNNAMED_MODULE);
|
||||
exports = ReflectionData.exports.get(this, ALL_UNNAMED_MODULE);
|
||||
if (exports != null) {
|
||||
Boolean b = exports.get(pn);
|
||||
if (b != null) {
|
||||
@ -886,8 +899,8 @@ public final class Module implements AnnotatedElement {
|
||||
}
|
||||
}
|
||||
|
||||
// add package name to reflectivelyExports if absent
|
||||
Map<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 @@ public final class Module implements AnnotatedElement {
|
||||
|
||||
// -- 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 @@ public final class Module implements AnnotatedElement {
|
||||
*/
|
||||
void implAddUses(Class<?> service) {
|
||||
if (!canUse(service)) {
|
||||
reflectivelyUses.putIfAbsent(this, service, Boolean.TRUE);
|
||||
ReflectionData.uses.putIfAbsent(this, service, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1011,7 +1020,7 @@ public final class Module implements AnnotatedElement {
|
||||
return true;
|
||||
|
||||
// uses added via addUses
|
||||
return reflectivelyUses.containsKeyPair(this, service);
|
||||
return ReflectionData.uses.containsKeyPair(this, service);
|
||||
}
|
||||
|
||||
|
||||
@ -1060,8 +1069,11 @@ public final class Module implements AnnotatedElement {
|
||||
Function<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 @@ public final class Module implements AnnotatedElement {
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
String name = resolvedModule.name();
|
||||
ClassLoader loader = clf.apply(name);
|
||||
moduleToLoader.put(name, loader);
|
||||
nameToLoader.put(name, loader);
|
||||
if (loader == null || loader == ClassLoaders.platformClassLoader()) {
|
||||
if (!(clf instanceof ModuleLoaderMap.Mapper)) {
|
||||
throw new IllegalArgumentException("loader can't be 'null'"
|
||||
@ -1087,20 +1099,19 @@ public final class Module implements AnnotatedElement {
|
||||
ModuleReference mref = resolvedModule.reference();
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
String name = descriptor.name();
|
||||
URI uri = mref.location().orElse(null);
|
||||
ClassLoader loader = moduleToLoader.get(resolvedModule.name());
|
||||
ClassLoader loader = nameToLoader.get(name);
|
||||
Module m;
|
||||
if (loader == null && name.equals("java.base")) {
|
||||
// java.base is already defined to the VM
|
||||
m = Object.class.getModule();
|
||||
} else {
|
||||
URI uri = mref.location().orElse(null);
|
||||
m = new Module(layer, loader, descriptor, uri);
|
||||
}
|
||||
nameToModule.put(name, m);
|
||||
moduleToLoader.put(name, loader);
|
||||
}
|
||||
|
||||
// setup readability and exports
|
||||
// setup readability and exports/opens
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleReference mref = resolvedModule.reference();
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
@ -1146,7 +1157,18 @@ public final class Module implements AnnotatedElement {
|
||||
}
|
||||
|
||||
// exports and opens
|
||||
initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
|
||||
if (descriptor.isOpen() || descriptor.isAutomatic()) {
|
||||
// The VM doesn't special case open or automatic modules yet
|
||||
// so need to export all packages
|
||||
for (String source : descriptor.packages()) {
|
||||
addExportsToAll0(m, source);
|
||||
}
|
||||
} else if (isBootLayer && descriptor.opens().isEmpty()) {
|
||||
// no open packages, no qualified exports to modules in parent layers
|
||||
initExports(m, nameToModule);
|
||||
} else {
|
||||
initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
|
||||
}
|
||||
}
|
||||
|
||||
// if there are modules defined to the boot or platform class loaders
|
||||
@ -1161,7 +1183,7 @@ public final class Module implements AnnotatedElement {
|
||||
if (!descriptor.provides().isEmpty()) {
|
||||
String name = descriptor.name();
|
||||
Module m = nameToModule.get(name);
|
||||
ClassLoader loader = moduleToLoader.get(name);
|
||||
ClassLoader loader = nameToLoader.get(name);
|
||||
if (loader == null) {
|
||||
bootCatalog.register(m);
|
||||
} else if (loader == pcl) {
|
||||
@ -1179,7 +1201,6 @@ public final class Module implements AnnotatedElement {
|
||||
return nameToModule;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the runtime Module corresponding to the given ResolvedModule
|
||||
* in the given parent layer (or its parents).
|
||||
@ -1201,25 +1222,55 @@ public final class Module implements AnnotatedElement {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize/setup a module's exports.
|
||||
*
|
||||
* @param m the module
|
||||
* @param nameToModule map of module name to Module (for qualified exports)
|
||||
*/
|
||||
private static void initExports(Module m, Map<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 @@ public final class Module implements AnnotatedElement {
|
||||
if (!targets.isEmpty()) {
|
||||
exportedPackages.put(source, targets);
|
||||
}
|
||||
|
||||
} else {
|
||||
// unqualified exports
|
||||
addExportsToAll0(m, source);
|
||||
|
@ -313,6 +313,10 @@ public final class System {
|
||||
* @see java.lang.RuntimePermission
|
||||
*/
|
||||
public static void setSecurityManager(final SecurityManager s) {
|
||||
if (security == null) {
|
||||
// ensure image reader is initialized
|
||||
Object.class.getResource("java/lang/ANY");
|
||||
}
|
||||
if (s != null) {
|
||||
try {
|
||||
s.checkPackageAccess("java.lang");
|
||||
|
@ -2476,7 +2476,7 @@ return mh1;
|
||||
return false;
|
||||
}
|
||||
ClassLoader loader = defc.getClassLoader();
|
||||
if (!jdk.internal.misc.VM.isSystemDomainLoader(loader)) {
|
||||
if (loader != null) {
|
||||
ClassLoader sysl = ClassLoader.getSystemClassLoader();
|
||||
boolean found = false;
|
||||
while (sysl != null) {
|
||||
|
@ -31,6 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -41,6 +42,9 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.module.ModuleReferenceImpl;
|
||||
import jdk.internal.module.ModuleTarget;
|
||||
|
||||
/**
|
||||
* A configuration that is the result of <a href="package-summary.html#resolution">
|
||||
* resolution</a> or resolution with <a href="#service-binding">service binding</a>.
|
||||
@ -121,11 +125,8 @@ public final class Configuration {
|
||||
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
|
||||
@ -146,6 +147,62 @@ public final class Configuration {
|
||||
this.targetPlatform = resolver.targetPlatform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Configuration for the boot layer from a pre-generated
|
||||
* readability graph.
|
||||
*
|
||||
* @apiNote This method is coded for startup performance.
|
||||
*/
|
||||
Configuration(ModuleFinder finder, Map<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
|
||||
@ -233,24 +290,20 @@ public final class Configuration {
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding, and with
|
||||
* the empty configuration as its parent. The consistency checks
|
||||
* are optionally run.
|
||||
* the empty configuration as its parent.
|
||||
*
|
||||
* This method is used to create the configuration for the boot layer.
|
||||
*/
|
||||
static Configuration resolveAndBind(ModuleFinder finder,
|
||||
Collection<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 @@ public final class Configuration {
|
||||
Resolver resolver = new Resolver(before, parentList, after, null);
|
||||
resolver.resolve(roots);
|
||||
|
||||
return new Configuration(parentList, resolver, true);
|
||||
return new Configuration(parentList, resolver);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -427,7 +480,7 @@ public final class Configuration {
|
||||
Resolver resolver = new Resolver(before, parentList, after, null);
|
||||
resolver.resolve(roots).bind();
|
||||
|
||||
return new Configuration(parentList, resolver, true);
|
||||
return new Configuration(parentList, resolver);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2728,10 +2728,15 @@ public class ModuleDescriptor
|
||||
@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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -25,9 +25,7 @@
|
||||
|
||||
package java.lang.module;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
@ -40,10 +38,8 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.module.ModuleBootstrap;
|
||||
import jdk.internal.module.ModulePatcher;
|
||||
import jdk.internal.module.ModulePath;
|
||||
import jdk.internal.module.SystemModuleFinder;
|
||||
import jdk.internal.module.SystemModuleFinders;
|
||||
|
||||
/**
|
||||
* A finder of modules. A {@code ModuleFinder} is used to find modules during
|
||||
@ -157,52 +153,13 @@ public interface ModuleFinder {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission("accessSystemModules"));
|
||||
PrivilegedAction<ModuleFinder> pa = ModuleFinder::privilegedOfSystem;
|
||||
PrivilegedAction<ModuleFinder> pa = SystemModuleFinders::ofSystem;
|
||||
return AccessController.doPrivileged(pa);
|
||||
} else {
|
||||
return privilegedOfSystem();
|
||||
return SystemModuleFinders.ofSystem();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a module finder that locates the system modules. This method
|
||||
* assumes it has permissions to access the runtime image.
|
||||
*/
|
||||
private static ModuleFinder privilegedOfSystem() {
|
||||
String home = System.getProperty("java.home");
|
||||
Path modules = Paths.get(home, "lib", "modules");
|
||||
if (Files.isRegularFile(modules)) {
|
||||
return SystemModuleFinder.getInstance();
|
||||
} else {
|
||||
Path dir = Paths.get(home, "modules");
|
||||
if (Files.isDirectory(dir)) {
|
||||
return privilegedOf(ModuleBootstrap.patcher(), dir);
|
||||
} else {
|
||||
throw new InternalError("Unable to detect the run-time image");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a module finder that locates the system modules in an exploded
|
||||
* image. The image may be patched.
|
||||
*/
|
||||
private static ModuleFinder privilegedOf(ModulePatcher patcher, Path dir) {
|
||||
ModuleFinder finder = ModulePath.of(patcher, dir);
|
||||
return new ModuleFinder() {
|
||||
@Override
|
||||
public Optional<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.
|
||||
|
@ -353,25 +353,13 @@ final class Resolver {
|
||||
|
||||
/**
|
||||
* Execute post-resolution checks and returns the module graph of resolved
|
||||
* modules as {@code Map}. The resolved modules will be in the given
|
||||
* configuration.
|
||||
*
|
||||
* @param check {@true} to execute the post resolution checks
|
||||
* modules as a map.
|
||||
*/
|
||||
Map<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;
|
||||
}
|
||||
|
||||
|
@ -453,7 +453,7 @@ public class Proxy implements java.io.Serializable {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
ClassLoader ccl = caller.getClassLoader();
|
||||
if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
|
||||
if (loader == null && ccl != null) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
|
||||
|
@ -409,7 +409,7 @@ public final class URL implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
protocol = protocol.toLowerCase(Locale.ROOT);
|
||||
protocol = toLowerCase(protocol);
|
||||
this.protocol = protocol;
|
||||
if (host != null) {
|
||||
|
||||
@ -585,7 +585,7 @@ public final class URL implements java.io.Serializable {
|
||||
for (i = start ; !aRef && (i < limit) &&
|
||||
((c = spec.charAt(i)) != '/') ; i++) {
|
||||
if (c == ':') {
|
||||
String s = spec.substring(start, i).toLowerCase(Locale.ROOT);
|
||||
String s = toLowerCase(spec.substring(start, i));
|
||||
if (isValidProtocol(s)) {
|
||||
newProtocol = s;
|
||||
start = i + 1;
|
||||
@ -1318,6 +1318,17 @@ public final class URL implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol in lower case. Special cases known protocols
|
||||
* to avoid loading locale classes during startup.
|
||||
*/
|
||||
static String toLowerCase(String protocol) {
|
||||
if (protocol.equals("jrt") || protocol.equals("file") || protocol.equals("jar")) {
|
||||
return protocol;
|
||||
} else {
|
||||
return protocol.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-overrideable protocols: "jrt" and "file"
|
||||
|
@ -70,7 +70,7 @@ public abstract class AbstractSelector
|
||||
extends Selector
|
||||
{
|
||||
|
||||
private AtomicBoolean selectorOpen = new AtomicBoolean(true);
|
||||
private final AtomicBoolean selectorOpen = new AtomicBoolean(true);
|
||||
|
||||
// The provider that created this selector
|
||||
private final SelectorProvider provider;
|
||||
|
@ -57,7 +57,7 @@ import javax.crypto.SecretKey;
|
||||
* 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 @@ public abstract class MessageDigest extends MessageDigestSpi {
|
||||
/**
|
||||
* Returns a string that identifies the algorithm, independent of
|
||||
* implementation details. The name should be a standard
|
||||
* Java Security name (such as "SHA", "MD5", and so on).
|
||||
* Java Security name (such as "SHA-256").
|
||||
* See the MessageDigest section in the <a href=
|
||||
* "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
|
||||
* Java Security Standard Algorithm Names Specification</a>
|
||||
|
@ -51,11 +51,10 @@ import sun.security.jca.GetInstance.Instance;
|
||||
* 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -81,13 +81,12 @@ import java.io.*;
|
||||
* verification in an attempt to bypass a security check.
|
||||
*
|
||||
* <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
|
||||
|
@ -667,11 +667,11 @@ import java.util.stream.StreamSupport;
|
||||
* <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>
|
||||
|
@ -59,7 +59,7 @@ import sun.security.jca.*;
|
||||
* <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 @@ import sun.security.jca.*;
|
||||
* 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 @@ public class Cipher {
|
||||
/*
|
||||
* array containing the components of a Cipher transformation:
|
||||
*
|
||||
* index 0: algorithm component (e.g., DES)
|
||||
* index 0: algorithm component (e.g., AES)
|
||||
* index 1: feedback component (e.g., CFB)
|
||||
* index 2: padding component (e.g., PKCS5Padding)
|
||||
*/
|
||||
@ -354,8 +356,8 @@ public class Cipher {
|
||||
// transform string to lookup in the provider
|
||||
final String transform;
|
||||
// the mode/padding suffix in upper case. for example, if the algorithm
|
||||
// to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"
|
||||
// if loopup is "DES", suffix is the empty string
|
||||
// to lookup is "AES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"
|
||||
// if lookup is "AES", suffix is the empty string
|
||||
// needed because aliases prevent straight transform.equals()
|
||||
final String suffix;
|
||||
// value to pass to setMode() or null if no such call required
|
||||
@ -440,11 +442,11 @@ public class Cipher {
|
||||
}
|
||||
|
||||
if ((mode == null) && (pad == null)) {
|
||||
// DES
|
||||
// AES
|
||||
Transform tr = new Transform(alg, "", null, null);
|
||||
return Collections.singletonList(tr);
|
||||
} else { // if ((mode != null) && (pad != null)) {
|
||||
// DES/CBC/PKCS5Padding
|
||||
// AES/CBC/PKCS5Padding
|
||||
List<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 @@ public class Cipher {
|
||||
* {@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 @@ public class Cipher {
|
||||
* 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 @@ public class Cipher {
|
||||
* 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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -59,7 +59,7 @@ import java.nio.ByteBuffer;
|
||||
* <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 @@ import java.nio.ByteBuffer;
|
||||
* 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 @@ import java.nio.ByteBuffer;
|
||||
* </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 @@ import java.nio.ByteBuffer;
|
||||
* <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 @@ import java.nio.ByteBuffer;
|
||||
*
|
||||
* <li>
|
||||
* <pre>
|
||||
* <code>Cipher.</code><i>DES</i>
|
||||
* <code>Cipher.</code><i>AES</i>
|
||||
* </pre>
|
||||
*
|
||||
* </ul>
|
||||
|
@ -50,7 +50,7 @@ import sun.security.jca.GetInstance.Instance;
|
||||
*
|
||||
* <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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -40,7 +40,7 @@ import java.security.NoSuchProviderException;
|
||||
* <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.
|
||||
|
@ -55,13 +55,13 @@ import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.ModulePatcher.PatchedModuleReader;
|
||||
import jdk.internal.module.SystemModules;
|
||||
import jdk.internal.module.Resources;
|
||||
|
||||
|
||||
@ -139,7 +139,7 @@ public class BuiltinClassLoader
|
||||
|
||||
// maps package name to loaded module for modules in the boot layer
|
||||
private static final Map<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 @@ public class BuiltinClassLoader
|
||||
URL url = cs.getLocation();
|
||||
if (url == null)
|
||||
return perms;
|
||||
Permission p = null;
|
||||
|
||||
// avoid opening connection when URL is to resource in run-time image
|
||||
if (url.getProtocol().equals("jrt")) {
|
||||
perms.add(new RuntimePermission("accessSystemModules"));
|
||||
return perms;
|
||||
}
|
||||
|
||||
// open connection to determine the permission needed
|
||||
try {
|
||||
p = url.openConnection().getPermission();
|
||||
Permission p = url.openConnection().getPermission();
|
||||
if (p != null) {
|
||||
// for directories then need recursive access
|
||||
if (p instanceof FilePermission) {
|
||||
@ -969,23 +976,26 @@ public class BuiltinClassLoader
|
||||
// -- miscellaneous supporting methods
|
||||
|
||||
/**
|
||||
* Returns the ModuleReader for the given module.
|
||||
* Returns the ModuleReader for the given module, creating it if needed
|
||||
*/
|
||||
private ModuleReader moduleReaderFor(ModuleReference mref) {
|
||||
return moduleToReader.computeIfAbsent(mref, BuiltinClassLoader::createModuleReader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ModuleReader for the given module.
|
||||
*/
|
||||
private static ModuleReader createModuleReader(ModuleReference mref) {
|
||||
try {
|
||||
return mref.open();
|
||||
} catch (IOException e) {
|
||||
// Return a null module reader to avoid a future class load
|
||||
// attempting to open the module again.
|
||||
return new NullModuleReader();
|
||||
ModuleReader reader = moduleToReader.get(mref);
|
||||
if (reader == null) {
|
||||
// avoid method reference during startup
|
||||
Function<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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package jdk.internal.loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.InvalidPathException;
|
||||
@ -38,7 +37,6 @@ import jdk.internal.misc.JavaLangAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
|
||||
/**
|
||||
* Creates and provides access to the built-in platform and application class
|
||||
* loaders. It also creates the class loader that is used to locate resources
|
||||
@ -61,23 +59,30 @@ public class ClassLoaders {
|
||||
*/
|
||||
static {
|
||||
|
||||
// -Xbootclasspth/a or -javaagent Boot-Class-Path
|
||||
// -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute
|
||||
URLClassPath bcp = null;
|
||||
String s = VM.getSavedProperty("jdk.boot.class.path.append");
|
||||
if (s != null && s.length() > 0)
|
||||
bcp = toURLClassPath(s);
|
||||
bcp = new URLClassPath(s, true);
|
||||
|
||||
// we have a class path if -cp is specified or -m is not specified.
|
||||
// If neither is specified then default to -cp <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 @@ public class ClassLoaders {
|
||||
* @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
|
||||
*/
|
||||
void appendToClassPathForInstrumentation(String path) {
|
||||
addClassPathToUCP(path, ucp);
|
||||
ucp.addFile(path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,41 +224,12 @@ public class ClassLoaders {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code URLClassPath} of file URLs to each of the elements in
|
||||
* the given class path.
|
||||
*/
|
||||
private static URLClassPath toURLClassPath(String cp) {
|
||||
URLClassPath ucp = new URLClassPath(new URL[0]);
|
||||
addClassPathToUCP(cp, ucp);
|
||||
return ucp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the elements in the given class path to file URLs and adds
|
||||
* them to the given URLClassPath.
|
||||
*/
|
||||
private static void addClassPathToUCP(String cp, URLClassPath ucp) {
|
||||
int off = 0;
|
||||
int next;
|
||||
while ((next = cp.indexOf(File.pathSeparator, off)) != -1) {
|
||||
URL url = toFileURL(cp.substring(off, next));
|
||||
if (url != null)
|
||||
ucp.addURL(url);
|
||||
off = next + 1;
|
||||
}
|
||||
|
||||
// remaining
|
||||
URL url = toFileURL(cp.substring(off));
|
||||
if (url != null)
|
||||
ucp.addURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to convert the given string to a file URL.
|
||||
*
|
||||
* @apiNote This is called by the VM
|
||||
*/
|
||||
@Deprecated
|
||||
private static URL toFileURL(String s) {
|
||||
try {
|
||||
// Use an intermediate File object to construct a URI/URL without
|
||||
@ -265,5 +241,4 @@ public class ClassLoaders {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import java.security.Permission;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
@ -66,7 +67,6 @@ import java.util.jar.Attributes.Name;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import jdk.internal.misc.JavaNetURLAccess;
|
||||
import jdk.internal.misc.JavaNetURLClassLoaderAccess;
|
||||
import jdk.internal.misc.JavaUtilZipFileAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.util.jar.InvalidJarIndexError;
|
||||
@ -100,19 +100,19 @@ public class URLClassPath {
|
||||
}
|
||||
|
||||
/* The original search path of URLs. */
|
||||
private ArrayList<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 class URLClassPath {
|
||||
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,18 +154,52 @@ public class URLClassPath {
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a URLClassPath with no additional security restrictions.
|
||||
* Used by code that implements the class path.
|
||||
*/
|
||||
public URLClassPath(URL[] urls) {
|
||||
this(urls, null, null);
|
||||
}
|
||||
|
||||
public URLClassPath(URL[] urls, AccessControlContext acc) {
|
||||
this(urls, null, acc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a URLClassPath from a class path string.
|
||||
*
|
||||
* @param cp the class path string
|
||||
* @param skipEmptyElements indicates if empty elements are ignored or
|
||||
* treated as the current working directory
|
||||
*
|
||||
* @apiNote Used to create the application class path.
|
||||
*/
|
||||
URLClassPath(String cp, boolean skipEmptyElements) {
|
||||
List<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() {
|
||||
if (closed) {
|
||||
return Collections.emptyList();
|
||||
@ -197,6 +235,28 @@ public class URLClassPath {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the specified file path as a file URL to the search path.
|
||||
*/
|
||||
public void addFile(String s) {
|
||||
URL url = toFileURL(s);
|
||||
if (url != null) {
|
||||
addURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file URL for the given file path.
|
||||
*/
|
||||
private static URL toFileURL(String s) {
|
||||
try {
|
||||
File f = new File(s).getCanonicalFile();
|
||||
return ParseUtil.fileToEncodedURL(f);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original search path of URLs.
|
||||
*/
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
package jdk.internal.logger;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
@ -140,15 +142,9 @@ public class DefaultLoggerFinder extends LoggerFinder {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Boolean run() {
|
||||
final ClassLoader moduleCL = m.getClassLoader();
|
||||
if (moduleCL == null) return true;
|
||||
ClassLoader cl = ClassLoader.getPlatformClassLoader();
|
||||
while (cl != null && moduleCL != cl) {
|
||||
cl = cl.getParent();
|
||||
}
|
||||
// returns true if moduleCL is the platform class loader
|
||||
// or one of its ancestors.
|
||||
return moduleCL == cl;
|
||||
return VM.isSystemDomainLoader(m.getClassLoader());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -34,16 +34,10 @@ import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
|
||||
/**
|
||||
* Provides access to non-public methods in java.lang.module.
|
||||
@ -131,12 +125,16 @@ public interface JavaLangModuleAccess {
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding
|
||||
* and the empty configuration as the parent. The post resolution
|
||||
* checks are optionally run.
|
||||
* and the empty configuration as the parent.
|
||||
*/
|
||||
Configuration resolveAndBind(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
boolean check,
|
||||
PrintStream traceOutput);
|
||||
|
||||
/**
|
||||
* Creates a configuration from a pre-generated readability graph.
|
||||
*/
|
||||
Configuration newConfiguration(ModuleFinder finder,
|
||||
Map<String, Set<String>> graph);
|
||||
|
||||
}
|
||||
|
@ -124,11 +124,11 @@ public class VM {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given class loader is in the system domain
|
||||
* in which all permissions are granted.
|
||||
* Returns true if the given class loader is the bootstrap class loader
|
||||
* or the platform class loader.
|
||||
*/
|
||||
public static boolean isSystemDomainLoader(ClassLoader loader) {
|
||||
return loader == null;
|
||||
return loader == null || loader == ClassLoader.getPlatformClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -40,16 +40,20 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.misc.JavaLangAccess;
|
||||
import jdk.internal.misc.JavaLangModuleAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
|
||||
@ -70,8 +74,6 @@ public final class ModuleBootstrap {
|
||||
|
||||
private static final String JAVA_BASE = "java.base";
|
||||
|
||||
private static final String JAVA_SE = "java.se";
|
||||
|
||||
// the token for "all default modules"
|
||||
private static final String ALL_DEFAULT = "ALL-DEFAULT";
|
||||
|
||||
@ -84,13 +86,13 @@ public final class ModuleBootstrap {
|
||||
// the token for "all modules on the module path"
|
||||
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
|
||||
|
||||
// access to java.lang/module
|
||||
private static final JavaLangModuleAccess JLMA
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
// The ModulePatcher for the initial configuration
|
||||
private static final ModulePatcher patcher = initModulePatcher();
|
||||
|
||||
// ModuleFinders for the initial configuration
|
||||
private static ModuleFinder unlimitedFinder;
|
||||
private static ModuleFinder limitedFinder;
|
||||
|
||||
/**
|
||||
* Returns the ModulePatcher for the initial configuration.
|
||||
*/
|
||||
@ -98,21 +100,38 @@ public final class ModuleBootstrap {
|
||||
return patcher;
|
||||
}
|
||||
|
||||
// ModuleFinders for the initial configuration
|
||||
private static volatile ModuleFinder unlimitedFinder;
|
||||
private static volatile ModuleFinder limitedFinder;
|
||||
|
||||
/**
|
||||
* Returns the ModuleFinder for the initial configuration before observability
|
||||
* is limited by the --limit-modules command line option.
|
||||
* Returns the ModuleFinder for the initial configuration before
|
||||
* observability is limited by the --limit-modules command line option.
|
||||
*
|
||||
* @apiNote Used to support locating modules {@code java.instrument} and
|
||||
* {@code jdk.management.agent} modules when they are loaded dynamically.
|
||||
*/
|
||||
public static ModuleFinder unlimitedFinder() {
|
||||
assert unlimitedFinder != null;
|
||||
return unlimitedFinder;
|
||||
ModuleFinder finder = unlimitedFinder;
|
||||
if (finder == null) {
|
||||
return ModuleFinder.ofSystem();
|
||||
} else {
|
||||
return finder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ModuleFinder for the initial configuration.
|
||||
*
|
||||
* @apiNote Used to support "{@code java --list-modules}".
|
||||
*/
|
||||
public static ModuleFinder limitedFinder() {
|
||||
assert limitedFinder != null;
|
||||
return limitedFinder;
|
||||
ModuleFinder finder = limitedFinder;
|
||||
if (finder == null) {
|
||||
return unlimitedFinder();
|
||||
} else {
|
||||
return finder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,13 +139,60 @@ public final class ModuleBootstrap {
|
||||
*
|
||||
* @see java.lang.System#initPhase2()
|
||||
*/
|
||||
public static ModuleLayer boot() {
|
||||
public static ModuleLayer boot() throws Exception {
|
||||
|
||||
// Step 1: Locate system modules (may be patched)
|
||||
// Step 0: Command line options
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
|
||||
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
|
||||
ModuleFinder appModulePath = finderFor("jdk.module.path");
|
||||
boolean isPatched = patcher.hasPatches();
|
||||
|
||||
String mainModule = System.getProperty("jdk.module.main");
|
||||
Set<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 @@ public final class ModuleBootstrap {
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
|
||||
ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
|
||||
ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
|
||||
if (base == null)
|
||||
throw new InternalError(JAVA_BASE + " not found");
|
||||
URI baseUri = base.location().orElse(null);
|
||||
@ -145,171 +211,138 @@ public final class ModuleBootstrap {
|
||||
BootLoader.loadModule(base);
|
||||
Modules.defineModule(null, base.descriptor(), baseUri);
|
||||
|
||||
PerfCounters.defineBaseTime.addElapsedTimeFrom(t2);
|
||||
Counters.add("jdk.module.boot.2.defineBaseTime", t2);
|
||||
|
||||
|
||||
// Step 2a: If --validate-modules is specified then the VM needs to
|
||||
// start with only java.base, all other options are ignored.
|
||||
|
||||
String propValue = getAndRemoveProperty("jdk.module.minimumBoot");
|
||||
if (propValue != null) {
|
||||
if (getAndRemoveProperty("jdk.module.minimumBoot") != null) {
|
||||
return createMinimalBootLayer();
|
||||
}
|
||||
|
||||
|
||||
// Step 3: Construct the module path and the set of root modules to
|
||||
// resolve. If --limit-modules is specified then it limits the set
|
||||
// modules that are observable.
|
||||
// Step 3: If resolution is needed then create the module finder and
|
||||
// the set of root modules to resolve.
|
||||
|
||||
long t3 = System.nanoTime();
|
||||
|
||||
// --upgrade-module-path option specified to launcher
|
||||
ModuleFinder upgradeModulePath
|
||||
= createModulePathFinder("jdk.module.upgrade.path");
|
||||
if (upgradeModulePath != null)
|
||||
systemModules = ModuleFinder.compose(upgradeModulePath, systemModules);
|
||||
ModuleFinder savedModuleFinder = null;
|
||||
ModuleFinder finder;
|
||||
Set<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 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);
|
||||
|
||||
// additional module(s) specified by --add-modules
|
||||
boolean addAllDefaultModules = false;
|
||||
boolean addAllSystemModules = false;
|
||||
boolean addAllApplicationModules = false;
|
||||
for (String mod: getExtraAddModules()) {
|
||||
switch (mod) {
|
||||
case ALL_DEFAULT:
|
||||
addAllDefaultModules = true;
|
||||
break;
|
||||
case ALL_SYSTEM:
|
||||
addAllSystemModules = true;
|
||||
break;
|
||||
case ALL_MODULE_PATH:
|
||||
addAllApplicationModules = true;
|
||||
break;
|
||||
default :
|
||||
roots.add(mod);
|
||||
// The module finder: [--upgrade-module-path] system [--module-path]
|
||||
if (appModulePath != null) {
|
||||
finder = ModuleFinder.compose(systemModuleFinder, appModulePath);
|
||||
} else {
|
||||
finder = systemModuleFinder;
|
||||
}
|
||||
}
|
||||
|
||||
// --limit-modules
|
||||
unlimitedFinder = finder;
|
||||
propValue = getAndRemoveProperty("jdk.module.limitmods");
|
||||
if (propValue != null) {
|
||||
Set<String> mods = new HashSet<>();
|
||||
for (String mod: propValue.split(",")) {
|
||||
mods.add(mod);
|
||||
}
|
||||
finder = limitFinder(finder, mods, roots);
|
||||
}
|
||||
limitedFinder = finder;
|
||||
// The root modules to resolve
|
||||
roots = new HashSet<>();
|
||||
|
||||
// If there is no initial module specified then assume that the initial
|
||||
// module is the unnamed module of the application class loader. This
|
||||
// is implemented by resolving "java.se" and all (non-java.*) modules
|
||||
// that export an API. If "java.se" is not observable then all java.*
|
||||
// modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
|
||||
// bit set in their ModuleResolution attribute flags are excluded from
|
||||
// the default set of roots.
|
||||
if (mainModule == null || addAllDefaultModules) {
|
||||
boolean hasJava = false;
|
||||
if (systemModules.find(JAVA_SE).isPresent()) {
|
||||
// java.se is a system module
|
||||
if (finder == systemModules || finder.find(JAVA_SE).isPresent()) {
|
||||
// java.se is observable
|
||||
hasJava = true;
|
||||
roots.add(JAVA_SE);
|
||||
// launcher -m option to specify the main/initial module
|
||||
if (mainModule != null)
|
||||
roots.add(mainModule);
|
||||
|
||||
// additional module(s) specified by --add-modules
|
||||
boolean addAllDefaultModules = false;
|
||||
boolean addAllSystemModules = false;
|
||||
boolean addAllApplicationModules = false;
|
||||
for (String mod : addModules) {
|
||||
switch (mod) {
|
||||
case ALL_DEFAULT:
|
||||
addAllDefaultModules = true;
|
||||
break;
|
||||
case ALL_SYSTEM:
|
||||
addAllSystemModules = true;
|
||||
break;
|
||||
case ALL_MODULE_PATH:
|
||||
addAllApplicationModules = true;
|
||||
break;
|
||||
default:
|
||||
roots.add(mod);
|
||||
}
|
||||
}
|
||||
|
||||
for (ModuleReference mref : systemModules.findAll()) {
|
||||
String mn = mref.descriptor().name();
|
||||
if (hasJava && mn.startsWith("java."))
|
||||
continue;
|
||||
|
||||
if (ModuleResolution.doNotResolveByDefault(mref))
|
||||
continue;
|
||||
|
||||
// add as root if observable and exports at least one package
|
||||
if ((finder == systemModules || finder.find(mn).isPresent())) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
for (ModuleDescriptor.Exports e : descriptor.exports()) {
|
||||
if (!e.isQualified()) {
|
||||
roots.add(mn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// --limit-modules
|
||||
savedModuleFinder = finder;
|
||||
if (!limitModules.isEmpty()) {
|
||||
finder = limitFinder(finder, limitModules, roots);
|
||||
}
|
||||
|
||||
// If there is no initial module specified then assume that the initial
|
||||
// module is the unnamed module of the application class loader. This
|
||||
// is implemented by resolving "java.se" and all (non-java.*) modules
|
||||
// that export an API. If "java.se" is not observable then all java.*
|
||||
// modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
|
||||
// bit set in their ModuleResolution attribute flags are excluded from
|
||||
// the default set of roots.
|
||||
if (mainModule == null || addAllDefaultModules) {
|
||||
roots.addAll(DefaultRoots.compute(systemModuleFinder, finder));
|
||||
}
|
||||
|
||||
// If `--add-modules ALL-SYSTEM` is specified then all observable system
|
||||
// modules will be resolved.
|
||||
if (addAllSystemModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
systemModuleFinder.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
// If `--add-modules ALL-MODULE-PATH` is specified then all observable
|
||||
// modules on the application module path will be resolved.
|
||||
if (appModulePath != null && addAllApplicationModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
appModulePath.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
} else {
|
||||
// no resolution case
|
||||
finder = systemModuleFinder;
|
||||
roots = null;
|
||||
}
|
||||
|
||||
// If `--add-modules ALL-SYSTEM` is specified then all observable system
|
||||
// modules will be resolved.
|
||||
if (addAllSystemModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
systemModules.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
// If `--add-modules ALL-MODULE-PATH` is specified then all observable
|
||||
// modules on the application module path will be resolved.
|
||||
if (appModulePath != null && addAllApplicationModules) {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
appModulePath.findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
.forEach(mn -> roots.add(mn));
|
||||
}
|
||||
|
||||
PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t3);
|
||||
|
||||
Counters.add("jdk.module.boot.3.optionsAndRootsTime", t3);
|
||||
|
||||
// Step 4: Resolve the root modules, with service binding, to create
|
||||
// the configuration for the boot layer.
|
||||
// the configuration for the boot layer. If resolution is not needed
|
||||
// then create the configuration for the boot layer from the
|
||||
// readability graph created at link time.
|
||||
|
||||
long t4 = System.nanoTime();
|
||||
|
||||
// determine if post resolution checks are needed
|
||||
boolean needPostResolutionChecks = true;
|
||||
if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here
|
||||
&& (upgradeModulePath == null)
|
||||
&& (appModulePath == null)
|
||||
&& (patcher.isEmpty())) {
|
||||
needPostResolutionChecks = false;
|
||||
Configuration cf;
|
||||
if (needResolution) {
|
||||
cf = JLMA.resolveAndBind(finder, roots, traceOutput);
|
||||
} else {
|
||||
Map<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 @@ public final class ModuleBootstrap {
|
||||
|
||||
// check that all modules to be mapped to the boot loader will be
|
||||
// loaded from the runtime image
|
||||
if (needPostResolutionChecks) {
|
||||
if (haveModulePath) {
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleReference mref = resolvedModule.reference();
|
||||
String name = mref.descriptor().name();
|
||||
@ -335,51 +368,54 @@ public final class ModuleBootstrap {
|
||||
if (upgradeModulePath != null
|
||||
&& upgradeModulePath.find(name).isPresent())
|
||||
fail(name + ": cannot be loaded from upgrade module path");
|
||||
if (!systemModules.find(name).isPresent())
|
||||
if (!systemModuleFinder.find(name).isPresent())
|
||||
fail(name + ": cannot be loaded from application module path");
|
||||
}
|
||||
}
|
||||
|
||||
// check if module specified in --patch-module is present
|
||||
for (String mn: patcher.patchedModules()) {
|
||||
if (!cf.findModule(mn).isPresent()) {
|
||||
warnUnknownModule(PATCH_MODULE, mn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for split packages in the modules mapped to the built-in loaders
|
||||
if (SystemModules.hasSplitPackages() || needPostResolutionChecks) {
|
||||
if (systemModules.hasSplitPackages() || isPatched || haveModulePath) {
|
||||
checkSplitPackages(cf, clf);
|
||||
}
|
||||
|
||||
// load/register the modules with the built-in class loaders
|
||||
loadModules(cf, clf);
|
||||
|
||||
PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
|
||||
Counters.add("jdk.module.boot.5.loadModulesTime", t5);
|
||||
|
||||
|
||||
// Step 6: Define all modules to the VM
|
||||
|
||||
long t6 = System.nanoTime();
|
||||
ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
|
||||
PerfCounters.layerCreateTime.addElapsedTimeFrom(t6);
|
||||
Counters.add("jdk.module.boot.6.layerCreateTime", t6);
|
||||
|
||||
|
||||
// Step 7: Miscellaneous
|
||||
|
||||
// check incubating status
|
||||
checkIncubatingStatus(cf);
|
||||
if (systemModules.hasIncubatorModules() || haveModulePath) {
|
||||
checkIncubatingStatus(cf);
|
||||
}
|
||||
|
||||
// --add-reads, --add-exports/--add-opens, and -illegal-access
|
||||
// --add-reads, --add-exports/--add-opens, and --illegal-access
|
||||
long t7 = System.nanoTime();
|
||||
addExtraReads(bootLayer);
|
||||
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
||||
addIllegalAccess(bootLayer, upgradeModulePath, extraExportsOrOpens);
|
||||
PerfCounters.adjustModulesTime.addElapsedTimeFrom(t7);
|
||||
addIllegalAccess(upgradeModulePath, systemModules, bootLayer, extraExportsOrOpens);
|
||||
Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
|
||||
|
||||
// save module finders for later use
|
||||
if (savedModuleFinder != null) {
|
||||
unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
|
||||
if (savedModuleFinder != finder)
|
||||
limitedFinder = new SafeModuleFinder(finder);
|
||||
}
|
||||
|
||||
// total time to initialize
|
||||
PerfCounters.bootstrapTime.addElapsedTimeFrom(t1);
|
||||
Counters.add("jdk.module.boot.totalTime", t0);
|
||||
Counters.publish();
|
||||
|
||||
return bootLayer;
|
||||
}
|
||||
@ -391,7 +427,6 @@ public final class ModuleBootstrap {
|
||||
Configuration cf = SharedSecrets.getJavaLangModuleAccess()
|
||||
.resolveAndBind(ModuleFinder.ofSystem(),
|
||||
Set.of(JAVA_BASE),
|
||||
false,
|
||||
null);
|
||||
|
||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
@ -439,7 +474,6 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +523,7 @@ public final class ModuleBootstrap {
|
||||
* Creates a finder from the module path that is the value of the given
|
||||
* system property and optionally patched by --patch-module
|
||||
*/
|
||||
private static ModuleFinder createModulePathFinder(String prop) {
|
||||
private static ModuleFinder finderFor(String prop) {
|
||||
String s = System.getProperty(prop);
|
||||
if (s == null) {
|
||||
return null;
|
||||
@ -510,35 +544,48 @@ public final class ModuleBootstrap {
|
||||
*/
|
||||
private static ModulePatcher initModulePatcher() {
|
||||
Map<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();
|
||||
}
|
||||
|
||||
Set<String> modules = new HashSet<>();
|
||||
while (value != null) {
|
||||
for (String s : value.split(",")) {
|
||||
if (s.length() > 0) modules.add(s);
|
||||
} 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);
|
||||
}
|
||||
index++;
|
||||
value = getAndRemoveProperty(prefix + index);
|
||||
return modules;
|
||||
}
|
||||
}
|
||||
|
||||
return modules;
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -676,8 +723,9 @@ public final class ModuleBootstrap {
|
||||
* Process the --illegal-access option (and its default) to open packages
|
||||
* of system modules in the boot layer to code in unnamed modules.
|
||||
*/
|
||||
private static void addIllegalAccess(ModuleLayer bootLayer,
|
||||
ModuleFinder upgradeModulePath,
|
||||
private static void addIllegalAccess(ModuleFinder upgradeModulePath,
|
||||
SystemModules systemModules,
|
||||
ModuleLayer bootLayer,
|
||||
boolean extraExportsOrOpens) {
|
||||
String value = getAndRemoveProperty("jdk.module.illegalAccess");
|
||||
IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
|
||||
@ -702,10 +750,10 @@ public final class ModuleBootstrap {
|
||||
IllegalAccessLogger.Builder builder
|
||||
= new IllegalAccessLogger.Builder(mode, System.err);
|
||||
|
||||
Map<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 @@ public final class ModuleBootstrap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator that yields all elements of the first iterator
|
||||
* followed by all the elements of the second iterator.
|
||||
*/
|
||||
static <T> Iterator<T> concat(Iterator<T> iterator1, Iterator<T> iterator2) {
|
||||
return new Iterator<T>() {
|
||||
@Override
|
||||
@ -921,23 +973,76 @@ public final class ModuleBootstrap {
|
||||
};
|
||||
}
|
||||
|
||||
static class PerfCounters {
|
||||
/**
|
||||
* Wraps a (potentially not thread safe) ModuleFinder created during startup
|
||||
* for use after startup.
|
||||
*/
|
||||
static class SafeModuleFinder implements ModuleFinder {
|
||||
private final Set<ModuleReference> mrefs;
|
||||
private volatile Map<String, ModuleReference> nameToModule;
|
||||
|
||||
static PerfCounter systemModulesTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime");
|
||||
static PerfCounter defineBaseTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime");
|
||||
static PerfCounter optionsAndRootsTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime");
|
||||
static PerfCounter resolveTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime");
|
||||
static PerfCounter layerCreateTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime");
|
||||
static PerfCounter loadModulesTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime");
|
||||
static PerfCounter adjustModulesTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.adjustModulesTime");
|
||||
static PerfCounter bootstrapTime
|
||||
= PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime");
|
||||
SafeModuleFinder(ModuleFinder finder) {
|
||||
this.mrefs = Collections.unmodifiableSet(finder.findAll());
|
||||
}
|
||||
@Override
|
||||
public Optional<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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,10 +200,10 @@ public final class ModulePatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true is this module patcher has no patches.
|
||||
* Returns true is this module patcher has patches.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
public boolean hasPatches() {
|
||||
return !map.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -68,14 +68,14 @@ public class ModuleReferenceImpl extends ModuleReference {
|
||||
/**
|
||||
* 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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -26,94 +26,73 @@
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* SystemModules class will be generated at link time to create
|
||||
* ModuleDescriptor for the system modules directly to improve
|
||||
* the module descriptor reconstitution time.
|
||||
*
|
||||
* This will skip parsing of module-info.class file and validating
|
||||
* names such as module name, package name, service and provider type names.
|
||||
* It also avoids taking a defensive copy of any collection.
|
||||
* A SystemModules object reconstitutes module descriptors and other modules
|
||||
* attributes in an efficient way to avoid parsing module-info.class files at
|
||||
* startup. Implementations of this class are generated by the "system modules"
|
||||
* jlink plugin.
|
||||
*
|
||||
* @see SystemModuleFinders
|
||||
* @see jdk.tools.jlink.internal.plugins.SystemModulesPlugin
|
||||
*/
|
||||
public final class SystemModules {
|
||||
/**
|
||||
* Name of the system modules.
|
||||
*
|
||||
* This array provides a way for SystemModuleFinder to fallback
|
||||
* and read module-info.class from the run-time image instead of
|
||||
* the fastpath.
|
||||
*/
|
||||
public static final String[] MODULE_NAMES = new String[0];
|
||||
|
||||
interface SystemModules {
|
||||
|
||||
/**
|
||||
* Number of packages in the boot layer from the installed modules.
|
||||
*
|
||||
* Don't make it final to avoid inlining during compile time as
|
||||
* the value will be changed at jlink time.
|
||||
* Returns false if the module reconstituted by this SystemModules object
|
||||
* have no overlapping packages. Returns true if there are overlapping
|
||||
* packages or unknown.
|
||||
*/
|
||||
public static int PACKAGES_IN_BOOT_LAYER = 1024;
|
||||
boolean hasSplitPackages();
|
||||
|
||||
/**
|
||||
* Return true if there are no split packages in the run-time image.
|
||||
* Return false if the modules reconstituted by this SystemModules object
|
||||
* do not include any incubator modules. Returns true if there are
|
||||
* incubating modules or unknown.
|
||||
*/
|
||||
public static boolean hasSplitPackages() {
|
||||
return true;
|
||||
}
|
||||
boolean hasIncubatorModules();
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleDescriptor objects in the run-time image.
|
||||
*
|
||||
* When running an exploded image it returns an empty array.
|
||||
* Returns the non-empty array of ModuleDescriptor objects.
|
||||
*/
|
||||
public static ModuleDescriptor[] descriptors() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
ModuleDescriptor[] moduleDescriptors();
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleTarget objects in the run-time image.
|
||||
*
|
||||
* When running an exploded image it returns an empty array.
|
||||
* Returns the array of ModuleTarget objects. The array elements correspond
|
||||
* to the array of ModuleDescriptor objects.
|
||||
*/
|
||||
public static ModuleTarget[] targets() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
ModuleTarget[] moduleTargets();
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleHashes recorded in each module
|
||||
* in the run-time image.
|
||||
*
|
||||
* When running an exploded image it returns an empty array.
|
||||
* Returns the array of ModuleHashes objects. The array elements correspond
|
||||
* to the array of ModuleDescriptor objects.
|
||||
*/
|
||||
public static ModuleHashes[] hashes() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
ModuleHashes[] moduleHashes();
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleResolutions in the run-time image.
|
||||
* Returns the array of ModuleResolution objects. The array elements correspond
|
||||
* to the array of ModuleDescriptor objects.
|
||||
*/
|
||||
public static ModuleResolution[] moduleResolutions() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
ModuleResolution[] moduleResolutions();
|
||||
|
||||
/**
|
||||
* Returns the map representing readability graph for the modules reconstituted
|
||||
* by this SystemModules object.
|
||||
*/
|
||||
Map<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();
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
@ -316,8 +316,7 @@ public class Reflection {
|
||||
*/
|
||||
public static boolean isCallerSensitive(Method m) {
|
||||
final ClassLoader loader = m.getDeclaringClass().getClassLoader();
|
||||
if (VM.isSystemDomainLoader(loader) ||
|
||||
loader == ClassLoaders.platformClassLoader()) {
|
||||
if (VM.isSystemDomainLoader(loader)) {
|
||||
return m.isAnnotationPresent(CallerSensitive.class);
|
||||
}
|
||||
return false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,10 +26,18 @@
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.net.SocketException;
|
||||
import java.util.*;
|
||||
import java.nio.channels.ClosedSelectorException;
|
||||
import java.nio.channels.IllegalSelectorException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.AbstractSelector;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
@ -54,23 +62,18 @@ public abstract class SelectorImpl
|
||||
super(sp);
|
||||
keys = new HashSet<>();
|
||||
selectedKeys = new HashSet<>();
|
||||
if (Util.atBugLevel("1.4")) {
|
||||
publicKeys = keys;
|
||||
publicSelectedKeys = selectedKeys;
|
||||
} else {
|
||||
publicKeys = Collections.unmodifiableSet(keys);
|
||||
publicSelectedKeys = Util.ungrowableSet(selectedKeys);
|
||||
}
|
||||
publicKeys = Collections.unmodifiableSet(keys);
|
||||
publicSelectedKeys = Util.ungrowableSet(selectedKeys);
|
||||
}
|
||||
|
||||
public Set<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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,13 +25,16 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.io.FileDescriptor;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
@ -456,21 +459,4 @@ public class Util {
|
||||
}
|
||||
return dbb;
|
||||
}
|
||||
|
||||
|
||||
// -- Bug compatibility --
|
||||
|
||||
private static volatile String bugLevel;
|
||||
|
||||
static boolean atBugLevel(String bl) { // package-private
|
||||
if (bugLevel == null) {
|
||||
if (!jdk.internal.misc.VM.isBooted())
|
||||
return false;
|
||||
String value = GetPropertyAction
|
||||
.privilegedGetProperty("sun.nio.ch.bugLevel");
|
||||
bugLevel = (value != null) ? value : "";
|
||||
}
|
||||
return bugLevel.equals(bl);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ public abstract class HandshakeMessage {
|
||||
public static final Debug debug = Debug.getInstance("ssl");
|
||||
|
||||
// enum HandshakeType:
|
||||
//
|
||||
// Please update the isUnsupported() method accordingly if the handshake
|
||||
// types get updated in the future.
|
||||
static final byte ht_hello_request = 0; // RFC 5246
|
||||
static final byte ht_client_hello = 1; // RFC 5246
|
||||
static final byte ht_server_hello = 2; // RFC 5246
|
||||
@ -130,6 +133,24 @@ public abstract class HandshakeMessage {
|
||||
return b;
|
||||
}
|
||||
|
||||
static boolean isUnsupported(byte handshakeType) {
|
||||
return (handshakeType != ht_hello_request) &&
|
||||
(handshakeType != ht_client_hello) &&
|
||||
(handshakeType != ht_server_hello) &&
|
||||
(handshakeType != ht_hello_verify_request) &&
|
||||
(handshakeType != ht_new_session_ticket) &&
|
||||
(handshakeType != ht_certificate) &&
|
||||
(handshakeType != ht_server_key_exchange) &&
|
||||
(handshakeType != ht_certificate_request) &&
|
||||
(handshakeType != ht_server_hello_done) &&
|
||||
(handshakeType != ht_certificate_verify) &&
|
||||
(handshakeType != ht_client_key_exchange) &&
|
||||
(handshakeType != ht_finished) &&
|
||||
(handshakeType != ht_certificate_url) &&
|
||||
(handshakeType != ht_certificate_status) &&
|
||||
(handshakeType != ht_supplemental_data);
|
||||
}
|
||||
|
||||
private static byte[] genPad(int b, int count) {
|
||||
byte[] padding = new byte[count];
|
||||
Arrays.fill(padding, (byte)b);
|
||||
|
@ -1034,6 +1034,12 @@ abstract class Handshaker {
|
||||
input.mark(4);
|
||||
|
||||
messageType = (byte)input.getInt8();
|
||||
if (HandshakeMessage.isUnsupported(messageType)) {
|
||||
throw new SSLProtocolException(
|
||||
"Received unsupported or unknown handshake message: " +
|
||||
messageType);
|
||||
}
|
||||
|
||||
messageLen = input.getInt24();
|
||||
|
||||
if (input.available() < messageLen) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -73,8 +73,8 @@ import javax.security.auth.Subject;
|
||||
* must not be null; the behavior is unspecified if it is.</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
|
||||
|
@ -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 @@ questions.
|
||||
<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>
|
||||
|
@ -588,8 +588,8 @@ public class ManagementFactory {
|
||||
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(
|
||||
|
@ -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 @@ questions.
|
||||
<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>
|
||||
|
@ -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 @@ mbs.invoke(mapName, "get", new Object[] {"key"}, new String[] {Object.class.getN
|
||||
|
||||
<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
|
||||
|
@ -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 @@ questions.
|
||||
</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>
|
||||
|
@ -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 @@ questions.
|
||||
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
|
||||
|
@ -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 @@ questions.
|
||||
</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
|
||||
|
||||
|
@ -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<ObjectName> dependentASet = dependentAMap.keySet();
|
||||
// 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
|
||||
|
@ -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 @@ questions.
|
||||
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 @@ rmi://192.18.1.9 username 1
|
||||
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
|
||||
|
@ -48,7 +48,7 @@ public class CardException extends Exception {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -48,7 +48,7 @@ public class CardNotPresentException extends CardException {
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -42,14 +42,16 @@ package com.sun.tools.attach;
|
||||
*
|
||||
* <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 @@ package com.sun.tools.attach;
|
||||
* </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>
|
||||
|
||||
|
@ -59,21 +59,29 @@ import com.sun.net.httpserver.spi.HttpServerProvider;
|
||||
* 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>
|
||||
|
@ -618,7 +618,7 @@ public abstract class HttpResponse<T> {
|
||||
* 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 @@ public abstract class HttpResponse<T> {
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
*
|
||||
* @param onComplete a CompletableFuture which completes after all
|
||||
* responses have been received relating to this multi request.
|
||||
|
@ -275,6 +275,12 @@ public class SocketTransportService extends TransportService {
|
||||
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);
|
||||
}
|
||||
|
@ -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 @@ getLastError() {
|
||||
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 @@ setOptions(int fd)
|
||||
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 @@ socketTransport_startListening(jdwpTransportEnv* env, const char* address,
|
||||
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,11 +534,17 @@ socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong a
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user