--- a/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44
bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45
722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46
+8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47
--- a/.hgtags-top-repo Thu Jan 22 22:42:33 2015 -0800
+++ b/.hgtags-top-repo Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
8994f5d87b3bb5e8d317d4e8ccb326da1a73684a jdk9-b44
3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
+b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
--- a/corba/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/corba/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
1f57bd728c9e6865ccb9d43ccd80a1c11230a32f jdk9-b44
9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
+ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
--- a/hotspot/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -449,3 +449,4 @@
43a44b56dca61a4d766a20f0528fdd8b5ceff873 jdk9-b44
5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
+3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -284,19 +284,20 @@
MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT),
MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT),
- MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT),
- MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT),
- MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT),
- MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT),
- MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT),
- MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT),
- MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT),
- MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT),
+ // Attention: Higher and lower half are inserted in reversed order.
+ MTTFHAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MFTFHAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MTTFIAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+ MFTFIAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
+ MTTEXASR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+ MFTEXASR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
+ MTTEXASRU_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
+ MFTEXASRU_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
- MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT),
- MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT),
+ MTVRSAVE_OPCODE = (MTSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
+ MFVRSAVE_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
- MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT),
+ MFTB_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 12 << SPR_0_4_SHIFT),
MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1),
MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1),
@@ -1494,6 +1495,26 @@
inline void mftexasr(Register d);
inline void mftexasru(Register d);
+ // TEXASR bit description
+ enum transaction_failure_reason {
+ // Upper half (TEXASRU):
+ tm_failure_persistent = 7, // The failure is likely to recur on each execution.
+ tm_disallowed = 8, // The instruction is not permitted.
+ tm_nesting_of = 9, // The maximum transaction level was exceeded.
+ tm_footprint_of = 10, // The tracking limit for transactional storage accesses was exceeded.
+ tm_self_induced_cf = 11, // A self-induced conflict occurred in Suspended state.
+ tm_non_trans_cf = 12, // A conflict occurred with a non-transactional access by another processor.
+ tm_trans_cf = 13, // A conflict occurred with another transaction.
+ tm_translation_cf = 14, // A conflict occurred with a TLB invalidation.
+ tm_inst_fetch_cf = 16, // An instruction fetch was performed from a block that was previously written transactionally.
+ tm_tabort = 31, // Termination was caused by the execution of an abort instruction.
+ // Lower half:
+ tm_suspended = 32, // Failure was recorded in Suspended state.
+ tm_failure_summary = 36, // Failure has been detected and recorded.
+ tm_tfiar_exact = 37, // Value in the TFIAR is exact.
+ tm_rot = 38, // Rollback-only transaction.
+ };
+
// PPC 1, section 2.4.1 Branch Instructions
inline void b( address a, relocInfo::relocType rt = relocInfo::none);
inline void b( Label& L);
@@ -1581,6 +1602,7 @@
inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none);
// condition register logic instructions
+ // NOTE: There's a preferred form: d and s2 should point into the same condition register.
inline void crand( int d, int s1, int s2);
inline void crnand(int d, int s1, int s2);
inline void cror( int d, int s1, int s2);
@@ -1590,6 +1612,19 @@
inline void crandc(int d, int s1, int s2);
inline void crorc( int d, int s1, int s2);
+ // More convenient version.
+ int condition_register_bit(ConditionRegister cr, Condition c) {
+ return 4 * (int)(intptr_t)cr + c;
+ }
+ void crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+ void crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
+
// icache and dcache related instructions
inline void icbi( Register s1, Register s2);
//inline void dcba(Register s1, Register s2); // Instruction for embedded processor only.
@@ -1673,6 +1708,10 @@
inline void smt_prio_low();
inline void smt_prio_medium_low();
inline void smt_prio_medium();
+ // >= Power7
+ inline void smt_yield();
+ inline void smt_mdoio();
+ inline void smt_mdoom();
// trap instructions
inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur)
@@ -1958,6 +1997,7 @@
inline void tbeginrot_(); // R=1 Rollback-Only Transaction
inline void tend_(); // A=0
inline void tendall_(); // A=1
+ inline void tabort_();
inline void tabort_(Register a);
inline void tabortwc_(int t, Register a, Register b);
inline void tabortwci_(int t, Register a, int si);
@@ -1967,6 +2007,10 @@
inline void tresume_(); // tsr with L=1
inline void tcheck(int f);
+ static bool is_tbegin(int x) {
+ return TBEGIN_OPCODE == (x & (0x3f << OPCODE_SHIFT | 0x3ff << 1));
+ }
+
// The following encoders use r0 as second operand. These instructions
// read r0 as '0'.
inline void lwzx( Register d, Register s2);
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -453,6 +453,48 @@
inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
+// More convenient version.
+inline void Assembler::crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crnand(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ cror(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crxor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crnor(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ creqv(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crandc(dst_bit, src_bit, dst_bit);
+}
+inline void Assembler::crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
+ int dst_bit = condition_register_bit(crdst, cdst),
+ src_bit = condition_register_bit(crsrc, csrc);
+ crorc(dst_bit, src_bit, dst_bit);
+}
+
// Conditional move (>= Power7)
inline void Assembler::isel(Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b) {
if (b == noreg) {
@@ -516,6 +558,10 @@
inline void Assembler::smt_prio_medium() { Assembler::or_unchecked(R2, R2, R2); }
inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5, R5, R5); }
inline void Assembler::smt_prio_high() { Assembler::or_unchecked(R3, R3, R3); }
+// >= Power7
+inline void Assembler::smt_yield() { Assembler::or_unchecked(R27, R27, R27); }
+inline void Assembler::smt_mdoio() { Assembler::or_unchecked(R29, R29, R29); }
+inline void Assembler::smt_mdoom() { Assembler::or_unchecked(R30, R30, R30); }
inline void Assembler::twi_0(Register a) { twi_unchecked(0, a, 0);}
@@ -778,7 +824,8 @@
inline void Assembler::tbeginrot_() { emit_int32( TBEGIN_OPCODE | /*R=1*/ 1u << (31-10) | rc(1)); }
inline void Assembler::tend_() { emit_int32( TEND_OPCODE | rc(1)); }
inline void Assembler::tendall_() { emit_int32( TEND_OPCODE | /*A=1*/ 1u << (31-6) | rc(1)); }
-inline void Assembler::tabort_(Register a) { emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
+inline void Assembler::tabort_() { emit_int32( TABORT_OPCODE | rc(1)); }
+inline void Assembler::tabort_(Register a) { assert(a != R0, "r0 not allowed"); emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
inline void Assembler::tabortwc_(int t, Register a, Register b) { emit_int32( TABORTWC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
inline void Assembler::tabortwci_(int t, Register a, int si) { emit_int32( TABORTWCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); }
inline void Assembler::tabortdc_(int t, Register a, Register b) { emit_int32( TABORTDC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1712,7 +1712,7 @@
andi_(R0, klass, TypeEntries::type_unknown);
// Already unknown. Nothing to do anymore.
//bne(CCR0, do_nothing);
- crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne
+ crorc(CCR0, Assembler::equal, CCR1, Assembler::equal); // cr0 eq = cr1 eq or cr0 ne
beq(CCR0, do_nothing);
clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask));
@@ -1826,9 +1826,9 @@
lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method);
cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic);
cmpwi(CCR1, tmp1, Bytecodes::_invokehandle);
- cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm);
- cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
bne(CCR0, profile_continue);
}
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1079,7 +1079,7 @@
__ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes
__ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison!
__ cmpld(CCR1, tmp1, tmp2);
- __ crand(/*CCR0 lt*/0, /*CCR1 lt*/4+0, /*CCR0 lt*/0);
+ __ crand(CCR0, Assembler::less, CCR1, Assembler::less);
__ blt(CCR0, l_overlap); // Src before dst and distance smaller than size.
// need to copy forwards
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -264,11 +264,11 @@
__ cmpdi(CCR0, Rmdo, 0);
__ beq(CCR0, no_mdo);
- // Increment backedge counter in the MDO.
- const int mdo_bc_offs = in_bytes(MethodData::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
- __ lwz(Rscratch2, mdo_bc_offs, Rmdo);
+ // Increment invocation counter in the MDO.
+ const int mdo_ic_offs = in_bytes(MethodData::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
+ __ lwz(Rscratch2, mdo_ic_offs, Rmdo);
__ addi(Rscratch2, Rscratch2, increment);
- __ stw(Rscratch2, mdo_bc_offs, Rmdo);
+ __ stw(Rscratch2, mdo_ic_offs, Rmdo);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ bne(CCR0, done);
@@ -276,12 +276,12 @@
}
// Increment counter in MethodCounters*.
- const int mo_bc_offs = in_bytes(MethodCounters::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
+ const int mo_ic_offs = in_bytes(MethodCounters::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
__ bind(no_mdo);
__ get_method_counters(R19_method, R3_counters, done);
- __ lwz(Rscratch2, mo_bc_offs, R3_counters);
+ __ lwz(Rscratch2, mo_ic_offs, R3_counters);
__ addi(Rscratch2, Rscratch2, increment);
- __ stw(Rscratch2, mo_bc_offs, R3_counters);
+ __ stw(Rscratch2, mo_ic_offs, R3_counters);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ beq(CCR0, *overflow);
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -335,11 +335,11 @@
__ cmpwi(CCR0, Rscratch2, JVM_CONSTANT_UnresolvedClass); // Unresolved class?
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_UnresolvedClassInError); // Unresolved class in error state?
- __ cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ __ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
// Resolved class - need to call vm to get java mirror of the class.
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_Class);
- __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // Neither resolved class nor unresolved case from above?
+ __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal); // Neither resolved class nor unresolved case from above?
__ beq(CCR0, notClass);
__ li(R4, wide ? 1 : 0);
@@ -2611,7 +2611,7 @@
__ cmpwi(CCR0, Rflags, ltos);
__ cmpwi(CCR1, Rflags, dtos);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(1));
- __ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
+ __ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal);
__ beq(CCR0, is_one_slot);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(2));
__ bind(is_one_slot);
@@ -3563,7 +3563,7 @@
// Make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class.
__ andi_(R0, Rinstance_size, Klass::_lh_instance_slow_path_bit); // slow path bit equals 0?
- __ crnand(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // slow path bit set or not fully initialized?
+ __ crnand(CCR0, Assembler::equal, CCR1, Assembler::equal); // slow path bit set or not fully initialized?
__ beq(CCR0, Lslow_case);
// --------------------------------------------------------------------------
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -3184,7 +3184,24 @@
jmp(done);
} else {
// Stack: X Y
- Label x_negative, y_odd;
+ Label x_negative, y_not_2;
+
+ static double two = 2.0;
+ ExternalAddress two_addr((address)&two);
+
+ // constant maybe too far on 64 bit
+ lea(tmp2, two_addr);
+ fld_d(Address(tmp2, 0)); // Stack: 2 X Y
+ fcmp(tmp, 2, true, false); // Stack: X Y
+ jcc(Assembler::parity, y_not_2);
+ jcc(Assembler::notEqual, y_not_2);
+
+ fxch(); fpop(); // Stack: X
+ fmul(0); // Stack: X*X
+
+ jmp(done);
+
+ bind(y_not_2);
fldz(); // Stack: 0 X Y
fcmp(tmp, 1, true, false); // Stack: X Y
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -197,7 +197,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -211,27 +242,185 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirfd(dirp))) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirfd(dirp);
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
-
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@@ -317,9 +506,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -344,25 +535,14 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
continue;
}
- // Since we don't create the backing store files in directories
- // pointed to by symbolic links, we also don't follow them when
- // looking for the files. We check for a symbolic link after the
- // call to opendir in order to eliminate a small window where the
- // symlink can be exploited.
- //
- if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
- os::closedir(subdirp);
- continue;
- }
-
struct dirent* udentry;
char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
@@ -465,26 +645,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -496,17 +656,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -520,6 +674,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -530,7 +685,7 @@
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -553,11 +708,14 @@
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -614,19 +772,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -684,8 +877,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -717,13 +917,21 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -838,12 +1046,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -197,7 +197,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -211,22 +242,180 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirfd(dirp))) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirfd(dirp);
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
@@ -317,9 +506,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -344,7 +535,8 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -465,26 +657,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -496,17 +668,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -520,6 +686,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -528,9 +695,8 @@
if (pid == 0) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
-
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -552,12 +718,14 @@
//
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
-
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -614,19 +782,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -684,8 +887,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -716,6 +926,13 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
@@ -723,7 +940,7 @@
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -838,12 +1055,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -199,7 +199,38 @@
}
-// check if the given path is considered a secure directory for
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+//
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ //
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ //
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ //
+ return false;
+ }
+ return true;
+}
+
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@@ -213,27 +244,185 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+//
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+//
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+//
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+ if (result == OS_ERR) {
+ // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
}
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirp->dd_fd)) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirp->dd_fd;
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+//
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+//
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
}
return true;
}
-
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@@ -308,9 +497,11 @@
const char* tmpdirname = os::get_temp_directory();
+ // open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
+ // Cannot open the directory to get the user name, return.
return NULL;
}
@@ -335,7 +526,8 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // open the user directory
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -504,26 +696,6 @@
}
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@@ -535,17 +707,11 @@
//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // open the directory
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
- return;
- }
-
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
+ // directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@@ -559,6 +725,7 @@
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -569,7 +736,7 @@
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
@@ -592,11 +759,14 @@
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
+
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
FREE_C_HEAP_ARRAY(char, dbuf);
}
@@ -653,19 +823,54 @@
return -1;
}
- int result;
+ int saved_cwd_fd;
+ // open the directory and set the current working directory to it
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
+ int result;
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // close the directory and reset the current working directory
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // truncate the file to get rid of any existing data
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -701,8 +906,15 @@
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
+ int fd = result;
- return result;
+ // check to see if the file is secure
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -734,13 +946,21 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // get the short filename
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -856,12 +1076,12 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
- file_flags = O_RDONLY;
+ file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
--- a/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/os_cpu/bsd_zero/vm/atomic_bsd_zero.inline.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -237,7 +237,13 @@
// operation. Note that some platforms only support this with the
// limitation that the only valid value to store is the immediate
// constant 1. There is a test for this in JNI_CreateJavaVM().
- return __sync_lock_test_and_set (dest, exchange_value);
+ jint result = __sync_lock_test_and_set (dest, exchange_value);
+ // All atomic operations are expected to be full memory barriers
+ // (see atomic.hpp). However, __sync_lock_test_and_set is not
+ // a full memory barrier, but an acquire barrier. Hence, this added
+ // barrier.
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
@@ -250,7 +256,9 @@
#ifdef M68K
return m68k_lock_test_and_set(dest, exchange_value);
#else
- return __sync_lock_test_and_set (dest, exchange_value);
+ intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
--- a/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/os_cpu/linux_zero/vm/atomic_linux_zero.inline.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007, 2008, 2011 Red Hat, Inc.
+ * Copyright 2007, 2008, 2011, 2015, Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -231,7 +231,13 @@
// operation. Note that some platforms only support this with the
// limitation that the only valid value to store is the immediate
// constant 1. There is a test for this in JNI_CreateJavaVM().
- return __sync_lock_test_and_set (dest, exchange_value);
+ jint result = __sync_lock_test_and_set (dest, exchange_value);
+ // All atomic operations are expected to be full memory barriers
+ // (see atomic.hpp). However, __sync_lock_test_and_set is not
+ // a full memory barrier, but an acquire barrier. Hence, this added
+ // barrier.
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
@@ -244,7 +250,9 @@
#ifdef M68K
return m68k_lock_test_and_set(dest, exchange_value);
#else
- return __sync_lock_test_and_set (dest, exchange_value);
+ intptr_t result = __sync_lock_test_and_set (dest, exchange_value);
+ __sync_synchronize();
+ return result;
#endif // M68K
#endif // ARM
}
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -89,8 +89,8 @@
public:
ArgumentMap *_vars;
ArgumentMap *_stack;
- short _stack_height;
- short _max_stack;
+ int _stack_height;
+ int _max_stack;
bool _initialized;
ArgumentMap empty_map;
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1905,11 +1905,12 @@
InstanceKlass::cast(WK_KLASS(Reference_klass))->set_reference_type(REF_OTHER);
InstanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(Reference_klass));
- initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(PhantomReference_klass), scan, CHECK);
+ initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Cleaner_klass), scan, CHECK);
InstanceKlass::cast(WK_KLASS(SoftReference_klass))->set_reference_type(REF_SOFT);
InstanceKlass::cast(WK_KLASS(WeakReference_klass))->set_reference_type(REF_WEAK);
InstanceKlass::cast(WK_KLASS(FinalReference_klass))->set_reference_type(REF_FINAL);
InstanceKlass::cast(WK_KLASS(PhantomReference_klass))->set_reference_type(REF_PHANTOM);
+ InstanceKlass::cast(WK_KLASS(Cleaner_klass))->set_reference_type(REF_CLEANER);
// JSR 292 classes
WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -128,6 +128,7 @@
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
+ do_klass(Cleaner_klass, sun_misc_Cleaner, Pre ) \
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
\
do_klass(Thread_klass, java_lang_Thread, Pre ) \
--- a/hotspot/src/share/vm/classfile/verifier.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1555,14 +1555,14 @@
case Bytecodes::_invokespecial :
case Bytecodes::_invokestatic :
verify_invoke_instructions(
- &bcs, code_length, ¤t_frame,
- &this_uninit, return_type, cp, CHECK_VERIFY(this));
+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokeinterface :
case Bytecodes::_invokedynamic :
verify_invoke_instructions(
- &bcs, code_length, ¤t_frame,
- &this_uninit, return_type, cp, CHECK_VERIFY(this));
+ &bcs, code_length, ¤t_frame, (bci >= ex_min && bci < ex_max),
+ &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_new :
{
@@ -2406,8 +2406,9 @@
void ClassVerifier::verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
- StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
- constantPoolHandle cp, TRAPS) {
+ StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+ bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+ TRAPS) {
u2 bci = bcs->bci();
VerificationType type = current_frame->pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
@@ -2423,28 +2424,36 @@
return;
}
- // Check if this call is done from inside of a TRY block. If so, make
- // sure that all catch clause paths end in a throw. Otherwise, this
- // can result in returning an incomplete object.
- ExceptionTable exhandlers(_method());
- int exlength = exhandlers.length();
- for(int i = 0; i < exlength; i++) {
- u2 start_pc = exhandlers.start_pc(i);
- u2 end_pc = exhandlers.end_pc(i);
+ // If this invokespecial call is done from inside of a TRY block then make
+ // sure that all catch clause paths end in a throw. Otherwise, this can
+ // result in returning an incomplete object.
+ if (in_try_block) {
+ ExceptionTable exhandlers(_method());
+ int exlength = exhandlers.length();
+ for(int i = 0; i < exlength; i++) {
+ u2 start_pc = exhandlers.start_pc(i);
+ u2 end_pc = exhandlers.end_pc(i);
- if (bci >= start_pc && bci < end_pc) {
- if (!ends_in_athrow(exhandlers.handler_pc(i))) {
- verify_error(ErrorContext::bad_code(bci),
- "Bad <init> method call from after the start of a try block");
- return;
- } else if (VerboseVerification) {
- ResourceMark rm;
- tty->print_cr(
- "Survived call to ends_in_athrow(): %s",
- current_class()->name()->as_C_string());
+ if (bci >= start_pc && bci < end_pc) {
+ if (!ends_in_athrow(exhandlers.handler_pc(i))) {
+ verify_error(ErrorContext::bad_code(bci),
+ "Bad <init> method call from after the start of a try block");
+ return;
+ } else if (VerboseVerification) {
+ ResourceMark rm;
+ tty->print_cr(
+ "Survived call to ends_in_athrow(): %s",
+ current_class()->name()->as_C_string());
+ }
}
}
- }
+
+ // Check the exception handler target stackmaps with the locals from the
+ // incoming stackmap (before initialize_object() changes them to outgoing
+ // state).
+ verify_exception_handler_targets(bci, true, current_frame,
+ stackmap_table, CHECK_VERIFY(this));
+ } // in_try_block
current_frame->initialize_object(type, current_type());
*this_uninit = true;
@@ -2498,6 +2507,13 @@
}
}
}
+ // Check the exception handler target stackmaps with the locals from the
+ // incoming stackmap (before initialize_object() changes them to outgoing
+ // state).
+ if (in_try_block) {
+ verify_exception_handler_targets(bci, *this_uninit, current_frame,
+ stackmap_table, CHECK_VERIFY(this));
+ }
current_frame->initialize_object(type, new_class_type);
} else {
verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()),
@@ -2526,8 +2542,8 @@
void ClassVerifier::verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
- bool *this_uninit, VerificationType return_type,
- constantPoolHandle cp, TRAPS) {
+ bool in_try_block, bool *this_uninit, VerificationType return_type,
+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
// Make sure the constant pool item is the right type
u2 index = bcs->get_index_u2();
Bytecodes::Code opcode = bcs->raw_code();
@@ -2693,7 +2709,8 @@
opcode != Bytecodes::_invokedynamic) {
if (method_name == vmSymbols::object_initializer_name()) { // <init> method
verify_invoke_init(bcs, index, ref_class_type, current_frame,
- code_length, this_uninit, cp, CHECK_VERIFY(this));
+ code_length, in_try_block, this_uninit, cp, stackmap_table,
+ CHECK_VERIFY(this));
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
--- a/hotspot/src/share/vm/classfile/verifier.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -301,8 +301,9 @@
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
- StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
- constantPoolHandle cp, TRAPS);
+ StackMapFrame* current_frame, u4 code_length, bool in_try_block,
+ bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+ TRAPS);
// Used by ends_in_athrow() to push all handlers that contain bci onto
// the handler_stack, if the handler is not already on the stack.
@@ -316,8 +317,8 @@
void verify_invoke_instructions(
RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
- bool* this_uninit, VerificationType return_type,
- constantPoolHandle cp, TRAPS);
+ bool in_try_block, bool* this_uninit, VerificationType return_type,
+ constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -79,6 +79,7 @@
template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \
+ template(sun_misc_Cleaner, "sun/misc/Cleaner") \
template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \
template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
--- a/hotspot/src/share/vm/code/dependencies.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -560,7 +560,7 @@
put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value());
} else if (arg.is_method()) {
what = "method ";
- put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value());
+ put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL);
} else if (arg.is_klass()) {
what = "class ";
} else {
@@ -878,8 +878,8 @@
// Static methods don't override non-static so punt
return true;
}
- if ( !Dependencies::is_concrete_method(lm)
- && !Dependencies::is_concrete_method(m)
+ if ( !Dependencies::is_concrete_method(lm, k)
+ && !Dependencies::is_concrete_method(m, ctxk)
&& lm->method_holder()->is_subtype_of(m->method_holder()))
// Method m is overridden by lm, but both are non-concrete.
return true;
@@ -915,8 +915,17 @@
} else if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
- Method* m = InstanceKlass::cast(k)->find_method(_name, _signature);
- if (m == NULL || !Dependencies::is_concrete_method(m)) return false;
+ // Search class hierarchy first.
+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+ if (!Dependencies::is_concrete_method(m, k)) {
+ // Check interface defaults also, if any exist.
+ Array<Method*>* default_methods = InstanceKlass::cast(k)->default_methods();
+ if (default_methods == NULL)
+ return false;
+ m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature);
+ if (!Dependencies::is_concrete_method(m, NULL))
+ return false;
+ }
_found_methods[_num_participants] = m;
// Note: If add_participant(k) is called,
// the method m will already be memoized for it.
@@ -1209,15 +1218,17 @@
return true;
}
-bool Dependencies::is_concrete_method(Method* m) {
- // Statics are irrelevant to virtual call sites.
- if (m->is_static()) return false;
-
- // We could also return false if m does not yet appear to be
- // executed, if the VM version supports this distinction also.
- // Default methods are considered "concrete" as well.
- return !m->is_abstract() &&
- !m->is_overpass(); // error functions aren't concrete
+bool Dependencies::is_concrete_method(Method* m, Klass * k) {
+ // NULL is not a concrete method,
+ // statics are irrelevant to virtual call sites,
+ // abstract methods are not concrete,
+ // overpass (error) methods are not concrete if k is abstract
+ //
+ // note "true" is conservative answer --
+ // overpass clause is false if k == NULL, implies return true if
+ // answer depends on overpass clause.
+ return ! ( m == NULL || m -> is_static() || m -> is_abstract() ||
+ m->is_overpass() && k != NULL && k -> is_abstract() );
}
@@ -1242,16 +1253,6 @@
return true;
}
-bool Dependencies::is_concrete_method(ciMethod* m) {
- // Statics are irrelevant to virtual call sites.
- if (m->is_static()) return false;
-
- // We could also return false if m does not yet appear to be
- // executed, if the VM version supports this distinction also.
- return !m->is_abstract();
-}
-
-
bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
return k->has_finalizable_subclass();
}
@@ -1469,7 +1470,7 @@
Klass* wit = wf.find_witness_definer(ctxk);
if (wit != NULL) return NULL; // Too many witnesses.
Method* fm = wf.found_method(0); // Will be NULL if num_parts == 0.
- if (Dependencies::is_concrete_method(m)) {
+ if (Dependencies::is_concrete_method(m, ctxk)) {
if (fm == NULL) {
// It turns out that m was always the only implementation.
fm = m;
@@ -1499,61 +1500,6 @@
return wf.find_witness_definer(ctxk, changes);
}
-// Find the set of all non-abstract methods under ctxk that match m[0].
-// (The method m[0] must be defined or inherited in ctxk.)
-// Include m itself in the set, unless it is abstract.
-// Fill the given array m[0..(mlen-1)] with this set, and return the length.
-// (The length may be zero if no concrete methods are found anywhere.)
-// If there are too many concrete methods to fit in marray, return -1.
-int Dependencies::find_exclusive_concrete_methods(Klass* ctxk,
- int mlen,
- Method* marray[]) {
- Method* m0 = marray[0];
- ClassHierarchyWalker wf(m0);
- assert(wf.check_method_context(ctxk, m0), "proper context");
- wf.record_witnesses(mlen);
- bool participants_hide_witnesses = true;
- Klass* wit = wf.find_witness_definer(ctxk);
- if (wit != NULL) return -1; // Too many witnesses.
- int num = wf.num_participants();
- assert(num <= mlen, "oob");
- // Keep track of whether m is also part of the result set.
- int mfill = 0;
- assert(marray[mfill] == m0, "sanity");
- if (Dependencies::is_concrete_method(m0))
- mfill++; // keep m0 as marray[0], the first result
- for (int i = 0; i < num; i++) {
- Method* fm = wf.found_method(i);
- if (fm == m0) continue; // Already put this guy in the list.
- if (mfill == mlen) {
- return -1; // Oops. Too many methods after all!
- }
- marray[mfill++] = fm;
- }
-#ifndef PRODUCT
- // Make sure the dependency mechanism will pass this discovery:
- if (VerifyDependencies) {
- // Turn off dependency tracing while actually testing deps.
- FlagSetting fs(TraceDependencies, false);
- switch (mfill) {
- case 1:
- guarantee(NULL == (void *)check_unique_concrete_method(ctxk, marray[0]),
- "verify dep.");
- break;
- case 2:
- guarantee(NULL == (void *)
- check_exclusive_concrete_methods(ctxk, marray[0], marray[1]),
- "verify dep.");
- break;
- default:
- ShouldNotReachHere(); // mlen > 2 yet supported
- }
- }
-#endif //PRODUCT
- return mfill;
-}
-
-
Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) {
Klass* search_at = ctxk;
if (changes != NULL)
@@ -1561,7 +1507,6 @@
return find_finalizable_subclass(search_at);
}
-
Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity");
assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
--- a/hotspot/src/share/vm/code/dependencies.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -288,7 +288,7 @@
// In that case, there would be a middle ground between concrete
// and abstract (as defined by the Java language and VM).
static bool is_concrete_klass(Klass* k); // k is instantiable
- static bool is_concrete_method(Method* m); // m is invocable
+ static bool is_concrete_method(Method* m, Klass* k); // m is invocable
static Klass* find_finalizable_subclass(Klass* k);
// These versions of the concreteness queries work through the CI.
@@ -302,7 +302,6 @@
// not go back into the VM to get their value; they must cache the
// bit in the CI, either eagerly or lazily.)
static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable
- static bool is_concrete_method(ciMethod* m); // m appears invocable
static bool has_finalizable_subclass(ciInstanceKlass* k);
// As a general rule, it is OK to compile under the assumption that
@@ -349,7 +348,6 @@
static Klass* find_unique_concrete_subtype(Klass* ctxk);
static Method* find_unique_concrete_method(Klass* ctxk, Method* m);
static int find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]);
- static int find_exclusive_concrete_methods(Klass* ctxk, int mlen, Method* m[]);
// Create the encoding which will be stored in an nmethod.
void encode_content_bytes();
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -252,7 +252,7 @@
} else {
task = new CompileTask();
DEBUG_ONLY(_num_allocated_tasks++;)
- assert (_num_allocated_tasks < 10000, "Leaking compilation tasks?");
+ assert (WhiteBoxAPI || _num_allocated_tasks < 10000, "Leaking compilation tasks?");
task->set_next(NULL);
task->set_is_free(true);
}
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -105,7 +105,6 @@
tty->print(".");
print_symbol(method_name(), _method_mode);
if (signature() != NULL) {
- tty->print(" ");
signature()->print_symbol_on(tty);
}
}
@@ -467,43 +466,85 @@
return UnknownCommand;
}
-
static void usage() {
- tty->print_cr(" CompileCommand and the CompilerOracle allows simple control over");
- tty->print_cr(" what's allowed to be compiled. The standard supported directives");
- tty->print_cr(" are exclude and compileonly. The exclude directive stops a method");
- tty->print_cr(" from being compiled and compileonly excludes all methods except for");
- tty->print_cr(" the ones mentioned by compileonly directives. The basic form of");
- tty->print_cr(" all commands is a command name followed by the name of the method");
- tty->print_cr(" in one of two forms: the standard class file format as in");
- tty->print_cr(" class/name.methodName or the PrintCompilation format");
- tty->print_cr(" class.name::methodName. The method name can optionally be followed");
- tty->print_cr(" by a space then the signature of the method in the class file");
- tty->print_cr(" format. Otherwise the directive applies to all methods with the");
- tty->print_cr(" same name and class regardless of signature. Leading and trailing");
- tty->print_cr(" *'s in the class and/or method name allows a small amount of");
- tty->print_cr(" wildcarding. ");
+ tty->cr();
+ tty->print_cr("The CompileCommand option enables the user of the JVM to control specific");
+ tty->print_cr("behavior of the dynamic compilers. Many commands require a pattern that defines");
+ tty->print_cr("the set of methods the command shall be applied to. The CompileCommand");
+ tty->print_cr("option provides the following commands:");
tty->cr();
- tty->print_cr(" Examples:");
+ tty->print_cr(" break,<pattern> - debug breakpoint in compiler and in generated code");
+ tty->print_cr(" print,<pattern> - print assembly");
+ tty->print_cr(" exclude,<pattern> - don't compile or inline");
+ tty->print_cr(" inline,<pattern> - always inline");
+ tty->print_cr(" dontinline,<pattern> - don't inline");
+ tty->print_cr(" compileonly,<pattern> - compile only");
+ tty->print_cr(" log,<pattern> - log compilation");
+ tty->print_cr(" option,<pattern>,<option type>,<option name>,<value>");
+ tty->print_cr(" - set value of custom option");
+ tty->print_cr(" option,<pattern>,<bool option name>");
+ tty->print_cr(" - shorthand for setting boolean flag");
+ tty->print_cr(" quiet - silence the compile command output");
+ tty->print_cr(" help - print this text");
+ tty->cr();
+ tty->print_cr("The preferred format for the method matching pattern is:");
+ tty->print_cr(" package/Class.method()");
+ tty->cr();
+ tty->print_cr("For backward compatibility this form is also allowed:");
+ tty->print_cr(" package.Class::method()");
+ tty->cr();
+ tty->print_cr("The signature can be separated by an optional whitespace or comma:");
+ tty->print_cr(" package/Class.method ()");
+ tty->cr();
+ tty->print_cr("The class and method identifier can be used together with leading or");
+ tty->print_cr("trailing *'s for a small amount of wildcarding:");
+ tty->print_cr(" *ackage/Clas*.*etho*()");
+ tty->cr();
+ tty->print_cr("It is possible to use more than one CompileCommand on the command line:");
+ tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*");
tty->cr();
- tty->print_cr(" exclude java/lang/StringBuffer.append");
- tty->print_cr(" compileonly java/lang/StringBuffer.toString ()Ljava/lang/String;");
- tty->print_cr(" exclude java/lang/String*.*");
- tty->print_cr(" exclude *.toString");
-}
-
+ tty->print_cr("The CompileCommands can be loaded from a file with the flag");
+ tty->print_cr("-XX:CompileCommandFile=<file> or be added to the file '.hotspot_compiler'");
+ tty->print_cr("Use the same format in the file as the argument to the CompileCommand flag.");
+ tty->print_cr("Add one command on each line.");
+ tty->print_cr(" exclude java/*.*");
+ tty->print_cr(" option java/*.* ReplayInline");
+ tty->cr();
+ tty->print_cr("The following commands have conflicting behavior: 'exclude', 'inline', 'dontinline',");
+ tty->print_cr("and 'compileonly'. There is no priority of commands. Applying (a subset of) these");
+ tty->print_cr("commands to the same method results in undefined behavior.");
+ tty->cr();
+};
-// The characters allowed in a class or method name. All characters > 0x7f
-// are allowed in order to handle obfuscated class files (e.g. Volano)
-#define RANGEBASE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$_<>" \
- "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
- "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
- "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
- "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
- "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
- "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
- "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" \
- "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+// The JVM specification defines the allowed characters.
+// Tokens that are disallowed by the JVM specification can have
+// a meaning to the parser so we need to include them here.
+// The parser does not enforce all rules of the JVMS - a successful parse
+// does not mean that it is an allowed name. Illegal names will
+// be ignored since they never can match a class or method.
+//
+// '\0' and 0xf0-0xff are disallowed in constant string values
+// 0x20 ' ', 0x09 '\t' and, 0x2c ',' are used in the matching
+// 0x5b '[' and 0x5d ']' can not be used because of the matcher
+// 0x28 '(' and 0x29 ')' are used for the signature
+// 0x2e '.' is always replaced before the matching
+// 0x2f '/' is only used in the class name as package separator
+
+#define RANGEBASE "\x1\x2\x3\x4\x5\x6\x7\x8\xa\xb\xc\xd\xe\xf" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x21\x22\x23\x24\x25\x26\x27\x2a\x2b\x2c\x2d" \
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" \
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5c\x5e\x5f" \
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" \
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" \
+ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" \
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" \
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf" \
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" \
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" \
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" \
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
#define RANGE0 "[*" RANGEBASE "]"
#define RANGESLASH "[*" RANGEBASE "/]"
@@ -681,8 +722,9 @@
if (command == UnknownCommand) {
ttyLocker ttyl;
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: unrecognized command");
tty->print_cr(" \"%s\"", original_line);
+ CompilerOracle::print_tip();
return;
}
@@ -712,9 +754,17 @@
Symbol* signature = NULL;
line += bytes_read;
+
+ // Skip any leading spaces before signature
+ int whitespace_read = 0;
+ sscanf(line, "%*[ \t]%n", &whitespace_read);
+ if (whitespace_read > 0) {
+ line += whitespace_read;
+ }
+
// there might be a signature following the method.
// signatures always begin with ( so match that by hand
- if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
+ if (1 == sscanf(line, "(%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
sig[0] = '(';
line += bytes_read;
signature = SymbolTable::new_symbol(sig, CHECK);
@@ -740,7 +790,7 @@
if (match != NULL && !_quiet) {
// Print out the last match added
ttyLocker ttyl;
- tty->print("CompilerOracle: %s ", command_names[command]);
+ tty->print("CompileCommand: %s ", command_names[command]);
match->print();
}
line += bytes_read;
@@ -775,26 +825,36 @@
ttyLocker ttyl;
if (error_msg != NULL) {
// an error has happened
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: An error occured during parsing");
tty->print_cr(" \"%s\"", original_line);
if (error_msg != NULL) {
tty->print_cr("%s", error_msg);
}
+ CompilerOracle::print_tip();
+
} else {
// check for remaining characters
bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (line[bytes_read] != '\0') {
- tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr("CompileCommand: Bad pattern");
tty->print_cr(" \"%s\"", original_line);
tty->print_cr(" Unrecognized text %s after command ", line);
+ CompilerOracle::print_tip();
} else if (match != NULL && !_quiet) {
- tty->print("CompilerOracle: %s ", command_names[command]);
+ tty->print("CompileCommand: %s ", command_names[command]);
match->print();
}
}
}
+void CompilerOracle::print_tip() {
+ tty->cr();
+ tty->print_cr("Usage: '-XX:CompileCommand=command,\"package/Class.method()\"'");
+ tty->print_cr("Use: '-XX:CompileCommand=help' for more information.");
+ tty->cr();
+}
+
static const char* default_cc_file = ".hotspot_compiler";
static const char* cc_file() {
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -34,6 +34,7 @@
class CompilerOracle : AllStatic {
private:
static bool _quiet;
+ static void print_tip();
public:
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -645,7 +645,7 @@
// Support for parallelizing survivor space rescan
if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) {
const size_t max_plab_samples =
- ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize;
+ ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size();
_survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
_survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
@@ -703,6 +703,12 @@
_inter_sweep_timer.start(); // start of time
}
+size_t CMSCollector::plab_sample_minimum_size() {
+ // The default value of MinTLABSize is 2k, but there is
+ // no way to get the default value if the flag has been overridden.
+ return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K);
+}
+
const char* ConcurrentMarkSweepGeneration::name() const {
return "concurrent mark-sweep generation";
}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -737,6 +737,10 @@
size_t* _cursor;
ChunkArray* _survivor_plab_array;
+ // A bounded minimum size of PLABs, should not return too small values since
+ // this will affect the size of the data structures used for parallel young gen rescan
+ size_t plab_sample_minimum_size();
+
// Support for marking stack overflow handling
bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack);
bool par_take_from_overflow_list(size_t num,
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1910,7 +1910,6 @@
}
void work(uint worker_id) {
- double start = os::elapsedTime();
FreeRegionList local_cleanup_list("Local Cleanup List");
HRRSCleanupTask hrrs_cleanup_task;
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,13 @@
// active field set to true.
PtrQueue(qset_, perm, true /* active */) { }
+ // Flush before destroying; queue may be used to capture pending work while
+ // doing something else, with auto-flush on completion.
+ ~DirtyCardQueue() { if (!is_permanent()) flush(); }
+
+ // Process queue entries and release resources.
+ void flush() { flush_impl(); }
+
// Apply the closure to all elements, and reset the index to make the
// buffer empty. If a closure application returns "false", return
// "false" immediately, halting the iteration. If "consume" is true,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1229,7 +1229,6 @@
TraceCollectorStats tcs(g1mm()->full_collection_counters());
TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
- double start = os::elapsedTime();
g1_policy()->record_full_collection_start();
// Note: When we have a more flexible GC logging framework that
@@ -1436,7 +1435,6 @@
_allocator->init_mutator_alloc_region();
- double end = os::elapsedTime();
g1_policy()->record_full_collection_end();
if (G1Log::fine()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -56,7 +56,6 @@
class GenerationSpec;
class OopsInHeapRegionClosure;
class G1KlassScanClosure;
-class G1ScanHeapEvacClosure;
class ObjectClosure;
class SpaceClosure;
class CompactibleSpaceClosure;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -153,14 +153,6 @@
_inc_cset_predicted_elapsed_time_ms(0.0),
_inc_cset_predicted_elapsed_time_ms_diffs(0.0),
-#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
-#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
-#endif // _MSC_VER
-
- _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived",
- G1YoungSurvRateNumRegionsSummary)),
- _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor",
- G1YoungSurvRateNumRegionsSummary)),
// add here any more surv rate groups
_recorded_survivor_regions(0),
_recorded_survivor_head(NULL),
@@ -169,6 +161,22 @@
_gc_overhead_perc(0.0) {
+ uintx confidence_perc = G1ConfidencePercent;
+ // Put an artificial ceiling on this so that it's not set to a silly value.
+ if (confidence_perc > 100) {
+ confidence_perc = 100;
+ warning("G1ConfidencePercent is set to a value that is too large, "
+ "it's been updated to %u", confidence_perc);
+ }
+ // '_sigma' must be initialized before the SurvRateGroups below because they
+ // indirecty access '_sigma' trough the 'this' pointer in their constructor.
+ _sigma = (double) confidence_perc / 100.0;
+
+ _short_lived_surv_rate_group =
+ new SurvRateGroup(this, "Short Lived", G1YoungSurvRateNumRegionsSummary);
+ _survivor_surv_rate_group =
+ new SurvRateGroup(this, "Survivor", G1YoungSurvRateNumRegionsSummary);
+
// Set up the region size and associated fields. Given that the
// policy is created before the heap, we have to set this up here,
// so it's done as soon as possible.
@@ -283,15 +291,6 @@
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
- uintx confidence_perc = G1ConfidencePercent;
- // Put an artificial ceiling on this so that it's not set to a silly value.
- if (confidence_perc > 100) {
- confidence_perc = 100;
- warning("G1ConfidencePercent is set to a value that is too large, "
- "it's been updated to %u", confidence_perc);
- }
- _sigma = (double) confidence_perc / 100.0;
-
// start conservatively (around 50ms is about right)
_concurrent_mark_remark_times_ms->add(0.05);
_concurrent_mark_cleanup_times_ms->add(0.20);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -46,9 +46,6 @@
class G1PrepareCompactClosure;
class G1MarkSweep : AllStatic {
- friend class VM_G1MarkSweep;
- friend class Scavenge;
-
public:
static void invoke_at_safepoint(ReferenceProcessor* rp,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -45,7 +45,8 @@
#include "utilities/bitMap.inline.hpp"
G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL),
- _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) {
+ _high_boundary(NULL), _committed(), _page_size(0), _special(false),
+ _dirty(), _executable(false) {
}
bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
@@ -66,6 +67,9 @@
assert(_committed.size() == 0, "virtual space initialized more than once");
uintx size_in_bits = rs.size() / page_size;
_committed.resize(size_in_bits, /* in_resource_area */ false);
+ if (_special) {
+ _dirty.resize(size_in_bits, /* in_resource_area */ false);
+ }
return true;
}
@@ -84,6 +88,7 @@
_executable = false;
_page_size = 0;
_committed.resize(0, false);
+ _dirty.resize(0, false);
}
size_t G1PageBasedVirtualSpace::committed_size() const {
@@ -120,34 +125,43 @@
return num * _page_size;
}
-MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
+bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
// We need to make sure to commit all pages covered by the given area.
guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
- if (!_special) {
+ bool zero_filled = true;
+ uintptr_t end = start + size_in_pages;
+
+ if (_special) {
+ // Check for dirty pages and update zero_filled if any found.
+ if (_dirty.get_next_one_offset(start,end) < end) {
+ zero_filled = false;
+ _dirty.clear_range(start, end);
+ }
+ } else {
os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable,
err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
}
- _committed.set_range(start, start + size_in_pages);
+ _committed.set_range(start, end);
- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
if (AlwaysPreTouch) {
- os::pretouch_memory((char*)result.start(), (char*)result.end());
+ os::pretouch_memory(page_start(start), page_start(end));
}
- return result;
+ return zero_filled;
}
-MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
+void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
guarantee(is_area_committed(start, size_in_pages), "checking");
- if (!_special) {
+ if (_special) {
+ // Mark that memory is dirty. If committed again the memory might
+ // need to be cleared explicitly.
+ _dirty.set_range(start, start + size_in_pages);
+ } else {
os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
}
_committed.clear_range(start, start + size_in_pages);
-
- MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
- return result;
}
bool G1PageBasedVirtualSpace::contains(const void* p) const {
@@ -157,7 +171,7 @@
#ifndef PRODUCT
void G1PageBasedVirtualSpace::print_on(outputStream* out) {
out->print ("Virtual space:");
- if (special()) out->print(" (pinned in memory)");
+ if (_special) out->print(" (pinned in memory)");
out->cr();
out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
--- a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -49,6 +49,12 @@
// Bitmap used for verification of commit/uncommit operations.
BitMap _committed;
+ // Bitmap used to keep track of which pages are dirty or not for _special
+ // spaces. This is needed because for those spaces the underlying memory
+ // will only be zero filled the first time it is committed. Calls to commit
+ // will use this bitmap and return whether or not the memory is zero filled.
+ BitMap _dirty;
+
// Indicates that the entire space has been committed and pinned in memory,
// os::commit_memory() or os::uncommit_memory() have no function.
bool _special;
@@ -71,12 +77,11 @@
public:
// Commit the given area of pages starting at start being size_in_pages large.
- MemRegion commit(uintptr_t start, size_t size_in_pages);
+ // Returns true if the given area is zero filled upon completion.
+ bool commit(uintptr_t start, size_t size_in_pages);
// Uncommit the given area of pages starting at start being size_in_pages large.
- MemRegion uncommit(uintptr_t start, size_t size_in_pages);
-
- bool special() const { return _special; }
+ void uncommit(uintptr_t start, size_t size_in_pages);
// Initialization
G1PageBasedVirtualSpace();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -67,9 +67,9 @@
}
virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
- _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
+ bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
_commit_map.set_range(start_idx, start_idx + num_regions);
- fire_on_commit(start_idx, num_regions, true);
+ fire_on_commit(start_idx, num_regions, zero_filled);
}
virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
@@ -117,8 +117,7 @@
uint old_refcount = _refcounts.get_by_index(idx);
bool zero_filled = false;
if (old_refcount == 0) {
- _storage.commit(idx, 1);
- zero_filled = true;
+ zero_filled = _storage.commit(idx, 1);
}
_refcounts.set_by_index(idx, old_refcount + 1);
_commit_map.set_bit(i);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -31,7 +31,6 @@
// collection set.
class G1CollectedHeap;
-class CardTableModRefBarrierSet;
class ConcurrentG1Refine;
class G1ParPushHeapRSClosure;
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -31,11 +31,15 @@
#include "runtime/thread.inline.hpp"
PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
- _qset(qset), _buf(NULL), _index(0), _active(active),
+ _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active),
_perm(perm), _lock(NULL)
{}
-void PtrQueue::flush() {
+PtrQueue::~PtrQueue() {
+ assert(_perm || (_buf == NULL), "queue must be flushed before delete");
+}
+
+void PtrQueue::flush_impl() {
if (!_perm && _buf != NULL) {
if (_index == _sz) {
// No work to do.
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,15 +65,18 @@
Mutex* _lock;
PtrQueueSet* qset() { return _qset; }
+ bool is_permanent() const { return _perm; }
+
+ // Process queue entries and release resources, if not permanent.
+ void flush_impl();
public:
// Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet.
PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
- // Release any contained resources.
- virtual void flush();
- // Calls flush() when destroyed.
- ~PtrQueue() { flush(); }
+
+ // Requires queue flushed or permanent.
+ ~PtrQueue();
// Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; }
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -39,7 +39,7 @@
// first before we flush it, otherwise we might end up with an
// enqueued buffer with refs into the CSet which breaks our invariants.
filter();
- PtrQueue::flush();
+ flush_impl();
}
// This method removes entries from an SATB buffer that will not be
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,9 +60,8 @@
// field to true. This is done in JavaThread::initialize_queues().
PtrQueue(qset, perm, false /* active */) { }
- // Overrides PtrQueue::flush() so that it can filter the buffer
- // before it is flushed.
- virtual void flush();
+ // Process queue entries and free resources.
+ void flush();
// Overrides PtrQueue::should_enqueue_buffer(). See the method's
// definition for more information.
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -63,7 +63,8 @@
virtual ~ParGCAllocBuffer() {}
static const size_t min_size() {
- return ThreadLocalAllocBuffer::min_size();
+ // Make sure that we return something that is larger than AlignmentReserve
+ return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve;
}
static const size_t max_size() {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -320,7 +320,7 @@
// First check in default method array
if (!resolved_method->is_abstract() &&
(InstanceKlass::cast(klass())->default_methods() != NULL)) {
- int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false);
+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false, false);
if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
}
--- a/hotspot/src/share/vm/memory/heap.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/heap.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -279,10 +279,12 @@
return sizeof(HeapBlock) & (_segment_size - 1);
}
-// Finds the next free heapblock. If the current one is free, that it returned
-void* CodeHeap::next_free(HeapBlock* b) const {
- // Since free blocks are merged, there is max. on free block
- // between two used ones
+// Returns the current block if available and used.
+// If not, it returns the subsequent block (if available), NULL otherwise.
+// Free blocks are merged, therefore there is at most one free block
+// between two used ones. As a result, the subsequent block (if available) is
+// guaranteed to be used.
+void* CodeHeap::next_used(HeapBlock* b) const {
if (b != NULL && b->free()) b = next_block(b);
assert(b == NULL || !b->free(), "must be in use or at end of heap");
return (b == NULL) ? NULL : b->allocated_space();
--- a/hotspot/src/share/vm/memory/heap.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/heap.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -123,7 +123,7 @@
FreeBlock* search_freelist(size_t length);
// Iteration helpers
- void* next_free(HeapBlock* b) const;
+ void* next_used(HeapBlock* b) const;
HeapBlock* first_block() const;
HeapBlock* next_block(HeapBlock* b) const;
HeapBlock* block_start(void* p) const;
@@ -158,9 +158,9 @@
int freelist_length() const { return _freelist_length; } // number of elements in the freelist
// returns the first block or NULL
- void* first() const { return next_free(first_block()); }
+ void* first() const { return next_used(first_block()); }
// returns the next block given a block p or NULL
- void* next(void* p) const { return next_free(next_block(block_start(p))); }
+ void* next(void* p) const { return next_used(next_block(block_start(p))); }
// Statistics
size_t capacity() const;
--- a/hotspot/src/share/vm/memory/metaspace.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -3170,7 +3170,9 @@
}
// the min_misc_data_size and min_misc_code_size estimates are based on
- // MetaspaceShared::generate_vtable_methods()
+ // MetaspaceShared::generate_vtable_methods().
+ // The minimum size only accounts for the vtable methods. Any size less than the
+ // minimum required size would cause vm crash when allocating the vtable methods.
uint min_misc_data_size = align_size_up(
MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment);
@@ -3336,6 +3338,10 @@
Metachunk* new_chunk = get_initialization_chunk(NonClassType,
word_size,
vsm()->medium_chunk_bunch());
+ // For dumping shared archive, report error if allocation has failed.
+ if (DumpSharedSpaces && new_chunk == NULL) {
+ report_insufficient_metaspace(MetaspaceAux::committed_bytes() + word_size * BytesPerWord);
+ }
assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks");
if (new_chunk != NULL) {
// Add to this manager's list of chunks in use and current_chunk().
@@ -3349,6 +3355,11 @@
class_vsm()->medium_chunk_bunch());
if (class_chunk != NULL) {
class_vsm()->add_chunk(class_chunk, true);
+ } else {
+ // For dumping shared archive, report error if allocation has failed.
+ if (DumpSharedSpaces) {
+ report_insufficient_metaspace(MetaspaceAux::committed_bytes() + class_word_size * BytesPerWord);
+ }
}
}
@@ -3829,11 +3840,13 @@
assert(cm.sum_free_chunks() == 2*MediumChunk, "sizes should add up");
}
- { // 4 pages of VSN is committed, some is used by chunks
+ const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
+ // This doesn't work for systems with vm_page_size >= 16K.
+ if (page_chunks < MediumChunk) {
+ // 4 pages of VSN is committed, some is used by chunks
ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
VirtualSpaceNode vsn(vsn_test_size_bytes);
- const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
- assert(page_chunks < MediumChunk, "Test expects medium chunks to be at least 4*page_size");
+
vsn.initialize();
vsn.expand_by(page_chunks, page_chunks);
vsn.get_chunk_vs(SmallChunk);
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -118,6 +118,7 @@
_discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q];
_discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q];
_discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q];
+ _discoveredCleanerRefs = &_discoveredPhantomRefs[_max_num_q];
// Initialize all entries to NULL
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
@@ -246,6 +247,13 @@
phantom_count =
process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
is_alive, keep_alive, complete_gc, task_executor);
+
+ // Process cleaners, but include them in phantom statistics. We expect
+ // Cleaner references to be temporary, and don't want to deal with
+ // possible incompatibilities arising from making it more visible.
+ phantom_count +=
+ process_discovered_reflist(_discoveredCleanerRefs, NULL, false,
+ is_alive, keep_alive, complete_gc, task_executor);
}
// Weak global JNI references. It would make more sense (semantically) to
@@ -885,6 +893,7 @@
balance_queues(_discoveredWeakRefs);
balance_queues(_discoveredFinalRefs);
balance_queues(_discoveredPhantomRefs);
+ balance_queues(_discoveredCleanerRefs);
}
size_t
@@ -998,6 +1007,9 @@
case REF_PHANTOM:
list = &_discoveredPhantomRefs[id];
break;
+ case REF_CLEANER:
+ list = &_discoveredCleanerRefs[id];
+ break;
case REF_NONE:
// we should not reach here if we are an InstanceRefKlass
default:
@@ -1263,6 +1275,17 @@
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
+
+ // Cleaner references. Included in timing for phantom references. We
+ // expect Cleaner references to be temporary, and don't want to deal with
+ // possible incompatibilities arising from making it more visible.
+ for (uint i = 0; i < _max_num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
+ preclean_discovered_reflist(_discoveredCleanerRefs[i], is_alive,
+ keep_alive, complete_gc, yield);
+ }
}
}
@@ -1331,6 +1354,7 @@
case 1: return "WeakRef";
case 2: return "FinalRef";
case 3: return "PhantomRef";
+ case 4: return "CleanerRef";
}
ShouldNotReachHere();
return NULL;
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -264,9 +264,10 @@
DiscoveredList* _discoveredWeakRefs;
DiscoveredList* _discoveredFinalRefs;
DiscoveredList* _discoveredPhantomRefs;
+ DiscoveredList* _discoveredCleanerRefs;
public:
- static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); }
+ static int number_of_subclasses_of_ref() { return (REF_CLEANER - REF_OTHER); }
uint num_q() { return _num_q; }
uint max_num_q() { return _max_num_q; }
--- a/hotspot/src/share/vm/memory/referenceType.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/referenceType.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -35,7 +35,8 @@
REF_SOFT, // Subclass of java/lang/ref/SoftReference
REF_WEAK, // Subclass of java/lang/ref/WeakReference
REF_FINAL, // Subclass of java/lang/ref/FinalReference
- REF_PHANTOM // Subclass of java/lang/ref/PhantomReference
+ REF_PHANTOM, // Subclass of java/lang/ref/PhantomReference
+ REF_CLEANER // Subclass of sun/misc/Cleaner
};
#endif // SHARE_VM_MEMORY_REFRERENCETYPE_HPP
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -235,22 +235,19 @@
}
size_t ThreadLocalAllocBuffer::initial_desired_size() {
- size_t init_sz;
+ size_t init_sz = 0;
if (TLABSize > 0) {
- init_sz = MIN2(TLABSize / HeapWordSize, max_size());
- } else if (global_stats() == NULL) {
- // Startup issue - main thread initialized before heap initialized.
- init_sz = min_size();
- } else {
+ init_sz = TLABSize / HeapWordSize;
+ } else if (global_stats() != NULL) {
// Initial size is a function of the average number of allocating threads.
unsigned nof_threads = global_stats()->allocating_threads_avg();
init_sz = (Universe::heap()->tlab_capacity(myThread()) / HeapWordSize) /
(nof_threads * target_refills());
init_sz = align_object_size(init_sz);
- init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
}
+ init_sz = MIN2(MAX2(init_sz, min_size()), max_size());
return init_sz;
}
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -106,7 +106,7 @@
// do nothing. tlabs must be inited by initialize() calls
}
- static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize); }
+ static const size_t min_size() { return align_object_size(MinTLABSize / HeapWordSize) + alignment_reserve(); }
static const size_t max_size() { assert(_max_size != 0, "max_size not set up"); return _max_size; }
static void set_max_size(size_t max_size) { _max_size = max_size; }
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1420,32 +1420,41 @@
}
Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const {
- return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass);
+ return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false);
}
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
Method* InstanceKlass::find_instance_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- Method* meth = InstanceKlass::find_method(methods, name, signature);
- if (meth != NULL && meth->is_static()) {
- meth = NULL;
- }
+ Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true);
return meth;
}
+// find_instance_method looks up the name/signature in the local methods array
+// and skips over static methods
+Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) {
+ return InstanceKlass::find_instance_method(methods(), name, signature);
+}
+
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- return InstanceKlass::find_method_impl(methods, name, signature, false);
+ return InstanceKlass::find_method_impl(methods, name, signature, false, false);
}
Method* InstanceKlass::find_method_impl(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
- int hit = find_method_index(methods, name, signature, skipping_overpass);
+ Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+ int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static);
return hit >= 0 ? methods->at(hit): NULL;
}
+bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+ return (m->signature() == signature) &&
+ (!skipping_overpass || !m->is_overpass()) &&
+ (!skipping_static || !m->is_static());
+}
+
// Used directly for default_methods to find the index into the
// default_vtable_indices, and indirectly by find_method
// find_method_index looks in the local methods array to return the index
@@ -1454,13 +1463,14 @@
// is important during method resolution to prefer a static method, for example,
// over an overpass method.
int InstanceKlass::find_method_index(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass) {
+ Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
+
// Do linear search to find matching signature. First, quick check
// for common case, ignoring overpasses if requested.
- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return hit;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit;
// search downwards through overloaded methods
int i;
@@ -1468,18 +1478,18 @@
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
}
// search upwards
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
- if ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass())) return i;
+ if (method_matches(m, signature, skipping_overpass, skipping_static)) return i;
}
// not found
#ifdef ASSERT
- int index = skipping_overpass ? -1 : linear_search(methods, name, signature);
+ int index = skipping_overpass || skipping_static ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -490,10 +490,16 @@
// find a local method (returns NULL if not found)
Method* find_method(Symbol* name, Symbol* signature) const;
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+
+ // find a local method, but skip static methods
+ Method* find_instance_method(Symbol* name, Symbol* signature);
static Method* find_instance_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
+ // true if method matches signature and conforms to skipping_X conditions.
+ static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
+
// find a local method index in default_methods (returns -1 if not found)
- static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+ static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// lookup operation (returns NULL if not found)
Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
@@ -1053,7 +1059,7 @@
// find a local method (returns NULL if not found)
Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const;
- static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass);
+ static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
// Free CHeap allocated fields.
void release_C_heap_structures();
--- a/hotspot/src/share/vm/opto/cfgnode.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/opto/cfgnode.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -361,22 +361,36 @@
#endif
};
-class IfTrueNode : public CProjNode {
+class IfProjNode : public CProjNode {
public:
- IfTrueNode( IfNode *ifnode ) : CProjNode(ifnode,1) {
+ IfProjNode(IfNode *ifnode, uint idx) : CProjNode(ifnode,idx) {}
+ virtual Node *Identity(PhaseTransform *phase);
+
+protected:
+ // Type of If input when this branch is always taken
+ virtual bool always_taken(const TypeTuple* t) const = 0;
+};
+
+class IfTrueNode : public IfProjNode {
+public:
+ IfTrueNode( IfNode *ifnode ) : IfProjNode(ifnode,1) {
init_class_id(Class_IfTrue);
}
virtual int Opcode() const;
- virtual Node *Identity( PhaseTransform *phase );
+
+protected:
+ virtual bool always_taken(const TypeTuple* t) const { return t == TypeTuple::IFTRUE; }
};
-class IfFalseNode : public CProjNode {
+class IfFalseNode : public IfProjNode {
public:
- IfFalseNode( IfNode *ifnode ) : CProjNode(ifnode,0) {
+ IfFalseNode( IfNode *ifnode ) : IfProjNode(ifnode,0) {
init_class_id(Class_IfFalse);
}
virtual int Opcode() const;
- virtual Node *Identity( PhaseTransform *phase );
+
+protected:
+ virtual bool always_taken(const TypeTuple* t) const { return t == TypeTuple::IFFALSE; }
};
--- a/hotspot/src/share/vm/opto/ifnode.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1122,12 +1122,21 @@
//------------------------------Identity---------------------------------------
// If the test is constant & we match, then we are the input Control
-Node *IfTrueNode::Identity( PhaseTransform *phase ) {
+Node *IfProjNode::Identity(PhaseTransform *phase) {
// Can only optimize if cannot go the other way
const TypeTuple *t = phase->type(in(0))->is_tuple();
- return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFTRUE )
- ? in(0)->in(0) // IfNode control
- : this; // no progress
+ if (t == TypeTuple::IFNEITHER ||
+ // kill dead branch first otherwise the IfNode's control will
+ // have 2 control uses (the IfNode that doesn't go away because
+ // it still has uses and this branch of the
+ // If). Node::has_special_unique_user() will cause this node to
+ // be reprocessed once the dead branch is killed.
+ (always_taken(t) && in(0)->outcnt() == 1)) {
+ // IfNode control
+ return in(0)->in(0);
+ }
+ // no progress
+ return this;
}
//------------------------------dump_spec--------------------------------------
@@ -1195,13 +1204,3 @@
// Progress
return iff;
}
-
-//------------------------------Identity---------------------------------------
-// If the test is constant & we match, then we are the input Control
-Node *IfFalseNode::Identity( PhaseTransform *phase ) {
- // Can only optimize if cannot go the other way
- const TypeTuple *t = phase->type(in(0))->is_tuple();
- return ( t == TypeTuple::IFNEITHER || t == TypeTuple::IFFALSE )
- ? in(0)->in(0) // IfNode control
- : this; // no progress
-}
--- a/hotspot/src/share/vm/opto/node.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/opto/node.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1080,18 +1080,21 @@
assert(outcnt() == 1, "match only for unique out");
Node* n = unique_out();
int op = Opcode();
- if( this->is_Store() ) {
+ if (this->is_Store()) {
// Condition for back-to-back stores folding.
return n->Opcode() == op && n->in(MemNode::Memory) == this;
} else if (this->is_Load()) {
// Condition for removing an unused LoadNode from the MemBarAcquire precedence input
return n->Opcode() == Op_MemBarAcquire;
- } else if( op == Op_AddL ) {
+ } else if (op == Op_AddL) {
// Condition for convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y))
return n->Opcode() == Op_ConvL2I && n->in(1) == this;
- } else if( op == Op_SubI || op == Op_SubL ) {
+ } else if (op == Op_SubI || op == Op_SubL) {
// Condition for subI(x,subI(y,z)) ==> subI(addI(x,z),y)
return n->Opcode() == op && n->in(2) == this;
+ } else if (is_If() && (n->is_IfFalse() || n->is_IfTrue())) {
+ // See IfProjNode::Identity()
+ return true;
}
return false;
};
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -2951,10 +2951,6 @@
develop(intx, MallocCatchPtr, -1, \
"Hit breakpoint when mallocing/freeing this pointer") \
\
- notproduct(intx, AssertRepeat, 1, \
- "number of times to evaluate expression in assert " \
- "(to estimate overhead); only works with -DUSE_REPEATED_ASSERTS") \
- \
notproduct(ccstrlist, SuppressErrorAt, "", \
"List of assertions (file:line) to muzzle") \
\
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -547,20 +547,16 @@
// This function supports testing of the malloc out of memory
// condition without really running the system out of memory.
//
-static u_char* testMalloc(size_t alloc_size) {
- assert(MallocMaxTestWords > 0, "sanity check");
-
- if ((cur_malloc_words + (alloc_size / BytesPerWord)) > MallocMaxTestWords) {
- return NULL;
- }
+static bool has_reached_max_malloc_test_peak(size_t alloc_size) {
+ if (MallocMaxTestWords > 0) {
+ jint words = (jint)(alloc_size / BytesPerWord);
- u_char* ptr = (u_char*)::malloc(alloc_size);
-
- if (ptr != NULL) {
- Atomic::add(((jint) (alloc_size / BytesPerWord)),
- (volatile jint *) &cur_malloc_words);
+ if ((cur_malloc_words + words) > MallocMaxTestWords) {
+ return true;
+ }
+ Atomic::add(words, (volatile jint *)&cur_malloc_words);
}
- return ptr;
+ return false;
}
void* os::malloc(size_t size, MEMFLAGS flags) {
@@ -608,12 +604,13 @@
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
+ // For the test flag -XX:MallocMaxTestWords
+ if (has_reached_max_malloc_test_peak(size)) {
+ return NULL;
+ }
+
u_char* ptr;
- if (MallocMaxTestWords > 0) {
- ptr = testMalloc(alloc_size);
- } else {
- ptr = (u_char*)::malloc(alloc_size);
- }
+ ptr = (u_char*)::malloc(alloc_size);
#ifdef ASSERT
if (ptr == NULL) {
@@ -642,6 +639,11 @@
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
+ // For the test flag -XX:MallocMaxTestWords
+ if (has_reached_max_malloc_test_peak(size)) {
+ return NULL;
+ }
+
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -661,6 +661,7 @@
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(FinalReference_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), Klass*) \
+ static_field(SystemDictionary, WK_KLASS(Cleaner_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Finalizer_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(Thread_klass), Klass*) \
static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), Klass*) \
--- a/hotspot/src/share/vm/shark/llvmHeaders.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/shark/llvmHeaders.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -87,30 +87,7 @@
#undef assert
#endif
-// from hotspot/src/share/vm/utilities/debug.hpp
-#ifdef ASSERT
-#ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg) \
-do { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
-} while (0)
-#else // #ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg)
-do { \
- for (int __i = 0; __i < AssertRepeat; __i++) { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
- } \
-} while (0)
-#endif // #ifndef USE_REPEATED_ASSERTS
-#else
- #define assert(p, msg)
-#endif
+#define assert(p, msg) vmassert(p, msg)
#ifdef DEBUG
#undef DEBUG
--- a/hotspot/src/share/vm/utilities/debug.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/debug.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -273,6 +273,14 @@
exit(2);
}
+void report_insufficient_metaspace(size_t required_size) {
+ warning("\nThe MaxMetaspaceSize of " UINTX_FORMAT " bytes is not large enough.\n"
+ "Either don't specify the -XX:MaxMetaspaceSize=<size>\n"
+ "or increase the size to at least " SIZE_FORMAT ".\n",
+ MaxMetaspaceSize, required_size);
+ exit(2);
+}
+
void report_java_out_of_memory(const char* message) {
static jint out_of_memory_reported = 0;
@@ -326,9 +334,9 @@
// Keep this in sync with test/runtime/6888954/vmerrors.sh.
switch (n) {
- case 1: assert(str == NULL, "expected null");
- case 2: assert(num == 1023 && *str == 'X',
- err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
+ case 1: vmassert(str == NULL, "expected null");
+ case 2: vmassert(num == 1023 && *str == 'X',
+ err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
case 3: guarantee(str == NULL, "expected null");
case 4: guarantee(num == 1023 && *str == 'X',
err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str));
--- a/hotspot/src/share/vm/utilities/debug.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/debug.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -105,58 +105,42 @@
va_end(argp);
}
-// Used to format messages for assert(), guarantee(), fatal(), etc.
+// Used to format messages for vmassert(), guarantee(), fatal(), etc.
typedef FormatBuffer<> err_msg;
typedef FormatBufferResource err_msg_res;
// assertions
-#ifdef ASSERT
-#ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg) \
+#ifndef ASSERT
+#define vmassert(p, msg)
+#else
+// Note: message says "assert" rather than "vmassert" for backward
+// compatibility with tools that parse/match the message text.
+#define vmassert(p, msg) \
do { \
if (!(p)) { \
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
BREAKPOINT; \
} \
} while (0)
-#else // #ifndef USE_REPEATED_ASSERTS
-#define assert(p, msg)
-do { \
- for (int __i = 0; __i < AssertRepeat; __i++) { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", msg); \
- BREAKPOINT; \
- } \
- } \
-} while (0)
-#endif // #ifndef USE_REPEATED_ASSERTS
+#endif
-// This version of assert is for use with checking return status from
+// For backward compatibility.
+#define assert(p, msg) vmassert(p, msg)
+
+// This version of vmassert is for use with checking return status from
// library calls that return actual error values eg. EINVAL,
// ENOMEM etc, rather than returning -1 and setting errno.
// When the status is not what is expected it is very useful to know
// what status was actually returned, so we pass the status variable as
// an extra arg and use strerror to convert it to a meaningful string
// like "Invalid argument", "out of memory" etc
-#define assert_status(p, status, msg) \
-do { \
- if (!(p)) { \
- report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", \
- err_msg("error %s(%d) %s", strerror(status), \
- status, msg)); \
- BREAKPOINT; \
- } \
-} while (0)
+#define vmassert_status(p, status, msg) \
+ vmassert(p, err_msg("error %s(%d), %s", strerror(status), status, msg))
-// Do not assert this condition if there's already another error reported.
-#define assert_if_no_error(cond,msg) assert((cond) || is_error_reported(), msg)
-#else // #ifdef ASSERT
- #define assert(p,msg)
- #define assert_status(p,status,msg)
- #define assert_if_no_error(cond,msg)
-#endif // #ifdef ASSERT
+// For backward compatibility.
+#define assert_status(p, status, msg) vmassert_status(p, status, msg)
-// guarantee is like assert except it's always executed -- use it for
+// guarantee is like vmassert except it's always executed -- use it for
// cheap tests that catch errors that would otherwise be hard to find.
// guarantee is also used for Verify options.
#define guarantee(p, msg) \
@@ -225,21 +209,22 @@
void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2);
-#ifdef ASSERT
-// Compile-time asserts.
-template <bool> struct StaticAssert;
-template <> struct StaticAssert<true> {};
+// Compile-time asserts. Cond must be a compile-time constant expression that
+// is convertible to bool. STATIC_ASSERT() can be used anywhere a declaration
+// may appear.
+//
+// Implementation Note: STATIC_ASSERT_FAILURE<true> provides a value member
+// rather than type member that could be used directly in the typedef, because
+// a type member would require conditional use of "typename", depending on
+// whether Cond is dependent or not. The use of a value member leads to the
+// use of an array type.
-// Only StaticAssert<true> is defined, so if cond evaluates to false we get
-// a compile time exception when trying to use StaticAssert<false>.
-#define STATIC_ASSERT(cond) \
- do { \
- StaticAssert<(cond)> DUMMY_STATIC_ASSERT; \
- (void)DUMMY_STATIC_ASSERT; /* ignore */ \
- } while (false)
-#else
-#define STATIC_ASSERT(cond)
-#endif
+template<bool x> struct STATIC_ASSERT_FAILURE;
+template<> struct STATIC_ASSERT_FAILURE<true> { enum { value = 1 }; };
+
+#define STATIC_ASSERT(Cond) \
+ typedef char STATIC_ASSERT_FAILURE_ ## __LINE__ [ \
+ STATIC_ASSERT_FAILURE< (Cond) >::value ]
// out of shared space reporting
enum SharedSpaceType {
@@ -251,6 +236,8 @@
void report_out_of_shared_space(SharedSpaceType space_type);
+void report_insufficient_metaspace(size_t required_size);
+
// out of memory reporting
void report_java_out_of_memory(const char* message);
@@ -258,7 +245,7 @@
bool is_error_reported();
void set_error_reported();
-/* Test assert(), fatal(), guarantee(), etc. */
+/* Test vmassert(), fatal(), guarantee(), etc. */
NOT_PRODUCT(void test_error_handler();)
void pd_ps(frame f);
--- a/hotspot/src/share/vm/utilities/defaultStream.hpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/defaultStream.hpp Mon Jan 26 17:00:39 2015 -0800
@@ -41,6 +41,8 @@
void init();
void init_log();
+ fileStream* open_file(const char* log_name);
+ void start_log();
void finish_log();
void finish_log_on_error(char *buf, int buflen);
public:
--- a/hotspot/src/share/vm/utilities/ostream.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/ostream.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -367,7 +367,6 @@
#define EXTRACHARLEN 32
#define CURRENTAPPX ".current"
-#define FILENAMEBUFLEN 1024
// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS
char* get_datetime_string(char *buf, size_t len) {
os::local_time_string(buf, len);
@@ -401,7 +400,6 @@
buffer_length = strlen(log_name) + 1;
}
- // const char* star = strchr(basename, '*');
const char* pts = strstr(basename, "%p");
int pid_pos = (pts == NULL) ? -1 : (pts - nametail);
@@ -416,6 +414,11 @@
buffer_length += strlen(tms);
}
+ // File name is too long.
+ if (buffer_length > JVM_MAXPATHLEN) {
+ return NULL;
+ }
+
// Create big enough buffer.
char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
@@ -489,46 +492,88 @@
void test_loggc_filename() {
int pid;
char tms[32];
- char i_result[FILENAMEBUFLEN];
+ char i_result[JVM_MAXPATHLEN];
const char* o_result;
get_datetime_string(tms, sizeof(tms));
pid = os::current_process_id();
// test.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test.log", tms);
o_result = make_log_name_internal("test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// test-%t-%p.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%s-pid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// test-%t%p.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "test-%spid%u.log", tms, pid);
o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %p%t.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u%s.log", pid, tms);
o_result = make_log_name_internal("%p%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %p-test.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "pid%u-test.log", pid);
o_result = make_log_name_internal("%p-test.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
// %t.log
- jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms);
+ jio_snprintf(i_result, JVM_MAXPATHLEN, "%s.log", tms);
o_result = make_log_name_internal("%t.log", NULL, pid, tms);
assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)");
FREE_C_HEAP_ARRAY(char, o_result);
+
+ {
+ // longest filename
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', sizeof(longest_name));
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(strcmp(longest_name, o_result) == 0, err_msg("longest name does not match. expected '%s' but got '%s'", longest_name, o_result));
+ FREE_C_HEAP_ARRAY(char, o_result);
+ }
+
+ {
+ // too long file name
+ char too_long_name[JVM_MAXPATHLEN + 100];
+ int too_long_length = sizeof(too_long_name);
+ memset(too_long_name, 'a', too_long_length);
+ too_long_name[too_long_length - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&too_long_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name should return NULL, but got '%s'", o_result));
+ }
+
+ {
+ // too long with timestamp
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', JVM_MAXPATHLEN);
+ longest_name[JVM_MAXPATHLEN - 3] = '%';
+ longest_name[JVM_MAXPATHLEN - 2] = 't';
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name after timestamp expansion should return NULL, but got '%s'", o_result));
+ }
+
+ {
+ // too long with pid
+ char longest_name[JVM_MAXPATHLEN];
+ memset(longest_name, 'a', JVM_MAXPATHLEN);
+ longest_name[JVM_MAXPATHLEN - 3] = '%';
+ longest_name[JVM_MAXPATHLEN - 2] = 'p';
+ longest_name[JVM_MAXPATHLEN - 1] = '\0';
+ o_result = make_log_name_internal((const char*)&longest_name, NULL, pid, tms);
+ assert(o_result == NULL, err_msg("Too long file name after pid expansion should return NULL, but got '%s'", o_result));
+ }
}
#endif // PRODUCT
@@ -637,9 +682,16 @@
_bytes_written = 0L;
_file_name = make_log_name(file_name, NULL);
+ if (_file_name == NULL) {
+ warning("Cannot open file %s: file name is too long.\n", file_name);
+ _need_close = false;
+ UseGCLogFileRotation = false;
+ return;
+ }
+
// gc log file rotation
if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) {
- char tempbuf[FILENAMEBUFLEN];
+ char tempbuf[JVM_MAXPATHLEN];
jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
_file = fopen(tempbuf, "w");
} else {
@@ -671,10 +723,10 @@
// concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log
// must be synchronized.
void gcLogFileStream::rotate_log(bool force, outputStream* out) {
- char time_msg[FILENAMEBUFLEN];
+ char time_msg[O_BUFLEN];
char time_str[EXTRACHARLEN];
- char current_file_name[FILENAMEBUFLEN];
- char renamed_file_name[FILENAMEBUFLEN];
+ char current_file_name[JVM_MAXPATHLEN];
+ char renamed_file_name[JVM_MAXPATHLEN];
if (!should_rotate(force)) {
return;
@@ -713,12 +765,15 @@
// have a form of extended_filename.<i>.current where i is the current rotation
// file number. After it reaches max file size, the file will be saved and renamed
// with .current removed from its tail.
- size_t filename_len = strlen(_file_name);
if (_file != NULL) {
- jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d",
+ jio_snprintf(renamed_file_name, JVM_MAXPATHLEN, "%s.%d",
_file_name, _cur_file_num);
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
- _file_name, _cur_file_num);
+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN,
+ "%s.%d" CURRENTAPPX, _file_name, _cur_file_num);
+ if (result >= JVM_MAXPATHLEN) {
+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+ return;
+ }
const char* msg = force ? "GC log rotation request has been received."
: "GC log file has reached the maximum size.";
@@ -757,19 +812,23 @@
_cur_file_num++;
if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0;
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX,
+ int result = jio_snprintf(current_file_name, JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX,
_file_name, _cur_file_num);
+ if (result >= JVM_MAXPATHLEN) {
+ warning("Cannot create new log file name: %s: file name is too long.\n", current_file_name);
+ return;
+ }
+
_file = fopen(current_file_name, "w");
if (_file != NULL) {
_bytes_written = 0L;
_need_close = true;
// reuse current_file_name for time_msg
- jio_snprintf(current_file_name, filename_len + EXTRACHARLEN,
+ jio_snprintf(current_file_name, JVM_MAXPATHLEN,
"%s.%d", _file_name, _cur_file_num);
jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n",
- os::local_time_string((char *)time_str, sizeof(time_str)),
- current_file_name);
+ os::local_time_string((char *)time_str, sizeof(time_str)), current_file_name);
write(time_msg, strlen(time_msg));
if (out != NULL) {
@@ -817,32 +876,64 @@
return _log_file != NULL;
}
+fileStream* defaultStream::open_file(const char* log_name) {
+ const char* try_name = make_log_name(log_name, NULL);
+ if (try_name == NULL) {
+ warning("Cannot open file %s: file name is too long.\n", log_name);
+ return NULL;
+ }
+
+ fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ FREE_C_HEAP_ARRAY(char, try_name);
+ if (file->is_open()) {
+ return file;
+ }
+
+ // Try again to open the file in the temp directory.
+ delete file;
+ char warnbuf[O_BUFLEN*2];
+ jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Cannot open log file: %s\n", log_name);
+ // Note: This feature is for maintainer use only. No need for L10N.
+ jio_print(warnbuf);
+ try_name = make_log_name(log_name, os::get_temp_directory());
+ if (try_name == NULL) {
+ warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
+ return NULL;
+ }
+
+ jio_snprintf(warnbuf, sizeof(warnbuf),
+ "Warning: Forcing option -XX:LogFile=%s\n", try_name);
+ jio_print(warnbuf);
+
+ file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ FREE_C_HEAP_ARRAY(char, try_name);
+ if (file->is_open()) {
+ return file;
+ }
+
+ delete file;
+ return NULL;
+}
+
void defaultStream::init_log() {
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log";
- const char* try_name = make_log_name(log_name, NULL);
- fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
- if (!file->is_open()) {
- // Try again to open the file.
- char warnbuf[O_BUFLEN*2];
- jio_snprintf(warnbuf, sizeof(warnbuf),
- "Warning: Cannot open log file: %s\n", try_name);
- // Note: This feature is for maintainer use only. No need for L10N.
- jio_print(warnbuf);
- FREE_C_HEAP_ARRAY(char, try_name);
- try_name = make_log_name(log_name, os::get_temp_directory());
- jio_snprintf(warnbuf, sizeof(warnbuf),
- "Warning: Forcing option -XX:LogFile=%s\n", try_name);
- jio_print(warnbuf);
- delete file;
- file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ fileStream* file = open_file(log_name);
+
+ if (file != NULL) {
+ _log_file = file;
+ _outer_xmlStream = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
+ start_log();
+ } else {
+ // and leave xtty as NULL
+ LogVMOutput = false;
+ DisplayVMOutput = true;
+ LogCompilation = false;
}
- FREE_C_HEAP_ARRAY(char, try_name);
+}
- if (file->is_open()) {
- _log_file = file;
- xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
- _outer_xmlStream = xs;
+void defaultStream::start_log() {
+ xmlStream*xs = _outer_xmlStream;
if (this == tty) xtty = xs;
// Write XML header.
xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
@@ -897,13 +988,6 @@
xs->head("tty");
// All further non-markup text gets copied to the tty:
xs->_text = this; // requires friend declaration!
- } else {
- delete(file);
- // and leave xtty as NULL
- LogVMOutput = false;
- DisplayVMOutput = true;
- LogCompilation = false;
- }
}
// finish_log() is called during normal VM shutdown. finish_log_on_error() is
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -22,6 +22,7 @@
*
*/
+#include <fcntl.h>
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
@@ -807,7 +808,8 @@
static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
int fd = -1;
if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
- fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
+ // the O_EXCL flag will cause the open to fail if the file exists
+ fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
}
return fd;
}
--- a/hotspot/src/share/vm/utilities/xmlstream.cpp Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/src/share/vm/utilities/xmlstream.cpp Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,10 @@
#include "runtime/vmThread.hpp"
#include "utilities/xmlstream.hpp"
+// Do not assert this condition if there's already another error reported.
+#define assert_if_no_error(cond, msg) \
+ vmassert((cond) || is_error_reported(), msg)
+
void xmlStream::initialize(outputStream* out) {
_out = out;
_last_flush = 0;
--- a/hotspot/test/TEST.groups Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/TEST.groups Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,6 @@
gc/metaspace/TestPerfCountersAndMemoryPools.java \
runtime/6819213/TestBootNativeLibraryPath.java \
runtime/7158988/FieldMonitor.java \
- runtime/7194254/Test7194254.java \
runtime/Metaspace/FragmentMetaspace.java \
runtime/NMT/BaselineWithParameter.java \
runtime/NMT/JcmdBaselineDetail.java \
@@ -94,6 +93,7 @@
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
runtime/Thread/TestThreadDumpMonitorContention.java \
+ runtime/Thread/ThreadPriorities.java \
runtime/XCheckJniJsig/XCheckJSig.java \
serviceability/attach/AttachWithStalePidFile.java \
serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \
@@ -232,7 +232,8 @@
gc/g1/ \
gc/metaspace/G1AddMetaspaceDependency.java \
gc/metaspace/TestMetaspacePerfCounters.java \
- gc/startup_warnings/TestG1.java
+ gc/startup_warnings/TestG1.java \
+ gc/whitebox/TestConcMarkCycleWB.java
# All tests that explicitly set the serial GC
#
@@ -357,7 +358,8 @@
compiler/inlining/ \
compiler/integerArithmetic/ \
compiler/interpreter/ \
- -compiler/codegen/7184394
+ -compiler/codegen/7184394 \
+ -compiler/codecache/stress
hotspot_compiler_3 = \
compiler/intrinsics/ \
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -37,6 +37,7 @@
/*
* @test PoolsIndependenceTest
+ * @ignore 8068385
* @library /testlibrary /../../test/lib
* @build PoolsIndependenceTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import com.oracle.java.testlibrary.TimeLimitedRunner;
+import com.oracle.java.testlibrary.Utils;
+
+public class CodeCacheStressRunner {
+ private final Runnable action;
+ public CodeCacheStressRunner(Runnable action) {
+ this.action = action;
+ }
+
+ protected final void runTest() {
+ Helper.startInfiniteLoopThread(action);
+ try {
+ // adjust timeout and substract vm init and exit time
+ long timeout = Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT);
+ timeout *= 0.9;
+ new TimeLimitedRunner(timeout, 2.0d, this::test).call();
+ } catch (Exception e) {
+ throw new Error("Exception occurred during test execution", e);
+ }
+ }
+
+ private boolean test() {
+ Helper.TestCase obj = Helper.TestCase.get();
+ Helper.callMethod(obj.getCallable(), obj.expectedValue());
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/Helper.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ByteCodeLoader;
+import com.oracle.java.testlibrary.InfiniteLoop;
+import com.oracle.java.testlibrary.Utils;
+import sun.hotspot.WhiteBox;
+
+public final class Helper {
+ public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ public static final Random RNG = Utils.getRandomInstance();
+
+ private static final long THRESHOLD = WHITE_BOX.getIntxVMFlag("CompileThreshold");
+ private static final String TEST_CASE_IMPL_CLASS_NAME = "Helper$TestCaseImpl";
+ private static byte[] CLASS_DATA;
+ static {
+ try {
+ CLASS_DATA = loadClassData(TEST_CASE_IMPL_CLASS_NAME);
+ } catch (IOException e) {
+ throw new Error("TESTBUG: cannot load class byte code", e);
+ }
+ }
+
+ private Helper() {
+ }
+
+ public static void startInfiniteLoopThread(Runnable action) {
+ startInfiniteLoopThread(action, 0L);
+ }
+
+ public static void startInfiniteLoopThread(Runnable action, long millis) {
+ Thread t = new Thread(new InfiniteLoop(action, millis));
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static int callMethod(Callable<Integer> callable, int expected) {
+ int result = 0;
+ for (int i = 0; i < THRESHOLD; ++i) {
+ try {
+ result = callable.call();
+ } catch (Exception e) {
+ throw new AssertionError(
+ "Exception occurred during test method execution", e);
+ }
+ Asserts.assertEQ(result, expected, "Method returns unexpected value");
+ }
+ return result;
+ }
+
+ private static byte[] loadClassData(String name) throws IOException {
+ try (BufferedInputStream in = new BufferedInputStream(
+ ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ + ".class"))) {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1) {
+ result.write(buffer, 0, read);
+ }
+ return result.toByteArray();
+ }
+ }
+
+ public interface TestCase {
+
+ public static TestCase get() {
+ try {
+ Class clazz = ByteCodeLoader.load(
+ TEST_CASE_IMPL_CLASS_NAME, CLASS_DATA);
+ return (TestCase) clazz.newInstance();
+ } catch (ReflectiveOperationException e) {
+ throw new Error(String.format(
+ "TESTBUG: error while creating %s instance from reloaded class",
+ TEST_CASE_IMPL_CLASS_NAME), e);
+ }
+ }
+
+ Callable<Integer> getCallable();
+ int method();
+ int expectedValue();
+ }
+
+ public static class TestCaseImpl implements TestCase {
+ private static final int RETURN_VALUE = 42;
+ private static final int RECURSION_DEPTH = 10;
+ private volatile int i;
+
+ @Override
+ public Callable<Integer> getCallable() {
+ return () -> {
+ i = 0;
+ return method();
+ };
+ }
+
+ @Override
+ public int method() {
+ ++i;
+ int result = RETURN_VALUE;
+ if (i < RECURSION_DEPTH) {
+ return result + method();
+ }
+ return result;
+ }
+
+ @Override
+ public int expectedValue() {
+ return RETURN_VALUE * RECURSION_DEPTH;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import java.lang.reflect.Method;
+import java.util.stream.IntStream;
+
+import com.oracle.java.testlibrary.Platform;
+
+/*
+ * @test OverloadCompileQueueTest
+ * @library /testlibrary /../../test/lib
+ * @build OverloadCompileQueueTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache OverloadCompileQueueTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache OverloadCompileQueueTest
+ * @summary stressing code cache by overloading compile queues
+ */
+public class OverloadCompileQueueTest implements Runnable {
+ private static final int MAX_SLEEP = 10000;
+ private static final String METHOD_TO_ENQUEUE = "method";
+ private static final int LEVEL_SIMPLE = 1;
+ private static final int LEVEL_FULL_OPTIMIZATION = 4;
+ private static final boolean INTERPRETED
+ = System.getProperty("java.vm.info").startsWith("interpreted ");
+ private static final boolean TIERED_COMPILATION
+ = Helper.WHITE_BOX.getBooleanVMFlag("TieredCompilation");
+ private static final int TIERED_STOP_AT_LEVEL
+ = Helper.WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue();
+ private static final int[] AVAILABLE_LEVELS;
+ static {
+ if (TIERED_COMPILATION) {
+ AVAILABLE_LEVELS = IntStream
+ .rangeClosed(LEVEL_SIMPLE, TIERED_STOP_AT_LEVEL)
+ .toArray();
+ } else if (Platform.isServer()) {
+ AVAILABLE_LEVELS = new int[] { LEVEL_FULL_OPTIMIZATION };
+ } else if (Platform.isClient() || Platform.isMinimal()) {
+ AVAILABLE_LEVELS = new int[] { LEVEL_SIMPLE };
+ } else {
+ throw new Error(String.format(
+ "TESTBUG: unknown VM: %s", System.getProperty("java.vm.name")));
+ }
+ }
+
+ public static void main(String[] args) {
+ if (INTERPRETED) {
+ System.err.println("Test isn't applicable for interpreter. Skip test.");
+ return;
+ }
+ new CodeCacheStressRunner(new OverloadCompileQueueTest()).runTest();
+ }
+
+ public OverloadCompileQueueTest() {
+ Helper.startInfiniteLoopThread(this::lockUnlock);
+ }
+
+ @Override
+ public void run() {
+ Helper.TestCase obj = Helper.TestCase.get();
+ Class clazz = obj.getClass();
+ Method mEnqueue;
+ try {
+ mEnqueue = clazz.getMethod(METHOD_TO_ENQUEUE);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new Error(String.format(
+ "TESTBUG: cannot get method '%s' of class %s",
+ METHOD_TO_ENQUEUE, clazz.getName()), e);
+ }
+ for (int compLevel : AVAILABLE_LEVELS) {
+ Helper.WHITE_BOX.enqueueMethodForCompilation(mEnqueue, compLevel);
+ }
+ }
+
+ private void lockUnlock() {
+ try {
+ Helper.WHITE_BOX.lockCompilation();
+ Thread.sleep(Helper.RNG.nextInt(MAX_SLEEP));
+ } catch (InterruptedException e) {
+ throw new Error("TESTBUG: lockUnlocker thread was unexpectedly interrupted", e);
+ } finally {
+ Helper.WHITE_BOX.unlockCompilation();
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+import java.util.ArrayList;
+
+import sun.hotspot.code.BlobType;
+
+/*
+ * @test RandomAllocationTest
+ * @library /testlibrary /../../test/lib
+ * @build RandomAllocationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache RandomAllocationTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache RandomAllocationTest
+ * @summary stressing code cache by allocating randomly sized "dummy" code blobs
+ */
+public class RandomAllocationTest implements Runnable {
+ private static final long CODE_CACHE_SIZE
+ = Helper.WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize");
+ private static final int MAX_BLOB_SIZE = (int) (CODE_CACHE_SIZE >> 7);
+ private static final BlobType[] BLOB_TYPES
+ = BlobType.getAvailable().toArray(new BlobType[0]);
+
+ public static void main(String[] args) {
+ new CodeCacheStressRunner(new RandomAllocationTest()).runTest();
+ }
+
+ private final ArrayList<Long> blobs = new ArrayList<>();
+ @Override
+ public void run() {
+ boolean allocate = blobs.isEmpty() || Helper.RNG.nextBoolean();
+ if (allocate) {
+ int type = Helper.RNG.nextInt(BLOB_TYPES.length);
+ long addr = Helper.WHITE_BOX.allocateCodeBlob(
+ Helper.RNG.nextInt(MAX_BLOB_SIZE), BLOB_TYPES[type].id);
+ if (addr != 0) {
+ blobs.add(addr);
+ }
+ } else {
+ int index = Helper.RNG.nextInt(blobs.size());
+ Helper.WHITE_BOX.freeCodeBlob(blobs.remove(index));
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test UnexpectedDeoptimizationTest
+ * @library /testlibrary /../../test/lib
+ * @build UnexpectedDeoptimizationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:-SegmentedCodeCache -XX:-DeoptimizeRandom
+ * UnexpectedDeoptimizationTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:CompileCommand=dontinline,Helper$TestCase::method
+ * -XX:+WhiteBoxAPI -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom
+ * UnexpectedDeoptimizationTest
+ * @summary stressing code cache by forcing unexpected deoptimizations
+ */
+public class UnexpectedDeoptimizationTest implements Runnable {
+
+ public static void main(String[] args) {
+ new CodeCacheStressRunner(new UnexpectedDeoptimizationTest()).runTest();
+ }
+
+ @Override
+ public void run() {
+ Helper.WHITE_BOX.deoptimizeFrames(Helper.RNG.nextBoolean());
+ }
+
+}
--- a/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/exceptions/TestRecursiveReplacedException.java Mon Jan 26 17:00:39 2015 -0800
@@ -25,7 +25,7 @@
* @test
* @bug 8054224
* @summary Recursive method compiled by C1 is unable to catch StackOverflowError
- * @run main/othervm -Xcomp -XX:CompileOnly=Test.run -XX:+TieredCompilation -XX:TieredStopAtLevel=2 -Xss256K TestRecursiveReplacedException
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test.run -XX:+TieredCompilation -XX:TieredStopAtLevel=2 -Xss392K TestRecursiveReplacedException
*
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/floatingpoint/TestPow2.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8063086
+ * @summary X^2 special case for C2 yields different result than interpreter
+ * @library /testlibrary /../../test/lib /compiler/whitebox
+ * @build TestPow2
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestPow2
+ *
+ */
+
+import java.lang.reflect.*;
+import sun.hotspot.WhiteBox;
+
+public class TestPow2 {
+
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ private static final double base = 5350.456329377186;
+ private static final double exp = 2.0;
+
+ static double m() {
+ return Math.pow(base, exp);
+ }
+
+ static public void main(String[] args) throws NoSuchMethodException {
+ Method test_method = TestPow2.class.getDeclaredMethod("m");
+
+ double interpreter_result = m();
+
+ // Compile with C1 if possible
+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
+
+ double c1_result = m();
+
+ WHITE_BOX.deoptimizeMethod(test_method);
+
+ // Compile it with C2 if possible
+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+
+ double c2_result = m();
+
+ if (interpreter_result != c1_result || interpreter_result != c2_result ||
+ c1_result != c2_result) {
+ System.out.println("interpreter = " + interpreter_result + " c1 = " + c1_result + " c2 = " + c2_result);
+ throw new RuntimeException("Test Failed");
+ }
+ }
+}
--- a/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Mon Jan 26 17:00:39 2015 -0800
@@ -26,6 +26,7 @@
* @bug 8042235
* @summary redefining method used by multiple MethodHandles crashes VM
* @compile -XDignore.symbol.file RedefineMethodUsedByMultipleMethodHandles.java
+ * @ignore 7076820
* @run main RedefineMethodUsedByMultipleMethodHandles
*/
--- a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Mon Jan 26 17:00:39 2015 -0800
@@ -172,7 +172,7 @@
out.shouldContain(expected_output);
}
- out.shouldNotContain("CompilerOracle: unrecognized line");
+ out.shouldNotContain("CompileCommand: unrecognized line");
out.shouldHaveExitValue(0);
}
@@ -183,7 +183,7 @@
pb = ProcessTools.createJavaProcessBuilder(arguments);
out = new OutputAnalyzer(pb.start());
- out.shouldContain("CompilerOracle: unrecognized line");
+ out.shouldContain("CompileCommand: unrecognized line");
out.shouldHaveExitValue(0);
}
--- a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Mon Jan 26 17:00:39 2015 -0800
@@ -28,6 +28,7 @@
* @bug 8038636
* @library /testlibrary
* @build Agent
+ * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Mon Jan 26 17:00:39 2015 -0800
@@ -28,6 +28,7 @@
* @bug 8040237
* @library /testlibrary
* @build Agent Test A B
+ * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Mon Jan 26 17:00:39 2015 -0800
@@ -53,6 +53,7 @@
*/
public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest {
private static final long LOCKING_THRESHOLD = 100L;
+ private static final long ABORT_THRESHOLD = LOCKING_THRESHOLD / 2L;
private TestRTMDeoptOnLowAbortRatio() {
super(new AndPredicate(new SupportedCPU(), new SupportedVM()));
@@ -77,7 +78,8 @@
useStackLock),
CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold",
TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD),
- "-XX:RTMAbortThreshold=1",
+ CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold",
+ TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD),
"-XX:RTMAbortRatio=100",
"-XX:CompileThreshold=1",
"-XX:RTMRetryCount=0",
@@ -107,7 +109,7 @@
for (RTMLockingStatistics s : statistics) {
if (s.getTotalLocks()
- == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD + 1L) {
+ == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD) {
Asserts.assertNull(statisticsBeforeDeopt,
"Only one abort was expected during test run");
statisticsBeforeDeopt = s;
@@ -154,8 +156,7 @@
}
for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
- t.forceAbort(
- i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD);
+ t.forceAbort(i >= TestRTMDeoptOnLowAbortRatio.ABORT_THRESHOLD);
}
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Mon Jan 26 17:00:39 2015 -0800
@@ -58,7 +58,7 @@
* interrupts, VMM calls, etc. during first lock attempt.
*
*/
- private static final int ABORT_THRESHOLD = 10;
+ private static final int MIN_ABORT_THRESHOLD = 10;
@Override
protected void runTestCases() throws Throwable {
@@ -75,6 +75,9 @@
boolean useStackLock) throws Throwable {
CompilableTest test = new Test();
+ int abortThreshold = Math.max(lockingThreshold / 2,
+ TestRTMLockingThreshold.MIN_ABORT_THRESHOLD);
+
OutputAnalyzer outputAnalyzer = RTMTestBase.executeRTMTest(
test,
"-XX:CompileThreshold=1",
@@ -84,7 +87,7 @@
"-XX:RTMTotalCountIncrRate=1",
"-XX:RTMRetryCount=0",
CommandLineOptionTest.prepareNumericFlag("RTMAbortThreshold",
- TestRTMLockingThreshold.ABORT_THRESHOLD),
+ abortThreshold),
CommandLineOptionTest.prepareNumericFlag("RTMLockingThreshold",
lockingThreshold),
"-XX:RTMAbortRatio=100",
@@ -103,16 +106,12 @@
+ "RTM locking statistics entries.");
/**
- * We force abort on each odd iteration, so if RTMLockingThreshold==0,
- * then we have to make 1 call without abort to avoid rtm state
- * transition to NoRTM (otherwise actual abort ratio will be 100%),
- * and after that make 1 call with abort to force deoptimization.
- * This leads us to two locks for threshold 0.
- * For other threshold values we have to make RTMLockingThreshold + 1
- * locks if locking threshold is even, or + 0 if odd.
+ * If RTMLockingThreshold==0, then we have to make at least 1 call.
*/
- long expectedValue = lockingThreshold +
- (lockingThreshold == 0L ? 2L : lockingThreshold % 2L);
+ long expectedValue = lockingThreshold;
+ if (expectedValue == 0) {
+ expectedValue++;
+ }
RTMLockingStatistics statBeforeDeopt = null;
for (RTMLockingStatistics s : statistics) {
@@ -159,15 +158,16 @@
* Test <inflate monitor>
*/
public static void main(String args[]) throws Throwable {
- Asserts.assertGTE(args.length, 1, "One argument required.");
+ Asserts.assertGTE(args.length, 2, "Two arguments required.");
Test t = new Test();
boolean shouldBeInflated = Boolean.valueOf(args[0]);
+ int lockingThreshold = Integer.valueOf(args[1]);
if (shouldBeInflated) {
AbortProvoker.inflateMonitor(t.monitor);
}
for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated);
- t.lock(i % 2 == 1);
+ t.lock(i >= lockingThreshold / 2);
}
}
}
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Mon Jan 26 17:00:39 2015 -0800
@@ -35,6 +35,7 @@
* -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate
*/
+import sun.misc.Unsafe;
import java.util.List;
import com.oracle.java.testlibrary.*;
@@ -97,14 +98,12 @@
Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS,
"Total locks should be exactly the same as amount of "
+ "iterations.");
- } else {
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM statistics "
- + "should contain information for at least on lock.");
}
}
public static class Test implements CompilableTest {
private static final long TOTAL_ITERATIONS = 10000L;
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
private final Object monitor = new Object();
// Following field have to be static in order to avoid escape analysis.
@SuppressWarnings("UnsuedDeclaration")
@@ -120,8 +119,17 @@
return new String[] { getMethodWithLockName() };
}
- public void lock() {
+ public void lock(booleab forceAbort) {
synchronized(monitor) {
+ if (forceAbort) {
+ // We're calling native method in order to force
+ // abort. It's done by explicit xabort call emitted
+ // in SharedRuntime::generate_native_wrapper.
+ // If an actuall JNI call will be replaced by
+ // intrinsic - we'll be in trouble, since xabort
+ // will be no longer called and test may fail.
+ UNSAFE.addressSize();
+ }
Test.field++;
}
}
@@ -140,7 +148,11 @@
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(test.monitor,
shouldBeInflated);
- test.lock();
+ // Force abort on first iteration to avoid rare case when
+ // there were no aborts and locks count was not incremented
+ // with RTMTotalCountIncrRate > 1 (in such case JVM won't
+ // print JVM locking statistics).
+ test.lock(i == 0);
}
}
}
--- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Mon Jan 26 17:00:39 2015 -0800
@@ -125,9 +125,6 @@
RTMLockingStatistics lock = statistics.get(0);
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM locking statistics "
- + "should contain non zero total locks count");
-
Asserts.assertGT(lock.getTotalAborts(), 0L,
"RTM locking statistics should contain non zero total aborts "
+ "count");
--- a/hotspot/test/compiler/runtime/6865265/StackOverflowBug.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/runtime/6865265/StackOverflowBug.java Mon Jan 26 17:00:39 2015 -0800
@@ -28,7 +28,7 @@
* @summary JVM crashes with "missing exception handler" error
* @author volker.simonis@sap.com
*
- * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss248k StackOverflowBug
+ * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss392k StackOverflowBug
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/testlibrary/uncommontrap/Verifier.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package uncommontrap;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.Asserts;
+/**
+ * Utility tool aimed to verify presence or absence of specified uncommon trap
+ * in compilation log.
+ */
+public class Verifier {
+ public static final String PROPERTIES_FILE_SUFFIX = ".verify.properties";
+ public static final String VERIFICATION_SHOULD_BE_SKIPPED
+ = "uncommon.trap.verification.skipped";
+ public static final String UNCOMMON_TRAP_NAME = "uncommon.trap.name";
+ public static final String UNCOMMON_TRAP_BCI = "uncommon.trap.bci";
+ public static final String UNCOMMON_TRAP_COMMENT = "uncommon.trap.comment";
+ public static final String UNCOMMON_TRAP_ACTION = "uncommon.trap.action";
+ public static final String UNCOMMON_TRAP_SHOULD_EMITTED
+ = "uncommon.trap.emitted";
+ public static final String UNCOMMON_TRAP_SHOULD_FIRED
+ = "uncommon.trap.fired";
+
+ private static final String EMITTED_TRAP_PATTERN
+ = "<uncommon_trap bci='%s' reason='%s' action='%s' "
+ + "comment='%s'";
+ private static final String FIRED_TRAP_PATTERN
+ = "<uncommon_trap thread='[0-9]*' reason='%s' action='%s'";
+ private static final String JVMS_PATTERN = "<jvms bci='%s'";
+
+ public static void main(String args[]) {
+ if (args.length == 0) {
+ throw new Error("At least one argument containing name of "
+ + "compilation log file is expected");
+ }
+
+ for (String compLogFile : args) {
+ try {
+ verify(Paths.get(compLogFile));
+ } catch (IOException e) {
+ throw new Error("Unable to process compilation log.", e);
+ }
+ }
+ }
+
+ private static void verify(Path compLogFile) throws IOException {
+ Path propertiesFile = Paths.get(compLogFile.toString() +
+ PROPERTIES_FILE_SUFFIX);
+
+ Properties properties = new Properties();
+ properties.load(new FileReader(propertiesFile.toFile()));
+
+ if (Boolean.valueOf(properties.getProperty(
+ VERIFICATION_SHOULD_BE_SKIPPED, "false"))) {
+ System.out.println("Skipping verification for log file: "
+ + compLogFile.toString());
+ return;
+ }
+
+ System.out.println("Verifying log file: " + compLogFile.toString());
+
+ List<String> compLogContent = Files.readAllLines(compLogFile);
+ verifyUncommonTrapEmitted(properties, compLogContent);
+ verifyUncommonTrapFired(properties, compLogContent);
+ }
+
+ private static void verifyUncommonTrapEmitted(Properties properties,
+ List<String> compLogContent) {
+ String emittedTrapRE = String.format(EMITTED_TRAP_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_BCI, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_NAME, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_ACTION, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_COMMENT, ".*"));
+ Pattern pattern = Pattern.compile(emittedTrapRE);
+
+ long trapsCount = compLogContent.stream()
+ .filter(line -> pattern.matcher(line).find())
+ .count();
+
+ boolean shouldBeEmitted = Boolean.valueOf(
+ properties.getProperty(UNCOMMON_TRAP_SHOULD_EMITTED));
+
+ Asserts.assertEQ(shouldBeEmitted, trapsCount > 0, String.format(
+ "Uncommon trap that matches following string in compilation log"
+ + " should %sbe emitted: %s.",
+ (shouldBeEmitted ? " " : "not "), emittedTrapRE));
+ }
+
+ private static void verifyUncommonTrapFired(Properties properties,
+ List<String> compLogContent) {
+ String firedTrapRE = String.format(FIRED_TRAP_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_NAME, ".*"),
+ properties.getProperty(UNCOMMON_TRAP_ACTION, ".*"));
+ String jvmsRE = String.format(JVMS_PATTERN,
+ properties.getProperty(UNCOMMON_TRAP_BCI, ".*"));
+
+ boolean trapFired = false;
+ Pattern firedTrapPattern = Pattern.compile(firedTrapRE);
+ Pattern jvmsPattern = Pattern.compile(jvmsRE);
+
+ Iterator<String> iterator = compLogContent.iterator();
+ while (iterator.hasNext() && !trapFired) {
+ trapFired = firedTrapPattern.matcher(iterator.next()).find()
+ && jvmsPattern.matcher(iterator.next()).find();
+ }
+
+ boolean shouldBeFired = Boolean.valueOf(
+ properties.getProperty(UNCOMMON_TRAP_SHOULD_FIRED));
+ Asserts.assertEQ(shouldBeFired, trapFired, String.format(
+ "Uncommon trap that matches following string in compilation log"
+ + " should %sbe fired: %s.",
+ (shouldBeFired ? "" : "not "), firedTrapRE));
+ }
+}
+
--- a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java Mon Jan 26 17:00:39 2015 -0800
@@ -32,7 +32,7 @@
* @build Test8009761
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss392K Test8009761
*/
public class Test8009761 {
--- a/hotspot/test/compiler/uncommontrap/StackOverflowGuardPagesOff.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/StackOverflowGuardPagesOff.java Mon Jan 26 17:00:39 2015 -0800
@@ -25,7 +25,7 @@
* @test
* @bug 8029383
* @summary stack overflow if callee is marked for deoptimization causes crash
- * @run main/othervm -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,StackOverflowGuardPagesOff::m1 -XX:CompileCommand=exclude,StackOverflowGuardPagesOff::m2 -Xss256K -XX:-UseOnStackReplacement StackOverflowGuardPagesOff
+ * @run main/othervm -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,StackOverflowGuardPagesOff::m1 -XX:CompileCommand=exclude,StackOverflowGuardPagesOff::m2 -Xss392K -XX:-UseOnStackReplacement StackOverflowGuardPagesOff
*
*/
--- a/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/TestStackBangMonitorOwned.java Mon Jan 26 17:00:39 2015 -0800
@@ -25,7 +25,7 @@
* @test
* @bug 8032410
* @summary Stack overflow at deoptimization doesn't release owned monitors
- * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangMonitorOwned::m1 -XX:CompileCommand=exclude,TestStackBangMonitorOwned::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangMonitorOwned
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangMonitorOwned::m1 -XX:CompileCommand=exclude,TestStackBangMonitorOwned::m2 -Xss392K -XX:-UseOnStackReplacement TestStackBangMonitorOwned
*
*/
public class TestStackBangMonitorOwned {
--- a/hotspot/test/compiler/uncommontrap/TestStackBangRbp.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/uncommontrap/TestStackBangRbp.java Mon Jan 26 17:00:39 2015 -0800
@@ -25,7 +25,7 @@
* @test
* @bug 8028308
* @summary rbp not restored when stack overflow is thrown from deopt/uncommon trap blobs
- * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangRbp::m1 -XX:CompileCommand=exclude,TestStackBangRbp::m2 -Xss256K -XX:-UseOnStackReplacement TestStackBangRbp
+ * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=dontinline,TestStackBangRbp::m1 -XX:CompileCommand=exclude,TestStackBangRbp::m2 -Xss392K -XX:-UseOnStackReplacement TestStackBangRbp
*
*/
public class TestStackBangRbp {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Properties;
+
+import com.oracle.java.testlibrary.ByteCodeLoader;
+import com.oracle.java.testlibrary.Platform;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+import sun.hotspot.WhiteBox;
+import uncommontrap.Verifier;
+
+/*
+ * @test
+ * @bug 8030976 8059226
+ * @library /testlibrary /compiler/testlibrary /../../test/lib
+ * @build TestUnstableIfTrap com.oracle.java.testlibrary.* uncommontrap.Verifier
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=always_taken_not_fired.xml
+ * TestUnstableIfTrap ALWAYS_TAKEN false
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=always_taken_fired.xml
+ * TestUnstableIfTrap ALWAYS_TAKEN true
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=never_taken_not_fired.xml
+ * TestUnstableIfTrap NEVER_TAKEN false
+ * @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+LogCompilation
+ * -XX:CompileCommand=compileonly,UnstableIfExecutable.test
+ * -XX:LogFile=never_taken_fired.xml
+ * TestUnstableIfTrap NEVER_TAKEN true
+ * @run main uncommontrap.Verifier always_taken_not_fired.xml
+ * always_taken_fired.xml
+ * never_taken_not_fired.xml
+ * never_taken_fired.xml
+ */
+public class TestUnstableIfTrap {
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final String CLASS_NAME = "UnstableIfExecutable";
+ private static final String METHOD_NAME = "test";
+ private static final String FIELD_NAME = "field";
+ private static final int ITERATIONS = 1_000_000;
+ // There is no dependency on particular class file version, so it could be
+ // set to any version (if you're updating this test for Java 42).
+ private static final int CLASS_FILE_VERSION = 49;
+ private static final int MAX_TIER = 4;
+ // This test aimed to verify that uncommon trap with reason "unstable_if"
+ // is emitted when method that contain control-flow divergence such that
+ // one of two branches is never taken (and other one is taken always).
+ // C2 will made a decision whether or not the branch was ever taken
+ // depending on method's profile.
+ // If profile was collected for a few method's invocations, then C2 will not
+ // trust in branches' probabilities and the tested trap won't be emitted.
+ // In fact, a method has to be invoked at least 40 time at the day when this
+ // comment was written (see Parse::dynamic_branch_prediction for an actual
+ // value). It would be to implementation dependent to use "40" as
+ // a threshold value in the test, so in order to improve test's robustness
+ // the threshold value is 1000: if the tested method was compiled by C2
+ // before it was invoked 1000 times, then we won't verify that trap was
+ // emitted and fired.
+ private static final int MIN_INVOCATIONS_BEFORE_C2_COMPILATION = 1000;
+ /**
+ * Description of test case parameters and uncommon trap that will
+ * be emitted during tested method compilation.
+ */
+ private static enum TestCaseName {
+ ALWAYS_TAKEN(false, "taken always"),
+ NEVER_TAKEN(true, "taken never");
+ TestCaseName(boolean predicate, String comment) {
+ this.predicate = predicate;
+ this.comment = comment;
+ }
+
+ public final boolean predicate;
+ public final String name = "unstable_if";
+ public final String comment;
+ }
+
+ public static void main(String args[]) {
+ if (args.length != 2) {
+ throw new Error("Expected two arguments: test case name and a "
+ + "boolean determining if uncommon trap should be fired.");
+ }
+ test(TestCaseName.valueOf(args[0]), Boolean.valueOf(args[1]));
+ }
+
+ private static void test(TestCaseName testCase, boolean shouldBeFired) {
+ Method testMethod;
+ Label unstableIfLocation = new Label();
+ boolean shouldBeEmitted;
+ boolean compiledToEarly = false;
+
+ try {
+ Class testClass = ByteCodeLoader.load(CLASS_NAME,
+ generateTest(unstableIfLocation));
+ testMethod = testClass.getDeclaredMethod(METHOD_NAME,
+ boolean.class);
+ for (int i = 0; i < ITERATIONS; i++) {
+ testMethod.invoke(null, testCase.predicate);
+ if (i < MIN_INVOCATIONS_BEFORE_C2_COMPILATION
+ && isMethodCompiledByC2(testMethod)) {
+ compiledToEarly = true;
+ // There is no sense in further invocations: we already
+ // decided to avoid verification.
+ break;
+ }
+ }
+ // We're checking that trap should be emitted (i.e. it was compiled
+ // by C2) before the trap is fired, because otherwise the nmethod
+ // will be deoptimized and isMethodCompiledByC2 will return false.
+ shouldBeEmitted = isMethodCompiledByC2(testMethod)
+ && !compiledToEarly;
+ if (shouldBeFired) {
+ testMethod.invoke(null, !testCase.predicate);
+ }
+ } catch (ReflectiveOperationException e) {
+ throw new Error("Test case should be generated, loaded and executed"
+ + " without any issues.", e);
+ }
+
+ shouldBeFired &= shouldBeEmitted;
+
+ Properties properties = new Properties();
+ properties.setProperty(Verifier.VERIFICATION_SHOULD_BE_SKIPPED,
+ Boolean.toString(compiledToEarly));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_SHOULD_EMITTED,
+ Boolean.toString(shouldBeEmitted));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_SHOULD_FIRED,
+ Boolean.toString(shouldBeFired));
+ properties.setProperty(Verifier.UNCOMMON_TRAP_NAME, testCase.name);
+ properties.setProperty(Verifier.UNCOMMON_TRAP_COMMENT,
+ testCase.comment);
+ properties.setProperty(Verifier.UNCOMMON_TRAP_BCI,
+ Integer.toString(unstableIfLocation.getOffset()));
+
+ properties.list(System.out);
+
+ File f = new File(WB.getStringVMFlag("LogFile") +
+ Verifier.PROPERTIES_FILE_SUFFIX);
+ try (FileWriter wr = new FileWriter(f)) {
+ properties.store(wr, "");
+ } catch (IOException e) {
+ throw new Error("Unable to store test properties.", e);
+ }
+ }
+
+ private static boolean isMethodCompiledByC2(Method m) {
+ boolean isTiered = WB.getBooleanVMFlag("TieredCompilation");
+ boolean isMethodCompiled = WB.isMethodCompiled(m);
+ boolean isMethodCompiledAtMaxTier
+ = WB.getMethodCompilationLevel(m) == MAX_TIER;
+
+ return Platform.isServer() && isMethodCompiled
+ && (!isTiered || isMethodCompiledAtMaxTier);
+ }
+
+ /**
+ * Generates class with name {@code CLASS_NAME}, which will contain a
+ * static method {@code METHOD_NAME}:
+ *
+ * <pre>{@code
+ * public abstract class UnstableIfExecutable {
+ * private static int field = 0;
+ *
+ * public static void test(boolean alwaysTrue) {
+ * if (alwaysTrue) {
+ * field++;
+ * } else {
+ * field--;
+ * }
+ * }
+ * }
+ * }</pre>
+ *
+ * @return generated bytecode.
+ */
+ private static byte[] generateTest(Label unstableIfLocation) {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+ cw.visit(CLASS_FILE_VERSION, ACC_PUBLIC | ACC_ABSTRACT, CLASS_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitField(ACC_PUBLIC | ACC_STATIC | ACC_VOLATILE, FIELD_NAME,
+ "I", null, Integer.valueOf(0));
+
+ generateTestMethod(cw, unstableIfLocation);
+
+ return cw.toByteArray();
+ }
+
+ private static void generateTestMethod(ClassVisitor cv,
+ Label unstableIfLocation) {
+ MethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, METHOD_NAME,
+ "(Z)V", null, null);
+ mv.visitCode();
+
+ Label end = new Label();
+ Label falseBranch = new Label();
+
+ // push "field" field's value and 1 to stack
+ mv.visitFieldInsn(GETSTATIC, CLASS_NAME, FIELD_NAME, "I");
+ mv.visitInsn(ICONST_1);
+ // load argument's value
+ mv.visitVarInsn(ILOAD, 0); // alwaysTrue
+ // here is our unstable if
+ mv.visitLabel(unstableIfLocation);
+ mv.visitJumpInsn(IFEQ, falseBranch);
+ // increment on "true"
+ mv.visitInsn(IADD);
+ mv.visitJumpInsn(GOTO, end);
+ // decrement on "false"
+ mv.visitLabel(falseBranch);
+ mv.visitInsn(ISUB);
+ mv.visitLabel(end);
+ // bye bye
+ mv.visitInsn(RETURN);
+
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+}
+
--- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -34,6 +34,7 @@
/*
* @test
* @bug 8059624 8064669
+ * @ignore 8066998
* @library /testlibrary /../../test/lib
* @build ForceNMethodSweepTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
--- a/hotspot/test/gc/TestSmallHeap.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/gc/TestSmallHeap.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,34 +26,46 @@
* @bug 8067438
* @requires vm.gc=="null"
* @summary Verify that starting the VM with a small heap works
- * @library /testlibrary
- * @run main/othervm -Xmx4m -XX:+UseParallelGC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseSerialGC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseG1GC TestSmallHeap
- * @run main/othervm -Xmx4m -XX:+UseConcMarkSweepGC -XX:CMSMarkStackSizeMax=1032 TestSmallHeap
+ * @library /testlibrary /../../test/lib
+ * @build TestSmallHeap
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseParallelGC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap
*
- * Note: It would be nice to verify the minimal supported heap size here,
- * but that turns out to be quite tricky since we align the heap size based
- * on the card table size. And the card table size is aligned based on the
- * minimal pages size provided by the os. This means that on most platforms,
- * where the minimal page size is 4k, we get a minimal heap size of 2m but
- * on Solaris/Sparc we have a page size of 8k and get a minimal heap size
- * of 8m.
+ * Note: It would be nice to verify the minimal supported heap size (2m) here,
+ * but we align the heap size based on the card table size. And the card table
+ * size is aligned based on the minimal pages size provided by the os. This
+ * means that on most platforms, where the minimal page size is 4k, we get a
+ * minimal heap size of 2m but on Solaris/Sparc we have a page size of 8k and
+ * get a minimal heap size of 4m. And on platforms where the page size is 64k
+ * we get a minimal heap size of 32m. We never use large pages for the card table.
+ *
* There is also no check in the VM for verifying that the maximum heap size
* is larger than the supported minimal heap size. This means that specifying
- * -Xmx1m on the command line is fine but will give a heap of 2m (or 4m).
- * To work around these rather strange behaviors this test uses 4m for all
- * platforms.
+ * -Xmx1m on the command line is fine but will give a heap of 2m (or 4m or 32m).
+ *
+ * To work around these rather strange behaviors this test uses -Xmx2m but then
+ * calculates what the expected heap size should be. The calculation is a
+ * simplified version of the code in the VM. We assume that the card table will
+ * use one page. Each byte in the card table corresponds to 512 bytes on the heap.
+ * So, the expected heap size is page_size * 512.
*/
+import com.oracle.java.testlibrary.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+import sun.hotspot.WhiteBox;
import sun.management.ManagementFactoryHelper;
-import static com.oracle.java.testlibrary.Asserts.*;
public class TestSmallHeap {
public static void main(String[] args) {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ int pageSize = wb.getVMPageSize();
+ int heapBytesPerCard = 512;
+ long expectedMaxHeap = pageSize * heapBytesPerCard;
String maxHeap = ManagementFactoryHelper.getDiagnosticMXBean().getVMOption("MaxHeapSize").getValue();
- String expectedMaxHeap = "4194304";
- assertEQ(maxHeap, expectedMaxHeap);
+ assertEQ(Long.parseLong(maxHeap), expectedMaxHeap);
}
}
--- a/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/gc/arguments/TestMaxHeapSizeTools.java Mon Jan 26 17:00:39 2015 -0800
@@ -112,7 +112,7 @@
}
private static void checkInvalidMinInitialHeapCombinations(String gcflag) throws Exception {
- expectError(new String[] { gcflag, "-Xms8M", "-XX:InitialHeapSize=4M", "-version" });
+ expectError(new String[] { gcflag, "-Xms64M", "-XX:InitialHeapSize=32M", "-version" });
}
private static void checkValidMinInitialHeapCombinations(String gcflag) throws Exception {
--- a/hotspot/test/gc/g1/TestGCLogMessages.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java Mon Jan 26 17:00:39 2015 -0800
@@ -107,8 +107,8 @@
private static void testWithToSpaceExhaustionLogs() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
- "-Xmx10M",
- "-Xmn5M",
+ "-Xmx32M",
+ "-Xmn16M",
"-XX:+PrintGCDetails",
GCTestWithToSpaceExhaustion.class.getName());
@@ -120,8 +120,8 @@
output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
- "-Xmx10M",
- "-Xmn5M",
+ "-Xmx32M",
+ "-Xmn16M",
"-XX:+PrintGCDetails",
"-XX:+UnlockExperimentalVMOptions",
"-XX:G1LogLevel=finest",
@@ -151,7 +151,7 @@
private static byte[] garbage;
private static byte[] largeObject;
public static void main(String [] args) {
- largeObject = new byte[5*1024*1024];
+ largeObject = new byte[16*1024*1024];
System.out.println("Creating garbage");
// create 128MB of garbage. This should result in at least one GC,
// some of them with to-space exhaustion.
--- a/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/gc/g1/TestHumongousAllocInitialMark.java Mon Jan 26 17:00:39 2015 -0800
@@ -31,7 +31,9 @@
import com.oracle.java.testlibrary.*;
public class TestHumongousAllocInitialMark {
- private static final int heapSize = 200; // MB
+ // Heap sizes < 224 MB are increased to 224 MB if vm_page_size == 64K to
+ // fulfill alignment constraints.
+ private static final int heapSize = 224; // MB
private static final int heapRegionSize = 1; // MB
private static final int initiatingHeapOccupancyPercent = 50; // %
--- a/hotspot/test/runtime/6888954/vmerrors.sh Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/runtime/6888954/vmerrors.sh Mon Jan 26 17:00:39 2015 -0800
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -71,11 +71,12 @@
# EXCEPTION_ACCESS_VIOLATION - Win-*
# SIGBUS - Solaris SPARC-64
# SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-*
+# SIGILL - Aix
#
# Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-*
# gets its signal at a PC in test_error_handler().
#
-bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc='
+bad_func_ptr_re='(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc='
guarantee_re='guarantee[(](str|num).*failed: *'
fatal_re='fatal error: *'
tail_1='.*expected null'
--- a/hotspot/test/runtime/7194254/Test7194254.java Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 7194254
- * @summary Creates several threads with different java priorities and checks
- * whether jstack reports correct priorities for them.
- *
- * @ignore 8060219
- * @run main Test7194254
- */
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CyclicBarrier;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class Test7194254 {
-
- public static void main(String[] args) throws Exception {
- final int NUMBER_OF_JAVA_PRIORITIES =
- Thread.MAX_PRIORITY - Thread.MIN_PRIORITY + 1;
- final CyclicBarrier barrier =
- new CyclicBarrier(NUMBER_OF_JAVA_PRIORITIES + 1);
-
- for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) {
- final int priority = p;
- new Thread("Priority=" + p) {
- {
- setPriority(priority);
- }
- public void run() {
- try {
- barrier.await(); // 1st
- barrier.await(); // 2nd
- } catch (Exception exc) {
- // ignore
- }
- }
- }.start();
- }
- barrier.await(); // 1st
-
- int matches = 0;
- List<String> failed = new ArrayList<>();
- try {
- String pid = getPid();
- String jstack = System.getProperty("java.home") + "/../bin/jstack";
- Process process = new ProcessBuilder(jstack, pid)
- .redirectErrorStream(true).start();
- Pattern pattern = Pattern.compile(
- "\\\"Priority=(\\d+)\\\".* prio=(\\d+).*");
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(process.getInputStream()))) {
- String line;
- while((line = reader.readLine()) != null) {
- Matcher matcher = pattern.matcher(line);
- if (matcher.matches()) {
- matches += 1;
- String expected = matcher.group(1);
- String actual = matcher.group(2);
- if (!expected.equals(actual)) {
- failed.add(line);
- }
- }
- }
- }
- barrier.await(); // 2nd
- } finally {
- barrier.reset();
- }
-
- if (matches != NUMBER_OF_JAVA_PRIORITIES) {
- throw new AssertionError("matches: expected " +
- NUMBER_OF_JAVA_PRIORITIES + ", but was " + matches);
- }
- if (!failed.isEmpty()) {
- throw new AssertionError(failed.size() + ":" + failed);
- }
- System.out.println("Test passes.");
- }
-
- static String getPid() {
- RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean();
- String vmname = runtimebean.getName();
- int i = vmname.indexOf('@');
- if (i != -1) {
- vmname = vmname.substring(0, i);
- }
- return vmname;
- }
-
-}
-
--- a/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/runtime/CommandLine/CompilerConfigFileWarning.java Mon Jan 26 17:00:39 2015 -0800
@@ -43,7 +43,7 @@
pb = ProcessTools.createJavaProcessBuilder("-XX:CompileCommandFile=hs_comp.txt", "-version");
output = new OutputAnalyzer(pb.start());
- output.shouldContain("CompilerOracle: unrecognized line");
+ output.shouldContain("CompileCommand: unrecognized command");
output.shouldContain("aaa aaa");
// Skip on debug builds since we'll always read the file there
--- a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java Mon Jan 26 17:00:39 2015 -0800
@@ -27,6 +27,7 @@
* @summary Test that you can decrease NMT tracking level but not increase it.
* @key nmt
* @library /testlibrary /../../test/lib
+ * @ignore 8067167
* @build ChangeTrackingLevel
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java Mon Jan 26 17:00:39 2015 -0800
@@ -27,6 +27,7 @@
* @bug 8005936 8058606
* @summary Verify PrintNMTStatistics on normal JVM exit for detail and summary tracking level
* @library /testlibrary
+ * @ignore 8067167
*/
import com.oracle.java.testlibrary.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/MaxMetaspaceSize.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8067187
+ * @summary Testing CDS dumping with the -XX:MaxMetaspaceSize=<size> option
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class MaxMetaspaceSize {
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:MaxMetaspaceSize=20m", "-Xshare:dump");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("is not large enough.\nEither don't specify the -XX:MaxMetaspaceSize=<size>\nor increase the size to at least");
+ output.shouldHaveExitValue(2);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Thread/ThreadPriorities.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7194254
+ * @summary Creates several threads with different java priorities and checks
+ * whether jstack reports correct priorities for them.
+ *
+ * @library /testlibrary
+ * @run main ThreadPriorities
+ */
+
+import java.util.ArrayList;
+import java.util.concurrent.CyclicBarrier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.java.testlibrary.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class ThreadPriorities {
+
+ public static void main(String[] args) throws Throwable {
+ final int NUMBER_OF_JAVA_PRIORITIES =
+ Thread.MAX_PRIORITY - Thread.MIN_PRIORITY + 1;
+ final CyclicBarrier barrier =
+ new CyclicBarrier(NUMBER_OF_JAVA_PRIORITIES + 1);
+
+ for (int p = Thread.MIN_PRIORITY; p <= Thread.MAX_PRIORITY; ++p) {
+ final int priority = p;
+ new Thread("Priority=" + p) {
+ {
+ setPriority(priority);
+ }
+ public void run() {
+ try {
+ barrier.await(); // 1st
+ barrier.await(); // 2nd
+ } catch (Exception exc) {
+ // ignore
+ }
+ }
+ }.start();
+ }
+ barrier.await(); // 1st
+
+ int matches = 0;
+ ArrayList<String> failed = new ArrayList<>();
+ ProcessBuilder pb = new ProcessBuilder(
+ JDKToolFinder.getJDKTool("jstack"),
+ String.valueOf(ProcessTools.getProcessId()));
+
+ String[] output = new OutputAnalyzer(pb.start()).getOutput().split("\\n+");
+
+ Pattern pattern = Pattern.compile(
+ "\\\"Priority=(\\d+)\\\".* prio=(\\d+).*");
+ for (String line : output) {
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.matches()) {
+ matches += 1;
+ String expected = matcher.group(1);
+ String actual = matcher.group(2);
+ if (!expected.equals(actual)) {
+ failed.add(line);
+ }
+ }
+ }
+ barrier.await(); // 2nd
+ barrier.reset();
+
+ assertEquals(matches, NUMBER_OF_JAVA_PRIORITIES);
+ assertTrue(failed.isEmpty(), failed.size() + ":" + failed);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/Reallocate.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8058897
+ * @library /testlibrary
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:MallocMaxTestWords=100m Reallocate
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class Reallocate {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+
+ long address = unsafe.allocateMemory(1);
+ assertNotEquals(address, 0L);
+
+ // Make sure we reallocate correctly
+ unsafe.putByte(address, Byte.MAX_VALUE);
+ address = unsafe.reallocateMemory(address, 2);
+ assertNotEquals(address, 0L);
+ assertEquals(unsafe.getByte(address), Byte.MAX_VALUE);
+
+ // Reallocating with a 0 size should return a null pointer
+ address = unsafe.reallocateMemory(address, 0);
+ assertEquals(address, 0L);
+
+ // Reallocating with a null pointer should result in a normal allocation
+ address = unsafe.reallocateMemory(0L, 1);
+ assertNotEquals(address, 0L);
+ unsafe.putByte(address, Byte.MAX_VALUE);
+ assertEquals(unsafe.getByte(address), Byte.MAX_VALUE);
+
+ // Make sure we can throw an OOME when we fail to reallocate due to OOM
+ try {
+ unsafe.reallocateMemory(address, 100 * 1024 * 1024 * 8);
+ } catch (OutOfMemoryError e) {
+ // Expected
+ return;
+ }
+ throw new RuntimeException("Did not get expected OOM");
+ }
+}
--- a/hotspot/test/runtime/whitebox/WBStackSize.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/runtime/whitebox/WBStackSize.java Mon Jan 26 17:00:39 2015 -0800
@@ -47,7 +47,7 @@
static final long K = 1024;
static final long MIN_STACK_SIZE = 8 * K;
- static final long MAX_STACK_SIZE_ALLOCATED_IN_MAIN = 200 * K; // current value is about 130k on 64-bit platforms
+ static final long MAX_STACK_SIZE_ALLOCATED_IN_MAIN = 150 * K; // current value is about 130k on 64-bit platforms
static final WhiteBox wb = WhiteBox.getWhiteBox();
@@ -82,8 +82,10 @@
public static void main(String[] args) {
long configStackSize = wb.getIntxVMFlag("ThreadStackSize") * K;
+ System.out.println("ThreadStackSize VM option: " + configStackSize);
- System.out.println("ThreadStackSize VM option: " + configStackSize);
+ long stackProtectionSize = wb.getIntxVMFlag("StackShadowPages") * wb.getVMPageSize();
+ System.out.println("Size of protected shadow pages: " + stackProtectionSize);
long actualStackSize = wb.getThreadStackSize();
System.out.println("Full stack size: " + actualStackSize);
@@ -96,14 +98,16 @@
long remainingStackSize = wb.getThreadRemainingStackSize();
System.out.println("Remaining stack size in main(): " + remainingStackSize);
- // Up to 200k can be already allocated by VM
+ // Up to 150k can be already allocated by VM and some space is used for stack protection.
+ long spaceAlreadyOccupied = MAX_STACK_SIZE_ALLOCATED_IN_MAIN + stackProtectionSize;
+
if (remainingStackSize > configStackSize
- || (configStackSize > MAX_STACK_SIZE_ALLOCATED_IN_MAIN
- && remainingStackSize < configStackSize - MAX_STACK_SIZE_ALLOCATED_IN_MAIN)) {
+ || (configStackSize > spaceAlreadyOccupied
+ && remainingStackSize < configStackSize - spaceAlreadyOccupied)) {
throw new RuntimeException("getThreadRemainingStackSize value [" + remainingStackSize
+ "] should be at least ThreadStackSize value [" + configStackSize + "] minus ["
- + MAX_STACK_SIZE_ALLOCATED_IN_MAIN + "]");
+ + spaceAlreadyOccupied + "]");
}
testStackOverflow();
--- a/hotspot/test/serviceability/dcmd/DynLibDcmdTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/serviceability/dcmd/DynLibDcmdTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -3,7 +3,7 @@
import com.oracle.java.testlibrary.Platform;
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,14 +39,16 @@
String result = DcmdUtil.executeDcmd("VM.dynlibs");
String osDependentBaseString = null;
- if (Platform.isSolaris()) {
+ if (Platform.isAix()) {
+ osDependentBaseString = "lib%s.so";
+ } else if (Platform.isLinux()) {
+ osDependentBaseString = "lib%s.so";
+ } else if (Platform.isOSX()) {
+ osDependentBaseString = "lib%s.dylib";
+ } else if (Platform.isSolaris()) {
osDependentBaseString = "lib%s.so";
} else if (Platform.isWindows()) {
osDependentBaseString = "%s.dll";
- } else if (Platform.isOSX()) {
- osDependentBaseString = "lib%s.dylib";
- } else if (Platform.isLinux()) {
- osDependentBaseString = "lib%s.so";
}
if (osDependentBaseString == null) {
--- a/hotspot/test/test_env.sh Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/test_env.sh Mon Jan 26 17:00:39 2015 -0800
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
- SunOS | Linux | Darwin )
+ AIX | Darwin | Linux | SunOS )
NULL=/dev/null
PS=":"
FS="/"
@@ -133,26 +133,31 @@
fi
VM_OS="unknown"
-grep "solaris" vm_version.out > ${NULL}
+grep "aix" vm_version.out > ${NULL}
if [ $? = 0 ]
then
- VM_OS="solaris"
+ VM_OS="aix"
+fi
+grep "bsd" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+ VM_OS="bsd"
fi
grep "linux" vm_version.out > ${NULL}
if [ $? = 0 ]
then
VM_OS="linux"
fi
+grep "solaris" vm_version.out > ${NULL}
+if [ $? = 0 ]
+then
+ VM_OS="solaris"
+fi
grep "windows" vm_version.out > ${NULL}
if [ $? = 0 ]
then
VM_OS="windows"
fi
-grep "bsd" vm_version.out > ${NULL}
-if [ $? = 0 ]
-then
- VM_OS="bsd"
-fi
VM_CPU="unknown"
grep "sparc" vm_version.out > ${NULL}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Platform.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -68,6 +68,18 @@
return dataModel.equals("64");
}
+ public static boolean isAix() {
+ return isOs("aix");
+ }
+
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
public static boolean isSolaris() {
return isOs("sunos");
}
@@ -76,14 +88,6 @@
return isOs("win");
}
- public static boolean isOSX() {
- return isOs("mac");
- }
-
- public static boolean isLinux() {
- return isOs("linux");
- }
-
private static boolean isOs(String osname) {
return osName.toLowerCase().startsWith(osname.toLowerCase());
}
@@ -140,7 +144,9 @@
*/
public static boolean shouldSAAttach() throws Exception {
- if (isLinux()) {
+ if (isAix()) {
+ return false; // SA not implemented.
+ } else if (isLinux()) {
return canPtraceAttachLinux();
} else if (isOSX()) {
return canAttachOSX();
--- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Jan 22 22:42:33 2015 -0800
+++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Mon Jan 26 17:00:39 2015 -0800
@@ -45,7 +45,7 @@
private static enum MethodGroup {
ARCH("isARM", "isPPC", "isSparc", "isX86", "isX64"),
BITNESS("is32bit", "is64bit"),
- OS("isLinux", "isSolaris", "isWindows", "isOSX"),
+ OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"),
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"),
IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach",
"canPtraceAttachLinux", "canAttachOSX", "isTieredSupported");
--- a/jaxp/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxp/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
0cb0844b58924d6086d2850c22087d06679d5eef jdk9-b44
0dab3e848229127c7aca4c58b98e2d90ba70372f jdk9-b45
74eaf7ad986576c792df4dbff05eed63e5727695 jdk9-b46
+e391de88e69b59d7c618387e3cf91032f6991ce9 jdk9-b47
--- a/jaxws/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -292,3 +292,4 @@
2a03baa4d849818ff6d635f110c2813b12fc2326 jdk9-b44
e529374fbe526dbd668e5e98fc047b42b3bc6d33 jdk9-b45
64ca52b0bda8028636e4ccafbe1107befcdda47d jdk9-b46
+6c17d648d03e4bf4729c3645f8db55d34115e0b7 jdk9-b47
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/api/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/api/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/model/impl/RuntimeBuiltinLeafInfoImpl.java Mon Jan 26 17:00:39 2015 -0800
@@ -205,7 +205,15 @@
static {
- QName[] qnames = (System.getProperty(MAP_ANYURI_TO_URI) == null) ? new QName[] {
+ String MAP_ANYURI_TO_URI_VALUE = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return System.getProperty(MAP_ANYURI_TO_URI);
+ }
+ }
+ );
+ QName[] qnames = (MAP_ANYURI_TO_URI_VALUE == null) ? new QName[] {
createXS("string"),
createXS("anySimpleType"),
createXS("normalizedString"),
@@ -318,7 +326,7 @@
return v.toExternalForm();
}
});
- if (System.getProperty(MAP_ANYURI_TO_URI) == null) {
+ if (MAP_ANYURI_TO_URI_VALUE == null) {
secondaryList.add(
new StringImpl<URI>(URI.class, createXS("string")) {
public URI parse(CharSequence text) throws SAXException {
@@ -782,17 +790,18 @@
}
});
primaryList.add(
- new StringImpl<BigDecimal>(BigDecimal.class,
- createXS("decimal")
+ new StringImpl<BigDecimal>(BigDecimal.class,
+ createXS("decimal")
) {
- public BigDecimal parse(CharSequence text) {
- return DatatypeConverterImpl._parseDecimal(text.toString());
+ public BigDecimal parse(CharSequence text) {
+ return DatatypeConverterImpl._parseDecimal(text.toString());
+ }
+
+ public String print(BigDecimal v) {
+ return DatatypeConverterImpl._printDecimal(v);
+ }
}
-
- public String print(BigDecimal v) {
- return DatatypeConverterImpl._printDecimal(v);
- }
- });
+ );
primaryList.add(
new StringImpl<QName>(QName.class,
createXS("QName")
@@ -820,7 +829,7 @@
w.getNamespaceContext().declareNamespace(v.getNamespaceURI(),v.getPrefix(),false);
}
});
- if (System.getProperty(MAP_ANYURI_TO_URI) != null) {
+ if (MAP_ANYURI_TO_URI_VALUE != null) {
primaryList.add(
new StringImpl<URI>(URI.class, createXS("anyURI")) {
public URI parse(CharSequence text) throws SAXException {
@@ -838,16 +847,17 @@
});
}
primaryList.add(
- new StringImpl<Duration>(Duration.class, createXS("duration")) {
- public String print(Duration duration) {
- return duration.toString();
- }
+ new StringImpl<Duration>(Duration.class, createXS("duration")) {
+ public String print(Duration duration) {
+ return duration.toString();
+ }
- public Duration parse(CharSequence lexical) {
- TODO.checkSpec("JSR222 Issue #42");
- return DatatypeConverterImpl.getDatatypeFactory().newDuration(lexical.toString());
+ public Duration parse(CharSequence lexical) {
+ TODO.checkSpec("JSR222 Issue #42");
+ return DatatypeConverterImpl.getDatatypeFactory().newDuration(lexical.toString());
+ }
}
- });
+ );
primaryList.add(
new StringImpl<Void>(Void.class) {
// 'void' binding isn't defined by the spec, but when the JAX-RPC processes user-defined
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/model/impl/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/model/impl/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/property/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/property/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/util/XmlFactory.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/util/XmlFactory.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
package com.sun.xml.internal.bind.v2.util;
-import com.sun.xml.internal.bind.Util;
import com.sun.xml.internal.bind.v2.Messages;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
@@ -43,8 +45,6 @@
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
-import static com.sun.xml.internal.bind.Util.getSystemProperty;
-
/**
* Provides helper methods for creating properly configured XML parser
* factory instances with namespace support turned on and configured for
@@ -68,7 +68,14 @@
*/
private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.bind.disableXmlSecurity";
- public static final boolean XML_SECURITY_DISABLED = Boolean.parseBoolean(getSystemProperty(DISABLE_XML_SECURITY));
+ private static final boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
+ new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ return Boolean.getBoolean(DISABLE_XML_SECURITY);
+ }
+ }
+ );
private static boolean isXMLSecurityDisabled(boolean runtimeSetting) {
return XML_SECURITY_DISABLED || runtimeSetting;
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -54,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -72,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/ProviderImpl.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/ProviderImpl.java Mon Jan 26 17:00:39 2015 -0800
@@ -147,19 +147,12 @@
}
public EndpointReference readEndpointReference(final Source eprInfoset) {
- // EPR constructors are private, so we need privilege escalation.
- // this unmarshalling can only access instances of a fixed, known set of classes,
- // so doing that shouldn't introduce security vulnerability.
- return AccessController.doPrivileged(new PrivilegedAction<EndpointReference>() {
- public EndpointReference run() {
- try {
- Unmarshaller unmarshaller = eprjc.get().createUnmarshaller();
- return (EndpointReference) unmarshaller.unmarshal(eprInfoset);
- } catch (JAXBException e) {
- throw new WebServiceException("Error creating Marshaller or marshalling.", e);
- }
- }
- });
+ try {
+ Unmarshaller unmarshaller = eprjc.get().createUnmarshaller();
+ return (EndpointReference) unmarshaller.unmarshal(eprInfoset);
+ } catch (JAXBException e) {
+ throw new WebServiceException("Error creating Marshaller or marshalling.", e);
+ }
}
public <T> T getPort(EndpointReference endpointReference, Class<T> clazz, WebServiceFeature... webServiceFeatures) {
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -54,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -72,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java Mon Jan 26 17:00:39 2015 -0800
@@ -63,6 +63,8 @@
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
@@ -84,12 +86,16 @@
private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
- private static boolean XML_SECURITY_DISABLED;
+ private static final String DISABLE_XML_SECURITY = "com.sun.xml.internal.ws.disableXmlSecurity";
- static {
- String disableXmlSecurity = System.getProperty("com.sun.xml.internal.ws.disableXmlSecurity");
- XML_SECURITY_DISABLED = disableXmlSecurity == null || !Boolean.valueOf(disableXmlSecurity);
- }
+ private static boolean XML_SECURITY_DISABLED = AccessController.doPrivileged(
+ new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ return Boolean.getBoolean(DISABLE_XML_SECURITY);
+ }
+ }
+ );
public static String getPrefix(String s) {
int i = s.indexOf(':');
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/nav/Utils.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/nav/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -38,6 +38,9 @@
/**
* Utils class.
+ *
+ * WARNING: If you are doing any changes don't forget to change other Utils classes in different packages.
+ *
* Has *package private* access to avoid inappropriate usage.
*/
final class Utils {
@@ -51,17 +54,20 @@
static { // we statically initializing REFLECTION_NAVIGATOR property
try {
- Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
- //noinspection unchecked
- final Method getInstance = refNav.getDeclaredMethod("getInstance");
+ final Class refNav = Class.forName("com.sun.xml.internal.bind.v2.model.nav.ReflectionNavigator");
// requires accessClassInPackage privilege
- AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
+ final Method getInstance = AccessController.doPrivileged(
+ new PrivilegedAction<Method>() {
@Override
- public Object run() {
- getInstance.setAccessible(true);
- return null;
+ public Method run() {
+ try {
+ Method getInstance = refNav.getDeclaredMethod("getInstance");
+ getInstance.setAccessible(true);
+ return getInstance;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
+ }
}
}
);
@@ -69,16 +75,10 @@
//noinspection unchecked
REFLECTION_NAVIGATOR = (Navigator<Type, Class, Field, Method>) getInstance.invoke(null);
} catch (ClassNotFoundException e) {
- e.printStackTrace();
throw new IllegalStateException("Can't find ReflectionNavigator class");
} catch (InvocationTargetException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance throws the exception");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- throw new IllegalStateException("ReflectionNavigator.getInstance can't be found");
} catch (IllegalAccessException e) {
- e.printStackTrace();
throw new IllegalStateException("ReflectionNavigator.getInstance method is inaccessible");
} catch (SecurityException e) {
LOGGER.log(Level.FINE, "Unable to access ReflectionNavigator.getInstance", e);
--- a/jdk/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
8cc4dc300041eb70a7a40e4b2431a8f4d4965ea4 jdk9-b44
9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45
efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46
+b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47
--- a/jdk/make/Tools.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/Tools.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -34,28 +34,23 @@
include NativeCompilation.gmk
include SetupJavaCompilers.gmk
-# The exception handling of swing beaninfo which have the own tool directory
-ifeq (, $(BUILD_TOOLS_JDK))
- $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
- SETUP := GENERATE_OLDBYTECODE, \
- ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
- SRC := $(JDK_TOPDIR)/make/src/classes, \
- BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
- COPY := boot.modules ext.modules))
-endif
+################################################################################
+
+$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
+ SRC := $(JDK_TOPDIR)/make/src/classes, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
+ COPY := boot.modules ext.modules))
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/%.template: \
- $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/%.template
- $(call install-file)
-
-BUILD_TOOLS_JDK += $(foreach i, $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template), $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/$(notdir $i))
+$(eval $(call SetupCopyFiles,COPY_NIMBUS_TEMPLATES, \
+ SRC := $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus, \
+ DEST := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources, \
+ FILES := $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template)))
-# Resource used by CheckDeps tool
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed: \
- $(JDK_TOPDIR)/make/data/checkdeps/refs.allowed
- $(call install-file)
+BUILD_TOOLS_JDK += $(COPY_NIMBUS_TEMPLATES)
-BUILD_TOOLS_JDK += $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed
+################################################################################
# Add a checksum ("jsum") to the end of a text file. Prevents trivial tampering with class lists.
TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
@@ -130,10 +125,6 @@
TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
build.tools.cldrconverter.CLDRConverter
-TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
- -cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
- build.tools.deps.CheckDeps
-
TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
-cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
build.tools.module.GenJdepsModulesXml
@@ -161,25 +152,25 @@
# Tools needed on solaris because OBJCOPY is broken.
ifeq ($(OPENJDK_TARGET_OS), solaris)
-$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
- SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
- LDFLAGS := -lelf, \
- OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
- OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
- PROGRAM := add_gnu_debuglink))
+ $(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
+ SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
+ LANG := C, \
+ CC := $(BUILD_CC), \
+ LDEXE := $(BUILD_LD), \
+ LDFLAGS := -lelf, \
+ OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
+ OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+ PROGRAM := add_gnu_debuglink))
-$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
- SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
- LDFLAGS := -lelf, \
- OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
- OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
- PROGRAM := fix_empty_sec_hdr_flags))
+ $(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
+ SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
+ LANG := C, \
+ CC := $(BUILD_CC), \
+ LDEXE := $(BUILD_LD), \
+ LDFLAGS := -lelf, \
+ OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
+ OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+ PROGRAM := fix_empty_sec_hdr_flags))
endif
$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE)
--- a/jdk/make/data/checkdeps/refs.allowed Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# This properties-formatted file contains the names of the non-existent types
-# that are allowed to be referenced from classes in a profiles image.
-#
-# The property key is a type that does not exist. The property value is one or
-# more types that reference the missing type. The property value also encodes
-# the names of the profiles where this reference is allowed.
-
-# jsse.jar is not subsetted by the profiles build. For compact1 and compact2
-# then this means that there are references to Kerberos types that do not
-# exist. These references are harmless.
-#
-javax.security.auth.kerberos.KerberosKey=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosPrincipal=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosTicket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-javax.security.auth.kerberos.KeyTab=sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.ServicePermission=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.GSSCaller=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.Krb5Util=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.ServiceCreds=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptedData= sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptionKey=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.crypto.KeyUsage=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.EncTicketPart=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Krb5=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Ticket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.KrbException=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.PrincipalName=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-
-# Residual references to java.beans.
-# The RemoveMethods tool does not yet purge the constant pool.
-#
-java.beans.PropertyChangeListener=java.util.logging.LogManager,compact1,compact2,compact3
--- a/jdk/make/gensrc/GensrcMisc.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/gensrc/GensrcMisc.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -28,6 +28,13 @@
# string and the runtime name into the Version.java file.
# To be printed by java -version
+# These dependencies should ideally be added to prerequesites for Version.java
+# but skip for now until we have better incremental build for java.
+# $(call DependOnVariable, LAUNCHER_NAME) \
+# $(call DependOnVariable, RELEASE) \
+# $(call DependOnVariable, FULL_VERSION) \
+# $(call DependOnVariable, RUNTIME_VERSION)
+
$(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java: \
$(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template
$(MKDIR) -p $(@D)
--- a/jdk/make/lib/CoreLibraries.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -74,8 +74,6 @@
##########################################################################################
-BUILD_LIBVERIFY_SRC := check_code.c check_format.c
-
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
BUILD_LIBVERIFY_REORDER := $(JDK_TOPDIR)/make/mapfiles/libverify/reorder-$(OPENJDK_TARGET_CPU)
@@ -116,10 +114,6 @@
LIBJAVA_SRC_DIRS := $(call FindSrcDirsForLib, java.base, java)
-ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBJAVA_EXCLUDE_FILES += $(JDK_TOPDIR)/src/java.base/unix/native/libjava/HostLocaleProviderAdapter_md.c
-endif
-
LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \
-I$(JDK_TOPDIR)/src/java.base/share/native/libfdlibm \
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
@@ -134,9 +128,7 @@
LIBJAVA_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"'
endif
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- LIBJAVA_EXCLUDE_FILES += java_props_macosx.c
-else
+ifeq ($(OPENJDK_TARGET_OS), macosx)
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
endif
@@ -151,8 +143,6 @@
LIBRARY := java, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVA_SRC_DIRS), \
- EXCLUDES := fdlibm/src zip prefs, \
- EXCLUDE_FILES := $(LIBJAVA_EXCLUDE_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
@@ -247,19 +237,10 @@
##########################################################################################
-BUILD_LIBJLI_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libjli \
- $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli
+LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli)
LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
-BUILD_LIBJLI_FILES := \
- java.c \
- splashscreen_stubs.c \
- parse_manifest.c \
- version_comp.c \
- wildcard.c \
- jli_util.c
-
ifeq ($(JVM_VARIANT_ZERO), true)
ERGO_FAMILY := zero
else
@@ -269,68 +250,55 @@
ERGO_FAMILY := $(OPENJDK_TARGET_CPU_ARCH)
endif
endif
+LIBJLI_ALL_ERGO := $(wildcard $(addsuffix /ergo_*.c, $(LIBJLI_SRC_DIRS)))
+LIBJLI_EXCLUDE_ERGO := $(filter-out %/ergo_$(ERGO_FAMILY).c, $(LIBJLI_ALL_ERGO))
+# If all specialized ergo files are excluded, use generic ergo
+ifeq ($(LIBJLI_ALL_ERGO), $(LIBJLI_EXCLUDE_ERGO))
+ LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
+endif
+LIBJLI_EXCLUDE_FILES += $(notdir $(LIBJLI_EXCLUDE_ERGO))
ifeq ($(OPENJDK_TARGET_OS), macosx)
- BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/macosx/native/libjli
- BUILD_LIBJLI_FILES += java_md_common.c java_md_macosx.c
+ LIBJLI_EXCLUDE_FILES += java_md_solinux.c ergo.c
BUILD_LIBJLI_java_md_macosx.c_CFLAGS := -x objective-c
BUILD_LIBJLI_STATIC_java_md_macosx.c_CFLAGS := -x objective-c
+
+ LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
- BUILD_LIBJLI_FILES += java_md.c \
- cmdtoargs.c
# Staticically link with c runtime on windows.
LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
-else ifneq ($(OPENJDK_TARGET_OS), macosx)
-
- BUILD_LIBJLI_FILES += java_md_common.c
- BUILD_LIBJLI_FILES += java_md_solinux.c ergo.c
-
- ERGO_ARCH_FILE = ergo_$(ERGO_FAMILY).c
-
- # if the architecture specific ergo file exists then
- # use it, else use the generic definitions from ergo.c
- ifneq ($(wildcard $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli/$(ERGO_ARCH_FILE)), )
- BUILD_LIBJLI_FILES += $(ERGO_ARCH_FILE)
- else # !ERGO_ARCH_FILE
- LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
- endif # ERGO_ARCH_FILE
-endif #WINDOWS
-
-LIBJLI_CFLAGS += $(foreach dir, $(BUILD_LIBJLI_SRC_DIRS), -I$(dir))
-
-# Append defines depending on target platform
-LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
-
-ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
-endif
-
-ifneq ($(USE_EXTERNAL_LIBZ), true)
- BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8
- LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
- BUILD_LIBJLI_FILES += \
- inflate.c \
- inftrees.c \
- inffast.c \
- zadler32.c \
- zcrc32.c \
- zutil.c
-endif
-
-ifeq ($(OPENJDK_TARGET_OS), windows)
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)
else
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli
endif
+LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
+
+# Append defines depending on target platform
+LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
+
+ifneq ($(USE_EXTERNAL_LIBZ), true)
+ LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
+ LIBJLI_EXTRA_FILES += \
+ $(addprefix $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8/, \
+ inflate.c \
+ inftrees.c \
+ inffast.c \
+ zadler32.c \
+ zcrc32.c \
+ zutil.c \
+ )
+endif
+
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
LIBRARY := jli, \
OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(LIBJLI_CFLAGS), \
@@ -376,8 +344,9 @@
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
STATIC_LIBRARY := jli_static, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
@@ -395,8 +364,9 @@
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
LIBRARY := jli_static, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
@@ -411,16 +381,17 @@
else ifeq ($(OPENJDK_TARGET_OS), aix)
# AIX also requires a static libjli because the compiler doesn't support '-rpath'
- $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC,\
- STATIC_LIBRARY:=jli_static,\
- OUTPUT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE),\
- SRC:=$(BUILD_LIBJLI_SRC_DIRS),\
- INCLUDE_FILES:=$(BUILD_LIBJLI_FILES),\
- LANG:=C,\
- OPTIMIZATION:=HIGH, \
- CFLAGS:=$(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS),\
- ARFLAGS:=$(ARFLAGS),\
- OBJECT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
+ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
+ STATIC_LIBRARY := jli_static, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
+ LANG := C, \
+ OPTIMIZATION := HIGH, \
+ CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
+ ARFLAGS := $(ARFLAGS), \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
TARGETS += $(BUILD_LIBJLI_STATIC)
--- a/jdk/make/lib/Lib-jdk.attach.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.attach.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -31,7 +31,7 @@
$(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
LIBRARY := attach, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \
+ SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
--- a/jdk/make/lib/Lib-jdk.security.auth.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.security.auth.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -28,9 +28,7 @@
################################################################################
LIBJAAS_MAPFILE :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
- LIBJAAS_EXCLUDE_FILES := Solaris.c
-else
+ifeq ($(OPENJDK_TARGET_OS), solaris)
# only on solaris...wonder why
LIBJAAS_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjaas/mapfile-vers
endif
@@ -43,7 +41,7 @@
$(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
LIBRARY := $(LIBJAAS_NAME), \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(JDK_TOPDIR)/src/jdk.security.auth/$(OPENJDK_TARGET_OS_TYPE)/native/libjaas, \
+ SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \
@@ -53,7 +51,6 @@
LDFLAGS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib, \
LDFLAGS_SUFFIX_windows := $(LDFLAGS_JDKLIB_SUFFIX), \
LDFLAGS_SUFFIX_solaris := -lc, \
- EXCLUDE_FILES := $(LIBJAAS_EXCLUDE_FILES), \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=$(LIBJAAS_NAME).dll" \
--- a/jdk/make/lib/NetworkingLibraries.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/lib/NetworkingLibraries.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -23,39 +23,16 @@
# questions.
#
-LIBNET_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libnet \
- $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnet
-LIBNET_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
- $(LIBJAVA_HEADER_FLAGS)
-
-LIBNET_CFLAGS += $(foreach dir, $(LIBNET_SRC_DIRS), -I$(dir))
-
-LIBNET_EXCLUDE_FILES :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
- LIBNET_EXCLUDE_FILES += solaris_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), linux)
- LIBNET_EXCLUDE_FILES += linux_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- LIBNET_EXCLUDE_FILES += bsd_close.c
-endif
-
-ifeq ($(OPENJDK_TARGET_OS), aix)
- LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/
-endif
+LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net)
$(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
LIBRARY := net, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBNET_SRC_DIRS), \
- EXCLUDE_FILES := $(LIBNET_EXCLUDE_FILES), \
LANG := C, \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) \
- $(LIBNET_CFLAGS), \
+ CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+ $(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/jdk/make/lib/NioLibraries.gmk Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/lib/NioLibraries.gmk Mon Jan 26 17:00:39 2015 -0800
@@ -65,7 +65,6 @@
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBNIO_SRC), \
EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
- EXCLUDES := sctp, \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -214,10 +214,10 @@
Java_java_lang_Throwable_fillInStackTrace;
Java_java_lang_Throwable_getStackTraceDepth;
Java_java_lang_Throwable_getStackTraceElement;
- Java_java_lang_UNIXProcess_init;
- Java_java_lang_UNIXProcess_waitForProcessExit;
- Java_java_lang_UNIXProcess_forkAndExec;
- Java_java_lang_UNIXProcess_destroyProcess;
+ Java_java_lang_ProcessImpl_init;
+ Java_java_lang_ProcessImpl_waitForProcessExit;
+ Java_java_lang_ProcessImpl_forkAndExec;
+ Java_java_lang_ProcessImpl_destroyProcess;
Java_java_nio_Bits_copyFromShortArray;
Java_java_nio_Bits_copyToShortArray;
Java_java_nio_Bits_copyFromIntArray;
--- a/jdk/make/src/classes/build/tools/deps/CheckDeps.java Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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 build.tools.deps;
-
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.charset.StandardCharsets;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.classfile.Dependencies;
-import com.sun.tools.classfile.Dependency;
-
-/**
- * A simple tool to check the JAR files in a JRE image to ensure that there
- * aren't any references to types that do not exist. The tool is intended to
- * be used in the JDK "profiles" build to help ensure that the profile
- * definitions are kept up to date.
- */
-
-public class CheckDeps {
-
- // classfile API for finding dependencies
- static final Dependency.Finder finder = Dependencies.getClassDependencyFinder();
-
- // "known types", found in rt.jar or other JAR files
- static final Set<String> knownTypes = new HashSet<>();
-
- // References to unknown types. The map key is the unknown type, the
- // map value is the set of classes that reference it.
- static final Map<String,Set<String>> unknownRefs = new HashMap<>();
-
- // The property name is the name of an unknown type that is allowed to be
- // references. The property value is a comma separated list of the types
- // that are allowed to reference it. The list also includes the names of
- // the profiles that the reference is allowed.
- static final Properties allowedBadRefs = new Properties();
-
- /**
- * Returns the class name for the given class file. In the case of inner
- * classes then the enclosing class is returned in order to keep the
- * rules simple.
- */
- static String toClassName(String s) {
- int i = s.indexOf('$');
- if (i > 0)
- s = s.substring(0, i);
- return s.replace("/", ".");
- }
-
- /**
- * Analyze the dependencies of all classes in the given JAR file. The
- * method updates knownTypes and unknownRefs as part of the analysis.
- */
- static void analyzeDependencies(Path jarpath) throws Exception {
- System.out.format("Analyzing %s%n", jarpath);
- try (JarFile jf = new JarFile(jarpath.toFile())) {
- Enumeration<JarEntry> entries = jf.entries();
- while (entries.hasMoreElements()) {
- JarEntry e = entries.nextElement();
- String name = e.getName();
- if (name.endsWith(".class")) {
- ClassFile cf = ClassFile.read(jf.getInputStream(e));
- for (Dependency d : finder.findDependencies(cf)) {
- String origin = toClassName(d.getOrigin().getName());
- String target = toClassName(d.getTarget().getName());
-
- // origin is now known
- unknownRefs.remove(origin);
- knownTypes.add(origin);
-
- // if the target is not known then record the reference
- if (!knownTypes.contains(target)) {
- Set<String> refs = unknownRefs.get(target);
- if (refs == null) {
- // first time seeing this unknown type
- refs = new HashSet<>();
- unknownRefs.put(target, refs);
- }
- refs.add(origin);
- }
- }
- }
- }
- }
- }
-
- /**
- * We have closure (no references to types that do not exist) if
- * unknownRefs is empty. When unknownRefs is not empty then it should
- * only contain references that are allowed to be present (these are
- * loaded from the refs.allowed properties file).
- *
- * @param the profile that is being tested, this determines the exceptions
- * in {@code allowedBadRefs} that apply.
- *
- * @return {@code true} if there are no missing types or the only references
- * to missing types are described by {@code allowedBadRefs}.
- */
- static boolean checkClosure(String profile) {
- // process the references to types that do not exist.
- boolean fail = false;
- for (Map.Entry<String,Set<String>> entry: unknownRefs.entrySet()) {
- String target = entry.getKey();
- for (String origin: entry.getValue()) {
- // check if origin -> target allowed
- String value = allowedBadRefs.getProperty(target);
- if (value == null) {
- System.err.format("%s -> %s (unknown type)%n", origin, target);
- fail = true;
- } else {
- // target is known, check if the origin is one that we
- // expect and that the exception applies to the profile.
- boolean found = false;
- boolean applicable = false;
- for (String s: value.split(",")) {
- s = s.trim();
- if (s.equals(origin))
- found = true;
- if (s.equals(profile))
- applicable = true;
- }
- if (!found || !applicable) {
- if (!found) {
- System.err.format("%s -> %s (not allowed)%n", origin, target);
- } else {
- System.err.format("%s -> %s (reference not applicable to %s)%n",
- origin, target, profile);
- }
- fail = true;
- }
- }
-
- }
- }
-
- return !fail;
- }
-
- static void fail(URL url) throws Exception {
- System.err.println("One or more unexpected references encountered");
- if (url != null)
- System.err.format("Check %s is up to date%n", Paths.get(url.toURI()));
- System.exit(-1);
- }
-
- public static void main(String[] args) throws Exception {
- // load properties file so that we know what missing types that are
- // allowed to be referenced.
- URL url = CheckDeps.class.getResource("refs.allowed");
- if (url != null) {
- try (InputStream in = url.openStream()) {
- allowedBadRefs.load(new InputStreamReader(in, StandardCharsets.UTF_8));
- }
- }
-
- if (args.length != 2) {
- System.err.println("Usage: java CheckDeps <image> <profile>");
- System.exit(-1);
- }
-
- String image = args[0];
- String profile = args[1];
-
- // process JAR files on boot class path
- Path lib = Paths.get(image, "lib");
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib, "*.jar")) {
- for (Path jarpath: stream) {
- analyzeDependencies(jarpath);
- }
- }
-
- // classes on boot class path should not reference other types
- boolean okay = checkClosure(profile);
- if (!okay)
- fail(url);
-
- // process JAR files in the extensions directory
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib.resolve("ext"), "*.jar")) {
- for (Path jarpath: stream) {
- analyzeDependencies(jarpath);
- }
- }
-
- // re-check to ensure that the extensions doesn't reference types that
- // do not exist.
- okay = checkClosure(profile);
- if (!okay)
- fail(url);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/aix/native/libnet/aix_close.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file contains implementations of NET_... functions. The NET_.. functions are
+ * wrappers for common file- and socket functions plus provisions for non-blocking IO.
+ *
+ * (basically, the layers remember all file descriptors waiting for a particular fd;
+ * all threads waiting on a certain fd can be woken up by sending them a signal; this
+ * is done e.g. when the fd is closed.)
+ *
+ * This was originally copied from the linux_close.c implementation.
+ *
+ * Side Note: This coding needs initialization. Under Linux this is done
+ * automatically via __attribute((constructor)), on AIX this is done manually
+ * (see aix_close_init).
+ *
+ */
+
+/*
+ AIX needs a workaround for I/O cancellation, see:
+ http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
+ ...
+ The close subroutine is blocked until all subroutines which use the file
+ descriptor return to usr space. For example, when a thread is calling close
+ and another thread is calling select with the same file descriptor, the
+ close subroutine does not return until the select call returns.
+ ...
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+ pthread_t thr; /* this thread */
+ struct threadEntry *next; /* next thread */
+ int intr; /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+ pthread_mutex_t lock; /* fd lock */
+ threadEntry_t *threads; /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = (SIGRTMAX - 1);
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable = NULL;
+static int fdCount = 0;
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ *
+ * On AIX we don't have __attribute((constructor)) so we need to initialize
+ * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
+ */
+void aix_close_init() {
+ struct rlimit nbr_files;
+ sigset_t sigset;
+ struct sigaction sa;
+
+ /* Check already initialized */
+ if (fdCount > 0 && fdTable != NULL) {
+ return;
+ }
+
+ /*
+ * Allocate table based on the maximum number of
+ * file descriptors.
+ */
+ if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
+ fprintf(stderr, "library initialization failed - "
+ "unable to get max # of allocated fds\n");
+ abort();
+ }
+ fdCount = nbr_files.rlim_max;
+ /*
+ * We have a conceptual problem here, when the number of files is
+ * unlimited. As a kind of workaround, we ensure the table is big
+ * enough for handle even a large number of files. Since SAP itself
+ * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
+ */
+ if (nbr_files.rlim_max == RLIM_INFINITY) {
+ fdCount = 64000;
+ }
+ fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+ if (fdTable == NULL) {
+ fprintf(stderr, "library initialization failed - "
+ "unable to allocate file descriptor table - out of memory");
+ abort();
+ }
+
+ {
+ int i;
+ for (i=0; i < fdCount; i++) {
+ pthread_mutex_init(&fdTable[i].lock, NULL);
+ }
+ }
+
+ /*
+ * Setup the signal handler
+ */
+ sa.sa_handler = sig_wakeup;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(sigWakeup, &sa, NULL);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, sigWakeup);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+ if (fd < 0 || fd >= fdCount) {
+ return NULL;
+ }
+ return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ * Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ self->thr = pthread_self();
+ self->intr = 0;
+
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ self->next = fdEntry->threads;
+ fdEntry->threads = self;
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ * Remove thread from thread list for the fd
+ * If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+ (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ int orig_errno = errno;
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ threadEntry_t *curr, *prev=NULL;
+ curr = fdEntry->threads;
+ while (curr != NULL) {
+ if (curr == self) {
+ if (curr->intr) {
+ orig_errno = EBADF;
+ }
+ if (prev == NULL) {
+ fdEntry->threads = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ break;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ * fd1 < 0 => close(fd2)
+ * fd1 >= 0 => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+ int rv, orig_errno;
+ fdEntry_t *fdEntry = getFdEntry(fd2);
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Lock the fd to hold-off additional I/O on this fd.
+ */
+ pthread_mutex_lock(&(fdEntry->lock));
+
+ {
+ /* On fast machines we see that we enter dup2 before the
+ * accepting thread had a chance to get and process the signal.
+ * So in case we woke a thread up, give it some time to cope.
+ * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */
+ int num_woken = 0;
+
+ /*
+ * Send a wakeup signal to all threads blocked on this
+ * file descriptor.
+ */
+ threadEntry_t *curr = fdEntry->threads;
+ while (curr != NULL) {
+ curr->intr = 1;
+ pthread_kill( curr->thr, sigWakeup );
+ num_woken ++;
+ curr = curr->next;
+ }
+
+ if (num_woken > 0) {
+ usleep(num_woken * 50);
+ }
+
+ /*
+ * And close/dup the file descriptor
+ * (restart if interrupted by signal)
+ */
+ do {
+ if (fd1 < 0) {
+ rv = close(fd2);
+ } else {
+ rv = dup2(fd1, fd2);
+ }
+ } while (rv == -1 && errno == EINTR);
+ }
+
+ /*
+ * Unlock without destroying errno
+ */
+ orig_errno = errno;
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+
+ return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+ if (fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+ return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while (ret == -1 && errno == EINTR); \
+ return ret; \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen) {
+ socklen_t socklen = *fromlen;
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
+ *fromlen = socklen;
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen) {
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
+ socklen_t socklen = *addrlen;
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
+ *addrlen = socklen;
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+ int crc = -1, prc = -1;
+ threadEntry_t self;
+ fdEntry_t* fdEntry = getFdEntry(s);
+
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /* On AIX, when the system call connect() is interrupted, the connection
+ * is not aborted and it will be established asynchronously by the kernel.
+ * Hence, no need to restart connect() when EINTR is received
+ */
+ startOp(fdEntry, &self);
+ crc = connect(s, addr, addrlen);
+ endOp(fdEntry, &self);
+
+ if (crc == -1 && errno == EINTR) {
+ struct pollfd s_pollfd;
+ int sockopt_arg = 0;
+ socklen_t len;
+
+ s_pollfd.fd = s;
+ s_pollfd.events = POLLOUT | POLLERR;
+
+ /* poll the file descriptor */
+ do {
+ startOp(fdEntry, &self);
+ prc = poll(&s_pollfd, 1, -1);
+ endOp(fdEntry, &self);
+ } while (prc == -1 && errno == EINTR);
+
+ if (prc < 0)
+ return prc;
+
+ len = sizeof(sockopt_arg);
+
+ /* Check whether the connection has been established */
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &sockopt_arg, &len) == -1)
+ return -1;
+
+ if (sockopt_arg != 0 ) {
+ errno = sockopt_arg;
+ return -1;
+ }
+ } else {
+ return crc;
+ }
+
+ /* At this point, fd is connected. Set successful return code */
+ return 0;
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for poll(s, timeout).
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+ long prevtime = 0, newtime;
+ struct timeval t;
+ fdEntry_t *fdEntry = getFdEntry(s);
+
+ /*
+ * Check that fd hasn't been closed.
+ */
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Pick up current time as may need to adjust timeout
+ */
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ }
+
+ for(;;) {
+ struct pollfd pfd;
+ int rv;
+ threadEntry_t self;
+
+ /*
+ * Poll the fd. If interrupted by our wakeup signal
+ * errno will be set to EBADF.
+ */
+ pfd.fd = s;
+ pfd.events = POLLIN | POLLERR;
+
+ startOp(fdEntry, &self);
+ rv = poll(&pfd, 1, timeout);
+ endOp(fdEntry, &self);
+
+ /*
+ * If interrupted then adjust timeout. If timeout
+ * has expired return 0 (indicating timeout expired).
+ */
+ if (rv < 0 && errno == EINTR) {
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ timeout -= newtime - prevtime;
+ if (timeout <= 0) {
+ return 0;
+ }
+ prevtime = newtime;
+ }
+ } else {
+ return rv;
+ }
+
+ }
+}
--- a/jdk/src/java.base/aix/native/libnet/java/net/aix_close.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file contains implementations of NET_... functions. The NET_.. functions are
- * wrappers for common file- and socket functions plus provisions for non-blocking IO.
- *
- * (basically, the layers remember all file descriptors waiting for a particular fd;
- * all threads waiting on a certain fd can be woken up by sending them a signal; this
- * is done e.g. when the fd is closed.)
- *
- * This was originally copied from the linux_close.c implementation.
- *
- * Side Note: This coding needs initialization. Under Linux this is done
- * automatically via __attribute((constructor)), on AIX this is done manually
- * (see aix_close_init).
- *
- */
-
-/*
- AIX needs a workaround for I/O cancellation, see:
- http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm
- ...
- The close subroutine is blocked until all subroutines which use the file
- descriptor return to usr space. For example, when a thread is calling close
- and another thread is calling select with the same file descriptor, the
- close subroutine does not return until the select call returns.
- ...
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
- pthread_t thr; /* this thread */
- struct threadEntry *next; /* next thread */
- int intr; /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
- pthread_mutex_t lock; /* fd lock */
- threadEntry_t *threads; /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = (SIGRTMAX - 1);
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable = NULL;
-static int fdCount = 0;
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- *
- * On AIX we don't have __attribute((constructor)) so we need to initialize
- * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c')
- */
-void aix_close_init() {
- struct rlimit nbr_files;
- sigset_t sigset;
- struct sigaction sa;
-
- /* Check already initialized */
- if (fdCount > 0 && fdTable != NULL) {
- return;
- }
-
- /*
- * Allocate table based on the maximum number of
- * file descriptors.
- */
- if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) {
- fprintf(stderr, "library initialization failed - "
- "unable to get max # of allocated fds\n");
- abort();
- }
- fdCount = nbr_files.rlim_max;
- /*
- * We have a conceptual problem here, when the number of files is
- * unlimited. As a kind of workaround, we ensure the table is big
- * enough for handle even a large number of files. Since SAP itself
- * recommends a limit of 32000 files, we just use 64000 as 'infinity'.
- */
- if (nbr_files.rlim_max == RLIM_INFINITY) {
- fdCount = 64000;
- }
- fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
- if (fdTable == NULL) {
- fprintf(stderr, "library initialization failed - "
- "unable to allocate file descriptor table - out of memory");
- abort();
- }
-
- {
- int i;
- for (i=0; i < fdCount; i++) {
- pthread_mutex_init(&fdTable[i].lock, NULL);
- }
- }
-
- /*
- * Setup the signal handler
- */
- sa.sa_handler = sig_wakeup;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigaction(sigWakeup, &sa, NULL);
-
- sigemptyset(&sigset);
- sigaddset(&sigset, sigWakeup);
- sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
- if (fd < 0 || fd >= fdCount) {
- return NULL;
- }
- return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- * Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
- self->thr = pthread_self();
- self->intr = 0;
-
- pthread_mutex_lock(&(fdEntry->lock));
- {
- self->next = fdEntry->threads;
- fdEntry->threads = self;
- }
- pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- * Remove thread from thread list for the fd
- * If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
- (fdEntry_t *fdEntry, threadEntry_t *self)
-{
- int orig_errno = errno;
- pthread_mutex_lock(&(fdEntry->lock));
- {
- threadEntry_t *curr, *prev=NULL;
- curr = fdEntry->threads;
- while (curr != NULL) {
- if (curr == self) {
- if (curr->intr) {
- orig_errno = EBADF;
- }
- if (prev == NULL) {
- fdEntry->threads = curr->next;
- } else {
- prev->next = curr->next;
- }
- break;
- }
- prev = curr;
- curr = curr->next;
- }
- }
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- * fd1 < 0 => close(fd2)
- * fd1 >= 0 => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
- int rv, orig_errno;
- fdEntry_t *fdEntry = getFdEntry(fd2);
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Lock the fd to hold-off additional I/O on this fd.
- */
- pthread_mutex_lock(&(fdEntry->lock));
-
- {
- /* On fast machines we see that we enter dup2 before the
- * accepting thread had a chance to get and process the signal.
- * So in case we woke a thread up, give it some time to cope.
- * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */
- int num_woken = 0;
-
- /*
- * Send a wakeup signal to all threads blocked on this
- * file descriptor.
- */
- threadEntry_t *curr = fdEntry->threads;
- while (curr != NULL) {
- curr->intr = 1;
- pthread_kill( curr->thr, sigWakeup );
- num_woken ++;
- curr = curr->next;
- }
-
- if (num_woken > 0) {
- usleep(num_woken * 50);
- }
-
- /*
- * And close/dup the file descriptor
- * (restart if interrupted by signal)
- */
- do {
- if (fd1 < 0) {
- rv = close(fd2);
- } else {
- rv = dup2(fd1, fd2);
- }
- } while (rv == -1 && errno == EINTR);
- }
-
- /*
- * Unlock without destroying errno
- */
- orig_errno = errno;
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-
- return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
- if (fd < 0) {
- errno = EBADF;
- return -1;
- }
- return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
- return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, int *fromlen) {
- socklen_t socklen = *fromlen;
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
- *fromlen = socklen;
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len, unsigned int
- flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
- socklen_t socklen = *addrlen;
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
- *addrlen = socklen;
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- int crc = -1, prc = -1;
- threadEntry_t self;
- fdEntry_t* fdEntry = getFdEntry(s);
-
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /* On AIX, when the system call connect() is interrupted, the connection
- * is not aborted and it will be established asynchronously by the kernel.
- * Hence, no need to restart connect() when EINTR is received
- */
- startOp(fdEntry, &self);
- crc = connect(s, addr, addrlen);
- endOp(fdEntry, &self);
-
- if (crc == -1 && errno == EINTR) {
- struct pollfd s_pollfd;
- int sockopt_arg = 0;
- socklen_t len;
-
- s_pollfd.fd = s;
- s_pollfd.events = POLLOUT | POLLERR;
-
- /* poll the file descriptor */
- do {
- startOp(fdEntry, &self);
- prc = poll(&s_pollfd, 1, -1);
- endOp(fdEntry, &self);
- } while (prc == -1 && errno == EINTR);
-
- if (prc < 0)
- return prc;
-
- len = sizeof(sockopt_arg);
-
- /* Check whether the connection has been established */
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, &sockopt_arg, &len) == -1)
- return -1;
-
- if (sockopt_arg != 0 ) {
- errno = sockopt_arg;
- return -1;
- }
- } else {
- return crc;
- }
-
- /* At this point, fd is connected. Set successful return code */
- return 0;
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for poll(s, timeout).
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
- long prevtime = 0, newtime;
- struct timeval t;
- fdEntry_t *fdEntry = getFdEntry(s);
-
- /*
- * Check that fd hasn't been closed.
- */
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Pick up current time as may need to adjust timeout
- */
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- }
-
- for(;;) {
- struct pollfd pfd;
- int rv;
- threadEntry_t self;
-
- /*
- * Poll the fd. If interrupted by our wakeup signal
- * errno will be set to EBADF.
- */
- pfd.fd = s;
- pfd.events = POLLIN | POLLERR;
-
- startOp(fdEntry, &self);
- rv = poll(&pfd, 1, timeout);
- endOp(fdEntry, &self);
-
- /*
- * If interrupted then adjust timeout. If timeout
- * has expired return 0 (indicating timeout expired).
- */
- if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- return 0;
- }
- prevtime = newtime;
- }
- } else {
- return rv;
- }
-
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/linux/native/libnet/linux_close.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+ pthread_t thr; /* this thread */
+ struct threadEntry *next; /* next thread */
+ int intr; /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+ pthread_mutex_t lock; /* fd lock */
+ threadEntry_t *threads; /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = (__SIGRTMAX - 2);
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable;
+static int fdCount;
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ */
+static void __attribute((constructor)) init() {
+ struct rlimit nbr_files;
+ sigset_t sigset;
+ struct sigaction sa;
+
+ /*
+ * Allocate table based on the maximum number of
+ * file descriptors.
+ */
+ getrlimit(RLIMIT_NOFILE, &nbr_files);
+ fdCount = nbr_files.rlim_max;
+ fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+ if (fdTable == NULL) {
+ fprintf(stderr, "library initialization failed - "
+ "unable to allocate file descriptor table - out of memory");
+ abort();
+ }
+
+ /*
+ * Setup the signal handler
+ */
+ sa.sa_handler = sig_wakeup;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(sigWakeup, &sa, NULL);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, sigWakeup);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+ if (fd < 0 || fd >= fdCount) {
+ return NULL;
+ }
+ return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ * Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ self->thr = pthread_self();
+ self->intr = 0;
+
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ self->next = fdEntry->threads;
+ fdEntry->threads = self;
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ * Remove thread from thread list for the fd
+ * If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+ (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ int orig_errno = errno;
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ threadEntry_t *curr, *prev=NULL;
+ curr = fdEntry->threads;
+ while (curr != NULL) {
+ if (curr == self) {
+ if (curr->intr) {
+ orig_errno = EBADF;
+ }
+ if (prev == NULL) {
+ fdEntry->threads = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ break;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ * fd1 < 0 => close(fd2)
+ * fd1 >= 0 => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+ int rv, orig_errno;
+ fdEntry_t *fdEntry = getFdEntry(fd2);
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Lock the fd to hold-off additional I/O on this fd.
+ */
+ pthread_mutex_lock(&(fdEntry->lock));
+
+ {
+ /*
+ * And close/dup the file descriptor
+ * (restart if interrupted by signal)
+ */
+ do {
+ if (fd1 < 0) {
+ rv = close(fd2);
+ } else {
+ rv = dup2(fd1, fd2);
+ }
+ } while (rv == -1 && errno == EINTR);
+
+ /*
+ * Send a wakeup signal to all threads blocked on this
+ * file descriptor.
+ */
+ threadEntry_t *curr = fdEntry->threads;
+ while (curr != NULL) {
+ curr->intr = 1;
+ pthread_kill( curr->thr, sigWakeup );
+ curr = curr->next;
+ }
+ }
+
+ /*
+ * Unlock without destroying errno
+ */
+ orig_errno = errno;
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+
+ return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+ if (fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+ return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while (ret == -1 && errno == EINTR); \
+ return ret; \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen) {
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen) {
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for poll(s, timeout).
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+ long prevtime = 0, newtime;
+ struct timeval t;
+ fdEntry_t *fdEntry = getFdEntry(s);
+
+ /*
+ * Check that fd hasn't been closed.
+ */
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Pick up current time as may need to adjust timeout
+ */
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ }
+
+ for(;;) {
+ struct pollfd pfd;
+ int rv;
+ threadEntry_t self;
+
+ /*
+ * Poll the fd. If interrupted by our wakeup signal
+ * errno will be set to EBADF.
+ */
+ pfd.fd = s;
+ pfd.events = POLLIN | POLLERR;
+
+ startOp(fdEntry, &self);
+ rv = poll(&pfd, 1, timeout);
+ endOp(fdEntry, &self);
+
+ /*
+ * If interrupted then adjust timeout. If timeout
+ * has expired return 0 (indicating timeout expired).
+ */
+ if (rv < 0 && errno == EINTR) {
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ timeout -= newtime - prevtime;
+ if (timeout <= 0) {
+ return 0;
+ }
+ prevtime = newtime;
+ }
+ } else {
+ return rv;
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <Security/AuthSession.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <Foundation/Foundation.h>
+
+#include "java_props_macosx.h"
+
+
+// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
+static void *getJRSFramework() {
+ static void *jrsFwk = NULL;
+ if (jrsFwk == NULL) {
+ jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
+ }
+ return jrsFwk;
+}
+
+char *getPosixLocale(int cat) {
+ char *lc = setlocale(cat, NULL);
+ if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
+ lc = getenv("LANG");
+ }
+ if (lc == NULL) return NULL;
+ return strdup(lc);
+}
+
+#define LOCALEIDLENGTH 128
+char *getMacOSXLocale(int cat) {
+ switch (cat) {
+ case LC_MESSAGES:
+ {
+ void *jrsFwk = getJRSFramework();
+ if (jrsFwk == NULL) return NULL;
+
+ char *(*JRSCopyPrimaryLanguage)() = dlsym(jrsFwk, "JRSCopyPrimaryLanguage");
+ char *primaryLanguage = JRSCopyPrimaryLanguage ? JRSCopyPrimaryLanguage() : NULL;
+ if (primaryLanguage == NULL) return NULL;
+
+ char *(*JRSCopyCanonicalLanguageForPrimaryLanguage)(char *) = dlsym(jrsFwk, "JRSCopyCanonicalLanguageForPrimaryLanguage");
+ char *canonicalLanguage = JRSCopyCanonicalLanguageForPrimaryLanguage ? JRSCopyCanonicalLanguageForPrimaryLanguage(primaryLanguage) : NULL;
+ free (primaryLanguage);
+
+ return canonicalLanguage;
+ }
+ break;
+ default:
+ {
+ char localeString[LOCALEIDLENGTH];
+ if (CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
+ localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
+ return strdup(localeString);
+ }
+ }
+ break;
+ }
+
+ return NULL;
+}
+
+char *setupMacOSXLocale(int cat) {
+ char * ret = getMacOSXLocale(cat);
+
+ if (cat == LC_MESSAGES && ret != NULL) {
+ void *jrsFwk = getJRSFramework();
+ if (jrsFwk != NULL) {
+ void (*JRSSetDefaultLocalization)(char *) = dlsym(jrsFwk, "JRSSetDefaultLocalization");
+ if (JRSSetDefaultLocalization) JRSSetDefaultLocalization(ret);
+ }
+ }
+
+ if (ret == NULL) {
+ return getPosixLocale(cat);
+ } else {
+ return ret;
+ }
+}
+
+int isInAquaSession() {
+ // environment variable to bypass the aqua session check
+ char *ev = getenv("AWT_FORCE_HEADFUL");
+ if (ev && (strncasecmp(ev, "true", 4) == 0)) {
+ // if "true" then tell the caller we're in an Aqua session without actually checking
+ return 1;
+ }
+ // Is the WindowServer available?
+ SecuritySessionId session_id;
+ SessionAttributeBits session_info;
+ OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
+ if (status == noErr) {
+ if (session_info & sessionHasGraphicAccess) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void setOSNameAndVersion(java_props_t *sprops) {
+ /* Don't rely on JRSCopyOSName because there's no guarantee the value will
+ * remain the same, or even if the JRS functions will continue to be part of
+ * Mac OS X. So hardcode os_name, and fill in os_version if we can.
+ */
+ sprops->os_name = strdup("Mac OS X");
+
+ void *jrsFwk = getJRSFramework();
+ if (jrsFwk != NULL) {
+ char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion");
+ if (copyOSVersion != NULL) {
+ sprops->os_version = copyOSVersion();
+ return;
+ }
+ }
+ sprops->os_version = strdup("Unknown");
+}
+
+
+static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey, CFStringRef inHostKey, CFStringRef inPortKey, CFStringRef *outProxyHost, int *ioProxyPort) {
+ /* See if the proxy is enabled. */
+ CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
+ if (cf_enabled == NULL) {
+ return false;
+ }
+
+ int isEnabled = false;
+ if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {
+ return isEnabled;
+ }
+
+ if (!isEnabled) return false;
+ *outProxyHost = CFDictionaryGetValue(inDict, inHostKey);
+
+ // If cf_host is null, that means the checkbox is set,
+ // but no host was entered. We'll treat that as NOT ENABLED.
+ // If cf_port is null or cf_port isn't a number, that means
+ // no port number was entered. Treat this as ENABLED with the
+ // protocol's default port.
+ if (*outProxyHost == NULL) {
+ return false;
+ }
+
+ if (CFStringGetLength(*outProxyHost) == 0) {
+ return false;
+ }
+
+ int newPort = 0;
+ CFNumberRef cf_port = NULL;
+ if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&
+ CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&
+ newPort > 0) {
+ *ioProxyPort = newPort;
+ } else {
+ // bad port or no port - leave *ioProxyPort unchanged
+ }
+
+ return true;
+}
+
+static char *createUTF8CString(const CFStringRef theString) {
+ if (theString == NULL) return NULL;
+
+ const CFIndex stringLength = CFStringGetLength(theString);
+ const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;
+ char *returnVal = (char *)malloc(bufSize);
+
+ if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {
+ return returnVal;
+ }
+
+ free(returnVal);
+ return NULL;
+}
+
+// Return TRUE if str is a syntactically valid IP address.
+// Using inet_pton() instead of inet_aton() for IPv6 support.
+// len is only a hint; cstr must still be nul-terminated
+static int looksLikeIPAddress(char *cstr, size_t len) {
+ if (len == 0 || (len == 1 && cstr[0] == '.')) return FALSE;
+
+ char dst[16]; // big enough for INET6
+ return (1 == inet_pton(AF_INET, cstr, dst) ||
+ 1 == inet_pton(AF_INET6, cstr, dst));
+}
+
+
+
+// Convert Mac OS X proxy exception entry to Java syntax.
+// See Radar #3441134 for details.
+// Returns NULL if this exception should be ignored by Java.
+// May generate a string with multiple exceptions separated by '|'.
+static char * createConvertedException(CFStringRef cf_original) {
+ // This is done with char* instead of CFString because inet_pton()
+ // needs a C string.
+ char *c_exception = createUTF8CString(cf_original);
+ if (!c_exception) return NULL;
+
+ int c_len = strlen(c_exception);
+
+ // 1. sanitize exception prefix
+ if (c_len >= 1 && 0 == strncmp(c_exception, ".", 1)) {
+ memmove(c_exception, c_exception+1, c_len);
+ c_len -= 1;
+ } else if (c_len >= 2 && 0 == strncmp(c_exception, "*.", 2)) {
+ memmove(c_exception, c_exception+2, c_len-1);
+ c_len -= 2;
+ }
+
+ // 2. pre-reject other exception wildcards
+ if (strchr(c_exception, '*')) {
+ free(c_exception);
+ return NULL;
+ }
+
+ // 3. no IP wildcarding
+ if (looksLikeIPAddress(c_exception, c_len)) {
+ return c_exception;
+ }
+
+ // 4. allow domain suffixes
+ // c_exception is now "str\0" - change to "str|*.str\0"
+ c_exception = reallocf(c_exception, c_len+3+c_len+1);
+ if (!c_exception) return NULL;
+
+ strncpy(c_exception+c_len, "|*.", 3);
+ strncpy(c_exception+c_len+3, c_exception, c_len);
+ c_exception[c_len+3+c_len] = '\0';
+ return c_exception;
+}
+
+/*
+ * Method for fetching the user.home path and storing it in the property list.
+ * For signed .apps running in the Mac App Sandbox, user.home is set to the
+ * app's sandbox container.
+ */
+void setUserHome(java_props_t *sprops) {
+ if (sprops == NULL) { return; }
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());
+ [pool drain];
+}
+
+/*
+ * Method for fetching proxy info and storing it in the property list.
+ */
+void setProxyProperties(java_props_t *sProps) {
+ if (sProps == NULL) return;
+
+ char buf[16]; /* Used for %d of an int - 16 is plenty */
+ CFStringRef
+ cf_httpHost = NULL,
+ cf_httpsHost = NULL,
+ cf_ftpHost = NULL,
+ cf_socksHost = NULL,
+ cf_gopherHost = NULL;
+ int
+ httpPort = 80, // Default proxy port values
+ httpsPort = 443,
+ ftpPort = 21,
+ socksPort = 1080,
+ gopherPort = 70;
+
+ CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
+ if (dict == NULL) return;
+
+ /* Read the proxy exceptions list */
+ CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
+
+ CFMutableStringRef cf_exceptionList = NULL;
+ if (cf_list != NULL) {
+ CFIndex len = CFArrayGetCount(cf_list), idx;
+
+ cf_exceptionList = CFStringCreateMutable(NULL, 0);
+ for (idx = (CFIndex)0; idx < len; idx++) {
+ CFStringRef cf_ehost;
+ if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {
+ /* Convert this exception from Mac OS X syntax to Java syntax.
+ See Radar #3441134 for details. This may generate a string
+ with multiple Java exceptions separated by '|'. */
+ char *c_exception = createConvertedException(cf_ehost);
+ if (c_exception) {
+ /* Append the host to the list of exclusions. */
+ if (CFStringGetLength(cf_exceptionList) > 0) {
+ CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);
+ }
+ CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);
+ free(c_exception);
+ }
+ }
+ }
+ }
+
+ if (cf_exceptionList != NULL) {
+ if (CFStringGetLength(cf_exceptionList) > 0) {
+ sProps->exceptionList = createUTF8CString(cf_exceptionList);
+ }
+ CFRelease(cf_exceptionList);
+ }
+
+#define CHECK_PROXY(protocol, PROTOCOL) \
+ sProps->protocol##ProxyEnabled = \
+ getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable, \
+ kSCPropNetProxies##PROTOCOL##Proxy, \
+ kSCPropNetProxies##PROTOCOL##Port, \
+ &cf_##protocol##Host, &protocol##Port); \
+ if (sProps->protocol##ProxyEnabled) { \
+ sProps->protocol##Host = createUTF8CString(cf_##protocol##Host); \
+ snprintf(buf, sizeof(buf), "%d", protocol##Port); \
+ sProps->protocol##Port = malloc(strlen(buf) + 1); \
+ strcpy(sProps->protocol##Port, buf); \
+ }
+
+ CHECK_PROXY(http, HTTP);
+ CHECK_PROXY(https, HTTPS);
+ CHECK_PROXY(ftp, FTP);
+ CHECK_PROXY(socks, SOCKS);
+ CHECK_PROXY(gopher, Gopher);
+
+#undef CHECK_PROXY
+
+ CFRelease(dict);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.h Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "java_props.h"
+
+char *setupMacOSXLocale(int cat);
+void setOSNameAndVersion(java_props_t *sprops);
+void setUserHome(java_props_t *sprops);
+void setProxyProperties(java_props_t *sProps);
+int isInAquaSession();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+ pthread_t thr; /* this thread */
+ struct threadEntry *next; /* next thread */
+ int intr; /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+ pthread_mutex_t lock; /* fd lock */
+ threadEntry_t *threads; /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = SIGIO;
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable;
+static int fdCount;
+
+/*
+ * This limit applies if getlimit() returns unlimited.
+ * Unfortunately, this means if someone wants a higher limit
+ * then they have to set an explicit limit, higher than this,
+ * which is probably counter-intuitive.
+ */
+#define MAX_FD_COUNT 4096
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ */
+static void __attribute((constructor)) init() {
+ struct rlimit nbr_files;
+ sigset_t sigset;
+ struct sigaction sa;
+ int i;
+
+ /*
+ * Allocate table based on the maximum number of
+ * file descriptors.
+ */
+ getrlimit(RLIMIT_NOFILE, &nbr_files);
+ if (nbr_files.rlim_max == RLIM_INFINITY) {
+ fdCount = MAX_FD_COUNT;
+ } else {
+ fdCount = nbr_files.rlim_max;
+ }
+ fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+ if (fdTable == NULL) {
+ fprintf(stderr, "library initialization failed - "
+ "unable to allocate file descriptor table - out of memory");
+ abort();
+ }
+ for (i=0; i<fdCount; i++) {
+ pthread_mutex_init(&fdTable[i].lock, NULL);
+ }
+
+ /*
+ * Setup the signal handler
+ */
+ sa.sa_handler = sig_wakeup;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(sigWakeup, &sa, NULL);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, sigWakeup);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+ if (fd < 0 || fd >= fdCount) {
+ return NULL;
+ }
+ return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ * Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ self->thr = pthread_self();
+ self->intr = 0;
+
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ self->next = fdEntry->threads;
+ fdEntry->threads = self;
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ * Remove thread from thread list for the fd
+ * If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+ (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ int orig_errno = errno;
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ threadEntry_t *curr, *prev=NULL;
+ curr = fdEntry->threads;
+ while (curr != NULL) {
+ if (curr == self) {
+ if (curr->intr) {
+ orig_errno = EBADF;
+ }
+ if (prev == NULL) {
+ fdEntry->threads = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ break;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ * fd1 < 0 => close(fd2)
+ * fd1 >= 0 => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+ int rv, orig_errno;
+ fdEntry_t *fdEntry = getFdEntry(fd2);
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Lock the fd to hold-off additional I/O on this fd.
+ */
+ pthread_mutex_lock(&(fdEntry->lock));
+
+ {
+ /*
+ * Send a wakeup signal to all threads blocked on this
+ * file descriptor.
+ */
+ threadEntry_t *curr = fdEntry->threads;
+ while (curr != NULL) {
+ curr->intr = 1;
+ pthread_kill( curr->thr, sigWakeup );
+ curr = curr->next;
+ }
+
+ /*
+ * And close/dup the file descriptor
+ * (restart if interrupted by signal)
+ */
+ do {
+ if (fd1 < 0) {
+ rv = close(fd2);
+ } else {
+ rv = dup2(fd1, fd2);
+ }
+ } while (rv == -1 && errno == EINTR);
+
+ }
+
+ /*
+ * Unlock without destroying errno
+ */
+ orig_errno = errno;
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+
+ return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+ if (fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+ return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while (ret == -1 && errno == EINTR); \
+ return ret; \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen) {
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen) {
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+
+/*
+ * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+ long prevtime = 0, newtime;
+ struct timeval t, *tp = &t;
+ fd_set fds;
+ fd_set* fdsp = NULL;
+ int allocated = 0;
+ threadEntry_t self;
+ fdEntry_t *fdEntry = getFdEntry(s);
+
+ /*
+ * Check that fd hasn't been closed.
+ */
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Pick up current time as may need to adjust timeout
+ */
+ if (timeout > 0) {
+ /* Timed */
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+ } else if (timeout < 0) {
+ /* Blocking */
+ tp = 0;
+ } else {
+ /* Poll */
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+ }
+
+ if (s < FD_SETSIZE) {
+ fdsp = &fds;
+ FD_ZERO(fdsp);
+ } else {
+ int length = (howmany(s+1, NFDBITS)) * sizeof(int);
+ fdsp = (fd_set *) calloc(1, length);
+ if (fdsp == NULL) {
+ return -1; // errno will be set to ENOMEM
+ }
+ allocated = 1;
+ }
+ FD_SET(s, fdsp);
+
+ for(;;) {
+ int rv;
+
+ /*
+ * call select on the fd. If interrupted by our wakeup signal
+ * errno will be set to EBADF.
+ */
+
+ startOp(fdEntry, &self);
+ rv = select(s+1, fdsp, 0, 0, tp);
+ endOp(fdEntry, &self);
+
+ /*
+ * If interrupted then adjust timeout. If timeout
+ * has expired return 0 (indicating timeout expired).
+ */
+ if (rv < 0 && errno == EINTR) {
+ if (timeout > 0) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
+ timeout -= newtime - prevtime;
+ if (timeout <= 0) {
+ if (allocated != 0)
+ free(fdsp);
+ return 0;
+ }
+ prevtime = newtime;
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+ }
+ } else {
+ if (allocated != 0)
+ free(fdsp);
+ return rv;
+ }
+
+ }
+}
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,9 @@
import sun.misc.FloatingDecimal;
import java.util.Arrays;
+import java.util.Spliterator;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
/**
* A mutable sequence of characters.
@@ -292,7 +295,7 @@
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
throw new IndexOutOfBoundsException();
}
- return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
+ return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
}
/**
@@ -1432,6 +1435,34 @@
public abstract String toString();
/**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public IntStream chars() {
+ // Reuse String-based spliterator. This requires a supplier to
+ // capture the value and count when the terminal operation is executed
+ return StreamSupport.intStream(
+ () -> new String.IntCharArraySpliterator(value, 0, count, 0),
+ Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
+ false);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public IntStream codePoints() {
+ // Reuse String-based spliterator. This requires a supplier to
+ // capture the value and count when the terminal operation is executed
+ return StreamSupport.intStream(
+ () -> new String.CodePointsSpliterator(value, 0, count, 0),
+ Spliterator.ORDERED,
+ false);
+ }
+
+ /**
* Needed by {@code String} for the contentEquals method.
*/
final char[] getValue() {
--- a/jdk/src/java.base/share/classes/java/lang/String.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/String.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,10 +34,14 @@
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
+import java.util.Spliterator;
import java.util.StringJoiner;
+import java.util.function.IntConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
/**
* The {@code String} class represents character strings. All
@@ -2894,6 +2898,180 @@
return this;
}
+ static class IntCharArraySpliterator implements Spliterator.OfInt {
+ private final char[] array;
+ private int index; // current index, modified on advance/split
+ private final int fence; // one past last index
+ private final int cs;
+
+ IntCharArraySpliterator(char[] array, int acs) {
+ this(array, 0, array.length, acs);
+ }
+
+ IntCharArraySpliterator(char[] array, int origin, int fence, int acs) {
+ this.array = array;
+ this.index = origin;
+ this.fence = fence;
+ this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+ | Spliterator.SUBSIZED;
+ }
+
+ @Override
+ public OfInt trySplit() {
+ int lo = index, mid = (lo + fence) >>> 1;
+ return (lo >= mid)
+ ? null
+ : new IntCharArraySpliterator(array, lo, index = mid, cs);
+ }
+
+ @Override
+ public void forEachRemaining(IntConsumer action) {
+ char[] a; int i, hi; // hoist accesses and checks from loop
+ if (action == null)
+ throw new NullPointerException();
+ if ((a = array).length >= (hi = fence) &&
+ (i = index) >= 0 && i < (index = hi)) {
+ do { action.accept(a[i]); } while (++i < hi);
+ }
+ }
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ if (action == null)
+ throw new NullPointerException();
+ if (index >= 0 && index < fence) {
+ action.accept(array[index++]);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public long estimateSize() { return (long)(fence - index); }
+
+ @Override
+ public int characteristics() {
+ return cs;
+ }
+ }
+
+ /**
+ * Returns a stream of {@code int} zero-extending the {@code char} values
+ * from this sequence. Any char which maps to a <a
+ * href="{@docRoot}/java/lang/Character.html#unicode">surrogate code
+ * point</a> is passed through uninterpreted.
+ *
+ * @return an IntStream of char values from this sequence
+ * @since 1.9
+ */
+ @Override
+ public IntStream chars() {
+ return StreamSupport.intStream(
+ new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
+ }
+
+ static class CodePointsSpliterator implements Spliterator.OfInt {
+ private final char[] array;
+ private int index; // current index, modified on advance/split
+ private final int fence; // one past last index
+ private final int cs;
+
+ CodePointsSpliterator(char[] array, int acs) {
+ this(array, 0, array.length, acs);
+ }
+
+ CodePointsSpliterator(char[] array, int origin, int fence, int acs) {
+ this.array = array;
+ this.index = origin;
+ this.fence = fence;
+ this.cs = acs | Spliterator.ORDERED;
+ }
+
+ @Override
+ public OfInt trySplit() {
+ int lo = index, mid = (lo + fence) >>> 1;
+ if (lo >= mid)
+ return null;
+
+ int midOneLess;
+ // If the mid-point intersects a surrogate pair
+ if (Character.isLowSurrogate(array[mid]) &&
+ Character.isHighSurrogate(array[midOneLess = (mid -1)])) {
+ // If there is only one pair it cannot be split
+ if (lo >= midOneLess)
+ return null;
+ // Shift the mid-point to align with the surrogate pair
+ return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
+ }
+ return new CodePointsSpliterator(array, lo, index = mid, cs);
+ }
+
+ @Override
+ public void forEachRemaining(IntConsumer action) {
+ char[] a; int i, hi; // hoist accesses and checks from loop
+ if (action == null)
+ throw new NullPointerException();
+ if ((a = array).length >= (hi = fence) &&
+ (i = index) >= 0 && i < (index = hi)) {
+ do {
+ i = advance(a, i, hi, action);
+ } while (i < hi);
+ }
+ }
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ if (action == null)
+ throw new NullPointerException();
+ if (index >= 0 && index < fence) {
+ index = advance(array, index, fence, action);
+ return true;
+ }
+ return false;
+ }
+
+ // Advance one code point from the index, i, and return the next
+ // index to advance from
+ private static int advance(char[] a, int i, int hi, IntConsumer action) {
+ char c1 = a[i++];
+ int cp = c1;
+ if (Character.isHighSurrogate(c1) && i < hi) {
+ char c2 = a[i];
+ if (Character.isLowSurrogate(c2)) {
+ i++;
+ cp = Character.toCodePoint(c1, c2);
+ }
+ }
+ action.accept(cp);
+ return i;
+ }
+
+ @Override
+ public long estimateSize() { return (long)(fence - index); }
+
+ @Override
+ public int characteristics() {
+ return cs;
+ }
+ }
+
+ /**
+ * Returns a stream of code point values from this sequence. Any surrogate
+ * pairs encountered in the sequence are combined as if by {@linkplain
+ * Character#toCodePoint Character.toCodePoint} and the result is passed
+ * to the stream. Any other code units, including ordinary BMP characters,
+ * unpaired surrogates, and undefined code units, are zero-extended to
+ * {@code int} values which are then passed to the stream.
+ *
+ * @return an IntStream of Unicode code points from this sequence
+ * @since 1.9
+ */
+ @Override
+ public IntStream codePoints() {
+ return StreamSupport.intStream(
+ new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
+ }
+
/**
* Converts this string to a new character array.
*
--- a/jdk/src/java.base/share/classes/java/net/URI.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URI.java Mon Jan 26 17:00:39 2015 -0800
@@ -2637,6 +2637,11 @@
private static final long H_URIC_NO_SLASH
= H_UNRESERVED | H_ESCAPED | highMask(";?:@&=+$,");
+ // scope_id = alpha | digit | "_" | "."
+ private static final long L_SCOPE_ID
+ = L_ALPHANUM | lowMask("_.");
+ private static final long H_SCOPE_ID
+ = H_ALPHANUM | highMask("_.");
// -- Escaping and encoding --
@@ -3226,7 +3231,7 @@
if (r+1 == q) {
fail ("scope id expected");
}
- checkChars (r+1, q, L_ALPHANUM, H_ALPHANUM,
+ checkChars (r+1, q, L_SCOPE_ID, H_SCOPE_ID,
"scope id");
} else {
parseIPv6Reference(p, q);
--- a/jdk/src/java.base/share/classes/java/nio/channels/Channels.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/channels/Channels.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -579,12 +579,13 @@
* charset and writes the resulting bytes to the given channel.
*
* <p> An invocation of this method of the form
- * <p>
+ *
* <pre> {@code
* Channels.newWriter(ch, csname)
* } </pre>
+ *
* behaves in exactly the same way as the expression
- * <p>
+ *
* <pre> {@code
* Channels.newWriter(ch, Charset.forName(csName).newEncoder(), -1)
* } </pre>
--- a/jdk/src/java.base/share/classes/java/util/Spliterator.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Spliterator.java Mon Jan 26 17:00:39 2015 -0800
@@ -553,6 +553,12 @@
* sub-split size is known and additions or removals to the source are not
* reflected when traversing.
*
+ * <p>A top-level Spliterator should not report both {@code CONCURRENT} and
+ * {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
+ * is inconsistent and no guarantees can be made about any computation using
+ * that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
+ * additions or removals to the source are not reflected when traversing.
+ *
* @apiNote Most concurrent collections maintain a consistency policy
* guaranteeing accuracy with respect to elements present at the point of
* Spliterator construction, but possibly not reflecting subsequent
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Mon Jan 26 17:00:39 2015 -0800
@@ -192,22 +192,6 @@
return userAgent;
}
- // should remove once HttpClient.newHttpProxy is putback
- private static Proxy newHttpProxy(String proxyHost, int proxyPort) {
- InetSocketAddress saddr = null;
- final String phost = proxyHost;
- final int pport = proxyPort < 0 ? httpsPortNumber : proxyPort;
- try {
- saddr = java.security.AccessController.doPrivileged(new
- java.security.PrivilegedExceptionAction<InetSocketAddress>() {
- public InetSocketAddress run() {
- return new InetSocketAddress(phost, pport);
- }});
- } catch (java.security.PrivilegedActionException pae) {
- }
- return new Proxy(Proxy.Type.HTTP, saddr);
- }
-
// CONSTRUCTOR, FACTORY
@@ -251,7 +235,7 @@
throws IOException {
this(sf, url,
(proxyHost == null? null:
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
+ HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
connectTimeout);
}
@@ -261,6 +245,11 @@
HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy,
int connectTimeout)
throws IOException {
+ PlatformLogger logger = HttpURLConnection.getHttpLogger();
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Creating new HttpsClient with url:" + url + " and proxy:" + proxy +
+ " with connect timeout:" + connectTimeout);
+ }
this.proxy = proxy;
setSSLSocketFactory(sf);
this.proxyDisabled = true;
@@ -317,7 +306,7 @@
return HttpsClient.New(sf, url, hv,
(proxyHost == null? null :
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
+ HttpClient.newHttpProxy(proxyHost, proxyPort, "https")),
useCache, connectTimeout, httpuc);
}
@@ -329,6 +318,11 @@
if (p == null) {
p = Proxy.NO_PROXY;
}
+ PlatformLogger logger = HttpURLConnection.getHttpLogger();
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Looking for HttpClient for URL " + url +
+ " and proxy value of " + p);
+ }
HttpsClient ret = null;
if (useCache) {
/* see if one's already around */
@@ -342,14 +336,13 @@
if (ret != null) {
if ((ret.proxy != null && ret.proxy.equals(p)) ||
- (ret.proxy == null && p == null)) {
+ (ret.proxy == null && p == Proxy.NO_PROXY)) {
synchronized (ret) {
ret.cachedHttpClient = true;
assert ret.inCache;
ret.inCache = false;
if (httpuc != null && ret.needsTunneling())
httpuc.setTunnelState(TUNNELING);
- PlatformLogger logger = HttpURLConnection.getHttpLogger();
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
logger.finest("KeepAlive stream retrieved from the cache, " + ret);
}
@@ -360,6 +353,9 @@
// This should be fine as it is very rare that a connection
// to the same host will not use the same proxy.
synchronized(ret) {
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
+ logger.finest("Not returning this connection to cache: " + ret);
+ }
ret.inCache = false;
ret.closeServer();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/solaris/native/libnet/solaris_close.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <stropts.h>
+#include <unistd.h>
+
+/* Support for restartable system calls on Solaris. */
+
+#define RESTARTABLE_RETURN_INT(_cmd) do { \
+ int _result; \
+ if (1) { \
+ do { \
+ _result = _cmd; \
+ } while((_result == -1) && (errno == EINTR)); \
+ return _result; \
+ } \
+} while(0)
+
+int NET_Read(int s, void* buf, size_t len) {
+ RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen) {
+ RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+ RESTARTABLE_RETURN_INT(readv(s, vector, count));
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+ RESTARTABLE_RETURN_INT(writev(s, vector, count));
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+ RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
+}
+
+int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
+ const struct sockaddr *to, int tolen) {
+ RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+ RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
+}
+
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
+ RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
+}
+
+int NET_SocketClose(int fd) {
+ return close(fd);
+}
+
+int NET_Dup2(int fd, int fd2) {
+ return dup2(fd, fd2);
+}
+
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+ RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
+}
+
+int NET_Timeout(int s, long timeout) {
+ int result;
+ struct timeval t;
+ long prevtime, newtime;
+ struct pollfd pfd;
+ pfd.fd = s;
+ pfd.events = POLLIN;
+
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ prevtime = (t.tv_sec * 1000) + t.tv_usec / 1000;
+ }
+
+ for(;;) {
+ result = poll(&pfd, 1, timeout);
+ if (result < 0 && errno == EINTR) {
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ newtime = (t.tv_sec * 1000) + t.tv_usec /1000;
+ timeout -= newtime - prevtime;
+ if (timeout <= 0)
+ return 0;
+ prevtime = newtime;
+ }
+ } else {
+ return result;
+ }
+ }
+}
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,24 +25,156 @@
package java.lang;
-import java.io.IOException;
+import java.lang.ProcessBuilder.Redirect;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.lang.ProcessBuilder.Redirect;
-import java.lang.ProcessBuilder.Redirect;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.security.AccessController;
+import static java.security.AccessController.doPrivileged;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
/**
- * This class is for the exclusive use of ProcessBuilder.start() to
- * create new processes.
+ * This java.lang.Process subclass in the UNIX environment is for the exclusive use of
+ * ProcessBuilder.start() to create new processes.
*
+ * @author Mario Wolczko and Ross Knippel.
+ * @author Konstantin Kladko (ported to Linux and Bsd)
* @author Martin Buchholz
+ * @author Volker Simonis (ported to AIX)
* @since 1.5
*/
-final class ProcessImpl {
+final class ProcessImpl extends Process {
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
- private ProcessImpl() {} // Not instantiable
+ private final int pid;
+ private int exitcode;
+ private boolean hasExited;
+
+ private /* final */ OutputStream stdin;
+ private /* final */ InputStream stdout;
+ private /* final */ InputStream stderr;
+
+ // only used on Solaris
+ private /* final */ DeferredCloseInputStream stdout_inner_stream;
+
+ private static enum LaunchMechanism {
+ // order IS important!
+ FORK,
+ POSIX_SPAWN,
+ VFORK
+ }
+
+ private static enum Platform {
+
+ LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
+
+ BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+ SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+ AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
+
+ final LaunchMechanism defaultLaunchMechanism;
+ final Set<LaunchMechanism> validLaunchMechanisms;
+
+ Platform(LaunchMechanism ... launchMechanisms) {
+ this.defaultLaunchMechanism = launchMechanisms[0];
+ this.validLaunchMechanisms =
+ EnumSet.copyOf(Arrays.asList(launchMechanisms));
+ }
+
+ @SuppressWarnings("fallthrough")
+ private String helperPath(String javahome, String osArch) {
+ switch (this) {
+ case SOLARIS:
+ if (osArch.equals("x86")) { osArch = "i386"; }
+ else if (osArch.equals("x86_64")) { osArch = "amd64"; }
+ // fall through...
+ case LINUX:
+ case AIX:
+ return javahome + "/lib/" + osArch + "/jspawnhelper";
+
+ case BSD:
+ return javahome + "/lib/jspawnhelper";
+
+ default:
+ throw new AssertionError("Unsupported platform: " + this);
+ }
+ }
+
+ String helperPath() {
+ return AccessController.doPrivileged(
+ (PrivilegedAction<String>) () ->
+ helperPath(System.getProperty("java.home"),
+ System.getProperty("os.arch"))
+ );
+ }
+
+ LaunchMechanism launchMechanism() {
+ return AccessController.doPrivileged(
+ (PrivilegedAction<LaunchMechanism>) () -> {
+ String s = System.getProperty(
+ "jdk.lang.Process.launchMechanism");
+ LaunchMechanism lm;
+ if (s == null) {
+ lm = defaultLaunchMechanism;
+ s = lm.name().toLowerCase(Locale.ENGLISH);
+ } else {
+ try {
+ lm = LaunchMechanism.valueOf(
+ s.toUpperCase(Locale.ENGLISH));
+ } catch (IllegalArgumentException e) {
+ lm = null;
+ }
+ }
+ if (lm == null || !validLaunchMechanisms.contains(lm)) {
+ throw new Error(
+ s + " is not a supported " +
+ "process launch mechanism on this platform."
+ );
+ }
+ return lm;
+ }
+ );
+ }
+
+ static Platform get() {
+ String osName = AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> System.getProperty("os.name")
+ );
+
+ if (osName.equals("Linux")) { return LINUX; }
+ if (osName.contains("OS X")) { return BSD; }
+ if (osName.equals("SunOS")) { return SOLARIS; }
+ if (osName.equals("AIX")) { return AIX; }
+
+ throw new Error(osName + " is not a supported OS platform.");
+ }
+ }
+
+ private static final Platform platform = Platform.get();
+ private static final LaunchMechanism launchMechanism = platform.launchMechanism();
+ private static final byte[] helperpath = toCString(platform.helperPath());
+
+ /* this is for the reaping thread */
+ private native int waitForProcessExit(int pid);
private static byte[] toCString(String s) {
if (s == null)
@@ -50,8 +182,8 @@
byte[] bytes = s.getBytes();
byte[] result = new byte[bytes.length + 1];
System.arraycopy(bytes, 0,
- result, 0,
- bytes.length);
+ result, 0,
+ bytes.length);
result[result.length-1] = (byte)0;
return result;
}
@@ -62,7 +194,7 @@
String dir,
ProcessBuilder.Redirect[] redirects,
boolean redirectErrorStream)
- throws IOException
+ throws IOException
{
assert cmdarray != null && cmdarray.length > 0;
@@ -112,7 +244,7 @@
std_fds[1] = 1;
else {
f1 = new FileOutputStream(redirects[1].file(),
- redirects[1].append());
+ redirects[1].append());
std_fds[1] = fdAccess.get(f1.getFD());
}
@@ -122,18 +254,18 @@
std_fds[2] = 2;
else {
f2 = new FileOutputStream(redirects[2].file(),
- redirects[2].append());
+ redirects[2].append());
std_fds[2] = fdAccess.get(f2.getFD());
}
}
- return new UNIXProcess
- (toCString(cmdarray[0]),
- argBlock, args.length,
- envBlock, envc[0],
- toCString(dir),
- std_fds,
- redirectErrorStream);
+ return new ProcessImpl
+ (toCString(cmdarray[0]),
+ argBlock, args.length,
+ envBlock, envc[0],
+ toCString(dir),
+ std_fds,
+ redirectErrorStream);
} finally {
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
@@ -144,4 +276,654 @@
}
}
}
+
+
+ /**
+ * Creates a process. Depending on the {@code mode} flag, this is done by
+ * one of the following mechanisms:
+ * <pre>
+ * 1 - fork(2) and exec(2)
+ * 2 - posix_spawn(3P)
+ * 3 - vfork(2) and exec(2)
+ *
+ * (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
+ * </pre>
+ * @param fds an array of three file descriptors.
+ * Indexes 0, 1, and 2 correspond to standard input,
+ * standard output and standard error, respectively. On
+ * input, a value of -1 means to create a pipe to connect
+ * child and parent processes. On output, a value which
+ * is not -1 is the parent pipe fd corresponding to the
+ * pipe which has been created. An element of this array
+ * is -1 on input if and only if it is <em>not</em> -1 on
+ * output.
+ * @return the pid of the subprocess
+ */
+ private native int forkAndExec(int mode, byte[] helperpath,
+ byte[] prog,
+ byte[] argBlock, int argc,
+ byte[] envBlock, int envc,
+ byte[] dir,
+ int[] fds,
+ boolean redirectErrorStream)
+ throws IOException;
+
+ /**
+ * The thread pool of "process reaper" daemon threads.
+ */
+ private static final Executor processReaperExecutor =
+ doPrivileged((PrivilegedAction<Executor>) () -> {
+
+ ThreadGroup tg = Thread.currentThread().getThreadGroup();
+ while (tg.getParent() != null) tg = tg.getParent();
+ ThreadGroup systemThreadGroup = tg;
+
+ ThreadFactory threadFactory = grimReaper -> {
+ // Our thread stack requirement is quite modest.
+ Thread t = new Thread(systemThreadGroup, grimReaper,
+ "process reaper", 32768);
+ t.setDaemon(true);
+ // A small attempt (probably futile) to avoid priority inversion
+ t.setPriority(Thread.MAX_PRIORITY);
+ return t;
+ };
+
+ return Executors.newCachedThreadPool(threadFactory);
+ });
+
+ private ProcessImpl(final byte[] prog,
+ final byte[] argBlock, final int argc,
+ final byte[] envBlock, final int envc,
+ final byte[] dir,
+ final int[] fds,
+ final boolean redirectErrorStream)
+ throws IOException {
+
+ pid = forkAndExec(launchMechanism.ordinal() + 1,
+ helperpath,
+ prog,
+ argBlock, argc,
+ envBlock, envc,
+ dir,
+ fds,
+ redirectErrorStream);
+
+ try {
+ doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+ initStreams(fds);
+ return null;
+ });
+ } catch (PrivilegedActionException ex) {
+ throw (IOException) ex.getException();
+ }
+ }
+
+ static FileDescriptor newFileDescriptor(int fd) {
+ FileDescriptor fileDescriptor = new FileDescriptor();
+ fdAccess.set(fileDescriptor, fd);
+ return fileDescriptor;
+ }
+
+ void initStreams(int[] fds) throws IOException {
+ switch (platform) {
+ case LINUX:
+ case BSD:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new ProcessPipeOutputStream(fds[0]);
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ProcessPipeInputStream(fds[1]);
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ProcessPipeInputStream(fds[2]);
+
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+
+ if (stdout instanceof ProcessPipeInputStream)
+ ((ProcessPipeInputStream) stdout).processExited();
+
+ if (stderr instanceof ProcessPipeInputStream)
+ ((ProcessPipeInputStream) stderr).processExited();
+
+ if (stdin instanceof ProcessPipeOutputStream)
+ ((ProcessPipeOutputStream) stdin).processExited();
+ });
+ break;
+
+ case SOLARIS:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new BufferedOutputStream(
+ new FileOutputStream(newFileDescriptor(fds[0])));
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new BufferedInputStream(
+ stdout_inner_stream =
+ new DeferredCloseInputStream(
+ newFileDescriptor(fds[1])));
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseInputStream(newFileDescriptor(fds[2]));
+
+ /*
+ * For each subprocess forked a corresponding reaper task
+ * is submitted. That task is the only thread which waits
+ * for the subprocess to terminate and it doesn't hold any
+ * locks while doing so. This design allows waitFor() and
+ * exitStatus() to be safely executed in parallel (and they
+ * need no native code).
+ */
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+ });
+ break;
+
+ case AIX:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new ProcessPipeOutputStream(fds[0]);
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseProcessPipeInputStream(fds[1]);
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseProcessPipeInputStream(fds[2]);
+
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+
+ if (stdout instanceof DeferredCloseProcessPipeInputStream)
+ ((DeferredCloseProcessPipeInputStream) stdout).processExited();
+
+ if (stderr instanceof DeferredCloseProcessPipeInputStream)
+ ((DeferredCloseProcessPipeInputStream) stderr).processExited();
+
+ if (stdin instanceof ProcessPipeOutputStream)
+ ((ProcessPipeOutputStream) stdin).processExited();
+ });
+ break;
+
+ default: throw new AssertionError("Unsupported platform: " + platform);
+ }
+ }
+
+ public OutputStream getOutputStream() {
+ return stdin;
+ }
+
+ public InputStream getInputStream() {
+ return stdout;
+ }
+
+ public InputStream getErrorStream() {
+ return stderr;
+ }
+
+ public synchronized int waitFor() throws InterruptedException {
+ while (!hasExited) {
+ wait();
+ }
+ return exitcode;
+ }
+
+ @Override
+ public synchronized boolean waitFor(long timeout, TimeUnit unit)
+ throws InterruptedException
+ {
+ if (hasExited) return true;
+ if (timeout <= 0) return false;
+
+ long remainingNanos = unit.toNanos(timeout);
+ long deadline = System.nanoTime() + remainingNanos;
+
+ do {
+ // Round up to next millisecond
+ wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
+ if (hasExited) {
+ return true;
+ }
+ remainingNanos = deadline - System.nanoTime();
+ } while (remainingNanos > 0);
+ return hasExited;
+ }
+
+ public synchronized int exitValue() {
+ if (!hasExited) {
+ throw new IllegalThreadStateException("process hasn't exited");
+ }
+ return exitcode;
+ }
+
+ private static native void destroyProcess(int pid, boolean force);
+
+ private void destroy(boolean force) {
+ switch (platform) {
+ case LINUX:
+ case BSD:
+ case AIX:
+ // There is a risk that pid will be recycled, causing us to
+ // kill the wrong process! So we only terminate processes
+ // that appear to still be running. Even with this check,
+ // there is an unavoidable race condition here, but the window
+ // is very small, and OSes try hard to not recycle pids too
+ // soon, so this is quite safe.
+ synchronized (this) {
+ if (!hasExited)
+ destroyProcess(pid, force);
+ }
+ try { stdin.close(); } catch (IOException ignored) {}
+ try { stdout.close(); } catch (IOException ignored) {}
+ try { stderr.close(); } catch (IOException ignored) {}
+ break;
+
+ case SOLARIS:
+ // There is a risk that pid will be recycled, causing us to
+ // kill the wrong process! So we only terminate processes
+ // that appear to still be running. Even with this check,
+ // there is an unavoidable race condition here, but the window
+ // is very small, and OSes try hard to not recycle pids too
+ // soon, so this is quite safe.
+ synchronized (this) {
+ if (!hasExited)
+ destroyProcess(pid, force);
+ try {
+ stdin.close();
+ if (stdout_inner_stream != null)
+ stdout_inner_stream.closeDeferred(stdout);
+ if (stderr instanceof DeferredCloseInputStream)
+ ((DeferredCloseInputStream) stderr)
+ .closeDeferred(stderr);
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ break;
+
+ default: throw new AssertionError("Unsupported platform: " + platform);
+ }
+ }
+
+ public void destroy() {
+ destroy(false);
+ }
+
+ @Override
+ public Process destroyForcibly() {
+ destroy(true);
+ return this;
+ }
+
+ @Override
+ public long getPid() {
+ return pid;
+ }
+
+ @Override
+ public synchronized boolean isAlive() {
+ return !hasExited;
+ }
+
+ private static native void init();
+
+ static {
+ init();
+ }
+
+ /**
+ * A buffered input stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ *
+ * This is tricky because we do not want the user-level InputStream to be
+ * closed until the user invokes close(), and we need to continue to be
+ * able to read any buffered data lingering in the OS pipe buffer.
+ */
+ private static class ProcessPipeInputStream extends BufferedInputStream {
+ private final Object closeLock = new Object();
+
+ ProcessPipeInputStream(int fd) {
+ super(new FileInputStream(newFileDescriptor(fd)));
+ }
+ private static byte[] drainInputStream(InputStream in)
+ throws IOException {
+ int n = 0;
+ int j;
+ byte[] a = null;
+ while ((j = in.available()) > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ n += in.read(a, n, j);
+ }
+ return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ synchronized (closeLock) {
+ try {
+ InputStream in = this.in;
+ // this stream is closed if and only if: in == null
+ if (in != null) {
+ byte[] stragglers = drainInputStream(in);
+ in.close();
+ this.in = (stragglers == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(stragglers);
+ }
+ } catch (IOException ignored) {}
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other
+ // methods. Synchronizing helps avoid race with processExited().
+ synchronized (closeLock) {
+ super.close();
+ }
+ }
+ }
+
+ /**
+ * A buffered output stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ */
+ private static class ProcessPipeOutputStream extends BufferedOutputStream {
+ ProcessPipeOutputStream(int fd) {
+ super(new FileOutputStream(newFileDescriptor(fd)));
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ OutputStream out = this.out;
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ignored) {
+ // We know of no reason to get an IOException, but if
+ // we do, there's nothing else to do but carry on.
+ }
+ this.out = ProcessBuilder.NullOutputStream.INSTANCE;
+ }
+ }
+ }
+
+ // A FileInputStream that supports the deferment of the actual close
+ // operation until the last pending I/O operation on the stream has
+ // finished. This is required on Solaris because we must close the stdin
+ // and stdout streams in the destroy method in order to reclaim the
+ // underlying file descriptors. Doing so, however, causes any thread
+ // currently blocked in a read on one of those streams to receive an
+ // IOException("Bad file number"), which is incompatible with historical
+ // behavior. By deferring the close we allow any pending reads to see -1
+ // (EOF) as they did before.
+ //
+ private static class DeferredCloseInputStream extends FileInputStream
+ {
+ DeferredCloseInputStream(FileDescriptor fd) {
+ super(fd);
+ }
+
+ private Object lock = new Object(); // For the following fields
+ private boolean closePending = false;
+ private int useCount = 0;
+ private InputStream streamToClose;
+
+ private void raise() {
+ synchronized (lock) {
+ useCount++;
+ }
+ }
+
+ private void lower() throws IOException {
+ synchronized (lock) {
+ useCount--;
+ if (useCount == 0 && closePending) {
+ streamToClose.close();
+ }
+ }
+ }
+
+ // stc is the actual stream to be closed; it might be this object, or
+ // it might be an upstream object for which this object is downstream.
+ //
+ private void closeDeferred(InputStream stc) throws IOException {
+ synchronized (lock) {
+ if (useCount == 0) {
+ stc.close();
+ } else {
+ closePending = true;
+ streamToClose = stc;
+ }
+ }
+ }
+
+ public void close() throws IOException {
+ synchronized (lock) {
+ useCount = 0;
+ closePending = false;
+ }
+ super.close();
+ }
+
+ public int read() throws IOException {
+ raise();
+ try {
+ return super.read();
+ } finally {
+ lower();
+ }
+ }
+
+ public int read(byte[] b) throws IOException {
+ raise();
+ try {
+ return super.read(b);
+ } finally {
+ lower();
+ }
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ raise();
+ try {
+ return super.read(b, off, len);
+ } finally {
+ lower();
+ }
+ }
+
+ public long skip(long n) throws IOException {
+ raise();
+ try {
+ return super.skip(n);
+ } finally {
+ lower();
+ }
+ }
+
+ public int available() throws IOException {
+ raise();
+ try {
+ return super.available();
+ } finally {
+ lower();
+ }
+ }
+ }
+
+ /**
+ * A buffered input stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ *
+ * This is tricky because we do not want the user-level InputStream to be
+ * closed until the user invokes close(), and we need to continue to be
+ * able to read any buffered data lingering in the OS pipe buffer.
+ *
+ * On AIX this is especially tricky, because the 'close()' system call
+ * will block if another thread is at the same time blocked in a file
+ * operation (e.g. 'read()') on the same file descriptor. We therefore
+ * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
+ * with the DeferredCloseInputStream approach used on Solaris. This means
+ * that every potentially blocking operation on the file descriptor
+ * increments a counter before it is executed and decrements it once it
+ * finishes. The 'close()' operation will only be executed if there are
+ * no pending operations. Otherwise it is deferred after the last pending
+ * operation has finished.
+ *
+ */
+ private static class DeferredCloseProcessPipeInputStream
+ extends BufferedInputStream {
+
+ private final Object closeLock = new Object();
+ private int useCount = 0;
+ private boolean closePending = false;
+
+ DeferredCloseProcessPipeInputStream(int fd) {
+ super(new FileInputStream(newFileDescriptor(fd)));
+ }
+
+ private InputStream drainInputStream(InputStream in)
+ throws IOException {
+ int n = 0;
+ int j;
+ byte[] a = null;
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ j = in.available();
+ }
+ while (j > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ n += in.read(a, n, j);
+ j = in.available();
+ }
+ }
+ return (a == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ try {
+ InputStream in = this.in;
+ if (in != null) {
+ InputStream stragglers = drainInputStream(in);
+ in.close();
+ this.in = stragglers;
+ }
+ } catch (IOException ignored) { }
+ }
+
+ private void raise() {
+ synchronized (closeLock) {
+ useCount++;
+ }
+ }
+
+ private void lower() throws IOException {
+ synchronized (closeLock) {
+ useCount--;
+ if (useCount == 0 && closePending) {
+ closePending = false;
+ super.close();
+ }
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ raise();
+ try {
+ return super.read();
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ raise();
+ try {
+ return super.read(b);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ raise();
+ try {
+ return super.read(b, off, len);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ raise();
+ try {
+ return super.skip(n);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ raise();
+ try {
+ return super.available();
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other
+ // methods. Synchronizing helps avoid racing with drainInputStream().
+ synchronized (closeLock) {
+ if (useCount == 0) {
+ super.close();
+ }
+ else {
+ closePending = true;
+ }
+ }
+ }
+ }
}
--- a/jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,836 +0,0 @@
-/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.lang;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.security.AccessController;
-import static java.security.AccessController.doPrivileged;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * java.lang.Process subclass in the UNIX environment.
- *
- * @author Mario Wolczko and Ross Knippel.
- * @author Konstantin Kladko (ported to Linux and Bsd)
- * @author Martin Buchholz
- * @author Volker Simonis (ported to AIX)
- */
-final class UNIXProcess extends Process {
- private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
- = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
-
- private final int pid;
- private int exitcode;
- private boolean hasExited;
-
- private /* final */ OutputStream stdin;
- private /* final */ InputStream stdout;
- private /* final */ InputStream stderr;
-
- // only used on Solaris
- private /* final */ DeferredCloseInputStream stdout_inner_stream;
-
- private static enum LaunchMechanism {
- // order IS important!
- FORK,
- POSIX_SPAWN,
- VFORK
- }
-
- private static enum Platform {
-
- LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
-
- BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
- SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
- AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
-
- final LaunchMechanism defaultLaunchMechanism;
- final Set<LaunchMechanism> validLaunchMechanisms;
-
- Platform(LaunchMechanism ... launchMechanisms) {
- this.defaultLaunchMechanism = launchMechanisms[0];
- this.validLaunchMechanisms =
- EnumSet.copyOf(Arrays.asList(launchMechanisms));
- }
-
- @SuppressWarnings("fallthrough")
- private String helperPath(String javahome, String osArch) {
- switch (this) {
- case SOLARIS:
- if (osArch.equals("x86")) { osArch = "i386"; }
- else if (osArch.equals("x86_64")) { osArch = "amd64"; }
- // fall through...
- case LINUX:
- case AIX:
- return javahome + "/lib/" + osArch + "/jspawnhelper";
-
- case BSD:
- return javahome + "/lib/jspawnhelper";
-
- default:
- throw new AssertionError("Unsupported platform: " + this);
- }
- }
-
- String helperPath() {
- return AccessController.doPrivileged(
- (PrivilegedAction<String>) () ->
- helperPath(System.getProperty("java.home"),
- System.getProperty("os.arch"))
- );
- }
-
- LaunchMechanism launchMechanism() {
- return AccessController.doPrivileged(
- (PrivilegedAction<LaunchMechanism>) () -> {
- String s = System.getProperty(
- "jdk.lang.Process.launchMechanism");
- LaunchMechanism lm;
- if (s == null) {
- lm = defaultLaunchMechanism;
- s = lm.name().toLowerCase(Locale.ENGLISH);
- } else {
- try {
- lm = LaunchMechanism.valueOf(
- s.toUpperCase(Locale.ENGLISH));
- } catch (IllegalArgumentException e) {
- lm = null;
- }
- }
- if (lm == null || !validLaunchMechanisms.contains(lm)) {
- throw new Error(
- s + " is not a supported " +
- "process launch mechanism on this platform."
- );
- }
- return lm;
- }
- );
- }
-
- static Platform get() {
- String osName = AccessController.doPrivileged(
- (PrivilegedAction<String>) () -> System.getProperty("os.name")
- );
-
- if (osName.equals("Linux")) { return LINUX; }
- if (osName.contains("OS X")) { return BSD; }
- if (osName.equals("SunOS")) { return SOLARIS; }
- if (osName.equals("AIX")) { return AIX; }
-
- throw new Error(osName + " is not a supported OS platform.");
- }
- }
-
- private static final Platform platform = Platform.get();
- private static final LaunchMechanism launchMechanism = platform.launchMechanism();
- private static final byte[] helperpath = toCString(platform.helperPath());
-
- private static byte[] toCString(String s) {
- if (s == null)
- return null;
- byte[] bytes = s.getBytes();
- byte[] result = new byte[bytes.length + 1];
- System.arraycopy(bytes, 0,
- result, 0,
- bytes.length);
- result[result.length-1] = (byte)0;
- return result;
- }
-
- /* this is for the reaping thread */
- private native int waitForProcessExit(int pid);
-
- /**
- * Creates a process. Depending on the {@code mode} flag, this is done by
- * one of the following mechanisms:
- * <pre>
- * 1 - fork(2) and exec(2)
- * 2 - posix_spawn(3P)
- * 3 - vfork(2) and exec(2)
- *
- * (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
- * </pre>
- * @param fds an array of three file descriptors.
- * Indexes 0, 1, and 2 correspond to standard input,
- * standard output and standard error, respectively. On
- * input, a value of -1 means to create a pipe to connect
- * child and parent processes. On output, a value which
- * is not -1 is the parent pipe fd corresponding to the
- * pipe which has been created. An element of this array
- * is -1 on input if and only if it is <em>not</em> -1 on
- * output.
- * @return the pid of the subprocess
- */
- private native int forkAndExec(int mode, byte[] helperpath,
- byte[] prog,
- byte[] argBlock, int argc,
- byte[] envBlock, int envc,
- byte[] dir,
- int[] fds,
- boolean redirectErrorStream)
- throws IOException;
-
- /**
- * The thread pool of "process reaper" daemon threads.
- */
- private static final Executor processReaperExecutor =
- doPrivileged((PrivilegedAction<Executor>) () -> {
-
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- while (tg.getParent() != null) tg = tg.getParent();
- ThreadGroup systemThreadGroup = tg;
-
- ThreadFactory threadFactory = grimReaper -> {
- // Our thread stack requirement is quite modest.
- Thread t = new Thread(systemThreadGroup, grimReaper,
- "process reaper", 32768);
- t.setDaemon(true);
- // A small attempt (probably futile) to avoid priority inversion
- t.setPriority(Thread.MAX_PRIORITY);
- return t;
- };
-
- return Executors.newCachedThreadPool(threadFactory);
- });
-
- UNIXProcess(final byte[] prog,
- final byte[] argBlock, final int argc,
- final byte[] envBlock, final int envc,
- final byte[] dir,
- final int[] fds,
- final boolean redirectErrorStream)
- throws IOException {
-
- pid = forkAndExec(launchMechanism.ordinal() + 1,
- helperpath,
- prog,
- argBlock, argc,
- envBlock, envc,
- dir,
- fds,
- redirectErrorStream);
-
- try {
- doPrivileged((PrivilegedExceptionAction<Void>) () -> {
- initStreams(fds);
- return null;
- });
- } catch (PrivilegedActionException ex) {
- throw (IOException) ex.getException();
- }
- }
-
- static FileDescriptor newFileDescriptor(int fd) {
- FileDescriptor fileDescriptor = new FileDescriptor();
- fdAccess.set(fileDescriptor, fd);
- return fileDescriptor;
- }
-
- void initStreams(int[] fds) throws IOException {
- switch (platform) {
- case LINUX:
- case BSD:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new ProcessPipeOutputStream(fds[0]);
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ProcessPipeInputStream(fds[1]);
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ProcessPipeInputStream(fds[2]);
-
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
-
- if (stdout instanceof ProcessPipeInputStream)
- ((ProcessPipeInputStream) stdout).processExited();
-
- if (stderr instanceof ProcessPipeInputStream)
- ((ProcessPipeInputStream) stderr).processExited();
-
- if (stdin instanceof ProcessPipeOutputStream)
- ((ProcessPipeOutputStream) stdin).processExited();
- });
- break;
-
- case SOLARIS:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new BufferedOutputStream(
- new FileOutputStream(newFileDescriptor(fds[0])));
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new BufferedInputStream(
- stdout_inner_stream =
- new DeferredCloseInputStream(
- newFileDescriptor(fds[1])));
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseInputStream(newFileDescriptor(fds[2]));
-
- /*
- * For each subprocess forked a corresponding reaper task
- * is submitted. That task is the only thread which waits
- * for the subprocess to terminate and it doesn't hold any
- * locks while doing so. This design allows waitFor() and
- * exitStatus() to be safely executed in parallel (and they
- * need no native code).
- */
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
- });
- break;
-
- case AIX:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new ProcessPipeOutputStream(fds[0]);
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseProcessPipeInputStream(fds[1]);
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseProcessPipeInputStream(fds[2]);
-
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
-
- if (stdout instanceof DeferredCloseProcessPipeInputStream)
- ((DeferredCloseProcessPipeInputStream) stdout).processExited();
-
- if (stderr instanceof DeferredCloseProcessPipeInputStream)
- ((DeferredCloseProcessPipeInputStream) stderr).processExited();
-
- if (stdin instanceof ProcessPipeOutputStream)
- ((ProcessPipeOutputStream) stdin).processExited();
- });
- break;
-
- default: throw new AssertionError("Unsupported platform: " + platform);
- }
- }
-
- public OutputStream getOutputStream() {
- return stdin;
- }
-
- public InputStream getInputStream() {
- return stdout;
- }
-
- public InputStream getErrorStream() {
- return stderr;
- }
-
- public synchronized int waitFor() throws InterruptedException {
- while (!hasExited) {
- wait();
- }
- return exitcode;
- }
-
- @Override
- public synchronized boolean waitFor(long timeout, TimeUnit unit)
- throws InterruptedException
- {
- if (hasExited) return true;
- if (timeout <= 0) return false;
-
- long remainingNanos = unit.toNanos(timeout);
- long deadline = System.nanoTime() + remainingNanos;
-
- do {
- // Round up to next millisecond
- wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
- if (hasExited) {
- return true;
- }
- remainingNanos = deadline - System.nanoTime();
- } while (remainingNanos > 0);
- return hasExited;
- }
-
- public synchronized int exitValue() {
- if (!hasExited) {
- throw new IllegalThreadStateException("process hasn't exited");
- }
- return exitcode;
- }
-
- private static native void destroyProcess(int pid, boolean force);
-
- private void destroy(boolean force) {
- switch (platform) {
- case LINUX:
- case BSD:
- case AIX:
- // There is a risk that pid will be recycled, causing us to
- // kill the wrong process! So we only terminate processes
- // that appear to still be running. Even with this check,
- // there is an unavoidable race condition here, but the window
- // is very small, and OSes try hard to not recycle pids too
- // soon, so this is quite safe.
- synchronized (this) {
- if (!hasExited)
- destroyProcess(pid, force);
- }
- try { stdin.close(); } catch (IOException ignored) {}
- try { stdout.close(); } catch (IOException ignored) {}
- try { stderr.close(); } catch (IOException ignored) {}
- break;
-
- case SOLARIS:
- // There is a risk that pid will be recycled, causing us to
- // kill the wrong process! So we only terminate processes
- // that appear to still be running. Even with this check,
- // there is an unavoidable race condition here, but the window
- // is very small, and OSes try hard to not recycle pids too
- // soon, so this is quite safe.
- synchronized (this) {
- if (!hasExited)
- destroyProcess(pid, force);
- try {
- stdin.close();
- if (stdout_inner_stream != null)
- stdout_inner_stream.closeDeferred(stdout);
- if (stderr instanceof DeferredCloseInputStream)
- ((DeferredCloseInputStream) stderr)
- .closeDeferred(stderr);
- } catch (IOException e) {
- // ignore
- }
- }
- break;
-
- default: throw new AssertionError("Unsupported platform: " + platform);
- }
- }
-
- public void destroy() {
- destroy(false);
- }
-
- @Override
- public Process destroyForcibly() {
- destroy(true);
- return this;
- }
-
- @Override
- public long getPid() {
- return pid;
- }
-
- @Override
- public synchronized boolean isAlive() {
- return !hasExited;
- }
-
- private static native void init();
-
- static {
- init();
- }
-
- /**
- * A buffered input stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- *
- * This is tricky because we do not want the user-level InputStream to be
- * closed until the user invokes close(), and we need to continue to be
- * able to read any buffered data lingering in the OS pipe buffer.
- */
- private static class ProcessPipeInputStream extends BufferedInputStream {
- private final Object closeLock = new Object();
-
- ProcessPipeInputStream(int fd) {
- super(new FileInputStream(newFileDescriptor(fd)));
- }
- private static byte[] drainInputStream(InputStream in)
- throws IOException {
- int n = 0;
- int j;
- byte[] a = null;
- while ((j = in.available()) > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- n += in.read(a, n, j);
- }
- return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- synchronized (closeLock) {
- try {
- InputStream in = this.in;
- // this stream is closed if and only if: in == null
- if (in != null) {
- byte[] stragglers = drainInputStream(in);
- in.close();
- this.in = (stragglers == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(stragglers);
- }
- } catch (IOException ignored) {}
- }
- }
-
- @Override
- public void close() throws IOException {
- // BufferedInputStream#close() is not synchronized unlike most other
- // methods. Synchronizing helps avoid race with processExited().
- synchronized (closeLock) {
- super.close();
- }
- }
- }
-
- /**
- * A buffered output stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- */
- private static class ProcessPipeOutputStream extends BufferedOutputStream {
- ProcessPipeOutputStream(int fd) {
- super(new FileOutputStream(newFileDescriptor(fd)));
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- OutputStream out = this.out;
- if (out != null) {
- try {
- out.close();
- } catch (IOException ignored) {
- // We know of no reason to get an IOException, but if
- // we do, there's nothing else to do but carry on.
- }
- this.out = ProcessBuilder.NullOutputStream.INSTANCE;
- }
- }
- }
-
- // A FileInputStream that supports the deferment of the actual close
- // operation until the last pending I/O operation on the stream has
- // finished. This is required on Solaris because we must close the stdin
- // and stdout streams in the destroy method in order to reclaim the
- // underlying file descriptors. Doing so, however, causes any thread
- // currently blocked in a read on one of those streams to receive an
- // IOException("Bad file number"), which is incompatible with historical
- // behavior. By deferring the close we allow any pending reads to see -1
- // (EOF) as they did before.
- //
- private static class DeferredCloseInputStream extends FileInputStream
- {
- DeferredCloseInputStream(FileDescriptor fd) {
- super(fd);
- }
-
- private Object lock = new Object(); // For the following fields
- private boolean closePending = false;
- private int useCount = 0;
- private InputStream streamToClose;
-
- private void raise() {
- synchronized (lock) {
- useCount++;
- }
- }
-
- private void lower() throws IOException {
- synchronized (lock) {
- useCount--;
- if (useCount == 0 && closePending) {
- streamToClose.close();
- }
- }
- }
-
- // stc is the actual stream to be closed; it might be this object, or
- // it might be an upstream object for which this object is downstream.
- //
- private void closeDeferred(InputStream stc) throws IOException {
- synchronized (lock) {
- if (useCount == 0) {
- stc.close();
- } else {
- closePending = true;
- streamToClose = stc;
- }
- }
- }
-
- public void close() throws IOException {
- synchronized (lock) {
- useCount = 0;
- closePending = false;
- }
- super.close();
- }
-
- public int read() throws IOException {
- raise();
- try {
- return super.read();
- } finally {
- lower();
- }
- }
-
- public int read(byte[] b) throws IOException {
- raise();
- try {
- return super.read(b);
- } finally {
- lower();
- }
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- raise();
- try {
- return super.read(b, off, len);
- } finally {
- lower();
- }
- }
-
- public long skip(long n) throws IOException {
- raise();
- try {
- return super.skip(n);
- } finally {
- lower();
- }
- }
-
- public int available() throws IOException {
- raise();
- try {
- return super.available();
- } finally {
- lower();
- }
- }
- }
-
- /**
- * A buffered input stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- *
- * This is tricky because we do not want the user-level InputStream to be
- * closed until the user invokes close(), and we need to continue to be
- * able to read any buffered data lingering in the OS pipe buffer.
- *
- * On AIX this is especially tricky, because the 'close()' system call
- * will block if another thread is at the same time blocked in a file
- * operation (e.g. 'read()') on the same file descriptor. We therefore
- * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
- * with the DeferredCloseInputStream approach used on Solaris. This means
- * that every potentially blocking operation on the file descriptor
- * increments a counter before it is executed and decrements it once it
- * finishes. The 'close()' operation will only be executed if there are
- * no pending operations. Otherwise it is deferred after the last pending
- * operation has finished.
- *
- */
- private static class DeferredCloseProcessPipeInputStream
- extends BufferedInputStream {
-
- private final Object closeLock = new Object();
- private int useCount = 0;
- private boolean closePending = false;
-
- DeferredCloseProcessPipeInputStream(int fd) {
- super(new FileInputStream(newFileDescriptor(fd)));
- }
-
- private InputStream drainInputStream(InputStream in)
- throws IOException {
- int n = 0;
- int j;
- byte[] a = null;
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- j = in.available();
- }
- while (j > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- n += in.read(a, n, j);
- j = in.available();
- }
- }
- return (a == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- try {
- InputStream in = this.in;
- if (in != null) {
- InputStream stragglers = drainInputStream(in);
- in.close();
- this.in = stragglers;
- }
- } catch (IOException ignored) { }
- }
-
- private void raise() {
- synchronized (closeLock) {
- useCount++;
- }
- }
-
- private void lower() throws IOException {
- synchronized (closeLock) {
- useCount--;
- if (useCount == 0 && closePending) {
- closePending = false;
- super.close();
- }
- }
- }
-
- @Override
- public int read() throws IOException {
- raise();
- try {
- return super.read();
- } finally {
- lower();
- }
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- raise();
- try {
- return super.read(b);
- } finally {
- lower();
- }
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- raise();
- try {
- return super.read(b, off, len);
- } finally {
- lower();
- }
- }
-
- @Override
- public long skip(long n) throws IOException {
- raise();
- try {
- return super.skip(n);
- } finally {
- lower();
- }
- }
-
- @Override
- public int available() throws IOException {
- raise();
- try {
- return super.available();
- } finally {
- lower();
- }
- }
-
- @Override
- public void close() throws IOException {
- // BufferedInputStream#close() is not synchronized unlike most other
- // methods. Synchronizing helps avoid racing with drainInputStream().
- synchronized (closeLock) {
- if (useCount == 0) {
- super.close();
- }
- else {
- closePending = true;
- }
- }
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#undef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE 1
+
+#include "jni.h"
+#include "jvm.h"
+#include "jvm_md.h"
+#include "jni_util.h"
+#include "io_util.h"
+
+/*
+ * Platform-specific support for java.lang.Process
+ */
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <string.h>
+
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+#include <spawn.h>
+#endif
+
+#include "childproc.h"
+
+/*
+ * There are 4 possible strategies we might use to "fork":
+ *
+ * - fork(2). Very portable and reliable but subject to
+ * failure due to overcommit (see the documentation on
+ * /proc/sys/vm/overcommit_memory in Linux proc(5)).
+ * This is the ancient problem of spurious failure whenever a large
+ * process starts a small subprocess.
+ *
+ * - vfork(). Using this is scary because all relevant man pages
+ * contain dire warnings, e.g. Linux vfork(2). But at least it's
+ * documented in the glibc docs and is standardized by XPG4.
+ * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
+ * On Linux, one might think that vfork() would be implemented using
+ * the clone system call with flag CLONE_VFORK, but in fact vfork is
+ * a separate system call (which is a good sign, suggesting that
+ * vfork will continue to be supported at least on Linux).
+ * Another good sign is that glibc implements posix_spawn using
+ * vfork whenever possible. Note that we cannot use posix_spawn
+ * ourselves because there's no reliable way to close all inherited
+ * file descriptors.
+ *
+ * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is
+ * Linux-specific, but this ought to work - at least the glibc
+ * sources contain code to handle different combinations of CLONE_VM
+ * and CLONE_THREAD. However, when this was implemented, it
+ * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
+ * the simple program
+ * Runtime.getRuntime().exec("/bin/true").waitFor();
+ * with:
+ * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
+ * # Error: pthread_getattr_np failed with errno = 3 (ESRCH)
+ * We believe this is a glibc bug, reported here:
+ * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
+ * but the glibc maintainers closed it as WONTFIX.
+ *
+ * - posix_spawn(). While posix_spawn() is a fairly elaborate and
+ * complicated system call, it can't quite do everything that the old
+ * fork()/exec() combination can do, so the only feasible way to do
+ * this, is to use posix_spawn to launch a new helper executable
+ * "jprochelper", which in turn execs the target (after cleaning
+ * up file-descriptors etc.) The end result is the same as before,
+ * a child process linked to the parent in the same way, but it
+ * avoids the problem of duplicating the parent (VM) process
+ * address space temporarily, before launching the target command.
+ *
+ * Based on the above analysis, we are currently using vfork() on
+ * Linux and spawn() on other Unix systems, but the code to use clone()
+ * and fork() remains.
+ */
+
+
+static void
+setSIGCHLDHandler(JNIEnv *env)
+{
+ /* There is a subtle difference between having the signal handler
+ * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
+ * termination information for child processes if the signal
+ * handler is SIG_IGN. It must be SIG_DFL.
+ *
+ * We used to set the SIGCHLD handler only on Linux, but it's
+ * safest to set it unconditionally.
+ *
+ * Consider what happens if java's parent process sets the SIGCHLD
+ * handler to SIG_IGN. Normally signal handlers are inherited by
+ * children, but SIGCHLD is a controversial case. Solaris appears
+ * to always reset it to SIG_DFL, but this behavior may be
+ * non-standard-compliant, and we shouldn't rely on it.
+ *
+ * References:
+ * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
+ * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
+ */
+ struct sigaction sa;
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ if (sigaction(SIGCHLD, &sa, NULL) < 0)
+ JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
+}
+
+static void*
+xmalloc(JNIEnv *env, size_t size)
+{
+ void *p = malloc(size);
+ if (p == NULL)
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return p;
+}
+
+#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
+
+/**
+ * If PATH is not defined, the OS provides some default value.
+ * Unfortunately, there's no portable way to get this value.
+ * Fortunately, it's only needed if the child has PATH while we do not.
+ */
+static const char*
+defaultPath(void)
+{
+#ifdef __solaris__
+ /* These really are the Solaris defaults! */
+ return (geteuid() == 0 || getuid() == 0) ?
+ "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
+ "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
+#else
+ return ":/bin:/usr/bin"; /* glibc */
+#endif
+}
+
+static const char*
+effectivePath(void)
+{
+ const char *s = getenv("PATH");
+ return (s != NULL) ? s : defaultPath();
+}
+
+static int
+countOccurrences(const char *s, char c)
+{
+ int count;
+ for (count = 0; *s != '\0'; s++)
+ count += (*s == c);
+ return count;
+}
+
+static const char * const *
+effectivePathv(JNIEnv *env)
+{
+ char *p;
+ int i;
+ const char *path = effectivePath();
+ int count = countOccurrences(path, ':') + 1;
+ size_t pathvsize = sizeof(const char *) * (count+1);
+ size_t pathsize = strlen(path) + 1;
+ const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
+
+ if (pathv == NULL)
+ return NULL;
+ p = (char *) pathv + pathvsize;
+ memcpy(p, path, pathsize);
+ /* split PATH by replacing ':' with NULs; empty components => "." */
+ for (i = 0; i < count; i++) {
+ char *q = p + strcspn(p, ":");
+ pathv[i] = (p == q) ? "." : p;
+ *q = '\0';
+ p = q + 1;
+ }
+ pathv[count] = NULL;
+ return pathv;
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
+{
+ parentPathv = effectivePathv(env);
+ CHECK_NULL(parentPathv);
+ setSIGCHLDHandler(env);
+}
+
+
+#ifndef WIFEXITED
+#define WIFEXITED(status) (((status)&0xFF) == 0)
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status) (((status)>>8)&0xFF)
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(status) ((status)&0x7F)
+#endif
+
+/* Block until a child process exits and return its exit code.
+ Note, can only be called once for any given pid. */
+JNIEXPORT jint JNICALL
+Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env,
+ jobject junk,
+ jint pid)
+{
+ /* We used to use waitid() on Solaris, waitpid() on Linux, but
+ * waitpid() is more standard, so use it on all POSIX platforms. */
+ int status;
+ /* Wait for the child process to exit. This returns immediately if
+ the child has already exited. */
+ while (waitpid(pid, &status, 0) < 0) {
+ switch (errno) {
+ case ECHILD: return 0;
+ case EINTR: break;
+ default: return -1;
+ }
+ }
+
+ if (WIFEXITED(status)) {
+ /*
+ * The child exited normally; get its exit code.
+ */
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ /* The child exited because of a signal.
+ * The best value to return is 0x80 + signal number,
+ * because that is what all Unix shells do, and because
+ * it allows callers to distinguish between process exit and
+ * process death by signal.
+ * Unfortunately, the historical behavior on Solaris is to return
+ * the signal number, and we preserve this for compatibility. */
+#ifdef __solaris__
+ return WTERMSIG(status);
+#else
+ return 0x80 + WTERMSIG(status);
+#endif
+ } else {
+ /*
+ * Unknown exit code; pass it through.
+ */
+ return status;
+ }
+}
+
+static const char *
+getBytes(JNIEnv *env, jbyteArray arr)
+{
+ return arr == NULL ? NULL :
+ (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
+}
+
+static void
+releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
+{
+ if (parr != NULL)
+ (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
+}
+
+static void
+throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
+{
+ static const char * const format = "error=%d, %s";
+ const char *detail = defaultDetail;
+ char *errmsg;
+ jstring s;
+
+ if (errnum != 0) {
+ const char *s = strerror(errnum);
+ if (strcmp(s, "Unknown error") != 0)
+ detail = s;
+ }
+ /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
+ errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
+ if (errmsg == NULL)
+ return;
+
+ sprintf(errmsg, format, errnum, detail);
+ s = JNU_NewStringPlatform(env, errmsg);
+ if (s != NULL) {
+ jobject x = JNU_NewObjectByName(env, "java/io/IOException",
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL)
+ (*env)->Throw(env, x);
+ }
+ free(errmsg);
+}
+
+#ifdef DEBUG_PROCESS
+/* Debugging process code is difficult; where to write debug output? */
+static void
+debugPrint(char *format, ...)
+{
+ FILE *tty = fopen("/dev/tty", "w");
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(tty, format, ap);
+ va_end(ap);
+ fclose(tty);
+}
+#endif /* DEBUG_PROCESS */
+
+static void
+copyPipe(int from[2], int to[2])
+{
+ to[0] = from[0];
+ to[1] = from[1];
+}
+
+/* arg is an array of pointers to 0 terminated strings. array is terminated
+ * by a null element.
+ *
+ * *nelems and *nbytes receive the number of elements of array (incl 0)
+ * and total number of bytes (incl. 0)
+ * Note. An empty array will have one null element
+ * But if arg is null, then *nelems set to 0, and *nbytes to 0
+ */
+static void arraysize(const char * const *arg, int *nelems, int *nbytes)
+{
+ int i, bytes, count;
+ const char * const *a = arg;
+ char *p;
+ int *q;
+ if (arg == 0) {
+ *nelems = 0;
+ *nbytes = 0;
+ return;
+ }
+ /* count the array elements and number of bytes */
+ for (count=0, bytes=0; *a != 0; count++, a++) {
+ bytes += strlen(*a)+1;
+ }
+ *nbytes = bytes;
+ *nelems = count+1;
+}
+
+/* copy the strings from arg[] into buf, starting at given offset
+ * return new offset to next free byte
+ */
+static int copystrings(char *buf, int offset, const char * const *arg) {
+ char *p;
+ const char * const *a;
+ int count=0;
+
+ if (arg == 0) {
+ return offset;
+ }
+ for (p=buf+offset, a=arg; *a != 0; a++) {
+ int len = strlen(*a) +1;
+ memcpy(p, *a, len);
+ p += len;
+ count += len;
+ }
+ return offset+count;
+}
+
+/**
+ * We are unusually paranoid; use of clone/vfork is
+ * especially likely to tickle gcc/glibc bugs.
+ */
+#ifdef __attribute_noinline__ /* See: sys/cdefs.h */
+__attribute_noinline__
+#endif
+
+#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */
+
+#ifdef START_CHILD_USE_CLONE
+static pid_t
+cloneChild(ChildStuff *c) {
+#ifdef __linux__
+#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
+ /*
+ * See clone(2).
+ * Instead of worrying about which direction the stack grows, just
+ * allocate twice as much and start the stack in the middle.
+ */
+ if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
+ /* errno will be set to ENOMEM */
+ return -1;
+ return clone(childProcess,
+ c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
+ CLONE_VFORK | CLONE_VM | SIGCHLD, c);
+#else
+/* not available on Solaris / Mac */
+ assert(0);
+ return -1;
+#endif
+}
+#endif
+
+static pid_t
+vforkChild(ChildStuff *c) {
+ volatile pid_t resultPid;
+
+ /*
+ * We separate the call to vfork into a separate function to make
+ * very sure to keep stack of child from corrupting stack of parent,
+ * as suggested by the scary gcc warning:
+ * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
+ */
+ resultPid = vfork();
+
+ if (resultPid == 0) {
+ childProcess(c);
+ }
+ assert(resultPid != 0); /* childProcess never returns */
+ return resultPid;
+}
+
+static pid_t
+forkChild(ChildStuff *c) {
+ pid_t resultPid;
+
+ /*
+ * From Solaris fork(2): In Solaris 10, a call to fork() is
+ * identical to a call to fork1(); only the calling thread is
+ * replicated in the child process. This is the POSIX-specified
+ * behavior for fork().
+ */
+ resultPid = fork();
+
+ if (resultPid == 0) {
+ childProcess(c);
+ }
+ assert(resultPid != 0); /* childProcess never returns */
+ return resultPid;
+}
+
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+static pid_t
+spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
+ pid_t resultPid;
+ jboolean isCopy;
+ int i, offset, rval, bufsize, magic;
+ char *buf, buf1[16];
+ char *hlpargs[2];
+ SpawnInfo sp;
+
+ /* need to tell helper which fd is for receiving the childstuff
+ * and which fd to send response back on
+ */
+ snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
+ /* put the fd string as argument to the helper cmd */
+ hlpargs[0] = buf1;
+ hlpargs[1] = 0;
+
+ /* Following items are sent down the pipe to the helper
+ * after it is spawned.
+ * All strings are null terminated. All arrays of strings
+ * have an empty string for termination.
+ * - the ChildStuff struct
+ * - the SpawnInfo struct
+ * - the argv strings array
+ * - the envv strings array
+ * - the home directory string
+ * - the parentPath string
+ * - the parentPathv array
+ */
+ /* First calculate the sizes */
+ arraysize(c->argv, &sp.nargv, &sp.argvBytes);
+ bufsize = sp.argvBytes;
+ arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
+ bufsize += sp.envvBytes;
+ sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
+ bufsize += sp.dirlen;
+ arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
+ bufsize += sp.parentPathvBytes;
+ /* We need to clear FD_CLOEXEC if set in the fds[].
+ * Files are created FD_CLOEXEC in Java.
+ * Otherwise, they will be closed when the target gets exec'd */
+ for (i=0; i<3; i++) {
+ if (c->fds[i] != -1) {
+ int flags = fcntl(c->fds[i], F_GETFD);
+ if (flags & FD_CLOEXEC) {
+ fcntl(c->fds[i], F_SETFD, flags & (~1));
+ }
+ }
+ }
+
+ rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
+
+ if (rval != 0) {
+ return -1;
+ }
+
+ /* now the lengths are known, copy the data */
+ buf = NEW(char, bufsize);
+ if (buf == 0) {
+ return -1;
+ }
+ offset = copystrings(buf, 0, &c->argv[0]);
+ offset = copystrings(buf, offset, &c->envv[0]);
+ memcpy(buf+offset, c->pdir, sp.dirlen);
+ offset += sp.dirlen;
+ offset = copystrings(buf, offset, parentPathv);
+ assert(offset == bufsize);
+
+ magic = magicNumber();
+
+ /* write the two structs and the data buffer */
+ write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
+ write(c->childenv[1], (char *)c, sizeof(*c));
+ write(c->childenv[1], (char *)&sp, sizeof(sp));
+ write(c->childenv[1], buf, bufsize);
+ free(buf);
+
+ /* In this mode an external main() in invoked which calls back into
+ * childProcess() in this file, rather than directly
+ * via the statement below */
+ return resultPid;
+}
+#endif
+
+/*
+ * Start a child process running function childProcess.
+ * This function only returns in the parent.
+ */
+static pid_t
+startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
+ switch (c->mode) {
+ case MODE_VFORK:
+ return vforkChild(c);
+ case MODE_FORK:
+ return forkChild(c);
+#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
+ case MODE_POSIX_SPAWN:
+ return spawnChild(env, process, c, helperpath);
+#endif
+ default:
+ return -1;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
+ jobject process,
+ jint mode,
+ jbyteArray helperpath,
+ jbyteArray prog,
+ jbyteArray argBlock, jint argc,
+ jbyteArray envBlock, jint envc,
+ jbyteArray dir,
+ jintArray std_fds,
+ jboolean redirectErrorStream)
+{
+ int errnum;
+ int resultPid = -1;
+ int in[2], out[2], err[2], fail[2], childenv[2];
+ jint *fds = NULL;
+ const char *phelperpath = NULL;
+ const char *pprog = NULL;
+ const char *pargBlock = NULL;
+ const char *penvBlock = NULL;
+ ChildStuff *c;
+
+ in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
+ childenv[0] = childenv[1] = -1;
+
+ if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
+ c->argv = NULL;
+ c->envv = NULL;
+ c->pdir = NULL;
+ c->clone_stack = NULL;
+
+ /* Convert prog + argBlock into a char ** argv.
+ * Add one word room for expansion of argv for use by
+ * execve_as_traditional_shell_script.
+ * This word is also used when using spawn mode
+ */
+ assert(prog != NULL && argBlock != NULL);
+ if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch;
+ if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
+ if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
+ if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
+ c->argv[0] = pprog;
+ c->argc = argc + 2;
+ initVectorFromBlock(c->argv+1, pargBlock, argc);
+
+ if (envBlock != NULL) {
+ /* Convert envBlock into a char ** envv */
+ if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch;
+ if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
+ initVectorFromBlock(c->envv, penvBlock, envc);
+ }
+
+ if (dir != NULL) {
+ if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
+ }
+
+ assert(std_fds != NULL);
+ fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
+ if (fds == NULL) goto Catch;
+
+ if ((fds[0] == -1 && pipe(in) < 0) ||
+ (fds[1] == -1 && pipe(out) < 0) ||
+ (fds[2] == -1 && pipe(err) < 0) ||
+ (pipe(childenv) < 0) ||
+ (pipe(fail) < 0)) {
+ throwIOException(env, errno, "Bad file descriptor");
+ goto Catch;
+ }
+ c->fds[0] = fds[0];
+ c->fds[1] = fds[1];
+ c->fds[2] = fds[2];
+
+ copyPipe(in, c->in);
+ copyPipe(out, c->out);
+ copyPipe(err, c->err);
+ copyPipe(fail, c->fail);
+ copyPipe(childenv, c->childenv);
+
+ c->redirectErrorStream = redirectErrorStream;
+ c->mode = mode;
+
+ resultPid = startChild(env, process, c, phelperpath);
+ assert(resultPid != 0);
+
+ if (resultPid < 0) {
+ switch (c->mode) {
+ case MODE_VFORK:
+ throwIOException(env, errno, "vfork failed");
+ break;
+ case MODE_FORK:
+ throwIOException(env, errno, "fork failed");
+ break;
+ case MODE_POSIX_SPAWN:
+ throwIOException(env, errno, "spawn failed");
+ break;
+ }
+ goto Catch;
+ }
+ close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */
+
+ switch (readFully(fail[0], &errnum, sizeof(errnum))) {
+ case 0: break; /* Exec succeeded */
+ case sizeof(errnum):
+ waitpid(resultPid, NULL, 0);
+ throwIOException(env, errnum, "Exec failed");
+ goto Catch;
+ default:
+ throwIOException(env, errno, "Read failed");
+ goto Catch;
+ }
+
+ fds[0] = (in [1] != -1) ? in [1] : -1;
+ fds[1] = (out[0] != -1) ? out[0] : -1;
+ fds[2] = (err[0] != -1) ? err[0] : -1;
+
+ Finally:
+ free(c->clone_stack);
+
+ /* Always clean up the child's side of the pipes */
+ closeSafely(in [0]);
+ closeSafely(out[1]);
+ closeSafely(err[1]);
+
+ /* Always clean up fail and childEnv descriptors */
+ closeSafely(fail[0]);
+ closeSafely(fail[1]);
+ closeSafely(childenv[0]);
+ closeSafely(childenv[1]);
+
+ releaseBytes(env, helperpath, phelperpath);
+ releaseBytes(env, prog, pprog);
+ releaseBytes(env, argBlock, pargBlock);
+ releaseBytes(env, envBlock, penvBlock);
+ releaseBytes(env, dir, c->pdir);
+
+ free(c->argv);
+ free(c->envv);
+ free(c);
+
+ if (fds != NULL)
+ (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
+
+ return resultPid;
+
+ Catch:
+ /* Clean up the parent's side of the pipes in case of failure only */
+ closeSafely(in [1]); in[1] = -1;
+ closeSafely(out[0]); out[0] = -1;
+ closeSafely(err[0]); err[0] = -1;
+ goto Finally;
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_ProcessImpl_destroyProcess(JNIEnv *env,
+ jobject junk,
+ jint pid,
+ jboolean force)
+{
+ int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
+ kill(pid, sig);
+}
--- a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#undef _LARGEFILE64_SOURCE
-#define _LARGEFILE64_SOURCE 1
-
-#include "jni.h"
-#include "jvm.h"
-#include "jvm_md.h"
-#include "jni_util.h"
-#include "io_util.h"
-
-/*
- * Platform-specific support for java.lang.Process
- */
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <string.h>
-
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
-#include <spawn.h>
-#endif
-
-#include "childproc.h"
-
-/*
- * There are 4 possible strategies we might use to "fork":
- *
- * - fork(2). Very portable and reliable but subject to
- * failure due to overcommit (see the documentation on
- * /proc/sys/vm/overcommit_memory in Linux proc(5)).
- * This is the ancient problem of spurious failure whenever a large
- * process starts a small subprocess.
- *
- * - vfork(). Using this is scary because all relevant man pages
- * contain dire warnings, e.g. Linux vfork(2). But at least it's
- * documented in the glibc docs and is standardized by XPG4.
- * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
- * On Linux, one might think that vfork() would be implemented using
- * the clone system call with flag CLONE_VFORK, but in fact vfork is
- * a separate system call (which is a good sign, suggesting that
- * vfork will continue to be supported at least on Linux).
- * Another good sign is that glibc implements posix_spawn using
- * vfork whenever possible. Note that we cannot use posix_spawn
- * ourselves because there's no reliable way to close all inherited
- * file descriptors.
- *
- * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is
- * Linux-specific, but this ought to work - at least the glibc
- * sources contain code to handle different combinations of CLONE_VM
- * and CLONE_THREAD. However, when this was implemented, it
- * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
- * the simple program
- * Runtime.getRuntime().exec("/bin/true").waitFor();
- * with:
- * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
- * # Error: pthread_getattr_np failed with errno = 3 (ESRCH)
- * We believe this is a glibc bug, reported here:
- * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
- * but the glibc maintainers closed it as WONTFIX.
- *
- * - posix_spawn(). While posix_spawn() is a fairly elaborate and
- * complicated system call, it can't quite do everything that the old
- * fork()/exec() combination can do, so the only feasible way to do
- * this, is to use posix_spawn to launch a new helper executable
- * "jprochelper", which in turn execs the target (after cleaning
- * up file-descriptors etc.) The end result is the same as before,
- * a child process linked to the parent in the same way, but it
- * avoids the problem of duplicating the parent (VM) process
- * address space temporarily, before launching the target command.
- *
- * Based on the above analysis, we are currently using vfork() on
- * Linux and spawn() on other Unix systems, but the code to use clone()
- * and fork() remains.
- */
-
-
-static void
-setSIGCHLDHandler(JNIEnv *env)
-{
- /* There is a subtle difference between having the signal handler
- * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
- * termination information for child processes if the signal
- * handler is SIG_IGN. It must be SIG_DFL.
- *
- * We used to set the SIGCHLD handler only on Linux, but it's
- * safest to set it unconditionally.
- *
- * Consider what happens if java's parent process sets the SIGCHLD
- * handler to SIG_IGN. Normally signal handlers are inherited by
- * children, but SIGCHLD is a controversial case. Solaris appears
- * to always reset it to SIG_DFL, but this behavior may be
- * non-standard-compliant, and we shouldn't rely on it.
- *
- * References:
- * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
- * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
- */
- struct sigaction sa;
- sa.sa_handler = SIG_DFL;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
- if (sigaction(SIGCHLD, &sa, NULL) < 0)
- JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
-}
-
-static void*
-xmalloc(JNIEnv *env, size_t size)
-{
- void *p = malloc(size);
- if (p == NULL)
- JNU_ThrowOutOfMemoryError(env, NULL);
- return p;
-}
-
-#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
-
-/**
- * If PATH is not defined, the OS provides some default value.
- * Unfortunately, there's no portable way to get this value.
- * Fortunately, it's only needed if the child has PATH while we do not.
- */
-static const char*
-defaultPath(void)
-{
-#ifdef __solaris__
- /* These really are the Solaris defaults! */
- return (geteuid() == 0 || getuid() == 0) ?
- "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
- "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
-#else
- return ":/bin:/usr/bin"; /* glibc */
-#endif
-}
-
-static const char*
-effectivePath(void)
-{
- const char *s = getenv("PATH");
- return (s != NULL) ? s : defaultPath();
-}
-
-static int
-countOccurrences(const char *s, char c)
-{
- int count;
- for (count = 0; *s != '\0'; s++)
- count += (*s == c);
- return count;
-}
-
-static const char * const *
-effectivePathv(JNIEnv *env)
-{
- char *p;
- int i;
- const char *path = effectivePath();
- int count = countOccurrences(path, ':') + 1;
- size_t pathvsize = sizeof(const char *) * (count+1);
- size_t pathsize = strlen(path) + 1;
- const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
-
- if (pathv == NULL)
- return NULL;
- p = (char *) pathv + pathvsize;
- memcpy(p, path, pathsize);
- /* split PATH by replacing ':' with NULs; empty components => "." */
- for (i = 0; i < count; i++) {
- char *q = p + strcspn(p, ":");
- pathv[i] = (p == q) ? "." : p;
- *q = '\0';
- p = q + 1;
- }
- pathv[count] = NULL;
- return pathv;
-}
-
-JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
-{
- parentPathv = effectivePathv(env);
- CHECK_NULL(parentPathv);
- setSIGCHLDHandler(env);
-}
-
-
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status)&0xFF) == 0)
-#endif
-
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status)>>8)&0xFF)
-#endif
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
-#endif
-
-#ifndef WTERMSIG
-#define WTERMSIG(status) ((status)&0x7F)
-#endif
-
-/* Block until a child process exits and return its exit code.
- Note, can only be called once for any given pid. */
-JNIEXPORT jint JNICALL
-Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
- jobject junk,
- jint pid)
-{
- /* We used to use waitid() on Solaris, waitpid() on Linux, but
- * waitpid() is more standard, so use it on all POSIX platforms. */
- int status;
- /* Wait for the child process to exit. This returns immediately if
- the child has already exited. */
- while (waitpid(pid, &status, 0) < 0) {
- switch (errno) {
- case ECHILD: return 0;
- case EINTR: break;
- default: return -1;
- }
- }
-
- if (WIFEXITED(status)) {
- /*
- * The child exited normally; get its exit code.
- */
- return WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- /* The child exited because of a signal.
- * The best value to return is 0x80 + signal number,
- * because that is what all Unix shells do, and because
- * it allows callers to distinguish between process exit and
- * process death by signal.
- * Unfortunately, the historical behavior on Solaris is to return
- * the signal number, and we preserve this for compatibility. */
-#ifdef __solaris__
- return WTERMSIG(status);
-#else
- return 0x80 + WTERMSIG(status);
-#endif
- } else {
- /*
- * Unknown exit code; pass it through.
- */
- return status;
- }
-}
-
-static const char *
-getBytes(JNIEnv *env, jbyteArray arr)
-{
- return arr == NULL ? NULL :
- (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
-}
-
-static void
-releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
-{
- if (parr != NULL)
- (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
-}
-
-static void
-throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
-{
- static const char * const format = "error=%d, %s";
- const char *detail = defaultDetail;
- char *errmsg;
- jstring s;
-
- if (errnum != 0) {
- const char *s = strerror(errnum);
- if (strcmp(s, "Unknown error") != 0)
- detail = s;
- }
- /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
- errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
- if (errmsg == NULL)
- return;
-
- sprintf(errmsg, format, errnum, detail);
- s = JNU_NewStringPlatform(env, errmsg);
- if (s != NULL) {
- jobject x = JNU_NewObjectByName(env, "java/io/IOException",
- "(Ljava/lang/String;)V", s);
- if (x != NULL)
- (*env)->Throw(env, x);
- }
- free(errmsg);
-}
-
-#ifdef DEBUG_PROCESS
-/* Debugging process code is difficult; where to write debug output? */
-static void
-debugPrint(char *format, ...)
-{
- FILE *tty = fopen("/dev/tty", "w");
- va_list ap;
- va_start(ap, format);
- vfprintf(tty, format, ap);
- va_end(ap);
- fclose(tty);
-}
-#endif /* DEBUG_PROCESS */
-
-static void
-copyPipe(int from[2], int to[2])
-{
- to[0] = from[0];
- to[1] = from[1];
-}
-
-/* arg is an array of pointers to 0 terminated strings. array is terminated
- * by a null element.
- *
- * *nelems and *nbytes receive the number of elements of array (incl 0)
- * and total number of bytes (incl. 0)
- * Note. An empty array will have one null element
- * But if arg is null, then *nelems set to 0, and *nbytes to 0
- */
-static void arraysize(const char * const *arg, int *nelems, int *nbytes)
-{
- int i, bytes, count;
- const char * const *a = arg;
- char *p;
- int *q;
- if (arg == 0) {
- *nelems = 0;
- *nbytes = 0;
- return;
- }
- /* count the array elements and number of bytes */
- for (count=0, bytes=0; *a != 0; count++, a++) {
- bytes += strlen(*a)+1;
- }
- *nbytes = bytes;
- *nelems = count+1;
-}
-
-/* copy the strings from arg[] into buf, starting at given offset
- * return new offset to next free byte
- */
-static int copystrings(char *buf, int offset, const char * const *arg) {
- char *p;
- const char * const *a;
- int count=0;
-
- if (arg == 0) {
- return offset;
- }
- for (p=buf+offset, a=arg; *a != 0; a++) {
- int len = strlen(*a) +1;
- memcpy(p, *a, len);
- p += len;
- count += len;
- }
- return offset+count;
-}
-
-/**
- * We are unusually paranoid; use of clone/vfork is
- * especially likely to tickle gcc/glibc bugs.
- */
-#ifdef __attribute_noinline__ /* See: sys/cdefs.h */
-__attribute_noinline__
-#endif
-
-#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */
-
-#ifdef START_CHILD_USE_CLONE
-static pid_t
-cloneChild(ChildStuff *c) {
-#ifdef __linux__
-#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
- /*
- * See clone(2).
- * Instead of worrying about which direction the stack grows, just
- * allocate twice as much and start the stack in the middle.
- */
- if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
- /* errno will be set to ENOMEM */
- return -1;
- return clone(childProcess,
- c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
- CLONE_VFORK | CLONE_VM | SIGCHLD, c);
-#else
-/* not available on Solaris / Mac */
- assert(0);
- return -1;
-#endif
-}
-#endif
-
-static pid_t
-vforkChild(ChildStuff *c) {
- volatile pid_t resultPid;
-
- /*
- * We separate the call to vfork into a separate function to make
- * very sure to keep stack of child from corrupting stack of parent,
- * as suggested by the scary gcc warning:
- * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
- */
- resultPid = vfork();
-
- if (resultPid == 0) {
- childProcess(c);
- }
- assert(resultPid != 0); /* childProcess never returns */
- return resultPid;
-}
-
-static pid_t
-forkChild(ChildStuff *c) {
- pid_t resultPid;
-
- /*
- * From Solaris fork(2): In Solaris 10, a call to fork() is
- * identical to a call to fork1(); only the calling thread is
- * replicated in the child process. This is the POSIX-specified
- * behavior for fork().
- */
- resultPid = fork();
-
- if (resultPid == 0) {
- childProcess(c);
- }
- assert(resultPid != 0); /* childProcess never returns */
- return resultPid;
-}
-
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
-static pid_t
-spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
- pid_t resultPid;
- jboolean isCopy;
- int i, offset, rval, bufsize, magic;
- char *buf, buf1[16];
- char *hlpargs[2];
- SpawnInfo sp;
-
- /* need to tell helper which fd is for receiving the childstuff
- * and which fd to send response back on
- */
- snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
- /* put the fd string as argument to the helper cmd */
- hlpargs[0] = buf1;
- hlpargs[1] = 0;
-
- /* Following items are sent down the pipe to the helper
- * after it is spawned.
- * All strings are null terminated. All arrays of strings
- * have an empty string for termination.
- * - the ChildStuff struct
- * - the SpawnInfo struct
- * - the argv strings array
- * - the envv strings array
- * - the home directory string
- * - the parentPath string
- * - the parentPathv array
- */
- /* First calculate the sizes */
- arraysize(c->argv, &sp.nargv, &sp.argvBytes);
- bufsize = sp.argvBytes;
- arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
- bufsize += sp.envvBytes;
- sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
- bufsize += sp.dirlen;
- arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
- bufsize += sp.parentPathvBytes;
- /* We need to clear FD_CLOEXEC if set in the fds[].
- * Files are created FD_CLOEXEC in Java.
- * Otherwise, they will be closed when the target gets exec'd */
- for (i=0; i<3; i++) {
- if (c->fds[i] != -1) {
- int flags = fcntl(c->fds[i], F_GETFD);
- if (flags & FD_CLOEXEC) {
- fcntl(c->fds[i], F_SETFD, flags & (~1));
- }
- }
- }
-
- rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
-
- if (rval != 0) {
- return -1;
- }
-
- /* now the lengths are known, copy the data */
- buf = NEW(char, bufsize);
- if (buf == 0) {
- return -1;
- }
- offset = copystrings(buf, 0, &c->argv[0]);
- offset = copystrings(buf, offset, &c->envv[0]);
- memcpy(buf+offset, c->pdir, sp.dirlen);
- offset += sp.dirlen;
- offset = copystrings(buf, offset, parentPathv);
- assert(offset == bufsize);
-
- magic = magicNumber();
-
- /* write the two structs and the data buffer */
- write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
- write(c->childenv[1], (char *)c, sizeof(*c));
- write(c->childenv[1], (char *)&sp, sizeof(sp));
- write(c->childenv[1], buf, bufsize);
- free(buf);
-
- /* In this mode an external main() in invoked which calls back into
- * childProcess() in this file, rather than directly
- * via the statement below */
- return resultPid;
-}
-#endif
-
-/*
- * Start a child process running function childProcess.
- * This function only returns in the parent.
- */
-static pid_t
-startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
- switch (c->mode) {
- case MODE_VFORK:
- return vforkChild(c);
- case MODE_FORK:
- return forkChild(c);
-#if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
- case MODE_POSIX_SPAWN:
- return spawnChild(env, process, c, helperpath);
-#endif
- default:
- return -1;
- }
-}
-
-JNIEXPORT jint JNICALL
-Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
- jobject process,
- jint mode,
- jbyteArray helperpath,
- jbyteArray prog,
- jbyteArray argBlock, jint argc,
- jbyteArray envBlock, jint envc,
- jbyteArray dir,
- jintArray std_fds,
- jboolean redirectErrorStream)
-{
- int errnum;
- int resultPid = -1;
- int in[2], out[2], err[2], fail[2], childenv[2];
- jint *fds = NULL;
- const char *phelperpath = NULL;
- const char *pprog = NULL;
- const char *pargBlock = NULL;
- const char *penvBlock = NULL;
- ChildStuff *c;
-
- in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
- childenv[0] = childenv[1] = -1;
-
- if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
- c->argv = NULL;
- c->envv = NULL;
- c->pdir = NULL;
- c->clone_stack = NULL;
-
- /* Convert prog + argBlock into a char ** argv.
- * Add one word room for expansion of argv for use by
- * execve_as_traditional_shell_script.
- * This word is also used when using spawn mode
- */
- assert(prog != NULL && argBlock != NULL);
- if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch;
- if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
- if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
- if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
- c->argv[0] = pprog;
- c->argc = argc + 2;
- initVectorFromBlock(c->argv+1, pargBlock, argc);
-
- if (envBlock != NULL) {
- /* Convert envBlock into a char ** envv */
- if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch;
- if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
- initVectorFromBlock(c->envv, penvBlock, envc);
- }
-
- if (dir != NULL) {
- if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
- }
-
- assert(std_fds != NULL);
- fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
- if (fds == NULL) goto Catch;
-
- if ((fds[0] == -1 && pipe(in) < 0) ||
- (fds[1] == -1 && pipe(out) < 0) ||
- (fds[2] == -1 && pipe(err) < 0) ||
- (pipe(childenv) < 0) ||
- (pipe(fail) < 0)) {
- throwIOException(env, errno, "Bad file descriptor");
- goto Catch;
- }
- c->fds[0] = fds[0];
- c->fds[1] = fds[1];
- c->fds[2] = fds[2];
-
- copyPipe(in, c->in);
- copyPipe(out, c->out);
- copyPipe(err, c->err);
- copyPipe(fail, c->fail);
- copyPipe(childenv, c->childenv);
-
- c->redirectErrorStream = redirectErrorStream;
- c->mode = mode;
-
- resultPid = startChild(env, process, c, phelperpath);
- assert(resultPid != 0);
-
- if (resultPid < 0) {
- switch (c->mode) {
- case MODE_VFORK:
- throwIOException(env, errno, "vfork failed");
- break;
- case MODE_FORK:
- throwIOException(env, errno, "fork failed");
- break;
- case MODE_POSIX_SPAWN:
- throwIOException(env, errno, "spawn failed");
- break;
- }
- goto Catch;
- }
- close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */
-
- switch (readFully(fail[0], &errnum, sizeof(errnum))) {
- case 0: break; /* Exec succeeded */
- case sizeof(errnum):
- waitpid(resultPid, NULL, 0);
- throwIOException(env, errnum, "Exec failed");
- goto Catch;
- default:
- throwIOException(env, errno, "Read failed");
- goto Catch;
- }
-
- fds[0] = (in [1] != -1) ? in [1] : -1;
- fds[1] = (out[0] != -1) ? out[0] : -1;
- fds[2] = (err[0] != -1) ? err[0] : -1;
-
- Finally:
- free(c->clone_stack);
-
- /* Always clean up the child's side of the pipes */
- closeSafely(in [0]);
- closeSafely(out[1]);
- closeSafely(err[1]);
-
- /* Always clean up fail and childEnv descriptors */
- closeSafely(fail[0]);
- closeSafely(fail[1]);
- closeSafely(childenv[0]);
- closeSafely(childenv[1]);
-
- releaseBytes(env, helperpath, phelperpath);
- releaseBytes(env, prog, pprog);
- releaseBytes(env, argBlock, pargBlock);
- releaseBytes(env, envBlock, penvBlock);
- releaseBytes(env, dir, c->pdir);
-
- free(c->argv);
- free(c->envv);
- free(c);
-
- if (fds != NULL)
- (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
-
- return resultPid;
-
- Catch:
- /* Clean up the parent's side of the pipes in case of failure only */
- closeSafely(in [1]); in[1] = -1;
- closeSafely(out[0]); out[0] = -1;
- closeSafely(err[0]); err[0] = -1;
- goto Finally;
-}
-
-JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env,
- jobject junk,
- jint pid,
- jboolean force)
-{
- int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM;
- kill(pid, sig);
-}
--- a/jdk/src/java.base/unix/native/libjava/childproc.h Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/unix/native/libjava/childproc.h Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
} while((_result == -1) && (errno == EINTR)); \
} while(0)
-/* These numbers must be the same as the Enum in UNIXProcess.java
+/* These numbers must be the same as the Enum in ProcessImpl.java
* Must be a better way of doing this.
*/
#define MODE_FORK 1
--- a/jdk/src/java.base/unix/native/libjava/java_props_macosx.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <dlfcn.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <Security/AuthSession.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <Foundation/Foundation.h>
-
-#include "java_props_macosx.h"
-
-
-// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
-static void *getJRSFramework() {
- static void *jrsFwk = NULL;
- if (jrsFwk == NULL) {
- jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
- }
- return jrsFwk;
-}
-
-char *getPosixLocale(int cat) {
- char *lc = setlocale(cat, NULL);
- if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
- lc = getenv("LANG");
- }
- if (lc == NULL) return NULL;
- return strdup(lc);
-}
-
-#define LOCALEIDLENGTH 128
-char *getMacOSXLocale(int cat) {
- switch (cat) {
- case LC_MESSAGES:
- {
- void *jrsFwk = getJRSFramework();
- if (jrsFwk == NULL) return NULL;
-
- char *(*JRSCopyPrimaryLanguage)() = dlsym(jrsFwk, "JRSCopyPrimaryLanguage");
- char *primaryLanguage = JRSCopyPrimaryLanguage ? JRSCopyPrimaryLanguage() : NULL;
- if (primaryLanguage == NULL) return NULL;
-
- char *(*JRSCopyCanonicalLanguageForPrimaryLanguage)(char *) = dlsym(jrsFwk, "JRSCopyCanonicalLanguageForPrimaryLanguage");
- char *canonicalLanguage = JRSCopyCanonicalLanguageForPrimaryLanguage ? JRSCopyCanonicalLanguageForPrimaryLanguage(primaryLanguage) : NULL;
- free (primaryLanguage);
-
- return canonicalLanguage;
- }
- break;
- default:
- {
- char localeString[LOCALEIDLENGTH];
- if (CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
- localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
- return strdup(localeString);
- }
- }
- break;
- }
-
- return NULL;
-}
-
-char *setupMacOSXLocale(int cat) {
- char * ret = getMacOSXLocale(cat);
-
- if (cat == LC_MESSAGES && ret != NULL) {
- void *jrsFwk = getJRSFramework();
- if (jrsFwk != NULL) {
- void (*JRSSetDefaultLocalization)(char *) = dlsym(jrsFwk, "JRSSetDefaultLocalization");
- if (JRSSetDefaultLocalization) JRSSetDefaultLocalization(ret);
- }
- }
-
- if (ret == NULL) {
- return getPosixLocale(cat);
- } else {
- return ret;
- }
-}
-
-int isInAquaSession() {
- // environment variable to bypass the aqua session check
- char *ev = getenv("AWT_FORCE_HEADFUL");
- if (ev && (strncasecmp(ev, "true", 4) == 0)) {
- // if "true" then tell the caller we're in an Aqua session without actually checking
- return 1;
- }
- // Is the WindowServer available?
- SecuritySessionId session_id;
- SessionAttributeBits session_info;
- OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
- if (status == noErr) {
- if (session_info & sessionHasGraphicAccess) {
- return 1;
- }
- }
- return 0;
-}
-
-void setOSNameAndVersion(java_props_t *sprops) {
- /* Don't rely on JRSCopyOSName because there's no guarantee the value will
- * remain the same, or even if the JRS functions will continue to be part of
- * Mac OS X. So hardcode os_name, and fill in os_version if we can.
- */
- sprops->os_name = strdup("Mac OS X");
-
- void *jrsFwk = getJRSFramework();
- if (jrsFwk != NULL) {
- char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion");
- if (copyOSVersion != NULL) {
- sprops->os_version = copyOSVersion();
- return;
- }
- }
- sprops->os_version = strdup("Unknown");
-}
-
-
-static Boolean getProxyInfoForProtocol(CFDictionaryRef inDict, CFStringRef inEnabledKey, CFStringRef inHostKey, CFStringRef inPortKey, CFStringRef *outProxyHost, int *ioProxyPort) {
- /* See if the proxy is enabled. */
- CFNumberRef cf_enabled = CFDictionaryGetValue(inDict, inEnabledKey);
- if (cf_enabled == NULL) {
- return false;
- }
-
- int isEnabled = false;
- if (!CFNumberGetValue(cf_enabled, kCFNumberIntType, &isEnabled)) {
- return isEnabled;
- }
-
- if (!isEnabled) return false;
- *outProxyHost = CFDictionaryGetValue(inDict, inHostKey);
-
- // If cf_host is null, that means the checkbox is set,
- // but no host was entered. We'll treat that as NOT ENABLED.
- // If cf_port is null or cf_port isn't a number, that means
- // no port number was entered. Treat this as ENABLED with the
- // protocol's default port.
- if (*outProxyHost == NULL) {
- return false;
- }
-
- if (CFStringGetLength(*outProxyHost) == 0) {
- return false;
- }
-
- int newPort = 0;
- CFNumberRef cf_port = NULL;
- if ((cf_port = CFDictionaryGetValue(inDict, inPortKey)) != NULL &&
- CFNumberGetValue(cf_port, kCFNumberIntType, &newPort) &&
- newPort > 0) {
- *ioProxyPort = newPort;
- } else {
- // bad port or no port - leave *ioProxyPort unchanged
- }
-
- return true;
-}
-
-static char *createUTF8CString(const CFStringRef theString) {
- if (theString == NULL) return NULL;
-
- const CFIndex stringLength = CFStringGetLength(theString);
- const CFIndex bufSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1;
- char *returnVal = (char *)malloc(bufSize);
-
- if (CFStringGetCString(theString, returnVal, bufSize, kCFStringEncodingUTF8)) {
- return returnVal;
- }
-
- free(returnVal);
- return NULL;
-}
-
-// Return TRUE if str is a syntactically valid IP address.
-// Using inet_pton() instead of inet_aton() for IPv6 support.
-// len is only a hint; cstr must still be nul-terminated
-static int looksLikeIPAddress(char *cstr, size_t len) {
- if (len == 0 || (len == 1 && cstr[0] == '.')) return FALSE;
-
- char dst[16]; // big enough for INET6
- return (1 == inet_pton(AF_INET, cstr, dst) ||
- 1 == inet_pton(AF_INET6, cstr, dst));
-}
-
-
-
-// Convert Mac OS X proxy exception entry to Java syntax.
-// See Radar #3441134 for details.
-// Returns NULL if this exception should be ignored by Java.
-// May generate a string with multiple exceptions separated by '|'.
-static char * createConvertedException(CFStringRef cf_original) {
- // This is done with char* instead of CFString because inet_pton()
- // needs a C string.
- char *c_exception = createUTF8CString(cf_original);
- if (!c_exception) return NULL;
-
- int c_len = strlen(c_exception);
-
- // 1. sanitize exception prefix
- if (c_len >= 1 && 0 == strncmp(c_exception, ".", 1)) {
- memmove(c_exception, c_exception+1, c_len);
- c_len -= 1;
- } else if (c_len >= 2 && 0 == strncmp(c_exception, "*.", 2)) {
- memmove(c_exception, c_exception+2, c_len-1);
- c_len -= 2;
- }
-
- // 2. pre-reject other exception wildcards
- if (strchr(c_exception, '*')) {
- free(c_exception);
- return NULL;
- }
-
- // 3. no IP wildcarding
- if (looksLikeIPAddress(c_exception, c_len)) {
- return c_exception;
- }
-
- // 4. allow domain suffixes
- // c_exception is now "str\0" - change to "str|*.str\0"
- c_exception = reallocf(c_exception, c_len+3+c_len+1);
- if (!c_exception) return NULL;
-
- strncpy(c_exception+c_len, "|*.", 3);
- strncpy(c_exception+c_len+3, c_exception, c_len);
- c_exception[c_len+3+c_len] = '\0';
- return c_exception;
-}
-
-/*
- * Method for fetching the user.home path and storing it in the property list.
- * For signed .apps running in the Mac App Sandbox, user.home is set to the
- * app's sandbox container.
- */
-void setUserHome(java_props_t *sprops) {
- if (sprops == NULL) { return; }
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- sprops->user_home = createUTF8CString((CFStringRef)NSHomeDirectory());
- [pool drain];
-}
-
-/*
- * Method for fetching proxy info and storing it in the property list.
- */
-void setProxyProperties(java_props_t *sProps) {
- if (sProps == NULL) return;
-
- char buf[16]; /* Used for %d of an int - 16 is plenty */
- CFStringRef
- cf_httpHost = NULL,
- cf_httpsHost = NULL,
- cf_ftpHost = NULL,
- cf_socksHost = NULL,
- cf_gopherHost = NULL;
- int
- httpPort = 80, // Default proxy port values
- httpsPort = 443,
- ftpPort = 21,
- socksPort = 1080,
- gopherPort = 70;
-
- CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
- if (dict == NULL) return;
-
- /* Read the proxy exceptions list */
- CFArrayRef cf_list = CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList);
-
- CFMutableStringRef cf_exceptionList = NULL;
- if (cf_list != NULL) {
- CFIndex len = CFArrayGetCount(cf_list), idx;
-
- cf_exceptionList = CFStringCreateMutable(NULL, 0);
- for (idx = (CFIndex)0; idx < len; idx++) {
- CFStringRef cf_ehost;
- if ((cf_ehost = CFArrayGetValueAtIndex(cf_list, idx))) {
- /* Convert this exception from Mac OS X syntax to Java syntax.
- See Radar #3441134 for details. This may generate a string
- with multiple Java exceptions separated by '|'. */
- char *c_exception = createConvertedException(cf_ehost);
- if (c_exception) {
- /* Append the host to the list of exclusions. */
- if (CFStringGetLength(cf_exceptionList) > 0) {
- CFStringAppendCString(cf_exceptionList, "|", kCFStringEncodingMacRoman);
- }
- CFStringAppendCString(cf_exceptionList, c_exception, kCFStringEncodingMacRoman);
- free(c_exception);
- }
- }
- }
- }
-
- if (cf_exceptionList != NULL) {
- if (CFStringGetLength(cf_exceptionList) > 0) {
- sProps->exceptionList = createUTF8CString(cf_exceptionList);
- }
- CFRelease(cf_exceptionList);
- }
-
-#define CHECK_PROXY(protocol, PROTOCOL) \
- sProps->protocol##ProxyEnabled = \
- getProxyInfoForProtocol(dict, kSCPropNetProxies##PROTOCOL##Enable, \
- kSCPropNetProxies##PROTOCOL##Proxy, \
- kSCPropNetProxies##PROTOCOL##Port, \
- &cf_##protocol##Host, &protocol##Port); \
- if (sProps->protocol##ProxyEnabled) { \
- sProps->protocol##Host = createUTF8CString(cf_##protocol##Host); \
- snprintf(buf, sizeof(buf), "%d", protocol##Port); \
- sProps->protocol##Port = malloc(strlen(buf) + 1); \
- strcpy(sProps->protocol##Port, buf); \
- }
-
- CHECK_PROXY(http, HTTP);
- CHECK_PROXY(https, HTTPS);
- CHECK_PROXY(ftp, FTP);
- CHECK_PROXY(socks, SOCKS);
- CHECK_PROXY(gopher, Gopher);
-
-#undef CHECK_PROXY
-
- CFRelease(dict);
-}
--- a/jdk/src/java.base/unix/native/libjava/java_props_macosx.h Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "java_props.h"
-
-char *setupMacOSXLocale(int cat);
-void setOSNameAndVersion(java_props_t *sprops);
-void setUserHome(java_props_t *sprops);
-void setProxyProperties(java_props_t *sProps);
-int isInAquaSession();
--- a/jdk/src/java.base/unix/native/libnet/bsd_close.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
- pthread_t thr; /* this thread */
- struct threadEntry *next; /* next thread */
- int intr; /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
- pthread_mutex_t lock; /* fd lock */
- threadEntry_t *threads; /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = SIGIO;
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable;
-static int fdCount;
-
-/*
- * This limit applies if getlimit() returns unlimited.
- * Unfortunately, this means if someone wants a higher limit
- * then they have to set an explicit limit, higher than this,
- * which is probably counter-intuitive.
- */
-#define MAX_FD_COUNT 4096
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- */
-static void __attribute((constructor)) init() {
- struct rlimit nbr_files;
- sigset_t sigset;
- struct sigaction sa;
- int i;
-
- /*
- * Allocate table based on the maximum number of
- * file descriptors.
- */
- getrlimit(RLIMIT_NOFILE, &nbr_files);
- if (nbr_files.rlim_max == RLIM_INFINITY) {
- fdCount = MAX_FD_COUNT;
- } else {
- fdCount = nbr_files.rlim_max;
- }
- fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
- if (fdTable == NULL) {
- fprintf(stderr, "library initialization failed - "
- "unable to allocate file descriptor table - out of memory");
- abort();
- }
- for (i=0; i<fdCount; i++) {
- pthread_mutex_init(&fdTable[i].lock, NULL);
- }
-
- /*
- * Setup the signal handler
- */
- sa.sa_handler = sig_wakeup;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigaction(sigWakeup, &sa, NULL);
-
- sigemptyset(&sigset);
- sigaddset(&sigset, sigWakeup);
- sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
- if (fd < 0 || fd >= fdCount) {
- return NULL;
- }
- return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- * Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
- self->thr = pthread_self();
- self->intr = 0;
-
- pthread_mutex_lock(&(fdEntry->lock));
- {
- self->next = fdEntry->threads;
- fdEntry->threads = self;
- }
- pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- * Remove thread from thread list for the fd
- * If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
- (fdEntry_t *fdEntry, threadEntry_t *self)
-{
- int orig_errno = errno;
- pthread_mutex_lock(&(fdEntry->lock));
- {
- threadEntry_t *curr, *prev=NULL;
- curr = fdEntry->threads;
- while (curr != NULL) {
- if (curr == self) {
- if (curr->intr) {
- orig_errno = EBADF;
- }
- if (prev == NULL) {
- fdEntry->threads = curr->next;
- } else {
- prev->next = curr->next;
- }
- break;
- }
- prev = curr;
- curr = curr->next;
- }
- }
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- * fd1 < 0 => close(fd2)
- * fd1 >= 0 => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
- int rv, orig_errno;
- fdEntry_t *fdEntry = getFdEntry(fd2);
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Lock the fd to hold-off additional I/O on this fd.
- */
- pthread_mutex_lock(&(fdEntry->lock));
-
- {
- /*
- * Send a wakeup signal to all threads blocked on this
- * file descriptor.
- */
- threadEntry_t *curr = fdEntry->threads;
- while (curr != NULL) {
- curr->intr = 1;
- pthread_kill( curr->thr, sigWakeup );
- curr = curr->next;
- }
-
- /*
- * And close/dup the file descriptor
- * (restart if interrupted by signal)
- */
- do {
- if (fd1 < 0) {
- rv = close(fd2);
- } else {
- rv = dup2(fd1, fd2);
- }
- } while (rv == -1 && errno == EINTR);
-
- }
-
- /*
- * Unlock without destroying errno
- */
- orig_errno = errno;
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-
- return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
- if (fd < 0) {
- errno = EBADF;
- return -1;
- }
- return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
- return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen) {
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len, unsigned int
- flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
- long prevtime = 0, newtime;
- struct timeval t, *tp = &t;
- fd_set fds;
- fd_set* fdsp = NULL;
- int allocated = 0;
- threadEntry_t self;
- fdEntry_t *fdEntry = getFdEntry(s);
-
- /*
- * Check that fd hasn't been closed.
- */
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Pick up current time as may need to adjust timeout
- */
- if (timeout > 0) {
- /* Timed */
- struct timeval now;
- gettimeofday(&now, NULL);
- prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
- } else if (timeout < 0) {
- /* Blocking */
- tp = 0;
- } else {
- /* Poll */
- t.tv_sec = 0;
- t.tv_usec = 0;
- }
-
- if (s < FD_SETSIZE) {
- fdsp = &fds;
- FD_ZERO(fdsp);
- } else {
- int length = (howmany(s+1, NFDBITS)) * sizeof(int);
- fdsp = (fd_set *) calloc(1, length);
- if (fdsp == NULL) {
- return -1; // errno will be set to ENOMEM
- }
- allocated = 1;
- }
- FD_SET(s, fdsp);
-
- for(;;) {
- int rv;
-
- /*
- * call select on the fd. If interrupted by our wakeup signal
- * errno will be set to EBADF.
- */
-
- startOp(fdEntry, &self);
- rv = select(s+1, fdsp, 0, 0, tp);
- endOp(fdEntry, &self);
-
- /*
- * If interrupted then adjust timeout. If timeout
- * has expired return 0 (indicating timeout expired).
- */
- if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- struct timeval now;
- gettimeofday(&now, NULL);
- newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- if (allocated != 0)
- free(fdsp);
- return 0;
- }
- prevtime = newtime;
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
- }
- } else {
- if (allocated != 0)
- free(fdsp);
- return rv;
- }
-
- }
-}
--- a/jdk/src/java.base/unix/native/libnet/linux_close.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/poll.h>
-
-/*
- * Stack allocated by thread when doing blocking operation
- */
-typedef struct threadEntry {
- pthread_t thr; /* this thread */
- struct threadEntry *next; /* next thread */
- int intr; /* interrupted */
-} threadEntry_t;
-
-/*
- * Heap allocated during initialized - one entry per fd
- */
-typedef struct {
- pthread_mutex_t lock; /* fd lock */
- threadEntry_t *threads; /* threads blocked on fd */
-} fdEntry_t;
-
-/*
- * Signal to unblock thread
- */
-static int sigWakeup = (__SIGRTMAX - 2);
-
-/*
- * The fd table and the number of file descriptors
- */
-static fdEntry_t *fdTable;
-static int fdCount;
-
-/*
- * Null signal handler
- */
-static void sig_wakeup(int sig) {
-}
-
-/*
- * Initialization routine (executed when library is loaded)
- * Allocate fd tables and sets up signal handler.
- */
-static void __attribute((constructor)) init() {
- struct rlimit nbr_files;
- sigset_t sigset;
- struct sigaction sa;
-
- /*
- * Allocate table based on the maximum number of
- * file descriptors.
- */
- getrlimit(RLIMIT_NOFILE, &nbr_files);
- fdCount = nbr_files.rlim_max;
- fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
- if (fdTable == NULL) {
- fprintf(stderr, "library initialization failed - "
- "unable to allocate file descriptor table - out of memory");
- abort();
- }
-
- /*
- * Setup the signal handler
- */
- sa.sa_handler = sig_wakeup;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigaction(sigWakeup, &sa, NULL);
-
- sigemptyset(&sigset);
- sigaddset(&sigset, sigWakeup);
- sigprocmask(SIG_UNBLOCK, &sigset, NULL);
-}
-
-/*
- * Return the fd table for this fd or NULL is fd out
- * of range.
- */
-static inline fdEntry_t *getFdEntry(int fd)
-{
- if (fd < 0 || fd >= fdCount) {
- return NULL;
- }
- return &fdTable[fd];
-}
-
-/*
- * Start a blocking operation :-
- * Insert thread onto thread list for the fd.
- */
-static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
-{
- self->thr = pthread_self();
- self->intr = 0;
-
- pthread_mutex_lock(&(fdEntry->lock));
- {
- self->next = fdEntry->threads;
- fdEntry->threads = self;
- }
- pthread_mutex_unlock(&(fdEntry->lock));
-}
-
-/*
- * End a blocking operation :-
- * Remove thread from thread list for the fd
- * If fd has been interrupted then set errno to EBADF
- */
-static inline void endOp
- (fdEntry_t *fdEntry, threadEntry_t *self)
-{
- int orig_errno = errno;
- pthread_mutex_lock(&(fdEntry->lock));
- {
- threadEntry_t *curr, *prev=NULL;
- curr = fdEntry->threads;
- while (curr != NULL) {
- if (curr == self) {
- if (curr->intr) {
- orig_errno = EBADF;
- }
- if (prev == NULL) {
- fdEntry->threads = curr->next;
- } else {
- prev->next = curr->next;
- }
- break;
- }
- prev = curr;
- curr = curr->next;
- }
- }
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-}
-
-/*
- * Close or dup2 a file descriptor ensuring that all threads blocked on
- * the file descriptor are notified via a wakeup signal.
- *
- * fd1 < 0 => close(fd2)
- * fd1 >= 0 => dup2(fd1, fd2)
- *
- * Returns -1 with errno set if operation fails.
- */
-static int closefd(int fd1, int fd2) {
- int rv, orig_errno;
- fdEntry_t *fdEntry = getFdEntry(fd2);
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Lock the fd to hold-off additional I/O on this fd.
- */
- pthread_mutex_lock(&(fdEntry->lock));
-
- {
- /*
- * And close/dup the file descriptor
- * (restart if interrupted by signal)
- */
- do {
- if (fd1 < 0) {
- rv = close(fd2);
- } else {
- rv = dup2(fd1, fd2);
- }
- } while (rv == -1 && errno == EINTR);
-
- /*
- * Send a wakeup signal to all threads blocked on this
- * file descriptor.
- */
- threadEntry_t *curr = fdEntry->threads;
- while (curr != NULL) {
- curr->intr = 1;
- pthread_kill( curr->thr, sigWakeup );
- curr = curr->next;
- }
- }
-
- /*
- * Unlock without destroying errno
- */
- orig_errno = errno;
- pthread_mutex_unlock(&(fdEntry->lock));
- errno = orig_errno;
-
- return rv;
-}
-
-/*
- * Wrapper for dup2 - same semantics as dup2 system call except
- * that any threads blocked in an I/O system call on fd2 will be
- * preempted and return -1/EBADF;
- */
-int NET_Dup2(int fd, int fd2) {
- if (fd < 0) {
- errno = EBADF;
- return -1;
- }
- return closefd(fd, fd2);
-}
-
-/*
- * Wrapper for close - same semantics as close system call
- * except that any threads blocked in an I/O on fd will be
- * preempted and the I/O system call will return -1/EBADF.
- */
-int NET_SocketClose(int fd) {
- return closefd(-1, fd);
-}
-
-/************** Basic I/O operations here ***************/
-
-/*
- * Macro to perform a blocking IO operation. Restarts
- * automatically if interrupted by signal (other than
- * our wakeup signal)
- */
-#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
- int ret; \
- threadEntry_t self; \
- fdEntry_t *fdEntry = getFdEntry(FD); \
- if (fdEntry == NULL) { \
- errno = EBADF; \
- return -1; \
- } \
- do { \
- startOp(fdEntry, &self); \
- ret = FUNC; \
- endOp(fdEntry, &self); \
- } while (ret == -1 && errno == EINTR); \
- return ret; \
-}
-
-int NET_Read(int s, void* buf, size_t len) {
- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen) {
- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, fromlen) );
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
-}
-
-int NET_SendTo(int s, const void *msg, int len, unsigned int
- flags, const struct sockaddr *to, int tolen) {
- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- BLOCKING_IO_RETURN_INT( s, accept(s, addr, addrlen) );
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
-}
-
-/*
- * Wrapper for poll(s, timeout).
- * Auto restarts with adjusted timeout if interrupted by
- * signal other than our wakeup signal.
- */
-int NET_Timeout(int s, long timeout) {
- long prevtime = 0, newtime;
- struct timeval t;
- fdEntry_t *fdEntry = getFdEntry(s);
-
- /*
- * Check that fd hasn't been closed.
- */
- if (fdEntry == NULL) {
- errno = EBADF;
- return -1;
- }
-
- /*
- * Pick up current time as may need to adjust timeout
- */
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- }
-
- for(;;) {
- struct pollfd pfd;
- int rv;
- threadEntry_t self;
-
- /*
- * Poll the fd. If interrupted by our wakeup signal
- * errno will be set to EBADF.
- */
- pfd.fd = s;
- pfd.events = POLLIN | POLLERR;
-
- startOp(fdEntry, &self);
- rv = poll(&pfd, 1, timeout);
- endOp(fdEntry, &self);
-
- /*
- * If interrupted then adjust timeout. If timeout
- * has expired return 0 (indicating timeout expired).
- */
- if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- return 0;
- }
- prevtime = newtime;
- }
- } else {
- return rv;
- }
-
- }
-}
--- a/jdk/src/java.base/unix/native/libnet/solaris_close.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <errno.h>
-#include <sys/socket.h>
-#include <stropts.h>
-#include <unistd.h>
-
-/* Support for restartable system calls on Solaris. */
-
-#define RESTARTABLE_RETURN_INT(_cmd) do { \
- int _result; \
- if (1) { \
- do { \
- _result = _cmd; \
- } while((_result == -1) && (errno == EINTR)); \
- return _result; \
- } \
-} while(0)
-
-int NET_Read(int s, void* buf, size_t len) {
- RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
-}
-
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
- struct sockaddr *from, socklen_t *fromlen) {
- RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
-}
-
-int NET_ReadV(int s, const struct iovec * vector, int count) {
- RESTARTABLE_RETURN_INT(readv(s, vector, count));
-}
-
-int NET_WriteV(int s, const struct iovec * vector, int count) {
- RESTARTABLE_RETURN_INT(writev(s, vector, count));
-}
-
-int NET_Send(int s, void *msg, int len, unsigned int flags) {
- RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
-}
-
-int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
- const struct sockaddr *to, int tolen) {
- RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
-}
-
-int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
- RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
-}
-
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
- RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
-}
-
-int NET_SocketClose(int fd) {
- return close(fd);
-}
-
-int NET_Dup2(int fd, int fd2) {
- return dup2(fd, fd2);
-}
-
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
- RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
-}
-
-int NET_Timeout(int s, long timeout) {
- int result;
- struct timeval t;
- long prevtime, newtime;
- struct pollfd pfd;
- pfd.fd = s;
- pfd.events = POLLIN;
-
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- prevtime = (t.tv_sec * 1000) + t.tv_usec / 1000;
- }
-
- for(;;) {
- result = poll(&pfd, 1, timeout);
- if (result < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = (t.tv_sec * 1000) + t.tv_usec /1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0)
- return 0;
- prevtime = newtime;
- }
- } else {
- return result;
- }
- }
-}
--- a/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/windows/native/libjava/ProcessImpl_md.c Mon Jan 26 17:00:39 2015 -0800
@@ -283,14 +283,10 @@
FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE};
- {
- /* Extraction of current process standard IOE handles */
- DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
- int i;
- for (i = 0; i < 3; ++i)
- /* Should not be closed by CloseHandle! */
- stdIOE[i] = GetStdHandle(idsIOE[i]);
- }
+ /* These three should not be closed by CloseHandle! */
+ stdIOE[0] = GetStdHandle(STD_INPUT_HANDLE);
+ stdIOE[1] = GetStdHandle(STD_OUTPUT_HANDLE);
+ stdIOE[2] = GetStdHandle(STD_ERROR_HANDLE);
prepareIOEHandleState(stdIOE, inherit);
{
@@ -319,11 +315,16 @@
if (success) {
PROCESS_INFORMATION pi;
- DWORD processFlag = CREATE_UNICODE_ENVIRONMENT;
+ DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
- /* Suppress popping-up of a console window for non-console applications */
- if (GetConsoleWindow() == NULL)
- processFlag |= CREATE_NO_WINDOW;
+ /* If the standard I/O is inherited, CREATE_NO_WINDOW must not be used. */
+ if (GetConsoleWindow() != NULL &&
+ (si.hStdInput == stdIOE[0] ||
+ si.hStdOutput == stdIOE[1] ||
+ si.hStdError == (redirectErrorStream ? stdIOE[1] : stdIOE[2])))
+ {
+ processFlag &= ~CREATE_NO_WINDOW;
+ }
si.dwFlags = STARTF_USESTDHANDLES;
if (!CreateProcessW(
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Mon Jan 26 17:00:39 2015 -0800
@@ -48,6 +48,8 @@
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
"(Ljava/net/InetAddress;I)V");
+ initInetAddressIDs(env);
+
// implement read timeout with select.
isRcvTimeoutSupported = 0;
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java Mon Jan 26 17:00:39 2015 -0800
@@ -913,9 +913,9 @@
private static String unquote(String s) {
s = s.trim();
- if (s.isEmpty()) return s;
- if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
- s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
+ if (s.length() >= 2 &&
+ ((s.charAt(0) == '"' && s.charAt(s.length()-1) == '"') ||
+ (s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\''))) {
s = s.substring(1, s.length()-1).trim();
}
return s;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.security.auth/solaris/native/libjaas/Solaris.c Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include "com_sun_security_auth_module_SolarisSystem.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+static void throwIllegalArgumentException(JNIEnv *env, const char *msg) {
+ jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
+ if (clazz != NULL)
+ (*env)->ThrowNew(env, clazz, msg);
+}
+
+JNIEXPORT void JNICALL
+Java_com_sun_security_auth_module_SolarisSystem_getSolarisInfo
+ (JNIEnv *env, jobject obj) {
+
+ int i;
+ char pwd_buf[1024];
+ struct passwd pwd;
+ jsize numSuppGroups = getgroups(0, NULL);
+ jfieldID fid;
+ jstring jstr;
+ jlongArray jgroups;
+ jlong *jgroupsAsArray;
+ gid_t *groups;
+ jclass cls;
+
+ groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
+
+ if (groups == NULL) {
+ jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
+ if (cls != NULL)
+ (*env)->ThrowNew(env, cls, NULL);
+ return;
+ }
+
+ cls = (*env)->GetObjectClass(env, obj);
+
+ memset(pwd_buf, 0, sizeof(pwd_buf));
+ if (getpwuid_r(getuid(), &pwd, pwd_buf, sizeof(pwd_buf)) != NULL &&
+ getgroups(numSuppGroups, groups) != -1) {
+
+ /*
+ * set username
+ */
+ fid = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
+ if (fid == 0) {
+ (*env)->ExceptionClear(env);
+ throwIllegalArgumentException(env, "invalid field: username");
+ goto cleanupAndReturn;
+ }
+ jstr = (*env)->NewStringUTF(env, pwd.pw_name);
+ if (jstr == NULL) {
+ goto cleanupAndReturn;
+ }
+ (*env)->SetObjectField(env, obj, fid, jstr);
+
+ /*
+ * set uid
+ */
+ fid = (*env)->GetFieldID(env, cls, "uid", "J");
+ if (fid == 0) {
+ (*env)->ExceptionClear(env);
+ throwIllegalArgumentException(env, "invalid field: uid");
+ goto cleanupAndReturn;
+ }
+ (*env)->SetLongField(env, obj, fid, pwd.pw_uid);
+
+ /*
+ * set gid
+ */
+ fid = (*env)->GetFieldID(env, cls, "gid", "J");
+ if (fid == 0) {
+ (*env)->ExceptionClear(env);
+ throwIllegalArgumentException(env, "invalid field: gid");
+ goto cleanupAndReturn;
+ }
+ (*env)->SetLongField(env, obj, fid, pwd.pw_gid);
+
+ /*
+ * set supplementary groups
+ */
+ fid = (*env)->GetFieldID(env, cls, "groups", "[J");
+ if (fid == 0) {
+ (*env)->ExceptionClear(env);
+ throwIllegalArgumentException(env, "invalid field: groups");
+ goto cleanupAndReturn;
+ }
+
+ jgroups = (*env)->NewLongArray(env, numSuppGroups);
+ if (jgroups == NULL) {
+ goto cleanupAndReturn;
+ }
+ jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
+ if (jgroupsAsArray == NULL) {
+ goto cleanupAndReturn;
+ }
+ for (i = 0; i < numSuppGroups; i++)
+ jgroupsAsArray[i] = groups[i];
+ (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
+ (*env)->SetObjectField(env, obj, fid, jgroups);
+ }
+cleanupAndReturn:
+ free(groups);
+
+ return;
+}
--- a/jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <jni.h>
-#include "com_sun_security_auth_module_SolarisSystem.h"
-#include <stdio.h>
-#include <pwd.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pwd.h>
-
-static void throwIllegalArgumentException(JNIEnv *env, const char *msg) {
- jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
- if (clazz != NULL)
- (*env)->ThrowNew(env, clazz, msg);
-}
-
-JNIEXPORT void JNICALL
-Java_com_sun_security_auth_module_SolarisSystem_getSolarisInfo
- (JNIEnv *env, jobject obj) {
-
- int i;
- char pwd_buf[1024];
- struct passwd pwd;
- jsize numSuppGroups = getgroups(0, NULL);
- jfieldID fid;
- jstring jstr;
- jlongArray jgroups;
- jlong *jgroupsAsArray;
- gid_t *groups;
- jclass cls;
-
- groups = (gid_t *)calloc(numSuppGroups, sizeof(gid_t));
-
- if (groups == NULL) {
- jclass cls = (*env)->FindClass(env,"java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, NULL);
- return;
- }
-
- cls = (*env)->GetObjectClass(env, obj);
-
- memset(pwd_buf, 0, sizeof(pwd_buf));
- if (getpwuid_r(getuid(), &pwd, pwd_buf, sizeof(pwd_buf)) != NULL &&
- getgroups(numSuppGroups, groups) != -1) {
-
- /*
- * set username
- */
- fid = (*env)->GetFieldID(env, cls, "username", "Ljava/lang/String;");
- if (fid == 0) {
- (*env)->ExceptionClear(env);
- throwIllegalArgumentException(env, "invalid field: username");
- goto cleanupAndReturn;
- }
- jstr = (*env)->NewStringUTF(env, pwd.pw_name);
- if (jstr == NULL) {
- goto cleanupAndReturn;
- }
- (*env)->SetObjectField(env, obj, fid, jstr);
-
- /*
- * set uid
- */
- fid = (*env)->GetFieldID(env, cls, "uid", "J");
- if (fid == 0) {
- (*env)->ExceptionClear(env);
- throwIllegalArgumentException(env, "invalid field: uid");
- goto cleanupAndReturn;
- }
- (*env)->SetLongField(env, obj, fid, pwd.pw_uid);
-
- /*
- * set gid
- */
- fid = (*env)->GetFieldID(env, cls, "gid", "J");
- if (fid == 0) {
- (*env)->ExceptionClear(env);
- throwIllegalArgumentException(env, "invalid field: gid");
- goto cleanupAndReturn;
- }
- (*env)->SetLongField(env, obj, fid, pwd.pw_gid);
-
- /*
- * set supplementary groups
- */
- fid = (*env)->GetFieldID(env, cls, "groups", "[J");
- if (fid == 0) {
- (*env)->ExceptionClear(env);
- throwIllegalArgumentException(env, "invalid field: groups");
- goto cleanupAndReturn;
- }
-
- jgroups = (*env)->NewLongArray(env, numSuppGroups);
- if (jgroups == NULL) {
- goto cleanupAndReturn;
- }
- jgroupsAsArray = (*env)->GetLongArrayElements(env, jgroups, 0);
- if (jgroupsAsArray == NULL) {
- goto cleanupAndReturn;
- }
- for (i = 0; i < numSuppGroups; i++)
- jgroupsAsArray[i] = groups[i];
- (*env)->ReleaseLongArrayElements(env, jgroups, jgroupsAsArray, 0);
- (*env)->SetObjectField(env, obj, fid, jgroups);
- }
-cleanupAndReturn:
- free(groups);
-
- return;
-}
--- a/jdk/test/ProblemList.txt Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/ProblemList.txt Mon Jan 26 17:00:39 2015 -0800
@@ -243,6 +243,9 @@
# 8062758
java/security/Security/ClassLoaderDeadlock/Deadlock2.sh generic-all
+# 8026393
+sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all
+
############################################################################
# jdk_sound
--- a/jdk/test/TEST.groups Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/TEST.groups Mon Jan 26 17:00:39 2015 -0800
@@ -628,7 +628,6 @@
sun/net/www/protocol/http \
java/io/BufferedReader/Lines.java \
java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java \
- java/lang/CharSequence/DefaultTest.java \
java/lang/IntegralPrimitiveToString.java \
java/lang/PrimitiveSumMinMaxTest.java \
java/lang/String/StringJoinTest.java \
--- a/jdk/test/java/lang/CharSequence/DefaultTest.java Thu Jan 22 22:42:33 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.PrimitiveIterator;
-import java.util.Spliterator;
-import java.util.stream.Collectors;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
-
-/*
- * @test
- * @summary Unit test for CharSequence default methods
- * @bug 8012665 8025002
- * @run testng DefaultTest
- */
-
-@Test(groups = "lib")
-public class DefaultTest {
-
- @Test(expectedExceptions = NoSuchElementException.class)
- public void testEmptyChars() {
- PrimitiveIterator.OfInt s = "".chars().iterator();
- assertFalse(s.hasNext());
- int ch = s.nextInt();
- }
-
- public void testSimpleChars() {
- List<Integer> list = "abc".chars().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int) 'a', (int) 'b', (int) 'c'));
- }
-
- public void testCodePointsCharacteristics() {
- Spliterator.OfInt s = "".codePoints().spliterator();
- assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
- assertTrue(s.hasCharacteristics(Spliterator.ORDERED));
- }
-
- @Test(expectedExceptions = NoSuchElementException.class)
- public void testEmptyCodePoints() {
- PrimitiveIterator.OfInt s = "".codePoints().iterator();
- assertFalse(s.hasNext());
- int cp = s.nextInt();
- }
-
- public void testSimpleCodePoints() {
- List<Integer> list = "abc".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'a', (int)'b', (int)'c'));
- }
-
- public void testUndefCodePoints() {
- List<Integer> list = "X\ufffeY".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'X', 0xFFFE, (int)'Y'));
- }
-
- public void testSurrogatePairing() {
- // U+1D11E = MUSICAL SYMBOL G CLEF
- // equivalent to surrogate pair U+D834 U+DD1E
- List<Integer> list;
- final int GCLEF = 0x1d11e;
-
- list = "\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(GCLEF));
- list = "A\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'A', GCLEF));
- list = "\ud834\udd1eB".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(GCLEF, (int)'B'));
- list = "X\ud834\udd1eY".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'X', GCLEF, (int)'Y'));
- }
-
- public void testUndefUnpaired() {
- List<Integer> list = "W\udd1eX\ud834Y\ufffeZ".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(
- (int)'W', 0xdd1e, (int)'X', 0xd834, (int)'Y', 0xfffe, (int)'Z'));
- }
-}
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Mon Jan 26 17:00:39 2015 -0800
@@ -2042,7 +2042,7 @@
final Object deferred;
Class<?> c = s.getClass();
if (c.getName().equals(
- "java.lang.UNIXProcess$DeferredCloseInputStream"))
+ "java.lang.ProcessImpl$DeferredCloseInputStream"))
{
deferred = s;
} else {
--- a/jdk/test/java/net/Socket/GetLocalAddress.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/java/net/Socket/GetLocalAddress.java Mon Jan 26 17:00:39 2015 -0800
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4106601 8026245
+ * @bug 4106601 8026245 8071424
* @run main/othervm GetLocalAddress
* @run main/othervm -Djava.net.preferIPv4Stack=true GetLocalAddress
* @run main/othervm -Djava.net.preferIPv6Addresses=true GetLocalAddress
@@ -39,6 +39,8 @@
static int port;
public static void main(String args[]) throws Exception {
+ testBindNull();
+
boolean error = true;
int linger = 65546;
int value = 0;
@@ -66,4 +68,18 @@
}
}
+ static void testBindNull() throws Exception {
+ try (Socket soc = new Socket()) {
+ soc.bind(null);
+ if (!soc.isBound())
+ throw new RuntimeException(
+ "should be bound after bind(null)");
+ if (soc.getLocalPort() <= 0)
+ throw new RuntimeException(
+ "bind(null) failed, local port: " + soc.getLocalPort());
+ if (soc.getLocalAddress() == null)
+ throw new RuntimeException(
+ "bind(null) failed, local address is null");
+ }
+ }
}
--- a/jdk/test/java/net/URI/Test.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/java/net/URI/Test.java Mon Jan 26 17:00:39 2015 -0800
@@ -24,7 +24,7 @@
/* @test
* @summary Unit test for java.net.URI
* @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800
- * 7171415
+ * 7171415 6933879
* @author Mark Reinhold
*/
@@ -1600,6 +1600,7 @@
static void bugs() {
b6339649();
+ b6933879();
b8037396();
}
@@ -1614,6 +1615,18 @@
}
}
+ // 6933879 - check that "." and "_" characters are allowed in IPv6 scope_id.
+ private static void b6933879() {
+ final String HOST = "fe80::c00:16fe:cebe:3214%eth1.12_55";
+ URI uri;
+ try {
+ uri = new URI("http", null, HOST, 10, "/", null, null);
+ } catch (URISyntaxException ex) {
+ throw new AssertionError("Should not happen", ex);
+ }
+ eq("[" + HOST + "]", uri.getHost());
+ }
+
private static void b8037396() {
// primary checks:
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8020156 8020009 8022326 8012913 8024405 8024408
+ * @bug 8020156 8020009 8022326 8012913 8024405 8024408 8071477
* @run testng SpliteratorCharacteristics
*/
@@ -59,6 +59,57 @@
@Test
public class SpliteratorCharacteristics {
+ public void testSpliteratorFromCharSequence() {
+ class CharSequenceImpl implements CharSequence {
+ final String s;
+
+ public CharSequenceImpl(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public int length() {
+ return s.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return s.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return s.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+ }
+
+ CharSequence cs = "A";
+ Spliterator.OfInt s = cs.chars().spliterator();
+ assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED |
+ Spliterator.SIZED | Spliterator.SUBSIZED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ s = cs.codePoints().spliterator();
+ assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+
+ for (CharSequence c : Arrays.asList(new CharSequenceImpl("A"),
+ new StringBuilder("A"),
+ new StringBuffer("A"))) {
+ s = cs.chars().spliterator();
+ assertCharacteristics(s, Spliterator.ORDERED |
+ Spliterator.SIZED | Spliterator.SUBSIZED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ s = cs.codePoints().spliterator();
+ assertCharacteristics(s, Spliterator.ORDERED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ }
+ }
+
public void testSpliteratorFromCollection() {
List<Integer> l = Arrays.asList(1, 2, 3, 4);
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
* @test
* @summary Spliterator traversing and splitting tests
* @run testng SpliteratorTraversingAndSplittingTest
- * @bug 8020016
+ * @bug 8020016 8071477
*/
import org.testng.annotations.DataProvider;
@@ -85,7 +85,38 @@
@Test
public class SpliteratorTraversingAndSplittingTest {
- private static List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+ private static final List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+
+ private static final String LOW = new String(new char[] {Character.MIN_LOW_SURROGATE});
+ private static final String HIGH = new String(new char[] {Character.MIN_HIGH_SURROGATE});
+ private static final String HIGH_LOW = HIGH + LOW;
+ private static final String CHAR_HIGH_LOW = "A" + HIGH_LOW;
+ private static final String HIGH_LOW_CHAR = HIGH_LOW + "A";
+ private static final String CHAR_HIGH_LOW_CHAR = "A" + HIGH_LOW + "A";
+
+ private static final List<String> STRINGS = generateTestStrings();
+
+ private static List<String> generateTestStrings() {
+ List<String> strings = new ArrayList<>();
+ for (int n : Arrays.asList(1, 2, 3, 16, 17)) {
+ strings.add(generate("A", n));
+ strings.add(generate(LOW, n));
+ strings.add(generate(HIGH, n));
+ strings.add(generate(HIGH_LOW, n));
+ strings.add(generate(CHAR_HIGH_LOW, n));
+ strings.add(generate(HIGH_LOW_CHAR, n));
+ strings.add(generate(CHAR_HIGH_LOW_CHAR, n));
+ }
+ return strings;
+ }
+
+ private static String generate(String s, int n) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < n; i++) {
+ sb.append(s);
+ }
+ return sb.toString();
+ }
private static class SpliteratorDataBuilder<T> {
List<Object[]> data;
@@ -564,6 +595,60 @@
}
}
+ private static class SpliteratorOfIntCharDataBuilder {
+ List<Object[]> data;
+
+ String s;
+
+ List<Integer> expChars;
+
+ List<Integer> expCodePoints;
+
+ SpliteratorOfIntCharDataBuilder(List<Object[]> data, String s) {
+ this.data = data;
+ this.s = s;
+ this.expChars = transform(s, false);
+ this.expCodePoints = transform(s, true);
+ }
+
+ static List<Integer> transform(String s, boolean toCodePoints) {
+ List<Integer> l = new ArrayList<>();
+
+ if (!toCodePoints) {
+ for (int i = 0; i < s.length(); i++) {
+ l.add((int) s.charAt(i));
+ }
+ }
+ else {
+ for (int i = 0; i < s.length();) {
+ char c1 = s.charAt(i++);
+ int cp = c1;
+ if (Character.isHighSurrogate(c1) && i < s.length()) {
+ char c2 = s.charAt(i);
+ if (Character.isLowSurrogate(c2)) {
+ i++;
+ cp = Character.toCodePoint(c1, c2);
+ }
+ }
+ l.add(cp);
+ }
+ }
+ return l;
+ }
+
+ void add(String description, Function<String, CharSequence> f) {
+ description = description.replace("%s", s);
+ {
+ Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).chars().spliterator();
+ data.add(new Object[]{description + ".chars().spliterator()", expChars, supplier});
+ }
+ {
+ Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).codePoints().spliterator();
+ data.add(new Object[]{description + ".codePoints().spliterator()", expCodePoints, supplier});
+ }
+ }
+ }
+
static Object[][] spliteratorOfIntDataProvider;
@DataProvider(name = "Spliterator.OfInt")
@@ -615,6 +700,43 @@
() -> new IntSpliteratorFromArray(exp));
}
+ // Class for testing default methods
+ class CharSequenceImpl implements CharSequence {
+ final String s;
+
+ public CharSequenceImpl(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public int length() {
+ return s.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return s.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return s.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+ }
+
+ for (String string : STRINGS) {
+ SpliteratorOfIntCharDataBuilder cdb = new SpliteratorOfIntCharDataBuilder(data, string);
+ cdb.add("\"%s\"", s -> s);
+ cdb.add("new CharSequenceImpl(\"%s\")", CharSequenceImpl::new);
+ cdb.add("new StringBuilder(\"%s\")", StringBuilder::new);
+ cdb.add("new StringBuffer(\"%s\")", StringBuffer::new);
+ }
+
return spliteratorOfIntDataProvider = data.toArray(new Object[0][]);
}
--- a/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,10 @@
/*
* @test
- * @bug 8049432
+ * @bug 8049432 8069038
* @summary New tests for TLS property jdk.tls.client.protocols
+ * @summary javax/net/ssl/TLS/TLSClientPropertyTest.java needs to be
+ * updated for JDK-8061210
* @run main/othervm TLSClientPropertyTest NoProperty
* @run main/othervm TLSClientPropertyTest SSLv3
* @run main/othervm TLSClientPropertyTest TLSv1
@@ -46,7 +48,7 @@
* protocols in the SSLContext.
*/
public class TLSClientPropertyTest {
- private final String[] expecteSupportedProtos = new String[] {
+ private final String[] expectedSupportedProtos = new String[] {
"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
};
@@ -67,31 +69,30 @@
}
contextProtocol = null;
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
+ "TLSv1", "TLSv1.1", "TLSv1.2"
};
break;
case "SSLv3":
contextProtocol = "SSLv3";
expectedDefaultProtos = new String[] {
- "SSLv3"
};
break;
case "TLSv1":
contextProtocol = "TLSv1";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1"
+ "TLSv1"
};
break;
case "TLSv11":
contextProtocol = "TLSv1.1";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1"
+ "TLSv1", "TLSv1.1"
};
break;
case "TLSv12":
contextProtocol = "TLSv1.2";
expectedDefaultProtos = new String[] {
- "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"
+ "TLSv1", "TLSv1.1", "TLSv1.2"
};
break;
case "WrongProperty":
@@ -182,12 +183,12 @@
expectedProto = "Default";
}
if (!context.getProtocol().equals(expectedProto)) {
- error("Invalid current protocol:" + context.getProtocol()
+ error("Invalid current protocol: " + context.getProtocol()
+ ", Expected:" + expectedProto, null);
}
List<String> actualDefaultProtos = Arrays.asList(context
.getDefaultSSLParameters().getProtocols());
- for (String p: expectedDefaultProtos) {
+ for (String p : expectedDefaultProtos) {
if (!actualDefaultProtos.contains(p)) {
error("Default protocol " + p + "missing", null);
}
@@ -195,7 +196,7 @@
List<String> actualSupportedProtos = Arrays.asList(context
.getSupportedSSLParameters().getProtocols());
- for (String p: expecteSupportedProtos) {
+ for (String p : expectedSupportedProtos) {
if (!actualSupportedProtos.contains(p)) {
error("Expected to support protocol:" + p, null);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/jaxp/transform/8062923/XslSubstringTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8062923 8062924
+ * @run testng XslSubstringTest
+ * @summary Test xsl substring function with negative, Inf and
+ * NaN length and few other use cases
+ */
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+public class XslSubstringTest {
+
+ final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test></test>";
+ final String xslPre = "<xsl:stylesheet version='1.0'"
+ + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"
+ + "<xsl:output method='xml' indent='yes' omit-xml-declaration='yes'/>"
+ + "<xsl:template match='/'><t>";
+ final String xslPost = "</t></xsl:template></xsl:stylesheet>";
+
+ private String testTransform(String xsl) throws Exception {
+ //Prepare sources for transormation
+ Source src = new StreamSource(new StringReader(xml));
+ Source xslsrc = new StreamSource(new StringReader(xslPre + xsl + xslPost));
+ //Create factory, template and transformer
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Templates tmpl = tf.newTemplates(xslsrc);
+ Transformer t = tmpl.newTransformer();
+ //Prepare output stream
+ StringWriter xmlResultString = new StringWriter();
+ StreamResult xmlResultStream = new StreamResult(xmlResultString);
+ //Transform
+ t.transform(src, xmlResultStream);
+ return xmlResultString.toString().trim();
+ }
+
+ @Test
+ public void test8062923() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1)\"/>|"),
+ "<t>||</t>");
+ }
+
+ @Test
+ public void test8062924() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1 div 0)\"/>|"),
+ "<t>||</t>");
+ }
+
+ @Test
+ public void testGeneral1() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1)\"/>|"),
+ "<t>|s|</t>");
+ }
+
+ @Test
+ public void testGeneral2() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1 div 0)\"/>|"),
+ "<t>|sdf|</t>");
+ }
+
+ @Test
+ public void testGeneral3() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, -0 div 0)\"/>|"),
+ "<t>||</t>");
+ }
+
+ @Test
+ public void testGeneral4() throws Exception {
+ assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 0 div 0)\"/>|"),
+ "<t>||</t>");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/GenerateEnumSchema.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8046817
+ * @summary schemagen fails to generate xsd for enum types
+ * @run main/othervm GenerateEnumSchema
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Paths;
+import java.util.Scanner;
+
+public class GenerateEnumSchema {
+
+ private static final String SCHEMA_OUTPUT_FILENAME = "schema1.xsd";
+ private static final File schemaOutputFile = new File(SCHEMA_OUTPUT_FILENAME);
+
+ public static void main(String[] args) throws Exception, IOException {
+ //Check schema generation for class type
+ runSchemaGen("TestClassType.java");
+ checkIfSchemaGenerated();
+ checkSchemaContent("<xs:complexType name=\"testClassType\">");
+ checkSchemaContent("<xs:element name=\"a\" type=\"xs:int\"/>");
+ schemaOutputFile.delete();
+ //Check schema generation for enum type
+ runSchemaGen("TestEnumType.java");
+ checkIfSchemaGenerated();
+ checkSchemaContent("<xs:simpleType name=\"testEnumType\">");
+ checkSchemaContent("<xs:enumeration value=\"ONE\"/>");
+ checkSchemaContent("<xs:enumeration value=\"TWO\"/>");
+ checkSchemaContent("<xs:enumeration value=\"THREE\"/>");
+ schemaOutputFile.delete();
+ }
+
+ private static void checkIfSchemaGenerated() {
+ if (!schemaOutputFile.exists()) {
+ throw new RuntimeException("FAIL:" + SCHEMA_OUTPUT_FILENAME + " was not generated by schemagen tool");
+ }
+ }
+
+ private static void checkSchemaContent(String exp_token) throws FileNotFoundException {
+ System.out.print("Check if generated schema contains '" + exp_token + "' string: ");
+ try (Scanner scanner = new Scanner(schemaOutputFile)) {
+ if (scanner.findWithinHorizon(exp_token, 0) != null) {
+ System.out.println("OK");
+ return;
+ }
+ }
+ System.out.println("FAIL");
+ throw new RuntimeException("The '" + exp_token + "' is not found in generated schema");
+
+ }
+
+ private static String getClassFilePath(String filename) {
+ String testSrc = System.getProperty("test.src");
+ if (testSrc == null) {
+ testSrc = ".";
+ }
+ return Paths.get(testSrc).resolve(filename).toString();
+ }
+
+ private static String getSchemagen() {
+ String javaHome = System.getProperty("java.home");
+ if (javaHome.endsWith("jre")) {
+ javaHome = new File(javaHome).getParent();
+ }
+ String schemagen = javaHome + File.separator + "bin" + File.separator + "schemagen";
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ schemagen = schemagen.concat(".exe");
+ }
+ return schemagen;
+ }
+
+ private static void logOutput(Process p) throws IOException {
+ BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String s = r.readLine();
+ while (s != null) {
+ System.out.println(s.trim());
+ s = r.readLine();
+ }
+ }
+
+ private static void runSchemaGen(String classFile) {
+ String schemagen = getSchemagen();
+
+ try {
+ System.out.println("Call to schemagen: " + schemagen + " " + classFile);
+ String[] schemagen_args = {
+ schemagen,
+ getClassFilePath(classFile)
+ };
+
+ ProcessBuilder pb = new ProcessBuilder(schemagen_args);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ logOutput(p);
+ int result = p.waitFor();
+ p.destroy();
+
+ if (result != 0) {
+ throw new RuntimeException("schemagen failed");
+ }
+ } catch (IOException | InterruptedException e) {
+ System.err.println("Can't run schemagen tool. Exception:");
+ e.printStackTrace(System.err);
+ throw new RuntimeException("Error launching schemagen tool");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/TestClassType.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class TestClassType {
+ public int a;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8046817/TestEnumType.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.xml.bind.annotation.XmlEnum;
+
+@XmlEnum(String.class)
+public enum TestEnumType {
+ ONE, TWO, THREE
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.testlibrary;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+/**
+ * Common library for various test jar file utility functions.
+ */
+public final class JarUtils {
+
+ /**
+ * Create jar file with specified files.
+ */
+ public static void createJar(String dest, String... files)
+ throws IOException {
+ try (JarOutputStream jos = new JarOutputStream(
+ new FileOutputStream(dest), new Manifest())) {
+ for (String file : files) {
+ System.out.println(String.format("Adding %s to %s",
+ file, dest));
+
+ // add an archive entry, and write a file
+ jos.putNextEntry(new JarEntry(file));
+ try (FileInputStream fis = new FileInputStream(file)) {
+ fis.transferTo(jos);
+ }
+ }
+ }
+ System.out.println();
+ }
+
+ /**
+ * Add specified files to existing jar file.
+ */
+ public static void updateJar(String src, String dest, String... files)
+ throws IOException {
+ try (JarOutputStream jos = new JarOutputStream(
+ new FileOutputStream(dest))) {
+
+ // copy each old entry into destination unless the entry name
+ // is in the updated list
+ List<String> updatedFiles = new ArrayList<>();
+ try (JarFile srcJarFile = new JarFile(src)) {
+ Enumeration entries = srcJarFile.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = (JarEntry) entries.nextElement();
+ String name = entry.getName();
+ boolean found = false;
+ for (String file : files) {
+ if (name.equals(file)) {
+ updatedFiles.add(file);
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ System.out.println(String.format("Updating %s with %s",
+ dest, name));
+ jos.putNextEntry(new JarEntry(name));
+ try (FileInputStream fis = new FileInputStream(name)) {
+ fis.transferTo(jos);
+ }
+ } else {
+ System.out.println(String.format("Copying %s to %s",
+ name, dest));
+ jos.putNextEntry(entry);
+ srcJarFile.getInputStream(entry).transferTo(jos);
+ }
+ }
+ }
+
+ // append new files
+ for (String file : files) {
+ if (!updatedFiles.contains(file)) {
+ System.out.println(String.format("Adding %s with %s",
+ dest, file));
+ jos.putNextEntry(new JarEntry(file));
+ try (FileInputStream fis = new FileInputStream(file)) {
+ fis.transferTo(jos);
+ }
+ }
+ }
+ }
+ System.out.println();
+ }
+
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.Map;
@@ -378,4 +379,40 @@
}
return cmd.toString().trim();
}
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout, and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param cmds The command line to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(String... cmds)
+ throws Throwable {
+ String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param pb The ProcessBuilder to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(ProcessBuilder pb)
+ throws Throwable {
+ String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
}
--- a/jdk/test/sun/security/krb5/config/ParseConfig.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/sun/security/krb5/config/ParseConfig.java Mon Jan 26 17:00:39 2015 -0800
@@ -22,7 +22,7 @@
*/
/*
* @test
- * @bug 6319046
+ * @bug 6319046 8055045
* @compile -XDignore.symbol.file ParseConfig.java
* @run main/othervm ParseConfig
* @summary Problem with parsing krb5.conf
@@ -32,7 +32,8 @@
public class ParseConfig {
public static void main(String[] args) throws Exception {
- System.setProperty("java.security.krb5.conf", System.getProperty("test.src", ".") +"/krb5.conf");
+ System.setProperty("java.security.krb5.conf",
+ System.getProperty("test.src", ".") + "/krb5.conf");
Config config = Config.getInstance();
config.listTable();
@@ -44,5 +45,11 @@
expected + "\"");
}
}
+
+ // JDK-8055045: IOOBE when reading an empty value
+ config.get("empty1", "NOVAL.COM");
+ config.get("empty2", "NOVAL.COM");
+ config.get("quote1", "NOVAL.COM");
+ config.get("quote2", "NOVAL.COM");
}
}
--- a/jdk/test/sun/security/krb5/config/krb5.conf Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/sun/security/krb5/config/krb5.conf Mon Jan 26 17:00:39 2015 -0800
@@ -27,3 +27,9 @@
}
}
+ NOVAL.COM = {
+ empty1 =
+ empty2 =.
+ quote1 = "
+ quote2 = '
+ }
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Thu Jan 22 22:42:33 2015 -0800
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,12 @@
static final String defaultPolicyId = "2.3.4.5";
- static class Handler implements HttpHandler {
+ static class Handler implements HttpHandler, AutoCloseable {
+
+ private final HttpServer httpServer;
+ private final String keystore;
+
+ @Override
public void handle(HttpExchange t) throws IOException {
int len = 0;
for (String h: t.getRequestHeaders().keySet()) {
@@ -136,7 +141,9 @@
// Write TSResponse
System.err.println("\nResponse\n===================");
KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(new FileInputStream(TSKS), "changeit".toCharArray());
+ try (FileInputStream fis = new FileInputStream(keystore)) {
+ ks.load(fis, "changeit".toCharArray());
+ }
String alias = "ts";
if (path == 6) alias = "tsbad1";
@@ -240,33 +247,74 @@
return out.toByteArray();
}
+
+ private Handler(HttpServer httpServer, String keystore) {
+ this.httpServer = httpServer;
+ this.keystore = keystore;
+ }
+
+ /**
+ * Initialize TSA instance.
+ *
+ * Extended Key Info extension of certificate that is used for
+ * signing TSA responses should contain timeStamping value.
+ */
+ static Handler init(int port, String keystore) throws IOException {
+ HttpServer httpServer = HttpServer.create(
+ new InetSocketAddress(port), 0);
+ Handler tsa = new Handler(httpServer, keystore);
+ httpServer.createContext("/", tsa);
+ return tsa;
+ }
+
+ /**
+ * Start TSA service.
+ */
+ void start() {
+ httpServer.start();
+ }
+
+ /**
+ * Stop TSA service.
+ */
+ void stop() {
+ httpServer.stop(0);
+ }
+
+ /**
+ * Return server port number.
+ */
+ int getPort() {
+ return httpServer.getAddress().getPort();
+ }
+
+ @Override
+ public void close() throws Exception {
+ stop();
+ }
}
public static void main(String[] args) throws Exception {
-
- Handler h = new Handler();
- HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
- int port = server.getAddress().getPort();
- HttpContext ctx = server.createContext("/", h);
- server.start();
+ try (Handler tsa = Handler.init(0, TSKS);) {
+ tsa.start();
+ int port = tsa.getPort();
- String cmd = null;
- // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
- // nonce generation in timestamping request. Not avaibale on
- // Windows and defaults to thread seed generator, not too bad.
- if (System.getProperty("java.home").endsWith("jre")) {
- cmd = System.getProperty("java.home") + "/../bin/jarsigner";
- } else {
- cmd = System.getProperty("java.home") + "/bin/jarsigner";
- }
+ String cmd;
+ // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
+ // nonce generation in timestamping request. Not avaibale on
+ // Windows and defaults to thread seed generator, not too bad.
+ if (System.getProperty("java.home").endsWith("jre")) {
+ cmd = System.getProperty("java.home") + "/../bin/jarsigner";
+ } else {
+ cmd = System.getProperty("java.home") + "/bin/jarsigner";
+ }
- cmd += " " + System.getProperty("test.tool.vm.opts") +
- " -J-Djava.security.egd=file:/dev/./urandom" +
- " -debug -keystore " + TSKS + " -storepass changeit" +
- " -tsa http://localhost:" + port + "/%d" +
- " -signedjar new_%d.jar " + JAR + " old";
+ cmd += " " + System.getProperty("test.tool.vm.opts")
+ + " -J-Djava.security.egd=file:/dev/./urandom"
+ + " -debug -keystore " + TSKS + " -storepass changeit"
+ + " -tsa http://localhost:" + port + "/%d"
+ + " -signedjar new_%d.jar " + JAR + " old";
- try {
if (args.length == 0) { // Run this test
jarsigner(cmd, 0, true); // Success, normal call
jarsigner(cmd, 1, false); // These 4 should fail
@@ -287,8 +335,6 @@
System.err.println("Press Enter to quit server");
System.in.read();
}
- } finally {
- server.stop(0);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary The test signs and verifies a jar file with -tsacert option
+ * @library /lib/testlibrary
+ * @run main TsacertOptionTest
+ */
+public class TsacertOptionTest {
+
+ private static final String FS = System.getProperty("file.separator");
+ private static final String JAVA_HOME = System.getProperty("java.home");
+ private static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS
+ + "keytool";
+ private static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS
+ + "jarsigner";
+ private static final String UNSIGNED_JARFILE = "unsigned.jar";
+ private static final String SIGNED_JARFILE = "signed.jar";
+ private static final String FILENAME = TsacertOptionTest.class.getName()
+ + ".txt";
+ private static final String PASSWORD = "changeit";
+ private static final String KEYSTORE = "ks.jks";
+ private static final String SIGNING_KEY_ALIAS = "sign_alias";
+ private static final String TSA_KEY_ALIAS = "ts";
+ private static final String KEY_ALG = "RSA";
+ private static final int KEY_SIZE = 2048;
+ private static final int VALIDITY = 365;
+ private static final String WARNING = "Warning:";
+ private static final String JAR_SIGNED = "jar signed.";
+ private static final String JAR_VERIFIED = "jar verified.";
+
+ /**
+ * The test signs and verifies a jar file with -tsacert option,
+ * and checks that no warning was shown.
+ * A certificate that is addressed in -tsacert option contains URL to TSA
+ * in Subject Information Access extension.
+ */
+ public static void main(String[] args) throws Throwable {
+ TsacertOptionTest test = new TsacertOptionTest();
+ test.start();
+ }
+
+ void start() throws Throwable {
+ // create a jar file that contains one file
+ Utils.createFiles(FILENAME);
+ JarUtils.createJar(UNSIGNED_JARFILE, FILENAME);
+
+ // look for free network port for TSA service
+ int port = jdk.testlibrary.Utils.getFreePort();
+ String host = jdk.testlibrary.Utils.getHostname();
+ String tsaUrl = "http://" + host + ":" + port;
+
+ // create key pair for jar signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", SIGNING_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // create key pair for TSA service
+ // SubjectInfoAccess extension contains URL to TSA service
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-v",
+ "-alias", TSA_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=TSA",
+ "-ext", "ExtendedkeyUsage:critical=timeStamping",
+ "-ext", "SubjectInfoAccess=timeStamping:URI:" + tsaUrl,
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ try (TimestampCheck.Handler tsa = TimestampCheck.Handler.init(port,
+ KEYSTORE);) {
+
+ // start TSA
+ tsa.start();
+
+ // sign jar file
+ // specify -tsadigestalg option because
+ // TSA server uses SHA-1 digest algorithm
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ "-tsacert", TSA_KEY_ALIAS,
+ "-tsadigestalg", "SHA-1",
+ UNSIGNED_JARFILE,
+ SIGNING_KEY_ALIAS);
+
+ analyzer.shouldHaveExitValue(0);
+ analyzer.stdoutShouldNotContain(WARNING);
+ analyzer.shouldContain(JAR_SIGNED);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ SIGNED_JARFILE);
+
+ analyzer.shouldHaveExitValue(0);
+ analyzer.stdoutShouldNotContain(WARNING);
+ analyzer.shouldContain(JAR_VERIFIED);
+ }
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/Utils.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Helper class.
+ */
+public class Utils {
+
+ static void createFiles(String... filenames) throws IOException {
+ for (String filename : filenames) {
+ new File(filename).createNewFile();
+ }
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for aliasNotInStore warning
+ * @library /lib/testlibrary ../
+ * @run main AliasNotInStoreTest
+ */
+public class AliasNotInStoreTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains signed entries
+ * that are not signed by any alias in keystore (aliasNotInStore).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ AliasNotInStoreTest test = new AliasNotInStoreTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ Utils.createFiles(FIRST_FILE, SECOND_FILE);
+ System.out.println(String.format("Create a %s that contains %s",
+ new Object[]{UNSIGNED_JARFILE, FIRST_FILE}));
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create first key pair for signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", FIRST_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", BOTH_KEYS_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=First",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // create second key pair for signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", SECOND_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", BOTH_KEYS_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Second",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar with first key
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", BOTH_KEYS_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ FIRST_KEY_ALIAS);
+
+ checkSigning(analyzer);
+
+ System.out.println(String.format("Copy %s to %s, and add %s",
+ new Object[] {SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
+ SECOND_FILE}));
+
+ JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+ // sign jar with second key
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", BOTH_KEYS_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE,
+ SECOND_KEY_ALIAS);
+
+ checkSigning(analyzer);
+
+ // create keystore that contains only first key
+ ProcessTools.executeCommand(KEYTOOL,
+ "-importkeystore",
+ "-srckeystore", BOTH_KEYS_KEYSTORE,
+ "-srcalias", FIRST_KEY_ALIAS,
+ "-srcstorepass", PASSWORD,
+ "-srckeypass", PASSWORD,
+ "-destkeystore", FIRST_KEY_KEYSTORE,
+ "-destalias", FIRST_KEY_ALIAS,
+ "-deststorepass", PASSWORD,
+ "-destkeypass", PASSWORD).shouldHaveExitValue(0);
+
+ // verify jar with keystore that contains only first key in strict mode,
+ // so there is signed entry (FirstClass.class) that is not signed
+ // by any alias in the keystore
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", FIRST_KEY_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
+ ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
+
+ // verify jar with keystore that contains only first key in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", FIRST_KEY_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE);
+
+ int expectedExitCode = ALIAS_NOT_IN_STORE_EXIT_CODE
+ + CHAIN_NOT_VALIDATED_EXIT_CODE;
+ checkVerifying(analyzer, expectedExitCode,
+ CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
+ ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badExtendedKeyUsage warning
+ * @library /lib/testlibrary ../
+ * @run main BadExtendedKeyUsageTest
+ */
+public class BadExtendedKeyUsageTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate's ExtendedKeyUsage extension
+ * doesn't allow code signing (badExtendedKeyUsage).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ BadExtendedKeyUsageTest test = new BadExtendedKeyUsageTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create a certificate whose signer certificate's
+ // ExtendedKeyUsage extension doesn't allow code signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-ext", "ExtendedkeyUsage=serverAuth",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
+
+ // verity signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, BAD_EXTENDED_KEY_USAGE_EXIT_CODE,
+ BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badKeyUsage warning
+ * @library /lib/testlibrary ../
+ * @ignore until 8026393 is fixed
+ * @run main BadKeyUsageTest
+ */
+public class BadKeyUsageTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate's KeyUsage extension
+ * doesn't allow code signing (badKeyUsage).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ BadKeyUsageTest test = new BadKeyUsageTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create a certificate whose signer certificate's KeyUsage extension
+ // doesn't allow code signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-ext", "KeyUsage=keyAgreement",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, BAD_KEY_USAGE_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, BAD_KEY_USAGE_VERIFYING_WARNING);
+
+ // verify signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, BAD_KEY_USAGE_EXIT_CODE,
+ BAD_KEY_USAGE_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Base64;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for badNetscapeCertType warning
+ * @library /lib/testlibrary ../
+ * @run main BadNetscapeCertTypeTest
+ */
+public class BadNetscapeCertTypeTest extends Test {
+
+ private static final String NETSCAPE_KEYSTORE_BASE64 = TEST_SOURCES + FS
+ + "bad_netscape_cert_type.jks.base64";
+
+ private static final String NETSCAPE_KEYSTORE
+ = "bad_netscape_cert_type.jks";
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate's NetscapeCertType extension
+ * doesn't allow code signing (badNetscapeCertType).
+ * Warning message is expected.
+ * Run bad_netscape_cert_type.sh script to create bad_netscape_cert_type.jks
+ */
+ public static void main(String[] args) throws Throwable {
+
+ Files.write(Paths.get(NETSCAPE_KEYSTORE),
+ Base64.getMimeDecoder().decode(
+ Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
+
+ BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-keystore", NETSCAPE_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", NETSCAPE_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
+
+ // verify signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", NETSCAPE_KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, BAD_NETSCAPE_CERT_TYPE_EXIT_CODE,
+ BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for chainNotValidated warning
+ * @library /lib/testlibrary ../
+ * @run main ChainNotValidatedTest
+ */
+public class ChainNotValidatedTest extends Test {
+
+ private static final String CHAIN = "chain";
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose cert chain can't be correctly validated (chainNotValidated).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ ChainNotValidatedTest test = new ChainNotValidatedTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create self-signed certificate whose BasicConstraints extension
+ // is set to false, so the certificate may not be used
+ // as a parent certificate (certpath validation should fail)
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkeypair",
+ "-alias", CA_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=CA",
+ "-ext", "BasicConstraints:critical=ca:false",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // create a certificate that is signed by self-signed certificate
+ // despite of it may not be used as a parent certificate
+ // (certpath validation should fail)
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkeypair",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-ext", "BasicConstraints:critical=ca:false",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ ProcessTools.executeCommand(KEYTOOL,
+ "-certreq",
+ "-alias", KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
+
+ ProcessTools.executeCommand(KEYTOOL,
+ "-gencert",
+ "-alias", CA_KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-infile", CERT_REQUEST_FILENAME,
+ "-validity", Integer.toString(VALIDITY),
+ "-outfile", CERT_FILENAME).shouldHaveExitValue(0);
+
+ ProcessTools.executeCommand(KEYTOOL,
+ "-importcert",
+ "-alias", KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-file", CERT_FILENAME).shouldHaveExitValue(0);
+
+ ProcessBuilder pb = new ProcessBuilder(KEYTOOL,
+ "-export",
+ "-rfc",
+ "-alias", KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD);
+ pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
+ ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+
+ pb = new ProcessBuilder(KEYTOOL,
+ "-export",
+ "-rfc",
+ "-alias", CA_KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD);
+ pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
+ ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
+
+ // remove CA certificate
+ ProcessTools.executeCommand(KEYTOOL,
+ "-delete",
+ "-alias", CA_KEY_ALIAS,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD).shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-certchain", CHAIN,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-certchain", CHAIN,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+
+ // verify signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-certchain", CHAIN,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
+ CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasExpiredCert warning
+ * @library /lib/testlibrary ../
+ * @run main HasExpiredCertTest
+ */
+public class HasExpiredCertTest extends Test {
+
+ static final int SHORT_VALIDITY = 365;
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate has expired (hasExpiredCert).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ HasExpiredCertTest test = new HasExpiredCertTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create key pair for jar signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-startdate", "-" + SHORT_VALIDITY * 2 + "d",
+ "-validity", Integer.toString(SHORT_VALIDITY))
+ .shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, HAS_EXPIRED_CERT_VERIFYING_WARNING);
+
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE);
+
+ checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
+ HAS_EXPIRED_CERT_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasExpiringCert warning
+ * @library /lib/testlibrary ../
+ * @run main HasExpiringCertTest
+ */
+public class HasExpiringCertTest extends Test {
+
+ static final int SHORT_VALIDITY = 90; // less than 6 month
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate will expire within six months (hasExpiringCert).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ HasExpiringCertTest test = new HasExpiringCertTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create key pair for jar signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-validity", Integer.toString(SHORT_VALIDITY))
+ .shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-verbose",
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, HAS_EXPIRING_CERT_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
+
+ // verify signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for hasUnsignedEntry warning
+ * @library /lib/testlibrary ../
+ * @run main HasUnsignedEntryTest
+ */
+public class HasUnsignedEntryTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains unsigned entries
+ * which have not been integrity-checked (hasUnsignedEntry).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ HasUnsignedEntryTest test = new HasUnsignedEntryTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ System.out.println(String.format("Create a %s that contains %s",
+ UNSIGNED_JARFILE, FIRST_FILE));
+ Utils.createFiles(FIRST_FILE, SECOND_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create key pair for signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer);
+
+ System.out.println(String.format("Copy %s to %s, and add %s.class, "
+ + "so it contains unsigned entry",
+ new Object[]{SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
+ SECOND_FILE}));
+
+ JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+ // verify jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE);
+
+ checkVerifying(analyzer, 0, HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
+
+ // verify jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE);
+
+ checkVerifying(analyzer, HAS_UNSIGNED_ENTRY_EXIT_CODE,
+ HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Checks if jarsigner prints appropriate warnings
+ * @library /lib/testlibrary ../
+ * @run main MultipleWarningsTest
+ */
+public class MultipleWarningsTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that:
+ * - contains entries whose signer certificate has expired
+ * - contains entries whose signer certificate's ExtendedKeyUsage
+ * extension doesn't allow code signing
+ * - contains unsigned entries which have not been integrity-checked
+ * - contains signed entries which are not signed by the specified alias
+ * Warning messages are expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ MultipleWarningsTest test = new MultipleWarningsTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ Utils.createFiles(FIRST_FILE, SECOND_FILE);
+
+ // create a jar file that contains one class file
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create first expired certificate
+ // whose ExtendedKeyUsage extension does not allow code signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", FIRST_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=First",
+ "-ext", "ExtendedkeyUsage=serverAuth",
+ "-startdate", "-" + VALIDITY * 2 + "d",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // create second expired certificate
+ // whose KeyUsage extension does not allow code signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", SECOND_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Second",
+ "-ext", "ExtendedkeyUsage=serverAuth",
+ "-startdate", "-" + VALIDITY * 2 + "d",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar with first key
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ FIRST_KEY_ALIAS);
+
+ checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING,
+ BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
+
+ // add a second class to created jar, so it contains unsigned entry
+ JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
+
+ // verify jar with second key
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE,
+ SECOND_KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+ HAS_EXPIRED_CERT_VERIFYING_WARNING,
+ HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with second key in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE,
+ SECOND_KEY_ALIAS);
+
+ int expectedExitCode = HAS_EXPIRED_CERT_EXIT_CODE
+ + BAD_EXTENDED_KEY_USAGE_EXIT_CODE
+ + HAS_UNSIGNED_ENTRY_EXIT_CODE
+ + NOT_SIGNED_BY_ALIAS_EXIT_CODE;
+ checkVerifying(analyzer, expectedExitCode,
+ BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+ HAS_EXPIRED_CERT_VERIFYING_WARNING,
+ HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with non-exisiting alias
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE,
+ "bogus");
+
+ checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+ HAS_EXPIRED_CERT_VERIFYING_WARNING,
+ HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with non-exisiting alias in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ UPDATED_SIGNED_JARFILE,
+ "bogus");
+
+ checkVerifying(analyzer, expectedExitCode,
+ BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
+ HAS_EXPIRED_CERT_VERIFYING_WARNING,
+ HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NoTimestampTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Date;
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Checks warnings if -tsa and -tsacert options are not specified
+ * @library /lib/testlibrary ../
+ * @run main NoTimestampTest
+ */
+public class NoTimestampTest extends Test {
+
+ /**
+ * The test signs and verifies a jar file without -tsa and -tsacert options,
+ * and checks that proper warnings are shown.
+ */
+ public static void main(String[] args) throws Throwable {
+ NoTimestampTest test = new NoTimestampTest();
+ test.start();
+ }
+
+ private void start() throws Throwable {
+ String timezone = System.getProperty("user.timezone");
+ System.out.println(String.format("Timezone = %s", timezone));
+
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // calculate certificate expiration date
+ Date expirationDate = new Date(System.currentTimeMillis() + VALIDITY
+ * 24 * 60 * 60 * 1000L);
+
+ // create key pair
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-validity", Integer.toString(VALIDITY));
+
+ // sign jar file
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-J-Duser.timezone=" + timezone,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ String warning = String.format(NO_TIMESTAMP_SIGNING_WARN_TEMPLATE,
+ expirationDate);
+ checkSigning(analyzer, warning);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-J-Duser.timezone=" + timezone,
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ warning = String.format(NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE, expirationDate);
+ checkVerifying(analyzer, 0, warning);
+
+ // verify signed jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-J-Duser.timezone=" + timezone,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, warning);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for notSignedByAlias warning
+ * @library /lib/testlibrary ../
+ * @run main NotSignedByAliasTest
+ */
+public class NotSignedByAliasTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains signed entries
+ * which are not signed by the specified alias(es) (notSignedByAlias).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ NotSignedByAliasTest test = new NotSignedByAliasTest();
+ test.start();
+ }
+
+ protected void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create first key pair for signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", FIRST_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=First",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // create first key pair for signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", SECOND_KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Second",
+ "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+
+ // sign jar with first key
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ FIRST_KEY_ALIAS);
+
+ checkSigning(analyzer);
+
+ // verify jar with second key
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ SECOND_KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with second key in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ SECOND_KEY_ALIAS);
+
+ checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with non-existing alias
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ "bogus");
+
+ checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ // verify jar with non-existing alias in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ "bogus");
+
+ checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
+ NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8024302 8026037
+ * @summary Test for notYetValidCert warning
+ * @library /lib/testlibrary ../
+ * @run main NotYetValidCertTest
+ */
+public class NotYetValidCertTest extends Test {
+
+ /**
+ * The test signs and verifies a jar that contains entries
+ * whose signer certificate is not yet valid (notYetValidCert).
+ * Warning message is expected.
+ */
+ public static void main(String[] args) throws Throwable {
+ NotYetValidCertTest test = new NotYetValidCertTest();
+ test.start();
+ }
+
+ protected void start() throws Throwable {
+ // create a jar file that contains one class file
+ Utils.createFiles(FIRST_FILE);
+ JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
+
+ // create certificate that will be valid only tomorrow
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", KEY_ALIAS,
+ "-keyalg", KEY_ALG,
+ "-keysize", Integer.toString(KEY_SIZE),
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-dname", "CN=Test",
+ "-startdate", "+1d",
+ "-validity", Integer.toString(VALIDITY));
+
+ // sign jar
+ OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ "-signedjar", SIGNED_JARFILE,
+ UNSIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkSigning(analyzer, NOT_YET_VALID_CERT_SIGNING_WARNING);
+
+ // verify signed jar
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkVerifying(analyzer, 0, NOT_YET_VALID_CERT_VERIFYING_WARNING);
+
+ // verify jar in strict mode
+ analyzer = ProcessTools.executeCommand(JARSIGNER,
+ "-verify",
+ "-verbose",
+ "-strict",
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ SIGNED_JARFILE,
+ KEY_ALIAS);
+
+ checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
+ NOT_YET_VALID_CERT_VERIFYING_WARNING);
+
+ System.out.println("Test passed");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/Test.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.testlibrary.OutputAnalyzer;
+
+/**
+ * Base class.
+ */
+public abstract class Test {
+
+ static final String TEST_SOURCES = System.getProperty("test.src", ".");
+ static final String TEST_CLASSES = System.getProperty("test.classes");
+ static final String FS = System.getProperty("file.separator");
+ static final String JAVA_HOME = System.getProperty("java.home");
+ static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
+ static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
+ static final String UNSIGNED_JARFILE = "unsigned.jar";
+ static final String SIGNED_JARFILE = "signed.jar";
+ static final String UPDATED_SIGNED_JARFILE = "updated_signed.jar";
+ static final String FIRST_FILE = "first.txt";
+ static final String SECOND_FILE = "second.txt";
+ static final String PASSWORD = "password";
+ static final String BOTH_KEYS_KEYSTORE = "both_keys.jks";
+ static final String FIRST_KEY_KEYSTORE = "first_key.jks";
+ static final String KEYSTORE = "keystore.jks";
+ static final String FIRST_KEY_ALIAS = "first";
+ static final String SECOND_KEY_ALIAS = "second";
+ static final String KEY_ALG = "RSA";
+ static final String KEY_ALIAS = "alias";
+ static final String CERT_REQUEST_FILENAME = "test.req";
+ static final String CERT_FILENAME = "test.crt";
+ static final String CA_KEY_ALIAS = "ca";
+ static final int KEY_SIZE = 2048;
+ static final int TIMEOUT = 6 * 60 * 1000; // in millis
+ static final int VALIDITY = 365;
+
+ static final String WARNING = "Warning:";
+
+ static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
+ = "This jar contains entries "
+ + "whose certificate chain is not validated.";
+
+ static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING
+ = "This jar contains signed entries "
+ + "that are not signed by alias in this keystore.";
+
+ static final String BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING
+ = "The signer certificate's ExtendedKeyUsage extension "
+ + "doesn't allow code signing.";
+
+ static final String BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING
+ = "This jar contains entries whose signer certificate's "
+ + "ExtendedKeyUsage extension doesn't allow code signing.";
+
+ static final String BAD_KEY_USAGE_SIGNING_WARNING
+ = "The signer certificate's KeyUsage extension "
+ + "doesn't allow code signing.";
+
+ static final String BAD_KEY_USAGE_VERIFYING_WARNING
+ = "This jar contains entries whose signer certificate's KeyUsage "
+ + "extension doesn't allow code signing.";
+
+ static final String BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING
+ = "The signer certificate's NetscapeCertType extension "
+ + "doesn't allow code signing.";
+
+ static final String BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING
+ = "This jar contains entries "
+ + "whose signer certificate's NetscapeCertType extension "
+ + "doesn't allow code signing.";
+
+ static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING
+ = "The signer's certificate chain is not validated.";
+
+ static final String HAS_EXPIRING_CERT_SIGNING_WARNING
+ = "The signer certificate will expire within six months.";
+
+ static final String HAS_EXPIRING_CERT_VERIFYING_WARNING
+ = "This jar contains entries "
+ + "whose signer certificate will expire within six months.";
+
+ static final String HAS_EXPIRED_CERT_SIGNING_WARNING
+ = "The signer certificate has expired.";
+
+ static final String HAS_EXPIRED_CERT_VERIFYING_WARNING
+ = "This jar contains entries whose signer certificate has expired.";
+
+ static final String HAS_UNSIGNED_ENTRY_VERIFYING_WARNING
+ = "This jar contains unsigned entries "
+ + "which have not been integrity-checked.";
+
+ static final String NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING
+ = "This jar contains signed entries "
+ + "which are not signed by the specified alias(es).";
+
+ static final String NO_TIMESTAMP_SIGNING_WARN_TEMPLATE
+ = "No -tsa or -tsacert is provided "
+ + "and this jar is not timestamped. "
+ + "Without a timestamp, users may not be able to validate this jar "
+ + "after the signer certificate's expiration date "
+ + "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
+
+ static final String NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE
+ = "This jar contains signatures that does not include a timestamp. "
+ + "Without a timestamp, users may not be able to validate this jar "
+ + "after the signer certificate's expiration date "
+ + "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
+
+ static final String NOT_YET_VALID_CERT_SIGNING_WARNING
+ = "The signer certificate is not yet valid.";
+
+ static final String NOT_YET_VALID_CERT_VERIFYING_WARNING
+ = "This jar contains entries "
+ + "whose signer certificate is not yet valid.";
+
+ static final String JAR_SIGNED = "jar signed.";
+
+ static final String JAR_VERIFIED = "jar verified.";
+
+ static final String JAR_VERIFIED_WITH_SIGNER_ERRORS
+ = "jar verified, with signer errors.";
+
+ static final int CHAIN_NOT_VALIDATED_EXIT_CODE = 4;
+ static final int HAS_EXPIRED_CERT_EXIT_CODE = 4;
+ static final int BAD_KEY_USAGE_EXIT_CODE = 8;
+ static final int BAD_EXTENDED_KEY_USAGE_EXIT_CODE = 8;
+ static final int BAD_NETSCAPE_CERT_TYPE_EXIT_CODE = 8;
+ static final int HAS_UNSIGNED_ENTRY_EXIT_CODE = 16;
+ static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
+ static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
+
+ protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
+ String... warnings) {
+ analyzer.shouldHaveExitValue(expectedExitCode);
+ for (String warning : warnings) {
+ analyzer.shouldContain(warning);
+ }
+ if (warnings.length > 0) {
+ analyzer.shouldContain(WARNING);
+ }
+ if (expectedExitCode == 0) {
+ analyzer.shouldContain(JAR_VERIFIED);
+ } else {
+ analyzer.shouldContain(JAR_VERIFIED_WITH_SIGNER_ERRORS);
+ }
+ }
+
+ protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
+ analyzer.shouldHaveExitValue(0);
+ for (String warning : warnings) {
+ analyzer.shouldContain(warning);
+ }
+ if (warnings.length > 0) {
+ analyzer.shouldContain(WARNING);
+ }
+ analyzer.shouldContain(JAR_SIGNED);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.jks.base64 Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,26 @@
+/u3+7QAAAAIAAAABAAAAAQAFYWxpYXMAAAFBpkwW0gAAAr0wggK5MA4GCisGAQQB
+KgIRAQEFAASCAqWkGJ3PPjYmWNKrV23Y1u413RMAkrRZ+1OLWYRcQt4jtxtIyEH5
+Ho5b9dy9XN9FBKlTOD4c2Pc1T43BLKXeuLu3uLLeIxgXFt0z9CLyGwdYZZ751kXr
+DQ99qY6aNQUO6SeE4Wdty0KPAqid6ZJ8bF7T6wsTZSvNhaBRzyFydEfG7bbUYjOl
+mWC44nlsu6VEU3o9RQpcm1gIMwradOaIVT/HoB2bKmAv8gHqI6kreiEZwTdZkSAI
+IRi2vt1RPllXt5hgjDxUfZe8XOYYweR4Vt2/jVuKLJ80DNTu/9SeUD88zQAz53k4
+r3nRhv6TRcPm6tV/Fh92XLHiskL+TAzTfm+bUAudPCCVxN+yRtxvAgA+UhdV/SuM
+Zn5F6nrmP+YJG1hmprgCJIJJaCEXa9RXYC+vIVpO0WVNRuGlGm+/1afnOuQC8Wss
+ShXwjkaqTwAhqBFq7eYmmP8BK3gflYrt2zDLXvhl4ndVvMhMthFJ3ZvLh2LWpqLI
+/n8EMCf8US3lIEFk9DTHBZjffiHkqK2e7+FXEpG3xrgE6ZYLMdbd5Pb3YjZfhQx+
+ZTtiEFzYSaEGhacek/m7dRq1qmwgFsytng2OdWZe2ln8LJY0odr1dGUfJHfgafvi
+tlfbkg/rgjONtwliChDggbkUwnerrj/D/zrdEufUvfyltSshhHXRNDD3fH6spmEk
+hHKgxEc4yvxqJxzdMGtuib355aSfNegyl+GsnsKzXQCVEK2h3BLTQObzaD+8NZ12
+LQHvbrCiaS34vxJ3rEC+a+SW7itZp0aCdXMWdMJNkRKqyLBD3vG3zN05sN3XrhEM
+8BRT020TWY00tbVFbbBFheYLQRgTjrQtr0Yt6UHWBZc4N20crDLcSH5gqcCOVpla
+1Y2uqFEn8yqrGRwn/kgfNgAAAAEABVguNTA5AAABtTCCAbEwggEaoAMCAQICCQDH
+cEuVvzCuqzANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARUZXN0MB4XDTEzMTAx
+MTA2NTUwNloXDTIzMTAwOTA2NTUwNlowDzENMAsGA1UEAwwEVGVzdDCBnzANBgkq
+hkiG9w0BAQEFAAOBjQAwgYkCgYEA8hOfp2Dcnvt//ZZQAja9TRiwKqXVS+TiYE3S
+gngCBjIi+YYdo0DsUeO5MBfE6uvCWOr5lwAR/u1iaJOhIoGJDiGoPasZlt+yIgtR
+LzA7j2q+1q6kcwiVxfikI3aUgHV/QsybTriT4Bf7TQNKtJG23MQa4sD7+PjtCWD7
+p3cHTfkCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBBQUA
+A4GBAKoDlTJ8wLRA7G8XdGm4gv733n1cSQzlkcsjfOO6/mA5Jvu8tyFNq9HTf9AT
+VXbrbGcUYJjhzSSY3w5apXK1kXyqTB1LUNEJ45WnmciqSSecVTpJz9TuegyoX0Zf
+HScSgqfDmjqoiiFiNCgn3ZEJ85ykGvoFYGH+php+BVi3S0bj5E/jRpyV3vNnii/S
+wJDSAXF6bYU=
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.sh Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+#!/bin/sh
+
+# This script creates JKS keystore with a certificate
+# that contains Netscape Certificate Type extension
+# that does not allow code signing
+# The keystore is used by BadNetscapeCertTypeTest.java test
+
+rm -rf keystore.jks
+echo "nsCertType = client" > ext.cfg
+
+openssl req -new -out cert.req -keyout key.pem -days 3650 \
+ -passin pass:password -passout pass:password -subj "/CN=Test"
+openssl x509 -in cert.req -out cert.pem -req -signkey key.pem -days 3650 \
+ -passin pass:password -extfile ext.cfg
+openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 \
+ -passin pass:password -passout pass:password -name alias
+
+${JAVA_HOME}/bin/keytool -importkeystore \
+ -srckeystore keystore.p12 -srcstoretype pkcs12 \
+ -srcstorepass password -alias alias \
+ -destkeystore bad_netscape_cert_type.jks -deststoretype jks \
+ -deststorepass password -destalias alias \
+
+openssl base64 < bad_netscape_cert_type.jks > bad_netscape_cert_type.jks.base64
+rm -rf cert.req key.pem cert.pem keystore.p12 ext.cfg bad_netscape_cert_type.jks
--- a/langtools/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -289,3 +289,4 @@
de2ce70d907c9f227b802cea29285bece5194cd5 jdk9-b44
73bbdcf236b297a0c1b8875f2eeba65eaf7ade60 jdk9-b45
e272d9be5f90edb6bb6b40f7816ec85eec0f5dc2 jdk9-b46
+230c139552501e612dd0d4423ac30f94c1201c0d jdk9-b47
--- a/langtools/make/tools/propertiesparser/gen/ClassGenerator.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/make/tools/propertiesparser/gen/ClassGenerator.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,3 +1,26 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
package propertiesparser.gen;
import propertiesparser.parser.Message;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon Jan 26 17:00:39 2015 -0800
@@ -2783,7 +2783,8 @@
@SuppressWarnings("fallthrough")
void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) {
- Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType());
+ InferenceContext inferenceContext = checkContext.inferenceContext();
+ Type returnType = inferenceContext.asUndetVar(descriptor.getReturnType());
Type resType;
switch (tree.getMode()) {
@@ -2812,10 +2813,20 @@
if (incompatibleReturnType != null) {
checkContext.report(tree, diags.fragment("incompatible.ret.type.in.mref",
diags.fragment("inconvertible.types", resType, descriptor.getReturnType())));
+ } else {
+ if (inferenceContext.free(refType)) {
+ // we need to wait for inference to finish and then replace inference vars in the referent type
+ inferenceContext.addFreeTypeListener(List.of(refType),
+ instantiatedContext -> {
+ tree.referentType = instantiatedContext.asInstType(refType);
+ });
+ } else {
+ tree.referentType = refType;
+ }
}
if (!speculativeAttr) {
- List<Type> thrownTypes = checkContext.inferenceContext().asUndetVars(descriptor.getThrownTypes());
+ List<Type> thrownTypes = inferenceContext.asUndetVars(descriptor.getThrownTypes());
if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Mon Jan 26 17:00:39 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -898,7 +898,7 @@
Type argtype = owntype.getParameterTypes().last();
if (!types.isReifiable(argtype) &&
(!allowSimplifiedVarargs ||
- sym.attribute(syms.trustMeType.tsym) == null ||
+ sym.baseSymbol().attribute(syms.trustMeType.tsym) == null ||
!isTrustMeAllowedOnMethod(sym))) {
warnUnchecked(env.tree.pos(),
"unchecked.generic.array.creation",
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java Mon Jan 26 17:00:39 2015 -0800
@@ -385,7 +385,7 @@
typeEnvs.put(c, localEnv);
// Fill out class fields.
- c.completer = typeEnter;
+ c.completer = null; // do not allow the initial completer linger on.
c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
c.sourcefile = env.toplevel.sourcefile;
c.members_field = WriteableScope.create(c);
@@ -409,6 +409,9 @@
// Enter type parameters.
ct.typarams_field = classEnter(tree.typarams, localEnv);
+ // install further completer for this type.
+ c.completer = typeEnter;
+
// Add non-local class to uncompleted, to make sure it will be
// completed later.
if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Mon Jan 26 17:00:39 2015 -0800
@@ -889,7 +889,9 @@
convertArgs(tree.sym, args.toList(), tree.varargsElement)).
setType(tree.sym.erasure(types).getReturnType());
- apply = transTypes.coerce(apply, localContext.generatedRefSig().getReturnType());
+ apply = transTypes.coerce(attrEnv, apply,
+ types.erasure(localContext.tree.referentType.getReturnType()));
+
setVarargsIfNeeded(apply, tree.varargsElement);
return apply;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java Mon Jan 26 17:00:39 2015 -0800
@@ -227,7 +227,7 @@
annotate.annotateTypeLater(tree, localEnv, m, tree.pos());
if (tree.defaultValue != null)
- annotateDefaultValueLater(tree.defaultValue, localEnv, m);
+ annotateDefaultValueLater(tree.defaultValue, localEnv, m, tree.pos());
}
/** Create a fresh environment for method bodies.
@@ -438,7 +438,8 @@
/** Queue processing of an attribute default value. */
void annotateDefaultValueLater(final JCExpression defaultValue,
final Env<AttrContext> localEnv,
- final MethodSymbol m) {
+ final MethodSymbol m,
+ final DiagnosticPosition deferPos) {
annotate.normal(new Annotate.Worker() {
@Override
public String toString() {
@@ -449,9 +450,11 @@
@Override
public void run() {
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+ DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos);
try {
enterDefaultValue(defaultValue, localEnv, m);
} finally {
+ deferredLintHandler.setPos(prevLintPos);
log.useSource(prev);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Jan 26 17:00:39 2015 -0800
@@ -85,7 +85,7 @@
private Names names;
/** End position mappings container */
- private final AbstractEndPosTable endPosTable;
+ protected final AbstractEndPosTable endPosTable;
// Because of javac's limited lookahead, some contexts are ambiguous in
// the presence of type annotations even though they are not ambiguous
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Mon Jan 26 17:00:39 2015 -0800
@@ -2101,6 +2101,7 @@
public PolyKind refPolyKind;
public boolean ownerAccessible;
public OverloadKind overloadKind;
+ public Type referentType;
public enum OverloadKind {
OVERLOADED,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8052070/DuplicateTypeParameter.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,15 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8052070
+ * @summary javac crashes when there are duplicated type parameters
+ * @compile/fail/ref=DuplicateTypeParameter.out -XDrawDiagnostics DuplicateTypeParameter.java
+ */
+
+public class DuplicateTypeParameter<T, T, A> {
+ class Inner <P, P, Q> {}
+ public void foo() {
+ class Local <M, M, N> {};
+ }
+}
+
+class Secondary<D, D, E> {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8052070/DuplicateTypeParameter.out Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,5 @@
+DuplicateTypeParameter.java:8:40: compiler.err.already.defined: kindname.type.variable, T, kindname.class, DuplicateTypeParameter
+DuplicateTypeParameter.java:9:21: compiler.err.already.defined: kindname.type.variable, P, kindname.class, DuplicateTypeParameter.Inner
+DuplicateTypeParameter.java:15:20: compiler.err.already.defined: kindname.type.variable, D, kindname.class, Secondary
+DuplicateTypeParameter.java:11:25: compiler.err.already.defined: kindname.type.variable, M, kindname.class, Local
+4 errors
--- a/langtools/test/tools/javac/lambda/LambdaLambdaSerialized.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/test/tools/javac/lambda/LambdaLambdaSerialized.java Mon Jan 26 17:00:39 2015 -0800
@@ -67,13 +67,13 @@
out.writeObject(lamb);
}
- static void readAssert(ObjectInputStream in, String expected) throws IOException, ClassNotFoundException {
- LSI<LSI<Map>> ls = (LSI<LSI<Map>>) in.readObject();
+ static void readAssert(ObjectInputStream in, String expected) throws IOException, ClassNotFoundException {
+ LSI<LSI<Map>> ls = (LSI<LSI<Map>>)in.readObject();
Map result = ls.get().get();
System.out.printf("Result: %s\n", result);
}
+
+ interface LSI<T> extends Serializable {
+ T get();
+ }
}
-
-interface LSI<T> extends Serializable {
- T get();
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReferenceGenericTarget.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8046977 8065303
+ * @summary ClassCastException: typing information needed for method reference bridging not preserved
+ * @author Srikanth
+ * @run main MethodReferenceGenericTarget
+ */
+
+public class MethodReferenceGenericTarget {
+ static String result = "";
+
+ interface ISi { int m(Short a); }
+
+ public static void main(String[] args) {
+ (new MethodReferenceGenericTarget()).testUnboxObjectToNumberWiden();
+ if (!result.equals("7775"))
+ throw new AssertionError("Incorrect result");
+ MethodReferenceTestPrivateTypeConversion.main(null);
+ new InferenceHookTest().test();
+ }
+
+ void foo(ISi q) {
+ result += q.m((short)75);
+ }
+
+ public void testUnboxObjectToNumberWiden() {
+ ISi q = (new E<Short>())::xI;
+ result += q.m((short)77);
+ // Verify poly invocation context to confirm we handle
+ // deferred/speculative attribution paths adequately.
+ foo((new E<Short>())::xI);
+ }
+
+ class E<T> {
+ private T xI(T t) { return t; }
+ }
+}
+
+// snippet from https://bugs.openjdk.java.net/browse/JDK-8065303
+class MethodReferenceTestPrivateTypeConversion {
+
+ class MethodReferenceTestTypeConversion_E<T> {
+ private T xI(T t) { return t; }
+ }
+
+ interface ISi { int m(Short a); }
+
+ interface ICc { char m(Character a); }
+
+ public void testUnboxObjectToNumberWiden() {
+ ISi q = (new MethodReferenceTestTypeConversion_E<Short>())::xI;
+ if ((q.m((short)77) != (short)77))
+ throw new AssertionError("Incorrect result");
+ }
+
+ public void testUnboxObjectToChar() {
+ ICc q = (new MethodReferenceTestTypeConversion_E<Character>())::xI;
+ if (q.m('@') != '@')
+ throw new AssertionError("Incorrect result");
+ }
+
+ public static void main(String[] args) {
+ new MethodReferenceTestPrivateTypeConversion().testUnboxObjectToNumberWiden();
+ new MethodReferenceTestPrivateTypeConversion().testUnboxObjectToChar();
+ }
+}
+
+class InferenceHookTestBase {
+ <X> X m(Integer i) { return null; }
+}
+
+class InferenceHookTest extends InferenceHookTestBase {
+ interface SAM1<R> {
+ R m(Integer i);
+ }
+
+ <Z> Z g(SAM1<Z> o) { return null; }
+
+ void test() {
+ String s = g(super::m);
+ if (s != null)
+ throw new AssertionError("Incorrect result");
+ }
+}
--- a/langtools/test/tools/javac/lambda/SerializedLambdaInInit.java Thu Jan 22 22:42:33 2015 -0800
+++ b/langtools/test/tools/javac/lambda/SerializedLambdaInInit.java Mon Jan 26 17:00:39 2015 -0800
@@ -111,8 +111,8 @@
}
}
}
+
+ interface LSI extends Serializable {
+ String convert(String x);
+ }
}
-
-interface LSI extends Serializable {
- String convert(String x);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/parser/extend/JavacExtensionTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.util.Context;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import javax.lang.model.element.Element;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.ToolProvider;
+import javax.tools.StandardJavaFileManager;
+import com.sun.source.tree.ImportTree;
+import java.util.Collections;
+import java.io.PrintWriter;
+import com.sun.source.tree.VariableTree;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+
+/*
+ * @test
+ * @bug 8067384 8068488
+ * @summary Verify that JavacParser can be extended
+ */
+public class JavacExtensionTest {
+
+ public static void main(String[] args) throws Exception {
+ PrintWriter pw = new PrintWriter("trialSource.java", "UTF-8");
+ pw.println("int x = 9;");
+ pw.close();
+ List<? extends Tree> defs = parse("trialSource.java");
+ if (defs.size() != 1) {
+ throw new AssertionError("Expected only one def, got: " + defs.size());
+ }
+ Tree tree = defs.get(0);
+ if (tree instanceof VariableTree) {
+ System.out.println("Passes! --- " + tree);
+ } else {
+ throw new AssertionError("Expected VariableTree, got: " + tree);
+ }
+ }
+
+ static List<? extends Tree> parse(String srcfile) throws Exception {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+ Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(srcfile);
+ String classPath = System.getProperty("java.class.path");
+ List<String> options = Arrays.asList("-classpath", classPath);
+ DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
+ Context context = new Context();
+ JavacTaskImpl task = (JavacTaskImpl) ((JavacTool) compiler).getTask(null, null,
+ diagnostics, options, null, fileObjects, context);
+ TrialParserFactory.instance(context);
+ Iterable<? extends CompilationUnitTree> asts = task.parse();
+ Iterator<? extends CompilationUnitTree> it = asts.iterator();
+ if (it.hasNext()) {
+ CompilationUnitTree cut = it.next();
+ return cut.getTypeDecls();
+ } else {
+ throw new AssertionError("Expected compilation unit");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/parser/extend/TrialParser.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.Tokens.Comment;
+import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
+import com.sun.tools.javac.parser.Tokens.Token;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.CLASS;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.COLON;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.ENUM;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.EOF;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.Tag;
+import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Position;
+
+/**
+ *
+ * @author Robert Field
+ */
+class TrialParser extends JavacParser {
+
+ public TrialParser(ParserFactory fac,
+ com.sun.tools.javac.parser.Lexer S,
+ boolean keepDocComments,
+ boolean keepLineMap,
+ boolean keepEndPositions) {
+ super(fac, S, keepDocComments, keepLineMap, keepEndPositions);
+ }
+
+ @Override
+ public JCCompilationUnit parseCompilationUnit() {
+ Token firstToken = token;
+ JCModifiers mods = null;
+ boolean seenImport = false;
+ boolean seenPackage = false;
+ ListBuffer<JCTree> defs = new ListBuffer<>();
+ if (token.kind == MONKEYS_AT) {
+ mods = modifiersOpt();
+ }
+
+ if (token.kind == PACKAGE) {
+ int packagePos = token.pos;
+ List<JCAnnotation> annotations = List.nil();
+ seenPackage = true;
+ if (mods != null) {
+ checkNoMods(mods.flags);
+ annotations = mods.annotations;
+ mods = null;
+ }
+ nextToken();
+ JCExpression pid = qualident(false);
+ accept(SEMI);
+ JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
+ attach(pd, firstToken.comment(CommentStyle.JAVADOC));
+ storeEnd(pd, token.pos);
+ defs.append(pd);
+ }
+
+ boolean firstTypeDecl = true;
+ while (token.kind != EOF) {
+ if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
+ // error recovery
+ skip(true, false, false, false);
+ if (token.kind == EOF) {
+ break;
+ }
+ }
+ if (mods == null && token.kind == IMPORT) {
+ seenImport = true;
+ defs.append(importDeclaration());
+ break;
+ } else {
+ Comment docComment = token.comment(CommentStyle.JAVADOC);
+ if (firstTypeDecl && !seenImport && !seenPackage) {
+ docComment = firstToken.comment(CommentStyle.JAVADOC);
+ }
+ List<? extends JCTree> udefs = aUnit(mods, docComment);
+ for (JCTree def : udefs) {
+ defs.append(def);
+ }
+ mods = null;
+ firstTypeDecl = false;
+ break;
+ }
+ }
+ List<JCTree> rdefs = defs.toList();
+ class TrialUnit extends JCCompilationUnit {
+
+ public TrialUnit(List<JCTree> defs) {
+ super(defs);
+ }
+ }
+ JCCompilationUnit toplevel = new TrialUnit(rdefs);
+ if (rdefs.isEmpty()) {
+ storeEnd(toplevel, S.prevToken().endPos);
+ }
+ toplevel.lineMap = S.getLineMap();
+ this.endPosTable.setParser(null); // remove reference to parser
+ toplevel.endPositions = this.endPosTable;
+ return toplevel;
+ }
+
+ List<? extends JCTree> aUnit(JCModifiers pmods, Comment dc) {
+ switch (token.kind) {
+ case EOF:
+ return List.nil();
+ case RBRACE:
+ case CASE:
+ case DEFAULT:
+ // These are illegal, fall through to handle as illegal statement
+ case LBRACE:
+ case IF:
+ case FOR:
+ case WHILE:
+ case DO:
+ case TRY:
+ case SWITCH:
+ case SYNCHRONIZED:
+ case RETURN:
+ case THROW:
+ case BREAK:
+ case CONTINUE:
+ case SEMI:
+ case ELSE:
+ case FINALLY:
+ case CATCH:
+ case ASSERT:
+ return List.<JCTree>of(parseStatement());
+ default:
+ JCModifiers mods = modifiersOpt(pmods);
+ if (token.kind == CLASS
+ || token.kind == INTERFACE
+ || token.kind == ENUM) {
+ return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
+ } else {
+ int pos = token.pos;
+ List<JCTypeParameter> typarams = typeParametersOpt();
+ // if there are type parameters but no modifiers, save the start
+ // position of the method in the modifiers.
+ if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
+ mods.pos = pos;
+ storeEnd(mods, pos);
+ }
+ List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION);
+
+ if (annosAfterParams.nonEmpty()) {
+ checkAnnotationsAfterTypeParams(annosAfterParams.head.pos);
+ mods.annotations = mods.annotations.appendList(annosAfterParams);
+ if (mods.pos == Position.NOPOS) {
+ mods.pos = mods.annotations.head.pos;
+ }
+ }
+
+ Token prevToken = token;
+ pos = token.pos;
+ JCExpression t;
+ boolean isVoid = token.kind == VOID;
+ if (isVoid) {
+ t = to(F.at(pos).TypeIdent(TypeTag.VOID));
+ nextToken();
+ } else {
+ // return type of method, declared type of variable, or an expression
+ t = term(EXPR | TYPE);
+ }
+ if (token.kind == COLON && t.hasTag(IDENT)) {
+ // labelled statement
+ nextToken();
+ JCStatement stat = parseStatement();
+ return List.<JCTree>of(F.at(pos).Labelled(prevToken.name(), stat));
+ } else if ((isVoid || (lastmode & TYPE) != 0) && LAX_IDENTIFIER.accepts(token.kind)) {
+ // we have "Type Ident", so we can assume it is variable or method declaration
+ pos = token.pos;
+ Name name = ident();
+ if (token.kind == LPAREN) {
+ // method declaration
+ //mods.flags |= Flags.STATIC;
+ return List.of(methodDeclaratorRest(
+ pos, mods, t, name, typarams,
+ false, isVoid, dc));
+ } else if (!isVoid && typarams.isEmpty()) {
+ // variable declaration
+ //mods.flags |= Flags.STATIC;
+ List<JCTree> defs
+ = variableDeclaratorsRest(pos, mods, t, name, false, dc,
+ new ListBuffer<JCTree>()).toList();
+ accept(SEMI);
+ storeEnd(defs.last(), S.prevToken().endPos);
+ return defs;
+ } else {
+ // malformed declaration, return error
+ pos = token.pos;
+ List<JCTree> err = isVoid
+ ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, t, typarams,
+ List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
+ : null;
+ return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
+ }
+ } else if (!typarams.isEmpty()) {
+ // type parameters on non-variable non-method -- error
+ return List.<JCTree>of(syntaxError(token.pos, "illegal.start.of.type"));
+ } else {
+ // expression-statement or expression to evaluate
+ accept(SEMI);
+ JCExpressionStatement expr = toP(F.at(pos).Exec(t));
+ return List.<JCTree>of(expr);
+ }
+
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/parser/extend/TrialParserFactory.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.Context;
+
+/**
+ *
+ * @author Robert Field
+ */
+class TrialParserFactory extends ParserFactory {
+
+ public static ParserFactory instance(Context context) {
+ ParserFactory instance = context.get(parserFactoryKey);
+ if (instance == null) {
+ instance = new TrialParserFactory(context);
+ }
+ return instance;
+ }
+
+ private final ScannerFactory scannerFactory;
+
+ protected TrialParserFactory(Context context) {
+ super(context);
+ this.scannerFactory = ScannerFactory.instance(context);
+ }
+
+ @Override
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
+ return new TrialParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/warning/Warn6.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8069254
+ * @summary Ensure the generic array creation warning is not incorrectly produced for diamonds
+ * @compile -Xlint:unchecked -Werror Warn6.java
+ */
+
+public class Warn6<T> {
+ @SafeVarargs
+ public Warn6(T... args) {
+ }
+
+ public static void main(String[] args) {
+ Iterable<String> i = null;
+
+ Warn6<Iterable<String>> foo2 = new Warn6<>(i, i);
+ Warn6<Iterable<String>> foo3 = new Warn6<Iterable<String>>(i, i);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/suppress/T8069094.java Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,17 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8069094
+ * @summary Verify that \\@SuppressWarnings("unchecked") works correctly for annotation default values
+ * @build VerifySuppressWarnings
+ * @compile/ref=T8069094.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast T8069094.java
+ * @run main VerifySuppressWarnings T8069094.java
+ */
+
+@interface T8069094 {
+ T8069094A foo() default T8069094A.Bar;
+}
+
+@Deprecated
+enum T8069094A {
+ Bar
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/suppress/T8069094.out Mon Jan 26 17:00:39 2015 -0800
@@ -0,0 +1,3 @@
+T8069094.java:11:5: compiler.warn.has.been.deprecated: T8069094A, compiler.misc.unnamed.package
+T8069094.java:11:29: compiler.warn.has.been.deprecated: T8069094A, compiler.misc.unnamed.package
+2 warnings
--- a/modules.xml Thu Jan 22 22:42:33 2015 -0800
+++ b/modules.xml Mon Jan 26 17:00:39 2015 -0800
@@ -737,7 +737,7 @@
</export>
<export>
<name>sun.awt</name>
- <to>oracle.accessbridge</to>
+ <to>jdk.accessbridge</to>
</export>
</module>
<module>
--- a/nashorn/.hgtags Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/.hgtags Mon Jan 26 17:00:39 2015 -0800
@@ -280,3 +280,4 @@
50ee576062726e536d1bb9a5eadd8fd4470128fc jdk9-b44
3c2bbeda038aef7061455fec604db7d8a342fac5 jdk9-b45
2ecf0a617f0f9af1ffd278a0c70e76f1946ce773 jdk9-b46
+29046d42a95e5b9f105ab086a628bbd7f81c915d jdk9-b47
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Mon Jan 26 17:00:39 2015 -0800
@@ -340,9 +340,10 @@
@Override
public boolean containsKey(final Object key) {
+ checkKey(key);
return inGlobal(new Callable<Boolean>() {
@Override public Boolean call() {
- return sobj.containsKey(unwrap(key, global));
+ return sobj.containsKey(key);
}
});
}
@@ -376,6 +377,7 @@
@Override
public Object get(final Object key) {
+ checkKey(key);
return inGlobal(new Callable<Object>() {
@Override public Object call() {
return translateUndefined(wrap(sobj.get(key), global));
@@ -410,6 +412,7 @@
@Override
public Object put(final String key, final Object value) {
+ checkKey(key);
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
return inGlobal(new Callable<Object>() {
@@ -422,6 +425,9 @@
@Override
public void putAll(final Map<? extends String, ? extends Object> map) {
+ if (map == null) {
+ throw new NullPointerException("map is null");
+ }
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
inGlobal(new Callable<Object>() {
@@ -429,7 +435,9 @@
for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
final Object value = entry.getValue();
final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
- sobj.set(entry.getKey(), unwrap(modValue, global), getCallSiteFlags());
+ final String key = entry.getKey();
+ checkKey(key);
+ sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
}
return null;
}
@@ -438,9 +446,10 @@
@Override
public Object remove(final Object key) {
+ checkKey(key);
return inGlobal(new Callable<Object>() {
@Override public Object call() {
- return wrap(sobj.remove(unwrap(key, global), strict), global);
+ return wrap(sobj.remove(key, strict), global);
}
});
}
@@ -629,7 +638,7 @@
}
/**
- * Utilitity to convert this script object to the given type.
+ * Utility to convert this script object to the given type.
*
* @param <T> destination type to convert to
* @param type destination type to convert to
@@ -786,6 +795,24 @@
}
}
+ /**
+ * Ensures the key is not null, empty string, or a non-String object. The contract of the {@link Bindings}
+ * interface requires that these are not accepted as keys.
+ * @param key the key to check
+ * @throws NullPointerException if key is null
+ * @throws ClassCastException if key is not a String
+ * @throws IllegalArgumentException if key is empty string
+ */
+ private static void checkKey(final Object key) {
+ if (key == null) {
+ throw new NullPointerException("key can not be null");
+ } else if (!(key instanceof String)) {
+ throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
+ } else if (((String)key).length() == 0) {
+ throw new IllegalArgumentException("key can not be empty");
+ }
+ }
+
@Override
public double toNumber() {
return inGlobal(new Callable<Double>() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Mon Jan 26 17:00:39 2015 -0800
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
@@ -761,39 +762,6 @@
}
/**
- * Push an array of items to the end of the array
- *
- * @param strict are we in strict mode
- * @param item the item
- * @return new array data (or same)
- */
- public ArrayData push(final boolean strict, final double item) {
- return push(strict, item);
- }
-
- /**
- * Push an array of items to the end of the array
- *
- * @param strict are we in strict mode
- * @param item the item
- * @return new array data (or same)
- */
- public ArrayData push(final boolean strict, final long item) {
- return push(strict, item);
- }
-
- /**
- * Push an array of items to the end of the array
- *
- * @param strict are we in strict mode
- * @param item the item
- * @return new array data (or same)
- */
- public ArrayData push(final boolean strict, final int item) {
- return push(strict, item);
- }
-
- /**
* Pop an element from the end of the array
*
* @return the popped element
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Mon Jan 26 17:00:39 2015 -0800
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -343,17 +344,6 @@
}
@Override
- public final ArrayData push(final boolean strict, final int item) {
- final long len = length();
- final ArrayData newData = ensure(len);
- if (newData == this) {
- array[(int)len] = item;
- return this;
- }
- return newData.set((int)len, item, strict);
- }
-
- @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Mon Jan 26 17:00:39 2015 -0800
@@ -27,6 +27,7 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -303,17 +304,6 @@
}
@Override
- public final ArrayData push(final boolean strict, final long item) {
- final long len = length();
- final ArrayData newData = ensure(len);
- if (newData == this) {
- array[(int)len] = item;
- return this;
- }
- return newData.set((int)len, item, strict);
- }
-
- @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Mon Jan 26 17:00:39 2015 -0800
@@ -28,6 +28,7 @@
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@@ -277,17 +278,6 @@
}
@Override
- public final ArrayData push(final boolean strict, final double item) {
- final long len = length();
- final ArrayData newData = ensure(len);
- if (newData == this) {
- array[(int)len] = item;
- return this;
- }
- return newData.set((int)len, item, strict);
- }
-
- @Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();
final long newLength = oldLength - removed + added;
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Thu Jan 22 22:42:33 2015 -0800
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Jan 26 17:00:39 2015 -0800
@@ -36,10 +36,12 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
+import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
@@ -719,6 +721,128 @@
assertTrue(invoked.get());
}
+ // @bug JDK-8068603: NashornScriptEngine.put/get() impls don't conform to NPE, IAE spec assertions
+ @Test
+ public void illegalBindingsValuesTest() throws Exception {
+ final ScriptEngineManager manager = new ScriptEngineManager();
+ final ScriptEngine e = manager.getEngineByName("nashorn");
+
+ try {
+ e.put(null, "null-value");
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ e.put("", "empty-value");
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+
+ final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
+ assertTrue(b instanceof ScriptObjectMirror);
+
+ try {
+ b.put(null, "null-value");
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.put("", "empty-value");
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+
+ try {
+ b.get(null);
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.get("");
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+
+ try {
+ b.get(1);
+ fail();
+ } catch (ClassCastException x) {
+ // expected
+ }
+
+ try {
+ b.remove(null);
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.remove("");
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+
+ try {
+ b.remove(1);
+ fail();
+ } catch (ClassCastException x) {
+ // expected
+ }
+
+ try {
+ b.containsKey(null);
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.containsKey("");
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+
+ try {
+ b.containsKey(1);
+ fail();
+ } catch (ClassCastException x) {
+ // expected
+ }
+
+ try {
+ b.putAll(null);
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.putAll(Collections.singletonMap((String)null, "null-value"));
+ fail();
+ } catch (NullPointerException x) {
+ // expected
+ }
+
+ try {
+ b.putAll(Collections.singletonMap("", "empty-value"));
+ fail();
+ } catch (IllegalArgumentException x) {
+ // expected
+ }
+ }
+
private static void checkProperty(final ScriptEngine e, final String name)
throws ScriptException {
final String value = System.getProperty(name);