Merge jdk9-b73
authorduke
Wed, 05 Jul 2017 20:41:30 +0200
changeset 31564 9b3a9d72f07b
parent 31563 6230c3f39d29 (diff)
parent 31510 b050dcca193f (current diff)
child 31565 161b5e260852
child 31566 a55acabac012
child 31567 626eeea487f8
child 31578 3736bed37826
child 31582 bac6259f016e
child 31636 75c6dcc9351d
child 31641 5a80ee918d0f
child 31642 7ae76e376fcd
child 31678 7a5da9274448
child 31732 2594f4a023af
child 31733 0d786ab95c1c
child 31736 4ed52f64daa2
child 31737 768d27701021
child 31743 de28c7256c35
child 31745 10f3c2e3d35b
child 31746 7573de6b8e46
child 31749 14c2c23cca7c
child 31750 c65c37c0c691
child 31756 610e4995e798
Merge
--- a/.hgtags-top-repo	Wed Jul 05 20:40:53 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 20:41:30 2017 +0200
@@ -314,3 +314,4 @@
 1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69
 eed77fcd77711fcdba05f18fc22f37d86efb243c jdk9-b70
 c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
+8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72
--- a/corba/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -314,3 +314,4 @@
 de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69
 e7cf01990ed366bd493080663259281e91ce223b jdk9-b70
 cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71
+f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72
--- a/hotspot/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -474,3 +474,4 @@
 ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69
 8672e9264db30c21504063932dbc374eabc287a1 jdk9-b70
 07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71
+c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 20:41:30 2017 +0200
@@ -865,6 +865,42 @@
     V31, V31_H
 );
 
+// Class for all 64bit vector registers
+reg_class vectord_reg(
+    V0, V0_H,
+    V1, V1_H,
+    V2, V2_H,
+    V3, V3_H,
+    V4, V4_H,
+    V5, V5_H,
+    V6, V6_H,
+    V7, V7_H,
+    V8, V8_H,
+    V9, V9_H,
+    V10, V10_H,
+    V11, V11_H,
+    V12, V12_H,
+    V13, V13_H,
+    V14, V14_H,
+    V15, V15_H,
+    V16, V16_H,
+    V17, V17_H,
+    V18, V18_H,
+    V19, V19_H,
+    V20, V20_H,
+    V21, V21_H,
+    V22, V22_H,
+    V23, V23_H,
+    V24, V24_H,
+    V25, V25_H,
+    V26, V26_H,
+    V27, V27_H,
+    V28, V28_H,
+    V29, V29_H,
+    V30, V30_H,
+    V31, V31_H
+);
+
 // Class for all 128bit vector registers
 reg_class vectorx_reg(
     V0, V0_H, V0_J, V0_K,
@@ -2133,40 +2169,48 @@
 
   if (bottom_type()->isa_vect() != NULL) {
     uint len = 4;
+    uint ireg = ideal_reg();
+    assert(ireg == Op_VecD || ireg == Op_VecX, "must be 64 bit or 128 bit vector");
     if (cbuf) {
       MacroAssembler _masm(cbuf);
-      uint ireg = ideal_reg();
       assert((src_lo_rc != rc_int && dst_lo_rc != rc_int), "sanity");
-      assert(ireg == Op_VecX, "sanity");
       if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) {
         // stack->stack
         int src_offset = ra_->reg2offset(src_lo);
         int dst_offset = ra_->reg2offset(dst_lo);
         assert((src_offset & 7) && (dst_offset & 7), "unaligned stack offset");
         len = 8;
-        if (src_offset < 512) {
-          __ ldp(rscratch1, rscratch2, Address(sp, src_offset));
-        } else {
+        if (ireg == Op_VecD) {
           __ ldr(rscratch1, Address(sp, src_offset));
-          __ ldr(rscratch2, Address(sp, src_offset+4));
-          len += 4;
-        }
-        if (dst_offset < 512) {
-          __ stp(rscratch1, rscratch2, Address(sp, dst_offset));
+          __ str(rscratch1, Address(sp, dst_offset));
         } else {
-          __ str(rscratch1, Address(sp, dst_offset));
-          __ str(rscratch2, Address(sp, dst_offset+4));
-          len += 4;
+          if (src_offset < 512) {
+            __ ldp(rscratch1, rscratch2, Address(sp, src_offset));
+          } else {
+            __ ldr(rscratch1, Address(sp, src_offset));
+            __ ldr(rscratch2, Address(sp, src_offset+4));
+            len += 4;
+          }
+          if (dst_offset < 512) {
+            __ stp(rscratch1, rscratch2, Address(sp, dst_offset));
+          } else {
+            __ str(rscratch1, Address(sp, dst_offset));
+            __ str(rscratch2, Address(sp, dst_offset+4));
+            len += 4;
+          }
         }
       } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
-        __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ T16B,
+        __ orr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+               ireg == Op_VecD ? __ T8B : __ T16B,
                as_FloatRegister(Matcher::_regEncode[src_lo]),
                as_FloatRegister(Matcher::_regEncode[src_lo]));
       } else if (src_lo_rc == rc_float && dst_lo_rc == rc_stack) {
-        __ str(as_FloatRegister(Matcher::_regEncode[src_lo]), __ Q,
+        __ str(as_FloatRegister(Matcher::_regEncode[src_lo]),
+               ireg == Op_VecD ? __ D : __ Q,
                Address(sp, ra_->reg2offset(dst_lo)));
       } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_float) {
-        __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]), __ Q,
+        __ ldr(as_FloatRegister(Matcher::_regEncode[dst_lo]),
+               ireg == Op_VecD ? __ D : __ Q,
                Address(sp, ra_->reg2offset(src_lo)));
       } else {
         ShouldNotReachHere();
@@ -2176,17 +2220,22 @@
         // stack->stack
         int src_offset = ra_->reg2offset(src_lo);
         int dst_offset = ra_->reg2offset(dst_lo);
-        if (src_offset < 512) {
-          st->print("ldp  rscratch1, rscratch2, [sp, #%d]", src_offset);
-        } else {
+        if (ireg == Op_VecD) {
           st->print("ldr  rscratch1, [sp, #%d]", src_offset);
-          st->print("\nldr  rscratch2, [sp, #%d]", src_offset+4);
-        }
-        if (dst_offset < 512) {
-          st->print("\nstp  rscratch1, rscratch2, [sp, #%d]", dst_offset);
+          st->print("str  rscratch1, [sp, #%d]", dst_offset);
         } else {
-          st->print("\nstr  rscratch1, [sp, #%d]", dst_offset);
-          st->print("\nstr  rscratch2, [sp, #%d]", dst_offset+4);
+          if (src_offset < 512) {
+            st->print("ldp  rscratch1, rscratch2, [sp, #%d]", src_offset);
+          } else {
+            st->print("ldr  rscratch1, [sp, #%d]", src_offset);
+            st->print("\nldr  rscratch2, [sp, #%d]", src_offset+4);
+          }
+          if (dst_offset < 512) {
+            st->print("\nstp  rscratch1, rscratch2, [sp, #%d]", dst_offset);
+          } else {
+            st->print("\nstr  rscratch1, [sp, #%d]", dst_offset);
+            st->print("\nstr  rscratch2, [sp, #%d]", dst_offset+4);
+          }
         }
         st->print("\t# vector spill, stack to stack");
       } else if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
@@ -2638,17 +2687,22 @@
   return vector_width_in_bytes(bt)/type2aelembytes(bt);
 }
 const int Matcher::min_vector_size(const BasicType bt) {
-  //return (type2aelembytes(bt) == 1) ? 4 : 2;
-  // For the moment, only support 1 vector size, 128 bits
-  return max_vector_size(bt);
+//  For the moment limit the vector size to 8 bytes
+    int size = 8 / type2aelembytes(bt);
+    if (size < 2) size = 2;
+    return size;
 }
 
 // Vector ideal reg.
 const int Matcher::vector_ideal_reg(int len) {
-  return Op_VecX;
+  switch(len) {
+    case  8: return Op_VecD;
+    case 16: return Op_VecX;
+  }
+  ShouldNotReachHere();
+  return 0;
 }
 
-// Only lowest bits of xmm reg are used for vector shift count.
 const int Matcher::vector_shift_count_ideal_reg(int size) {
   return Op_VecX;
 }
@@ -2660,9 +2714,7 @@
 
 // x86 supports misaligned vectors store/load.
 const bool Matcher::misaligned_vectors_ok() {
-  // TODO fixme
-  // return !AlignVector; // can be changed by flag
-  return false;
+  return !AlignVector; // can be changed by flag
 }
 
 // false => size gets scaled to BytesPerLong, ok.
@@ -3073,13 +3125,13 @@
                as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}
 
-  enc_class aarch64_enc_ldrvS(vecX dst, memory mem) %{
+  enc_class aarch64_enc_ldrvS(vecD dst, memory mem) %{
     FloatRegister dst_reg = as_FloatRegister($dst$$reg);
     loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::S,
        $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}
 
-  enc_class aarch64_enc_ldrvD(vecX dst, memory mem) %{
+  enc_class aarch64_enc_ldrvD(vecD dst, memory mem) %{
     FloatRegister dst_reg = as_FloatRegister($dst$$reg);
     loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldr, dst_reg, MacroAssembler::D,
        $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
@@ -3159,13 +3211,13 @@
                as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}
 
-  enc_class aarch64_enc_strvS(vecX src, memory mem) %{
+  enc_class aarch64_enc_strvS(vecD src, memory mem) %{
     FloatRegister src_reg = as_FloatRegister($src$$reg);
     loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::S,
        $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
   %}
 
-  enc_class aarch64_enc_strvD(vecX src, memory mem) %{
+  enc_class aarch64_enc_strvD(vecD src, memory mem) %{
     FloatRegister src_reg = as_FloatRegister($src$$reg);
     loadStore(MacroAssembler(&cbuf), &MacroAssembler::str, src_reg, MacroAssembler::D,
        $mem->opcode(), as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
@@ -5187,6 +5239,16 @@
   interface(REG_INTER);
 %}
 
+operand vecD()
+%{
+  constraint(ALLOC_IN_RC(vectord_reg));
+  match(VecD);
+
+  op_cost(0);
+  format %{ %}
+  interface(REG_INTER);
+%}
+
 operand vecX()
 %{
   constraint(ALLOC_IN_RC(vectorx_reg));
@@ -7402,6 +7464,96 @@
   ins_pipe(ialu_reg);
 %}
 
+//---------- Population Count Instructions -------------------------------------
+//
+
+instruct popCountI(iRegINoSp dst, iRegIorL2I src, vRegF tmp) %{
+  predicate(UsePopCountInstruction);
+  match(Set dst (PopCountI src));
+  effect(TEMP tmp);
+  ins_cost(INSN_COST * 13);
+
+  format %{ "movw   $src, $src\n\t"
+            "mov    $tmp, $src\t# vector (1D)\n\t"
+            "cnt    $tmp, $tmp\t# vector (8B)\n\t"
+            "addv   $tmp, $tmp\t# vector (8B)\n\t"
+            "mov    $dst, $tmp\t# vector (1D)" %}
+  ins_encode %{
+    __ movw($src$$Register, $src$$Register); // ensure top 32 bits 0
+    __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register);
+    __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct popCountI_mem(iRegINoSp dst, memory mem, vRegF tmp) %{
+  predicate(UsePopCountInstruction);
+  match(Set dst (PopCountI (LoadI mem)));
+  effect(TEMP tmp);
+  ins_cost(INSN_COST * 13);
+
+  format %{ "ldrs   $tmp, $mem\n\t"
+            "cnt    $tmp, $tmp\t# vector (8B)\n\t"
+            "addv   $tmp, $tmp\t# vector (8B)\n\t"
+            "mov    $dst, $tmp\t# vector (1D)" %}
+  ins_encode %{
+    FloatRegister tmp_reg = as_FloatRegister($tmp$$reg);
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrs, tmp_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+    __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+// Note: Long.bitCount(long) returns an int.
+instruct popCountL(iRegINoSp dst, iRegL src, vRegD tmp) %{
+  predicate(UsePopCountInstruction);
+  match(Set dst (PopCountL src));
+  effect(TEMP tmp);
+  ins_cost(INSN_COST * 13);
+
+  format %{ "mov    $tmp, $src\t# vector (1D)\n\t"
+            "cnt    $tmp, $tmp\t# vector (8B)\n\t"
+            "addv   $tmp, $tmp\t# vector (8B)\n\t"
+            "mov    $dst, $tmp\t# vector (1D)" %}
+  ins_encode %{
+    __ mov($tmp$$FloatRegister, __ T1D, 0, $src$$Register);
+    __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
+instruct popCountL_mem(iRegINoSp dst, memory mem, vRegD tmp) %{
+  predicate(UsePopCountInstruction);
+  match(Set dst (PopCountL (LoadL mem)));
+  effect(TEMP tmp);
+  ins_cost(INSN_COST * 13);
+
+  format %{ "ldrd   $tmp, $mem\n\t"
+            "cnt    $tmp, $tmp\t# vector (8B)\n\t"
+            "addv   $tmp, $tmp\t# vector (8B)\n\t"
+            "mov    $dst, $tmp\t# vector (1D)" %}
+  ins_encode %{
+    FloatRegister tmp_reg = as_FloatRegister($tmp$$reg);
+    loadStore(MacroAssembler(&cbuf), &MacroAssembler::ldrd, tmp_reg, $mem->opcode(),
+               as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
+    __ cnt($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ addv($tmp$$FloatRegister, __ T8B, $tmp$$FloatRegister);
+    __ mov($dst$$Register, $tmp$$FloatRegister, __ T1D, 0);
+  %}
+
+  ins_pipe(pipe_class_default);
+%}
+
 // ============================================================================
 // MemBar Instruction
 
@@ -13194,7 +13346,7 @@
 // ====================VECTOR INSTRUCTIONS=====================================
 
 // Load vector (32 bits)
-instruct loadV4(vecX dst, vmem mem)
+instruct loadV4(vecD dst, vmem mem)
 %{
   predicate(n->as_LoadVector()->memory_size() == 4);
   match(Set dst (LoadVector mem));
@@ -13205,7 +13357,7 @@
 %}
 
 // Load vector (64 bits)
-instruct loadV8(vecX dst, vmem mem)
+instruct loadV8(vecD dst, vmem mem)
 %{
   predicate(n->as_LoadVector()->memory_size() == 8);
   match(Set dst (LoadVector mem));
@@ -13227,7 +13379,7 @@
 %}
 
 // Store Vector (32 bits)
-instruct storeV4(vecX src, vmem mem)
+instruct storeV4(vecD src, vmem mem)
 %{
   predicate(n->as_StoreVector()->memory_size() == 4);
   match(Set mem (StoreVector mem src));
@@ -13238,7 +13390,7 @@
 %}
 
 // Store Vector (64 bits)
-instruct storeV8(vecX src, vmem mem)
+instruct storeV8(vecD src, vmem mem)
 %{
   predicate(n->as_StoreVector()->memory_size() == 8);
   match(Set mem (StoreVector mem src));
@@ -13259,8 +13411,22 @@
   ins_pipe(pipe_class_memory);
 %}
 
+instruct replicate8B(vecD dst, iRegIorL2I src)
+%{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (ReplicateB src));
+  ins_cost(INSN_COST);
+  format %{ "dup  $dst, $src\t# vector (8B)" %}
+  ins_encode %{
+    __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($src$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate16B(vecX dst, iRegIorL2I src)
 %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (ReplicateB src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (16B)" %}
@@ -13270,8 +13436,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate8B_imm(vecD dst, immI con)
+%{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (ReplicateB con));
+  ins_cost(INSN_COST);
+  format %{ "movi  $dst, $con\t# vector(8B)" %}
+  ins_encode %{
+    __ mov(as_FloatRegister($dst$$reg), __ T8B, $con$$constant & 0xff);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate16B_imm(vecX dst, immI con)
 %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (ReplicateB con));
   ins_cost(INSN_COST);
   format %{ "movi  $dst, $con\t# vector(16B)" %}
@@ -13281,8 +13461,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate4S(vecD dst, iRegIorL2I src)
+%{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (ReplicateS src));
+  ins_cost(INSN_COST);
+  format %{ "dup  $dst, $src\t# vector (4S)" %}
+  ins_encode %{
+    __ dup(as_FloatRegister($dst$$reg), __ T4H, as_Register($src$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate8S(vecX dst, iRegIorL2I src)
 %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (ReplicateS src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (8S)" %}
@@ -13292,8 +13486,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate4S_imm(vecD dst, immI con)
+%{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (ReplicateS con));
+  ins_cost(INSN_COST);
+  format %{ "movi  $dst, $con\t# vector(4H)" %}
+  ins_encode %{
+    __ mov(as_FloatRegister($dst$$reg), __ T4H, $con$$constant & 0xffff);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate8S_imm(vecX dst, immI con)
 %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (ReplicateS con));
   ins_cost(INSN_COST);
   format %{ "movi  $dst, $con\t# vector(8H)" %}
@@ -13303,8 +13511,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate2I(vecD dst, iRegIorL2I src)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (ReplicateI src));
+  ins_cost(INSN_COST);
+  format %{ "dup  $dst, $src\t# vector (2I)" %}
+  ins_encode %{
+    __ dup(as_FloatRegister($dst$$reg), __ T2S, as_Register($src$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate4I(vecX dst, iRegIorL2I src)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (ReplicateI src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (4I)" %}
@@ -13314,8 +13535,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate2I_imm(vecD dst, immI con)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (ReplicateI con));
+  ins_cost(INSN_COST);
+  format %{ "movi  $dst, $con\t# vector(2I)" %}
+  ins_encode %{
+    __ mov(as_FloatRegister($dst$$reg), __ T2S, $con$$constant);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate4I_imm(vecX dst, immI con)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (ReplicateI con));
   ins_cost(INSN_COST);
   format %{ "movi  $dst, $con\t# vector(4I)" %}
@@ -13327,6 +13561,7 @@
 
 instruct replicate2L(vecX dst, iRegL src)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (ReplicateL src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (2L)" %}
@@ -13338,6 +13573,7 @@
 
 instruct replicate2L_zero(vecX dst, immI0 zero)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (ReplicateI zero));
   ins_cost(INSN_COST);
   format %{ "movi  $dst, $zero\t# vector(4I)" %}
@@ -13349,8 +13585,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct replicate2F(vecD dst, vRegF src)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (ReplicateF src));
+  ins_cost(INSN_COST);
+  format %{ "dup  $dst, $src\t# vector (2F)" %}
+  ins_encode %{
+    __ dup(as_FloatRegister($dst$$reg), __ T2S,
+           as_FloatRegister($src$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct replicate4F(vecX dst, vRegF src)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (ReplicateF src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (4F)" %}
@@ -13363,6 +13613,7 @@
 
 instruct replicate2D(vecX dst, vRegD src)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (ReplicateD src));
   ins_cost(INSN_COST);
   format %{ "dup  $dst, $src\t# vector (2D)" %}
@@ -13375,6 +13626,25 @@
 
 // ====================REDUCTION ARITHMETIC====================================
 
+instruct reduce_add2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp, iRegI tmp2)
+%{
+  match(Set dst (AddReductionVI src1 src2));
+  ins_cost(INSN_COST);
+  effect(TEMP tmp, TEMP tmp2);
+  format %{ "umov  $tmp, $src2, S, 0\n\t"
+            "umov  $tmp2, $src2, S, 1\n\t"
+            "addw  $dst, $src1, $tmp\n\t"
+            "addw  $dst, $dst, $tmp2\t add reduction2i"
+  %}
+  ins_encode %{
+    __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0);
+    __ umov($tmp2$$Register, as_FloatRegister($src2$$reg), __ S, 1);
+    __ addw($dst$$Register, $src1$$Register, $tmp$$Register);
+    __ addw($dst$$Register, $dst$$Register, $tmp2$$Register);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct reduce_add4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
 %{
   match(Set dst (AddReductionVI src1 src2));
@@ -13393,6 +13663,25 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I src1, vecD src2, iRegI tmp)
+%{
+  match(Set dst (MulReductionVI src1 src2));
+  ins_cost(INSN_COST);
+  effect(TEMP tmp, TEMP dst);
+  format %{ "umov  $tmp, $src2, S, 0\n\t"
+            "mul   $dst, $tmp, $src1\n\t"
+            "umov  $tmp, $src2, S, 1\n\t"
+            "mul   $dst, $tmp, $dst\t mul reduction2i\n\t"
+  %}
+  ins_encode %{
+    __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 0);
+    __ mul($dst$$Register, $tmp$$Register, $src1$$Register);
+    __ umov($tmp$$Register, as_FloatRegister($src2$$reg), __ S, 1);
+    __ mul($dst$$Register, $tmp$$Register, $dst$$Register);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I src1, vecX src2, vecX tmp, iRegI tmp2)
 %{
   match(Set dst (MulReductionVI src1 src2));
@@ -13418,6 +13707,26 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct reduce_add2F(vRegF dst, vRegF src1, vecD src2, vecD tmp)
+%{
+  match(Set dst (AddReductionVF src1 src2));
+  ins_cost(INSN_COST);
+  effect(TEMP tmp, TEMP dst);
+  format %{ "fadds $dst, $src1, $src2\n\t"
+            "ins   $tmp, S, $src2, 0, 1\n\t"
+            "fadds $dst, $dst, $tmp\t add reduction2f"
+  %}
+  ins_encode %{
+    __ fadds(as_FloatRegister($dst$$reg),
+             as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
+    __ ins(as_FloatRegister($tmp$$reg), __ S,
+           as_FloatRegister($src2$$reg), 0, 1);
+    __ fadds(as_FloatRegister($dst$$reg),
+             as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct reduce_add4F(vRegF dst, vRegF src1, vecX src2, vecX tmp)
 %{
   match(Set dst (AddReductionVF src1 src2));
@@ -13450,6 +13759,26 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct reduce_mul2F(vRegF dst, vRegF src1, vecD src2, vecD tmp)
+%{
+  match(Set dst (MulReductionVF src1 src2));
+  ins_cost(INSN_COST);
+  effect(TEMP tmp, TEMP dst);
+  format %{ "fmuls $dst, $src1, $src2\n\t"
+            "ins   $tmp, S, $src2, 0, 1\n\t"
+            "fmuls $dst, $dst, $tmp\t add reduction4f"
+  %}
+  ins_encode %{
+    __ fmuls(as_FloatRegister($dst$$reg),
+             as_FloatRegister($src1$$reg), as_FloatRegister($src2$$reg));
+    __ ins(as_FloatRegister($tmp$$reg), __ S,
+           as_FloatRegister($src2$$reg), 0, 1);
+    __ fmuls(as_FloatRegister($dst$$reg),
+             as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct reduce_mul4F(vRegF dst, vRegF src1, vecX src2, vecX tmp)
 %{
   match(Set dst (MulReductionVF src1 src2));
@@ -13526,8 +13855,24 @@
 
 // --------------------------------- ADD --------------------------------------
 
+instruct vadd8B(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (AddVB src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "addv  $dst,$src1,$src2\t# vector (8B)" %}
+  ins_encode %{
+    __ addv(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vadd16B(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (AddVB src1 src2));
   ins_cost(INSN_COST);
   format %{ "addv  $dst,$src1,$src2\t# vector (16B)" %}
@@ -13539,8 +13884,24 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vadd4S(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (AddVS src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "addv  $dst,$src1,$src2\t# vector (4H)" %}
+  ins_encode %{
+    __ addv(as_FloatRegister($dst$$reg), __ T4H,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vadd8S(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (AddVS src1 src2));
   ins_cost(INSN_COST);
   format %{ "addv  $dst,$src1,$src2\t# vector (8H)" %}
@@ -13552,8 +13913,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vadd2I(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (AddVI src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "addv  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ addv(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vadd4I(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (AddVI src1 src2));
   ins_cost(INSN_COST);
   format %{ "addv  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13567,6 +13943,7 @@
 
 instruct vadd2L(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (AddVL src1 src2));
   ins_cost(INSN_COST);
   format %{ "addv  $dst,$src1,$src2\t# vector (2L)" %}
@@ -13578,8 +13955,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vadd2F(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (AddVF src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "fadd  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ fadd(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vadd4F(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (AddVF src1 src2));
   ins_cost(INSN_COST);
   format %{ "fadd  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13606,8 +13998,24 @@
 
 // --------------------------------- SUB --------------------------------------
 
+instruct vsub8B(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (SubVB src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "subv  $dst,$src1,$src2\t# vector (8B)" %}
+  ins_encode %{
+    __ subv(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsub16B(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (SubVB src1 src2));
   ins_cost(INSN_COST);
   format %{ "subv  $dst,$src1,$src2\t# vector (16B)" %}
@@ -13619,8 +14027,24 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsub4S(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (SubVS src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "subv  $dst,$src1,$src2\t# vector (4H)" %}
+  ins_encode %{
+    __ subv(as_FloatRegister($dst$$reg), __ T4H,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsub8S(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (SubVS src1 src2));
   ins_cost(INSN_COST);
   format %{ "subv  $dst,$src1,$src2\t# vector (8H)" %}
@@ -13632,8 +14056,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsub2I(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (SubVI src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "subv  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ subv(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsub4I(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (SubVI src1 src2));
   ins_cost(INSN_COST);
   format %{ "subv  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13647,6 +14086,7 @@
 
 instruct vsub2L(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (SubVL src1 src2));
   ins_cost(INSN_COST);
   format %{ "subv  $dst,$src1,$src2\t# vector (2L)" %}
@@ -13658,8 +14098,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsub2F(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (AddVF src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "fsub  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ fsub(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsub4F(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (SubVF src1 src2));
   ins_cost(INSN_COST);
   format %{ "fsub  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13673,6 +14128,7 @@
 
 instruct vsub2D(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (SubVD src1 src2));
   ins_cost(INSN_COST);
   format %{ "fsub  $dst,$src1,$src2\t# vector (2D)" %}
@@ -13686,8 +14142,24 @@
 
 // --------------------------------- MUL --------------------------------------
 
+instruct vmul4S(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (MulVS src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "mulv  $dst,$src1,$src2\t# vector (4H)" %}
+  ins_encode %{
+    __ mulv(as_FloatRegister($dst$$reg), __ T4H,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vmul8S(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (MulVS src1 src2));
   ins_cost(INSN_COST);
   format %{ "mulv  $dst,$src1,$src2\t# vector (8H)" %}
@@ -13699,8 +14171,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vmul2I(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (MulVI src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "mulv  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ mulv(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vmul4I(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (MulVI src1 src2));
   ins_cost(INSN_COST);
   format %{ "mulv  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13712,8 +14199,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vmul2F(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (MulVF src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "fmul  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ fmul(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vmul4F(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (MulVF src1 src2));
   ins_cost(INSN_COST);
   format %{ "fmul  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13727,6 +14229,7 @@
 
 instruct vmul2D(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (MulVD src1 src2));
   ins_cost(INSN_COST);
   format %{ "fmul  $dst,$src1,$src2\t# vector (2D)" %}
@@ -13740,8 +14243,23 @@
 
 // --------------------------------- DIV --------------------------------------
 
+instruct vdiv2F(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (DivVF src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "fdiv  $dst,$src1,$src2\t# vector (2S)" %}
+  ins_encode %{
+    __ fdiv(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vdiv4F(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (DivVF src1 src2));
   ins_cost(INSN_COST);
   format %{ "fdiv  $dst,$src1,$src2\t# vector (4S)" %}
@@ -13755,6 +14273,7 @@
 
 instruct vdiv2D(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (DivVD src1 src2));
   ins_cost(INSN_COST);
   format %{ "fdiv  $dst,$src1,$src2\t# vector (2D)" %}
@@ -13768,8 +14287,24 @@
 
 // --------------------------------- AND --------------------------------------
 
+instruct vand8B(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length_in_bytes() == 4 ||
+            n->as_Vector()->length_in_bytes() == 8);
+  match(Set dst (AndV src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "and  $dst,$src1,$src2\t# vector (8B)" %}
+  ins_encode %{
+    __ andr(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vand16B(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length_in_bytes() == 16);
   match(Set dst (AndV src1 src2));
   ins_cost(INSN_COST);
   format %{ "and  $dst,$src1,$src2\t# vector (16B)" %}
@@ -13783,8 +14318,24 @@
 
 // --------------------------------- OR ---------------------------------------
 
+instruct vor8B(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length_in_bytes() == 4 ||
+            n->as_Vector()->length_in_bytes() == 8);
+  match(Set dst (OrV src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "and  $dst,$src1,$src2\t# vector (8B)" %}
+  ins_encode %{
+    __ orr(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vor16B(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length_in_bytes() == 16);
   match(Set dst (OrV src1 src2));
   ins_cost(INSN_COST);
   format %{ "orr  $dst,$src1,$src2\t# vector (16B)" %}
@@ -13798,8 +14349,24 @@
 
 // --------------------------------- XOR --------------------------------------
 
+instruct vxor8B(vecD dst, vecD src1, vecD src2)
+%{
+  predicate(n->as_Vector()->length_in_bytes() == 4 ||
+            n->as_Vector()->length_in_bytes() == 8);
+  match(Set dst (XorV src1 src2));
+  ins_cost(INSN_COST);
+  format %{ "xor  $dst,$src1,$src2\t# vector (8B)" %}
+  ins_encode %{
+    __ eor(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src1$$reg),
+            as_FloatRegister($src2$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vxor16B(vecX dst, vecX src1, vecX src2)
 %{
+  predicate(n->as_Vector()->length_in_bytes() == 16);
   match(Set dst (XorV src1 src2));
   ins_cost(INSN_COST);
   format %{ "xor  $dst,$src1,$src2\t# vector (16B)" %}
@@ -13833,7 +14400,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll8B(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (LShiftVB src shift));
+  match(Set dst (RShiftVB src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshl  $dst,$src,$shift\t# vector (8B)" %}
+  ins_encode %{
+    __ sshl(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll16B(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (LShiftVB src shift));
   match(Set dst (RShiftVB src shift));
   ins_cost(INSN_COST);
@@ -13846,7 +14429,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl8B(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (URShiftVB src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushl  $dst,$src,$shift\t# vector (8B)" %}
+  ins_encode %{
+    __ ushl(as_FloatRegister($dst$$reg), __ T8B,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl16B(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (URShiftVB src shift));
   ins_cost(INSN_COST);
   format %{ "ushl  $dst,$src,$shift\t# vector (16B)" %}
@@ -13858,7 +14456,28 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (LShiftVB src shift));
+  ins_cost(INSN_COST);
+  format %{ "shl    $dst, $src, $shift\t# vector (8B)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 8) {
+      __ eor(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg),
+             as_FloatRegister($src$$reg));
+    } else {
+      __ shl(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg), sh);
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (LShiftVB src shift));
   ins_cost(INSN_COST);
   format %{ "shl    $dst, $src, $shift\t# vector (16B)" %}
@@ -13876,7 +14495,24 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (RShiftVB src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshr    $dst, $src, $shift\t# vector (8B)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 8) sh = 7;
+    sh = -sh & 7;
+    __ sshr(as_FloatRegister($dst$$reg), __ T8B,
+           as_FloatRegister($src$$reg), sh);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (RShiftVB src shift));
   ins_cost(INSN_COST);
   format %{ "sshr    $dst, $src, $shift\t# vector (16B)" %}
@@ -13890,7 +14526,28 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4 ||
+            n->as_Vector()->length() == 8);
+  match(Set dst (URShiftVB src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushr    $dst, $src, $shift\t# vector (8B)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 8) {
+      __ eor(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg),
+             as_FloatRegister($src$$reg));
+    } else {
+      __ ushr(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg), -sh & 7);
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 16);
   match(Set dst (URShiftVB src shift));
   ins_cost(INSN_COST);
   format %{ "ushr    $dst, $src, $shift\t# vector (16B)" %}
@@ -13908,7 +14565,23 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll4S(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (LShiftVS src shift));
+  match(Set dst (RShiftVS src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshl  $dst,$src,$shift\t# vector (4H)" %}
+  ins_encode %{
+    __ sshl(as_FloatRegister($dst$$reg), __ T4H,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll8S(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (LShiftVS src shift));
   match(Set dst (RShiftVS src shift));
   ins_cost(INSN_COST);
@@ -13921,7 +14594,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl4S(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (URShiftVS src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushl  $dst,$src,$shift\t# vector (4H)" %}
+  ins_encode %{
+    __ ushl(as_FloatRegister($dst$$reg), __ T4H,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl8S(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (URShiftVS src shift));
   ins_cost(INSN_COST);
   format %{ "ushl  $dst,$src,$shift\t# vector (8H)" %}
@@ -13933,7 +14621,28 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (LShiftVS src shift));
+  ins_cost(INSN_COST);
+  format %{ "shl    $dst, $src, $shift\t# vector (4H)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 16) {
+      __ eor(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg),
+             as_FloatRegister($src$$reg));
+    } else {
+      __ shl(as_FloatRegister($dst$$reg), __ T4H,
+             as_FloatRegister($src$$reg), sh);
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (LShiftVS src shift));
   ins_cost(INSN_COST);
   format %{ "shl    $dst, $src, $shift\t# vector (8H)" %}
@@ -13951,7 +14660,24 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (RShiftVS src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshr    $dst, $src, $shift\t# vector (4H)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 16) sh = 15;
+    sh = -sh & 15;
+    __ sshr(as_FloatRegister($dst$$reg), __ T4H,
+           as_FloatRegister($src$$reg), sh);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (RShiftVS src shift));
   ins_cost(INSN_COST);
   format %{ "sshr    $dst, $src, $shift\t# vector (8H)" %}
@@ -13965,7 +14691,28 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2 ||
+            n->as_Vector()->length() == 4);
+  match(Set dst (URShiftVS src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushr    $dst, $src, $shift\t# vector (4H)" %}
+  ins_encode %{
+    int sh = (int)$shift$$constant & 31;
+    if (sh >= 16) {
+      __ eor(as_FloatRegister($dst$$reg), __ T8B,
+             as_FloatRegister($src$$reg),
+             as_FloatRegister($src$$reg));
+    } else {
+      __ ushr(as_FloatRegister($dst$$reg), __ T4H,
+             as_FloatRegister($src$$reg), -sh & 15);
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 8);
   match(Set dst (URShiftVS src shift));
   ins_cost(INSN_COST);
   format %{ "ushr    $dst, $src, $shift\t# vector (8H)" %}
@@ -13983,7 +14730,22 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll2I(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (LShiftVI src shift));
+  match(Set dst (RShiftVI src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshl  $dst,$src,$shift\t# vector (2S)" %}
+  ins_encode %{
+    __ sshl(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll4I(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (LShiftVI src shift));
   match(Set dst (RShiftVI src shift));
   ins_cost(INSN_COST);
@@ -13996,7 +14758,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl2I(vecD dst, vecD src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (URShiftVI src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushl  $dst,$src,$shift\t# vector (2S)" %}
+  ins_encode %{
+    __ ushl(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src$$reg),
+            as_FloatRegister($shift$$reg));
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl4I(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (URShiftVI src shift));
   ins_cost(INSN_COST);
   format %{ "ushl  $dst,$src,$shift\t# vector (4S)" %}
@@ -14008,7 +14784,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (LShiftVI src shift));
+  ins_cost(INSN_COST);
+  format %{ "shl    $dst, $src, $shift\t# vector (2S)" %}
+  ins_encode %{
+    __ shl(as_FloatRegister($dst$$reg), __ T2S,
+           as_FloatRegister($src$$reg),
+           (int)$shift$$constant & 31);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (LShiftVI src shift));
   ins_cost(INSN_COST);
   format %{ "shl    $dst, $src, $shift\t# vector (4S)" %}
@@ -14020,7 +14810,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (RShiftVI src shift));
+  ins_cost(INSN_COST);
+  format %{ "sshr    $dst, $src, $shift\t# vector (2S)" %}
+  ins_encode %{
+    __ sshr(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src$$reg),
+            -(int)$shift$$constant & 31);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (RShiftVI src shift));
   ins_cost(INSN_COST);
   format %{ "sshr    $dst, $src, $shift\t# vector (4S)" %}
@@ -14032,7 +14836,21 @@
   ins_pipe(pipe_class_default);
 %}
 
+instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
+  match(Set dst (URShiftVI src shift));
+  ins_cost(INSN_COST);
+  format %{ "ushr    $dst, $src, $shift\t# vector (2S)" %}
+  ins_encode %{
+    __ ushr(as_FloatRegister($dst$$reg), __ T2S,
+            as_FloatRegister($src$$reg),
+            -(int)$shift$$constant & 31);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 4);
   match(Set dst (URShiftVI src shift));
   ins_cost(INSN_COST);
   format %{ "ushr    $dst, $src, $shift\t# vector (4S)" %}
@@ -14045,6 +14863,7 @@
 %}
 
 instruct vsll2L(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (LShiftVL src shift));
   match(Set dst (RShiftVL src shift));
   ins_cost(INSN_COST);
@@ -14058,6 +14877,7 @@
 %}
 
 instruct vsrl2L(vecX dst, vecX src, vecX shift) %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (URShiftVL src shift));
   ins_cost(INSN_COST);
   format %{ "ushl  $dst,$src,$shift\t# vector (2D)" %}
@@ -14070,6 +14890,7 @@
 %}
 
 instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (LShiftVL src shift));
   ins_cost(INSN_COST);
   format %{ "shl    $dst, $src, $shift\t# vector (2D)" %}
@@ -14082,6 +14903,7 @@
 %}
 
 instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (RShiftVL src shift));
   ins_cost(INSN_COST);
   format %{ "sshr    $dst, $src, $shift\t# vector (2D)" %}
@@ -14094,6 +14916,7 @@
 %}
 
 instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{
+  predicate(n->as_Vector()->length() == 2);
   match(Set dst (URShiftVL src shift));
   ins_cost(INSN_COST);
   format %{ "ushr    $dst, $src, $shift\t# vector (2D)" %}
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -2055,6 +2055,9 @@
   INSN(negr,  1, 0b100000101110);
   INSN(notr,  1, 0b100000010110);
   INSN(addv,  0, 0b110001101110);
+  INSN(cls,   0, 0b100000010010);
+  INSN(clz,   1, 0b100000010010);
+  INSN(cnt,   0, 0b100000010110);
 
 #undef INSN
 
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -36,6 +36,7 @@
 class MacroAssembler: public Assembler {
   friend class LIR_Assembler;
 
+ public:
   using Assembler::mov;
   using Assembler::movi;
 
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -199,6 +199,12 @@
     UseCRC32Intrinsics = true;
   }
 
+  if (UseCRC32CIntrinsics) {
+    if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics))
+      warning("CRC32C intrinsics are not available on this CPU");
+    FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+  }
+
   if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) {
     if (FLAG_IS_DEFAULT(UseSHA)) {
       FLAG_SET_DEFAULT(UseSHA, true);
@@ -251,6 +257,10 @@
     UseBarriersForVolatile = (_cpuFeatures & CPU_DMB_ATOMICS) != 0;
   }
 
+  if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
+    UsePopCountInstruction = true;
+  }
+
 #ifdef COMPILER2
   if (FLAG_IS_DEFAULT(OptoScheduling)) {
     OptoScheduling = true;
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -191,6 +191,13 @@
     FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
   }
+
+  if (UseCRC32CIntrinsics) {
+    if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics))
+      warning("CRC32C intrinsics are not available on this CPU");
+    FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+  }
+
   // Adjust RTM (Restricted Transactional Memory) flags.
   if (!has_tcheck() && UseRTMLocking) {
     // Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -128,8 +128,11 @@
     faligndata_op3 = 0x36,
     flog3_op3    = 0x36,
     edge_op3     = 0x36,
+    fzero_op3    = 0x36,
     fsrc_op3     = 0x36,
+    fnot_op3     = 0x36,
     xmulx_op3    = 0x36,
+    crc32c_op3   = 0x36,
     impdep2_op3  = 0x37,
     stpartialf_op3 = 0x37,
     jmpl_op3     = 0x38,
@@ -231,7 +234,9 @@
 
     sha1_opf           = 0x141,
     sha256_opf         = 0x142,
-    sha512_opf         = 0x143
+    sha512_opf         = 0x143,
+
+    crc32c_opf         = 0x147
   };
 
   enum op5s {
@@ -600,6 +605,11 @@
     return x & ((1 << 10) - 1);
   }
 
+  // create a low12 __value__ (not a field) for a given a 32-bit constant
+  static int low12( int x ) {
+    return x & ((1 << 12) - 1);
+  }
+
   // AES crypto instructions supported only on certain processors
   static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); }
 
@@ -608,6 +618,9 @@
   static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); }
   static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); }
 
+  // CRC32C instruction supported only on certain processors
+  static void crc32c_only() { assert( VM_Version::has_crc32c(), "This instruction only works on SPARC with CRC32C"); }
+
   // instruction only in VIS1
   static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); }
 
@@ -1022,6 +1035,7 @@
 
   void nop() { emit_int32( op(branch_op) | op2(sethi_op2) ); }
 
+  void sw_count() { emit_int32( op(branch_op) | op2(sethi_op2) | 0x3f0 ); }
 
   // pp 202
 
@@ -1198,8 +1212,14 @@
 
   void faligndata( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(faligndata_op3) | fs1(s1, FloatRegisterImpl::D) | opf(faligndata_opf) | fs2(s2, FloatRegisterImpl::D)); }
 
+  void fzero( FloatRegisterImpl::Width w, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fzero_op3) | opf(0x62 - w)); }
+
   void fsrc2( FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fsrc_op3) | opf(0x7A - w) | fs2(s2, w)); }
 
+  void fnot1( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fnot_op3) | fs1(s1, w) | opf(0x6C - w)); }
+
+  void fpmerge( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(0x36) | fs1(s1, FloatRegisterImpl::S) | opf(0x4b) | fs2(s2, FloatRegisterImpl::S)); }
+
   void stpartialf( Register s1, Register s2, FloatRegister d, int ia = -1 ) { vis1_only(); emit_int32( op(ldst_op) | fd(d, FloatRegisterImpl::D) | op3(stpartialf_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); }
 
   //  VIS2 instructions
@@ -1224,6 +1244,10 @@
   void sha256() { sha256_only();  emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); }
   void sha512() { sha512_only();  emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); }
 
+  // CRC32C instruction
+
+  void crc32c( FloatRegister s1, FloatRegister s2, FloatRegister d ) { crc32c_only();  emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(crc32c_op3) | fs1(s1, FloatRegisterImpl::D) | opf(crc32c_opf) | fs2(s2, FloatRegisterImpl::D)); }
+
   // Creation
   Assembler(CodeBuffer* code) : AbstractAssembler(code) {
 #ifdef CHECK_DELAY
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -956,6 +956,7 @@
 
   int hi = (int)(value >> 32);
   int lo = (int)(value & ~0);
+  int bits_33to2 = (int)((value >> 2) & ~0);
   // (Matcher::isSimpleConstant64 knows about the following optimizations.)
   if (Assembler::is_simm13(lo) && value == lo) {
     or3(G0, lo, d);
@@ -964,6 +965,12 @@
     if (low10(lo) != 0)
       or3(d, low10(lo), d);
   }
+  else if ((hi >> 2) == 0) {
+    Assembler::sethi(bits_33to2, d);  // hardware version zero-extends to upper 32
+    sllx(d, 2, d);
+    if (low12(lo) != 0)
+      or3(d, low12(lo), d);
+  }
   else if (hi == -1) {
     Assembler::sethi(~lo, d);  // hardware version zero-extends to upper 32
     xor3(d, low10(lo) ^ ~low10(~0), d);
@@ -4351,3 +4358,52 @@
   cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop);
   nop(); // Separate short branches
 }
+
+/**
+ * Update CRC-32[C] with a byte value according to constants in table
+ *
+ * @param [in,out]crc   Register containing the crc.
+ * @param [in]val       Register containing the byte to fold into the CRC.
+ * @param [in]table     Register containing the table of crc constants.
+ *
+ * uint32_t crc;
+ * val = crc_table[(val ^ crc) & 0xFF];
+ * crc = val ^ (crc >> 8);
+ */
+void MacroAssembler::update_byte_crc32(Register crc, Register val, Register table) {
+  xor3(val, crc, val);
+  and3(val, 0xFF, val);
+  sllx(val, 2, val);
+  lduw(table, val, val);
+  srlx(crc, 8, crc);
+  xor3(val, crc, crc);
+}
+
+// Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros
+void MacroAssembler::reverse_bytes_32(Register src, Register dst, Register tmp) {
+  srlx(src, 24, dst);
+
+  sllx(src, 32+8, tmp);
+  srlx(tmp, 32+24, tmp);
+  sllx(tmp, 8, tmp);
+  or3(dst, tmp, dst);
+
+  sllx(src, 32+16, tmp);
+  srlx(tmp, 32+24, tmp);
+  sllx(tmp, 16, tmp);
+  or3(dst, tmp, dst);
+
+  sllx(src, 32+24, tmp);
+  srlx(tmp, 32, tmp);
+  or3(dst, tmp, dst);
+}
+
+void MacroAssembler::movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2) {
+  reverse_bytes_32(src, tmp1, tmp2);
+  movxtod(tmp1, dst);
+}
+
+void MacroAssembler::movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2) {
+  movdtox(src, tmp1);
+  reverse_bytes_32(tmp1, dst, tmp2);
+}
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -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
@@ -903,6 +903,10 @@
   inline void ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d);
   inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0);
 
+  // little-endian
+  inline void ldxl(Register s1, Register s2, Register d) { ldxa(s1, s2, ASI_PRIMARY_LITTLE, d); }
+  inline void ldfl(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { ldfa(w, s1, s2, ASI_PRIMARY_LITTLE, d); }
+
   // membar psuedo instruction.  takes into account target memory model.
   inline void membar( Assembler::Membar_mask_bits const7a );
 
@@ -1436,6 +1440,14 @@
   // Use BIS for zeroing
   void bis_zeroing(Register to, Register count, Register temp, Label& Ldone);
 
+  // Update CRC-32[C] with a byte value according to constants in table
+  void update_byte_crc32(Register crc, Register val, Register table);
+
+  // Reverse byte order of lower 32 bits, assuming upper 32 bits all zeros
+  void reverse_bytes_32(Register src, Register dst, Register tmp);
+  void movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2);
+  void movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2);
+
 #undef VIRTUAL
 };
 
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -4910,6 +4910,206 @@
       return start;
   }
 
+#define CHUNK_LEN   128          /* 128 x 8B = 1KB */
+#define CHUNK_K1    0x1307a0206  /* reverseBits(pow(x, CHUNK_LEN*8*8*3 - 32) mod P(x)) << 1 */
+#define CHUNK_K2    0x1a0f717c4  /* reverseBits(pow(x, CHUNK_LEN*8*8*2 - 32) mod P(x)) << 1 */
+#define CHUNK_K3    0x0170076fa  /* reverseBits(pow(x, CHUNK_LEN*8*8*1 - 32) mod P(x)) << 1 */
+
+  /**
+   *  Arguments:
+   *
+   * Inputs:
+   *   O0   - int   crc
+   *   O1   - byte* buf
+   *   O2   - int   len
+   *   O3   - int*  table
+   *
+   * Output:
+   *   O0   - int crc result
+   */
+  address generate_updateBytesCRC32C() {
+    assert(UseCRC32CIntrinsics, "need CRC32C instruction");
+
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C");
+    address start = __ pc();
+
+    const Register crc   = O0;  // crc
+    const Register buf   = O1;  // source java byte array address
+    const Register len   = O2;  // number of bytes
+    const Register table = O3;  // byteTable
+
+    Label L_crc32c_head, L_crc32c_aligned;
+    Label L_crc32c_parallel, L_crc32c_parallel_loop;
+    Label L_crc32c_serial, L_crc32c_x32_loop, L_crc32c_x8, L_crc32c_x8_loop;
+    Label L_crc32c_done, L_crc32c_tail, L_crc32c_return;
+
+    __ cmp_and_br_short(len, 0, Assembler::lessEqual, Assembler::pn, L_crc32c_return);
+
+    // clear upper 32 bits of crc
+    __ clruwu(crc);
+
+    __ and3(buf, 7, G4);
+    __ cmp_and_brx_short(G4, 0, Assembler::equal, Assembler::pt, L_crc32c_aligned);
+
+    __ mov(8, G1);
+    __ sub(G1, G4, G4);
+
+    // ------ process the misaligned head (7 bytes or less) ------
+    __ BIND(L_crc32c_head);
+
+    // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF];
+    __ ldub(buf, 0, G1);
+    __ update_byte_crc32(crc, G1, table);
+
+    __ inc(buf);
+    __ dec(len);
+    __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pn, L_crc32c_return);
+    __ dec(G4);
+    __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_head);
+
+    // ------ process the 8-byte-aligned body ------
+    __ BIND(L_crc32c_aligned);
+    __ nop();
+    __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pn, L_crc32c_tail);
+
+    // reverse the byte order of lower 32 bits to big endian, and move to FP side
+    __ movitof_revbytes(crc, F0, G1, G3);
+
+    __ set(CHUNK_LEN*8*4, G4);
+    __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pt, L_crc32c_serial);
+
+    // ------ process four 1KB chunks in parallel ------
+    __ BIND(L_crc32c_parallel);
+
+    __ fzero(FloatRegisterImpl::D, F2);
+    __ fzero(FloatRegisterImpl::D, F4);
+    __ fzero(FloatRegisterImpl::D, F6);
+
+    __ mov(CHUNK_LEN - 1, G4);
+    __ BIND(L_crc32c_parallel_loop);
+    // schedule ldf's ahead of crc32c's to hide the load-use latency
+    __ ldf(FloatRegisterImpl::D, buf, 0,            F8);
+    __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8,  F10);
+    __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12);
+    __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*24, F14);
+    __ crc32c(F0, F8,  F0);
+    __ crc32c(F2, F10, F2);
+    __ crc32c(F4, F12, F4);
+    __ crc32c(F6, F14, F6);
+    __ inc(buf, 8);
+    __ dec(G4);
+    __ cmp_and_br_short(G4, 0, Assembler::greater, Assembler::pt, L_crc32c_parallel_loop);
+
+    __ ldf(FloatRegisterImpl::D, buf, 0,            F8);
+    __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*8,  F10);
+    __ ldf(FloatRegisterImpl::D, buf, CHUNK_LEN*16, F12);
+    __ crc32c(F0, F8,  F0);
+    __ crc32c(F2, F10, F2);
+    __ crc32c(F4, F12, F4);
+
+    __ inc(buf, CHUNK_LEN*24);
+    __ ldfl(FloatRegisterImpl::D, buf, G0, F14);  // load in little endian
+    __ inc(buf, 8);
+
+    __ prefetch(buf, 0,            Assembler::severalReads);
+    __ prefetch(buf, CHUNK_LEN*8,  Assembler::severalReads);
+    __ prefetch(buf, CHUNK_LEN*16, Assembler::severalReads);
+    __ prefetch(buf, CHUNK_LEN*24, Assembler::severalReads);
+
+    // move to INT side, and reverse the byte order of lower 32 bits to little endian
+    __ movftoi_revbytes(F0, O4, G1, G4);
+    __ movftoi_revbytes(F2, O5, G1, G4);
+    __ movftoi_revbytes(F4, G5, G1, G4);
+
+    // combine the results of 4 chunks
+    __ set64(CHUNK_K1, G3, G1);
+    __ xmulx(O4, G3, O4);
+    __ set64(CHUNK_K2, G3, G1);
+    __ xmulx(O5, G3, O5);
+    __ set64(CHUNK_K3, G3, G1);
+    __ xmulx(G5, G3, G5);
+
+    __ movdtox(F14, G4);
+    __ xor3(O4, O5, O5);
+    __ xor3(G5, O5, O5);
+    __ xor3(G4, O5, O5);
+
+    // reverse the byte order to big endian, via stack, and move to FP side
+    __ add(SP, -8, G1);
+    __ srlx(G1, 3, G1);
+    __ sllx(G1, 3, G1);
+    __ stx(O5, G1, G0);
+    __ ldfl(FloatRegisterImpl::D, G1, G0, F2);  // load in little endian
+
+    __ crc32c(F6, F2, F0);
+
+    __ set(CHUNK_LEN*8*4, G4);
+    __ sub(len, G4, len);
+    __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_parallel);
+    __ nop();
+    __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_done);
+
+    __ BIND(L_crc32c_serial);
+
+    __ mov(32, G4);
+    __ cmp_and_br_short(len, G4, Assembler::less, Assembler::pn, L_crc32c_x8);
+
+    // ------ process 32B chunks ------
+    __ BIND(L_crc32c_x32_loop);
+    __ ldf(FloatRegisterImpl::D, buf, 0, F2);
+    __ inc(buf, 8);
+    __ crc32c(F0, F2, F0);
+    __ ldf(FloatRegisterImpl::D, buf, 0, F2);
+    __ inc(buf, 8);
+    __ crc32c(F0, F2, F0);
+    __ ldf(FloatRegisterImpl::D, buf, 0, F2);
+    __ inc(buf, 8);
+    __ crc32c(F0, F2, F0);
+    __ ldf(FloatRegisterImpl::D, buf, 0, F2);
+    __ inc(buf, 8);
+    __ crc32c(F0, F2, F0);
+    __ dec(len, 32);
+    __ cmp_and_br_short(len, G4, Assembler::greaterEqual, Assembler::pt, L_crc32c_x32_loop);
+
+    __ BIND(L_crc32c_x8);
+    __ nop();
+    __ cmp_and_br_short(len, 8, Assembler::less, Assembler::pt, L_crc32c_done);
+
+    // ------ process 8B chunks ------
+    __ BIND(L_crc32c_x8_loop);
+    __ ldf(FloatRegisterImpl::D, buf, 0, F2);
+    __ inc(buf, 8);
+    __ crc32c(F0, F2, F0);
+    __ dec(len, 8);
+    __ cmp_and_br_short(len, 8, Assembler::greaterEqual, Assembler::pt, L_crc32c_x8_loop);
+
+    __ BIND(L_crc32c_done);
+
+    // move to INT side, and reverse the byte order of lower 32 bits to little endian
+    __ movftoi_revbytes(F0, crc, G1, G3);
+
+    __ cmp_and_br_short(len, 0, Assembler::equal, Assembler::pt, L_crc32c_return);
+
+    // ------ process the misaligned tail (7 bytes or less) ------
+    __ BIND(L_crc32c_tail);
+
+    // crc = (crc >>> 8) ^ byteTable[(crc ^ b) & 0xFF];
+    __ ldub(buf, 0, G1);
+    __ update_byte_crc32(crc, G1, table);
+
+    __ inc(buf);
+    __ dec(len);
+    __ cmp_and_br_short(len, 0, Assembler::greater, Assembler::pt, L_crc32c_tail);
+
+    __ BIND(L_crc32c_return);
+    __ nop();
+    __ retl();
+    __ delayed()->nop();
+
+    return start;
+  }
+
   void generate_initial() {
     // Generates all stubs and initializes the entry points
 
@@ -5001,6 +5201,11 @@
       StubRoutines::_sha512_implCompress   = generate_sha512_implCompress(false, "sha512_implCompress");
       StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true,  "sha512_implCompressMB");
     }
+
+    // generate CRC32C intrinsic code
+    if (UseCRC32CIntrinsics) {
+      StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
+    }
   }
 
 
--- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, 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
@@ -41,7 +41,7 @@
 enum /* platform_dependent_constants */ {
   // %%%%%%%% May be able to shrink this a lot
   code_size1 = 20000,           // simply increase if too small (assembler will crash if too small)
-  code_size2 = 23000            // simply increase if too small (assembler will crash if too small)
+  code_size2 = 24000            // simply increase if too small (assembler will crash if too small)
 };
 
 class Sparc {
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -230,7 +230,7 @@
   assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 
   char buf[512];
-  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
                (has_hardware_popc() ? ", popc" : ""),
                (has_vis1() ? ", vis1" : ""),
@@ -242,6 +242,7 @@
                (has_sha1() ? ", sha1" : ""),
                (has_sha256() ? ", sha256" : ""),
                (has_sha512() ? ", sha512" : ""),
+               (has_crc32c() ? ", crc32c" : ""),
                (is_ultra3() ? ", ultra3" : ""),
                (is_sun4v() ? ", sun4v" : ""),
                (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
@@ -363,6 +364,23 @@
     }
   }
 
+  // SPARC T4 and above should have support for CRC32C instruction
+  if (has_crc32c()) {
+    if (UseVIS > 2) { // CRC32C intrinsics use VIS3 instructions
+      if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
+        FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
+      }
+    } else {
+      if (UseCRC32CIntrinsics) {
+        warning("SPARC CRC32C intrinsics require VIS3 instruction support. Intrinsics will be disabled.");
+        FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+      }
+    }
+  } else if (UseCRC32CIntrinsics) {
+    warning("CRC32C instruction is not available on this CPU");
+    FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+  }
+
   if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
     (cache_line_size > ContendedPaddingWidth))
     ContendedPaddingWidth = cache_line_size;
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -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
@@ -53,7 +53,8 @@
     aes_instructions     = 19,
     sha1_instruction     = 20,
     sha256_instruction   = 21,
-    sha512_instruction   = 22
+    sha512_instruction   = 22,
+    crc32c_instruction   = 23
   };
 
   enum Feature_Flag_Set {
@@ -83,6 +84,7 @@
     sha1_instruction_m      = 1 << sha1_instruction,
     sha256_instruction_m    = 1 << sha256_instruction,
     sha512_instruction_m    = 1 << sha512_instruction,
+    crc32c_instruction_m    = 1 << crc32c_instruction,
 
     generic_v8_m        = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
     generic_v9_m        = generic_v8_m | v9_instructions_m,
@@ -141,6 +143,7 @@
   static bool has_sha1()                { return (_features & sha1_instruction_m) != 0; }
   static bool has_sha256()              { return (_features & sha256_instruction_m) != 0; }
   static bool has_sha512()              { return (_features & sha512_instruction_m) != 0; }
+  static bool has_crc32c()              { return (_features & crc32c_instruction_m) != 0; }
 
   static bool supports_compare_and_exchange()
                                         { return has_v9(); }
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -699,6 +699,12 @@
     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
   }
 
+  if (UseCRC32CIntrinsics) {
+    if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics))
+      warning("CRC32C intrinsics are not available on this CPU");
+    FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+  }
+
   // Adjust RTM (Restricted Transactional Memory) flags
   if (!supports_rtm() && UseRTMLocking) {
     // Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -363,6 +363,11 @@
 #endif
   if (av & AV_SPARC_CBCOND)       features |= cbcond_instructions_m;
 
+#ifndef AV_SPARC_CRC32C
+#define AV_SPARC_CRC32C 0x20000000  /* crc32c instruction supported */
+#endif
+  if (av & AV_SPARC_CRC32C)       features |= crc32c_instruction_m;
+
 #ifndef AV_SPARC_AES
 #define AV_SPARC_AES 0x00020000  /* aes instrs supported */
 #endif
--- a/hotspot/src/share/vm/ci/ciField.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/ci/ciField.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -186,6 +186,10 @@
   // Even if general trusting is disabled, trust system-built closures in these packages.
   if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke"))
     return true;
+  // Trust VM anonymous classes. They are private API (sun.misc.Unsafe) and can't be serialized,
+  // so there is no hacking of finals going on with them.
+  if (holder->is_anonymous())
+    return true;
   return TrustFinalNonStaticFields;
 }
 
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -58,6 +58,7 @@
   _nonstatic_field_size = ik->nonstatic_field_size();
   _has_nonstatic_fields = ik->has_nonstatic_fields();
   _has_default_methods = ik->has_default_methods();
+  _is_anonymous = ik->is_anonymous();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
   _has_injected_fields = -1;
   _implementor = NULL; // we will fill these lazily
@@ -101,6 +102,7 @@
   _has_nonstatic_fields = false;
   _nonstatic_fields = NULL;
   _has_injected_fields = -1;
+  _is_anonymous = false;
   _loader = loader;
   _protection_domain = protection_domain;
   _is_shared = false;
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -53,6 +53,7 @@
   bool                   _has_subklass;
   bool                   _has_nonstatic_fields;
   bool                   _has_default_methods;
+  bool                   _is_anonymous;
 
   ciFlags                _flags;
   jint                   _nonstatic_field_size;
@@ -179,6 +180,10 @@
     return _has_default_methods;
   }
 
+  bool is_anonymous() {
+    return _is_anonymous;
+  }
+
   ciInstanceKlass* get_canonical_holder(int offset);
   ciField* get_field_by_offset(int field_offset, bool is_static);
   ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static);
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -863,6 +863,12 @@
    do_name(     updateByteBuffer_name,                           "updateByteBuffer")                                    \
    do_signature(updateByteBuffer_signature,                      "(IJII)I")                                             \
                                                                                                                         \
+  /* support for java.util.zip.CRC32C */                                                                                \
+  do_class(java_util_zip_CRC32C,          "java/util/zip/CRC32C")                                                       \
+  do_intrinsic(_updateBytesCRC32C,         java_util_zip_CRC32C,  updateBytes_name, updateBytes_signature,       F_S)   \
+  do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \
+   do_name(     updateDirectByteBuffer_name,                     "updateDirectByteBuffer")                              \
+                                                                                                                        \
   /* support for sun.misc.Unsafe */                                                                                     \
   do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
                                                                                                                         \
--- a/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -962,6 +962,7 @@
                  (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre")  == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "updateBytesCRC32C") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
--- a/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -197,7 +197,7 @@
   CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
     return generate_method_call(method_id, true, false);
   }
-  Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static);
+  Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 
   Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
   Node* make_string_method_node(int opcode, Node* str1, Node* str2);
@@ -291,6 +291,9 @@
   bool inline_updateCRC32();
   bool inline_updateBytesCRC32();
   bool inline_updateByteBufferCRC32();
+  Node* get_table_from_crc32c_class(ciInstanceKlass *crc32c_class);
+  bool inline_updateBytesCRC32C();
+  bool inline_updateDirectByteBufferCRC32C();
   bool inline_multiplyToLen();
   bool inline_squareToLen();
   bool inline_mulAdd();
@@ -539,6 +542,11 @@
     if (!UseCRC32Intrinsics) return NULL;
     break;
 
+  case vmIntrinsics::_updateBytesCRC32C:
+  case vmIntrinsics::_updateDirectByteBufferCRC32C:
+    if (!UseCRC32CIntrinsics) return NULL;
+    break;
+
   case vmIntrinsics::_incrementExactI:
   case vmIntrinsics::_addExactI:
     if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL;
@@ -947,6 +955,11 @@
   case vmIntrinsics::_updateByteBufferCRC32:
     return inline_updateByteBufferCRC32();
 
+  case vmIntrinsics::_updateBytesCRC32C:
+    return inline_updateBytesCRC32C();
+  case vmIntrinsics::_updateDirectByteBufferCRC32C:
+    return inline_updateDirectByteBufferCRC32C();
+
   case vmIntrinsics::_profileBoolean:
     return inline_profileBoolean();
   case vmIntrinsics::_isCompileConstant:
@@ -5536,6 +5549,106 @@
   return true;
 }
 
+//------------------------------get_table_from_crc32c_class-----------------------
+Node * LibraryCallKit::get_table_from_crc32c_class(ciInstanceKlass *crc32c_class) {
+  Node* table = load_field_from_object(NULL, "byteTable", "[I", /*is_exact*/ false, /*is_static*/ true, crc32c_class);
+  assert (table != NULL, "wrong version of java.util.zip.CRC32C");
+
+  return table;
+}
+
+//------------------------------inline_updateBytesCRC32C-----------------------
+//
+// Calculate CRC32C for byte[] array.
+// int java.util.zip.CRC32C.updateBytes(int crc, byte[] buf, int off, int end)
+//
+bool LibraryCallKit::inline_updateBytesCRC32C() {
+  assert(UseCRC32CIntrinsics, "need CRC32C instruction support");
+  assert(callee()->signature()->size() == 4, "updateBytes has 4 parameters");
+  assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded");
+  // no receiver since it is a static method
+  Node* crc     = argument(0); // type: int
+  Node* src     = argument(1); // type: oop
+  Node* offset  = argument(2); // type: int
+  Node* end     = argument(3); // type: int
+
+  Node* length = _gvn.transform(new SubINode(end, offset));
+
+  const Type* src_type = src->Value(&_gvn);
+  const TypeAryPtr* top_src = src_type->isa_aryptr();
+  if (top_src  == NULL || top_src->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+
+  // Figure out the size and type of the elements we will be copying.
+  BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (src_elem != T_BYTE) {
+    return false;
+  }
+
+  // 'src_start' points to src array + scaled offset
+  Node* src_start = array_element_address(src, offset, src_elem);
+
+  // static final int[] byteTable in class CRC32C
+  Node* table = get_table_from_crc32c_class(callee()->holder());
+  Node* table_start = array_element_address(table, intcon(0), T_INT);
+
+  // We assume that range check is done by caller.
+  // TODO: generate range check (offset+length < src.length) in debug VM.
+
+  // Call the stub.
+  address stubAddr = StubRoutines::updateBytesCRC32C();
+  const char *stubName = "updateBytesCRC32C";
+
+  Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 crc, src_start, length, table_start);
+  Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+  return true;
+}
+
+//------------------------------inline_updateDirectByteBufferCRC32C-----------------------
+//
+// Calculate CRC32C for DirectByteBuffer.
+// int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int end)
+//
+bool LibraryCallKit::inline_updateDirectByteBufferCRC32C() {
+  assert(UseCRC32CIntrinsics, "need CRC32C instruction support");
+  assert(callee()->signature()->size() == 5, "updateDirectByteBuffer has 4 parameters and one is long");
+  assert(callee()->holder()->is_loaded(), "CRC32C class must be loaded");
+  // no receiver since it is a static method
+  Node* crc     = argument(0); // type: int
+  Node* src     = argument(1); // type: long
+  Node* offset  = argument(3); // type: int
+  Node* end     = argument(4); // type: int
+
+  Node* length = _gvn.transform(new SubINode(end, offset));
+
+  src = ConvL2X(src);  // adjust Java long to machine word
+  Node* base = _gvn.transform(new CastX2PNode(src));
+  offset = ConvI2X(offset);
+
+  // 'src_start' points to src array + scaled offset
+  Node* src_start = basic_plus_adr(top(), base, offset);
+
+  // static final int[] byteTable in class CRC32C
+  Node* table = get_table_from_crc32c_class(callee()->holder());
+  Node* table_start = array_element_address(table, intcon(0), T_INT);
+
+  // Call the stub.
+  address stubAddr = StubRoutines::updateBytesCRC32C();
+  const char *stubName = "updateBytesCRC32C";
+
+  Node* call = make_runtime_call(RC_LEAF, OptoRuntime::updateBytesCRC32C_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 crc, src_start, length, table_start);
+  Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+  return true;
+}
+
 //----------------------------inline_reference_get----------------------------
 // public T java.lang.ref.Reference.get();
 bool LibraryCallKit::inline_reference_get() {
@@ -5571,18 +5684,28 @@
 
 
 Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString,
-                                              bool is_exact=true, bool is_static=false) {
-
-  const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
-  assert(tinst != NULL, "obj is null");
-  assert(tinst->klass()->is_loaded(), "obj is not loaded");
-  assert(!is_exact || tinst->klass_is_exact(), "klass not exact");
-
-  ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName),
-                                                                          ciSymbol::make(fieldTypeString),
-                                                                          is_static);
+                                              bool is_exact=true, bool is_static=false,
+                                              ciInstanceKlass * fromKls=NULL) {
+  if (fromKls == NULL) {
+    const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
+    assert(tinst != NULL, "obj is null");
+    assert(tinst->klass()->is_loaded(), "obj is not loaded");
+    assert(!is_exact || tinst->klass_is_exact(), "klass not exact");
+    fromKls = tinst->klass()->as_instance_klass();
+  } else {
+    assert(is_static, "only for static field access");
+  }
+  ciField* field = fromKls->get_field_by_name(ciSymbol::make(fieldName),
+                                              ciSymbol::make(fieldTypeString),
+                                              is_static);
+
+  assert (field != NULL, "undefined field");
   if (field == NULL) return (Node *) NULL;
-  assert (field != NULL, "undefined field");
+
+  if (is_static) {
+    const TypeInstPtr* tip = TypeInstPtr::make(fromKls->java_mirror());
+    fromObj = makecon(tip);
+  }
 
   // Next code  copied from Parse::do_get_xxx():
 
--- a/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -851,6 +851,29 @@
   return TypeFunc::make(domain, range);
 }
 
+/**
+ * int updateBytesCRC32C(int crc, byte* buf, int len, int* table)
+ */
+const TypeFunc* OptoRuntime::updateBytesCRC32C_Type() {
+  // create input type (domain)
+  int num_args      = 4;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypeInt::INT;        // crc
+  fields[argp++] = TypePtr::NOTNULL;    // buf
+  fields[argp++] = TypeInt::INT;        // len
+  fields[argp++] = TypePtr::NOTNULL;    // table
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypeInt::INT; // crc result
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
+  return TypeFunc::make(domain, range);
+}
+
 // for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning int
 const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
   // create input type (domain)
--- a/hotspot/src/share/vm/opto/runtime.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/opto/runtime.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -319,6 +319,7 @@
   static const TypeFunc* ghash_processBlocks_Type();
 
   static const TypeFunc* updateBytesCRC32_Type();
+  static const TypeFunc* updateBytesCRC32C_Type();
 
   // leaf on stack replacement interpreter accessor types
   static const TypeFunc* osr_end_Type();
--- a/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -183,13 +183,20 @@
       break;
     }
 
+    // Ignore nodes with non-primitive type.
+    BasicType bt;
+    if (n->is_Mem()) {
+      bt = n->as_Mem()->memory_type();
+    } else {
+      bt = n->bottom_type()->basic_type();
+    }
+    if (is_java_primitive(bt) == false) {
+      ignored_loop_nodes[i] = n->_idx;
+      continue;
+    }
+
     if (n->is_Mem()) {
       MemNode* current = n->as_Mem();
-      BasicType bt = current->memory_type();
-      if (is_java_primitive(bt) == false) {
-        ignored_loop_nodes[i] = n->_idx;
-        continue;
-      }
       Node* adr = n->in(MemNode::Address);
       Node* n_ctrl = _phase->get_ctrl(adr);
 
@@ -231,11 +238,12 @@
 
       BasicType bt;
       Node* n = lpt()->_body.at(i);
-      if (n->is_Store()) {
+      if (n->is_Mem()) {
         bt = n->as_Mem()->memory_type();
       } else {
         bt = n->bottom_type()->basic_type();
       }
+      if (is_java_primitive(bt) == false) continue;
 
       int cur_max_vector = Matcher::max_vector_size(bt);
 
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -3753,8 +3753,12 @@
   if (TieredCompilation) {
     set_tiered_flags();
   } else {
-    // Check if the policy is valid. Policies 0 and 1 are valid for non-tiered setup.
-    if (CompilationPolicyChoice >= 2) {
+    int max_compilation_policy_choice = 1;
+#ifdef COMPILER2
+    max_compilation_policy_choice = 2;
+#endif
+    // Check if the policy is valid.
+    if (CompilationPolicyChoice >= max_compilation_policy_choice) {
       vm_exit_during_initialization(
         "Incompatible compilation policy selected", NULL);
     }
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -512,7 +512,7 @@
     RegisterMap reg_map(thread, false);
     javaVFrame* triggerVF = thread->last_java_vframe(&reg_map);
     // triggerVF is the frame that triggered its counter
-    RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m);
+    RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m());
 
     if (first->top_method()->code() != NULL) {
       // called obsolete method/nmethod -- no need to recompile
@@ -557,8 +557,8 @@
     if( !next )               // No next frame up the stack?
       break;                  // Then compile with current frame
 
-    methodHandle m = current->top_method();
-    methodHandle next_m = next->top_method();
+    Method* m = current->top_method();
+    Method* next_m = next->top_method();
 
     if (TraceCompilationPolicy && Verbose) {
       tty->print("[caller: ");
@@ -644,7 +644,7 @@
     if (TraceCompilationPolicy && Verbose) {
       tty->print("\n\t     check caller: ");
       next_m->print_short_name(tty);
-      tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m()), next_m->code_size());
+      tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", p2i((address)next_m), next_m->code_size());
     }
 
     current = next;
--- a/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -848,6 +848,9 @@
   product(bool, UseCRC32Intrinsics, false,                                  \
           "use intrinsics for java.util.zip.CRC32")                         \
                                                                             \
+  product(bool, UseCRC32CIntrinsics, false,                                 \
+          "use intrinsics for java.util.zip.CRC32C")                        \
+                                                                            \
   develop(bool, TraceCallFixup, false,                                      \
           "Trace all call fixups")                                          \
                                                                             \
--- a/hotspot/src/share/vm/runtime/rframe.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/rframe.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -52,12 +52,12 @@
 : RFrame(fr, thread, callee) {
   RegisterMap map(thread, false);
   _vf     = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread));
-  _method = methodHandle(thread, _vf->method());
+  _method = _vf->method();
   assert(   _vf->is_interpreted_frame(), "must be interpreted");
   init();
 }
 
-InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m)
+InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, Method* m)
 : RFrame(fr, thread, NULL) {
   RegisterMap map(thread, false);
   _vf     = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread));
@@ -140,8 +140,8 @@
   _nm = compiledVFrame::cast(vf)->code();
   vf = vf->top();
   _vf = javaVFrame::cast(vf);
-  _method = methodHandle(thread(), CodeCache::find_nmethod(_fr.pc())->method());
-  assert(_method(), "should have found a method");
+  _method = CodeCache::find_nmethod(_fr.pc())->method();
+  assert(_method, "should have found a method");
 #ifndef PRODUCT
   _invocations = _method->compiled_invocation_count();
 #endif
--- a/hotspot/src/share/vm/runtime/rframe.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/rframe.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -60,7 +60,7 @@
   frame fr() const                        { return _fr; }
   JavaThread* thread() const              { return _thread; }
   virtual int cost() const = 0;           // estimated inlining cost (size)
-  virtual methodHandle top_method() const  = 0;
+  virtual Method* top_method() const  = 0;
   virtual javaVFrame* top_vframe() const = 0;
   virtual nmethod* nm() const             { ShouldNotCallThis(); return NULL; }
 
@@ -79,7 +79,7 @@
  protected:
   nmethod*    _nm;
   javaVFrame* _vf;                        // top vframe; may be NULL (for most recent frame)
-  methodHandle _method;                   // top method
+  Method* _method;                        // top method
 
   CompiledRFrame(frame fr, JavaThread* thread, RFrame*const  callee);
   void init();
@@ -88,7 +88,7 @@
  public:
   CompiledRFrame(frame fr, JavaThread* thread); // for nmethod triggering its counter (callee == NULL)
   bool is_compiled() const                 { return true; }
-  methodHandle top_method() const          { return _method; }
+  Method* top_method() const               { return _method; }
   javaVFrame* top_vframe() const           { return _vf; }
   nmethod* nm() const                      { return _nm; }
   int cost() const;
@@ -98,16 +98,16 @@
 class InterpretedRFrame : public RFrame {    // interpreter frame
  protected:
   javaVFrame* _vf;                           // may be NULL (for most recent frame)
-  methodHandle   _method;
+  Method* _method;
 
   InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const  callee);
   void init();
   friend class RFrame;
 
  public:
-  InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m); // constructor for method triggering its invocation counter
+  InterpretedRFrame(frame fr, JavaThread* thread, Method* m); // constructor for method triggering its invocation counter
   bool is_interpreted() const                { return true; }
-  methodHandle top_method() const            { return _method; }
+  Method* top_method() const                 { return _method; }
   javaVFrame* top_vframe() const             { return _vf; }
   int cost() const;
   void print();
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -137,6 +137,8 @@
 address StubRoutines::_updateBytesCRC32 = NULL;
 address StubRoutines::_crc_table_adr = NULL;
 
+address StubRoutines::_updateBytesCRC32C = NULL;
+
 address StubRoutines::_multiplyToLen = NULL;
 address StubRoutines::_squareToLen = NULL;
 address StubRoutines::_mulAdd = NULL;
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp	Wed Jul 05 20:41:30 2017 +0200
@@ -197,6 +197,8 @@
   static address _updateBytesCRC32;
   static address _crc_table_adr;
 
+  static address _updateBytesCRC32C;
+
   static address _multiplyToLen;
   static address _squareToLen;
   static address _mulAdd;
@@ -359,6 +361,8 @@
   static address updateBytesCRC32()    { return _updateBytesCRC32; }
   static address crc_table_addr()      { return _crc_table_adr; }
 
+  static address updateBytesCRC32C()   { return _updateBytesCRC32C; }
+
   static address multiplyToLen()       {return _multiplyToLen; }
   static address squareToLen()         {return _squareToLen; }
   static address mulAdd()              {return _mulAdd; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -830,6 +830,7 @@
      static_field(StubRoutines,                _ghash_processBlocks,                          address)                               \
      static_field(StubRoutines,                _updateBytesCRC32,                             address)                               \
      static_field(StubRoutines,                _crc_table_adr,                                address)                               \
+     static_field(StubRoutines,                _updateBytesCRC32C,                            address)                               \
      static_field(StubRoutines,                _multiplyToLen,                                address)                               \
      static_field(StubRoutines,                _squareToLen,                                  address)                               \
      static_field(StubRoutines,                _mulAdd,                                       address)                               \
--- a/hotspot/test/TEST.groups	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/TEST.groups	Wed Jul 05 20:41:30 2017 +0200
@@ -147,12 +147,16 @@
   gc/survivorAlignment \
   gc/TestGCLogRotationViaJcmd.java \
   runtime/InternalApi/ThreadCpuTimesDeadlock.java \
+  runtime/NMT/JcmdSummaryDiff.java \
+  runtime/RedefineTests/RedefineAnnotations.java
   serviceability/sa/jmap-hashcode/Test8028623.java \
   serviceability/threads/TestFalseDeadLock.java \
   compiler/codecache/jmx \
   compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java \
   compiler/rangechecks/TestRangeCheckSmearing.java \
-  serviceability/dcmd
+  compiler/whitebox/DeoptimizeMultipleOSRTest.java \
+  serviceability/dcmd \
+  testlibrary_tests/whitebox/vm_flags
 
 # Compact 2 adds full VM tests
 compact2 = \
--- a/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/CodeCacheUtils.java	Wed Jul 05 20:41:30 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 import java.lang.management.MemoryPoolMXBean;
 import javax.management.Notification;
@@ -80,19 +81,42 @@
     }
 
     /**
-     * A "non-nmethods" code heap is used by interpreter during bytecode
-     * execution, thus, it can't be predicted if this code heap usage will be
-     * increased or not. Same goes for 'All'.
+     * Checks if the usage of the code heap corresponding to 'btype' can be
+     * predicted at runtime if we disable compilation. The usage of the
+     * 'NonNMethod' code heap can not be predicted because we generate adapters
+     * and buffers at runtime. The 'MethodNonProfiled' code heap is also not
+     * predictable because we may generate compiled versions of method handle
+     * intrinsics while resolving methods at runtime. Same applies to 'All'.
      *
      * @param btype BlobType to be checked
      * @return boolean value, true if respective code heap is predictable
      */
     public static boolean isCodeHeapPredictable(BlobType btype) {
-        return btype == BlobType.MethodNonProfiled
-                || btype == BlobType.MethodProfiled;
+        return btype == BlobType.MethodProfiled;
     }
 
-    public static void disableCollectionUsageThresholds(){
+    /**
+     * Verifies that 'newValue' is equal to 'oldValue' if usage of the
+     * corresponding code heap is predictable. Checks the weaker condition
+     * 'newValue >= oldValue' if usage is not predictable because intermediate
+     * allocations may happen.
+     *
+     * @param btype BlobType of the code heap to be checked
+     * @param newValue New value to be verified
+     * @param oldValue Old value to be verified
+     * @param msg Error message if verification fails
+     */
+    public static void assertEQorGTE(BlobType btype, long newValue, long oldValue, String msg) {
+        if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
+            // Usage is predictable, check strong == condition
+            Asserts.assertEQ(newValue, oldValue, msg);
+        } else {
+            // Usage is not predictable, check weaker >= condition
+            Asserts.assertGTE(newValue, oldValue, msg);
+        }
+    }
+
+    public static void disableCollectionUsageThresholds() {
         BlobType.getAvailable().stream()
                 .map(BlobType::getMemoryPool)
                 .filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported)
--- a/hotspot/test/compiler/codecache/jmx/GetUsageTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/GetUsageTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -52,10 +52,8 @@
 
     public static void main(String[] args) throws Exception {
         for (BlobType btype : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
-                for (int allocSize = 10; allocSize < 100000; allocSize *= 10) {
-                    new GetUsageTest(btype, allocSize).runTest();
-                }
+            for (int allocSize = 10; allocSize < 100000; allocSize *= 10) {
+                new GetUsageTest(btype, allocSize).runTest();
             }
         }
     }
@@ -87,13 +85,15 @@
             for (MemoryPoolMXBean entry : predictableBeans) {
                 long diff = current.get(entry) - initial.get(entry);
                 if (entry.equals(btype.getMemoryPool())) {
-                    Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate,
-                            String.format("Pool %s usage increase was reported "
-                                    + "unexpectedly as increased by %d using "
-                                    + "allocation size %d", entry.getName(),
-                                    diff, allocateSize));
+                    if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
+                        Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate,
+                                String.format("Pool %s usage increase was reported "
+                                        + "unexpectedly as increased by %d using "
+                                        + "allocation size %d", entry.getName(),
+                                        diff, allocateSize));
+                    }
                 } else {
-                    Asserts.assertEQ(diff, 0L,
+                    CodeCacheUtils.assertEQorGTE(btype, diff, 0L,
                             String.format("Pool %s usage changed unexpectedly while"
                                     + " trying to increase: %s using allocation "
                                     + "size %d", entry.getName(),
--- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -52,9 +52,7 @@
 
     public static void main(String[] args) {
         for (BlobType btype : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
-                new PeakUsageTest(btype).runTest();
-            }
+            new PeakUsageTest(btype).runTest();
         }
     }
 
@@ -65,7 +63,7 @@
                 CodeCacheUtils.ALLOCATION_SIZE, btype.id);
         long newPeakUsage = bean.getPeakUsage().getUsed();
         try {
-            Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(),
+            CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getUsage().getUsed(),
                     "Peak usage does not match usage after allocation for "
                     + bean.getName());
         } finally {
@@ -73,18 +71,18 @@
                 CodeCacheUtils.WB.freeCodeBlob(addr);
             }
         }
-        Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(),
+        CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getPeakUsage().getUsed(),
                 "Code cache peak usage has changed after usage decreased for "
                 + bean.getName());
         bean.resetPeakUsage();
-        Asserts.assertEQ(bean.getPeakUsage().getUsed(),
+        CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(),
                 bean.getUsage().getUsed(),
                 "Code cache peak usage is not equal to usage after reset for "
                 + bean.getName());
         long addr2 = CodeCacheUtils.WB.allocateCodeBlob(
                 CodeCacheUtils.ALLOCATION_SIZE, btype.id);
         try {
-            Asserts.assertEQ(bean.getPeakUsage().getUsed(),
+            CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(),
                     bean.getUsage().getUsed(),
                     "Code cache peak usage is not equal to usage after fresh "
                     + "allocation for " + bean.getName());
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -97,13 +97,11 @@
             return false;
         });
         for (BlobType bt : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
-                int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
-                Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
-                        expectedNotificationsAmount, String.format("Unexpected "
-                                + "amount of notifications for pool: %s",
-                                bt.getMemoryPool().getName()));
-            }
+            int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
+            CodeCacheUtils.assertEQorGTE(btype, counters.get(bt.getMemoryPool().getName()).get(),
+                    expectedNotificationsAmount, String.format("Unexpected "
+                            + "amount of notifications for pool: %s",
+                            bt.getMemoryPool().getName()));
         }
         try {
             ((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
--- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -54,9 +54,7 @@
 
     public static void main(String[] args) {
         for (BlobType bt : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
-                new ThresholdNotificationsTest(bt).runTest();
-            }
+            new ThresholdNotificationsTest(bt).runTest();
         }
     }
 
@@ -92,7 +90,9 @@
         }
         Asserts.assertTrue(
                 Utils.waitForCondition(
-                        () -> counter == iterationsCount, WAIT_TIME),
+                        () -> (CodeCacheUtils.isCodeHeapPredictable(btype) ?
+                                (counter == iterationsCount) : (counter >= iterationsCount)),
+                        WAIT_TIME),
                 "Couldn't receive expected notifications count");
         try {
             ((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
--- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -51,13 +51,9 @@
     }
 
     public static void main(String[] args) {
-        int iterationsCount =
-            Integer.getInteger("jdk.test.lib.iterations", 1);
+        int iterationsCount = Integer.getInteger("jdk.test.lib.iterations", 1);
         for (BlobType btype : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
-                new UsageThresholdExceededTest(btype, iterationsCount)
-                        .runTest();
-            }
+            new UsageThresholdExceededTest(btype, iterationsCount).runTest();
         }
     }
 
@@ -67,9 +63,8 @@
         for (int i = 0; i < iterations; i++) {
             CodeCacheUtils.hitUsageThreshold(bean, btype);
         }
-        Asserts.assertEQ(bean.getUsageThresholdCount(), oldValue + iterations,
+        CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), oldValue + iterations,
                 "Unexpected threshold usage count");
-        System.out.printf("INFO: Scenario finished successfully for %s%n",
-                bean.getName());
+        System.out.printf("INFO: Scenario finished successfully for %s%n", bean.getName());
     }
 }
--- a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -27,7 +27,6 @@
 
 /*
  * @test UsageThresholdIncreasedTest
- * @ignore 8129937
  * @library /testlibrary /../../test/lib
  * @modules java.base/sun.misc
  *          java.management
@@ -54,14 +53,12 @@
 
     public static void main(String[] args) {
         for (BlobType btype : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
-                new UsageThresholdIncreasedTest(btype).runTest();
-            }
+            new UsageThresholdIncreasedTest(btype).runTest();
         }
     }
 
     private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){
-        Asserts.assertEQ(bean.getUsageThresholdCount(), count,
+        CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), count,
                 String.format("Usage threshold was hit: %d times for %s "
                         + "Threshold value: %d with current usage: %d",
                         bean.getUsageThresholdCount(), bean.getName(),
--- a/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdNotExceededTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -50,9 +50,7 @@
 
     public static void main(String[] args) {
         for (BlobType btype : BlobType.getAvailable()) {
-            if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
-                new UsageThresholdNotExceededTest(btype).runTest();
-            }
+            new UsageThresholdNotExceededTest(btype).runTest();
         }
     }
 
@@ -65,13 +63,11 @@
                 - CodeCacheUtils.getHeaderSize(btype), btype.id);
         // a gc cycle triggers usage threshold recalculation
         CodeCacheUtils.WB.fullGC();
-        Asserts.assertEQ(bean.getUsageThresholdCount(), initialThresholdCount,
-                String.format("Usage threshold was hit: %d  times for %s. "
+        CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), initialThresholdCount,
+                String.format("Usage threshold was hit: %d times for %s. "
                         + "Threshold value: %d with current usage: %d",
                         bean.getUsageThresholdCount(), bean.getName(),
                         bean.getUsageThreshold(), bean.getUsage().getUsed()));
-
-        System.out.println("INFO: Case finished successfully for "
-                + bean.getName());
+        System.out.println("INFO: Case finished successfully for " + bean.getName());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/crc32c/TestCRC32C.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,221 @@
+/*
+ * 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 8073583
+ * @summary C2 support for CRC32C on SPARC
+ *
+ * @run main/othervm/timeout=600 -Xbatch TestCRC32C -m
+ */
+
+import java.nio.ByteBuffer;
+import java.util.zip.Checksum;
+import java.util.zip.CRC32C;
+
+public class TestCRC32C {
+    public static void main(String[] args) {
+        int offset = Integer.getInteger("offset", 0);
+        int msgSize = Integer.getInteger("msgSize", 512);
+        boolean multi = false;
+        int iters = 20000;
+        int warmupIters = 20000;
+
+        if (args.length > 0) {
+            if (args[0].equals("-m")) {
+                multi = true;
+            } else {
+                iters = Integer.valueOf(args[0]);
+            }
+            if (args.length > 1) {
+                warmupIters = Integer.valueOf(args[1]);
+            }
+        }
+
+        if (multi) {
+            test_multi(warmupIters);
+            return;
+        }
+
+        System.out.println(" offset = " + offset);
+        System.out.println("msgSize = " + msgSize + " bytes");
+        System.out.println("  iters = " + iters);
+
+        byte[] b = initializedBytes(msgSize, offset);
+
+        CRC32C crc0 = new CRC32C();
+        CRC32C crc1 = new CRC32C();
+        CRC32C crc2 = new CRC32C();
+
+        crc0.update(b, offset, msgSize);
+
+        System.out.println("-------------------------------------------------------");
+
+        /* warm up */
+        for (int i = 0; i < warmupIters; i++) {
+            crc1.reset();
+            crc1.update(b, offset, msgSize);
+        }
+
+        /* measure performance */
+        long start = System.nanoTime();
+        for (int i = 0; i < iters; i++) {
+            crc1.reset();
+            crc1.update(b, offset, msgSize);
+        }
+        long end = System.nanoTime();
+        double total = (double)(end - start)/1e9;         // in seconds
+        double thruput = (double)msgSize*iters/1e6/total; // in MB/s
+        System.out.println("CRC32C.update(byte[]) runtime = " + total + " seconds");
+        System.out.println("CRC32C.update(byte[]) throughput = " + thruput + " MB/s");
+
+        /* check correctness */
+        for (int i = 0; i < iters; i++) {
+            crc1.reset();
+            crc1.update(b, offset, msgSize);
+            if (!check(crc0, crc1)) break;
+        }
+        report("CRCs", crc0, crc1);
+
+        System.out.println("-------------------------------------------------------");
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(msgSize);
+        buf.put(b, offset, msgSize);
+        buf.flip();
+
+        /* warm up */
+        for (int i = 0; i < warmupIters; i++) {
+            crc2.reset();
+            crc2.update(buf);
+            buf.rewind();
+        }
+
+        /* measure performance */
+        start = System.nanoTime();
+        for (int i = 0; i < iters; i++) {
+            crc2.reset();
+            crc2.update(buf);
+            buf.rewind();
+        }
+        end = System.nanoTime();
+        total = (double)(end - start)/1e9;         // in seconds
+        thruput = (double)msgSize*iters/1e6/total; // in MB/s
+        System.out.println("CRC32C.update(ByteBuffer) runtime = " + total + " seconds");
+        System.out.println("CRC32C.update(ByteBuffer) throughput = " + thruput + " MB/s");
+
+        /* check correctness */
+        for (int i = 0; i < iters; i++) {
+            crc2.reset();
+            crc2.update(buf);
+            buf.rewind();
+            if (!check(crc0, crc2)) break;
+        }
+        report("CRCs", crc0, crc2);
+
+        System.out.println("-------------------------------------------------------");
+    }
+
+    private static void report(String s, Checksum crc0, Checksum crc1) {
+        System.out.printf("%s: crc0 = %08x, crc1 = %08x\n",
+                          s, crc0.getValue(), crc1.getValue());
+    }
+
+    private static boolean check(Checksum crc0, Checksum crc1) {
+        if (crc0.getValue() != crc1.getValue()) {
+            System.err.printf("ERROR: crc0 = %08x, crc1 = %08x\n",
+                              crc0.getValue(), crc1.getValue());
+            return false;
+        }
+        return true;
+    }
+
+    private static byte[] initializedBytes(int M, int offset) {
+        byte[] bytes = new byte[M + offset];
+        for (int i = 0; i < offset; i++) {
+            bytes[i] = (byte) i;
+        }
+        for (int i = offset; i < bytes.length; i++) {
+            bytes[i] = (byte) (i - offset);
+        }
+        return bytes;
+    }
+
+    private static void test_multi(int iters) {
+        int len1 = 8;    // the  8B/iteration loop
+        int len2 = 32;   // the 32B/iteration loop
+        int len3 = 4096; // the 4KB/iteration loop
+
+        byte[] b = initializedBytes(len3*16, 0);
+        int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 };
+        int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7,
+                        len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7,
+                        len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7,
+                        len2, len2+1, len2+3, len2+5, len2+7,
+                        len2*2, len2*4, len2*8, len2*16, len2*32, len2*64,
+                        len3, len3+1, len3+3, len3+5, len3+7,
+                        len3*2, len3*4, len3*8,
+                        len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7,
+                        len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7,
+                        len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7,
+                        len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3,
+                        len1+len2+len3+5, len1+len2+len3+7,
+                        (len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3,
+                        (len1+len2+len3)*2+5, (len1+len2+len3)*2+7,
+                        (len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,
+                        (len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };
+        CRC32C[] crc0 = new CRC32C[offsets.length*sizes.length];
+        CRC32C[] crc1 = new CRC32C[offsets.length*sizes.length];
+        int i, j, k;
+
+        System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);
+
+        /* set the result from interpreter as reference */
+        for (i = 0; i < offsets.length; i++) {
+            for (j = 0; j < sizes.length; j++) {
+                crc0[i*sizes.length + j] = new CRC32C();
+                crc1[i*sizes.length + j] = new CRC32C();
+                crc0[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+            }
+        }
+
+        /* warm up the JIT compiler and get result */
+        for (k = 0; k < iters; k++) {
+            for (i = 0; i < offsets.length; i++) {
+                for (j = 0; j < sizes.length; j++) {
+                    crc1[i*sizes.length + j].reset();
+                    crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]);
+                }
+            }
+        }
+
+        /* check correctness */
+        for (i = 0; i < offsets.length; i++) {
+            for (j = 0; j < sizes.length; j++) {
+                if (!check(crc0[i*sizes.length + j], crc1[i*sizes.length + j])) {
+                    System.out.printf("offsets[%d] = %d", i, offsets[i]);
+                    System.out.printf("\tsizes[%d] = %d\n", j, sizes[j]);
+                }
+            }
+        }
+    }
+}
--- a/jaxp/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -314,3 +314,4 @@
 f844a908d3308f47d73cf64e87c98d37d5d76ce8 jdk9-b69
 42180703e0a362c1de7cdbf61d2cbc6609e678c4 jdk9-b70
 a3200b88f259f904876b9ab13fd4c4ec2726f8ba jdk9-b71
+81e85f3b6174314155991048767452a9931e12e2 jdk9-b72
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Compile.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: Compile.java,v 1.2.4.1 2005/08/31 11:24:13 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline;
-
-import com.sun.org.apache.xalan.internal.utils.FeatureManager;
-import java.io.File;
-import java.net.URL;
-import java.util.Vector;
-
-import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOpt;
-import com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOptsException;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
-
-/**
- * @author Jacek Ambroziak
- * @author Santiago Pericas-Geertsen
- * @author G. Todd Miller
- * @author Morten Jorgensen
- */
-public final class Compile {
-
-    // Versioning numbers  for the compiler -v option output
-    private static int VERSION_MAJOR = 1;
-    private static int VERSION_MINOR = 4;
-    private static int VERSION_DELTA = 0;
-
-
-
-    // This variable should be set to false to prevent any methods in this
-    // class from calling System.exit(). As this is a command-line tool,
-    // calling System.exit() is normally OK, but we also want to allow for
-    // this class being used in other ways as well.
-    private static boolean _allowExit = true;
-
-
-    public static void printUsage() {
-      System.err.println("XSLTC version " +
-              VERSION_MAJOR + "." + VERSION_MINOR +
-              ((VERSION_DELTA > 0) ? ("." + VERSION_DELTA) : ("")) + "\n" +
-              new ErrorMsg(ErrorMsg.COMPILE_USAGE_STR));
-        if (_allowExit) System.exit(-1);
-    }
-
-    /**
-     * This method implements the command line compiler. See the USAGE_STRING
-     * constant for a description. It may make sense to move the command-line
-     * handling to a separate package (ie. make one xsltc.cmdline.Compiler
-     * class that contains this main() method and one xsltc.cmdline.Transform
-     * class that contains the DefaultRun stuff).
-     */
-    public static void main(String[] args) {
-        try {
-            boolean inputIsURL = false;
-            boolean useStdIn = false;
-            boolean classNameSet = false;
-            final GetOpt getopt = new GetOpt(args, "o:d:j:p:uxhsinv");
-            if (args.length < 1) printUsage();
-
-            final XSLTC xsltc = new XSLTC(true, new FeatureManager());
-            xsltc.init();
-
-            int c;
-            while ((c = getopt.getNextOption()) != -1) {
-                switch(c) {
-                case 'i':
-                    useStdIn = true;
-                    break;
-                case 'o':
-                    xsltc.setClassName(getopt.getOptionArg());
-                    classNameSet = true;
-                    break;
-                case 'd':
-                    xsltc.setDestDirectory(getopt.getOptionArg());
-                    break;
-                case 'p':
-                    xsltc.setPackageName(getopt.getOptionArg());
-                    break;
-                case 'j':
-                    xsltc.setJarFileName(getopt.getOptionArg());
-                    break;
-                case 'x':
-                    xsltc.setDebug(true);
-                    break;
-                case 'u':
-                    inputIsURL = true;
-                    break;
-                case 's':
-                    _allowExit = false;
-                    break;
-                case 'n':
-                    xsltc.setTemplateInlining(true);    // used to be 'false'
-                    break;
-                case 'v':
-                    // fall through to case h
-                case 'h':
-                default:
-                    printUsage();
-                    break;
-                }
-            }
-
-            boolean compileOK;
-
-            if (useStdIn) {
-                if (!classNameSet) {
-                    System.err.println(new ErrorMsg(ErrorMsg.COMPILE_STDIN_ERR));
-                    if (_allowExit) System.exit(-1);
-                }
-                compileOK = xsltc.compile(System.in, xsltc.getClassName());
-            }
-            else {
-                // Generate a vector containg URLs for all stylesheets specified
-                final String[] stylesheetNames = getopt.getCmdArgs();
-                final Vector   stylesheetVector = new Vector();
-                for (int i = 0; i < stylesheetNames.length; i++) {
-                    final String name = stylesheetNames[i];
-                    URL url;
-                    if (inputIsURL)
-                        url = new URL(name);
-                    else
-                        url = (new File(name)).toURI().toURL();
-                    stylesheetVector.addElement(url);
-                }
-                compileOK = xsltc.compile(stylesheetVector);
-            }
-
-            // Compile the stylesheet and output class/jar file(s)
-            if (compileOK) {
-                xsltc.printWarnings();
-                if (xsltc.getJarFileName() != null) xsltc.outputToJar();
-                if (_allowExit) System.exit(0);
-            }
-            else {
-                xsltc.printWarnings();
-                xsltc.printErrors();
-                if (_allowExit) System.exit(-1);
-            }
-        }
-        catch (GetOptsException ex) {
-            System.err.println(ex);
-            printUsage(); // exits with code '-1'
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-            if (_allowExit) System.exit(-1);
-        }
-    }
-
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/Transform.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,292 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: Transform.java,v 1.2.4.1 2005/09/12 09:07:33 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline;
-
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
-import com.sun.org.apache.xalan.internal.xsltc.StripFilter;
-import com.sun.org.apache.xalan.internal.xsltc.TransletException;
-import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
-import com.sun.org.apache.xalan.internal.xsltc.dom.DOMWSFilter;
-import com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager;
-import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
-import com.sun.org.apache.xalan.internal.xsltc.runtime.Constants;
-import com.sun.org.apache.xalan.internal.xsltc.runtime.Parameter;
-import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;
-import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
-import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
-import java.io.FileNotFoundException;
-import java.net.MalformedURLException;
-import java.net.UnknownHostException;
-import java.util.Vector;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.transform.sax.SAXSource;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-/**
- * @author Jacek Ambroziak
- * @author Santiago Pericas-Geertsen
- * @author G. Todd Miller
- * @author Morten Jorgensen
- */
-final public class Transform {
-
-    private SerializationHandler _handler;
-
-    private String  _fileName;
-    private String  _className;
-    private String  _jarFileSrc;
-    private boolean _isJarFileSpecified = false;
-    private Vector  _params = null;
-    private boolean _uri, _debug;
-    private int     _iterations;
-
-    public Transform(String className, String fileName,
-                     boolean uri, boolean debug, int iterations) {
-        _fileName = fileName;
-        _className = className;
-        _uri = uri;
-        _debug = debug;
-        _iterations = iterations;
-  }
-
-   public String getFileName(){return _fileName;}
-   public String getClassName(){return _className;}
-
-    public void setParameters(Vector params) {
-        _params = params;
-    }
-
-    private void setJarFileInputSrc(boolean flag,  String jarFile) {
-        // TODO: at this time we do not do anything with this
-        // information, attempts to add the jarfile to the CLASSPATH
-        // were successful via System.setProperty, but the effects
-        // were not visible to the running JVM. For now we add jarfile
-        // to CLASSPATH in the wrapper script that calls this program.
-        _isJarFileSpecified = flag;
-        // TODO verify jarFile exists...
-        _jarFileSrc = jarFile;
-    }
-
-    private void doTransform() {
-        try {
-            final Class clazz = ObjectFactory.findProviderClass(_className, true);
-            final AbstractTranslet translet = (AbstractTranslet)clazz.newInstance();
-            translet.postInitialization();
-
-            // Create a SAX parser and get the XMLReader object it uses
-            final SAXParserFactory factory = SAXParserFactory.newInstance();
-            try {
-                factory.setFeature(Constants.NAMESPACE_FEATURE,true);
-            }
-            catch (Exception e) {
-                factory.setNamespaceAware(true);
-            }
-            final SAXParser parser = factory.newSAXParser();
-            final XMLReader reader = parser.getXMLReader();
-
-            // Set the DOM's DOM builder as the XMLReader's SAX2 content handler
-            XSLTCDTMManager dtmManager =
-                XSLTCDTMManager.createNewDTMManagerInstance();
-
-            DTMWSFilter wsfilter;
-            if (translet != null && translet instanceof StripFilter) {
-                wsfilter = new DOMWSFilter(translet);
-            } else {
-                wsfilter = null;
-            }
-
-            final DOMEnhancedForDTM dom =
-                   (DOMEnhancedForDTM)dtmManager.getDTM(
-                            new SAXSource(reader, new InputSource(_fileName)),
-                            false, wsfilter, true, false, translet.hasIdCall());
-
-            dom.setDocumentURI(_fileName);
-            translet.prepassDocument(dom);
-
-            // Pass global parameters
-            int n = _params.size();
-            for (int i = 0; i < n; i++) {
-                Parameter param = (Parameter) _params.elementAt(i);
-                translet.addParameter(param._name, param._value);
-            }
-
-            // Transform the document
-            TransletOutputHandlerFactory tohFactory =
-                TransletOutputHandlerFactory.newInstance();
-            tohFactory.setOutputType(TransletOutputHandlerFactory.STREAM);
-            tohFactory.setEncoding(translet._encoding);
-            tohFactory.setOutputMethod(translet._method);
-
-            if (_iterations == -1) {
-                translet.transform(dom, tohFactory.getSerializationHandler());
-            }
-            else if (_iterations > 0) {
-                long mm = System.currentTimeMillis();
-                for (int i = 0; i < _iterations; i++) {
-                    translet.transform(dom,
-                                       tohFactory.getSerializationHandler());
-                }
-                mm = System.currentTimeMillis() - mm;
-
-                System.err.println("\n<!--");
-                System.err.println("  transform  = "
-                                   + (((double) mm) / ((double) _iterations))
-                                   + " ms");
-                System.err.println("  throughput = "
-                                   + (1000.0 / (((double) mm)
-                                                 / ((double) _iterations)))
-                                   + " tps");
-                System.err.println("-->");
-            }
-        }
-        catch (TransletException e) {
-            if (_debug) e.printStackTrace();
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                   e.getMessage());
-        }
-        catch (RuntimeException e) {
-            if (_debug) e.printStackTrace();
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               e.getMessage());
-        }
-        catch (FileNotFoundException e) {
-            if (_debug) e.printStackTrace();
-            ErrorMsg err = new ErrorMsg(ErrorMsg.FILE_NOT_FOUND_ERR, _fileName);
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               err.toString());
-        }
-        catch (MalformedURLException e) {
-            if (_debug) e.printStackTrace();
-            ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, _fileName);
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               err.toString());
-        }
-        catch (ClassNotFoundException e) {
-            if (_debug) e.printStackTrace();
-            ErrorMsg err= new ErrorMsg(ErrorMsg.CLASS_NOT_FOUND_ERR,_className);
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               err.toString());
-        }
-        catch (UnknownHostException e) {
-            if (_debug) e.printStackTrace();
-            ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_URI_ERR, _fileName);
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               err.toString());
-        }
-        catch (SAXException e) {
-            Exception ex = e.getException();
-            if (_debug) {
-                if (ex != null) ex.printStackTrace();
-                e.printStackTrace();
-            }
-            System.err.print(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY));
-            if (ex != null)
-                System.err.println(ex.getMessage());
-            else
-                System.err.println(e.getMessage());
-        }
-        catch (Exception e) {
-            if (_debug) e.printStackTrace();
-            System.err.println(new ErrorMsg(ErrorMsg.RUNTIME_ERROR_KEY)+
-                               e.getMessage());
-        }
-    }
-
-    public static void printUsage() {
-        System.err.println(new ErrorMsg(ErrorMsg.TRANSFORM_USAGE_STR));
-    }
-
-    public static void main(String[] args) {
-        try {
-            if (args.length > 0) {
-                int i;
-                int iterations = -1;
-                boolean uri = false, debug = false;
-                boolean isJarFileSpecified = false;
-                String  jarFile = null;
-
-                // Parse options starting with '-'
-                for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++) {
-                    if (args[i].equals("-u")) {
-                        uri = true;
-                    }
-                    else if (args[i].equals("-x")) {
-                        debug = true;
-                    }
-                    else if (args[i].equals("-j")) {
-                        isJarFileSpecified = true;
-                        jarFile = args[++i];
-                    }
-                    else if (args[i].equals("-n")) {
-                        try {
-                            iterations = Integer.parseInt(args[++i]);
-                        }
-                        catch (NumberFormatException e) {
-                            // ignore
-                        }
-                    }
-                    else {
-                        printUsage();
-                    }
-                }
-
-                // Enough arguments left ?
-                if (args.length - i < 2) printUsage();
-
-                // Get document file and class name
-                Transform handler = new Transform(args[i+1], args[i], uri,
-                    debug, iterations);
-                handler.setJarFileInputSrc(isJarFileSpecified,  jarFile);
-
-                // Parse stylesheet parameters
-                Vector params = new Vector();
-                for (i += 2; i < args.length; i++) {
-                    final int equal = args[i].indexOf('=');
-                    if (equal > 0) {
-                        final String name  = args[i].substring(0, equal);
-                        final String value = args[i].substring(equal+1);
-                        params.addElement(new Parameter(name, value));
-                    }
-                    else {
-                        printUsage();
-                    }
-                }
-
-                if (i == args.length) {
-                    handler.setParameters(params);
-                    handler.doTransform();
-                }
-            } else {
-                printUsage();
-            }
-        }
-        catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOpt.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: GetOpt.java,v 1.2.4.1 2005/08/31 11:46:04 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
-
-
-/**
-* GetOpt is a Java equivalent to the C getopt() library function
-* discussed in man page getopt(3C). It provides command line
-* parsing for Java applications. It supports the most rules of the
-* command line standard (see man page intro(1)) including stacked
-* options such as '-sxm' (which is equivalent to -s -x -m); it
-* handles special '--' option that signifies the end of options.
-* Additionally this implementation of getopt will check for
-* mandatory arguments to options such as in the case of
-* '-d <file>' it will throw a MissingOptArgException if the
-* option argument '<file>' is not included on the commandline.
-* getopt(3C) does not check for this.
- * @author G Todd Miller
-*/
-public class GetOpt{
-    public GetOpt(String[] args, String optString){
-        theOptions = new ArrayList();
-        int currOptIndex = 0;
-        theCmdArgs = new ArrayList();
-        theOptionMatcher = new OptionMatcher(optString);
-        // fill in the options list
-        for(int i=0; i<args.length; i++){
-            String token = args[i];
-            int tokenLength = token.length();
-            if(token.equals("--")){         // end of opts
-                currOptIndex = i+1;         // set index of first operand
-                break;                      // end of options
-            }
-            else if(token.startsWith("-") && tokenLength == 2){
-                // simple option token such as '-s' found
-                theOptions.add(new Option(token.charAt(1)));
-            }
-            else if(token.startsWith("-") && tokenLength > 2){
-                // stacked options found, such as '-shm'
-                // iterate thru the tokens after the dash and
-                // add them to theOptions list
-                for(int j=1; j<tokenLength; j++){
-                    theOptions.add(new Option(token.charAt(j)));
-                }
-            }
-            else if(!token.startsWith("-")){
-                // case 1- there are not options stored yet therefore
-                // this must be an command argument, not an option argument
-                if(theOptions.size() == 0){
-                    currOptIndex = i;
-                    break;              // stop processing options
-                }
-                else {
-                    // case 2-
-                    // there are options stored, check to see if
-                    // this arg belong to the last arg stored
-                    int indexoflast=0;
-                    indexoflast = theOptions.size()-1;
-                    Option op = (Option)theOptions.get(indexoflast);
-                    char opLetter = op.getArgLetter();
-                    if(!op.hasArg() && theOptionMatcher.hasArg(opLetter)){
-                        op.setArg(token);
-                    }
-                    else{
-                        // case 3 -
-                        // the last option stored does not take
-                        // an argument, so again, this argument
-                        // must be a command argument, not
-                        // an option argument
-                        currOptIndex = i;
-                        break;                  // end of options
-                    }
-                }
-            }// end option does not start with "-"
-        } // end for args loop
-
-        //  attach an iterator to list of options
-        theOptionsIterator = theOptions.listIterator();
-
-        // options are done, now fill out cmd arg list with remaining args
-        for(int i=currOptIndex; i<args.length; i++){
-            String token = args[i];
-            theCmdArgs.add(token);
-        }
-    }
-
-
-    /**
-    * debugging routine to print out all options collected
-    */
-    public void printOptions(){
-        for(ListIterator it=theOptions.listIterator(); it.hasNext();){
-            Option opt = (Option)it.next();
-            System.out.print("OPT =" + opt.getArgLetter());
-            String arg = opt.getArgument();
-            if(arg != null){
-               System.out.print(" " + arg);
-            }
-            System.out.println();
-        }
-    }
-
-    /**
-    * gets the next option found in the commandline. Distinguishes
-    * between two bad cases, one case is when an illegal option
-    * is found, and then other case is when an option takes an
-    * argument but no argument was found for that option.
-    * If the option found was not declared in the optString, then
-    * an IllegalArgumentException will be thrown (case 1).
-    * If the next option found has been declared to take an argument,
-    * and no such argument exists, then a MissingOptArgException
-    * is thrown (case 2).
-    * @param none
-    * @return int - the next option found.
-    * @throws IllegalArgumentException, MissingOptArgException.
-    */
-    public int getNextOption() throws IllegalArgumentException,
-        MissingOptArgException
-    {
-        int retval = -1;
-        if(theOptionsIterator.hasNext()){
-            theCurrentOption = (Option)theOptionsIterator.next();
-            char c = theCurrentOption.getArgLetter();
-            boolean shouldHaveArg = theOptionMatcher.hasArg(c);
-            String arg = theCurrentOption.getArgument();
-            if(!theOptionMatcher.match(c)) {
-                ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_CMDLINE_OPTION_ERR,
-                                            new Character(c));
-                throw (new IllegalArgumentException(msg.toString()));
-            }
-            else if(shouldHaveArg && (arg == null)) {
-                ErrorMsg msg = new ErrorMsg(ErrorMsg.CMDLINE_OPT_MISSING_ARG_ERR,
-                                            new Character(c));
-                throw (new MissingOptArgException(msg.toString()));
-            }
-            retval = c;
-        }
-        return retval;
-    }
-
-    /**
-    * gets the argument for the current parsed option. For example,
-    * in case of '-d <file>', if current option parsed is 'd' then
-    * getOptionArg() would return '<file>'.
-    * @return String - argument for current parsed option.
-    * @param none
-    */
-    public String getOptionArg(){
-        String retval = null;
-        String tmp = theCurrentOption.getArgument();
-        char c = theCurrentOption.getArgLetter();
-        if(theOptionMatcher.hasArg(c)){
-            retval = tmp;
-        }
-        return retval;
-    }
-
-    /**
-    * gets list of the commandline arguments. For example, in command
-    * such as 'cmd -s -d file file2 file3 file4'  with the usage
-    * 'cmd [-s] [-d <file>] <file>...', getCmdArgs() would return
-    * the list {file2, file3, file4}.
-    * @return String[] - list of command arguments that may appear
-    *                    after options and option arguments.
-    * @params none
-    */
-    public String[] getCmdArgs(){
-        String[] retval = new String[theCmdArgs.size()];
-        int i=0;
-        for(ListIterator it=theCmdArgs.listIterator(); it.hasNext();){
-            retval[i++] = (String)it.next();
-        }
-        return retval;
-    }
-
-
-    private Option theCurrentOption = null;
-    private ListIterator theOptionsIterator;
-    private List theOptions = null;
-    private List theCmdArgs = null;
-    private OptionMatcher theOptionMatcher = null;
-
-    ///////////////////////////////////////////////////////////
-    //
-    //   Inner Classes
-    //
-    ///////////////////////////////////////////////////////////
-
-    // inner class to model an option
-    class Option{
-        private char theArgLetter;
-        private String theArgument = null;
-        public Option(char argLetter) { theArgLetter = argLetter; }
-        public void setArg(String arg) {
-            theArgument = arg;
-        }
-        public boolean hasArg() { return (theArgument != null); }
-        public char getArgLetter() { return theArgLetter; }
-        public String getArgument() { return theArgument; }
-    } // end class Option
-
-
-    // inner class to query optString for a possible option match,
-    // and whether or not a given legal option takes an argument.
-    //
-    class OptionMatcher{
-        public OptionMatcher(String optString){
-            theOptString = optString;
-        }
-        public boolean match(char c){
-            boolean retval = false;
-            if(theOptString.indexOf(c) != -1){
-                retval = true;
-            }
-            return retval;
-        }
-        public boolean hasArg(char c){
-            boolean retval = false;
-            int index = theOptString.indexOf(c)+1;
-            if (index == theOptString.length()){
-                // reached end of theOptString
-                retval = false;
-            }
-            else if(theOptString.charAt(index) == ':'){
-                retval = true;
-            }
-            return retval;
-        }
-        private String theOptString = null;
-    } // end class OptionMatcher
-}// end class GetOpt
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/GetOptsException.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: GetOptsException.java,v 1.2.4.1 2005/08/31 11:47:06 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt;
-
-/**
- * @author G Todd Miller
- */
-public class GetOptsException extends Exception{
-    static final long serialVersionUID = 8736874967183039804L;
-    public GetOptsException(String msg){
-        super(msg);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/IllegalArgumentException.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: IllegalArgumentException.java,v 1.2.4.1 2005/08/31 11:47:56 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt;
-
-
-class IllegalArgumentException extends GetOptsException{
-    static final long serialVersionUID = 8642122427294793651L;
-    public IllegalArgumentException(String msg){
-        super(msg);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/cmdline/getopt/MissingOptArgException.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: MissingOptArgException.java,v 1.2.4.1 2005/08/31 11:49:21 pvedula Exp $
- */
-
-package com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt;
-
-
-/**
- * @author G Todd Miller
- */
-class MissingOptArgException extends GetOptsException{
-    static final long serialVersionUID = -1972471465394544822L;
-    public MissingOptArgException(String msg){
-        super(msg);
-    }
-}
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java	Wed Jul 05 20:41:30 2017 +0200
@@ -49,7 +49,7 @@
    * Get the next XMLEvent
    * @see XMLEvent
    * @throws XMLStreamException if there is an error with the underlying XML.
-   * @throws NoSuchElementException iteration has no more elements.
+   * @throws java.util.NoSuchElementException iteration has no more elements.
    */
   public XMLEvent nextEvent() throws XMLStreamException;
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/events/XMLEvent.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/events/XMLEvent.java	Wed Jul 05 20:41:30 2017 +0200
@@ -170,7 +170,7 @@
    * infoset expressed.
    *
    * @param writer The writer that will output the data
-   * @throws XMLStreamException if there is a fatal error writing the event
+   * @throws javax.xml.stream.XMLStreamException if there is a fatal error writing the event
    */
   public void writeAsEncodedUnicode(Writer writer)
     throws javax.xml.stream.XMLStreamException;
--- a/jaxws/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -317,3 +317,4 @@
 f5911c6155c29ac24b6f9068273207e5ebd3a3df jdk9-b69
 94084caa27a3c8a09a7510aef596ebd64e97c569 jdk9-b70
 61caeb7061bbf8cc74a767997e5d17cc00712629 jdk9-b71
+1d87054e2d2f405c114f0061b97cbf8214bddf0a jdk9-b72
--- a/jdk/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -314,3 +314,4 @@
 551323004d0ce2f1d4b0e99552f7e0cdcebc6fca jdk9-b69
 a7f731125b7fb0e4b0186172f85a21e2d5139f7e jdk9-b70
 e47d3bfbc61accc3fbd372a674fdce2933b54f31 jdk9-b71
+f376824d4940f45719d91838f3f6249f873440db jdk9-b72
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/Lib-jdk.internal.le.gmk	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+  LIBLE_SRC := $(JDK_TOPDIR)/src/jdk.internal.le/$(OPENJDK_TARGET_OS_TYPE)/native/lible \
+      #
+  LIBLE_CPPFLAGS := \
+      $(addprefix -I, $(LIBLE_SRC)) \
+      -I$(SUPPORT_OUTPUTDIR)/headers/jdk.internal.le \
+      #
+
+  $(eval $(call SetupNativeCompilation,BUILD_LIBLE, \
+      LIBRARY := le, \
+      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+      SRC := $(LIBLE_SRC), \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CFLAGS_JDKLIB) $(LIBJAVA_HEADER_FLAGS)\
+          $(LIBLE_CPPFLAGS), \
+      LDFLAGS := $(LDFLAGS_JDKLIB), \
+      LDFLAGS_SUFFIX := $(LDFLAGS_JDKLIB_SUFFIX) user32.lib, \
+      VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+      RC_FLAGS := $(RC_FLAGS) \
+          -D "JDK_FNAME=le.dll" \
+          -D "JDK_INTERNAL_NAME=le" \
+          -D "JDK_FTYPE=0x2L", \
+      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lible, \
+      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+
+  TARGETS += $(BUILD_LIBLE)
+
+endif # OPENJDK_TARGET_OS
+
+################################################################################
--- a/jdk/make/non-build-utils/sharing/README.txt	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-This directory contains tools and tests associated with creating the
-class list for class data sharing.
-
-The class list is produced by running the refWorkload startup3 benchmark with
-the -XX:+TraceClassLoadingPreorder option.  The -Xshare:off option must also be
-used so that bootclasspath classes are loaded from rt.jar.  The MakeClasslist
-program should be built into the jar file makeclasslist.jar and is run
-on one of the logs from each of the benchmarks in the following fashion:
-
-cd .../<resultsdir>/results.startup3
-$JAVA_HOME/bin/java -jar makeclasslist.jar results.Noop/results_1/log results.Framer/results_1/log results.XFramer/results_1/log results.JEdit/results_1/log results.LimeWire/results_1/log results.NetBeans50/results_1/log
-
-Presently, $JAVA_HOME must be the same path used to run the startup3 benchmark.
-
-The logs are deliberately concatenated in roughly smallest to largest order
-based on application size.  The resulting output is redirected into a file
-and results in one of classlist.solaris, classlist.linux, classlist.macosx,
-or classlist.windows.  These files are checked in to the workspace.  A
-necessary checksum (AddJsum.java) is added to the final classlist
-(installed in lib/ or jre/lib/) during the build process by the
-makefiles in make/java/redist.
-
-In a forthcoming JDK build we plan to manually add the dependent
-classes for the calendar manager Glow, which pulls in the Preferences
-classes and, on Unix platforms, the XML parsing classes.
-
-The properties file supplied to the refworkload is approximately the
-following:
-
-javahome=/usr/java/j2sdk1.8.0
-resultsdir=classlist-run
-iterations=1
-benchmarks=startup3
-globalvmoptions=-client -Xshare:off -XX:+TraceClassLoadingPreorder
--- a/jdk/make/non-build-utils/sharing/tests/GHello.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- */
-
-
-import java.awt.Font;
-import java.awt.Frame;
-import java.awt.Label;
-
-public class GHello extends Frame {
-
-    public static void main(String[] args) {
-        System.out.println("Hello");
-
-        new GHello().show();
-        if (args.length == 1 && args[0].equals("quit")) {
-            try {
-                Thread.currentThread().sleep(200);
-            } catch (InterruptedException e) {
-            }
-            System.exit(0);
-        }
-    }
-
-
-    GHello() {
-        Label label = new Label("Hello");
-        label.setFont(new Font("Monospaced", Font.PLAIN, 144));
-        add(label);
-        pack();
-    }
-}
--- a/jdk/make/non-build-utils/sharing/tests/Hello.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- */
-
-
-
-public class Hello {
-    public static void main(String[] args) {
-        System.out.println("Hello, World!");
-    }
-}
--- a/jdk/make/non-build-utils/sharing/tests/JHello.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- */
-
-
-import java.awt.Font;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-
-public class JHello extends JFrame {
-
-    public static void main(String[] args) {
-        System.out.println("Hello");
-
-        new JHello().show();
-        if (args.length == 1 && args[0].equals("quit")) {
-            try {
-                Thread.currentThread().sleep(1000);
-            } catch (InterruptedException e) {
-            }
-            System.exit(0);
-        }
-    }
-
-
-    JHello() {
-        JLabel jlabel = new JLabel("Hello");
-        jlabel.setFont(new Font("Monospaced", Font.PLAIN, 144));
-        getContentPane().add(jlabel);
-        pack();
-    }
-}
--- a/jdk/make/non-build-utils/src/build/tools/makeclasslist/MakeClasslist.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2003, 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.makeclasslist;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-/** Reads a set of files containing the output of java
-    -XX:+TraceClassLoadingPreorder runs. Finds all classes that were
-    loaded from the bootstrap class path by comparing the prefix of
-    the load path to the current JRE's java.home system property.
-    Prints the names of these classes to stdout.
-*/
-
-public class MakeClasslist {
-  public static void main(String[] args) throws IOException {
-    List<String> classes = new ArrayList<>();
-    String origJavaHome = System.getProperty("java.home");
-    String javaHome     = origJavaHome.toLowerCase();
-    if (javaHome.endsWith("jre")) {
-      origJavaHome = origJavaHome.substring(0, origJavaHome.length() - 4);
-      javaHome     = javaHome.substring(0, javaHome.length() - 4);
-    }
-    for (int i = 0; i < args.length; i++) {
-      try {
-        File file = new File(args[i]);
-        BufferedReader reader = new BufferedReader(new FileReader(file));
-        String line = null;
-        while ((line = reader.readLine()) != null) {
-          StringTokenizer tok = new StringTokenizer(line, "[ \t\n\r\f");
-          if (tok.hasMoreTokens()) {
-            String t = tok.nextToken();
-            // Understand only "Loading" from -XX:+TraceClassLoadingPreorder.
-            // This ignores old "Loaded" from -verbose:class to force correct
-            // classlist generation on Mustang.
-            if (t.equals("Loading")) {
-              t = tok.nextToken();
-              t = t.replace('.', '/');
-
-              // Check to make sure it came from the boot class path
-              if (tok.hasMoreTokens()) {
-                String tmp = tok.nextToken();
-                if (tmp.equals("from")) {
-                  if (tok.hasMoreTokens()) {
-                    tmp = tok.nextToken().toLowerCase();
-                    // System.err.println("Loaded " + t + " from " + tmp);
-                    if (tmp.startsWith(javaHome)) {
-                      // OK, remember this class for later
-                      classes.add(t);
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      } catch (IOException e) {
-        System.err.println("Error reading file " + args[i]);
-        throw(e);
-      }
-    }
-
-    Set<String> seenClasses = new HashSet<>();
-
-    for (String str : classes) {
-      if (seenClasses.add(str)) {
-        System.out.println(str);
-      }
-    }
-
-    // Try to complete certain packages
-    // Note: not using this new code yet; need to consider whether the
-    // footprint increase is worth any startup gains
-    // Note also that the packages considered below for completion are
-    // (obviously) platform-specific
-    // JarFile rtJar = new JarFile(origJavaHome + File.separator +
-    //                             "jre" + File.separator +
-    //                             "lib" + File.separator +
-    //                             "rt.jar");
-    // completePackage(seenClasses, rtJar, "java/awt");
-    // completePackage(seenClasses, rtJar, "sun/awt");
-    // completePackage(seenClasses, rtJar, "sun/awt/X11");
-    // completePackage(seenClasses, rtJar, "java/awt/im/spi");
-    // completePackage(seenClasses, rtJar, "java/lang");
-  }
-
-  private static void completePackage(Set<String> seenClasses,
-                                      JarFile jar,
-                                      String packageName) {
-    int len = packageName.length();
-    Enumeration<JarEntry> entries = jar.entries();
-    while (entries.hasMoreElements()) {
-      JarEntry entry = entries.nextElement();
-      String name = entry.getName();
-      if (name.startsWith(packageName) &&
-          name.endsWith(".class") &&
-          name.lastIndexOf('/') == len) {
-        // Trim ".class" from end
-        name = name.substring(0, name.length() - 6);
-        if (seenClasses.add(name)) {
-          System.out.println(name);
-        }
-      }
-    }
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/non-build-utils/src/build/tools/makeclasslist/makeClasslist.js	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This tool is used to help create the class list for class data sharing.
+ *
+ * The classlist is produced internally by first running a select number of
+ * startup benchmarks with the -XX:DumpLoadedClassList=<file> option, then
+ * running this tool in the following fashion to produce a complete classlist:
+ *
+ * jjs -scripting makeClasslist.js -- list1 list2 list3 > classlist.platform
+ *
+ * The lists should be listed in roughly smallest to largest order based on
+ * application size.
+ *
+ * After generating the classlist it's necessary to add a checksum (using
+ * AddJsum.java) before checking it into the workspace as the corresponding
+ * platform-specific classlist, such as make/data/classlist/classlist.linux 
+ */
+"use strict";
+var classlist = [];
+var seenClasses = {};
+
+for (var a in $ARG) {
+  var arg = $ARG[a];
+
+  var classes = readFully(arg).replace(/[\r\n]+/g, "\n").split("\n");
+
+  for (var c in classes) {
+    var clazz = classes[c];
+    if (clazz !== "" && seenClasses[clazz] === undefined) {
+      seenClasses[clazz] = clazz;
+      classlist.push(clazz);
+    }
+  }
+}
+
+for (c in classlist) {
+  print(classlist[c]);
+}
--- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, 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
@@ -31,6 +31,7 @@
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import sun.net.SocksProxy;
+import sun.net.spi.DefaultProxySelector;
 import sun.net.www.ParseUtil;
 /* import org.ietf.jgss.*; */
 
@@ -69,12 +70,21 @@
             server = ad.getHostString();
             serverPort = ad.getPort();
         }
+        useV4 = useV4(proxy);
     }
 
     void setV4() {
         useV4 = true;
     }
 
+    private static boolean useV4(Proxy proxy) {
+        if (proxy instanceof SocksProxy
+            && ((SocksProxy)proxy).protocolVersion() == 4) {
+            return true;
+        }
+        return DefaultProxySelector.socksProxyVersion() == 4;
+    }
+
     private synchronized void privilegedConnect(final String host,
                                               final int port,
                                               final int timeout)
@@ -398,11 +408,7 @@
                 // Use getHostString() to avoid reverse lookups
                 server = ((InetSocketAddress) p.address()).getHostString();
                 serverPort = ((InetSocketAddress) p.address()).getPort();
-                if (p instanceof SocksProxy) {
-                    if (((SocksProxy)p).protocolVersion() == 4) {
-                        useV4 = true;
-                    }
-                }
+                useV4 = useV4(p);
 
                 // Connects to the SOCKS server
                 try {
@@ -715,11 +721,7 @@
                 // Use getHostString() to avoid reverse lookups
                 server = ((InetSocketAddress) p.address()).getHostString();
                 serverPort = ((InetSocketAddress) p.address()).getPort();
-                if (p instanceof SocksProxy) {
-                    if (((SocksProxy)p).protocolVersion() == 4) {
-                        useV4 = true;
-                    }
-                }
+                useV4 = useV4(p);
 
                 // Connects to the SOCKS server
                 try {
--- a/jdk/src/java.base/share/classes/java/security/AccessControlContext.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/AccessControlContext.java	Wed Jul 05 20:41:30 2017 +0200
@@ -76,7 +76,7 @@
 
 public final class AccessControlContext {
 
-    private ProtectionDomain context[];
+    private ProtectionDomain[] context;
     // isPrivileged and isAuthorized are referenced by the VM - do not remove
     // or change their names
     private boolean isPrivileged;
@@ -89,13 +89,13 @@
     private DomainCombiner combiner = null;
 
     // limited privilege scope
-    private Permission permissions[];
+    private Permission[] permissions;
     private AccessControlContext parent;
     private boolean isWrapped;
 
     // is constrained by limited privilege scope?
     private boolean isLimited;
-    private ProtectionDomain limitedContext[];
+    private ProtectionDomain[] limitedContext;
 
     private static boolean debugInit = false;
     private static Debug debug = null;
@@ -123,7 +123,7 @@
      * changes to the array will not affect this AccessControlContext.
      * @throws NullPointerException if {@code context} is {@code null}
      */
-    public AccessControlContext(ProtectionDomain context[])
+    public AccessControlContext(ProtectionDomain[] context)
     {
         if (context.length == 0) {
             this.context = null;
@@ -282,7 +282,7 @@
      * package private constructor for AccessController.getContext()
      */
 
-    AccessControlContext(ProtectionDomain context[],
+    AccessControlContext(ProtectionDomain[] context,
                          boolean isPrivileged)
     {
         this.context = context;
@@ -643,7 +643,7 @@
     /*
      * Combine the current (stack) and assigned domains.
      */
-    private static ProtectionDomain[] combine(ProtectionDomain[]current,
+    private static ProtectionDomain[] combine(ProtectionDomain[] current,
         ProtectionDomain[] assigned) {
 
         // current could be null if only system code is on the stack;
@@ -666,7 +666,7 @@
         int n = (skipAssigned) ? 0 : assigned.length;
 
         // now we combine both of them, and create a new context
-        ProtectionDomain pd[] = new ProtectionDomain[slen + n];
+        ProtectionDomain[] pd = new ProtectionDomain[slen + n];
 
         // first copy in the assigned context domains, no need to compress
         if (!skipAssigned) {
@@ -695,7 +695,7 @@
             } else if (skipAssigned && n == slen) {
                 return current;
             }
-            ProtectionDomain tmp[] = new ProtectionDomain[n];
+            ProtectionDomain[] tmp = new ProtectionDomain[n];
             System.arraycopy(pd, 0, tmp, 0, n);
             pd = tmp;
         }
--- a/jdk/src/java.base/share/classes/java/security/CodeSource.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java	Wed Jul 05 20:41:30 2017 +0200
@@ -65,7 +65,7 @@
     /*
      * The code signers. Certificate chains are concatenated.
      */
-    private transient java.security.cert.Certificate certs[] = null;
+    private transient java.security.cert.Certificate[] certs = null;
 
     // cached SocketPermission used for matchLocation
     private transient SocketPermission sp;
@@ -91,7 +91,7 @@
      * @param certs the certificate(s). It may be null. The contents of the
      * array are copied to protect against subsequent modification.
      */
-    public CodeSource(URL url, java.security.cert.Certificate certs[]) {
+    public CodeSource(URL url, java.security.cert.Certificate[] certs) {
         this.location = url;
         if (url != null) {
             this.locationNoFragString = URLUtil.urlNoFragString(url);
--- a/jdk/src/java.base/share/classes/java/security/Permissions.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/Permissions.java	Wed Jul 05 20:41:30 2017 +0200
@@ -289,9 +289,9 @@
         if (unresolvedPerms == null)
             return null;
 
-        java.security.cert.Certificate certs[] = null;
+        java.security.cert.Certificate[] certs = null;
 
-        Object signers[] = p.getClass().getSigners();
+        Object[] signers = p.getClass().getSigners();
 
         int n = 0;
         if (signers != null) {
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Wed Jul 05 20:41:30 2017 +0200
@@ -69,7 +69,7 @@
  *
  * <pre>
  *      SecureRandom random = new SecureRandom();
- *      byte bytes[] = new byte[20];
+ *      byte[] bytes = new byte[20];
  *      random.nextBytes(bytes);
  * </pre>
  *
@@ -77,7 +77,7 @@
  * to generate a given number of seed bytes (to seed other random number
  * generators, for example):
  * <pre>
- *      byte seed[] = random.generateSeed(20);
+ *      byte[] seed = random.generateSeed(20);
  * </pre>
  *
  * Note: Depending on the implementation, the {@code generateSeed} and
@@ -186,7 +186,7 @@
      *
      * @param seed the seed.
      */
-    public SecureRandom(byte seed[]) {
+    public SecureRandom(byte[] seed) {
         super(0);
         getDefaultPRNG(true, seed);
     }
@@ -486,7 +486,7 @@
     @Override
     final protected int next(int numBits) {
         int numBytes = (numBits+7)/8;
-        byte b[] = new byte[numBytes];
+        byte[] b = new byte[numBytes];
         int next = 0;
 
         nextBytes(b);
--- a/jdk/src/java.base/share/classes/java/security/UnresolvedPermission.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/UnresolvedPermission.java	Wed Jul 05 20:41:30 2017 +0200
@@ -130,7 +130,7 @@
      */
     private String actions;
 
-    private transient java.security.cert.Certificate certs[];
+    private transient java.security.cert.Certificate[] certs;
 
     /**
      * Creates a new UnresolvedPermission containing the permission
@@ -152,7 +152,7 @@
     public UnresolvedPermission(String type,
                                 String name,
                                 String actions,
-                                java.security.cert.Certificate certs[])
+                                java.security.cert.Certificate[] certs)
     {
         super(type);
 
@@ -224,7 +224,7 @@
      * try and resolve this permission using the class loader of the permission
      * that was passed in.
      */
-    Permission resolve(Permission p, java.security.cert.Certificate certs[]) {
+    Permission resolve(Permission p, java.security.cert.Certificate[] certs) {
         if (this.certs != null) {
             // if p wasn't signed, we don't have a match
             if (certs == null) {
--- a/jdk/src/java.base/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java	Wed Jul 05 20:41:30 2017 +0200
@@ -54,7 +54,7 @@
     private final BigInteger primeExponentP;
     private final BigInteger primeExponentQ;
     private final BigInteger crtCoefficient;
-    private final RSAOtherPrimeInfo otherPrimeInfo[];
+    private final RSAOtherPrimeInfo[] otherPrimeInfo;
 
    /**
     * Creates a new {@code RSAMultiPrimePrivateCrtKeySpec}
--- a/jdk/src/java.base/share/classes/java/util/ArrayList.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java	Wed Jul 05 20:41:30 2017 +0200
@@ -178,7 +178,8 @@
     public ArrayList(Collection<? extends E> c) {
         elementData = c.toArray();
         if ((size = elementData.length) != 0) {
-            // c.toArray might (incorrectly) not return Object[] (see 6260652)
+            // defend against c.toArray (incorrectly) not returning Object[]
+            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
             if (elementData.getClass() != Object[].class)
                 elementData = Arrays.copyOf(elementData, size, Object[].class);
         } else {
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 20:41:30 2017 +0200
@@ -3820,7 +3820,7 @@
 
         @Override
         public Object[] toArray() {
-            return a.clone();
+            return Arrays.copyOf(a, a.length, Object[].class);
         }
 
         @Override
--- a/jdk/src/java.base/share/classes/java/util/Vector.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Vector.java	Wed Jul 05 20:41:30 2017 +0200
@@ -174,7 +174,8 @@
     public Vector(Collection<? extends E> c) {
         elementData = c.toArray();
         elementCount = elementData.length;
-        // c.toArray might (incorrectly) not return Object[] (see 6260652)
+        // defend against c.toArray (incorrectly) not returning Object[]
+        // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
         if (elementData.getClass() != Object[].class)
             elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 05 20:41:30 2017 +0200
@@ -134,7 +134,8 @@
             elements = ((CopyOnWriteArrayList<?>)c).getArray();
         else {
             elements = c.toArray();
-            // c.toArray might (incorrectly) not return Object[] (see 6260652)
+            // defend against c.toArray (incorrectly) not returning Object[]
+            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
             if (elements.getClass() != Object[].class)
                 elements = Arrays.copyOf(elements, elements.length, Object[].class);
         }
--- a/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java	Wed Jul 05 20:41:30 2017 +0200
@@ -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
@@ -106,6 +106,15 @@
         }
     }
 
+    public static int socksProxyVersion() {
+        return AccessController.doPrivileged(
+                new PrivilegedAction<Integer>() {
+                    @Override public Integer run() {
+                        return NetProperties.getInteger(SOCKS_PROXY_VERSION, 5);
+                    }
+                });
+    }
+
     /**
      * How to deal with "non proxy hosts":
      * since we do have to generate a pattern we don't want to do that if
@@ -302,8 +311,7 @@
                             saddr = InetSocketAddress.createUnresolved(phost, pport);
                             // Socks is *always* the last on the list.
                             if (j == (props[i].length - 1)) {
-                                int version = NetProperties.getInteger(SOCKS_PROXY_VERSION, 5).intValue();
-                                return SocksProxy.create(saddr, version);
+                                return SocksProxy.create(saddr, socksProxyVersion());
                             } else {
                                 return new Proxy(Proxy.Type.HTTP, saddr);
                             }
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS7.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS7.java	Wed Jul 05 20:41:30 2017 +0200
@@ -507,7 +507,7 @@
         // certificates (optional)
         if (certificates != null && certificates.length != 0) {
             // cast to X509CertImpl[] since X509CertImpl implements DerEncoder
-            X509CertImpl implCerts[] = new X509CertImpl[certificates.length];
+            X509CertImpl[] implCerts = new X509CertImpl[certificates.length];
             for (int i = 0; i < certificates.length; i++) {
                 if (certificates[i] instanceof X509CertImpl)
                     implCerts[i] = (X509CertImpl) certificates[i];
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java	Wed Jul 05 20:41:30 2017 +0200
@@ -78,7 +78,7 @@
      * data is stored and transmitted losslessly, but no knowledge
      * about this particular algorithm is available.
      */
-    private PKCS8Key (AlgorithmId algid, byte key [])
+    private PKCS8Key (AlgorithmId algid, byte[] key)
     throws InvalidKeyException {
         this.algid = algid;
         this.key = key;
--- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Wed Jul 05 20:41:30 2017 +0200
@@ -154,28 +154,28 @@
 
     private static final Debug debug = Debug.getInstance("pkcs12");
 
-    private static final int keyBag[]  = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
-    private static final int certBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 3};
-    private static final int secretBag[] = {1, 2, 840, 113549, 1, 12, 10, 1, 5};
+    private static final int[] keyBag  = {1, 2, 840, 113549, 1, 12, 10, 1, 2};
+    private static final int[] certBag = {1, 2, 840, 113549, 1, 12, 10, 1, 3};
+    private static final int[] secretBag = {1, 2, 840, 113549, 1, 12, 10, 1, 5};
 
-    private static final int pkcs9Name[]  = {1, 2, 840, 113549, 1, 9, 20};
-    private static final int pkcs9KeyId[] = {1, 2, 840, 113549, 1, 9, 21};
+    private static final int[] pkcs9Name  = {1, 2, 840, 113549, 1, 9, 20};
+    private static final int[] pkcs9KeyId = {1, 2, 840, 113549, 1, 9, 21};
 
-    private static final int pkcs9certType[] = {1, 2, 840, 113549, 1, 9, 22, 1};
+    private static final int[] pkcs9certType = {1, 2, 840, 113549, 1, 9, 22, 1};
 
-    private static final int pbeWithSHAAnd40BitRC2CBC[] =
+    private static final int[] pbeWithSHAAnd40BitRC2CBC =
                                         {1, 2, 840, 113549, 1, 12, 1, 6};
-    private static final int pbeWithSHAAnd3KeyTripleDESCBC[] =
+    private static final int[] pbeWithSHAAnd3KeyTripleDESCBC =
                                         {1, 2, 840, 113549, 1, 12, 1, 3};
-    private static final int pbes2[] = {1, 2, 840, 113549, 1, 5, 13};
+    private static final int[] pbes2 = {1, 2, 840, 113549, 1, 5, 13};
     // TODO: temporary Oracle OID
     /*
      * { joint-iso-itu-t(2) country(16) us(840) organization(1) oracle(113894)
      *   jdk(746875) crypto(1) id-at-trustedKeyUsage(1) }
      */
-    private static final int TrustedKeyUsage[] =
+    private static final int[] TrustedKeyUsage =
                                         {2, 16, 840, 1, 113894, 746875, 1, 1};
-    private static final int AnyExtendedKeyUsage[] = {2, 5, 29, 37, 0};
+    private static final int[] AnyExtendedKeyUsage = {2, 5, 29, 37, 0};
 
     private static ObjectIdentifier PKCS8ShroudedKeyBag_OID;
     private static ObjectIdentifier CertBag_OID;
@@ -243,7 +243,7 @@
     // A private key entry and its supporting certificate chain
     private static class PrivateKeyEntry extends KeyEntry {
         byte[] protectedPrivKey;
-        Certificate chain[];
+        Certificate[] chain;
     };
 
     // A secret key
--- a/jdk/src/java.base/share/classes/sun/security/provider/AuthPolicyFile.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/AuthPolicyFile.java	Wed Jul 05 20:41:30 2017 +0200
@@ -403,7 +403,7 @@
                         debug.println("  "+perm);
                     }
                 } catch (ClassNotFoundException cnfe) {
-                    Certificate certs[];
+                    Certificate[] certs;
                     if (pe.signedBy != null) {
                         certs = getCertificates(keyStore, pe.signedBy);
                     } else {
@@ -623,7 +623,7 @@
             init();
         }
 
-        final CodeSource codesource[] = {null};
+        final CodeSource[] codesource = {null};
 
         codesource[0] = canonicalizeCodebase(cs, true);
 
@@ -666,7 +666,7 @@
         // now see if any of the keys are trusted ids.
 
         if (!ignoreIdentityScope) {
-            Certificate certs[] = codesource[0].getCertificates();
+            Certificate[] certs = codesource[0].getCertificates();
             if (certs != null) {
                 for (int k=0; k < certs.length; k++) {
                     if (aliasMapping.get(certs[k]) == null &&
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAParameterGenerator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -237,7 +237,7 @@
             BigInteger offset = ONE;
             /* Step 11 */
             for (counter = 0; counter < 4*valueL; counter++) {
-                BigInteger V[] = new BigInteger[n + 1];
+                BigInteger[] V = new BigInteger[n + 1];
                 /* Step 11.1 */
                 for (int j = 0; j <= n; j++) {
                     BigInteger J = BigInteger.valueOf(j);
--- a/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/JavaKeyStore.java	Wed Jul 05 20:41:30 2017 +0200
@@ -82,7 +82,7 @@
     private static class KeyEntry {
         Date date; // the creation date of this entry
         byte[] protectedPrivKey;
-        Certificate chain[];
+        Certificate[] chain;
     };
 
     // Trusted certificates
@@ -604,7 +604,7 @@
              * the keystore (such as deleting or modifying key or
              * certificate entries).
              */
-            byte digest[] = md.digest();
+            byte[] digest = md.digest();
 
             dos.write(digest);
             dos.flush();
@@ -770,9 +770,8 @@
              * with
              */
             if (password != null) {
-                byte computed[], actual[];
-                computed = md.digest();
-                actual = new byte[computed.length];
+                byte[] computed = md.digest();
+                byte[] actual = new byte[computed.length];
                 dis.readFully(actual);
                 for (int i = 0; i < computed.length; i++) {
                     if (computed[i] != actual[i]) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Wed Jul 05 20:41:30 2017 +0200
@@ -795,7 +795,7 @@
                         // an unresolved permission which will be resolved
                         // when implies is called
                         // Add it to entry
-                        Certificate certs[];
+                        Certificate[] certs;
                         if (pe.signedBy != null) {
                             certs = getCertificates(keyStore,
                                                     pe.signedBy,
@@ -817,7 +817,7 @@
                         debug.println("  "+perm);
                     }
                 } catch (ClassNotFoundException cnfe) {
-                    Certificate certs[];
+                    Certificate[] certs;
                     if (pe.signedBy != null) {
                         certs = getCertificates(keyStore,
                                                 pe.signedBy,
@@ -2032,7 +2032,7 @@
          *
          * @serial
          */
-        private Certificate certs[];
+        private Certificate[] certs;
 
         /**
          * Creates a new SelfPermission containing the permission
@@ -2048,7 +2048,7 @@
          * certificate first and the (root) certificate authority last).
          */
         public SelfPermission(String type, String name, String actions,
-                              Certificate certs[])
+                              Certificate[] certs)
         {
             super(type);
             if (type == null) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/PolicyParser.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1353,7 +1353,7 @@
         }
     }
 
-    public static void main(String arg[]) throws Exception {
+    public static void main(String[] arg) throws Exception {
         try (FileReader fr = new FileReader(arg[0]);
              FileWriter fw = new FileWriter(arg[1])) {
             PolicyParser pp = new PolicyParser(true);
--- a/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SecureRandom.java	Wed Jul 05 20:41:30 2017 +0200
@@ -85,7 +85,7 @@
      *
      * @param seed the seed.
      */
-    private SecureRandom(byte seed[]) {
+    private SecureRandom(byte[] seed) {
         init(seed);
     }
 
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ByteBufferInputStream.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ByteBufferInputStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -70,7 +70,7 @@
      * Increments position().
      */
     @Override
-    public int read(byte b[]) throws IOException {
+    public int read(byte[] b) throws IOException {
 
         if (bb == null) {
             throw new IOException("read on a closed InputStream");
@@ -85,7 +85,7 @@
      * Increments position().
      */
     @Override
-    public int read(byte b[], int off, int len) throws IOException {
+    public int read(byte[] b, int off, int len) throws IOException {
 
         if (bb == null) {
             throw new IOException("read on a closed InputStream");
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Wed Jul 05 20:41:30 2017 +0200
@@ -810,7 +810,7 @@
             String alias = null;
             int keytypesTmpSize = keytypesTmp.size();
             if (keytypesTmpSize != 0) {
-                String keytypes[] =
+                String[] keytypes =
                         keytypesTmp.toArray(new String[keytypesTmpSize]);
 
                 if (conn != null) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java	Wed Jul 05 20:41:30 2017 +0200
@@ -48,7 +48,7 @@
      * This value may be empty if it was included in the
      * client's certificate ...
      */
-    private byte dh_Yc[];               // 1 to 2^16 -1 bytes
+    private byte[] dh_Yc;               // 1 to 2^16 -1 bytes
 
     BigInteger getClientPublicKey() {
         return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -146,7 +146,7 @@
     byte[] getBytes8() throws IOException {
         int len = getInt8();
         verifyLength(len);
-        byte b[] = new byte[len];
+        byte[] b = new byte[len];
 
         read(b);
         return b;
@@ -155,7 +155,7 @@
     public byte[] getBytes16() throws IOException {
         int len = getInt16();
         verifyLength(len);
-        byte b[] = new byte[len];
+        byte[] b = new byte[len];
 
         read(b);
         return b;
@@ -164,7 +164,7 @@
     byte[] getBytes24() throws IOException {
         int len = getInt24();
         verifyLength(len);
-        byte b[] = new byte[len];
+        byte[] b = new byte[len];
 
         read(b);
         return b;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java	Wed Jul 05 20:41:30 2017 +0200
@@ -689,8 +689,8 @@
 static final
 class RSA_ServerKeyExchange extends ServerKeyExchange
 {
-    private byte rsa_modulus[];     // 1 to 2^16 - 1 bytes
-    private byte rsa_exponent[];    // 1 to 2^16 - 1 bytes
+    private byte[] rsa_modulus;     // 1 to 2^16 - 1 bytes
+    private byte[] rsa_exponent;    // 1 to 2^16 - 1 bytes
 
     private Signature signature;
     private byte[] signatureBytes;
@@ -698,7 +698,7 @@
     /*
      * Hash the nonces and the ephemeral RSA public key.
      */
-    private void updateSignature(byte clntNonce[], byte svrNonce[])
+    private void updateSignature(byte[] clntNonce, byte[] svrNonce)
             throws SignatureException {
         int tmp;
 
@@ -827,11 +827,11 @@
     private final static boolean dhKeyExchangeFix =
         Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
 
-    private byte                dh_p [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_g [];        // 1 to 2^16 - 1 bytes
-    private byte                dh_Ys [];       // 1 to 2^16 - 1 bytes
+    private byte[]                dh_p;        // 1 to 2^16 - 1 bytes
+    private byte[]                dh_g;        // 1 to 2^16 - 1 bytes
+    private byte[]                dh_Ys;       // 1 to 2^16 - 1 bytes
 
-    private byte                signature [];
+    private byte[]                signature;
 
     // protocol version being established using this ServerKeyExchange message
     ProtocolVersion protocolVersion;
@@ -857,8 +857,8 @@
      * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
      * key exchange.  (Constructor called by server.)
      */
-    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
-            byte svrNonce[], SecureRandom sr,
+    DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte[] clntNonce,
+            byte[] svrNonce, SecureRandom sr,
             SignatureAndHashAlgorithm signAlgorithm,
             ProtocolVersion protocolVersion) throws GeneralSecurityException {
 
@@ -913,7 +913,7 @@
      * DHE_DSS or DHE_RSA key exchange.  (Called by client.)
      */
     DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
-            byte clntNonce[], byte svrNonce[], int messageSize,
+            byte[] clntNonce, byte[] svrNonce, int messageSize,
             Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
             ProtocolVersion protocolVersion)
             throws IOException, GeneralSecurityException {
@@ -948,7 +948,7 @@
         }
 
         // read the signature
-        byte signature[];
+        byte[] signature;
         if (dhKeyExchangeFix) {
             signature = input.getBytes16();
         } else {
@@ -1004,8 +1004,8 @@
     /*
      * Update sig with nonces and Diffie-Hellman public key.
      */
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
+    private void updateSignature(Signature sig, byte[] clntNonce,
+            byte[] svrNonce) throws SignatureException {
         int tmp;
 
         sig.update(clntNonce);
@@ -1268,8 +1268,8 @@
             }
     }
 
-    private void updateSignature(Signature sig, byte clntNonce[],
-            byte svrNonce[]) throws SignatureException {
+    private void updateSignature(Signature sig, byte[] clntNonce,
+            byte[] svrNonce) throws SignatureException {
         sig.update(clntNonce);
         sig.update(svrNonce);
 
@@ -1334,7 +1334,7 @@
      * DER encoded distinguished name.
      * TLS requires that its not longer than 65535 bytes.
      */
-    byte name[];
+    byte[] name;
 
     DistinguishedName(HandshakeInStream input) throws IOException {
         name = input.getBytes16();
@@ -1411,8 +1411,8 @@
     private final static byte[] TYPES_ECC =
         { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
 
-    byte                types [];               // 1 to 255 types
-    DistinguishedName   authorities [];         // 3 to 2^16 - 1
+    byte[]                types;               // 1 to 255 types
+    DistinguishedName[]   authorities;         // 3 to 2^16 - 1
         // ... "3" because that's the smallest DER-encoded X500 DN
 
     // protocol version being established using this CertificateRequest message
@@ -1424,7 +1424,7 @@
     // length of supported_signature_algorithms
     private int algorithmsLen;
 
-    CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
+    CertificateRequest(X509Certificate[] ca, KeyExchange keyExchange,
             Collection<SignatureAndHashAlgorithm> signAlgs,
             ProtocolVersion protocolVersion) throws IOException {
 
@@ -2063,7 +2063,7 @@
         if (protocolVersion.useTLS10PlusSpec()) {
             // TLS 1.0+
             try {
-                byte [] seed;
+                byte[] seed;
                 String prfAlg;
                 PRF prf;
 
--- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeOutStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -119,7 +119,7 @@
         }
     }
 
-    public void putBytes16(byte b[]) throws IOException {
+    public void putBytes16(byte[] b) throws IOException {
         if (b == null) {
             putInt16(0);
         } else {
@@ -128,7 +128,7 @@
         }
     }
 
-    void putBytes24(byte b[]) throws IOException {
+    void putBytes24(byte[] b) throws IOException {
         if (b == null) {
             putInt24(0);
         } else {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/MAC.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/MAC.java	Wed Jul 05 20:41:30 2017 +0200
@@ -52,7 +52,7 @@
     final static MAC TLS_NULL = new MAC(false);
 
     // Value of the null MAC is fixed
-    private static final byte nullMAC[] = new byte[0];
+    private static final byte[] nullMAC = new byte[0];
 
     // internal identifier for the MAC algorithm
     private final MacAlg macAlg;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/RandomCookie.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/RandomCookie.java	Wed Jul 05 20:41:30 2017 +0200
@@ -38,7 +38,7 @@
  */
 final class RandomCookie {
 
-    byte random_bytes[];  // exactly 32 bytes
+    byte[] random_bytes;  // exactly 32 bytes
 
     RandomCookie(SecureRandom generator) {
         long temp = System.currentTimeMillis() / 1000;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Wed Jul 05 20:41:30 2017 +0200
@@ -986,7 +986,7 @@
                 ClientKeyExchangeService.find(keyExchange.name) == null) {
 
             CertificateRequest m4;
-            X509Certificate caCerts[];
+            X509Certificate[] caCerts;
 
             Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
             if (protocolVersion.useTLS12PlusSpec()) {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SessionId.java	Wed Jul 05 20:41:30 2017 +0200
@@ -43,7 +43,7 @@
 class SessionId
 {
     static int MAX_LENGTH = 32;
-    private byte sessionId [];          // max 32 bytes
+    private byte[] sessionId;          // max 32 bytes
 
     /** Constructs a new session ID ... perhaps for a rejoinable session */
     SessionId (boolean isRejoinable, SecureRandom generator)
@@ -56,7 +56,7 @@
     }
 
     /** Constructs a session ID from a byte array (max size 32 bytes) */
-    SessionId (byte sessionId [])
+    SessionId (byte[] sessionId)
         { this.sessionId = sessionId; }
 
     /** Returns the length of the ID, in bytes */
@@ -64,7 +64,7 @@
         { return sessionId.length; }
 
     /** Returns the bytes in the ID.  May be an empty array.  */
-    byte [] getId ()
+    byte[] getId ()
     {
         return sessionId.clone ();
     }
@@ -106,7 +106,7 @@
             return false;
 
         SessionId s = (SessionId) obj;
-        byte b [] = s.getId ();
+        byte[] b = s.getId ();
 
         if (b.length != sessionId.length)
             return false;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -94,13 +94,13 @@
     }
 
     @Override
-    public void checkClientTrusted(X509Certificate chain[], String authType)
+    public void checkClientTrusted(X509Certificate[] chain, String authType)
             throws CertificateException {
         checkTrusted(chain, authType, (Socket)null, true);
     }
 
     @Override
-    public void checkServerTrusted(X509Certificate chain[], String authType)
+    public void checkServerTrusted(X509Certificate[] chain, String authType)
             throws CertificateException {
         checkTrusted(chain, authType, (Socket)null, false);
     }
--- a/jdk/src/java.base/share/classes/sun/security/util/ManifestDigester.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/ManifestDigester.java	Wed Jul 05 20:41:30 2017 +0200
@@ -37,7 +37,7 @@
     public static final String MF_MAIN_ATTRS = "Manifest-Main-Attributes";
 
     /** the raw bytes of the manifest */
-    private byte rawBytes[];
+    private byte[] rawBytes;
 
     /** the offset/length pair for a section */
     private HashMap<String, Entry> entries; // key is a UTF-8 string
@@ -107,7 +107,7 @@
         return false;
     }
 
-    public ManifestDigester(byte bytes[])
+    public ManifestDigester(byte[] bytes)
     {
         rawBytes = bytes;
         entries = new HashMap<>();
@@ -181,7 +181,7 @@
         }
     }
 
-    private boolean isNameAttr(byte bytes[], int start)
+    private boolean isNameAttr(byte[] bytes, int start)
     {
         return ((bytes[start] == 'N') || (bytes[start] == 'n')) &&
                ((bytes[start+1] == 'a') || (bytes[start+1] == 'A')) &&
@@ -261,11 +261,10 @@
         return e;
     }
 
-    public byte[] manifestDigest(MessageDigest md)
-        {
-            md.reset();
-            md.update(rawBytes, 0, rawBytes.length);
-            return md.digest();
-        }
+    public byte[] manifestDigest(MessageDigest md) {
+        md.reset();
+        md.update(rawBytes, 0, rawBytes.length);
+        return md.digest();
+    }
 
 }
--- a/jdk/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/ManifestEntryVerifier.java	Wed Jul 05 20:41:30 2017 +0200
@@ -165,7 +165,7 @@
     /**
      * update the digests for the digests we are interested in
      */
-    public void update(byte buffer[], int off, int len) {
+    public void update(byte[] buffer, int off, int len) {
         if (skip) return;
 
         for (int i=0; i < digests.size(); i++) {
--- a/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java	Wed Jul 05 20:41:30 2017 +0200
@@ -212,7 +212,7 @@
      * Constructor, from an array of integers.
      * Validity check included.
      */
-    public ObjectIdentifier (int values []) throws IOException
+    public ObjectIdentifier(int[] values) throws IOException
     {
         checkCount(values.length);
         checkFirstComponent(values[0]);
--- a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java	Wed Jul 05 20:41:30 2017 +0200
@@ -55,7 +55,7 @@
     private PKCS7 block;
 
     /** the raw bytes of the .SF file */
-    private byte sfBytes[];
+    private byte[] sfBytes;
 
     /** the name of the signature block file, uppercased and without
      *  the extension (.DSA/.RSA/.EC)
@@ -84,7 +84,7 @@
     public SignatureFileVerifier(ArrayList<CodeSigner[]> signerCache,
                                  ManifestDigester md,
                                  String name,
-                                 byte rawBytes[])
+                                 byte[] rawBytes)
         throws IOException, CertificateException
     {
         // new PKCS7() calls CertificateFactory.getInstance()
@@ -129,7 +129,7 @@
      * used to set the raw bytes of the .SF file when it
      * is external to the signature block file.
      */
-    public void setSignatureFile(byte sfBytes[])
+    public void setSignatureFile(byte[] sfBytes)
     {
         this.sfBytes = sfBytes;
     }
@@ -511,7 +511,7 @@
      * CodeSigner objects. We do this only *once* for a given
      * signature block file.
      */
-    private CodeSigner[] getSigners(SignerInfo infos[], PKCS7 block)
+    private CodeSigner[] getSigners(SignerInfo[] infos, PKCS7 block)
         throws IOException, NoSuchAlgorithmException, SignatureException,
             CertificateException {
 
--- a/jdk/src/java.base/share/classes/sun/security/x509/AVA.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AVA.java	Wed Jul 05 20:41:30 2017 +0200
@@ -967,7 +967,7 @@
 
                     previousWhite = false;
 
-                    byte valueBytes[] = null;
+                    byte[] valueBytes = null;
                     try {
                         valueBytes = Character.toString(c).getBytes("UTF8");
                     } catch (IOException ie) {
@@ -1051,7 +1051,7 @@
                 // using the hex format below.  This will be used only
                 // when the value is not a string type
 
-                byte    data [] = value.toByteArray();
+                byte[] data = value.toByteArray();
 
                 retval.append('#');
                 for (int i = 0; i < data.length; i++) {
--- a/jdk/src/java.base/share/classes/sun/security/x509/AlgIdDSA.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgIdDSA.java	Wed Jul 05 20:41:30 2017 +0200
@@ -117,7 +117,7 @@
      * @param q the DSS/DSA parameter "Q"
      * @param g the DSS/DSA parameter "G"
      */
-    public AlgIdDSA (byte p [], byte q [], byte g [])
+    public AlgIdDSA (byte[] p, byte[] q, byte[] g)
     throws IOException
     {
         this (new BigInteger (1, p),
--- a/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/AlgorithmId.java	Wed Jul 05 20:41:30 2017 +0200
@@ -648,12 +648,12 @@
     /*
      * COMMON PUBLIC KEY TYPES
      */
-    private static final int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 };
-    private static final int DH_PKIX_data[] = { 1, 2, 840, 10046, 2, 1 };
-    private static final int DSA_OIW_data[] = { 1, 3, 14, 3, 2, 12 };
-    private static final int DSA_PKIX_data[] = { 1, 2, 840, 10040, 4, 1 };
-    private static final int RSA_data[] = { 2, 5, 8, 1, 1 };
-    private static final int RSAEncryption_data[] =
+    private static final int[] DH_data = { 1, 2, 840, 113549, 1, 3, 1 };
+    private static final int[] DH_PKIX_data = { 1, 2, 840, 10046, 2, 1 };
+    private static final int[] DSA_OIW_data = { 1, 3, 14, 3, 2, 12 };
+    private static final int[] DSA_PKIX_data = { 1, 2, 840, 10040, 4, 1 };
+    private static final int[] RSA_data = { 2, 5, 8, 1, 1 };
+    private static final int[] RSAEncryption_data =
                                  { 1, 2, 840, 113549, 1, 1, 1 };
 
     public static final ObjectIdentifier DH_oid;
@@ -674,27 +674,27 @@
     /*
      * COMMON SIGNATURE ALGORITHMS
      */
-    private static final int md2WithRSAEncryption_data[] =
+    private static final int[] md2WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 2 };
-    private static final int md5WithRSAEncryption_data[] =
+    private static final int[] md5WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 4 };
-    private static final int sha1WithRSAEncryption_data[] =
+    private static final int[] sha1WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 5 };
-    private static final int sha1WithRSAEncryption_OIW_data[] =
+    private static final int[] sha1WithRSAEncryption_OIW_data =
                                        { 1, 3, 14, 3, 2, 29 };
-    private static final int sha224WithRSAEncryption_data[] =
+    private static final int[] sha224WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 14 };
-    private static final int sha256WithRSAEncryption_data[] =
+    private static final int[] sha256WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 11 };
-    private static final int sha384WithRSAEncryption_data[] =
+    private static final int[] sha384WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 12 };
-    private static final int sha512WithRSAEncryption_data[] =
+    private static final int[] sha512WithRSAEncryption_data =
                                        { 1, 2, 840, 113549, 1, 1, 13 };
-    private static final int shaWithDSA_OIW_data[] =
+    private static final int[] shaWithDSA_OIW_data =
                                        { 1, 3, 14, 3, 2, 13 };
-    private static final int sha1WithDSA_OIW_data[] =
+    private static final int[] sha1WithDSA_OIW_data =
                                        { 1, 3, 14, 3, 2, 27 };
-    private static final int dsaWithSHA1_PKIX_data[] =
+    private static final int[] dsaWithSHA1_PKIX_data =
                                        { 1, 2, 840, 10040, 4, 3 };
 
     public static final ObjectIdentifier md2WithRSAEncryption_oid;
--- a/jdk/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/NetscapeCertTypeExtension.java	Wed Jul 05 20:41:30 2017 +0200
@@ -69,7 +69,7 @@
     public static final String S_MIME_CA = "s_mime_ca";
     public static final String OBJECT_SIGNING_CA = "object_signing_ca";
 
-    private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
+    private static final int[] CertType_data = { 2, 16, 840, 1, 113730, 1, 1 };
 
     /**
      * Object identifier for the Netscape-Cert-Type extension.
--- a/jdk/src/java.base/share/classes/sun/security/x509/OIDMap.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/OIDMap.java	Wed Jul 05 20:41:30 2017 +0200
@@ -102,7 +102,7 @@
     private static final String OCSPNOCHECK = ROOT + "." +
                                         OCSPNoCheckExtension.NAME;
 
-    private static final int NetscapeCertType_data[] =
+    private static final int[] NetscapeCertType_data =
         { 2, 16, 840, 1, 113730, 1, 1 };
 
     /** Map ObjectIdentifier(oid) -> OIDInfo(info) */
--- a/jdk/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/PKIXExtensions.java	Wed Jul 05 20:41:30 2017 +0200
@@ -49,32 +49,32 @@
  */
 public class PKIXExtensions {
     // The object identifiers
-    private static final int AuthorityKey_data [] = { 2, 5, 29, 35 };
-    private static final int SubjectKey_data [] = { 2, 5, 29, 14 };
-    private static final int KeyUsage_data [] = { 2, 5, 29, 15 };
-    private static final int PrivateKeyUsage_data [] = { 2, 5, 29, 16 };
-    private static final int CertificatePolicies_data [] = { 2, 5, 29, 32 };
-    private static final int PolicyMappings_data [] = { 2, 5, 29, 33 };
-    private static final int SubjectAlternativeName_data [] = { 2, 5, 29, 17 };
-    private static final int IssuerAlternativeName_data [] = { 2, 5, 29, 18 };
-    private static final int SubjectDirectoryAttributes_data [] = { 2, 5, 29, 9 };
-    private static final int BasicConstraints_data [] = { 2, 5, 29, 19 };
-    private static final int NameConstraints_data [] = { 2, 5, 29, 30 };
-    private static final int PolicyConstraints_data [] = { 2, 5, 29, 36 };
-    private static final int CRLDistributionPoints_data [] = { 2, 5, 29, 31 };
-    private static final int CRLNumber_data [] = { 2, 5, 29, 20 };
-    private static final int IssuingDistributionPoint_data [] = { 2, 5, 29, 28 };
-    private static final int DeltaCRLIndicator_data [] = { 2, 5, 29, 27 };
-    private static final int ReasonCode_data [] = { 2, 5, 29, 21 };
-    private static final int HoldInstructionCode_data [] = { 2, 5, 29, 23 };
-    private static final int InvalidityDate_data [] = { 2, 5, 29, 24 };
-    private static final int ExtendedKeyUsage_data [] = { 2, 5, 29, 37 };
-    private static final int InhibitAnyPolicy_data [] = { 2, 5, 29, 54 };
-    private static final int CertificateIssuer_data [] = { 2, 5, 29, 29 };
-    private static final int AuthInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 1};
-    private static final int SubjectInfoAccess_data [] = { 1, 3, 6, 1, 5, 5, 7, 1, 11};
-    private static final int FreshestCRL_data [] = { 2, 5, 29, 46 };
-    private static final int OCSPNoCheck_data [] = { 1, 3, 6, 1, 5, 5, 7,
+    private static final int[] AuthorityKey_data = { 2, 5, 29, 35 };
+    private static final int[] SubjectKey_data = { 2, 5, 29, 14 };
+    private static final int[] KeyUsage_data = { 2, 5, 29, 15 };
+    private static final int[] PrivateKeyUsage_data = { 2, 5, 29, 16 };
+    private static final int[] CertificatePolicies_data = { 2, 5, 29, 32 };
+    private static final int[] PolicyMappings_data = { 2, 5, 29, 33 };
+    private static final int[] SubjectAlternativeName_data = { 2, 5, 29, 17 };
+    private static final int[] IssuerAlternativeName_data = { 2, 5, 29, 18 };
+    private static final int[] SubjectDirectoryAttributes_data = { 2, 5, 29, 9 };
+    private static final int[] BasicConstraints_data = { 2, 5, 29, 19 };
+    private static final int[] NameConstraints_data = { 2, 5, 29, 30 };
+    private static final int[] PolicyConstraints_data = { 2, 5, 29, 36 };
+    private static final int[] CRLDistributionPoints_data = { 2, 5, 29, 31 };
+    private static final int[] CRLNumber_data = { 2, 5, 29, 20 };
+    private static final int[] IssuingDistributionPoint_data = { 2, 5, 29, 28 };
+    private static final int[] DeltaCRLIndicator_data = { 2, 5, 29, 27 };
+    private static final int[] ReasonCode_data = { 2, 5, 29, 21 };
+    private static final int[] HoldInstructionCode_data = { 2, 5, 29, 23 };
+    private static final int[] InvalidityDate_data = { 2, 5, 29, 24 };
+    private static final int[] ExtendedKeyUsage_data = { 2, 5, 29, 37 };
+    private static final int[] InhibitAnyPolicy_data = { 2, 5, 29, 54 };
+    private static final int[] CertificateIssuer_data = { 2, 5, 29, 29 };
+    private static final int[] AuthInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 1};
+    private static final int[] SubjectInfoAccess_data = { 1, 3, 6, 1, 5, 5, 7, 1, 11};
+    private static final int[] FreshestCRL_data = { 2, 5, 29, 46 };
+    private static final int[] OCSPNoCheck_data = { 1, 3, 6, 1, 5, 5, 7,
                                                     48, 1, 5};
 
     /**
--- a/jdk/src/java.base/share/classes/sun/security/x509/X500Name.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X500Name.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1119,25 +1119,25 @@
      * Includes all those specified in RFC 5280 as MUST or SHOULD
      * be recognized
      */
-    private static final int commonName_data[] = { 2, 5, 4, 3 };
-    private static final int SURNAME_DATA[] = { 2, 5, 4, 4 };
-    private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 };
-    private static final int countryName_data[] = { 2, 5, 4, 6 };
-    private static final int localityName_data[] = { 2, 5, 4, 7 };
-    private static final int stateName_data[] = { 2, 5, 4, 8 };
-    private static final int streetAddress_data[] = { 2, 5, 4, 9 };
-    private static final int orgName_data[] = { 2, 5, 4, 10 };
-    private static final int orgUnitName_data[] = { 2, 5, 4, 11 };
-    private static final int title_data[] = { 2, 5, 4, 12 };
-    private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 };
-    private static final int INITIALS_DATA[] = { 2, 5, 4, 43 };
-    private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 };
-    private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 };
+    private static final int[] commonName_data = { 2, 5, 4, 3 };
+    private static final int[] SURNAME_DATA = { 2, 5, 4, 4 };
+    private static final int[] SERIALNUMBER_DATA = { 2, 5, 4, 5 };
+    private static final int[] countryName_data = { 2, 5, 4, 6 };
+    private static final int[] localityName_data = { 2, 5, 4, 7 };
+    private static final int[] stateName_data = { 2, 5, 4, 8 };
+    private static final int[] streetAddress_data = { 2, 5, 4, 9 };
+    private static final int[] orgName_data = { 2, 5, 4, 10 };
+    private static final int[] orgUnitName_data = { 2, 5, 4, 11 };
+    private static final int[] title_data = { 2, 5, 4, 12 };
+    private static final int[] GIVENNAME_DATA = { 2, 5, 4, 42 };
+    private static final int[] INITIALS_DATA = { 2, 5, 4, 43 };
+    private static final int[] GENERATIONQUALIFIER_DATA = { 2, 5, 4, 44 };
+    private static final int[] DNQUALIFIER_DATA = { 2, 5, 4, 46 };
 
-    private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 };
-    private static final int DOMAIN_COMPONENT_DATA[] =
+    private static final int[] ipAddress_data = { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 };
+    private static final int[] DOMAIN_COMPONENT_DATA =
         { 0, 9, 2342, 19200300, 100, 1, 25 };
-    private static final int userid_data[] =
+    private static final int[] userid_data =
         { 0, 9, 2342, 19200300, 100, 1, 1 };
 
 
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1086,7 +1086,7 @@
             throw new CRLException("Invalid DER-encoded CRL data");
 
         signedCRL = val.toByteArray();
-        DerValue seq[] = new DerValue[3];
+        DerValue[] seq = new DerValue[3];
 
         seq[0] = val.data.getDerValue();
         seq[1] = val.data.getDerValue();
--- a/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java	Wed Jul 05 20:41:30 2017 +0200
@@ -142,7 +142,8 @@
     public IdentityArrayList(Collection<? extends E> c) {
         elementData = c.toArray();
         size = elementData.length;
-        // c.toArray might (incorrectly) not return Object[] (see 6260652)
+        // defend against c.toArray (incorrectly) not returning Object[]
+        // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
         if (elementData.getClass() != Object[].class)
             elementData = Arrays.copyOf(elementData, size, Object[].class);
     }
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java	Wed Jul 05 20:41:30 2017 +0200
@@ -427,7 +427,7 @@
 
 
     /*
-      public static void main(String args[]) throws Exception {
+      public static void main(String[] args) throws Exception {
       ServicePermission this_ =
       new ServicePermission(args[0], "accept");
       ServicePermission that_ =
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -75,7 +75,7 @@
     }
 
     GSSCredentialImpl(GSSManagerImpl gssManager, GSSName name,
-                      int lifetime, Oid mechs[], int usage)
+                      int lifetime, Oid[] mechs, int usage)
         throws GSSException {
         init(gssManager);
         boolean defaultList = false;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/GSSManagerImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -128,7 +128,7 @@
         return new GSSNameImpl(this, nameStr, nameType);
     }
 
-    public GSSName createName(byte name[], Oid nameType)
+    public GSSName createName(byte[] name, Oid nameType)
         throws GSSException {
         return new GSSNameImpl(this, name, nameType);
     }
@@ -138,7 +138,7 @@
         return new GSSNameImpl(this, nameStr, nameType, mech);
     }
 
-    public GSSName createName(byte name[], Oid nameType, Oid mech)
+    public GSSName createName(byte[] name, Oid nameType, Oid mech)
         throws GSSException {
         return new GSSNameImpl(this, name, nameType, mech);
     }
@@ -155,7 +155,7 @@
     }
 
     public GSSCredential createCredential(GSSName aName,
-                                          int lifetime, Oid mechs[], int usage)
+                                          int lifetime, Oid[] mechs, int usage)
         throws GSSException {
         return wrap(new GSSCredentialImpl(this, aName, lifetime, mechs, usage));
     }
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java	Wed Jul 05 20:41:30 2017 +0200
@@ -159,7 +159,7 @@
     /**
      * Constructor for Krb5Context to import a previously exported context.
      */
-    public Krb5Context(GSSCaller caller, byte [] interProcessToken)
+    public Krb5Context(GSSCaller caller, byte[] interProcessToken)
         throws GSSException {
         throw new GSSException(GSSException.UNAVAILABLE,
                                -1, "GSS Import Context not available");
@@ -905,7 +905,7 @@
      * and verifyMIC care about the remote sequence number (peerSeqNumber).
      */
 
-    public final byte[] wrap(byte inBuf[], int offset, int len,
+    public final byte[] wrap(byte[] inBuf, int offset, int len,
                              MessageProp msgProp) throws GSSException {
         if (DEBUG) {
             System.out.println("Krb5Context.wrap: data=["
@@ -943,7 +943,7 @@
         }
     }
 
-    public final int wrap(byte inBuf[], int inOffset, int len,
+    public final int wrap(byte[] inBuf, int inOffset, int len,
                           byte[] outBuf, int outOffset,
                           MessageProp msgProp) throws GSSException {
 
@@ -977,7 +977,7 @@
         }
     }
 
-    public final void wrap(byte inBuf[], int offset, int len,
+    public final void wrap(byte[] inBuf, int offset, int len,
                            OutputStream os, MessageProp msgProp)
         throws GSSException {
 
@@ -1032,7 +1032,7 @@
         wrap(data, 0, data.length, os, msgProp);
     }
 
-    public final byte[] unwrap(byte inBuf[], int offset, int len,
+    public final byte[] unwrap(byte[] inBuf, int offset, int len,
                                MessageProp msgProp)
         throws GSSException {
 
@@ -1069,7 +1069,7 @@
             return data;
         }
 
-    public final int unwrap(byte inBuf[], int inOffset, int len,
+    public final int unwrap(byte[] inBuf, int inOffset, int len,
                              byte[] outBuf, int outOffset,
                              MessageProp msgProp) throws GSSException {
 
@@ -1141,7 +1141,7 @@
         }
     }
 
-    public final byte[] getMIC(byte []inMsg, int offset, int len,
+    public final byte[] getMIC(byte[] inMsg, int offset, int len,
                                MessageProp msgProp)
         throws GSSException {
 
@@ -1166,7 +1166,7 @@
             }
         }
 
-    private int getMIC(byte []inMsg, int offset, int len,
+    private int getMIC(byte[] inMsg, int offset, int len,
                        byte[] outBuf, int outOffset,
                        MessageProp msgProp)
         throws GSSException {
@@ -1236,7 +1236,7 @@
         getMIC(data, 0, data.length, os, msgProp);
     }
 
-    public final void verifyMIC(byte []inTok, int tokOffset, int tokLen,
+    public final void verifyMIC(byte[] inTok, int tokOffset, int tokLen,
                                 byte[] inMsg, int msgOffset, int msgLen,
                                 MessageProp msgProp)
         throws GSSException {
@@ -1293,7 +1293,7 @@
      * @param os the output token will be written to this stream
      * @exception GSSException
      */
-    public final byte [] export() throws GSSException {
+    public final byte[] export() throws GSSException {
         throw new GSSException(GSSException.UNAVAILABLE, -1,
                                "GSS Export Context not available");
     }
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/spi/GSSContextSpi.java	Wed Jul 05 20:41:30 2017 +0200
@@ -265,7 +265,7 @@
     /**
      * For apps that want simplicity and don't care about buffer copies.
      */
-    public byte[] wrap(byte inBuf[], int offset, int len,
+    public byte[] wrap(byte[] inBuf, int offset, int len,
                        MessageProp msgProp) throws GSSException;
 
     /**
@@ -275,7 +275,7 @@
      *
      * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext
      *
-    public int wrap(byte inBuf[], int inOffset, int len,
+    public int wrap(byte[] inBuf, int inOffset, int len,
                     byte[] outBuf, int outOffset,
                     MessageProp msgProp) throws GSSException;
 
@@ -292,7 +292,7 @@
      *
      * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext
      *
-    public void wrap(byte inBuf[], int offset, int len,
+    public void wrap(byte[] inBuf, int offset, int len,
                      OutputStream os, MessageProp msgProp)
         throws GSSException;
     */
@@ -314,7 +314,7 @@
     /**
      * For apps that want simplicity and don't care about buffer copies.
      */
-    public byte[] unwrap(byte inBuf[], int offset, int len,
+    public byte[] unwrap(byte[] inBuf, int offset, int len,
                          MessageProp msgProp) throws GSSException;
 
     /**
@@ -324,7 +324,7 @@
      *
      * NOTE: This method is not defined in public class org.ietf.jgss.GSSContext
      *
-    public int unwrap(byte inBuf[], int inOffset, int len,
+    public int unwrap(byte[] inBuf, int inOffset, int len,
                       byte[] outBuf, int outOffset,
                       MessageProp msgProp) throws GSSException;
 
@@ -356,7 +356,7 @@
                         MessageProp msgProp)
                 throws GSSException;
 
-    public byte[] getMIC(byte []inMsg, int offset, int len,
+    public byte[] getMIC(byte[] inMsg, int offset, int len,
                          MessageProp msgProp) throws GSSException;
 
     /**
@@ -372,7 +372,7 @@
     public void verifyMIC(InputStream is, InputStream msgStr,
                            MessageProp mProp) throws GSSException;
 
-    public void verifyMIC(byte []inTok, int tokOffset, int tokLen,
+    public void verifyMIC(byte[] inTok, int tokOffset, int tokLen,
                           byte[] inMsg, int msgOffset, int msgLen,
                           MessageProp msgProp) throws GSSException;
 
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java	Wed Jul 05 20:41:30 2017 +0200
@@ -372,7 +372,7 @@
         }
         return cStub.wrap(pContext, data, msgProp);
     }
-    public void wrap(byte inBuf[], int offset, int len,
+    public void wrap(byte[] inBuf, int offset, int len,
                      OutputStream os, MessageProp msgProp)
         throws GSSException {
         try {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java	Wed Jul 05 20:41:30 2017 +0200
@@ -78,7 +78,7 @@
                             if (DEBUG) err.printStackTrace();
                             return null;
                         }
-                        String gssLibs[] = new String[0];
+                        String[] gssLibs = new String[0];
                         String defaultLib = System.getProperty(LIB_PROP);
                         if (defaultLib == null || defaultLib.trim().equals("")) {
                             String osname = System.getProperty("os.name");
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java	Wed Jul 05 20:41:30 2017 +0200
@@ -568,7 +568,7 @@
         temp.putInteger(bint);
         bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
         temp = new DerOutputStream();
-        DerValue der[] = new DerValue[nameStrings.length];
+        DerValue[] der = new DerValue[nameStrings.length];
         for (int i = 0; i < nameStrings.length; i++) {
             der[i] = new KerberosString(nameStrings[i]).toDerValue();
         }
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Authenticator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Authenticator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -198,7 +198,7 @@
         if (authorizationData != null) {
             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x08), authorizationData.asn1Encode()));
         }
-        DerValue der[] = new DerValue[v.size()];
+        DerValue[] der = new DerValue[v.size()];
         v.copyInto(der);
         temp = new DerOutputStream();
         temp.putSequence(der);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/AuthorizationData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/AuthorizationData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -120,7 +120,7 @@
      */
     public byte[] asn1Encode() throws Asn1Exception, IOException {
         DerOutputStream bytes = new DerOutputStream();
-        DerValue der[] = new DerValue[entry.length];
+        DerValue[] der = new DerValue[entry.length];
         for (int i = 0; i < entry.length; i++) {
             der[i] = new DerValue(entry[i].asn1Encode());
         }
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncAPRepPart.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncAPRepPart.java	Wed Jul 05 20:41:30 2017 +0200
@@ -151,7 +151,7 @@
             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
                     true, (byte) 0x03), temp.toByteArray()));
         }
-        DerValue der[] = new DerValue[v.size()];
+        DerValue[] der = new DerValue[v.size()];
         v.copyInto(der);
         temp = new DerOutputStream();
         temp.putSequence(der);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKrbCredPart.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKrbCredPart.java	Wed Jul 05 20:41:30 2017 +0200
@@ -129,7 +129,7 @@
 
         subDer = der.getData().getDerValue();
         if ((subDer.getTag() & (byte) 0x1F) == (byte) 0x00) {
-            DerValue derValues[] = subDer.getData().getSequence(1);
+            DerValue[] derValues = subDer.getData().getSequence(1);
             ticketInfo = new KrbCredInfo[derValues.length];
             for (int i = 0; i < derValues.length; i++) {
                 ticketInfo[i] = new KrbCredInfo(derValues[i]);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddresses.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/HostAddresses.java	Wed Jul 05 20:41:30 2017 +0200
@@ -98,8 +98,8 @@
             throw new KrbException(Krb5.KRB_ERR_GENERIC, "Bad name");
 
         String host = components[1];
-        InetAddress addr[] = InetAddress.getAllByName(host);
-        HostAddress hAddrs[] = new HostAddress[addr.length];
+        InetAddress[] addr = InetAddress.getAllByName(host);
+        HostAddress[] hAddrs = new HostAddress[addr.length];
 
         for (int i = 0; i < addr.length; i++) {
             hAddrs[i] = new HostAddress(addr[i]);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReqBody.java	Wed Jul 05 20:41:30 2017 +0200
@@ -269,7 +269,7 @@
             ticketsTemp.write(DerValue.tag_SequenceOf, temp);
             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0B), ticketsTemp.toByteArray()));
         }
-        DerValue der[] = new DerValue[v.size()];
+        DerValue[] der = new DerValue[v.size()];
         v.copyInto(der);
         temp = new DerOutputStream();
         temp.putSequence(der);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KrbCredInfo.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KrbCredInfo.java	Wed Jul 05 20:41:30 2017 +0200
@@ -172,7 +172,7 @@
         }
         if (caddr != null)
             v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x0A), caddr.asn1Encode()));
-        DerValue der[] = new DerValue[v.size()];
+        DerValue[] der = new DerValue[v.size()];
         v.copyInto(der);
         DerOutputStream out = new DerOutputStream();
         out.putSequence(der);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/NetClient.java	Wed Jul 05 20:41:30 2017 +0200
@@ -200,7 +200,7 @@
 
     @Override
     public byte[] receive() throws IOException {
-        byte ibuf[] = new byte[bufSize];
+        byte[] ibuf = new byte[bufSize];
         dgPacketIn = new DatagramPacket(ibuf, ibuf.length);
         try {
             dgSocket.receive(dgPacketIn);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Ticket.java	Wed Jul 05 20:41:30 2017 +0200
@@ -135,7 +135,7 @@
     public byte[] asn1Encode() throws Asn1Exception, IOException {
         DerOutputStream bytes = new DerOutputStream();
         DerOutputStream temp = new DerOutputStream();
-        DerValue der[] = new DerValue[4];
+        DerValue[] der = new DerValue[4];
         temp.putInteger(BigInteger.valueOf(tkt_vno));
         bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), temp);
         bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), sname.getRealm().asn1Encode());
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -357,7 +357,7 @@
         if (DEBUG) {
             System.out.println(">>>DEBUG <CCacheInputStream> key type: " + key.getEType());
         }
-        long times[] = readTimes();
+        long[] times = readTimes();
         KerberosTime authtime = new KerberosTime(times[0]);
         KerberosTime starttime =
                 (times[1]==0) ? null : new KerberosTime(times[1]);
@@ -374,9 +374,9 @@
                     ((renewTill==null)?"null":renewTill.toDate().toString()));
         }
         boolean skey = readskey();
-        boolean flags[] = readFlags();
+        boolean[] flags = readFlags();
         TicketFlags tFlags = new TicketFlags(flags);
-        HostAddress addr[] = readAddr();
+        HostAddress[] addr = readAddr();
         HostAddresses addrs = null;
         if (addr != null) {
             addrs = new HostAddresses(addr);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/crc32.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/crc32.java	Wed Jul 05 20:41:30 2017 +0200
@@ -112,7 +112,7 @@
      * This version is more efficient than the byte-at-a-time version;
      * it avoids data copies and reduces per-byte call overhead.
      */
-    protected synchronized void engineUpdate(byte input[], int offset,
+    protected synchronized void engineUpdate(byte[] input, int offset,
                                              int len) {
         processData(input, offset, len);
     }
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/KerberosPreMasterSecret.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ssl/KerberosPreMasterSecret.java	Wed Jul 05 20:41:30 2017 +0200
@@ -53,8 +53,8 @@
 final class KerberosPreMasterSecret {
 
     private ProtocolVersion protocolVersion; // preMaster [0,1]
-    private byte preMaster[];           // 48 bytes
-    private byte encrypted[];
+    private byte[] preMaster;           // 48 bytes
+    private byte[] encrypted;
 
     /**
      * Constructor used by client to generate premaster secret.
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ClientFactoryImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ClientFactoryImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -47,13 +47,13 @@
   * @author Rosanna Lee
   */
 final public class ClientFactoryImpl implements SaslClientFactory {
-    private static final String myMechs[] = {
+    private static final String[] myMechs = {
         "EXTERNAL",
         "CRAM-MD5",
         "PLAIN",
     };
 
-    private static final int mechPolicies[] = {
+    private static final int[] mechPolicies = {
         // %%% RL: Policies should actually depend on the external channel
         PolicyUtils.NOPLAINTEXT|PolicyUtils.NOACTIVE|PolicyUtils.NODICTIONARY,
         PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS,    // CRAM-MD5
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java	Wed Jul 05 20:41:30 2017 +0200
@@ -165,7 +165,7 @@
                 PasswordCallback pcb =
                     new PasswordCallback("CRAM-MD5 password: ", false);
                 cbh.handle(new Callback[]{ncb,pcb});
-                char pwChars[] = pcb.getPassword();
+                char[] pwChars = pcb.getPassword();
                 if (pwChars == null || pwChars.length == 0) {
                     // user has no password; OK to disclose to server
                     aborted = true;
@@ -190,7 +190,7 @@
                 clearPassword();
 
                 // Check whether digest is as expected
-                byte [] expectedDigest = digest.getBytes("UTF8");
+                byte[] expectedDigest = digest.getBytes("UTF8");
                 int digestLen = responseData.length - ulen - 1;
                 if (expectedDigest.length != digestLen) {
                     aborted = true;
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ServerFactoryImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ServerFactoryImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -41,11 +41,11 @@
   * @author Rosanna Lee
   */
 final public class ServerFactoryImpl implements SaslServerFactory {
-    private static final String myMechs[] = {
+    private static final String[] myMechs = {
         "CRAM-MD5", //
     };
 
-    private static final int mechPolicies[] = {
+    private static final int[] mechPolicies = {
         PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS,      // CRAM-MD5
     };
 
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java	Wed Jul 05 20:41:30 2017 +0200
@@ -272,7 +272,7 @@
      */
 
     /** This array maps the characters to their 6 bit values */
-    private final static char pem_array[] = {
+    private final static char[] pem_array = {
         //       0   1   2   3   4   5   6   7
                 'A','B','C','D','E','F','G','H', // 0
                 'I','J','K','L','M','N','O','P', // 1
@@ -1068,7 +1068,7 @@
                 byte[] hMAC_MD5 = m.doFinal();
 
                 /* First 10 bytes of HMAC_MD5 digest */
-                byte macBuffer[] = new byte[10];
+                byte[] macBuffer = new byte[10];
                 System.arraycopy(hMAC_MD5, 0, macBuffer, 0, 10);
 
                 return macBuffer;
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/FactoryImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/FactoryImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -44,9 +44,9 @@
 public final class FactoryImpl implements SaslClientFactory,
 SaslServerFactory{
 
-    private static final String myMechs[] = { "DIGEST-MD5" };
+    private static final String[] myMechs = { "DIGEST-MD5" };
     private static final int DIGEST_MD5 = 0;
-    private static final int mechPolicies[] = {
+    private static final int[] mechPolicies = {
         PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS};
 
     /**
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -43,8 +43,8 @@
 public final class FactoryImpl implements SaslClientFactory,
 SaslServerFactory{
 
-    private static final String myMechs[] = { "NTLM" };
-    private static final int mechPolicies[] = {
+    private static final String[] myMechs = { "NTLM" };
+    private static final int[] mechPolicies = {
             PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS
     };
 
--- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/KeyStore.java	Wed Jul 05 20:41:30 2017 +0200
@@ -66,7 +66,7 @@
     class KeyEntry
     {
         private Key privateKey;
-        private X509Certificate certChain[];
+        private X509Certificate[] certChain;
         private String alias;
 
         KeyEntry(Key key, X509Certificate[] chain) {
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Cipher.java	Wed Jul 05 20:41:30 2017 +0200
@@ -175,7 +175,7 @@
         this.algorithm = algorithm;
         this.mechanism = mechanism;
 
-        String algoParts[] = algorithm.split("/");
+        String[] algoParts = algorithm.split("/");
 
         if (algoParts[0].startsWith("AES")) {
             blockSize = 16;
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java	Wed Jul 05 20:41:30 2017 +0200
@@ -164,7 +164,7 @@
         private X509Certificate cert = null;
 
         // chain
-        private X509Certificate chain[] = null;
+        private X509Certificate[] chain = null;
 
         // true if CKA_ID for private key and cert match up
         private boolean matched = false;
--- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/CK_AES_CTR_PARAMS.java	Wed Jul 05 20:41:30 2017 +0200
@@ -42,7 +42,7 @@
 public class CK_AES_CTR_PARAMS {
 
     private final long ulCounterBits;
-    private final byte cb[];
+    private final byte[] cb;
 
     public CK_AES_CTR_PARAMS(byte[] cb) {
         ulCounterBits = 128;
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java	Wed Jul 05 20:41:30 2017 +0200
@@ -40,7 +40,7 @@
     private static final long serialVersionUID = -933864511110035746L;
 
     // NOTE: check /usr/include/sys/crypto/common.h for updates
-    private static final String ERROR_MSG[] = {
+    private static final String[] ERROR_MSG = {
         "CRYPTO_SUCCESS",
         "CRYPTO_CANCEL",
         "CRYPTO_HOST_MEMORY",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+// Based on Apache Karaf impl
+
+/**
+ * Non-interruptible (via CTRL-C) {@link UnixTerminal}.
+ *
+ * @since 2.0
+ */
+public class NoInterruptUnixTerminal
+    extends UnixTerminal
+{
+    public NoInterruptUnixTerminal() throws Exception {
+        super();
+    }
+
+    @Override
+    public void init() throws Exception {
+        super.init();
+        getSettings().set("intr undef");
+    }
+
+    @Override
+    public void restore() throws Exception {
+        getSettings().set("intr ^C");
+        super.restore();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Representation of the input terminal for a platform.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public interface Terminal
+{
+    void init() throws Exception;
+
+    void restore() throws Exception;
+
+    void reset() throws Exception;
+
+    boolean isSupported();
+
+    int getWidth();
+
+    int getHeight();
+
+    boolean isAnsiSupported();
+
+    /**
+     * When ANSI is not natively handled, the output will have to be wrapped.
+     */
+    OutputStream wrapOutIfNeeded(OutputStream out);
+
+    /**
+     * When using native support, return the InputStream to use for reading characters
+     * else return the input stream passed as a parameter.
+     *
+     * @since 2.6
+     */
+    InputStream wrapInIfNeeded(InputStream in) throws IOException;
+
+    /**
+     * For terminals that don't wrap when character is written in last column,
+     * only when the next character is written.
+     * These are the ones that have 'am' and 'xn' termcap attributes (xterm and
+     * rxvt flavors falls under that category)
+     */
+    boolean hasWeirdWrap();
+
+    boolean isEchoEnabled();
+
+    void setEchoEnabled(boolean enabled);
+
+    String getOutputEncoding();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import jdk.internal.jline.internal.Configuration;
+import jdk.internal.jline.internal.Log;
+import jdk.internal.jline.internal.Preconditions;
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Creates terminal instances.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class TerminalFactory
+{
+    public static final String JLINE_TERMINAL = "jline.terminal";
+
+    public static final String AUTO = "auto";
+
+    public static final String UNIX = "unix";
+
+    public static final String WIN = "win";
+
+    public static final String WINDOWS = "windows";
+
+    public static final String NONE = "none";
+
+    public static final String OFF = "off";
+
+    public static final String FALSE = "false";
+
+    private static Terminal term = null;
+
+    public static synchronized Terminal create() {
+        if (Log.TRACE) {
+            //noinspection ThrowableInstanceNeverThrown
+            Log.trace(new Throwable("CREATE MARKER"));
+        }
+
+        String type = Configuration.getString(JLINE_TERMINAL, AUTO);
+        if ("dumb".equals(System.getenv("TERM"))) {
+            type = "none";
+            Log.debug("$TERM=dumb; setting type=", type);
+        }
+
+        Log.debug("Creating terminal; type=", type);
+
+        Terminal t;
+        try {
+            String tmp = type.toLowerCase();
+
+            if (tmp.equals(UNIX)) {
+                t = getFlavor(Flavor.UNIX);
+            }
+            else if (tmp.equals(WIN) | tmp.equals(WINDOWS)) {
+                t = getFlavor(Flavor.WINDOWS);
+            }
+            else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) {
+                t = new UnsupportedTerminal();
+            }
+            else {
+                if (tmp.equals(AUTO)) {
+                    String os = Configuration.getOsName();
+                    Flavor flavor = Flavor.UNIX;
+                    if (os.contains(WINDOWS)) {
+                        flavor = Flavor.WINDOWS;
+                    }
+                    t = getFlavor(flavor);
+                }
+                else {
+                    try {
+                        t = (Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
+                    }
+                    catch (Exception e) {
+                        throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
+                    }
+                }
+            }
+        }
+        catch (Exception e) {
+            Log.error("Failed to construct terminal; falling back to unsupported", e);
+            t = new UnsupportedTerminal();
+        }
+
+        Log.debug("Created Terminal: ", t);
+
+        try {
+            t.init();
+        }
+        catch (Throwable e) {
+            Log.error("Terminal initialization failed; falling back to unsupported", e);
+            return new UnsupportedTerminal();
+        }
+
+        return t;
+    }
+
+    public static synchronized void reset() {
+        term = null;
+    }
+
+    public static synchronized void resetIf(final Terminal t) {
+        if(t == term) {
+            reset();
+        }
+    }
+
+    public static enum Type
+    {
+        AUTO,
+        WINDOWS,
+        UNIX,
+        NONE
+    }
+
+    public static synchronized void configure(final String type) {
+        checkNotNull(type);
+        System.setProperty(JLINE_TERMINAL, type);
+    }
+
+    public static synchronized void configure(final Type type) {
+        checkNotNull(type);
+        configure(type.name().toLowerCase());
+    }
+
+    //
+    // Flavor Support
+    //
+
+    public static enum Flavor
+    {
+        WINDOWS,
+        UNIX
+    }
+
+    private static final Map<Flavor, Callable<? extends Terminal>> FLAVORS = new HashMap<>();
+
+    static {
+//        registerFlavor(Flavor.WINDOWS, AnsiWindowsTerminal.class);
+//        registerFlavor(Flavor.UNIX, UnixTerminal.class);
+        registerFlavor(Flavor.WINDOWS, WindowsTerminal :: new);
+        registerFlavor(Flavor.UNIX, UnixTerminal :: new);
+    }
+
+    public static synchronized Terminal get() {
+        if (term == null) {
+            term = create();
+        }
+        return term;
+    }
+
+    public static Terminal getFlavor(final Flavor flavor) throws Exception {
+        return FLAVORS.getOrDefault(flavor, () -> {throw new InternalError();}).call();
+    }
+
+    public static void registerFlavor(final Flavor flavor, final Callable<? extends Terminal> sup) {
+        FLAVORS.put(flavor, sup);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import jdk.internal.jline.internal.Log;
+import jdk.internal.jline.internal.ShutdownHooks;
+import jdk.internal.jline.internal.ShutdownHooks.Task;
+
+/**
+ * Provides support for {@link Terminal} instances.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public abstract class TerminalSupport
+    implements Terminal
+{
+    public static final int DEFAULT_WIDTH = 80;
+
+    public static final int DEFAULT_HEIGHT = 24;
+
+    private Task shutdownTask;
+
+    private boolean supported;
+
+    private boolean echoEnabled;
+
+    private boolean ansiSupported;
+
+    protected TerminalSupport(final boolean supported) {
+        this.supported = supported;
+    }
+
+    public void init() throws Exception {
+        if (shutdownTask != null) {
+            ShutdownHooks.remove(shutdownTask);
+        }
+        // Register a task to restore the terminal on shutdown
+        this.shutdownTask = ShutdownHooks.add(new Task()
+        {
+            public void run() throws Exception {
+                restore();
+            }
+        });
+    }
+
+    public void restore() throws Exception {
+        TerminalFactory.resetIf(this);
+        if (shutdownTask != null) {
+          ShutdownHooks.remove(shutdownTask);
+          shutdownTask = null;
+        }
+    }
+
+    public void reset() throws Exception {
+        restore();
+        init();
+    }
+
+    public final boolean isSupported() {
+        return supported;
+    }
+
+    public synchronized boolean isAnsiSupported() {
+        return ansiSupported;
+    }
+
+    protected synchronized void setAnsiSupported(final boolean supported) {
+        this.ansiSupported = supported;
+        Log.debug("Ansi supported: ", supported);
+    }
+
+    /**
+     * Subclass to change behavior if needed.
+     * @return the passed out
+     */
+    public OutputStream wrapOutIfNeeded(OutputStream out) {
+        return out;
+    }
+
+    /**
+     * Defaults to true which was the behaviour before this method was added.
+     */
+    public boolean hasWeirdWrap() {
+        return true;
+    }
+
+    public int getWidth() {
+        return DEFAULT_WIDTH;
+    }
+
+    public int getHeight() {
+        return DEFAULT_HEIGHT;
+    }
+
+    public synchronized boolean isEchoEnabled() {
+        return echoEnabled;
+    }
+
+    public synchronized void setEchoEnabled(final boolean enabled) {
+        this.echoEnabled = enabled;
+        Log.debug("Echo enabled: ", enabled);
+    }
+
+    public InputStream wrapInIfNeeded(InputStream in) throws IOException {
+        return in;
+    }
+
+    public String getOutputEncoding() {
+        // null for unknown
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+import jdk.internal.jline.internal.Log;
+import jdk.internal.jline.internal.TerminalLineSettings;
+
+/**
+ * Terminal that is used for unix platforms. Terminal initialization
+ * is handled by issuing the <em>stty</em> command against the
+ * <em>/dev/tty</em> file to disable character echoing and enable
+ * character input. All known unix systems (including
+ * Linux and Macintosh OS X) support the <em>stty</em>), so this
+ * implementation should work for an reasonable POSIX system.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:dwkemp@gmail.com">Dale Kemp</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:jbonofre@apache.org">Jean-Baptiste Onofr\u00E9</a>
+ * @since 2.0
+ */
+public class UnixTerminal
+    extends TerminalSupport
+{
+    private final TerminalLineSettings settings = new TerminalLineSettings();
+
+    public UnixTerminal() throws Exception {
+        super(true);
+    }
+
+    protected TerminalLineSettings getSettings() {
+        return settings;
+    }
+
+    /**
+     * Remove line-buffered input by invoking "stty -icanon min 1"
+     * against the current terminal.
+     */
+    @Override
+    public void init() throws Exception {
+        super.init();
+
+        setAnsiSupported(true);
+
+        // Set the console to be character-buffered instead of line-buffered.
+        // Make sure we're distinguishing carriage return from newline.
+        // Allow ctrl-s keypress to be used (as forward search)
+        settings.set("-icanon min 1 -icrnl -inlcr -ixon");
+        settings.set("dsusp undef");
+
+        setEchoEnabled(false);
+    }
+
+    /**
+     * Restore the original terminal configuration, which can be used when
+     * shutting down the console reader. The ConsoleReader cannot be
+     * used after calling this method.
+     */
+    @Override
+    public void restore() throws Exception {
+        settings.restore();
+        super.restore();
+    }
+
+    /**
+     * Returns the value of <tt>stty columns</tt> param.
+     */
+    @Override
+    public int getWidth() {
+        int w = settings.getProperty("columns");
+        return w < 1 ? DEFAULT_WIDTH : w;
+    }
+
+    /**
+     * Returns the value of <tt>stty rows>/tt> param.
+     */
+    @Override
+    public int getHeight() {
+        int h = settings.getProperty("rows");
+        return h < 1 ? DEFAULT_HEIGHT : h;
+    }
+
+    @Override
+    public synchronized void setEchoEnabled(final boolean enabled) {
+        try {
+            if (enabled) {
+                settings.set("echo");
+            }
+            else {
+                settings.set("-echo");
+            }
+            super.setEchoEnabled(enabled);
+        }
+        catch (Exception e) {
+            if (e instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
+            Log.error("Failed to ", (enabled ? "enable" : "disable"), " echo", e);
+        }
+    }
+
+    public void disableInterruptCharacter()
+    {
+        try {
+            settings.set("intr undef");
+        }
+        catch (Exception e) {
+            if (e instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
+            Log.error("Failed to disable interrupt character", e);
+        }
+    }
+
+    public void enableInterruptCharacter()
+    {
+        try {
+            settings.set("intr ^C");
+        }
+        catch (Exception e) {
+            if (e instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
+            Log.error("Failed to enable interrupt character", e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+/**
+ * An unsupported terminal.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class UnsupportedTerminal
+    extends TerminalSupport
+{
+    public UnsupportedTerminal() {
+        super(false);
+        setAnsiSupported(false);
+        setEchoEnabled(true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import jdk.internal.jline.internal.Configuration;
+import jdk.internal.jline.internal.Log;
+//import org.fusesource.jansi.internal.WindowsSupport;
+//import org.fusesource.jansi.internal.Kernel32;
+//import static org.fusesource.jansi.internal.Kernel32.*;
+
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
+
+/**
+ * Terminal implementation for Microsoft Windows. Terminal initialization in
+ * {@link #init} is accomplished by extracting the
+ * <em>jline_<i>version</i>.dll</em>, saving it to the system temporary
+ * directoy (determined by the setting of the <em>java.io.tmpdir</em> System
+ * property), loading the library, and then calling the Win32 APIs <a
+ * href="http://msdn.microsoft.com/library/default.asp?
+ * url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a> and
+ * <a href="http://msdn.microsoft.com/library/default.asp?
+ * url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a> to
+ * disable character echoing.
+ * <p/>
+ * <p>
+ * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
+ * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
+ * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
+ * directly invoke the readc() method in the JNI library. This is so the class
+ * can read special keys (like arrow keys) which are otherwise inaccessible via
+ * the {@link System#in} stream. Using JNI reading can be bypassed by setting
+ * the <code>jline.WindowsTerminal.directConsole</code> system property
+ * to <code>false</code>.
+ * </p>
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class WindowsTerminal
+    extends TerminalSupport
+{
+    public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
+
+    public static final String ANSI = WindowsTerminal.class.getName() + ".ansi";
+
+    private boolean directConsole;
+
+    private int originalMode;
+
+    public WindowsTerminal() throws Exception {
+        super(true);
+    }
+
+    @Override
+    public void init() throws Exception {
+        super.init();
+
+//        setAnsiSupported(Configuration.getBoolean(ANSI, true));
+        setAnsiSupported(false);
+
+        //
+        // FIXME: Need a way to disable direct console and sysin detection muck
+        //
+
+        setDirectConsole(Configuration.getBoolean(DIRECT_CONSOLE, true));
+
+        this.originalMode = getConsoleMode();
+        setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code);
+        setEchoEnabled(false);
+    }
+
+    /**
+     * Restore the original terminal configuration, which can be used when
+     * shutting down the console reader. The ConsoleReader cannot be
+     * used after calling this method.
+     */
+    @Override
+    public void restore() throws Exception {
+        // restore the old console mode
+        setConsoleMode(originalMode);
+        super.restore();
+    }
+
+    @Override
+    public int getWidth() {
+        int w = getWindowsTerminalWidth();
+        return w < 1 ? DEFAULT_WIDTH : w;
+    }
+
+    @Override
+    public int getHeight() {
+        int h = getWindowsTerminalHeight();
+        return h < 1 ? DEFAULT_HEIGHT : h;
+    }
+
+    @Override
+    public void setEchoEnabled(final boolean enabled) {
+        // Must set these four modes at the same time to make it work fine.
+        if (enabled) {
+            setConsoleMode(getConsoleMode() |
+                ENABLE_ECHO_INPUT.code |
+                ENABLE_LINE_INPUT.code |
+                ENABLE_PROCESSED_INPUT.code |
+                ENABLE_WINDOW_INPUT.code);
+        }
+        else {
+            setConsoleMode(getConsoleMode() &
+                ~(ENABLE_LINE_INPUT.code |
+                    ENABLE_ECHO_INPUT.code |
+                    ENABLE_PROCESSED_INPUT.code |
+                    ENABLE_WINDOW_INPUT.code));
+        }
+        super.setEchoEnabled(enabled);
+    }
+
+    /**
+     * Whether or not to allow the use of the JNI console interaction.
+     */
+    public void setDirectConsole(final boolean flag) {
+        this.directConsole = flag;
+        Log.debug("Direct console: ", flag);
+    }
+
+    /**
+     * Whether or not to allow the use of the JNI console interaction.
+     */
+    public Boolean getDirectConsole() {
+        return directConsole;
+    }
+
+
+    @Override
+    public InputStream wrapInIfNeeded(InputStream in) throws IOException {
+        if (directConsole && isSystemIn(in)) {
+            return new InputStream() {
+                private byte[] buf = null;
+                int bufIdx = 0;
+
+                @Override
+                public int read() throws IOException {
+                    while (buf == null || bufIdx == buf.length) {
+                        buf = readConsoleInput();
+                        bufIdx = 0;
+                    }
+                    int c = buf[bufIdx] & 0xFF;
+                    bufIdx++;
+                    return c;
+                }
+            };
+        } else {
+            return super.wrapInIfNeeded(in);
+        }
+    }
+
+    protected boolean isSystemIn(final InputStream in) throws IOException {
+        if (in == null) {
+            return false;
+        }
+        else if (in == System.in) {
+            return true;
+        }
+        else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
+            return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public String getOutputEncoding() {
+        int codepage = getConsoleOutputCodepage();
+        //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
+        String charsetMS = "ms" + codepage;
+        if (java.nio.charset.Charset.isSupported(charsetMS)) {
+            return charsetMS;
+        }
+        String charsetCP = "cp" + codepage;
+        if (java.nio.charset.Charset.isSupported(charsetCP)) {
+            return charsetCP;
+        }
+        Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")...");
+        return super.getOutputEncoding();
+    }
+
+    //
+    // Original code:
+    //
+//    private int getConsoleMode() {
+//        return WindowsSupport.getConsoleMode();
+//    }
+//
+//    private void setConsoleMode(int mode) {
+//        WindowsSupport.setConsoleMode(mode);
+//    }
+//
+//    private byte[] readConsoleInput() {
+//        // XXX does how many events to read in one call matter?
+//        INPUT_RECORD[] events = null;
+//        try {
+//            events = WindowsSupport.readConsoleInput(1);
+//        } catch (IOException e) {
+//            Log.debug("read Windows console input error: ", e);
+//        }
+//        if (events == null) {
+//            return new byte[0];
+//        }
+//        StringBuilder sb = new StringBuilder();
+//        for (int i = 0; i < events.length; i++ ) {
+//            KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
+//            //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
+//            if (keyEvent.keyDown) {
+//                if (keyEvent.uchar > 0) {
+//                    // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
+//                    // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
+//                    final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
+//                    // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
+//                    // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
+//                    final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
+//                    if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
+//                        && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
+//                        sb.append('\u001B'); // ESC
+//                    }
+//
+//                    sb.append(keyEvent.uchar);
+//                    continue;
+//                }
+//                // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
+//                // just add support for basic editing keys (no control state, no numpad keys)
+//                String escapeSequence = null;
+//                switch (keyEvent.keyCode) {
+//                case 0x21: // VK_PRIOR PageUp
+//                    escapeSequence = "\u001B[5~";
+//                    break;
+//                case 0x22: // VK_NEXT PageDown
+//                    escapeSequence = "\u001B[6~";
+//                    break;
+//                case 0x23: // VK_END
+//                    escapeSequence = "\u001B[4~";
+//                    break;
+//                case 0x24: // VK_HOME
+//                    escapeSequence = "\u001B[1~";
+//                    break;
+//                case 0x25: // VK_LEFT
+//                    escapeSequence = "\u001B[D";
+//                    break;
+//                case 0x26: // VK_UP
+//                    escapeSequence = "\u001B[A";
+//                    break;
+//                case 0x27: // VK_RIGHT
+//                    escapeSequence = "\u001B[C";
+//                    break;
+//                case 0x28: // VK_DOWN
+//                    escapeSequence = "\u001B[B";
+//                    break;
+//                case 0x2D: // VK_INSERT
+//                    escapeSequence = "\u001B[2~";
+//                    break;
+//                case 0x2E: // VK_DELETE
+//                    escapeSequence = "\u001B[3~";
+//                    break;
+//                default:
+//                    break;
+//                }
+//                if (escapeSequence != null) {
+//                    for (int k = 0; k < keyEvent.repeatCount; k++) {
+//                        sb.append(escapeSequence);
+//                    }
+//                }
+//            } else {
+//                // key up event
+//                // support ALT+NumPad input method
+//                if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
+//                    sb.append(keyEvent.uchar);
+//                }
+//            }
+//        }
+//        return sb.toString().getBytes();
+//    }
+//
+//    private int getConsoleOutputCodepage() {
+//        return Kernel32.GetConsoleOutputCP();
+//    }
+//
+//    private int getWindowsTerminalWidth() {
+//        return WindowsSupport.getWindowsTerminalWidth();
+//    }
+//
+//    private int getWindowsTerminalHeight() {
+//        return WindowsSupport.getWindowsTerminalHeight();
+//    }
+
+    //
+    // Native Bits
+    //
+    static {
+        System.loadLibrary("le");
+        initIDs();
+    }
+
+    private static native void initIDs();
+
+    private native int getConsoleMode();
+
+    private native void setConsoleMode(int mode);
+
+    private byte[] readConsoleInput() {
+        KEY_EVENT_RECORD keyEvent = readKeyEvent();
+
+        return convertKeys(keyEvent).getBytes();
+    }
+
+    public static String convertKeys(KEY_EVENT_RECORD keyEvent) {
+        if (keyEvent == null) {
+            return "";
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        if (keyEvent.keyDown) {
+            if (keyEvent.uchar > 0) {
+                // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
+                // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
+                final int altState = KEY_EVENT_RECORD.ALT_PRESSED;
+                // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
+                // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
+                final int ctrlState = KEY_EVENT_RECORD.CTRL_PRESSED;
+
+                boolean handled = false;
+
+                if ((keyEvent.controlKeyState & ctrlState) != 0) {
+                    switch (keyEvent.keyCode) {
+                        case 0x43: //Ctrl-C
+                            sb.append("\003");
+                            handled = true;
+                            break;
+                    }
+                }
+
+                if ((keyEvent.controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
+                    switch (keyEvent.keyCode) {
+                        case 0x09: //Shift-Tab
+                            sb.append("\033\133\132");
+                            handled = true;
+                            break;
+                    }
+                }
+
+                if (!handled) {
+                    if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
+                        && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
+                        sb.append('\u001B'); // ESC
+                    }
+
+                    sb.append(keyEvent.uchar);
+                }
+            } else {
+                // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
+                // just add support for basic editing keys (no control state, no numpad keys)
+                String escapeSequence = null;
+                switch (keyEvent.keyCode) {
+                case 0x21: // VK_PRIOR PageUp
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~");
+                    break;
+                case 0x22: // VK_NEXT PageDown
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~");
+                    break;
+                case 0x23: // VK_END
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~");
+                    break;
+                case 0x24: // VK_HOME
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~");
+                    break;
+                case 0x25: // VK_LEFT
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD");
+                    break;
+                case 0x26: // VK_UP
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA");
+                    break;
+                case 0x27: // VK_RIGHT
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC");
+                    break;
+                case 0x28: // VK_DOWN
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB");
+                    break;
+                case 0x2D: // VK_INSERT
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~");
+                    break;
+                case 0x2E: // VK_DELETE
+                    escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[3~", "\u001B[3;%d~");
+                    break;
+                default:
+                    break;
+                }
+                if (escapeSequence != null) {
+                    for (int k = 0; k < keyEvent.repeatCount; k++) {
+                        sb.append(escapeSequence);
+                    }
+                }
+            }
+        } else {
+            // key up event
+            // support ALT+NumPad input method
+            if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
+                sb.append(keyEvent.uchar);
+            }
+        }
+        return sb.toString();
+    }
+
+    private static String escapeSequence(int controlKeyState, String noControlSequence, String withControlSequence) {
+        int controlNum = 1;
+
+        if ((controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
+            controlNum += 1;
+        }
+
+        if ((controlKeyState & KEY_EVENT_RECORD.ALT_PRESSED) != 0) {
+            controlNum += 2;
+        }
+
+        if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) {
+            controlNum += 4;
+        }
+
+        if (controlNum > 1) {
+            return String.format(withControlSequence, controlNum);
+        } else {
+            return noControlSequence;
+        }
+    }
+
+    private native KEY_EVENT_RECORD readKeyEvent();
+
+    public static class KEY_EVENT_RECORD {
+        public final static int ALT_PRESSED = 0x3;
+        public final static int CTRL_PRESSED = 0xC;
+        public final static int SHIFT_PRESSED = 0x10;
+        public final boolean keyDown;
+        public final char uchar;
+        public final int controlKeyState;
+        public final int keyCode;
+        public final int repeatCount;
+
+        public KEY_EVENT_RECORD(boolean keyDown, char uchar, int controlKeyState, int keyCode, int repeatCount) {
+            this.keyDown = keyDown;
+            this.uchar = uchar;
+            this.controlKeyState = controlKeyState;
+            this.keyCode = keyCode;
+            this.repeatCount = repeatCount;
+        }
+
+    }
+
+    private native int getConsoleOutputCodepage();
+
+    private native int getWindowsTerminalWidth();
+
+    private native int getWindowsTerminalHeight();
+
+    /**
+     * Console mode
+     * <p/>
+     * Constants copied <tt>wincon.h</tt>.
+     */
+    public static enum ConsoleMode
+    {
+        /**
+         * The ReadFile or ReadConsole function returns only when a carriage return
+         * character is read. If this mode is disable, the functions return when one
+         * or more characters are available.
+         */
+        ENABLE_LINE_INPUT(2),
+
+        /**
+         * Characters read by the ReadFile or ReadConsole function are written to
+         * the active screen buffer as they are read. This mode can be used only if
+         * the ENABLE_LINE_INPUT mode is also enabled.
+         */
+        ENABLE_ECHO_INPUT(4),
+
+        /**
+         * CTRL+C is processed by the system and is not placed in the input buffer.
+         * If the input buffer is being read by ReadFile or ReadConsole, other
+         * control keys are processed by the system and are not returned in the
+         * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
+         * enabled, backspace, carriage return, and linefeed characters are handled
+         * by the system.
+         */
+        ENABLE_PROCESSED_INPUT(1),
+
+        /**
+         * User interactions that change the size of the console screen buffer are
+         * reported in the console's input buffee. Information about these events
+         * can be read from the input buffer by applications using
+         * theReadConsoleInput function, but not by those using ReadFile
+         * orReadConsole.
+         */
+        ENABLE_WINDOW_INPUT(8),
+
+        /**
+         * If the mouse pointer is within the borders of the console window and the
+         * window has the keyboard focus, mouse events generated by mouse movement
+         * and button presses are placed in the input buffer. These events are
+         * discarded by ReadFile or ReadConsole, even when this mode is enabled.
+         */
+        ENABLE_MOUSE_INPUT(16),
+
+        /**
+         * When enabled, text entered in a console window will be inserted at the
+         * current cursor location and all text following that location will not be
+         * overwritten. When disabled, all following text will be overwritten. An OR
+         * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
+         * flag to enable this functionality.
+         */
+        ENABLE_PROCESSED_OUTPUT(1),
+
+        /**
+         * This flag enables the user to use the mouse to select and edit text. To
+         * enable this option, use the OR to combine this flag with
+         * ENABLE_EXTENDED_FLAGS.
+         */
+        ENABLE_WRAP_AT_EOL_OUTPUT(2),;
+
+        public final int code;
+
+        ConsoleMode(final int code) {
+            this.code = code;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.internal.jline.internal.Log;
+
+/**
+ * @author St\u00E5le W. Pedersen <stale.pedersen@jboss.org>
+ */
+public class ConsoleKeys {
+
+    private KeyMap keys;
+
+    private Map<String, KeyMap> keyMaps;
+    private Map<String, String> variables = new HashMap<String,String>();
+
+    public ConsoleKeys(String appName, URL inputrcUrl) {
+        keyMaps = KeyMap.keyMaps();
+        loadKeys(appName, inputrcUrl);
+    }
+
+    protected boolean isViEditMode() {
+        return keys.isViKeyMap();
+    }
+
+    protected boolean setKeyMap (String name) {
+        KeyMap map = keyMaps.get(name);
+        if (map == null) {
+            return false;
+        }
+        this.keys = map;
+        return true;
+    }
+
+    protected Map<String, KeyMap> getKeyMaps() {
+        return keyMaps;
+    }
+
+    protected KeyMap getKeys() {
+        return keys;
+    }
+
+    protected void setKeys(KeyMap keys) {
+        this.keys = keys;
+    }
+
+    protected boolean getViEditMode() {
+        return keys.isViKeyMap ();
+    }
+
+    protected void loadKeys(String appName, URL inputrcUrl) {
+        keys = keyMaps.get(KeyMap.EMACS);
+
+        try {
+            InputStream input = inputrcUrl.openStream();
+            try {
+                loadKeys(input, appName);
+                Log.debug("Loaded user configuration: ", inputrcUrl);
+            }
+            finally {
+                try {
+                    input.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+        catch (IOException e) {
+            if (inputrcUrl.getProtocol().equals("file")) {
+                File file = new File(inputrcUrl.getPath());
+                if (file.exists()) {
+                    Log.warn("Unable to read user configuration: ", inputrcUrl, e);
+                }
+            } else {
+                Log.warn("Unable to read user configuration: ", inputrcUrl, e);
+            }
+        }
+    }
+
+    private void loadKeys(InputStream input, String appName) throws IOException {
+        BufferedReader reader = new BufferedReader( new java.io.InputStreamReader( input ) );
+        String line;
+        boolean parsing = true;
+        List<Boolean> ifsStack = new ArrayList<Boolean>();
+        while ( (line = reader.readLine()) != null ) {
+            try {
+                line = line.trim();
+                if (line.length() == 0) {
+                    continue;
+                }
+                if (line.charAt(0) == '#') {
+                    continue;
+                }
+                int i = 0;
+                if (line.charAt(i) == '$') {
+                    String cmd;
+                    String args;
+                    for (++i; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
+                    int s = i;
+                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
+                    cmd = line.substring(s, i);
+                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
+                    s = i;
+                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
+                    args = line.substring(s, i);
+                    if ("if".equalsIgnoreCase(cmd)) {
+                        ifsStack.add( parsing );
+                        if (!parsing) {
+                            continue;
+                        }
+                        if (args.startsWith("term=")) {
+                            // TODO
+                        } else if (args.startsWith("mode=")) {
+                            if (args.equalsIgnoreCase("mode=vi")) {
+                                parsing = isViEditMode();
+                            } else if (args.equals("mode=emacs")) {
+                                parsing = !isViEditMode();
+                            } else {
+                                parsing = false;
+                            }
+                        } else {
+                            parsing = args.equalsIgnoreCase(appName);
+                        }
+                    } else if ("else".equalsIgnoreCase(cmd)) {
+                        if (ifsStack.isEmpty()) {
+                            throw new IllegalArgumentException("$else found without matching $if");
+                        }
+                        boolean invert = true;
+                        for (boolean b : ifsStack) {
+                            if (!b) {
+                                invert = false;
+                                break;
+                            }
+                        }
+                        if (invert) {
+                            parsing = !parsing;
+                        }
+                    } else if ("endif".equalsIgnoreCase(cmd)) {
+                        if (ifsStack.isEmpty()) {
+                            throw new IllegalArgumentException("endif found without matching $if");
+                        }
+                        parsing = ifsStack.remove( ifsStack.size() - 1 );
+                    } else if ("include".equalsIgnoreCase(cmd)) {
+                        // TODO
+                    }
+                    continue;
+                }
+                if (!parsing) {
+                    continue;
+                }
+                boolean equivalency;
+                String keySeq = "";
+                if (line.charAt(i++) == '"') {
+                    boolean esc = false;
+                    for (;; i++) {
+                        if (i >= line.length()) {
+                            throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
+                        }
+                        if (esc) {
+                            esc = false;
+                        } else if (line.charAt(i) == '\\') {
+                            esc = true;
+                        } else if (line.charAt(i) == '"') {
+                            break;
+                        }
+                    }
+                }
+                for (; i < line.length() && line.charAt(i) != ':'
+                        && line.charAt(i) != ' ' && line.charAt(i) != '\t'
+                        ; i++);
+                keySeq = line.substring(0, i);
+                equivalency = (i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=');
+                i++;
+                if (equivalency) {
+                    i++;
+                }
+                if (keySeq.equalsIgnoreCase("set")) {
+                    String key;
+                    String val;
+                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
+                    int s = i;
+                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
+                    key = line.substring( s, i );
+                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
+                    s = i;
+                    for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
+                    val = line.substring( s, i );
+                    setVar( key, val );
+                } else {
+                    for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
+                    int start = i;
+                    if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
+                        char delim = line.charAt(i++);
+                        boolean esc = false;
+                        for (;; i++) {
+                            if (i >= line.length()) {
+                                break;
+                            }
+                            if (esc) {
+                                esc = false;
+                            } else if (line.charAt(i) == '\\') {
+                                esc = true;
+                            } else if (line.charAt(i) == delim) {
+                                break;
+                            }
+                        }
+                    }
+                    for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++);
+                    String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
+                    if (keySeq.charAt(0) == '"') {
+                        keySeq = translateQuoted(keySeq);
+                    } else {
+                        // Bind key name
+                        String keyName = keySeq.lastIndexOf('-') > 0 ? keySeq.substring( keySeq.lastIndexOf('-') + 1 ) : keySeq;
+                        char key = getKeyFromName(keyName);
+                        keyName = keySeq.toLowerCase();
+                        keySeq = "";
+                        if (keyName.contains("meta-") || keyName.contains("m-")) {
+                            keySeq += "\u001b";
+                        }
+                        if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
+                            key = (char)(Character.toUpperCase( key ) & 0x1f);
+                        }
+                        keySeq += key;
+                    }
+                    if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
+                        keys.bind( keySeq, translateQuoted(val) );
+                    } else {
+                        String operationName = val.replace('-', '_').toUpperCase();
+                        try {
+                          keys.bind(keySeq, Operation.valueOf(operationName));
+                        } catch(IllegalArgumentException e) {
+                          Log.info("Unable to bind key for unsupported operation: ", val);
+                        }
+                    }
+                }
+            } catch (IllegalArgumentException e) {
+              Log.warn("Unable to parse user configuration: ", e);
+            }
+        }
+    }
+
+    private String translateQuoted(String keySeq) {
+        int i;
+        String str = keySeq.substring( 1, keySeq.length() - 1 );
+        keySeq = "";
+        for (i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c == '\\') {
+                boolean ctrl = str.regionMatches(i, "\\C-", 0, 3)|| str.regionMatches(i, "\\M-\\C-", 0, 6);
+                boolean meta = str.regionMatches(i, "\\M-", 0, 3)|| str.regionMatches(i, "\\C-\\M-", 0, 6);
+                i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0);
+                if (i >= str.length()) {
+                    break;
+                }
+                c = str.charAt(i);
+                if (meta) {
+                    keySeq += "\u001b";
+                }
+                if (ctrl) {
+                    c = c == '?' ? 0x7f : (char)(Character.toUpperCase( c ) & 0x1f);
+                }
+                if (!meta && !ctrl) {
+                    switch (c) {
+                        case 'a': c = 0x07; break;
+                        case 'b': c = '\b'; break;
+                        case 'd': c = 0x7f; break;
+                        case 'e': c = 0x1b; break;
+                        case 'f': c = '\f'; break;
+                        case 'n': c = '\n'; break;
+                        case 'r': c = '\r'; break;
+                        case 't': c = '\t'; break;
+                        case 'v': c = 0x0b; break;
+                        case '\\': c = '\\'; break;
+                        case '0': case '1': case '2': case '3':
+                        case '4': case '5': case '6': case '7':
+                            c = 0;
+                            for (int j = 0; j < 3; j++, i++) {
+                                if (i >= str.length()) {
+                                    break;
+                                }
+                                int k = Character.digit(str.charAt(i), 8);
+                                if (k < 0) {
+                                    break;
+                                }
+                                c = (char)(c * 8 + k);
+                            }
+                            c &= 0xFF;
+                            break;
+                        case 'x':
+                            i++;
+                            c = 0;
+                            for (int j = 0; j < 2; j++, i++) {
+                                if (i >= str.length()) {
+                                    break;
+                                }
+                                int k = Character.digit(str.charAt(i), 16);
+                                if (k < 0) {
+                                    break;
+                                }
+                                c = (char)(c * 16 + k);
+                            }
+                            c &= 0xFF;
+                            break;
+                        case 'u':
+                            i++;
+                            c = 0;
+                            for (int j = 0; j < 4; j++, i++) {
+                                if (i >= str.length()) {
+                                    break;
+                                }
+                                int k = Character.digit(str.charAt(i), 16);
+                                if (k < 0) {
+                                    break;
+                                }
+                                c = (char)(c * 16 + k);
+                            }
+                            break;
+                    }
+                }
+                keySeq += c;
+            } else {
+                keySeq += c;
+            }
+        }
+        return keySeq;
+    }
+
+    private char getKeyFromName(String name) {
+        if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
+            return 0x7f;
+        } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
+            return '\033';
+        } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
+            return '\n';
+        } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
+            return '\r';
+        } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
+            return ' ';
+        } else if ("Tab".equalsIgnoreCase(name)) {
+            return '\t';
+        } else {
+            return name.charAt(0);
+        }
+    }
+
+    private void setVar(String key, String val) {
+        if ("keymap".equalsIgnoreCase(key)) {
+            if (keyMaps.containsKey(val)) {
+                keys = keyMaps.get(val);
+            }
+        } else if ("editing-mode".equals(key)) {
+            if ("vi".equalsIgnoreCase(val)) {
+                keys = keyMaps.get(KeyMap.VI_INSERT);
+            } else if ("emacs".equalsIgnoreCase(key)) {
+                keys = keyMaps.get(KeyMap.EMACS);
+            }
+        } else if ("blink-matching-paren".equals(key)) {
+            if ("on".equalsIgnoreCase(val)) {
+              keys.setBlinkMatchingParen(true);
+            } else if ("off".equalsIgnoreCase(val)) {
+              keys.setBlinkMatchingParen(false);
+            }
+        }
+
+        /*
+         * Technically variables should be defined as a functor class
+         * so that validation on the variable value can be done at parse
+         * time. This is a stop-gap.
+         */
+        variables.put(key, val);
+    }
+
+    /**
+     * Retrieves the value of a variable that was set in the .inputrc file
+     * during processing
+     * @param var The variable name
+     * @return The variable value.
+     */
+    public String getVariable(String var) {
+        return variables.get (var);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,4006 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+//import java.awt.*;
+//import java.awt.datatransfer.Clipboard;
+//import java.awt.datatransfer.DataFlavor;
+//import java.awt.datatransfer.Transferable;
+//import java.awt.datatransfer.UnsupportedFlavorException;
+//import java.awt.event.ActionListener;
+//import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+//import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+//import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+//import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Stack;
+import java.util.regex.Pattern;
+
+import jdk.internal.jline.Terminal;
+import jdk.internal.jline.TerminalFactory;
+import jdk.internal.jline.UnixTerminal;
+import jdk.internal.jline.console.completer.CandidateListCompletionHandler;
+import jdk.internal.jline.console.completer.Completer;
+import jdk.internal.jline.console.completer.CompletionHandler;
+import jdk.internal.jline.console.history.History;
+import jdk.internal.jline.console.history.MemoryHistory;
+import jdk.internal.jline.internal.Configuration;
+import jdk.internal.jline.internal.InputStreamReader;
+import jdk.internal.jline.internal.Log;
+import jdk.internal.jline.internal.NonBlockingInputStream;
+import jdk.internal.jline.internal.Nullable;
+import jdk.internal.jline.internal.Urls;
+//import org.fusesource.jansi.AnsiOutputStream;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * A reader for console applications. It supports custom tab-completion,
+ * saveable command history, and command line editing. On some platforms,
+ * platform-specific commands will need to be issued before the reader will
+ * function properly. See {@link jline.Terminal#init} for convenience
+ * methods for issuing platform-specific setup commands.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ */
+public class ConsoleReader
+{
+    public static final String JLINE_NOBELL = "jline.nobell";
+
+    public static final String JLINE_ESC_TIMEOUT = "jline.esc.timeout";
+
+    public static final String JLINE_INPUTRC = "jline.inputrc";
+
+    public static final String INPUT_RC = ".inputrc";
+
+    public static final String DEFAULT_INPUT_RC = "/etc/inputrc";
+
+    public static final char BACKSPACE = '\b';
+
+    public static final char RESET_LINE = '\r';
+
+    public static final char KEYBOARD_BELL = '\07';
+
+    public static final char NULL_MASK = 0;
+
+    public static final int TAB_WIDTH = 4;
+
+    private static final ResourceBundle
+        resources = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName());
+
+    private final Terminal terminal;
+
+    private final Writer out;
+
+    private final CursorBuffer buf = new CursorBuffer();
+
+    private String prompt;
+    private int    promptLen;
+
+    private boolean expandEvents = true;
+
+    private boolean bellEnabled = !Configuration.getBoolean(JLINE_NOBELL, true);
+
+    private boolean handleUserInterrupt = false;
+
+    private Character mask;
+
+    private Character echoCharacter;
+
+    private StringBuffer searchTerm = null;
+
+    private String previousSearchTerm = "";
+
+    private int searchIndex = -1;
+
+    private int parenBlinkTimeout = 500;
+
+    /*
+     * The reader and the nonBlockingInput go hand-in-hand.  The reader wraps
+     * the nonBlockingInput, but we have to retain a handle to it so that
+     * we can shut down its blocking read thread when we go away.
+     */
+    private NonBlockingInputStream in;
+    private long                   escapeTimeout;
+    private Reader                 reader;
+
+    /*
+     * TODO: Please read the comments about this in setInput(), but this needs
+     * to be done away with.
+     */
+    private boolean                isUnitTestInput;
+
+    /**
+     * Last character searched for with a vi character search
+     */
+    private char  charSearchChar = 0;           // Character to search for
+    private char  charSearchLastInvokeChar = 0; // Most recent invocation key
+    private char  charSearchFirstInvokeChar = 0;// First character that invoked
+
+    /**
+     * The vi yank buffer
+     */
+    private String yankBuffer = "";
+
+    private KillRing killRing = new KillRing();
+
+    private String encoding;
+
+    private boolean recording;
+
+    private String macro = "";
+
+    private String appName;
+
+    private URL inputrcUrl;
+
+    private ConsoleKeys consoleKeys;
+
+    private String commentBegin = null;
+
+    private boolean skipLF = false;
+
+    /**
+     * Set to true if the reader should attempt to detect copy-n-paste. The
+     * effect of this that an attempt is made to detect if tab is quickly
+     * followed by another character, then it is assumed that the tab was
+     * a literal tab as part of a copy-and-paste operation and is inserted as
+     * such.
+     */
+    private boolean copyPasteDetection = false;
+
+    /*
+     * Current internal state of the line reader
+     */
+    private State   state = State.NORMAL;
+
+    /**
+     * Possible states in which the current readline operation may be in.
+     */
+    private static enum State {
+        /**
+         * The user is just typing away
+         */
+        NORMAL,
+        /**
+         * In the middle of a emacs seach
+         */
+        SEARCH,
+        FORWARD_SEARCH,
+        /**
+         * VI "yank-to" operation ("y" during move mode)
+         */
+        VI_YANK_TO,
+        /**
+         * VI "delete-to" operation ("d" during move mode)
+         */
+        VI_DELETE_TO,
+        /**
+         * VI "change-to" operation ("c" during move mode)
+         */
+        VI_CHANGE_TO
+    }
+
+    public ConsoleReader() throws IOException {
+        this(null, new FileInputStream(FileDescriptor.in), System.out, null);
+    }
+
+    public ConsoleReader(final InputStream in, final OutputStream out) throws IOException {
+        this(null, in, out, null);
+    }
+
+    public ConsoleReader(final InputStream in, final OutputStream out, final Terminal term) throws IOException {
+        this(null, in, out, term);
+    }
+
+    public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term) throws IOException {
+        this(appName, in, out, term, null);
+    }
+
+    public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable Terminal term, final @Nullable String encoding)
+        throws IOException
+    {
+        this.appName = appName != null ? appName : "JLine";
+        this.encoding = encoding != null ? encoding : Configuration.getEncoding();
+        this.terminal = term != null ? term : TerminalFactory.get();
+        String outEncoding = terminal.getOutputEncoding() != null? terminal.getOutputEncoding() : this.encoding;
+        this.out = new OutputStreamWriter(terminal.wrapOutIfNeeded(out), outEncoding);
+        setInput( in );
+
+        this.inputrcUrl = getInputRc();
+
+        consoleKeys = new ConsoleKeys(this.appName, inputrcUrl);
+    }
+
+    private URL getInputRc() throws IOException {
+        String path = Configuration.getString(JLINE_INPUTRC);
+        if (path == null) {
+            File f = new File(Configuration.getUserHome(), INPUT_RC);
+            if (!f.exists()) {
+                f = new File(DEFAULT_INPUT_RC);
+            }
+            return f.toURI().toURL();
+        } else {
+            return Urls.create(path);
+        }
+    }
+
+    public KeyMap getKeys() {
+        return consoleKeys.getKeys();
+    }
+
+    void setInput(final InputStream in) throws IOException {
+        this.escapeTimeout = Configuration.getLong(JLINE_ESC_TIMEOUT, 100);
+        /*
+         * This is gross and here is how to fix it. In getCurrentPosition()
+         * and getCurrentAnsiRow(), the logic is disabled when running unit
+         * tests and the fact that it is a unit test is determined by knowing
+         * if the original input stream was a ByteArrayInputStream. So, this
+         * is our test to do this.  What SHOULD happen is that the unit
+         * tests should pass in a terminal that is appropriately configured
+         * such that whatever behavior they expect to happen (or not happen)
+         * happens (or doesn't).
+         *
+         * So, TODO, get rid of this and fix the unit tests.
+         */
+        this.isUnitTestInput = in instanceof ByteArrayInputStream;
+        boolean nonBlockingEnabled =
+               escapeTimeout > 0L
+            && terminal.isSupported()
+            && in != null;
+
+        /*
+         * If we had a non-blocking thread already going, then shut it down
+         * and start a new one.
+         */
+        if (this.in != null) {
+            this.in.shutdown();
+        }
+
+        final InputStream wrapped = terminal.wrapInIfNeeded( in );
+
+        this.in = new NonBlockingInputStream(wrapped, nonBlockingEnabled);
+        this.reader = new InputStreamReader( this.in, encoding );
+    }
+
+    /**
+     * Shuts the console reader down.  This method should be called when you
+     * have completed using the reader as it shuts down and cleans up resources
+     * that would otherwise be "leaked".
+     */
+    public void shutdown() {
+        if (in != null) {
+            in.shutdown();
+        }
+    }
+
+    /**
+     * Shuts down the ConsoleReader if the JVM attempts to clean it up.
+     */
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            shutdown();
+        }
+        finally {
+            super.finalize();
+        }
+    }
+
+    public InputStream getInput() {
+        return in;
+    }
+
+    public Writer getOutput() {
+        return out;
+    }
+
+    public Terminal getTerminal() {
+        return terminal;
+    }
+
+    public CursorBuffer getCursorBuffer() {
+        return buf;
+    }
+
+    public void setExpandEvents(final boolean expand) {
+        this.expandEvents = expand;
+    }
+
+    public boolean getExpandEvents() {
+        return expandEvents;
+    }
+
+    /**
+     * Enables or disables copy and paste detection. The effect of enabling this
+     * this setting is that when a tab is received immediately followed by another
+     * character, the tab will not be treated as a completion, but as a tab literal.
+     * @param onoff true if detection is enabled
+     */
+    public void setCopyPasteDetection(final boolean onoff) {
+        copyPasteDetection = onoff;
+    }
+
+    /**
+     * @return true if copy and paste detection is enabled.
+     */
+    public boolean isCopyPasteDetectionEnabled() {
+        return copyPasteDetection;
+    }
+
+    /**
+     * Set whether the console bell is enabled.
+     *
+     * @param enabled true if enabled; false otherwise
+     * @since 2.7
+     */
+    public void setBellEnabled(boolean enabled) {
+        this.bellEnabled = enabled;
+    }
+
+    /**
+     * Get whether the console bell is enabled
+     *
+     * @return true if enabled; false otherwise
+     * @since 2.7
+     */
+    public boolean getBellEnabled() {
+        return bellEnabled;
+    }
+
+    /**
+     * Set whether user interrupts (ctrl-C) are handled by having JLine
+     * throw {@link UserInterruptException} from {@link #readLine}.
+     * Otherwise, the JVM will handle {@code SIGINT} as normal, which
+     * usually causes it to exit. The default is {@code false}.
+     *
+     * @since 2.10
+     */
+    public void setHandleUserInterrupt(boolean enabled)
+    {
+        this.handleUserInterrupt = enabled;
+    }
+
+    /**
+     * Get whether user interrupt handling is enabled
+     *
+     * @return true if enabled; false otherwise
+     * @since 2.10
+     */
+    public boolean getHandleUserInterrupt()
+    {
+        return handleUserInterrupt;
+    }
+
+    /**
+     * Sets the string that will be used to start a comment when the
+     * insert-comment key is struck.
+     * @param commentBegin The begin comment string.
+     * @since 2.7
+     */
+    public void setCommentBegin(String commentBegin) {
+        this.commentBegin = commentBegin;
+    }
+
+    /**
+     * @return the string that will be used to start a comment when the
+     * insert-comment key is struck.
+     * @since 2.7
+     */
+    public String getCommentBegin() {
+        String str = commentBegin;
+
+        if (str == null) {
+            str = consoleKeys.getVariable("comment-begin");
+            if (str == null) {
+                str = "#";
+            }
+        }
+        return str;
+    }
+
+    public void setPrompt(final String prompt) {
+        this.prompt = prompt;
+        this.promptLen = ((prompt == null) ? 0 : stripAnsi(lastLine(prompt)).length());
+    }
+
+    public String getPrompt() {
+        return prompt;
+    }
+
+    /**
+     * Set the echo character. For example, to have "*" entered when a password is typed:
+     * <p/>
+     * <pre>
+     * myConsoleReader.setEchoCharacter(new Character('*'));
+     * </pre>
+     * <p/>
+     * Setting the character to
+     * <p/>
+     * <pre>
+     * null
+     * </pre>
+     * <p/>
+     * will restore normal character echoing. Setting the character to
+     * <p/>
+     * <pre>
+     * new Character(0)
+     * </pre>
+     * <p/>
+     * will cause nothing to be echoed.
+     *
+     * @param c the character to echo to the console in place of the typed character.
+     */
+    public void setEchoCharacter(final Character c) {
+        this.echoCharacter = c;
+    }
+
+    /**
+     * Returns the echo character.
+     */
+    public Character getEchoCharacter() {
+        return echoCharacter;
+    }
+
+    /**
+     * Erase the current line.
+     *
+     * @return false if we failed (e.g., the buffer was empty)
+     */
+    protected final boolean resetLine() throws IOException {
+        if (buf.cursor == 0) {
+            return false;
+        }
+
+        StringBuilder killed = new StringBuilder();
+
+        while (buf.cursor > 0) {
+            char c = buf.current();
+            if (c == 0) {
+                break;
+            }
+
+            killed.append(c);
+            backspace();
+        }
+
+        String copy = killed.reverse().toString();
+        killRing.addBackwards(copy);
+
+        return true;
+    }
+
+    int getCursorPosition() {
+        // FIXME: does not handle anything but a line with a prompt absolute position
+        return promptLen + buf.cursor;
+    }
+
+    /**
+     * Returns the text after the last '\n'.
+     * prompt is returned if no '\n' characters are present.
+     * null is returned if prompt is null.
+     */
+    private String lastLine(String str) {
+        if (str == null) return "";
+        int last = str.lastIndexOf("\n");
+
+        if (last >= 0) {
+            return str.substring(last + 1, str.length());
+        }
+
+        return str;
+    }
+
+    String stripAnsi(String str) {
+        if (str == null) return "";
+        return ANSI_CODE_PATTERN.matcher(str).replaceAll("");
+//        try {
+//            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//            AnsiOutputStream aos = new AnsiOutputStream(baos);
+//            aos.write(str.getBytes());
+//            aos.flush();
+//            return baos.toString();
+//        } catch (IOException e) {
+//            return str;
+//        }
+    }
+    //where:
+        private static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[^@-~]*[@-~]");
+
+    /**
+     * Move the cursor position to the specified absolute index.
+     */
+    public final boolean setCursorPosition(final int position) throws IOException {
+        if (position == buf.cursor) {
+            return true;
+        }
+
+        return moveCursor(position - buf.cursor) != 0;
+    }
+
+    /**
+     * Set the current buffer's content to the specified {@link String}. The
+     * visual console will be modified to show the current buffer.
+     *
+     * @param buffer the new contents of the buffer.
+     */
+    private void setBuffer(final String buffer) throws IOException {
+        // don't bother modifying it if it is unchanged
+        if (buffer.equals(buf.buffer.toString())) {
+            return;
+        }
+
+        // obtain the difference between the current buffer and the new one
+        int sameIndex = 0;
+
+        for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1)
+            && (i < l2); i++) {
+            if (buffer.charAt(i) == buf.buffer.charAt(i)) {
+                sameIndex++;
+            }
+            else {
+                break;
+            }
+        }
+
+        int diff = buf.cursor - sameIndex;
+        if (diff < 0) { // we can't backspace here so try from the end of the buffer
+            moveToEnd();
+            diff = buf.buffer.length() - sameIndex;
+        }
+
+        backspace(diff); // go back for the differences
+        killLine(); // clear to the end of the line
+        buf.buffer.setLength(sameIndex); // the new length
+        putString(buffer.substring(sameIndex)); // append the differences
+    }
+
+    private void setBuffer(final CharSequence buffer) throws IOException {
+        setBuffer(String.valueOf(buffer));
+    }
+
+    private void setBufferKeepPos(final String buffer) throws IOException {
+        int pos = buf.cursor;
+        setBuffer(buffer);
+        setCursorPosition(pos);
+    }
+
+    private void setBufferKeepPos(final CharSequence buffer) throws IOException {
+        setBufferKeepPos(String.valueOf(buffer));
+    }
+
+    /**
+     * Output put the prompt + the current buffer
+     */
+    public final void drawLine() throws IOException {
+        String prompt = getPrompt();
+        if (prompt != null) {
+            print(prompt);
+        }
+
+        print(buf.buffer.toString());
+
+        if (buf.length() != buf.cursor) { // not at end of line
+            back(buf.length() - buf.cursor - 1);
+        }
+        // force drawBuffer to check for weird wrap (after clear screen)
+        drawBuffer();
+    }
+
+    /**
+     * Clear the line and redraw it.
+     */
+    public final void redrawLine() throws IOException {
+        print(RESET_LINE);
+//        flush();
+        drawLine();
+    }
+
+    /**
+     * Clear the buffer and add its contents to the history.
+     *
+     * @return the former contents of the buffer.
+     */
+    final String finishBuffer() throws IOException { // FIXME: Package protected because used by tests
+        String str = buf.buffer.toString();
+        String historyLine = str;
+
+        if (expandEvents) {
+            try {
+                str = expandEvents(str);
+                // all post-expansion occurrences of '!' must have been escaped, so re-add escape to each
+                historyLine = str.replace("!", "\\!");
+                // only leading '^' results in expansion, so only re-add escape for that case
+                historyLine = historyLine.replaceAll("^\\^", "\\\\^");
+            } catch(IllegalArgumentException e) {
+                Log.error("Could not expand event", e);
+                beep();
+                buf.clear();
+                str = "";
+            }
+        }
+
+        // we only add it to the history if the buffer is not empty
+        // and if mask is null, since having a mask typically means
+        // the string was a password. We clear the mask after this call
+        if (str.length() > 0) {
+            if (mask == null && isHistoryEnabled()) {
+                history.add(historyLine);
+            }
+            else {
+                mask = null;
+            }
+        }
+
+        history.moveToEnd();
+
+        buf.buffer.setLength(0);
+        buf.cursor = 0;
+
+        return str;
+    }
+
+    /**
+     * Expand event designator such as !!, !#, !3, etc...
+     * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
+     */
+    @SuppressWarnings("fallthrough")
+    protected String expandEvents(String str) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            switch (c) {
+                case '\\':
+                    // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
+                    // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
+                    // otherwise, add the escape
+                    if (i + 1 < str.length()) {
+                        char nextChar = str.charAt(i+1);
+                        if (nextChar == '!' || (nextChar == '^' && i == 0)) {
+                            c = nextChar;
+                            i++;
+                        }
+                    }
+                    sb.append(c);
+                    break;
+                case '!':
+                    if (i + 1 < str.length()) {
+                        c = str.charAt(++i);
+                        boolean neg = false;
+                        String rep = null;
+                        int i1, idx;
+                        switch (c) {
+                            case '!':
+                                if (history.size() == 0) {
+                                    throw new IllegalArgumentException("!!: event not found");
+                                }
+                                rep = history.get(history.index() - 1).toString();
+                                break;
+                            case '#':
+                                sb.append(sb.toString());
+                                break;
+                            case '?':
+                                i1 = str.indexOf('?', i + 1);
+                                if (i1 < 0) {
+                                    i1 = str.length();
+                                }
+                                String sc = str.substring(i + 1, i1);
+                                i = i1;
+                                idx = searchBackwards(sc);
+                                if (idx < 0) {
+                                    throw new IllegalArgumentException("!?" + sc + ": event not found");
+                                } else {
+                                    rep = history.get(idx).toString();
+                                }
+                                break;
+                            case '$':
+                                if (history.size() == 0) {
+                                    throw new IllegalArgumentException("!$: event not found");
+                                }
+                                String previous = history.get(history.index() - 1).toString().trim();
+                                int lastSpace = previous.lastIndexOf(' ');
+                                if(lastSpace != -1) {
+                                    rep = previous.substring(lastSpace+1);
+                                } else {
+                                    rep = previous;
+                                }
+                                break;
+                            case ' ':
+                            case '\t':
+                                sb.append('!');
+                                sb.append(c);
+                                break;
+                            case '-':
+                                neg = true;
+                                i++;
+                                // fall through
+                            case '0':
+                            case '1':
+                            case '2':
+                            case '3':
+                            case '4':
+                            case '5':
+                            case '6':
+                            case '7':
+                            case '8':
+                            case '9':
+                                i1 = i;
+                                for (; i < str.length(); i++) {
+                                    c = str.charAt(i);
+                                    if (c < '0' || c > '9') {
+                                        break;
+                                    }
+                                }
+                                idx = 0;
+                                try {
+                                    idx = Integer.parseInt(str.substring(i1, i));
+                                } catch (NumberFormatException e) {
+                                    throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
+                                }
+                                if (neg) {
+                                    if (idx > 0 && idx <= history.size()) {
+                                        rep = (history.get(history.index() - idx)).toString();
+                                    } else {
+                                        throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
+                                    }
+                                } else {
+                                    if (idx > history.index() - history.size() && idx <= history.index()) {
+                                        rep = (history.get(idx - 1)).toString();
+                                    } else {
+                                        throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
+                                    }
+                                }
+                                break;
+                            default:
+                                String ss = str.substring(i);
+                                i = str.length();
+                                idx = searchBackwards(ss, history.index(), true);
+                                if (idx < 0) {
+                                    throw new IllegalArgumentException("!" + ss + ": event not found");
+                                } else {
+                                    rep = history.get(idx).toString();
+                                }
+                                break;
+                        }
+                        if (rep != null) {
+                            sb.append(rep);
+                        }
+                    } else {
+                        sb.append(c);
+                    }
+                    break;
+                case '^':
+                    if (i == 0) {
+                        int i1 = str.indexOf('^', i + 1);
+                        int i2 = str.indexOf('^', i1 + 1);
+                        if (i2 < 0) {
+                            i2 = str.length();
+                        }
+                        if (i1 > 0 && i2 > 0) {
+                            String s1 = str.substring(i + 1, i1);
+                            String s2 = str.substring(i1 + 1, i2);
+                            String s = history.get(history.index() - 1).toString().replace(s1, s2);
+                            sb.append(s);
+                            i = i2 + 1;
+                            break;
+                        }
+                    }
+                    sb.append(c);
+                    break;
+                default:
+                    sb.append(c);
+                    break;
+            }
+        }
+        String result = sb.toString();
+        if (!str.equals(result)) {
+            print(result);
+            println();
+            flush();
+        }
+        return result;
+
+    }
+
+    /**
+     * Write out the specified string to the buffer and the output stream.
+     */
+    public final void putString(final CharSequence str) throws IOException {
+        buf.write(str);
+        if (mask == null) {
+            // no masking
+            print(str);
+        } else if (mask == NULL_MASK) {
+            // don't print anything
+        } else {
+            print(mask, str.length());
+        }
+        drawBuffer();
+    }
+
+    /**
+     * Redraw the rest of the buffer from the cursor onwards. This is necessary
+     * for inserting text into the buffer.
+     *
+     * @param clear the number of characters to clear after the end of the buffer
+     */
+    private void drawBuffer(final int clear) throws IOException {
+        // debug ("drawBuffer: " + clear);
+        if (buf.cursor == buf.length() && clear == 0) {
+        } else {
+            char[] chars = buf.buffer.substring(buf.cursor).toCharArray();
+            if (mask != null) {
+                Arrays.fill(chars, mask);
+            }
+            if (terminal.hasWeirdWrap()) {
+                // need to determine if wrapping will occur:
+                int width = terminal.getWidth();
+                int pos = getCursorPosition();
+                for (int i = 0; i < chars.length; i++) {
+                    print(chars[i]);
+                    if ((pos + i + 1) % width == 0) {
+                        print(32); // move cursor to next line by printing dummy space
+                        print(13); // CR / not newline.
+                    }
+                }
+            } else {
+                print(chars);
+            }
+            clearAhead(clear, chars.length);
+            if (terminal.isAnsiSupported()) {
+                if (chars.length > 0) {
+                    back(chars.length);
+                }
+            } else {
+                back(chars.length);
+            }
+        }
+        if (terminal.hasWeirdWrap()) {
+            int width = terminal.getWidth();
+            // best guess on whether the cursor is in that weird location...
+            // Need to do this without calling ansi cursor location methods
+            // otherwise it breaks paste of wrapped lines in xterm.
+            if (getCursorPosition() > 0 && (getCursorPosition() % width == 0)
+                    && buf.cursor == buf.length() && clear == 0) {
+                // the following workaround is reverse-engineered from looking
+                // at what bash sent to the terminal in the same situation
+                print(32); // move cursor to next line by printing dummy space
+                print(13); // CR / not newline.
+            }
+        }
+    }
+
+    /**
+     * Redraw the rest of the buffer from the cursor onwards. This is necessary
+     * for inserting text into the buffer.
+     */
+    private void drawBuffer() throws IOException {
+        drawBuffer(0);
+    }
+
+    /**
+     * Clear ahead the specified number of characters without moving the cursor.
+     *
+     * @param num the number of characters to clear
+     * @param delta the difference between the internal cursor and the screen
+     * cursor - if > 0, assume some stuff was printed and weird wrap has to be
+     * checked
+     */
+    private void clearAhead(final int num, int delta) throws IOException {
+        if (num == 0) {
+            return;
+        }
+
+        if (terminal.isAnsiSupported()) {
+            int width = terminal.getWidth();
+            int screenCursorCol = getCursorPosition() + delta;
+            // clear current line
+            printAnsiSequence("K");
+            // if cursor+num wraps, then we need to clear the line(s) below too
+            int curCol = screenCursorCol % width;
+            int endCol = (screenCursorCol + num - 1) % width;
+            int lines = num / width;
+            if (endCol < curCol) lines++;
+            for (int i = 0; i < lines; i++) {
+                printAnsiSequence("B");
+                printAnsiSequence("2K");
+            }
+            for (int i = 0; i < lines; i++) {
+                printAnsiSequence("A");
+            }
+            return;
+        }
+
+        // print blank extra characters
+        print(' ', num);
+
+        // we need to flush here so a "clever" console doesn't just ignore the redundancy
+        // of a space followed by a backspace.
+//        flush();
+
+        // reset the visual cursor
+        back(num);
+
+//        flush();
+    }
+
+    /**
+     * Move the visual cursor backwards without modifying the buffer cursor.
+     */
+    protected void back(final int num) throws IOException {
+        if (num == 0) return;
+        if (terminal.isAnsiSupported()) {
+            int width = getTerminal().getWidth();
+            int cursor = getCursorPosition();
+            int realCursor = cursor + num;
+            int realCol  = realCursor % width;
+            int newCol = cursor % width;
+            int moveup = num / width;
+            int delta = realCol - newCol;
+            if (delta < 0) moveup++;
+            if (moveup > 0) {
+                printAnsiSequence(moveup + "A");
+            }
+            printAnsiSequence((1 + newCol) + "G");
+            return;
+        }
+        print(BACKSPACE, num);
+//        flush();
+    }
+
+    /**
+     * Flush the console output stream. This is important for printout out single characters (like a backspace or
+     * keyboard) that we want the console to handle immediately.
+     */
+    public void flush() throws IOException {
+        out.flush();
+    }
+
+    private int backspaceAll() throws IOException {
+        return backspace(Integer.MAX_VALUE);
+    }
+
+    /**
+     * Issue <em>num</em> backspaces.
+     *
+     * @return the number of characters backed up
+     */
+    private int backspace(final int num) throws IOException {
+        if (buf.cursor == 0) {
+            return 0;
+        }
+
+        int count = 0;
+
+        int termwidth = getTerminal().getWidth();
+        int lines = getCursorPosition() / termwidth;
+        count = moveCursor(-1 * num) * -1;
+        buf.buffer.delete(buf.cursor, buf.cursor + count);
+        if (getCursorPosition() / termwidth != lines) {
+            if (terminal.isAnsiSupported()) {
+                // debug("doing backspace redraw: " + getCursorPosition() + " on " + termwidth + ": " + lines);
+                printAnsiSequence("K");
+                // if cursor+num wraps, then we need to clear the line(s) below too
+                // last char printed is one pos less than cursor so we subtract
+                // one
+/*
+                // TODO: fixme (does not work - test with reverse search with wrapping line and CTRL-E)
+                int endCol = (getCursorPosition() + num - 1) % termwidth;
+                int curCol = getCursorPosition() % termwidth;
+                if (endCol < curCol) lines++;
+                for (int i = 1; i < lines; i++) {
+                    printAnsiSequence("B");
+                    printAnsiSequence("2K");
+                }
+                for (int i = 1; i < lines; i++) {
+                    printAnsiSequence("A");
+                }
+                return count;
+*/
+            }
+        }
+        drawBuffer(count);
+
+        return count;
+    }
+
+    /**
+     * Issue a backspace.
+     *
+     * @return true if successful
+     */
+    public boolean backspace() throws IOException {
+        return backspace(1) == 1;
+    }
+
+    protected boolean moveToEnd() throws IOException {
+        if (buf.cursor == buf.length()) {
+            return true;
+        }
+        return moveCursor(buf.length() - buf.cursor) > 0;
+    }
+
+    /**
+     * Delete the character at the current position and redraw the remainder of the buffer.
+     */
+    private boolean deleteCurrentCharacter() throws IOException {
+        if (buf.length() == 0 || buf.cursor == buf.length()) {
+            return false;
+        }
+
+        buf.buffer.deleteCharAt(buf.cursor);
+        drawBuffer(1);
+        return true;
+    }
+
+    /**
+     * This method is calling while doing a delete-to ("d"), change-to ("c"),
+     * or yank-to ("y") and it filters out only those movement operations
+     * that are allowable during those operations. Any operation that isn't
+     * allow drops you back into movement mode.
+     *
+     * @param op The incoming operation to remap
+     * @return The remaped operation
+     */
+    private Operation viDeleteChangeYankToRemap (Operation op) {
+        switch (op) {
+            case VI_EOF_MAYBE:
+            case ABORT:
+            case BACKWARD_CHAR:
+            case FORWARD_CHAR:
+            case END_OF_LINE:
+            case VI_MATCH:
+            case VI_BEGNNING_OF_LINE_OR_ARG_DIGIT:
+            case VI_ARG_DIGIT:
+            case VI_PREV_WORD:
+            case VI_END_WORD:
+            case VI_CHAR_SEARCH:
+            case VI_NEXT_WORD:
+            case VI_FIRST_PRINT:
+            case VI_GOTO_MARK:
+            case VI_COLUMN:
+            case VI_DELETE_TO:
+            case VI_YANK_TO:
+            case VI_CHANGE_TO:
+                return op;
+
+            default:
+                return Operation.VI_MOVEMENT_MODE;
+        }
+    }
+
+    /**
+     * Deletes the previous character from the cursor position
+     * @param count number of times to do it.
+     * @return true if it was done.
+     * @throws IOException
+     */
+    private boolean viRubout(int count) throws IOException {
+        boolean ok = true;
+        for (int i = 0; ok && i < count; i++) {
+            ok = backspace();
+        }
+        return ok;
+    }
+
+    /**
+     * Deletes the character you are sitting on and sucks the rest of
+     * the line in from the right.
+     * @param count Number of times to perform the operation.
+     * @return true if its works, false if it didn't
+     * @throws IOException
+     */
+    private boolean viDelete(int count) throws IOException {
+        boolean ok = true;
+        for (int i = 0; ok && i < count; i++) {
+            ok = deleteCurrentCharacter();
+        }
+        return ok;
+    }
+
+    /**
+     * Switches the case of the current character from upper to lower
+     * or lower to upper as necessary and advances the cursor one
+     * position to the right.
+     * @param count The number of times to repeat
+     * @return true if it completed successfully, false if not all
+     *   case changes could be completed.
+     * @throws IOException
+     */
+    private boolean viChangeCase(int count) throws IOException {
+        boolean ok = true;
+        for (int i = 0; ok && i < count; i++) {
+
+            ok = buf.cursor < buf.buffer.length ();
+            if (ok) {
+                char ch = buf.buffer.charAt(buf.cursor);
+                if (Character.isUpperCase(ch)) {
+                    ch = Character.toLowerCase(ch);
+                }
+                else if (Character.isLowerCase(ch)) {
+                    ch = Character.toUpperCase(ch);
+                }
+                buf.buffer.setCharAt(buf.cursor, ch);
+                drawBuffer(1);
+                moveCursor(1);
+            }
+        }
+        return ok;
+    }
+
+    /**
+     * Implements the vi change character command (in move-mode "r"
+     * followed by the character to change to).
+     * @param count Number of times to perform the action
+     * @param c The character to change to
+     * @return Whether or not there were problems encountered
+     * @throws IOException
+     */
+    private boolean viChangeChar(int count, int c) throws IOException {
+        // EOF, ESC, or CTRL-C aborts.
+        if (c < 0 || c == '\033' || c == '\003') {
+            return true;
+        }
+
+        boolean ok = true;
+        for (int i = 0; ok && i < count; i++) {
+            ok = buf.cursor < buf.buffer.length ();
+            if (ok) {
+                buf.buffer.setCharAt(buf.cursor, (char) c);
+                drawBuffer(1);
+                if (i < (count-1)) {
+                    moveCursor(1);
+                }
+            }
+        }
+        return ok;
+    }
+
+    /**
+     * This is a close facsimile of the actual vi previous word logic. In
+     * actual vi words are determined by boundaries of identity characterse.
+     * This logic is a bit more simple and simply looks at white space or
+     * digits or characters.  It should be revised at some point.
+     *
+     * @param count number of iterations
+     * @return true if the move was successful, false otherwise
+     * @throws IOException
+     */
+    private boolean viPreviousWord(int count) throws IOException {
+        boolean ok = true;
+        if (buf.cursor == 0) {
+            return false;
+        }
+
+        int pos = buf.cursor - 1;
+        for (int i = 0; pos > 0 && i < count; i++) {
+            // If we are on white space, then move back.
+            while (pos > 0 && isWhitespace(buf.buffer.charAt(pos))) {
+                --pos;
+            }
+
+            while (pos > 0 && !isDelimiter(buf.buffer.charAt(pos-1))) {
+                --pos;
+            }
+
+            if (pos > 0 && i < (count-1)) {
+                --pos;
+            }
+        }
+        setCursorPosition(pos);
+        return ok;
+    }
+
+    /**
+     * Performs the vi "delete-to" action, deleting characters between a given
+     * span of the input line.
+     * @param startPos The start position
+     * @param endPos The end position.
+     * @param isChange If true, then the delete is part of a change operationg
+     *    (e.g. "c$" is change-to-end-of line, so we first must delete to end
+     *    of line to start the change
+     * @return true if it succeeded, false otherwise
+     * @throws IOException
+     */
+    private boolean viDeleteTo(int startPos, int endPos, boolean isChange) throws IOException {
+        if (startPos == endPos) {
+            return true;
+        }
+
+        if (endPos < startPos) {
+            int tmp = endPos;
+            endPos = startPos;
+            startPos = tmp;
+        }
+
+        setCursorPosition(startPos);
+        buf.cursor = startPos;
+        buf.buffer.delete(startPos, endPos);
+        drawBuffer(endPos - startPos);
+
+        // If we are doing a delete operation (e.g. "d$") then don't leave the
+        // cursor dangling off the end. In reality the "isChange" flag is silly
+        // what is really happening is that if we are in "move-mode" then the
+        // cursor can't be moved off the end of the line, but in "edit-mode" it
+        // is ok, but I have no easy way of knowing which mode we are in.
+        if (! isChange && startPos > 0 && startPos == buf.length()) {
+            moveCursor(-1);
+        }
+        return true;
+    }
+
+    /**
+     * Implement the "vi" yank-to operation.  This operation allows you
+     * to yank the contents of the current line based upon a move operation,
+     * for exaple "yw" yanks the current word, "3yw" yanks 3 words, etc.
+     *
+     * @param startPos The starting position from which to yank
+     * @param endPos The ending position to which to yank
+     * @return true if the yank succeeded
+     * @throws IOException
+     */
+    private boolean viYankTo(int startPos, int endPos) throws IOException {
+        int cursorPos = startPos;
+
+        if (endPos < startPos) {
+            int tmp = endPos;
+            endPos = startPos;
+            startPos = tmp;
+        }
+
+        if (startPos == endPos) {
+            yankBuffer = "";
+            return true;
+        }
+
+        yankBuffer = buf.buffer.substring(startPos, endPos);
+
+        /*
+         * It was a movement command that moved the cursor to find the
+         * end position, so put the cursor back where it started.
+         */
+        setCursorPosition(cursorPos);
+        return true;
+    }
+
+    /**
+     * Pasts the yank buffer to the right of the current cursor position
+     * and moves the cursor to the end of the pasted region.
+     *
+     * @param count Number of times to perform the operation.
+     * @return true if it worked, false otherwise
+     * @throws IOException
+     */
+    private boolean viPut(int count) throws IOException {
+        if (yankBuffer.length () == 0) {
+            return true;
+        }
+        if (buf.cursor < buf.buffer.length ()) {
+            moveCursor(1);
+        }
+        for (int i = 0; i < count; i++) {
+            putString(yankBuffer);
+        }
+        moveCursor(-1);
+        return true;
+    }
+
+    /**
+     * Searches forward of the current position for a character and moves
+     * the cursor onto it.
+     * @param count Number of times to repeat the process.
+     * @param ch The character to search for
+     * @return true if the char was found, false otherwise
+     * @throws IOException
+     */
+    private boolean viCharSearch(int count, int invokeChar, int ch) throws IOException {
+        if (ch < 0 || invokeChar < 0) {
+            return false;
+        }
+
+        char    searchChar = (char)ch;
+        boolean isForward;
+        boolean stopBefore;
+
+        /*
+         * The character stuff turns out to be hairy. Here is how it works:
+         *   f - search forward for ch
+         *   F - search backward for ch
+         *   t - search forward for ch, but stop just before the match
+         *   T - search backward for ch, but stop just after the match
+         *   ; - After [fFtT;], repeat the last search, after ',' reverse it
+         *   , - After [fFtT;], reverse the last search, after ',' repeat it
+         */
+        if (invokeChar == ';' || invokeChar == ',') {
+            // No recent search done? Then bail
+            if (charSearchChar == 0) {
+                return false;
+            }
+
+            // Reverse direction if switching between ',' and ';'
+            if (charSearchLastInvokeChar == ';' || charSearchLastInvokeChar == ',') {
+                if (charSearchLastInvokeChar != invokeChar) {
+                    charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
+                }
+            }
+            else {
+                if (invokeChar == ',') {
+                    charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
+                }
+            }
+
+            searchChar = charSearchChar;
+        }
+        else {
+            charSearchChar            = searchChar;
+            charSearchFirstInvokeChar = (char) invokeChar;
+        }
+
+        charSearchLastInvokeChar = (char)invokeChar;
+
+        isForward = Character.isLowerCase(charSearchFirstInvokeChar);
+        stopBefore = (Character.toLowerCase(charSearchFirstInvokeChar) == 't');
+
+        boolean ok = false;
+
+        if (isForward) {
+            while (count-- > 0) {
+                int pos = buf.cursor + 1;
+                while (pos < buf.buffer.length()) {
+                    if (buf.buffer.charAt(pos) == searchChar) {
+                        setCursorPosition(pos);
+                        ok = true;
+                        break;
+                    }
+                    ++pos;
+                }
+            }
+
+            if (ok) {
+                if (stopBefore)
+                    moveCursor(-1);
+
+                /*
+                 * When in yank-to, move-to, del-to state we actually want to
+                 * go to the character after the one we landed on to make sure
+                 * that the character we ended up on is included in the
+                 * operation
+                 */
+                if (isInViMoveOperationState()) {
+                    moveCursor(1);
+                }
+            }
+        }
+        else {
+            while (count-- > 0) {
+                int pos = buf.cursor - 1;
+                while (pos >= 0) {
+                    if (buf.buffer.charAt(pos) == searchChar) {
+                        setCursorPosition(pos);
+                        ok = true;
+                        break;
+                    }
+                    --pos;
+                }
+            }
+
+            if (ok && stopBefore)
+                moveCursor(1);
+        }
+
+        return ok;
+    }
+
+    private char switchCase(char ch) {
+        if (Character.isUpperCase(ch)) {
+            return Character.toLowerCase(ch);
+        }
+        return Character.toUpperCase(ch);
+    }
+
+    /**
+     * @return true if line reader is in the middle of doing a change-to
+     *   delete-to or yank-to.
+     */
+    private final boolean isInViMoveOperationState() {
+        return state == State.VI_CHANGE_TO
+            || state == State.VI_DELETE_TO
+            || state == State.VI_YANK_TO;
+    }
+
+    /**
+     * This is a close facsimile of the actual vi next word logic.
+     * As with viPreviousWord() this probably needs to be improved
+     * at some point.
+     *
+     * @param count number of iterations
+     * @return true if the move was successful, false otherwise
+     * @throws IOException
+     */
+    private boolean viNextWord(int count) throws IOException {
+        int pos = buf.cursor;
+        int end = buf.buffer.length();
+
+        for (int i = 0; pos < end && i < count; i++) {
+            // Skip over letter/digits
+            while (pos < end && !isDelimiter(buf.buffer.charAt(pos))) {
+                ++pos;
+            }
+
+            /*
+             * Don't you love special cases? During delete-to and yank-to
+             * operations the word movement is normal. However, during a
+             * change-to, the trailing spaces behind the last word are
+             * left in tact.
+             */
+            if (i < (count-1) || !(state == State.VI_CHANGE_TO)) {
+                while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
+                    ++pos;
+                }
+            }
+        }
+
+        setCursorPosition(pos);
+        return true;
+    }
+
+    /**
+     * Implements a close facsimile of the vi end-of-word movement.
+     * If the character is on white space, it takes you to the end
+     * of the next word.  If it is on the last character of a word
+     * it takes you to the next of the next word.  Any other character
+     * of a word, takes you to the end of the current word.
+     *
+     * @param count Number of times to repeat the action
+     * @return true if it worked.
+     * @throws IOException
+     */
+    private boolean viEndWord(int count) throws IOException {
+        int pos = buf.cursor;
+        int end = buf.buffer.length();
+
+        for (int i = 0; pos < end && i < count; i++) {
+            if (pos < (end-1)
+                    && !isDelimiter(buf.buffer.charAt(pos))
+                    && isDelimiter(buf.buffer.charAt (pos+1))) {
+                ++pos;
+            }
+
+            // If we are on white space, then move back.
+            while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
+                ++pos;
+            }
+
+            while (pos < (end-1) && !isDelimiter(buf.buffer.charAt(pos+1))) {
+                ++pos;
+            }
+        }
+        setCursorPosition(pos);
+        return true;
+    }
+
+    private boolean previousWord() throws IOException {
+        while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
+            // nothing
+        }
+
+        while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
+            // nothing
+        }
+
+        return true;
+    }
+
+    private boolean nextWord() throws IOException {
+        while (isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
+            // nothing
+        }
+
+        while (!isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
+            // nothing
+        }
+
+        return true;
+    }
+
+    /**
+     * Deletes to the beginning of the word that the cursor is sitting on.
+     * If the cursor is on white-space, it deletes that and to the beginning
+     * of the word before it.  If the user is not on a word or whitespace
+     * it deletes up to the end of the previous word.
+     *
+     * @param count Number of times to perform the operation
+     * @return true if it worked, false if you tried to delete too many words
+     * @throws IOException
+     */
+    private boolean unixWordRubout(int count) throws IOException {
+        boolean success = true;
+        StringBuilder killed = new StringBuilder();
+
+        for (; count > 0; --count) {
+            if (buf.cursor == 0) {
+                success = false;
+                break;
+            }
+
+            while (isWhitespace(buf.current())) {
+                char c = buf.current();
+                if (c == 0) {
+                    break;
+                }
+
+                killed.append(c);
+                backspace();
+            }
+
+            while (!isWhitespace(buf.current())) {
+                char c = buf.current();
+                if (c == 0) {
+                    break;
+                }
+
+                killed.append(c);
+                backspace();
+            }
+        }
+
+        String copy = killed.reverse().toString();
+        killRing.addBackwards(copy);
+
+        return success;
+    }
+
+    private String insertComment(boolean isViMode) throws IOException {
+        String comment = this.getCommentBegin ();
+        setCursorPosition(0);
+        putString(comment);
+        if (isViMode) {
+            consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+        }
+        return accept();
+    }
+
+    /**
+     * Similar to putString() but allows the string to be repeated a specific
+     * number of times, allowing easy support of vi digit arguments to a given
+     * command. The string is placed as the current cursor position.
+     *
+     * @param count The count of times to insert the string.
+     * @param str The string to insert
+     * @return true if the operation is a success, false otherwise
+     * @throws IOException
+     */
+    private boolean insert(int count, final CharSequence str) throws IOException {
+        for (int i = 0; i < count; i++) {
+            buf.write(str);
+            if (mask == null) {
+                // no masking
+                print(str);
+            } else if (mask == NULL_MASK) {
+                // don't print anything
+            } else {
+                print(mask, str.length());
+            }
+        }
+        drawBuffer();
+        return true;
+    }
+
+    /**
+     * Implements vi search ("/" or "?").
+     * @throws IOException
+     */
+    @SuppressWarnings("fallthrough")
+    private int viSearch(char searchChar) throws IOException {
+        boolean isForward = (searchChar == '/');
+
+        /*
+         * This is a little gross, I'm sure there is a more appropriate way
+         * of saving and restoring state.
+         */
+        CursorBuffer origBuffer = buf.copy();
+
+        // Clear the contents of the current line and
+        setCursorPosition (0);
+        killLine();
+
+        // Our new "prompt" is the character that got us into search mode.
+        putString(Character.toString(searchChar));
+        flush();
+
+        boolean isAborted = false;
+        boolean isComplete = false;
+
+        /*
+         * Readline doesn't seem to do any special character map handling
+         * here, so I think we are safe.
+         */
+        int ch = -1;
+        while (!isAborted && !isComplete && (ch = readCharacter()) != -1) {
+            switch (ch) {
+                case '\033':  // ESC
+                    /*
+                     * The ESC behavior doesn't appear to be readline behavior,
+                     * but it is a little tweak of my own. I like it.
+                     */
+                    isAborted = true;
+                    break;
+                case '\010':  // Backspace
+                case '\177':  // Delete
+                    backspace();
+                    /*
+                     * Backspacing through the "prompt" aborts the search.
+                     */
+                    if (buf.cursor == 0) {
+                        isAborted = true;
+                    }
+                    break;
+                case '\012': // NL
+                case '\015': // CR
+                    isComplete = true;
+                    break;
+                default:
+                    putString(Character.toString((char) ch));
+            }
+
+            flush();
+        }
+
+        // If we aborted, then put ourself at the end of the original buffer.
+        if (ch == -1 || isAborted) {
+            setCursorPosition(0);
+            killLine();
+            putString(origBuffer.buffer);
+            setCursorPosition(origBuffer.cursor);
+            return -1;
+        }
+
+        /*
+         * The first character of the buffer was the search character itself
+         * so we discard it.
+         */
+        String searchTerm = buf.buffer.substring(1);
+        int idx = -1;
+
+        /*
+         * The semantics of the history thing is gross when you want to
+         * explicitly iterate over entries (without an iterator) as size()
+         * returns the actual number of entries in the list but get()
+         * doesn't work the way you think.
+         */
+        int end   = history.index();
+        int start = (end <= history.size()) ? 0 : end - history.size();
+
+        if (isForward) {
+            for (int i = start; i < end; i++) {
+                if (history.get(i).toString().contains(searchTerm)) {
+                    idx = i;
+                    break;
+                }
+            }
+        }
+        else {
+            for (int i = end-1; i >= start; i--) {
+                if (history.get(i).toString().contains(searchTerm)) {
+                    idx = i;
+                    break;
+                }
+            }
+        }
+
+        /*
+         * No match? Then restore what we were working on, but make sure
+         * the cursor is at the beginning of the line.
+         */
+        if (idx == -1) {
+            setCursorPosition(0);
+            killLine();
+            putString(origBuffer.buffer);
+            setCursorPosition(0);
+            return -1;
+        }
+
+        /*
+         * Show the match.
+         */
+        setCursorPosition(0);
+        killLine();
+        putString(history.get(idx));
+        setCursorPosition(0);
+        flush();
+
+        /*
+         * While searching really only the "n" and "N" keys are interpreted
+         * as movement, any other key is treated as if you are editing the
+         * line with it, so we return it back up to the caller for interpretation.
+         */
+        isComplete = false;
+        while (!isComplete && (ch = readCharacter()) != -1) {
+            boolean forward = isForward;
+            switch (ch) {
+                case 'p': case 'P':
+                    forward = !isForward;
+                    // Fallthru
+                case 'n': case 'N':
+                    boolean isMatch = false;
+                    if (forward) {
+                        for (int i = idx+1; !isMatch && i < end; i++) {
+                            if (history.get(i).toString().contains(searchTerm)) {
+                                idx = i;
+                                isMatch = true;
+                            }
+                        }
+                    }
+                    else {
+                        for (int i = idx - 1; !isMatch && i >= start; i--) {
+                            if (history.get(i).toString().contains(searchTerm)) {
+                                idx = i;
+                                isMatch = true;
+                            }
+                        }
+                    }
+                    if (isMatch) {
+                        setCursorPosition(0);
+                        killLine();
+                        putString(history.get(idx));
+                        setCursorPosition(0);
+                    }
+                    break;
+                default:
+                    isComplete = true;
+            }
+            flush();
+        }
+
+        /*
+         * Complete?
+         */
+        return ch;
+    }
+
+    public void setParenBlinkTimeout(int timeout) {
+        parenBlinkTimeout = timeout;
+    }
+
+    private void insertClose(String s) throws IOException {
+         putString(s);
+         int closePosition = buf.cursor;
+
+         moveCursor(-1);
+         viMatch();
+
+
+         if (in.isNonBlockingEnabled()) {
+            in.peek(parenBlinkTimeout);
+         }
+
+         setCursorPosition(closePosition);
+    }
+
+    /**
+     * Implements vi style bracket matching ("%" command). The matching
+     * bracket for the current bracket type that you are sitting on is matched.
+     * The logic works like so:
+     * @return true if it worked, false if the cursor was not on a bracket
+     *   character or if there was no matching bracket.
+     * @throws IOException
+     */
+    private boolean viMatch() throws IOException {
+        int pos        = buf.cursor;
+
+        if (pos == buf.length()) {
+            return false;
+        }
+
+        int type       = getBracketType(buf.buffer.charAt (pos));
+        int move       = (type < 0) ? -1 : 1;
+        int count      = 1;
+
+        if (type == 0)
+            return false;
+
+        while (count > 0) {
+            pos += move;
+
+            // Fell off the start or end.
+            if (pos < 0 || pos >= buf.buffer.length ()) {
+                return false;
+            }
+
+            int curType = getBracketType(buf.buffer.charAt (pos));
+            if (curType == type) {
+                ++count;
+            }
+            else if (curType == -type) {
+                --count;
+            }
+        }
+
+        /*
+         * Slight adjustment for delete-to, yank-to, change-to to ensure
+         * that the matching paren is consumed
+         */
+        if (move > 0 && isInViMoveOperationState())
+            ++pos;
+
+        setCursorPosition(pos);
+        return true;
+    }
+
+    /**
+     * Given a character determines what type of bracket it is (paren,
+     * square, curly, or none).
+     * @param ch The character to check
+     * @return 1 is square, 2 curly, 3 parent, or zero for none.  The value
+     *   will be negated if it is the closing form of the bracket.
+     */
+    private int getBracketType (char ch) {
+        switch (ch) {
+            case '[': return  1;
+            case ']': return -1;
+            case '{': return  2;
+            case '}': return -2;
+            case '(': return  3;
+            case ')': return -3;
+            default:
+                return 0;
+        }
+    }
+
+    private boolean deletePreviousWord() throws IOException {
+        StringBuilder killed = new StringBuilder();
+        char c;
+
+        while (isDelimiter((c = buf.current()))) {
+            if (c == 0) {
+                break;
+            }
+
+            killed.append(c);
+            backspace();
+        }
+
+        while (!isDelimiter((c = buf.current()))) {
+            if (c == 0) {
+                break;
+            }
+
+            killed.append(c);
+            backspace();
+        }
+
+        String copy = killed.reverse().toString();
+        killRing.addBackwards(copy);
+        return true;
+    }
+
+    private boolean deleteNextWord() throws IOException {
+        StringBuilder killed = new StringBuilder();
+        char c;
+
+        while (isDelimiter((c = buf.nextChar()))) {
+            if (c == 0) {
+                break;
+            }
+            killed.append(c);
+            delete();
+        }
+
+        while (!isDelimiter((c = buf.nextChar()))) {
+            if (c == 0) {
+                break;
+            }
+            killed.append(c);
+            delete();
+        }
+
+        String copy = killed.toString();
+        killRing.add(copy);
+
+        return true;
+    }
+
+    private boolean capitalizeWord() throws IOException {
+        boolean first = true;
+        int i = 1;
+        char c;
+        while (buf.cursor + i  - 1< buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
+            buf.buffer.setCharAt(buf.cursor + i - 1, first ? Character.toUpperCase(c) : Character.toLowerCase(c));
+            first = false;
+            i++;
+        }
+        drawBuffer();
+        moveCursor(i - 1);
+        return true;
+    }
+
+    private boolean upCaseWord() throws IOException {
+        int i = 1;
+        char c;
+        while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
+            buf.buffer.setCharAt(buf.cursor + i - 1, Character.toUpperCase(c));
+            i++;
+        }
+        drawBuffer();
+        moveCursor(i - 1);
+        return true;
+    }
+
+    private boolean downCaseWord() throws IOException {
+        int i = 1;
+        char c;
+        while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
+            buf.buffer.setCharAt(buf.cursor + i - 1, Character.toLowerCase(c));
+            i++;
+        }
+        drawBuffer();
+        moveCursor(i - 1);
+        return true;
+    }
+
+    /**
+     * Performs character transpose. The character prior to the cursor and the
+     * character under the cursor are swapped and the cursor is advanced one
+     * character unless you are already at the end of the line.
+     *
+     * @param count The number of times to perform the transpose
+     * @return true if the operation succeeded, false otherwise (e.g. transpose
+     *   cannot happen at the beginning of the line).
+     * @throws IOException
+     */
+    private boolean transposeChars(int count) throws IOException {
+        for (; count > 0; --count) {
+            if (buf.cursor == 0 || buf.cursor == buf.buffer.length()) {
+                return false;
+            }
+
+            int first  = buf.cursor-1;
+            int second = buf.cursor;
+
+            char tmp = buf.buffer.charAt (first);
+            buf.buffer.setCharAt(first, buf.buffer.charAt(second));
+            buf.buffer.setCharAt(second, tmp);
+
+            // This could be done more efficiently by only re-drawing at the end.
+            moveInternal(-1);
+            drawBuffer();
+            moveInternal(2);
+        }
+
+        return true;
+    }
+
+    public boolean isKeyMap(String name) {
+        // Current keymap.
+        KeyMap map = consoleKeys.getKeys();
+        KeyMap mapByName = consoleKeys.getKeyMaps().get(name);
+
+        if (mapByName == null)
+            return false;
+
+        /*
+         * This may not be safe to do, but there doesn't appear to be a
+         * clean way to find this information out.
+         */
+        return map == mapByName;
+    }
+
+
+    /**
+     * The equivalent of hitting &lt;RET&gt;.  The line is considered
+     * complete and is returned.
+     *
+     * @return The completed line of text.
+     * @throws IOException
+     */
+    public String accept() throws IOException {
+        moveToEnd();
+        println(); // output newline
+        flush();
+        return finishBuffer();
+    }
+
+    private void abort() throws IOException {
+        beep();
+        buf.clear();
+        println();
+        redrawLine();
+    }
+
+    /**
+     * Move the cursor <i>where</i> characters.
+     *
+     * @param num   If less than 0, move abs(<i>where</i>) to the left, otherwise move <i>where</i> to the right.
+     * @return      The number of spaces we moved
+     */
+    public int moveCursor(final int num) throws IOException {
+        int where = num;
+
+        if ((buf.cursor == 0) && (where <= 0)) {
+            return 0;
+        }
+
+        if ((buf.cursor == buf.buffer.length()) && (where >= 0)) {
+            return 0;
+        }
+
+        if ((buf.cursor + where) < 0) {
+            where = -buf.cursor;
+        }
+        else if ((buf.cursor + where) > buf.buffer.length()) {
+            where = buf.buffer.length() - buf.cursor;
+        }
+
+        moveInternal(where);
+
+        return where;
+    }
+
+    /**
+     * Move the cursor <i>where</i> characters, without checking the current buffer.
+     *
+     * @param where the number of characters to move to the right or left.
+     */
+    private void moveInternal(final int where) throws IOException {
+        // debug ("move cursor " + where + " ("
+        // + buf.cursor + " => " + (buf.cursor + where) + ")");
+        buf.cursor += where;
+
+        if (terminal.isAnsiSupported()) {
+            if (where < 0) {
+                back(Math.abs(where));
+            } else {
+                int width = getTerminal().getWidth();
+                int cursor = getCursorPosition();
+                int oldLine = (cursor - where) / width;
+                int newLine = cursor / width;
+                if (newLine > oldLine) {
+                    printAnsiSequence((newLine - oldLine) + "B");
+                }
+                printAnsiSequence(1 +(cursor % width) + "G");
+            }
+//            flush();
+            return;
+        }
+
+        char c;
+
+        if (where < 0) {
+            int len = 0;
+            for (int i = buf.cursor; i < buf.cursor - where; i++) {
+                if (buf.buffer.charAt(i) == '\t') {
+                    len += TAB_WIDTH;
+                }
+                else {
+                    len++;
+                }
+            }
+
+            char chars[] = new char[len];
+            Arrays.fill(chars, BACKSPACE);
+            out.write(chars);
+
+            return;
+        }
+        else if (buf.cursor == 0) {
+            return;
+        }
+        else if (mask != null) {
+            c = mask;
+        }
+        else {
+            print(buf.buffer.substring(buf.cursor - where, buf.cursor).toCharArray());
+            return;
+        }
+
+        // null character mask: don't output anything
+        if (mask == NULL_MASK) {
+            return;
+        }
+
+        print(c, Math.abs(where));
+    }
+
+    // FIXME: replace() is not used
+
+    public final boolean replace(final int num, final String replacement) {
+        buf.buffer.replace(buf.cursor - num, buf.cursor, replacement);
+        try {
+            moveCursor(-num);
+            drawBuffer(Math.max(0, num - replacement.length()));
+            moveCursor(replacement.length());
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Read a character from the console.
+     *
+     * @return the character, or -1 if an EOF is received.
+     */
+    public final int readCharacter() throws IOException {
+        int c = reader.read();
+        if (c >= 0) {
+            Log.trace("Keystroke: ", c);
+            // clear any echo characters
+            if (terminal.isSupported()) {
+                clearEcho(c);
+            }
+        }
+        return c;
+    }
+
+    /**
+     * Clear the echoed characters for the specified character code.
+     */
+    private int clearEcho(final int c) throws IOException {
+        // if the terminal is not echoing, then ignore
+        if (!terminal.isEchoEnabled()) {
+            return 0;
+        }
+
+        // otherwise, clear
+        int num = countEchoCharacters(c);
+        back(num);
+        drawBuffer(num);
+
+        return num;
+    }
+
+    private int countEchoCharacters(final int c) {
+        // tabs as special: we need to determine the number of spaces
+        // to cancel based on what out current cursor position is
+        if (c == 9) {
+            int tabStop = 8; // will this ever be different?
+            int position = getCursorPosition();
+
+            return tabStop - (position % tabStop);
+        }
+
+        return getPrintableCharacters(c).length();
+    }
+
+    /**
+     * Return the number of characters that will be printed when the specified
+     * character is echoed to the screen
+     *
+     * Adapted from cat by Torbjorn Granlund, as repeated in stty by David MacKenzie.
+     */
+    private StringBuilder getPrintableCharacters(final int ch) {
+        StringBuilder sbuff = new StringBuilder();
+
+        if (ch >= 32) {
+            if (ch < 127) {
+                sbuff.append(ch);
+            }
+            else if (ch == 127) {
+                sbuff.append('^');
+                sbuff.append('?');
+            }
+            else {
+                sbuff.append('M');
+                sbuff.append('-');
+
+                if (ch >= (128 + 32)) {
+                    if (ch < (128 + 127)) {
+                        sbuff.append((char) (ch - 128));
+                    }
+                    else {
+                        sbuff.append('^');
+                        sbuff.append('?');
+                    }
+                }
+                else {
+                    sbuff.append('^');
+                    sbuff.append((char) (ch - 128 + 64));
+                }
+            }
+        }
+        else {
+            sbuff.append('^');
+            sbuff.append((char) (ch + 64));
+        }
+
+        return sbuff;
+    }
+
+    public final int readCharacter(final char... allowed) throws IOException {
+        // if we restrict to a limited set and the current character is not in the set, then try again.
+        char c;
+
+        Arrays.sort(allowed); // always need to sort before binarySearch
+
+        while (Arrays.binarySearch(allowed, c = (char) readCharacter()) < 0) {
+            // nothing
+        }
+
+        return c;
+    }
+
+    //
+    // Key Bindings
+    //
+
+    public static final String JLINE_COMPLETION_THRESHOLD = "jline.completion.threshold";
+
+    //
+    // Line Reading
+    //
+
+    /**
+     * Read the next line and return the contents of the buffer.
+     */
+    public String readLine() throws IOException {
+        return readLine((String) null);
+    }
+
+    /**
+     * Read the next line with the specified character mask. If null, then
+     * characters will be echoed. If 0, then no characters will be echoed.
+     */
+    public String readLine(final Character mask) throws IOException {
+        return readLine(null, mask);
+    }
+
+    public String readLine(final String prompt) throws IOException {
+        return readLine(prompt, null);
+    }
+
+    /**
+     * Sets the current keymap by name. Supported keymaps are "emacs",
+     * "vi-insert", "vi-move".
+     * @param name The name of the keymap to switch to
+     * @return true if the keymap was set, or false if the keymap is
+     *    not recognized.
+     */
+    public boolean setKeyMap(String name) {
+        return consoleKeys.setKeyMap(name);
+    }
+
+    /**
+     * Returns the name of the current key mapping.
+     * @return the name of the key mapping. This will be the canonical name
+     *   of the current mode of the key map and may not reflect the name that
+     *   was used with {@link #setKeyMap(String)}.
+     */
+    public String getKeyMap() {
+        return consoleKeys.getKeys().getName();
+    }
+
+    /**
+     * Read a line from the <i>in</i> {@link InputStream}, and return the line
+     * (without any trailing newlines).
+     *
+     * @param prompt    The prompt to issue to the console, may be null.
+     * @return          A line that is read from the terminal, or null if there was null input (e.g., <i>CTRL-D</i>
+     *                  was pressed).
+     */
+    public String readLine(String prompt, final Character mask) throws IOException {
+        // prompt may be null
+        // mask may be null
+
+        /*
+         * This is the accumulator for VI-mode repeat count. That is, while in
+         * move mode, if you type 30x it will delete 30 characters. This is
+         * where the "30" is accumulated until the command is struck.
+         */
+        int repeatCount = 0;
+
+        // FIXME: This blows, each call to readLine will reset the console's state which doesn't seem very nice.
+        this.mask = mask;
+        if (prompt != null) {
+            setPrompt(prompt);
+        }
+        else {
+            prompt = getPrompt();
+        }
+
+        try {
+            if (!terminal.isSupported()) {
+                beforeReadLine(prompt, mask);
+            }
+
+            if (prompt != null && prompt.length() > 0) {
+                out.write(prompt);
+                out.flush();
+            }
+
+            // if the terminal is unsupported, just use plain-java reading
+            if (!terminal.isSupported()) {
+                return readLineSimple();
+            }
+
+            if (handleUserInterrupt && (terminal instanceof UnixTerminal)) {
+                ((UnixTerminal) terminal).disableInterruptCharacter();
+            }
+
+            String originalPrompt = this.prompt;
+
+            state = State.NORMAL;
+
+            boolean success = true;
+
+            StringBuilder sb = new StringBuilder();
+            Stack<Character> pushBackChar = new Stack<Character>();
+            while (true) {
+                int c = pushBackChar.isEmpty() ? readCharacter() : pushBackChar.pop ();
+                if (c == -1) {
+                    return null;
+                }
+                sb.appendCodePoint(c);
+
+                if (recording) {
+                    macro += new String(new int[]{c}, 0, 1);
+                }
+
+                Object o = getKeys().getBound( sb );
+                /*
+                 * The kill ring keeps record of whether or not the
+                 * previous command was a yank or a kill. We reset
+                 * that state here if needed.
+                 */
+                if (!recording && !(o instanceof KeyMap)) {
+                    if (o != Operation.YANK_POP && o != Operation.YANK) {
+                        killRing.resetLastYank();
+                    }
+                    if (o != Operation.KILL_LINE && o != Operation.KILL_WHOLE_LINE
+                        && o != Operation.BACKWARD_KILL_WORD && o != Operation.KILL_WORD
+                        && o != Operation.UNIX_LINE_DISCARD && o != Operation.UNIX_WORD_RUBOUT) {
+                        killRing.resetLastKill();
+                    }
+                }
+
+                if (o == Operation.DO_LOWERCASE_VERSION) {
+                    sb.setLength( sb.length() - 1);
+                    sb.append( Character.toLowerCase( (char) c ));
+                    o = getKeys().getBound( sb );
+                }
+
+                /*
+                 * A KeyMap indicates that the key that was struck has a
+                 * number of keys that can follow it as indicated in the
+                 * map. This is used primarily for Emacs style ESC-META-x
+                 * lookups. Since more keys must follow, go back to waiting
+                 * for the next key.
+                 */
+                if ( o instanceof KeyMap ) {
+                    /*
+                     * The ESC key (#27) is special in that it is ambiguous until
+                     * you know what is coming next.  The ESC could be a literal
+                     * escape, like the user entering vi-move mode, or it could
+                     * be part of a terminal control sequence.  The following
+                     * logic attempts to disambiguate things in the same
+                     * fashion as regular vi or readline.
+                     *
+                     * When ESC is encountered and there is no other pending
+                     * character in the pushback queue, then attempt to peek
+                     * into the input stream (if the feature is enabled) for
+                     * 150ms. If nothing else is coming, then assume it is
+                     * not a terminal control sequence, but a raw escape.
+                     */
+                    if (c == 27
+                            && pushBackChar.isEmpty()
+                            && in.isNonBlockingEnabled()
+                            && in.peek(escapeTimeout) == -2) {
+                        o = ((KeyMap) o).getAnotherKey();
+                        if (o == null || o instanceof KeyMap) {
+                            continue;
+                        }
+                        sb.setLength(0);
+                    }
+                    else {
+                        continue;
+                    }
+                }
+
+                /*
+                 * If we didn't find a binding for the key and there is
+                 * more than one character accumulated then start checking
+                 * the largest span of characters from the beginning to
+                 * see if there is a binding for them.
+                 *
+                 * For example if our buffer has ESC,CTRL-M,C the getBound()
+                 * called previously indicated that there is no binding for
+                 * this sequence, so this then checks ESC,CTRL-M, and failing
+                 * that, just ESC. Each keystroke that is pealed off the end
+                 * during these tests is stuffed onto the pushback buffer so
+                 * they won't be lost.
+                 *
+                 * If there is no binding found, then we go back to waiting for
+                 * input.
+                 */
+                while ( o == null && sb.length() > 0 ) {
+                    c = sb.charAt( sb.length() - 1 );
+                    sb.setLength( sb.length() - 1 );
+                    Object o2 = getKeys().getBound( sb );
+                    if ( o2 instanceof KeyMap ) {
+                        o = ((KeyMap) o2).getAnotherKey();
+                        if ( o == null ) {
+                            continue;
+                        } else {
+                            pushBackChar.push( (char) c );
+                        }
+                    }
+                }
+
+                if ( o == null ) {
+                    continue;
+                }
+                Log.trace("Binding: ", o);
+
+
+                // Handle macros
+                if (o instanceof String) {
+                    String macro = (String) o;
+                    for (int i = 0; i < macro.length(); i++) {
+                        pushBackChar.push(macro.charAt(macro.length() - 1 - i));
+                    }
+                    sb.setLength( 0 );
+                    continue;
+                }
+
+                // Handle custom callbacks
+                //original code:
+//                if (o instanceof ActionListener) {
+//                    ((ActionListener) o).actionPerformed(null);
+//                    sb.setLength( 0 );
+//                    continue;
+//                }
+                //using reflection to avoid dependency on java.desktop:
+                try {
+                    Class<?> actionListener =
+                            Class.forName("java.awt.event.ActionListener", false, ClassLoader.getSystemClassLoader());
+                    Class<?> actionEvent =
+                            Class.forName("java.awt.event.ActionEvent", false, ClassLoader.getSystemClassLoader());
+                    if (actionListener.isAssignableFrom(o.getClass())) {
+                        Method actionPerformed =
+                                actionListener.getMethod("actionPerformed", actionEvent);
+                        try {
+                            actionPerformed.invoke(o, (Object) null);
+                        } catch (InvocationTargetException ex ) {
+                            Log.error("Exception while running registered action", ex);
+                        }
+                        sb.setLength( 0 );
+                        continue;
+                    }
+                } catch (ReflectiveOperationException ex) {
+                    //ignore
+                }
+
+                // Search mode.
+                //
+                // Note that we have to do this first, because if there is a command
+                // not linked to a search command, we leave the search mode and fall
+                // through to the normal state.
+                if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
+                    int cursorDest = -1;
+                    switch ( ((Operation) o )) {
+                        case ABORT:
+                            state = State.NORMAL;
+                            buf.clear();
+                            buf.buffer.append(searchTerm);
+                            break;
+
+                        case REVERSE_SEARCH_HISTORY:
+                            state = State.SEARCH;
+                            if (searchTerm.length() == 0) {
+                                searchTerm.append(previousSearchTerm);
+                            }
+
+                            if (searchIndex > 0) {
+                                searchIndex = searchBackwards(searchTerm.toString(), searchIndex);
+                            }
+                            break;
+
+                        case FORWARD_SEARCH_HISTORY:
+                            state = State.FORWARD_SEARCH;
+                            if (searchTerm.length() == 0) {
+                                searchTerm.append(previousSearchTerm);
+                            }
+
+                            if (searchIndex > -1 && searchIndex < history.size() - 1) {
+                                searchIndex = searchForwards(searchTerm.toString(), searchIndex);
+                            }
+                            break;
+
+                        case BACKWARD_DELETE_CHAR:
+                            if (searchTerm.length() > 0) {
+                                searchTerm.deleteCharAt(searchTerm.length() - 1);
+                                if (state == State.SEARCH) {
+                                    searchIndex = searchBackwards(searchTerm.toString());
+                                } else {
+                                    searchIndex = searchForwards(searchTerm.toString());
+                                }
+                            }
+                            break;
+
+                        case SELF_INSERT:
+                            searchTerm.appendCodePoint(c);
+                            if (state == State.SEARCH) {
+                                searchIndex = searchBackwards(searchTerm.toString());
+                            } else {
+                                searchIndex = searchForwards(searchTerm.toString());
+                            }
+                            break;
+
+                        default:
+                            // Set buffer and cursor position to the found string.
+                            if (searchIndex != -1) {
+                                history.moveTo(searchIndex);
+                                // set cursor position to the found string
+                                cursorDest = history.current().toString().indexOf(searchTerm.toString());
+                            }
+                            state = State.NORMAL;
+                            break;
+                    }
+
+                    // if we're still in search mode, print the search status
+                    if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
+                        if (searchTerm.length() == 0) {
+                            if (state == State.SEARCH) {
+                                printSearchStatus("", "");
+                            } else {
+                                printForwardSearchStatus("", "");
+                            }
+                            searchIndex = -1;
+                        } else {
+                            if (searchIndex == -1) {
+                                beep();
+                                printSearchStatus(searchTerm.toString(), "");
+                            } else if (state == State.SEARCH) {
+                                printSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
+                            } else {
+                                printForwardSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
+                            }
+                        }
+                    }
+                    // otherwise, restore the line
+                    else {
+                        restoreLine(originalPrompt, cursorDest);
+                    }
+                }
+                if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
+                    /*
+                     * If this is still false at the end of the switch, then
+                     * we reset our repeatCount to 0.
+                     */
+                    boolean isArgDigit = false;
+
+                    /*
+                     * Every command that can be repeated a specified number
+                     * of times, needs to know how many times to repeat, so
+                     * we figure that out here.
+                     */
+                    int count = (repeatCount == 0) ? 1 : repeatCount;
+
+                    /*
+                     * Default success to true. You only need to explicitly
+                     * set it if something goes wrong.
+                     */
+                    success = true;
+
+                    if (o instanceof Operation) {
+                        Operation op = (Operation)o;
+                        /*
+                         * Current location of the cursor (prior to the operation).
+                         * These are used by vi *-to operation (e.g. delete-to)
+                         * so we know where we came from.
+                         */
+                        int     cursorStart = buf.cursor;
+                        State   origState   = state;
+
+                        /*
+                         * If we are on a "vi" movement based operation, then we
+                         * need to restrict the sets of inputs pretty heavily.
+                         */
+                        if (state == State.VI_CHANGE_TO
+                            || state == State.VI_YANK_TO
+                            || state == State.VI_DELETE_TO) {
+
+                            op = viDeleteChangeYankToRemap(op);
+                        }
+
+                        switch ( op ) {
+                            case COMPLETE: // tab
+                                // There is an annoyance with tab completion in that
+                                // sometimes the user is actually pasting input in that
+                                // has physical tabs in it.  This attempts to look at how
+                                // quickly a character follows the tab, if the character
+                                // follows *immediately*, we assume it is a tab literal.
+                                boolean isTabLiteral = false;
+                                if (copyPasteDetection
+                                    && c == 9
+                                    && (!pushBackChar.isEmpty()
+                                        || (in.isNonBlockingEnabled() && in.peek(escapeTimeout) != -2))) {
+                                    isTabLiteral = true;
+                                }
+
+                                if (! isTabLiteral) {
+                                    success = complete();
+                                }
+                                else {
+                                    putString(sb);
+                                }
+                                break;
+
+                            case POSSIBLE_COMPLETIONS:
+                                printCompletionCandidates();
+                                break;
+
+                            case BEGINNING_OF_LINE:
+                                success = setCursorPosition(0);
+                                break;
+
+                            case YANK:
+                                success = yank();
+                                break;
+
+                            case YANK_POP:
+                                success = yankPop();
+                                break;
+
+                            case KILL_LINE: // CTRL-K
+                                success = killLine();
+                                break;
+
+                            case KILL_WHOLE_LINE:
+                                success = setCursorPosition(0) && killLine();
+                                break;
+
+                            case CLEAR_SCREEN: // CTRL-L
+                                success = clearScreen();
+                                redrawLine();
+                                break;
+
+                            case OVERWRITE_MODE:
+                                buf.setOverTyping(!buf.isOverTyping());
+                                break;
+
+                            case SELF_INSERT:
+                                putString(sb);
+                                break;
+
+                            case ACCEPT_LINE:
+                                return accept();
+
+                            case ABORT:
+                                if (searchTerm == null) {
+                                    abort();
+                                }
+                                break;
+
+                            case INTERRUPT:
+                                if (handleUserInterrupt) {
+                                    println();
+                                    flush();
+                                    String partialLine = buf.buffer.toString();
+                                    buf.clear();
+                                    history.moveToEnd();
+                                    throw new UserInterruptException(partialLine);
+                                }
+                                break;
+
+                            /*
+                             * VI_MOVE_ACCEPT_LINE is the result of an ENTER
+                             * while in move mode. This is the same as a normal
+                             * ACCEPT_LINE, except that we need to enter
+                             * insert mode as well.
+                             */
+                            case VI_MOVE_ACCEPT_LINE:
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                return accept();
+
+                            case BACKWARD_WORD:
+                                success = previousWord();
+                                break;
+
+                            case FORWARD_WORD:
+                                success = nextWord();
+                                break;
+
+                            case PREVIOUS_HISTORY:
+                                success = moveHistory(false);
+                                break;
+
+                            /*
+                             * According to bash/readline move through history
+                             * in "vi" mode will move the cursor to the
+                             * start of the line. If there is no previous
+                             * history, then the cursor doesn't move.
+                             */
+                            case VI_PREVIOUS_HISTORY:
+                                success = moveHistory(false, count)
+                                    && setCursorPosition(0);
+                                break;
+
+                            case NEXT_HISTORY:
+                                success = moveHistory(true);
+                                break;
+
+                            /*
+                             * According to bash/readline move through history
+                             * in "vi" mode will move the cursor to the
+                             * start of the line. If there is no next history,
+                             * then the cursor doesn't move.
+                             */
+                            case VI_NEXT_HISTORY:
+                                success = moveHistory(true, count)
+                                    && setCursorPosition(0);
+                                break;
+
+                            case BACKWARD_DELETE_CHAR: // backspace
+                                success = backspace();
+                                break;
+
+                            case EXIT_OR_DELETE_CHAR:
+                                if (buf.buffer.length() == 0) {
+                                    return null;
+                                }
+                                success = deleteCurrentCharacter();
+                                break;
+
+                            case DELETE_CHAR: // delete
+                                success = deleteCurrentCharacter();
+                                break;
+
+                            case BACKWARD_CHAR:
+                                success = moveCursor(-(count)) != 0;
+                                break;
+
+                            case FORWARD_CHAR:
+                                success = moveCursor(count) != 0;
+                                break;
+
+                            case UNIX_LINE_DISCARD:
+                                success = resetLine();
+                                break;
+
+                            case UNIX_WORD_RUBOUT:
+                                success = unixWordRubout(count);
+                                break;
+
+                            case BACKWARD_KILL_WORD:
+                                success = deletePreviousWord();
+                                break;
+
+                            case KILL_WORD:
+                                success = deleteNextWord();
+                                break;
+
+                            case BEGINNING_OF_HISTORY:
+                                success = history.moveToFirst();
+                                if (success) {
+                                    setBuffer(history.current());
+                                }
+                                break;
+
+                            case END_OF_HISTORY:
+                                success = history.moveToLast();
+                                if (success) {
+                                    setBuffer(history.current());
+                                }
+                                break;
+
+                            case HISTORY_SEARCH_BACKWARD:
+                                searchTerm = new StringBuffer(buf.upToCursor());
+                                searchIndex = searchBackwards(searchTerm.toString(), history.index(), true);
+
+                                if (searchIndex == -1) {
+                                    beep();
+                                } else {
+                                    // Maintain cursor position while searching.
+                                    success = history.moveTo(searchIndex);
+                                    if (success) {
+                                        setBufferKeepPos(history.current());
+                                    }
+                                }
+                                break;
+
+                            case HISTORY_SEARCH_FORWARD:
+                                searchTerm = new StringBuffer(buf.upToCursor());
+                                int index = history.index() + 1;
+
+                                if (index == history.size()) {
+                                    history.moveToEnd();
+                                    setBufferKeepPos(searchTerm.toString());
+                                } else if (index < history.size()) {
+                                    searchIndex = searchForwards(searchTerm.toString(), index, true);
+                                    if (searchIndex == -1) {
+                                        beep();
+                                    } else {
+                                        // Maintain cursor position while searching.
+                                        success = history.moveTo(searchIndex);
+                                        if (success) {
+                                            setBufferKeepPos(history.current());
+                                        }
+                                    }
+                                }
+                                break;
+
+                            case REVERSE_SEARCH_HISTORY:
+                                if (searchTerm != null) {
+                                    previousSearchTerm = searchTerm.toString();
+                                }
+                                searchTerm = new StringBuffer(buf.buffer);
+                                state = State.SEARCH;
+                                if (searchTerm.length() > 0) {
+                                    searchIndex = searchBackwards(searchTerm.toString());
+                                    if (searchIndex == -1) {
+                                        beep();
+                                    }
+                                    printSearchStatus(searchTerm.toString(),
+                                            searchIndex > -1 ? history.get(searchIndex).toString() : "");
+                                } else {
+                                    searchIndex = -1;
+                                    printSearchStatus("", "");
+                                }
+                                break;
+
+                            case FORWARD_SEARCH_HISTORY:
+                                if (searchTerm != null) {
+                                    previousSearchTerm = searchTerm.toString();
+                                }
+                                searchTerm = new StringBuffer(buf.buffer);
+                                state = State.FORWARD_SEARCH;
+                                if (searchTerm.length() > 0) {
+                                    searchIndex = searchForwards(searchTerm.toString());
+                                    if (searchIndex == -1) {
+                                        beep();
+                                    }
+                                    printForwardSearchStatus(searchTerm.toString(),
+                                            searchIndex > -1 ? history.get(searchIndex).toString() : "");
+                                } else {
+                                    searchIndex = -1;
+                                    printForwardSearchStatus("", "");
+                                }
+                                break;
+
+                            case CAPITALIZE_WORD:
+                                success = capitalizeWord();
+                                break;
+
+                            case UPCASE_WORD:
+                                success = upCaseWord();
+                                break;
+
+                            case DOWNCASE_WORD:
+                                success = downCaseWord();
+                                break;
+
+                            case END_OF_LINE:
+                                success = moveToEnd();
+                                break;
+
+                            case TAB_INSERT:
+                                putString( "\t" );
+                                break;
+
+                            case RE_READ_INIT_FILE:
+                                consoleKeys.loadKeys(appName, inputrcUrl);
+                                break;
+
+                            case START_KBD_MACRO:
+                                recording = true;
+                                break;
+
+                            case END_KBD_MACRO:
+                                recording = false;
+                                macro = macro.substring(0, macro.length() - sb.length());
+                                break;
+
+                            case CALL_LAST_KBD_MACRO:
+                                for (int i = 0; i < macro.length(); i++) {
+                                    pushBackChar.push(macro.charAt(macro.length() - 1 - i));
+                                }
+                                sb.setLength( 0 );
+                                break;
+
+                            case VI_EDITING_MODE:
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case VI_MOVEMENT_MODE:
+                                /*
+                                 * If we are re-entering move mode from an
+                                 * aborted yank-to, delete-to, change-to then
+                                 * don't move the cursor back. The cursor is
+                                 * only move on an expclit entry to movement
+                                 * mode.
+                                 */
+                                if (state == State.NORMAL) {
+                                    moveCursor(-1);
+                                }
+                                consoleKeys.setKeyMap(KeyMap.VI_MOVE);
+                                break;
+
+                            case VI_INSERTION_MODE:
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case VI_APPEND_MODE:
+                                moveCursor(1);
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case VI_APPEND_EOL:
+                                success = moveToEnd();
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            /*
+                             * Handler for CTRL-D. Attempts to follow readline
+                             * behavior. If the line is empty, then it is an EOF
+                             * otherwise it is as if the user hit enter.
+                             */
+                            case VI_EOF_MAYBE:
+                                if (buf.buffer.length() == 0) {
+                                    return null;
+                                }
+                                return accept();
+
+                            case TRANSPOSE_CHARS:
+                                success = transposeChars(count);
+                                break;
+
+                            case INSERT_COMMENT:
+                                return insertComment (false);
+
+                            case INSERT_CLOSE_CURLY:
+                                insertClose("}");
+                                break;
+
+                            case INSERT_CLOSE_PAREN:
+                                insertClose(")");
+                                break;
+
+                            case INSERT_CLOSE_SQUARE:
+                                insertClose("]");
+                                break;
+
+                            case VI_INSERT_COMMENT:
+                                return insertComment (true);
+
+                            case VI_MATCH:
+                                success = viMatch ();
+                                break;
+
+                            case VI_SEARCH:
+                                int lastChar = viSearch(sb.charAt (0));
+                                if (lastChar != -1) {
+                                    pushBackChar.push((char)lastChar);
+                                }
+                                break;
+
+                            case VI_ARG_DIGIT:
+                                repeatCount = (repeatCount * 10) + sb.charAt(0) - '0';
+                                isArgDigit = true;
+                                break;
+
+                            case VI_BEGNNING_OF_LINE_OR_ARG_DIGIT:
+                                if (repeatCount > 0) {
+                                    repeatCount = (repeatCount * 10) + sb.charAt(0) - '0';
+                                    isArgDigit = true;
+                                }
+                                else {
+                                    success = setCursorPosition(0);
+                                }
+                                break;
+
+                            case VI_FIRST_PRINT:
+                                success = setCursorPosition(0) && viNextWord(1);
+                                break;
+
+                            case VI_PREV_WORD:
+                                success = viPreviousWord(count);
+                                break;
+
+                            case VI_NEXT_WORD:
+                                success = viNextWord(count);
+                                break;
+
+                            case VI_END_WORD:
+                                success = viEndWord(count);
+                                break;
+
+                            case VI_INSERT_BEG:
+                                success = setCursorPosition(0);
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case VI_RUBOUT:
+                                success = viRubout(count);
+                                break;
+
+                            case VI_DELETE:
+                                success = viDelete(count);
+                                break;
+
+                            case VI_DELETE_TO:
+                                /*
+                                 * This is a weird special case. In vi
+                                 * "dd" deletes the current line. So if we
+                                 * get a delete-to, followed by a delete-to,
+                                 * we delete the line.
+                                 */
+                                if (state == State.VI_DELETE_TO) {
+                                    success = setCursorPosition(0) && killLine();
+                                    state = origState = State.NORMAL;
+                                }
+                                else {
+                                    state = State.VI_DELETE_TO;
+                                }
+                                break;
+
+                            case VI_YANK_TO:
+                                // Similar to delete-to, a "yy" yanks the whole line.
+                                if (state == State.VI_YANK_TO) {
+                                    yankBuffer = buf.buffer.toString();
+                                    state = origState = State.NORMAL;
+                                }
+                                else {
+                                    state = State.VI_YANK_TO;
+                                }
+                                break;
+
+                            case VI_CHANGE_TO:
+                                if (state == State.VI_CHANGE_TO) {
+                                    success = setCursorPosition(0) && killLine();
+                                    state = origState = State.NORMAL;
+                                    consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                }
+                                else {
+                                    state = State.VI_CHANGE_TO;
+                                }
+                                break;
+
+                            case VI_KILL_WHOLE_LINE:
+                                success = setCursorPosition(0) && killLine();
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case VI_PUT:
+                                success = viPut(count);
+                                break;
+
+                            case VI_CHAR_SEARCH: {
+                                 // ';' and ',' don't need another character. They indicate repeat next or repeat prev.
+                                int searchChar = (c != ';' && c != ',')
+                                    ? (pushBackChar.isEmpty()
+                                        ? readCharacter()
+                                        : pushBackChar.pop ())
+                                    : 0;
+
+                                    success = viCharSearch(count, c, searchChar);
+                                }
+                                break;
+
+                            case VI_CHANGE_CASE:
+                                success = viChangeCase(count);
+                                break;
+
+                            case VI_CHANGE_CHAR:
+                                success = viChangeChar(count,
+                                    pushBackChar.isEmpty()
+                                        ? readCharacter()
+                                        : pushBackChar.pop());
+                                break;
+
+                            case VI_DELETE_TO_EOL:
+                                success = viDeleteTo(buf.cursor, buf.buffer.length(), false);
+                                break;
+
+                            case VI_CHANGE_TO_EOL:
+                                success = viDeleteTo(buf.cursor, buf.buffer.length(), true);
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                                break;
+
+                            case EMACS_EDITING_MODE:
+                                consoleKeys.setKeyMap(KeyMap.EMACS);
+                                break;
+
+                            default:
+                                break;
+                        }
+
+                        /*
+                         * If we were in a yank-to, delete-to, move-to
+                         * when this operation started, then fall back to
+                         */
+                        if (origState != State.NORMAL) {
+                            if (origState == State.VI_DELETE_TO) {
+                                success = viDeleteTo(cursorStart, buf.cursor, false);
+                            }
+                            else if (origState == State.VI_CHANGE_TO) {
+                                success = viDeleteTo(cursorStart, buf.cursor, true);
+                                consoleKeys.setKeyMap(KeyMap.VI_INSERT);
+                            }
+                            else if (origState == State.VI_YANK_TO) {
+                                success = viYankTo(cursorStart, buf.cursor);
+                            }
+                            state = State.NORMAL;
+                        }
+
+                        /*
+                         * Another subtly. The check for the NORMAL state is
+                         * to ensure that we do not clear out the repeat
+                         * count when in delete-to, yank-to, or move-to modes.
+                         */
+                        if (state == State.NORMAL && !isArgDigit) {
+                            /*
+                             * If the operation performed wasn't a vi argument
+                             * digit, then clear out the current repeatCount;
+                             */
+                            repeatCount = 0;
+                        }
+
+                        if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
+                            previousSearchTerm = "";
+                            searchTerm = null;
+                            searchIndex = -1;
+                        }
+                    }
+                }
+                if (!success) {
+                    beep();
+                }
+                sb.setLength( 0 );
+                flush();
+            }
+        }
+        finally {
+            if (!terminal.isSupported()) {
+                afterReadLine();
+            }
+            if (handleUserInterrupt && (terminal instanceof UnixTerminal)) {
+                ((UnixTerminal) terminal).enableInterruptCharacter();
+            }
+        }
+    }
+
+    /**
+     * Read a line for unsupported terminals.
+     */
+    private String readLineSimple() throws IOException {
+        StringBuilder buff = new StringBuilder();
+
+        if (skipLF) {
+            skipLF = false;
+
+            int i = readCharacter();
+
+            if (i == -1 || i == '\r') {
+                return buff.toString();
+            } else if (i == '\n') {
+                // ignore
+            } else {
+                buff.append((char) i);
+            }
+        }
+
+        while (true) {
+            int i = readCharacter();
+
+            if (i == -1 && buff.length() == 0) {
+              return null;
+            }
+
+            if (i == -1 || i == '\n') {
+                return buff.toString();
+            } else if (i == '\r') {
+                skipLF = true;
+                return buff.toString();
+            } else {
+                buff.append((char) i);
+            }
+        }
+    }
+
+    //
+    // Completion
+    //
+
+    private final List<Completer> completers = new LinkedList<Completer>();
+
+    private CompletionHandler completionHandler = new CandidateListCompletionHandler();
+
+    /**
+     * Add the specified {@link jline.console.completer.Completer} to the list of handlers for tab-completion.
+     *
+     * @param completer the {@link jline.console.completer.Completer} to add
+     * @return true if it was successfully added
+     */
+    public boolean addCompleter(final Completer completer) {
+        return completers.add(completer);
+    }
+
+    /**
+     * Remove the specified {@link jline.console.completer.Completer} from the list of handlers for tab-completion.
+     *
+     * @param completer     The {@link Completer} to remove
+     * @return              True if it was successfully removed
+     */
+    public boolean removeCompleter(final Completer completer) {
+        return completers.remove(completer);
+    }
+
+    /**
+     * Returns an unmodifiable list of all the completers.
+     */
+    public Collection<Completer> getCompleters() {
+        return Collections.unmodifiableList(completers);
+    }
+
+    public void setCompletionHandler(final CompletionHandler handler) {
+        this.completionHandler = checkNotNull(handler);
+    }
+
+    public CompletionHandler getCompletionHandler() {
+        return this.completionHandler;
+    }
+
+    /**
+     * Use the completers to modify the buffer with the appropriate completions.
+     *
+     * @return true if successful
+     */
+    protected boolean complete() throws IOException {
+        // debug ("tab for (" + buf + ")");
+        if (completers.size() == 0) {
+            return false;
+        }
+
+        List<CharSequence> candidates = new LinkedList<CharSequence>();
+        String bufstr = buf.buffer.toString();
+        int cursor = buf.cursor;
+
+        int position = -1;
+
+        for (Completer comp : completers) {
+            if ((position = comp.complete(bufstr, cursor, candidates)) != -1) {
+                break;
+            }
+        }
+
+        return candidates.size() != 0 && getCompletionHandler().complete(this, candidates, position);
+    }
+
+    protected void printCompletionCandidates() throws IOException {
+        // debug ("tab for (" + buf + ")");
+        if (completers.size() == 0) {
+            return;
+        }
+
+        List<CharSequence> candidates = new LinkedList<CharSequence>();
+        String bufstr = buf.buffer.toString();
+        int cursor = buf.cursor;
+
+        for (Completer comp : completers) {
+            if (comp.complete(bufstr, cursor, candidates) != -1) {
+                break;
+            }
+        }
+        CandidateListCompletionHandler.printCandidates(this, candidates);
+        drawLine();
+    }
+
+    /**
+     * The number of tab-completion candidates above which a warning will be
+     * prompted before showing all the candidates.
+     */
+    private int autoprintThreshold = Configuration.getInteger(JLINE_COMPLETION_THRESHOLD, 100); // same default as bash
+
+    /**
+     * @param threshold the number of candidates to print without issuing a warning.
+     */
+    public void setAutoprintThreshold(final int threshold) {
+        this.autoprintThreshold = threshold;
+    }
+
+    /**
+     * @return the number of candidates to print without issuing a warning.
+     */
+    public int getAutoprintThreshold() {
+        return autoprintThreshold;
+    }
+
+    private boolean paginationEnabled;
+
+    /**
+     * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
+     */
+    public void setPaginationEnabled(final boolean enabled) {
+        this.paginationEnabled = enabled;
+    }
+
+    /**
+     * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
+     */
+    public boolean isPaginationEnabled() {
+        return paginationEnabled;
+    }
+
+    //
+    // History
+    //
+
+    private History history = new MemoryHistory();
+
+    public void setHistory(final History history) {
+        this.history = history;
+    }
+
+    public History getHistory() {
+        return history;
+    }
+
+    private boolean historyEnabled = true;
+
+    /**
+     * Whether or not to add new commands to the history buffer.
+     */
+    public void setHistoryEnabled(final boolean enabled) {
+        this.historyEnabled = enabled;
+    }
+
+    /**
+     * Whether or not to add new commands to the history buffer.
+     */
+    public boolean isHistoryEnabled() {
+        return historyEnabled;
+    }
+
+    /**
+     * Used in "vi" mode for argumented history move, to move a specific
+     * number of history entries forward or back.
+     *
+     * @param next If true, move forward
+     * @param count The number of entries to move
+     * @return true if the move was successful
+     * @throws IOException
+     */
+    private boolean moveHistory(final boolean next, int count) throws IOException {
+        boolean ok = true;
+        for (int i = 0; i < count && (ok = moveHistory(next)); i++) {
+            /* empty */
+        }
+        return ok;
+    }
+
+    /**
+     * Move up or down the history tree.
+     */
+    private boolean moveHistory(final boolean next) throws IOException {
+        if (next && !history.next()) {
+            return false;
+        }
+        else if (!next && !history.previous()) {
+            return false;
+        }
+
+        setBuffer(history.current());
+
+        return true;
+    }
+
+    //
+    // Printing
+    //
+
+    public static final String CR = Configuration.getLineSeparator();
+
+    /**
+     * Output the specified character to the output stream without manipulating the current buffer.
+     */
+    private void print(final int c) throws IOException {
+        if (c == '\t') {
+            char chars[] = new char[TAB_WIDTH];
+            Arrays.fill(chars, ' ');
+            out.write(chars);
+            return;
+        }
+
+        out.write(c);
+    }
+
+    /**
+     * Output the specified characters to the output stream without manipulating the current buffer.
+     */
+    private void print(final char... buff) throws IOException {
+        int len = 0;
+        for (char c : buff) {
+            if (c == '\t') {
+                len += TAB_WIDTH;
+            }
+            else {
+                len++;
+            }
+        }
+
+        char chars[];
+        if (len == buff.length) {
+            chars = buff;
+        }
+        else {
+            chars = new char[len];
+            int pos = 0;
+            for (char c : buff) {
+                if (c == '\t') {
+                    Arrays.fill(chars, pos, pos + TAB_WIDTH, ' ');
+                    pos += TAB_WIDTH;
+                }
+                else {
+                    chars[pos] = c;
+                    pos++;
+                }
+            }
+        }
+
+        out.write(chars);
+    }
+
+    private void print(final char c, final int num) throws IOException {
+        if (num == 1) {
+            print(c);
+        }
+        else {
+            char[] chars = new char[num];
+            Arrays.fill(chars, c);
+            print(chars);
+        }
+    }
+
+    /**
+     * Output the specified string to the output stream (but not the buffer).
+     */
+    public final void print(final CharSequence s) throws IOException {
+        print(checkNotNull(s).toString().toCharArray());
+    }
+
+    public final void println(final CharSequence s) throws IOException {
+        print(checkNotNull(s).toString().toCharArray());
+        println();
+    }
+
+    /**
+     * Output a platform-dependant newline.
+     */
+    public final void println() throws IOException {
+        print(CR);
+//        flush();
+    }
+
+    //
+    // Actions
+    //
+
+    /**
+     * Issue a delete.
+     *
+     * @return true if successful
+     */
+    public final boolean delete() throws IOException {
+        if (buf.cursor == buf.buffer.length()) {
+          return false;
+        }
+
+        buf.buffer.delete(buf.cursor, buf.cursor + 1);
+        drawBuffer(1);
+
+        return true;
+    }
+
+    /**
+     * Kill the buffer ahead of the current cursor position.
+     *
+     * @return true if successful
+     */
+    public boolean killLine() throws IOException {
+        int cp = buf.cursor;
+        int len = buf.buffer.length();
+
+        if (cp >= len) {
+            return false;
+        }
+
+        int num = len - cp;
+        clearAhead(num, 0);
+
+        char[] killed = new char[num];
+        buf.buffer.getChars(cp, (cp + num), killed, 0);
+        buf.buffer.delete(cp, (cp + num));
+
+        String copy = new String(killed);
+        killRing.add(copy);
+
+        return true;
+    }
+
+    public boolean yank() throws IOException {
+        String yanked = killRing.yank();
+
+        if (yanked == null) {
+            return false;
+        }
+        putString(yanked);
+        return true;
+    }
+
+    public boolean yankPop() throws IOException {
+        if (!killRing.lastYank()) {
+            return false;
+        }
+        String current = killRing.yank();
+        if (current == null) {
+            // This shouldn't happen.
+            return false;
+        }
+        backspace(current.length());
+        String yanked = killRing.yankPop();
+        if (yanked == null) {
+            // This shouldn't happen.
+            return false;
+        }
+
+        putString(yanked);
+        return true;
+    }
+
+    /**
+     * Clear the screen by issuing the ANSI "clear screen" code.
+     */
+    public boolean clearScreen() throws IOException {
+        if (!terminal.isAnsiSupported()) {
+            return false;
+        }
+
+        // send the ANSI code to clear the screen
+        printAnsiSequence("2J");
+
+        // then send the ANSI code to go to position 1,1
+        printAnsiSequence("1;1H");
+
+        return true;
+    }
+
+    /**
+     * Issue an audible keyboard bell.
+     */
+    public void beep() throws IOException {
+        if (bellEnabled) {
+            print(KEYBOARD_BELL);
+            // need to flush so the console actually beeps
+            flush();
+        }
+    }
+
+    //disabled to avoid dependency on java.desktop:
+//    /**
+//     * Paste the contents of the clipboard into the console buffer
+//     *
+//     * @return true if clipboard contents pasted
+//     */
+//    public boolean paste() throws IOException {
+//        Clipboard clipboard;
+//        try { // May throw ugly exception on system without X
+//            clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+//        }
+//        catch (Exception e) {
+//            return false;
+//        }
+//
+//        if (clipboard == null) {
+//            return false;
+//        }
+//
+//        Transferable transferable = clipboard.getContents(null);
+//
+//        if (transferable == null) {
+//            return false;
+//        }
+//
+//        try {
+//            @SuppressWarnings("deprecation")
+//            Object content = transferable.getTransferData(DataFlavor.plainTextFlavor);
+//
+//            // This fix was suggested in bug #1060649 at
+//            // http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056
+//            // to get around the deprecated DataFlavor.plainTextFlavor, but it
+//            // raises a UnsupportedFlavorException on Mac OS X
+//
+//            if (content == null) {
+//                try {
+//                    content = new DataFlavor().getReaderForText(transferable);
+//                }
+//                catch (Exception e) {
+//                    // ignore
+//                }
+//            }
+//
+//            if (content == null) {
+//                return false;
+//            }
+//
+//            String value;
+//
+//            if (content instanceof Reader) {
+//                // TODO: we might want instead connect to the input stream
+//                // so we can interpret individual lines
+//                value = "";
+//                String line;
+//
+//                BufferedReader read = new BufferedReader((Reader) content);
+//                while ((line = read.readLine()) != null) {
+//                    if (value.length() > 0) {
+//                        value += "\n";
+//                    }
+//
+//                    value += line;
+//                }
+//            }
+//            else {
+//                value = content.toString();
+//            }
+//
+//            if (value == null) {
+//                return true;
+//            }
+//
+//            putString(value);
+//
+//            return true;
+//        }
+//        catch (UnsupportedFlavorException e) {
+//            Log.error("Paste failed: ", e);
+//
+//            return false;
+//        }
+//    }
+
+    //disabled to avoid dependency on java.desktop:
+//    //
+//    // Triggered Actions
+//    //
+//
+//    private final Map<Character, ActionListener> triggeredActions = new HashMap<Character, ActionListener>();
+//
+//    /**
+//     * Adding a triggered Action allows to give another curse of action if a character passed the pre-processing.
+//     * <p/>
+//     * Say you want to close the application if the user enter q.
+//     * addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick.
+//     */
+//    public void addTriggeredAction(final char c, final ActionListener listener) {
+//        triggeredActions.put(c, listener);
+//    }
+
+    //
+    // Formatted Output
+    //
+
+    /**
+     * Output the specified {@link Collection} in proper columns.
+     */
+    public void printColumns(final Collection<? extends CharSequence> items) throws IOException {
+        if (items == null || items.isEmpty()) {
+            return;
+        }
+
+        int width = getTerminal().getWidth();
+        int height = getTerminal().getHeight();
+
+        int maxWidth = 0;
+        for (CharSequence item : items) {
+            maxWidth = Math.max(maxWidth, item.length());
+        }
+        maxWidth = maxWidth + 3;
+        Log.debug("Max width: ", maxWidth);
+
+        int showLines;
+        if (isPaginationEnabled()) {
+            showLines = height - 1; // page limit
+        }
+        else {
+            showLines = Integer.MAX_VALUE;
+        }
+
+        StringBuilder buff = new StringBuilder();
+        for (CharSequence item : items) {
+            if ((buff.length() + maxWidth) > width) {
+                println(buff);
+                buff.setLength(0);
+
+                if (--showLines == 0) {
+                    // Overflow
+                    print(resources.getString("DISPLAY_MORE"));
+                    flush();
+                    int c = readCharacter();
+                    if (c == '\r' || c == '\n') {
+                        // one step forward
+                        showLines = 1;
+                    }
+                    else if (c != 'q') {
+                        // page forward
+                        showLines = height - 1;
+                    }
+
+                    back(resources.getString("DISPLAY_MORE").length());
+                    if (c == 'q') {
+                        // cancel
+                        break;
+                    }
+                }
+            }
+
+            // NOTE: toString() is important here due to AnsiString being retarded
+            buff.append(item.toString());
+            for (int i = 0; i < (maxWidth - item.length()); i++) {
+                buff.append(' ');
+            }
+        }
+
+        if (buff.length() > 0) {
+            println(buff);
+        }
+    }
+
+    //
+    // Non-supported Terminal Support
+    //
+
+    private Thread maskThread;
+
+    private void beforeReadLine(final String prompt, final Character mask) {
+        if (mask != null && maskThread == null) {
+            final String fullPrompt = "\r" + prompt
+                + "                 "
+                + "                 "
+                + "                 "
+                + "\r" + prompt;
+
+            maskThread = new Thread()
+            {
+                public void run() {
+                    while (!interrupted()) {
+                        try {
+                            Writer out = getOutput();
+                            out.write(fullPrompt);
+                            out.flush();
+                            sleep(3);
+                        }
+                        catch (IOException e) {
+                            return;
+                        }
+                        catch (InterruptedException e) {
+                            return;
+                        }
+                    }
+                }
+            };
+
+            maskThread.setPriority(Thread.MAX_PRIORITY);
+            maskThread.setDaemon(true);
+            maskThread.start();
+        }
+    }
+
+    private void afterReadLine() {
+        if (maskThread != null && maskThread.isAlive()) {
+            maskThread.interrupt();
+        }
+
+        maskThread = null;
+    }
+
+    /**
+     * Erases the current line with the existing prompt, then redraws the line
+     * with the provided prompt and buffer
+     * @param prompt
+     *            the new prompt
+     * @param buffer
+     *            the buffer to be drawn
+     * @param cursorDest
+     *            where you want the cursor set when the line has been drawn.
+     *            -1 for end of line.
+     * */
+    public void resetPromptLine(String prompt, String buffer, int cursorDest) throws IOException {
+        // move cursor to end of line
+        moveToEnd();
+
+        // backspace all text, including prompt
+        buf.buffer.append(this.prompt);
+        int promptLength = 0;
+        if (this.prompt != null) {
+            promptLength = this.prompt.length();
+        }
+
+        buf.cursor += promptLength;
+        setPrompt("");
+        backspaceAll();
+
+        setPrompt(prompt);
+        redrawLine();
+        setBuffer(buffer);
+
+        // move cursor to destination (-1 will move to end of line)
+        if (cursorDest < 0) cursorDest = buffer.length();
+        setCursorPosition(cursorDest);
+
+        flush();
+    }
+
+    public void printSearchStatus(String searchTerm, String match) throws IOException {
+        printSearchStatus(searchTerm, match, "(reverse-i-search)`");
+    }
+
+    public void printForwardSearchStatus(String searchTerm, String match) throws IOException {
+        printSearchStatus(searchTerm, match, "(i-search)`");
+    }
+
+    private void printSearchStatus(String searchTerm, String match, String searchLabel) throws IOException {
+        String prompt = searchLabel + searchTerm + "': ";
+        int cursorDest = match.indexOf(searchTerm);
+        resetPromptLine(prompt, match, cursorDest);
+    }
+
+    public void restoreLine(String originalPrompt, int cursorDest) throws IOException {
+        // TODO move cursor to matched string
+        String prompt = lastLine(originalPrompt);
+        String buffer = buf.buffer.toString();
+        resetPromptLine(prompt, buffer, cursorDest);
+    }
+
+    //
+    // History search
+    //
+    /**
+     * Search backward in history from a given position.
+     *
+     * @param searchTerm substring to search for.
+     * @param startIndex the index from which on to search
+     * @return index where this substring has been found, or -1 else.
+     */
+    public int searchBackwards(String searchTerm, int startIndex) {
+        return searchBackwards(searchTerm, startIndex, false);
+    }
+
+    /**
+     * Search backwards in history from the current position.
+     *
+     * @param searchTerm substring to search for.
+     * @return index where the substring has been found, or -1 else.
+     */
+    public int searchBackwards(String searchTerm) {
+        return searchBackwards(searchTerm, history.index());
+    }
+
+
+    public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) {
+        ListIterator<History.Entry> it = history.entries(startIndex);
+        while (it.hasPrevious()) {
+            History.Entry e = it.previous();
+            if (startsWith) {
+                if (e.value().toString().startsWith(searchTerm)) {
+                    return e.index();
+                }
+            } else {
+                if (e.value().toString().contains(searchTerm)) {
+                    return e.index();
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Search forward in history from a given position.
+     *
+     * @param searchTerm substring to search for.
+     * @param startIndex the index from which on to search
+     * @return index where this substring has been found, or -1 else.
+     */
+    public int searchForwards(String searchTerm, int startIndex) {
+        return searchForwards(searchTerm, startIndex, false);
+    }
+    /**
+     * Search forwards in history from the current position.
+     *
+     * @param searchTerm substring to search for.
+     * @return index where the substring has been found, or -1 else.
+     */
+    public int searchForwards(String searchTerm) {
+        return searchForwards(searchTerm, history.index());
+    }
+
+    public int searchForwards(String searchTerm, int startIndex, boolean startsWith) {
+        if (startIndex >= history.size()) {
+            startIndex = history.size() - 1;
+        }
+
+        ListIterator<History.Entry> it = history.entries(startIndex);
+
+        if (searchIndex != -1 && it.hasNext()) {
+            it.next();
+        }
+
+        while (it.hasNext()) {
+            History.Entry e = it.next();
+            if (startsWith) {
+                if (e.value().toString().startsWith(searchTerm)) {
+                    return e.index();
+                }
+            } else {
+                if (e.value().toString().contains(searchTerm)) {
+                    return e.index();
+                }
+            }
+        }
+        return -1;
+    }
+
+    //
+    // Helpers
+    //
+
+    /**
+     * Checks to see if the specified character is a delimiter. We consider a
+     * character a delimiter if it is anything but a letter or digit.
+     *
+     * @param c     The character to test
+     * @return      True if it is a delimiter
+     */
+    private boolean isDelimiter(final char c) {
+        return !Character.isLetterOrDigit(c);
+    }
+
+    /**
+     * Checks to see if a character is a whitespace character. Currently
+     * this delegates to {@link Character#isWhitespace(char)}, however
+     * eventually it should be hooked up so that the definition of whitespace
+     * can be configured, as readline does.
+     *
+     * @param c The character to check
+     * @return true if the character is a whitespace
+     */
+    private boolean isWhitespace(final char c) {
+        return Character.isWhitespace (c);
+    }
+
+    private void printAnsiSequence(String sequence) throws IOException {
+        print(27);
+        print('[');
+        print(sequence);
+        flush(); // helps with step debugging
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * A holder for a {@link StringBuilder} that also contains the current cursor position.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class CursorBuffer
+{
+    private boolean overTyping = false;
+
+    public int cursor = 0;
+
+    public final StringBuilder buffer = new StringBuilder();
+
+    public CursorBuffer copy () {
+        CursorBuffer that = new CursorBuffer();
+        that.overTyping = this.overTyping;
+        that.cursor = this.cursor;
+        that.buffer.append (this.toString());
+
+        return that;
+    }
+
+    public boolean isOverTyping() {
+        return overTyping;
+    }
+
+    public void setOverTyping(final boolean b) {
+        overTyping = b;
+    }
+
+    public int length() {
+        return buffer.length();
+    }
+
+    public char nextChar() {
+        if (cursor == buffer.length()) {
+            return 0;
+        } else {
+            return buffer.charAt(cursor);
+        }
+    }
+
+    public char current() {
+        if (cursor <= 0) {
+            return 0;
+        }
+
+        return buffer.charAt(cursor - 1);
+    }
+
+    /**
+     * Write the specific character into the buffer, setting the cursor position
+     * ahead one. The text may overwrite or insert based on the current setting
+     * of {@link #isOverTyping}.
+     *
+     * @param c the character to insert
+     */
+    public void write(final char c) {
+        buffer.insert(cursor++, c);
+        if (isOverTyping() && cursor < buffer.length()) {
+            buffer.deleteCharAt(cursor);
+        }
+    }
+
+    /**
+     * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point.
+     */
+    public void write(final CharSequence str) {
+        checkNotNull(str);
+
+        if (buffer.length() == 0) {
+            buffer.append(str);
+        }
+        else {
+            buffer.insert(cursor, str);
+        }
+
+        cursor += str.length();
+
+        if (isOverTyping() && cursor < buffer.length()) {
+            buffer.delete(cursor, (cursor + str.length()));
+        }
+    }
+
+    public boolean clear() {
+        if (buffer.length() == 0) {
+            return false;
+        }
+
+        buffer.delete(0, buffer.length());
+        cursor = 0;
+        return true;
+    }
+
+    public String upToCursor() {
+        if (cursor <= 0) {
+            return "";
+        }
+
+        return buffer.substring(0, cursor);
+    }
+
+    @Override
+    public String toString() {
+        return buffer.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The KeyMap class contains all bindings from keys to operations.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.6
+ */
+public class KeyMap {
+
+    public static final String VI_MOVE        = "vi-move";
+    public static final String VI_INSERT      = "vi-insert";
+    public static final String EMACS          = "emacs";
+    public static final String EMACS_STANDARD = "emacs-standard";
+    public static final String EMACS_CTLX     = "emacs-ctlx";
+    public static final String EMACS_META     = "emacs-meta";
+
+    private static final int KEYMAP_LENGTH = 256;
+
+    private static final Object NULL_FUNCTION = new Object();
+
+    private Object[] mapping = new Object[KEYMAP_LENGTH];
+    private Object anotherKey = null;
+    private String name;
+    private boolean isViKeyMap;
+
+    public KeyMap(String name, boolean isViKeyMap) {
+        this(name, new Object[KEYMAP_LENGTH], isViKeyMap);
+    }
+
+    protected KeyMap(String name, Object[] mapping, boolean isViKeyMap) {
+        this.mapping = mapping;
+        this.name = name;
+        this.isViKeyMap = isViKeyMap;
+    }
+
+    public boolean isViKeyMap() {
+        return isViKeyMap;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Object getAnotherKey() {
+        return anotherKey;
+    }
+
+    public void from(KeyMap other) {
+        this.mapping = other.mapping;
+        this.anotherKey = other.anotherKey;
+    }
+
+    public Object getBound( CharSequence keySeq ) {
+        if (keySeq != null && keySeq.length() > 0) {
+            KeyMap map = this;
+            for (int i = 0; i < keySeq.length(); i++) {
+                char c = keySeq.charAt(i);
+                if (c > 255) {
+                    return Operation.SELF_INSERT;
+                }
+                if (map.mapping[c] instanceof KeyMap) {
+                    if (i == keySeq.length() - 1) {
+                        return map.mapping[c];
+                    } else {
+                        map = (KeyMap) map.mapping[c];
+                    }
+                } else {
+                    return map.mapping[c];
+                }
+            }
+        }
+        return null;
+    }
+
+    public void bindIfNotBound( CharSequence keySeq, Object function ) {
+
+        bind (this, keySeq, function, true);
+    }
+
+    public void bind( CharSequence keySeq, Object function ) {
+
+        bind (this, keySeq, function, false);
+    }
+
+    private static void bind( KeyMap map, CharSequence keySeq, Object function ) {
+
+        bind (map, keySeq, function, false);
+    }
+
+    private static void bind( KeyMap map, CharSequence keySeq, Object function,
+            boolean onlyIfNotBound ) {
+
+        if (keySeq != null && keySeq.length() > 0) {
+            for (int i = 0; i < keySeq.length(); i++) {
+                char c = keySeq.charAt(i);
+                if (c >= map.mapping.length) {
+                    return;
+                }
+                if (i < keySeq.length() - 1) {
+                    if (!(map.mapping[c] instanceof KeyMap)) {
+                        KeyMap m = new KeyMap("anonymous", false);
+                        if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) {
+                            m.anotherKey = map.mapping[c];
+                        }
+                        map.mapping[c] = m;
+                    }
+                    map = (KeyMap) map.mapping[c];
+                } else {
+                    if (function == null) {
+                        function = NULL_FUNCTION;
+                    }
+                    if (map.mapping[c] instanceof KeyMap) {
+                        map.anotherKey = function;
+                    } else {
+                        Object op = map.mapping[c];
+                        if (onlyIfNotBound == false
+                            || op == null
+                            || op == Operation.DO_LOWERCASE_VERSION
+                            || op == Operation.VI_MOVEMENT_MODE ) {
+
+                        }
+
+                        map.mapping[c] = function;
+                    }
+                }
+            }
+        }
+    }
+
+    public void setBlinkMatchingParen(boolean on) {
+        if (on) {
+            bind( "}", Operation.INSERT_CLOSE_CURLY );
+            bind( ")", Operation.INSERT_CLOSE_PAREN );
+            bind( "]", Operation.INSERT_CLOSE_SQUARE );
+        }
+    }
+
+    private static void bindArrowKeys(KeyMap map) {
+
+        // MS-DOS
+        bind( map, "\033[0A", Operation.PREVIOUS_HISTORY );
+        bind( map, "\033[0B", Operation.BACKWARD_CHAR );
+        bind( map, "\033[0C", Operation.FORWARD_CHAR );
+        bind( map, "\033[0D", Operation.NEXT_HISTORY );
+
+        // Windows
+        bind( map, "\340\000", Operation.KILL_WHOLE_LINE );
+        bind( map, "\340\107", Operation.BEGINNING_OF_LINE );
+        bind( map, "\340\110", Operation.PREVIOUS_HISTORY );
+        bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY );
+        bind( map, "\340\113", Operation.BACKWARD_CHAR );
+        bind( map, "\340\115", Operation.FORWARD_CHAR );
+        bind( map, "\340\117", Operation.END_OF_LINE );
+        bind( map, "\340\120", Operation.NEXT_HISTORY );
+        bind( map, "\340\121", Operation.END_OF_HISTORY );
+        bind( map, "\340\122", Operation.OVERWRITE_MODE );
+        bind( map, "\340\123", Operation.DELETE_CHAR );
+
+        bind( map, "\000\107", Operation.BEGINNING_OF_LINE );
+        bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
+        bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY );
+        bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
+        bind( map, "\000\113", Operation.BACKWARD_CHAR );
+        bind( map, "\000\115", Operation.FORWARD_CHAR );
+        bind( map, "\000\117", Operation.END_OF_LINE );
+        bind( map, "\000\120", Operation.NEXT_HISTORY );
+        bind( map, "\000\121", Operation.END_OF_HISTORY );
+        bind( map, "\000\122", Operation.OVERWRITE_MODE );
+        bind( map, "\000\123", Operation.DELETE_CHAR );
+
+        bind( map, "\033[A", Operation.PREVIOUS_HISTORY );
+        bind( map, "\033[B", Operation.NEXT_HISTORY );
+        bind( map, "\033[C", Operation.FORWARD_CHAR );
+        bind( map, "\033[D", Operation.BACKWARD_CHAR );
+        bind( map, "\033[H", Operation.BEGINNING_OF_LINE );
+        bind( map, "\033[F", Operation.END_OF_LINE );
+
+        bind( map, "\033OA", Operation.PREVIOUS_HISTORY );
+        bind( map, "\033OB", Operation.NEXT_HISTORY );
+        bind( map, "\033OC", Operation.FORWARD_CHAR );
+        bind( map, "\033OD", Operation.BACKWARD_CHAR );
+        bind( map, "\033OH", Operation.BEGINNING_OF_LINE );
+        bind( map, "\033OF", Operation.END_OF_LINE );
+
+        bind( map, "\033[1~", Operation.BEGINNING_OF_LINE);
+        bind( map, "\033[4~", Operation.END_OF_LINE);
+        bind( map, "\033[3~", Operation.DELETE_CHAR);
+
+        // MINGW32
+        bind( map, "\0340H", Operation.PREVIOUS_HISTORY );
+        bind( map, "\0340P", Operation.NEXT_HISTORY );
+        bind( map, "\0340M", Operation.FORWARD_CHAR );
+        bind( map, "\0340K", Operation.BACKWARD_CHAR );
+    }
+
+//    public boolean isConvertMetaCharsToAscii() {
+//        return convertMetaCharsToAscii;
+//    }
+
+//    public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) {
+//        this.convertMetaCharsToAscii = convertMetaCharsToAscii;
+//    }
+
+    public static boolean isMeta( char c ) {
+        return c > 0x7f && c <= 0xff;
+    }
+
+    public static char unMeta( char c ) {
+        return (char) (c & 0x7F);
+    }
+
+    public static char meta( char c ) {
+        return (char) (c | 0x80);
+    }
+
+    public static Map<String, KeyMap> keyMaps() {
+        Map<String, KeyMap> keyMaps = new HashMap<String, KeyMap>();
+
+        KeyMap emacs = emacs();
+        bindArrowKeys(emacs);
+        keyMaps.put(EMACS, emacs);
+        keyMaps.put(EMACS_STANDARD, emacs);
+        keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018"));
+        keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b"));
+
+        KeyMap viMov = viMovement();
+        bindArrowKeys(viMov);
+        keyMaps.put(VI_MOVE, viMov);
+        keyMaps.put("vi-command", viMov);
+
+        KeyMap viIns = viInsertion();
+        bindArrowKeys(viIns);
+        keyMaps.put(VI_INSERT, viIns);
+        keyMaps.put("vi", viIns);
+
+        return keyMaps;
+    }
+
+    public static KeyMap emacs() {
+        Object[] map = new Object[KEYMAP_LENGTH];
+        Object[] ctrl = new Object[] {
+                        // Control keys.
+                        Operation.SET_MARK,                 /* Control-@ */
+                        Operation.BEGINNING_OF_LINE,        /* Control-A */
+                        Operation.BACKWARD_CHAR,            /* Control-B */
+                        Operation.INTERRUPT,                /* Control-C */
+                        Operation.EXIT_OR_DELETE_CHAR,      /* Control-D */
+                        Operation.END_OF_LINE,              /* Control-E */
+                        Operation.FORWARD_CHAR,             /* Control-F */
+                        Operation.ABORT,                    /* Control-G */
+                        Operation.BACKWARD_DELETE_CHAR,     /* Control-H */
+                        Operation.COMPLETE,                 /* Control-I */
+                        Operation.ACCEPT_LINE,              /* Control-J */
+                        Operation.KILL_LINE,                /* Control-K */
+                        Operation.CLEAR_SCREEN,             /* Control-L */
+                        Operation.ACCEPT_LINE,              /* Control-M */
+                        Operation.NEXT_HISTORY,             /* Control-N */
+                        null,                               /* Control-O */
+                        Operation.PREVIOUS_HISTORY,         /* Control-P */
+                        Operation.QUOTED_INSERT,            /* Control-Q */
+                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
+                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
+                        Operation.TRANSPOSE_CHARS,          /* Control-T */
+                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
+                        Operation.QUOTED_INSERT,            /* Control-V */
+                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
+                        emacsCtrlX(),                       /* Control-X */
+                        Operation.YANK,                     /* Control-Y */
+                        null,                               /* Control-Z */
+                        emacsMeta(),                        /* Control-[ */
+                        null,                               /* Control-\ */
+                        Operation.CHARACTER_SEARCH,         /* Control-] */
+                        null,                               /* Control-^ */
+                        Operation.UNDO,                     /* Control-_ */
+                };
+        System.arraycopy( ctrl, 0, map, 0, ctrl.length );
+        for (int i = 32; i < 256; i++) {
+            map[i] = Operation.SELF_INSERT;
+        }
+        map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
+        return new KeyMap(EMACS, map, false);
+    }
+
+    public static final char CTRL_D = (char) 4;
+    public static final char CTRL_G = (char) 7;
+    public static final char CTRL_H = (char) 8;
+    public static final char CTRL_I = (char) 9;
+    public static final char CTRL_J = (char) 10;
+    public static final char CTRL_M = (char) 13;
+    public static final char CTRL_R = (char) 18;
+    public static final char CTRL_S = (char) 19;
+    public static final char CTRL_U = (char) 21;
+    public static final char CTRL_X = (char) 24;
+    public static final char CTRL_Y = (char) 25;
+    public static final char ESCAPE = (char) 27; /* Ctrl-[ */
+    public static final char CTRL_OB = (char) 27; /* Ctrl-[ */
+    public static final char CTRL_CB = (char) 29; /* Ctrl-] */
+
+    public static final int DELETE = (char) 127;
+
+    public static KeyMap emacsCtrlX() {
+        Object[] map = new Object[KEYMAP_LENGTH];
+        map[CTRL_G] = Operation.ABORT;
+        map[CTRL_R] = Operation.RE_READ_INIT_FILE;
+        map[CTRL_U] = Operation.UNDO;
+        map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK;
+        map['('] = Operation.START_KBD_MACRO;
+        map[')'] = Operation.END_KBD_MACRO;
+        for (int i = 'A'; i <= 'Z'; i++) {
+            map[i] = Operation.DO_LOWERCASE_VERSION;
+        }
+        map['e'] = Operation.CALL_LAST_KBD_MACRO;
+        map[DELETE] = Operation.KILL_LINE;
+        return new KeyMap(EMACS_CTLX, map, false);
+    }
+
+    public static KeyMap emacsMeta() {
+        Object[] map = new Object[KEYMAP_LENGTH];
+        map[CTRL_G] = Operation.ABORT;
+        map[CTRL_H] = Operation.BACKWARD_KILL_WORD;
+        map[CTRL_I] = Operation.TAB_INSERT;
+        map[CTRL_J] = Operation.VI_EDITING_MODE;
+        map[CTRL_M] = Operation.VI_EDITING_MODE;
+        map[CTRL_R] = Operation.REVERT_LINE;
+        map[CTRL_Y] = Operation.YANK_NTH_ARG;
+        map[CTRL_OB] = Operation.COMPLETE;
+        map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD;
+        map[' '] = Operation.SET_MARK;
+        map['#'] = Operation.INSERT_COMMENT;
+        map['&'] = Operation.TILDE_EXPAND;
+        map['*'] = Operation.INSERT_COMPLETIONS;
+        map['-'] = Operation.DIGIT_ARGUMENT;
+        map['.'] = Operation.YANK_LAST_ARG;
+        map['<'] = Operation.BEGINNING_OF_HISTORY;
+        map['='] = Operation.POSSIBLE_COMPLETIONS;
+        map['>'] = Operation.END_OF_HISTORY;
+        map['?'] = Operation.POSSIBLE_COMPLETIONS;
+        for (int i = 'A'; i <= 'Z'; i++) {
+            map[i] = Operation.DO_LOWERCASE_VERSION;
+        }
+        map['\\'] = Operation.DELETE_HORIZONTAL_SPACE;
+        map['_'] = Operation.YANK_LAST_ARG;
+        map['b'] = Operation.BACKWARD_WORD;
+        map['c'] = Operation.CAPITALIZE_WORD;
+        map['d'] = Operation.KILL_WORD;
+        map['f'] = Operation.FORWARD_WORD;
+        map['l'] = Operation.DOWNCASE_WORD;
+        map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY;
+        map['r'] = Operation.REVERT_LINE;
+        map['t'] = Operation.TRANSPOSE_WORDS;
+        map['u'] = Operation.UPCASE_WORD;
+        map['y'] = Operation.YANK_POP;
+        map['~'] = Operation.TILDE_EXPAND;
+        map[DELETE] = Operation.BACKWARD_KILL_WORD;
+        return new KeyMap(EMACS_META, map, false);
+    }
+
+    public static KeyMap viInsertion() {
+        Object[] map = new Object[KEYMAP_LENGTH];
+        Object[] ctrl = new Object[] {
+                        // Control keys.
+                        null,                               /* Control-@ */
+                        Operation.SELF_INSERT,              /* Control-A */
+                        Operation.SELF_INSERT,              /* Control-B */
+                        Operation.SELF_INSERT,              /* Control-C */
+                        Operation.VI_EOF_MAYBE,             /* Control-D */
+                        Operation.SELF_INSERT,              /* Control-E */
+                        Operation.SELF_INSERT,              /* Control-F */
+                        Operation.SELF_INSERT,              /* Control-G */
+                        Operation.BACKWARD_DELETE_CHAR,     /* Control-H */
+                        Operation.COMPLETE,                 /* Control-I */
+                        Operation.ACCEPT_LINE,              /* Control-J */
+                        Operation.SELF_INSERT,              /* Control-K */
+                        Operation.SELF_INSERT,              /* Control-L */
+                        Operation.ACCEPT_LINE,              /* Control-M */
+                        Operation.MENU_COMPLETE,            /* Control-N */
+                        Operation.SELF_INSERT,              /* Control-O */
+                        Operation.MENU_COMPLETE_BACKWARD,   /* Control-P */
+                        Operation.SELF_INSERT,              /* Control-Q */
+                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
+                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
+                        Operation.TRANSPOSE_CHARS,          /* Control-T */
+                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
+                        Operation.QUOTED_INSERT,            /* Control-V */
+                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
+                        Operation.SELF_INSERT,              /* Control-X */
+                        Operation.YANK,                     /* Control-Y */
+                        Operation.SELF_INSERT,              /* Control-Z */
+                        Operation.VI_MOVEMENT_MODE,         /* Control-[ */
+                        Operation.SELF_INSERT,              /* Control-\ */
+                        Operation.SELF_INSERT,              /* Control-] */
+                        Operation.SELF_INSERT,              /* Control-^ */
+                        Operation.UNDO,                     /* Control-_ */
+                };
+        System.arraycopy( ctrl, 0, map, 0, ctrl.length );
+        for (int i = 32; i < 256; i++) {
+            map[i] = Operation.SELF_INSERT;
+        }
+        map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
+        return new KeyMap(VI_INSERT, map, false);
+    }
+
+    public static KeyMap viMovement() {
+        Object[] map = new Object[KEYMAP_LENGTH];
+        Object[] low = new Object[] {
+                        // Control keys.
+                        null,                               /* Control-@ */
+                        null,                               /* Control-A */
+                        null,                               /* Control-B */
+                        Operation.INTERRUPT,                /* Control-C */
+                        /*
+                         * ^D is supposed to move down half a screen. In bash
+                         * appears to be ignored.
+                         */
+                        Operation.VI_EOF_MAYBE,             /* Control-D */
+                        Operation.EMACS_EDITING_MODE,       /* Control-E */
+                        null,                               /* Control-F */
+                        Operation.ABORT,                    /* Control-G */
+                        Operation.BACKWARD_CHAR,            /* Control-H */
+                        null,                               /* Control-I */
+                        Operation.VI_MOVE_ACCEPT_LINE,      /* Control-J */
+                        Operation.KILL_LINE,                /* Control-K */
+                        Operation.CLEAR_SCREEN,             /* Control-L */
+                        Operation.VI_MOVE_ACCEPT_LINE,      /* Control-M */
+                        Operation.VI_NEXT_HISTORY,          /* Control-N */
+                        null,                               /* Control-O */
+                        Operation.VI_PREVIOUS_HISTORY,      /* Control-P */
+                        /*
+                         * My testing with readline is the ^Q is ignored.
+                         * Maybe this should be null?
+                         */
+                        Operation.QUOTED_INSERT,            /* Control-Q */
+
+                        /*
+                         * TODO - Very broken.  While in forward/reverse
+                         * history search the VI keyset should go out the
+                         * window and we need to enter a very simple keymap.
+                         */
+                        Operation.REVERSE_SEARCH_HISTORY,   /* Control-R */
+                        /* TODO */
+                        Operation.FORWARD_SEARCH_HISTORY,   /* Control-S */
+                        Operation.TRANSPOSE_CHARS,          /* Control-T */
+                        Operation.UNIX_LINE_DISCARD,        /* Control-U */
+                        /* TODO */
+                        Operation.QUOTED_INSERT,            /* Control-V */
+                        Operation.UNIX_WORD_RUBOUT,         /* Control-W */
+                        null,                               /* Control-X */
+                        /* TODO */
+                        Operation.YANK,                     /* Control-Y */
+                        null,                               /* Control-Z */
+                        emacsMeta(),                        /* Control-[ */
+                        null,                               /* Control-\ */
+                        /* TODO */
+                        Operation.CHARACTER_SEARCH,         /* Control-] */
+                        null,                               /* Control-^ */
+                        /* TODO */
+                        Operation.UNDO,                     /* Control-_ */
+                        Operation.FORWARD_CHAR,             /* SPACE */
+                        null,                               /* ! */
+                        null,                               /* " */
+                        Operation.VI_INSERT_COMMENT,        /* # */
+                        Operation.END_OF_LINE,              /* $ */
+                        Operation.VI_MATCH,                 /* % */
+                        Operation.VI_TILDE_EXPAND,          /* & */
+                        null,                               /* ' */
+                        null,                               /* ( */
+                        null,                               /* ) */
+                        /* TODO */
+                        Operation.VI_COMPLETE,              /* * */
+                        Operation.VI_NEXT_HISTORY,          /* + */
+                        Operation.VI_CHAR_SEARCH,           /* , */
+                        Operation.VI_PREVIOUS_HISTORY,      /* - */
+                        /* TODO */
+                        Operation.VI_REDO,                  /* . */
+                        Operation.VI_SEARCH,                /* / */
+                        Operation.VI_BEGNNING_OF_LINE_OR_ARG_DIGIT, /* 0 */
+                        Operation.VI_ARG_DIGIT,             /* 1 */
+                        Operation.VI_ARG_DIGIT,             /* 2 */
+                        Operation.VI_ARG_DIGIT,             /* 3 */
+                        Operation.VI_ARG_DIGIT,             /* 4 */
+                        Operation.VI_ARG_DIGIT,             /* 5 */
+                        Operation.VI_ARG_DIGIT,             /* 6 */
+                        Operation.VI_ARG_DIGIT,             /* 7 */
+                        Operation.VI_ARG_DIGIT,             /* 8 */
+                        Operation.VI_ARG_DIGIT,             /* 9 */
+                        null,                               /* : */
+                        Operation.VI_CHAR_SEARCH,           /* ; */
+                        null,                               /* < */
+                        Operation.VI_COMPLETE,              /* = */
+                        null,                               /* > */
+                        Operation.VI_SEARCH,                /* ? */
+                        null,                               /* @ */
+                        Operation.VI_APPEND_EOL,            /* A */
+                        Operation.VI_PREV_WORD,             /* B */
+                        Operation.VI_CHANGE_TO_EOL,         /* C */
+                        Operation.VI_DELETE_TO_EOL,         /* D */
+                        Operation.VI_END_WORD,              /* E */
+                        Operation.VI_CHAR_SEARCH,           /* F */
+                        /* I need to read up on what this does */
+                        Operation.VI_FETCH_HISTORY,         /* G */
+                        null,                               /* H */
+                        Operation.VI_INSERT_BEG,            /* I */
+                        null,                               /* J */
+                        null,                               /* K */
+                        null,                               /* L */
+                        null,                               /* M */
+                        Operation.VI_SEARCH_AGAIN,          /* N */
+                        null,                               /* O */
+                        Operation.VI_PUT,                   /* P */
+                        null,                               /* Q */
+                        /* TODO */
+                        Operation.VI_REPLACE,               /* R */
+                        Operation.VI_KILL_WHOLE_LINE,       /* S */
+                        Operation.VI_CHAR_SEARCH,           /* T */
+                        /* TODO */
+                        Operation.REVERT_LINE,              /* U */
+                        null,                               /* V */
+                        Operation.VI_NEXT_WORD,             /* W */
+                        Operation.VI_RUBOUT,                /* X */
+                        Operation.VI_YANK_TO,               /* Y */
+                        null,                               /* Z */
+                        null,                               /* [ */
+                        Operation.VI_COMPLETE,              /* \ */
+                        null,                               /* ] */
+                        Operation.VI_FIRST_PRINT,           /* ^ */
+                        Operation.VI_YANK_ARG,              /* _ */
+                        Operation.VI_GOTO_MARK,             /* ` */
+                        Operation.VI_APPEND_MODE,           /* a */
+                        Operation.VI_PREV_WORD,             /* b */
+                        Operation.VI_CHANGE_TO,             /* c */
+                        Operation.VI_DELETE_TO,             /* d */
+                        Operation.VI_END_WORD,              /* e */
+                        Operation.VI_CHAR_SEARCH,           /* f */
+                        null,                               /* g */
+                        Operation.BACKWARD_CHAR,            /* h */
+                        Operation.VI_INSERTION_MODE,        /* i */
+                        Operation.NEXT_HISTORY,             /* j */
+                        Operation.PREVIOUS_HISTORY,         /* k */
+                        Operation.FORWARD_CHAR,             /* l */
+                        Operation.VI_SET_MARK,              /* m */
+                        Operation.VI_SEARCH_AGAIN,          /* n */
+                        null,                               /* o */
+                        Operation.VI_PUT,                   /* p */
+                        null,                               /* q */
+                        Operation.VI_CHANGE_CHAR,           /* r */
+                        Operation.VI_SUBST,                 /* s */
+                        Operation.VI_CHAR_SEARCH,           /* t */
+                        Operation.UNDO,                     /* u */
+                        null,                               /* v */
+                        Operation.VI_NEXT_WORD,             /* w */
+                        Operation.VI_DELETE,                /* x */
+                        Operation.VI_YANK_TO,               /* y */
+                        null,                               /* z */
+                        null,                               /* { */
+                        Operation.VI_COLUMN,                /* | */
+                        null,                               /* } */
+                        Operation.VI_CHANGE_CASE,           /* ~ */
+                        Operation.VI_DELETE                 /* DEL */
+                };
+        System.arraycopy( low, 0, map, 0, low.length );
+        for (int i = 128; i < 256; i++) {
+            map[i] = null;
+        }
+        return new KeyMap(VI_MOVE, map, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2002-2013, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+/**
+ * The kill ring class keeps killed text in a fixed size ring. In this
+ * class we also keep record of whether or not the last command was a
+ * kill or a yank. Depending on this, the class may behave
+ * different. For instance, two consecutive kill-word commands fill
+ * the same slot such that the next yank will return the two
+ * previously killed words instead that only the last one. Likewise
+ * yank pop requires that the previous command was either a yank or a
+ * yank-pop.
+ */
+public final class KillRing {
+
+    /**
+     * Default size is 60, like in emacs.
+     */
+    private static final int DEFAULT_SIZE = 60;
+
+    private final String[] slots;
+    private int head = 0;
+    private boolean lastKill = false;
+    private boolean lastYank = false;
+
+    /**
+     * Creates a new kill ring of the given size.
+     */
+    public KillRing(int size) {
+        slots = new String[size];
+    }
+
+    /**
+     * Creates a new kill ring of the default size. {@see DEFAULT_SIZE}.
+     */
+    public KillRing() {
+        this(DEFAULT_SIZE);
+    }
+
+    /**
+     * Resets the last-yank state.
+     */
+    public void resetLastYank() {
+        lastYank = false;
+    }
+
+    /**
+     * Resets the last-kill state.
+     */
+    public void resetLastKill() {
+        lastKill = false;
+    }
+
+    /**
+     * Returns {@code true} if the last command was a yank.
+     */
+    public boolean lastYank() {
+        return lastYank;
+    }
+
+    /**
+     * Adds the string to the kill-ring. Also sets lastYank to false
+     * and lastKill to true.
+     */
+    public void add(String str) {
+        lastYank = false;
+
+        if (lastKill) {
+            if (slots[head] != null) {
+                slots[head] += str;
+                return;
+            }
+        }
+
+        lastKill = true;
+        next();
+        slots[head] = str;
+    }
+
+    /**
+     * Adds the string to the kill-ring product of killing
+     * backwards. If the previous command was a kill text one then
+     * adds the text at the beginning of the previous kill to avoid
+     * that two consecutive backwards kills followed by a yank leaves
+     * things reversed.
+     */
+    public void addBackwards(String str) {
+        lastYank = false;
+
+        if (lastKill) {
+            if (slots[head] != null) {
+                slots[head] = str + slots[head];
+                return;
+            }
+        }
+
+        lastKill = true;
+        next();
+        slots[head] = str;
+    }
+
+    /**
+     * Yanks a previously killed text. Returns {@code null} if the
+     * ring is empty.
+     */
+    public String yank() {
+        lastKill = false;
+        lastYank = true;
+        return slots[head];
+    }
+
+    /**
+     * Moves the pointer to the current slot back and returns the text
+     * in that position. If the previous command was not yank returns
+     * null.
+     */
+    public String yankPop() {
+        lastKill = false;
+        if (lastYank) {
+            prev();
+            return slots[head];
+        }
+        return null;
+    }
+
+    /**
+     * Moves the pointer to the current slot forward. If the end of
+     * the slots is reached then points back to the beginning.
+     */
+    private void next() {
+        if (head == 0 && slots[0] == null) {
+            return;
+        }
+        head++;
+        if (head == slots.length) {
+            head = 0;
+        }
+    }
+
+    /**
+     * Moves the pointer to the current slot backwards. If the
+     * beginning of the slots is reached then traverses the slot
+     * backwards until one with not null content is found.
+     */
+    private void prev() {
+        head--;
+        if (head == -1) {
+            int x = (slots.length - 1);
+            for (; x >= 0; x--) {
+                if (slots[x] != null) {
+                    break;
+                }
+            }
+            head = x;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+/**
+ * List of all operations.
+ *
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.6
+ */
+public enum Operation {
+
+    ABORT,
+    ACCEPT_LINE,
+    ARROW_KEY_PREFIX,
+    BACKWARD_BYTE,
+    BACKWARD_CHAR,
+    BACKWARD_DELETE_CHAR,
+    BACKWARD_KILL_LINE,
+    BACKWARD_KILL_WORD,
+    BACKWARD_WORD,
+    BEGINNING_OF_HISTORY,
+    BEGINNING_OF_LINE,
+    CALL_LAST_KBD_MACRO,
+    CAPITALIZE_WORD,
+    CHARACTER_SEARCH,
+    CHARACTER_SEARCH_BACKWARD,
+    CLEAR_SCREEN,
+    COMPLETE,
+    COPY_BACKWARD_WORD,
+    COPY_FORWARD_WORD,
+    COPY_REGION_AS_KILL,
+    DELETE_CHAR,
+    DELETE_CHAR_OR_LIST,
+    DELETE_HORIZONTAL_SPACE,
+    DIGIT_ARGUMENT,
+    DO_LOWERCASE_VERSION,
+    DOWNCASE_WORD,
+    DUMP_FUNCTIONS,
+    DUMP_MACROS,
+    DUMP_VARIABLES,
+    EMACS_EDITING_MODE,
+    END_KBD_MACRO,
+    END_OF_HISTORY,
+    END_OF_LINE,
+    EXCHANGE_POINT_AND_MARK,
+    EXIT_OR_DELETE_CHAR,
+    FORWARD_BACKWARD_DELETE_CHAR,
+    FORWARD_BYTE,
+    FORWARD_CHAR,
+    FORWARD_SEARCH_HISTORY,
+    FORWARD_WORD,
+    HISTORY_SEARCH_BACKWARD,
+    HISTORY_SEARCH_FORWARD,
+    INSERT_CLOSE_CURLY,
+    INSERT_CLOSE_PAREN,
+    INSERT_CLOSE_SQUARE,
+    INSERT_COMMENT,
+    INSERT_COMPLETIONS,
+    INTERRUPT,
+    KILL_WHOLE_LINE,
+    KILL_LINE,
+    KILL_REGION,
+    KILL_WORD,
+    MENU_COMPLETE,
+    MENU_COMPLETE_BACKWARD,
+    NEXT_HISTORY,
+    NON_INCREMENTAL_FORWARD_SEARCH_HISTORY,
+    NON_INCREMENTAL_REVERSE_SEARCH_HISTORY,
+    NON_INCREMENTAL_FORWARD_SEARCH_HISTORY_AGAIN,
+    NON_INCREMENTAL_REVERSE_SEARCH_HISTORY_AGAIN,
+    OLD_MENU_COMPLETE,
+    OVERWRITE_MODE,
+    PASTE_FROM_CLIPBOARD,
+    POSSIBLE_COMPLETIONS,
+    PREVIOUS_HISTORY,
+    QUOTED_INSERT,
+    RE_READ_INIT_FILE,
+    REDRAW_CURRENT_LINE,
+    REVERSE_SEARCH_HISTORY,
+    REVERT_LINE,
+    SELF_INSERT,
+    SET_MARK,
+    SKIP_CSI_SEQUENCE,
+    START_KBD_MACRO,
+    TAB_INSERT,
+    TILDE_EXPAND,
+    TRANSPOSE_CHARS,
+    TRANSPOSE_WORDS,
+    TTY_STATUS,
+    UNDO,
+    UNIVERSAL_ARGUMENT,
+    UNIX_FILENAME_RUBOUT,
+    UNIX_LINE_DISCARD,
+    UNIX_WORD_RUBOUT,
+    UPCASE_WORD,
+    YANK,
+    YANK_LAST_ARG,
+    YANK_NTH_ARG,
+    YANK_POP,
+    VI_APPEND_EOL,
+    VI_APPEND_MODE,
+    VI_ARG_DIGIT,
+    VI_BACK_TO_INDENT,
+    VI_BACKWARD_BIGWORD,
+    VI_BACKWARD_WORD,
+    VI_BWORD,
+    VI_CHANGE_CASE,
+    VI_CHANGE_CHAR,
+    VI_CHANGE_TO,
+    VI_CHANGE_TO_EOL,
+    VI_CHAR_SEARCH,
+    VI_COLUMN,
+    VI_COMPLETE,
+    VI_DELETE,
+    VI_DELETE_TO,
+    VI_DELETE_TO_EOL,
+    VI_EDITING_MODE,
+    VI_END_BIGWORD,
+    VI_END_WORD,
+    VI_EOF_MAYBE,
+    VI_EWORD,
+    VI_FWORD,
+    VI_FETCH_HISTORY,
+    VI_FIRST_PRINT,
+    VI_FORWARD_BIGWORD,
+    VI_FORWARD_WORD,
+    VI_GOTO_MARK,
+    VI_INSERT_BEG,
+    VI_INSERTION_MODE,
+    VI_KILL_WHOLE_LINE,
+    VI_MATCH,
+    VI_MOVEMENT_MODE,
+    VI_NEXT_WORD,
+    VI_OVERSTRIKE,
+    VI_OVERSTRIKE_DELETE,
+    VI_PREV_WORD,
+    VI_PUT,
+    VI_REDO,
+    VI_REPLACE,
+    VI_RUBOUT,
+    VI_SEARCH,
+    VI_SEARCH_AGAIN,
+    VI_SET_MARK,
+    VI_SUBST,
+    VI_TILDE_EXPAND,
+    VI_YANK_ARG,
+    VI_YANK_TO,
+    VI_MOVE_ACCEPT_LINE,
+    VI_NEXT_HISTORY,
+    VI_PREVIOUS_HISTORY,
+    VI_INSERT_COMMENT,
+    VI_BEGNNING_OF_LINE_OR_ARG_DIGIT,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console;
+
+/**
+ * This exception is thrown by {@link ConsoleReader#readLine} when
+ * user interrupt handling is enabled and the user types the
+ * interrupt character (ctrl-C). The partially entered line is
+ * available via the {@link #getPartialLine()} method.
+ */
+public class UserInterruptException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = 6172232572140736750L;
+
+    private final String partialLine;
+
+    public UserInterruptException(String partialLine)
+    {
+        this.partialLine = partialLine;
+    }
+
+    /**
+     * @return the partially entered line when ctrl-C was pressed
+     */
+    public String getPartialLine()
+    {
+        return partialLine;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Completer which contains multiple completers and aggregates them together.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class AggregateCompleter
+    implements Completer
+{
+    private final List<Completer> completers = new ArrayList<Completer>();
+
+    public AggregateCompleter() {
+        // empty
+    }
+
+    /**
+     * Construct an AggregateCompleter with the given collection of completers.
+     * The completers will be used in the iteration order of the collection.
+     *
+     * @param completers the collection of completers
+     */
+    public AggregateCompleter(final Collection<Completer> completers) {
+        checkNotNull(completers);
+        this.completers.addAll(completers);
+    }
+
+    /**
+     * Construct an AggregateCompleter with the given completers.
+     * The completers will be used in the order given.
+     *
+     * @param completers the completers
+     */
+    public AggregateCompleter(final Completer... completers) {
+        this(Arrays.asList(completers));
+    }
+
+    /**
+     * Retrieve the collection of completers currently being aggregated.
+     *
+     * @return the aggregated completers
+     */
+    public Collection<Completer> getCompleters() {
+        return completers;
+    }
+
+    /**
+     * Perform a completion operation across all aggregated completers.
+     *
+     * @see Completer#complete(String, int, java.util.List)
+     * @return the highest completion return value from all completers
+     */
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        // buffer could be null
+        checkNotNull(candidates);
+
+        List<Completion> completions = new ArrayList<Completion>(completers.size());
+
+        // Run each completer, saving its completion results
+        int max = -1;
+        for (Completer completer : completers) {
+            Completion completion = new Completion(candidates);
+            completion.complete(completer, buffer, cursor);
+
+            // Compute the max cursor position
+            max = Math.max(max, completion.cursor);
+
+            completions.add(completion);
+        }
+
+        // Append candidates from completions which have the same cursor position as max
+        for (Completion completion : completions) {
+            if (completion.cursor == max) {
+                candidates.addAll(completion.candidates);
+            }
+        }
+
+        return max;
+    }
+
+    /**
+     * @return a string representing the aggregated completers
+     */
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "{" +
+            "completers=" + completers +
+            '}';
+    }
+
+    private class Completion
+    {
+        public final List<CharSequence> candidates;
+
+        public int cursor;
+
+        public Completion(final List<CharSequence> candidates) {
+            checkNotNull(candidates);
+            this.candidates = new LinkedList<CharSequence>(candidates);
+        }
+
+        public void complete(final Completer completer, final String buffer, final int cursor) {
+            checkNotNull(completer);
+            this.cursor = completer.complete(buffer, cursor, candidates);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import jdk.internal.jline.internal.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * A {@link Completer} implementation that invokes a child completer using the appropriate <i>separator</i> argument.
+ * This can be used instead of the individual completers having to know about argument parsing semantics.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class ArgumentCompleter
+    implements Completer
+{
+    private final ArgumentDelimiter delimiter;
+
+    private final List<Completer> completers = new ArrayList<Completer>();
+
+    private boolean strict = true;
+
+    /**
+     * Create a new completer with the specified argument delimiter.
+     *
+     * @param delimiter     The delimiter for parsing arguments
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final ArgumentDelimiter delimiter, final Collection<Completer> completers) {
+        this.delimiter = checkNotNull(delimiter);
+        checkNotNull(completers);
+        this.completers.addAll(completers);
+    }
+
+    /**
+     * Create a new completer with the specified argument delimiter.
+     *
+     * @param delimiter     The delimiter for parsing arguments
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final ArgumentDelimiter delimiter, final Completer... completers) {
+        this(delimiter, Arrays.asList(completers));
+    }
+
+    /**
+     * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
+     *
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final Completer... completers) {
+        this(new WhitespaceArgumentDelimiter(), completers);
+    }
+
+    /**
+     * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
+     *
+     * @param completers    The embedded completers
+     */
+    public ArgumentCompleter(final List<Completer> completers) {
+        this(new WhitespaceArgumentDelimiter(), completers);
+    }
+
+    /**
+     * If true, a completion at argument index N will only succeed
+     * if all the completions from 0-(N-1) also succeed.
+     */
+    public void setStrict(final boolean strict) {
+        this.strict = strict;
+    }
+
+    /**
+     * Returns whether a completion at argument index N will success
+     * if all the completions from arguments 0-(N-1) also succeed.
+     *
+     * @return  True if strict.
+     * @since 2.3
+     */
+    public boolean isStrict() {
+        return this.strict;
+    }
+
+    /**
+     * @since 2.3
+     */
+    public ArgumentDelimiter getDelimiter() {
+        return delimiter;
+    }
+
+    /**
+     * @since 2.3
+     */
+    public List<Completer> getCompleters() {
+        return completers;
+    }
+
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        // buffer can be null
+        checkNotNull(candidates);
+
+        ArgumentDelimiter delim = getDelimiter();
+        ArgumentList list = delim.delimit(buffer, cursor);
+        int argpos = list.getArgumentPosition();
+        int argIndex = list.getCursorArgumentIndex();
+
+        if (argIndex < 0) {
+            return -1;
+        }
+
+        List<Completer> completers = getCompleters();
+        Completer completer;
+
+        // if we are beyond the end of the completers, just use the last one
+        if (argIndex >= completers.size()) {
+            completer = completers.get(completers.size() - 1);
+        }
+        else {
+            completer = completers.get(argIndex);
+        }
+
+        // ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
+        for (int i = 0; isStrict() && (i < argIndex); i++) {
+            Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i);
+            String[] args = list.getArguments();
+            String arg = (args == null || i >= args.length) ? "" : args[i];
+
+            List<CharSequence> subCandidates = new LinkedList<CharSequence>();
+
+            if (sub.complete(arg, arg.length(), subCandidates) == -1) {
+                return -1;
+            }
+
+            if (subCandidates.size() == 0) {
+                return -1;
+            }
+        }
+
+        int ret = completer.complete(list.getCursorArgument(), argpos, candidates);
+
+        if (ret == -1) {
+            return -1;
+        }
+
+        int pos = ret + list.getBufferPosition() - argpos;
+
+        // Special case: when completing in the middle of a line, and the area under the cursor is a delimiter,
+        // then trim any delimiters from the candidates, since we do not need to have an extra delimiter.
+        //
+        // E.g., if we have a completion for "foo", and we enter "f bar" into the buffer, and move to after the "f"
+        // and hit TAB, we want "foo bar" instead of "foo  bar".
+
+        if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
+            for (int i = 0; i < candidates.size(); i++) {
+                CharSequence val = candidates.get(i);
+
+                while (val.length() > 0 && delim.isDelimiter(val, val.length() - 1)) {
+                    val = val.subSequence(0, val.length() - 1);
+                }
+
+                candidates.set(i, val);
+            }
+        }
+
+        Log.trace("Completing ", buffer, " (pos=", cursor, ") with: ", candidates, ": offset=", pos);
+
+        return pos;
+    }
+
+    /**
+     * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom breaking up of a {@link String} into individual
+     * arguments in order to dispatch the arguments to the nested {@link Completer}.
+     *
+     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+     */
+    public static interface ArgumentDelimiter
+    {
+        /**
+         * Break the specified buffer into individual tokens that can be completed on their own.
+         *
+         * @param buffer    The buffer to split
+         * @param pos       The current position of the cursor in the buffer
+         * @return          The tokens
+         */
+        ArgumentList delimit(CharSequence buffer, int pos);
+
+        /**
+         * Returns true if the specified character is a whitespace parameter.
+         *
+         * @param buffer    The complete command buffer
+         * @param pos       The index of the character in the buffer
+         * @return          True if the character should be a delimiter
+         */
+        boolean isDelimiter(CharSequence buffer, int pos);
+    }
+
+    /**
+     * Abstract implementation of a delimiter that uses the {@link #isDelimiter} method to determine if a particular
+     * character should be used as a delimiter.
+     *
+     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+     */
+    public abstract static class AbstractArgumentDelimiter
+        implements ArgumentDelimiter
+    {
+        private char[] quoteChars = {'\'', '"'};
+
+        private char[] escapeChars = {'\\'};
+
+        public void setQuoteChars(final char[] chars) {
+            this.quoteChars = chars;
+        }
+
+        public char[] getQuoteChars() {
+            return this.quoteChars;
+        }
+
+        public void setEscapeChars(final char[] chars) {
+            this.escapeChars = chars;
+        }
+
+        public char[] getEscapeChars() {
+            return this.escapeChars;
+        }
+
+        public ArgumentList delimit(final CharSequence buffer, final int cursor) {
+            List<String> args = new LinkedList<String>();
+            StringBuilder arg = new StringBuilder();
+            int argpos = -1;
+            int bindex = -1;
+            int quoteStart = -1;
+
+            for (int i = 0; (buffer != null) && (i < buffer.length()); i++) {
+                // once we reach the cursor, set the
+                // position of the selected index
+                if (i == cursor) {
+                    bindex = args.size();
+                    // the position in the current argument is just the
+                    // length of the current argument
+                    argpos = arg.length();
+                }
+
+                if (quoteStart < 0 && isQuoteChar(buffer, i)) {
+                    // Start a quote block
+                    quoteStart = i;
+                } else if (quoteStart >= 0) {
+                    // In a quote block
+                    if (buffer.charAt(quoteStart) == buffer.charAt(i) && !isEscaped(buffer, i)) {
+                        // End the block; arg could be empty, but that's fine
+                        args.add(arg.toString());
+                        arg.setLength(0);
+                        quoteStart = -1;
+                    } else if (!isEscapeChar(buffer, i)) {
+                        // Take the next character
+                        arg.append(buffer.charAt(i));
+                    }
+                } else {
+                    // Not in a quote block
+                    if (isDelimiter(buffer, i)) {
+                        if (arg.length() > 0) {
+                            args.add(arg.toString());
+                            arg.setLength(0); // reset the arg
+                        }
+                    } else if (!isEscapeChar(buffer, i)) {
+                        arg.append(buffer.charAt(i));
+                    }
+                }
+            }
+
+            if (cursor == buffer.length()) {
+                bindex = args.size();
+                // the position in the current argument is just the
+                // length of the current argument
+                argpos = arg.length();
+            }
+            if (arg.length() > 0) {
+                args.add(arg.toString());
+            }
+
+            return new ArgumentList(args.toArray(new String[args.size()]), bindex, argpos, cursor);
+        }
+
+        /**
+         * Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not
+         * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and
+         * returns true from {@link #isDelimiterChar}.
+         *
+         * @param buffer    The complete command buffer
+         * @param pos       The index of the character in the buffer
+         * @return          True if the character should be a delimiter
+         */
+        public boolean isDelimiter(final CharSequence buffer, final int pos) {
+            return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
+        }
+
+        public boolean isQuoted(final CharSequence buffer, final int pos) {
+            return false;
+        }
+
+        public boolean isQuoteChar(final CharSequence buffer, final int pos) {
+            if (pos < 0) {
+                return false;
+            }
+
+            for (int i = 0; (quoteChars != null) && (i < quoteChars.length); i++) {
+                if (buffer.charAt(pos) == quoteChars[i]) {
+                    return !isEscaped(buffer, pos);
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * Check if this character is a valid escape char (i.e. one that has not been escaped)
+         *
+         * @param buffer
+         * @param pos
+         * @return
+         */
+        public boolean isEscapeChar(final CharSequence buffer, final int pos) {
+            if (pos < 0) {
+                return false;
+            }
+
+            for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) {
+                if (buffer.charAt(pos) == escapeChars[i]) {
+                    return !isEscaped(buffer, pos); // escape escape
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * Check if a character is escaped (i.e. if the previous character is an escape)
+         *
+         * @param buffer
+         *          the buffer to check in
+         * @param pos
+         *          the position of the character to check
+         * @return true if the character at the specified position in the given buffer is an escape character and the character immediately preceding it is not an
+         *         escape character.
+         */
+        public boolean isEscaped(final CharSequence buffer, final int pos) {
+            if (pos <= 0) {
+                return false;
+            }
+
+            return isEscapeChar(buffer, pos - 1);
+        }
+
+        /**
+         * Returns true if the character at the specified position if a delimiter. This method will only be called if
+         * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the
+         * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
+         */
+        public abstract boolean isDelimiterChar(CharSequence buffer, int pos);
+    }
+
+    /**
+     * {@link ArgumentCompleter.ArgumentDelimiter} implementation that counts all whitespace (as reported by
+     * {@link Character#isWhitespace}) as being a delimiter.
+     *
+     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+     */
+    public static class WhitespaceArgumentDelimiter
+        extends AbstractArgumentDelimiter
+    {
+        /**
+         * The character is a delimiter if it is whitespace, and the
+         * preceding character is not an escape character.
+         */
+        @Override
+        public boolean isDelimiterChar(final CharSequence buffer, final int pos) {
+            return Character.isWhitespace(buffer.charAt(pos));
+        }
+    }
+
+    /**
+     * The result of a delimited buffer.
+     *
+     * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+     */
+    public static class ArgumentList
+    {
+        private String[] arguments;
+
+        private int cursorArgumentIndex;
+
+        private int argumentPosition;
+
+        private int bufferPosition;
+
+        /**
+         * @param arguments             The array of tokens
+         * @param cursorArgumentIndex   The token index of the cursor
+         * @param argumentPosition      The position of the cursor in the current token
+         * @param bufferPosition        The position of the cursor in the whole buffer
+         */
+        public ArgumentList(final String[] arguments, final int cursorArgumentIndex, final int argumentPosition, final int bufferPosition) {
+            this.arguments = checkNotNull(arguments);
+            this.cursorArgumentIndex = cursorArgumentIndex;
+            this.argumentPosition = argumentPosition;
+            this.bufferPosition = bufferPosition;
+        }
+
+        public void setCursorArgumentIndex(final int i) {
+            this.cursorArgumentIndex = i;
+        }
+
+        public int getCursorArgumentIndex() {
+            return this.cursorArgumentIndex;
+        }
+
+        public String getCursorArgument() {
+            if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) {
+                return null;
+            }
+
+            return arguments[cursorArgumentIndex];
+        }
+
+        public void setArgumentPosition(final int pos) {
+            this.argumentPosition = pos;
+        }
+
+        public int getArgumentPosition() {
+            return this.argumentPosition;
+        }
+
+        public void setArguments(final String[] arguments) {
+            this.arguments = arguments;
+        }
+
+        public String[] getArguments() {
+            return this.arguments;
+        }
+
+        public void setBufferPosition(final int pos) {
+            this.bufferPosition = pos;
+        }
+
+        public int getBufferPosition() {
+            return this.bufferPosition;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.CursorBuffer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+/**
+ * A {@link CompletionHandler} that deals with multiple distinct completions
+ * by outputting the complete list of possibilities to the console. This
+ * mimics the behavior of the
+ * <a href="http://www.gnu.org/directory/readline.html">readline</a> library.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class CandidateListCompletionHandler
+    implements CompletionHandler
+{
+    // TODO: handle quotes and escaped quotes && enable automatic escaping of whitespace
+
+    public boolean complete(final ConsoleReader reader, final List<CharSequence> candidates, final int pos) throws
+        IOException
+    {
+        CursorBuffer buf = reader.getCursorBuffer();
+
+        // if there is only one completion, then fill in the buffer
+        if (candidates.size() == 1) {
+            CharSequence value = candidates.get(0);
+
+            // fail if the only candidate is the same as the current buffer
+            if (value.equals(buf.toString())) {
+                return false;
+            }
+
+            setBuffer(reader, value, pos);
+
+            return true;
+        }
+        else if (candidates.size() > 1) {
+            String value = getUnambiguousCompletions(candidates);
+            setBuffer(reader, value, pos);
+        }
+
+        printCandidates(reader, candidates);
+
+        // redraw the current console buffer
+        reader.drawLine();
+
+        return true;
+    }
+
+    public static void setBuffer(final ConsoleReader reader, final CharSequence value, final int offset) throws
+        IOException
+    {
+        while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) {
+            // empty
+        }
+
+        reader.putString(value);
+        reader.setCursorPosition(offset + value.length());
+    }
+
+    /**
+     * Print out the candidates. If the size of the candidates is greater than the
+     * {@link ConsoleReader#getAutoprintThreshold}, they prompt with a warning.
+     *
+     * @param candidates the list of candidates to print
+     */
+    public static void printCandidates(final ConsoleReader reader, Collection<CharSequence> candidates) throws
+        IOException
+    {
+        Set<CharSequence> distinct = new HashSet<CharSequence>(candidates);
+
+        if (distinct.size() > reader.getAutoprintThreshold()) {
+            //noinspection StringConcatenation
+            reader.print(Messages.DISPLAY_CANDIDATES.format(candidates.size()));
+            reader.flush();
+
+            int c;
+
+            String noOpt = Messages.DISPLAY_CANDIDATES_NO.format();
+            String yesOpt = Messages.DISPLAY_CANDIDATES_YES.format();
+            char[] allowed = {yesOpt.charAt(0), noOpt.charAt(0)};
+
+            while ((c = reader.readCharacter(allowed)) != -1) {
+                String tmp = new String(new char[]{(char) c});
+
+                if (noOpt.startsWith(tmp)) {
+                    reader.println();
+                    return;
+                }
+                else if (yesOpt.startsWith(tmp)) {
+                    break;
+                }
+                else {
+                    reader.beep();
+                }
+            }
+        }
+
+        // copy the values and make them distinct, without otherwise affecting the ordering. Only do it if the sizes differ.
+        if (distinct.size() != candidates.size()) {
+            Collection<CharSequence> copy = new ArrayList<CharSequence>();
+
+            for (CharSequence next : candidates) {
+                if (!copy.contains(next)) {
+                    copy.add(next);
+                }
+            }
+
+            candidates = copy;
+        }
+
+        reader.println();
+        reader.printColumns(candidates);
+    }
+
+    /**
+     * Returns a root that matches all the {@link String} elements of the specified {@link List},
+     * or null if there are no commonalities. For example, if the list contains
+     * <i>foobar</i>, <i>foobaz</i>, <i>foobuz</i>, the method will return <i>foob</i>.
+     */
+    private String getUnambiguousCompletions(final List<CharSequence> candidates) {
+        if (candidates == null || candidates.isEmpty()) {
+            return null;
+        }
+
+        // convert to an array for speed
+        String[] strings = candidates.toArray(new String[candidates.size()]);
+
+        String first = strings[0];
+        StringBuilder candidate = new StringBuilder();
+
+        for (int i = 0; i < first.length(); i++) {
+            if (startsWith(first.substring(0, i + 1), strings)) {
+                candidate.append(first.charAt(i));
+            }
+            else {
+                break;
+            }
+        }
+
+        return candidate.toString();
+    }
+
+    /**
+     * @return true is all the elements of <i>candidates</i> start with <i>starts</i>
+     */
+    private boolean startsWith(final String starts, final String[] candidates) {
+        for (String candidate : candidates) {
+            if (!candidate.startsWith(starts)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private static enum Messages
+    {
+        DISPLAY_CANDIDATES,
+        DISPLAY_CANDIDATES_YES,
+        DISPLAY_CANDIDATES_NO,;
+
+        private static final
+        ResourceBundle
+            bundle =
+            ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
+
+        public String format(final Object... args) {
+            if (bundle == null)
+                return "";
+            else
+                return String.format(bundle.getString(name()), args);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2002-2012, the original author or authors.
+#
+# This software is distributable under the BSD license. See the terms of the
+# BSD license in the documentation provided with this software.
+#
+# http://www.opensource.org/licenses/bsd-license.php
+#
+
+DISPLAY_CANDIDATES=Display all %d possibilities? (y or n)
+DISPLAY_CANDIDATES_YES=y
+DISPLAY_CANDIDATES_NO=n
+DISPLAY_MORE=--More--
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import java.util.List;
+
+/**
+ * A completer is the mechanism by which tab-completion candidates will be resolved.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public interface Completer
+{
+    //
+    // FIXME: Check if we can use CharSequece for buffer?
+    //
+
+    /**
+     * Populates <i>candidates</i> with a list of possible completions for the <i>buffer</i>.
+     *
+     * The <i>candidates</i> list will not be sorted before being displayed to the user: thus, the
+     * complete method should sort the {@link List} before returning.
+     *
+     * @param buffer        The buffer
+     * @param cursor        The current position of the cursor in the <i>buffer</i>
+     * @param candidates    The {@link List} of candidates to populate
+     * @return              The index of the <i>buffer</i> for which the completion will be relative
+     */
+    int complete(String buffer, int cursor, List<CharSequence> candidates);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import jdk.internal.jline.console.ConsoleReader;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Handler for dealing with candidates for tab-completion.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public interface CompletionHandler
+{
+    boolean complete(ConsoleReader reader, List<CharSequence> candidates, int position) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * {@link Completer} for {@link Enum} names.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class EnumCompleter
+    extends StringsCompleter
+{
+    public EnumCompleter(Class<? extends Enum<?>> source) {
+        checkNotNull(source);
+
+        for (Enum<?> n : source.getEnumConstants()) {
+            this.getStrings().add(n.name().toLowerCase());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import jdk.internal.jline.internal.Configuration;
+
+import java.io.File;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * A file name completer takes the buffer and issues a list of
+ * potential completions.
+ * <p/>
+ * This completer tries to behave as similar as possible to
+ * <i>bash</i>'s file name completion (using GNU readline)
+ * with the following exceptions:
+ * <p/>
+ * <ul>
+ * <li>Candidates that are directories will end with "/"</li>
+ * <li>Wildcard regular expressions are not evaluated or replaced</li>
+ * <li>The "~" character can be used to represent the user's home,
+ * but it cannot complete to other users' homes, since java does
+ * not provide any way of determining that easily</li>
+ * </ul>
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class FileNameCompleter
+    implements Completer
+{
+    // TODO: Handle files with spaces in them
+
+    private static final boolean OS_IS_WINDOWS;
+
+    static {
+        String os = Configuration.getOsName();
+        OS_IS_WINDOWS = os.contains("windows");
+    }
+
+    public int complete(String buffer, final int cursor, final List<CharSequence> candidates) {
+        // buffer can be null
+        checkNotNull(candidates);
+
+        if (buffer == null) {
+            buffer = "";
+        }
+
+        if (OS_IS_WINDOWS) {
+            buffer = buffer.replace('/', '\\');
+        }
+
+        String translated = buffer;
+
+        File homeDir = getUserHome();
+
+        // Special character: ~ maps to the user's home directory
+        if (translated.startsWith("~" + separator())) {
+            translated = homeDir.getPath() + translated.substring(1);
+        }
+        else if (translated.startsWith("~")) {
+            translated = homeDir.getParentFile().getAbsolutePath();
+        }
+        else if (!(new File(translated).isAbsolute())) {
+            String cwd = getUserDir().getAbsolutePath();
+            translated = cwd + separator() + translated;
+        }
+
+        File file = new File(translated);
+        final File dir;
+
+        if (translated.endsWith(separator())) {
+            dir = file;
+        }
+        else {
+            dir = file.getParentFile();
+        }
+
+        File[] entries = dir == null ? new File[0] : dir.listFiles();
+
+        return matchFiles(buffer, translated, entries, candidates);
+    }
+
+    protected String separator() {
+        return File.separator;
+    }
+
+    protected File getUserHome() {
+        return Configuration.getUserHome();
+    }
+
+    protected File getUserDir() {
+        return new File(".");
+    }
+
+    protected int matchFiles(final String buffer, final String translated, final File[] files, final List<CharSequence> candidates) {
+        if (files == null) {
+            return -1;
+        }
+
+        int matches = 0;
+
+        // first pass: just count the matches
+        for (File file : files) {
+            if (file.getAbsolutePath().startsWith(translated)) {
+                matches++;
+            }
+        }
+        for (File file : files) {
+            if (file.getAbsolutePath().startsWith(translated)) {
+                CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " ");
+                candidates.add(render(file, name).toString());
+            }
+        }
+
+        final int index = buffer.lastIndexOf(separator());
+
+        return index + separator().length();
+    }
+
+    protected CharSequence render(final File file, final CharSequence name) {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import java.util.List;
+
+/**
+ * Null completer.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public final class NullCompleter
+    implements Completer
+{
+    public static final NullCompleter INSTANCE = new NullCompleter();
+
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        return -1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.completer;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Completer for a set of strings.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class StringsCompleter
+    implements Completer
+{
+    private final SortedSet<String> strings = new TreeSet<String>();
+
+    public StringsCompleter() {
+        // empty
+    }
+
+    public StringsCompleter(final Collection<String> strings) {
+        checkNotNull(strings);
+        getStrings().addAll(strings);
+    }
+
+    public StringsCompleter(final String... strings) {
+        this(Arrays.asList(strings));
+    }
+
+    public Collection<String> getStrings() {
+        return strings;
+    }
+
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        // buffer could be null
+        checkNotNull(candidates);
+
+        if (buffer == null) {
+            candidates.addAll(strings);
+        }
+        else {
+            for (String match : strings.tailSet(buffer)) {
+                if (!match.startsWith(buffer)) {
+                    break;
+                }
+
+                candidates.add(match);
+            }
+        }
+
+        if (candidates.size() == 1) {
+            candidates.set(0, candidates.get(0) + " ");
+        }
+
+        return candidates.isEmpty() ? -1 : 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * Console completer support.
+ *
+ * @since 2.3
+ */
+package jdk.internal.jline.console.completer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.history;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.Reader;
+
+import jdk.internal.jline.internal.Log;
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * {@link History} using a file for persistent backing.
+ * <p/>
+ * Implementers should install shutdown hook to call {@link FileHistory#flush}
+ * to save history to disk.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public class FileHistory
+    extends MemoryHistory
+    implements PersistentHistory, Flushable
+{
+    private final File file;
+
+    public FileHistory(final File file) throws IOException {
+        this.file = checkNotNull(file);
+        load(file);
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public void load(final File file) throws IOException {
+        checkNotNull(file);
+        if (file.exists()) {
+            Log.trace("Loading history from: ", file);
+            load(new FileReader(file));
+        }
+    }
+
+    public void load(final InputStream input) throws IOException {
+        checkNotNull(input);
+        load(new InputStreamReader(input));
+    }
+
+    public void load(final Reader reader) throws IOException {
+        checkNotNull(reader);
+        BufferedReader input = new BufferedReader(reader);
+
+        String item;
+        while ((item = input.readLine()) != null) {
+            internalAdd(item);
+        }
+    }
+
+    public void flush() throws IOException {
+        Log.trace("Flushing history");
+
+        if (!file.exists()) {
+            File dir = file.getParentFile();
+            if (!dir.exists() && !dir.mkdirs()) {
+                Log.warn("Failed to create directory: ", dir);
+            }
+            if (!file.createNewFile()) {
+                Log.warn("Failed to create file: ", file);
+            }
+        }
+
+        PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
+        try {
+            for (Entry entry : this) {
+                out.println(entry.value());
+            }
+        }
+        finally {
+            out.close();
+        }
+    }
+
+    public void purge() throws IOException {
+        Log.trace("Purging history");
+
+        clear();
+
+        if (!file.delete()) {
+            Log.warn("Failed to delete history file: ", file);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.history;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Console history.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public interface History
+    extends Iterable<History.Entry>
+{
+    int size();
+
+    boolean isEmpty();
+
+    int index();
+
+    void clear();
+
+    CharSequence get(int index);
+
+    void add(CharSequence line);
+
+    /**
+     * Set the history item at the given index to the given CharSequence.
+     *
+     * @param index the index of the history offset
+     * @param item the new item
+     * @since 2.7
+     */
+    void set(int index, CharSequence item);
+
+    /**
+     * Remove the history element at the given index.
+     *
+     * @param i the index of the element to remove
+     * @return the removed element
+     * @since 2.7
+     */
+    CharSequence remove(int i);
+
+    /**
+     * Remove the first element from history.
+     *
+     * @return the removed element
+     * @since 2.7
+     */
+    CharSequence removeFirst();
+
+    /**
+     * Remove the last element from history
+     *
+     * @return the removed element
+     * @since 2.7
+     */
+    CharSequence removeLast();
+
+    void replace(CharSequence item);
+
+    //
+    // Entries
+    //
+
+    interface Entry
+    {
+        int index();
+
+        CharSequence value();
+    }
+
+    ListIterator<Entry> entries(int index);
+
+    ListIterator<Entry> entries();
+
+    Iterator<Entry> iterator();
+
+    //
+    // Navigation
+    //
+
+    CharSequence current();
+
+    boolean previous();
+
+    boolean next();
+
+    boolean moveToFirst();
+
+    boolean moveToLast();
+
+    boolean moveTo(int index);
+
+    void moveToEnd();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.history;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Non-persistent {@link History}.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public class MemoryHistory
+    implements History
+{
+    public static final int DEFAULT_MAX_SIZE = 500;
+
+    private final LinkedList<CharSequence> items = new LinkedList<CharSequence>();
+
+    private int maxSize = DEFAULT_MAX_SIZE;
+
+    private boolean ignoreDuplicates = true;
+
+    private boolean autoTrim = false;
+
+    // NOTE: These are all ideas from looking at the Bash man page:
+
+    // TODO: Add ignore space? (lines starting with a space are ignored)
+
+    // TODO: Add ignore patterns?
+
+    // TODO: Add history timestamp?
+
+    // TODO: Add erase dups?
+
+    private int offset = 0;
+
+    private int index = 0;
+
+    public void setMaxSize(final int maxSize) {
+        this.maxSize = maxSize;
+        maybeResize();
+    }
+
+    public int getMaxSize() {
+        return maxSize;
+    }
+
+    public boolean isIgnoreDuplicates() {
+        return ignoreDuplicates;
+    }
+
+    public void setIgnoreDuplicates(final boolean flag) {
+        this.ignoreDuplicates = flag;
+    }
+
+    public boolean isAutoTrim() {
+        return autoTrim;
+    }
+
+    public void setAutoTrim(final boolean flag) {
+        this.autoTrim = flag;
+    }
+
+    public int size() {
+        return items.size();
+    }
+
+    public boolean isEmpty() {
+        return items.isEmpty();
+    }
+
+    public int index() {
+        return offset + index;
+    }
+
+    public void clear() {
+        items.clear();
+        offset = 0;
+        index = 0;
+    }
+
+    public CharSequence get(final int index) {
+        return items.get(index - offset);
+    }
+
+    public void set(int index, CharSequence item) {
+        items.set(index - offset, item);
+    }
+
+    public void add(CharSequence item) {
+        checkNotNull(item);
+
+        if (isAutoTrim()) {
+            item = String.valueOf(item).trim();
+        }
+
+        if (isIgnoreDuplicates()) {
+            if (!items.isEmpty() && item.equals(items.getLast())) {
+                return;
+            }
+        }
+
+        internalAdd(item);
+    }
+
+    public CharSequence remove(int i) {
+        return items.remove(i);
+    }
+
+    public CharSequence removeFirst() {
+        return items.removeFirst();
+    }
+
+    public CharSequence removeLast() {
+        return items.removeLast();
+    }
+
+    protected void internalAdd(CharSequence item) {
+        items.add(item);
+
+        maybeResize();
+    }
+
+    public void replace(final CharSequence item) {
+        items.removeLast();
+        add(item);
+    }
+
+    private void maybeResize() {
+        while (size() > getMaxSize()) {
+            items.removeFirst();
+            offset++;
+        }
+
+        index = size();
+    }
+
+    public ListIterator<Entry> entries(final int index) {
+        return new EntriesIterator(index - offset);
+    }
+
+    public ListIterator<Entry> entries() {
+        return entries(offset);
+    }
+
+    public Iterator<Entry> iterator() {
+        return entries();
+    }
+
+    private static class EntryImpl
+        implements Entry
+    {
+        private final int index;
+
+        private final CharSequence value;
+
+        public EntryImpl(int index, CharSequence value) {
+            this.index = index;
+            this.value = value;
+        }
+
+        public int index() {
+            return index;
+        }
+
+        public CharSequence value() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%d: %s", index, value);
+        }
+    }
+
+    private class EntriesIterator
+        implements ListIterator<Entry>
+    {
+        private final ListIterator<CharSequence> source;
+
+        private EntriesIterator(final int index) {
+            source = items.listIterator(index);
+        }
+
+        public Entry next() {
+            if (!source.hasNext()) {
+                throw new NoSuchElementException();
+            }
+            return new EntryImpl(offset + source.nextIndex(), source.next());
+        }
+
+        public Entry previous() {
+            if (!source.hasPrevious()) {
+                throw new NoSuchElementException();
+            }
+            return new EntryImpl(offset + source.previousIndex(), source.previous());
+        }
+
+        public int nextIndex() {
+            return offset + source.nextIndex();
+        }
+
+        public int previousIndex() {
+            return offset + source.previousIndex();
+        }
+
+        public boolean hasNext() {
+            return source.hasNext();
+        }
+
+        public boolean hasPrevious() {
+            return source.hasPrevious();
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void set(final Entry entry) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void add(final Entry entry) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    //
+    // Navigation
+    //
+
+    /**
+     * This moves the history to the last entry. This entry is one position
+     * before the moveToEnd() position.
+     *
+     * @return Returns false if there were no history entries or the history
+     *         index was already at the last entry.
+     */
+    public boolean moveToLast() {
+        int lastEntry = size() - 1;
+        if (lastEntry >= 0 && lastEntry != index) {
+            index = size() - 1;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Move to the specified index in the history
+     * @param index
+     * @return
+     */
+    public boolean moveTo(int index) {
+        index -= offset;
+        if (index >= 0 && index < size() ) {
+            this.index = index;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Moves the history index to the first entry.
+     *
+     * @return Return false if there are no entries in the history or if the
+     *         history is already at the beginning.
+     */
+    public boolean moveToFirst() {
+        if (size() > 0 && index != 0) {
+            index = 0;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Move to the end of the history buffer. This will be a blank entry, after
+     * all of the other entries.
+     */
+    public void moveToEnd() {
+        index = size();
+    }
+
+    /**
+     * Return the content of the current buffer.
+     */
+    public CharSequence current() {
+        if (index >= size()) {
+            return "";
+        }
+
+        return items.get(index);
+    }
+
+    /**
+     * Move the pointer to the previous element in the buffer.
+     *
+     * @return true if we successfully went to the previous element
+     */
+    public boolean previous() {
+        if (index <= 0) {
+            return false;
+        }
+
+        index--;
+
+        return true;
+    }
+
+    /**
+     * Move the pointer to the next element in the buffer.
+     *
+     * @return true if we successfully went to the next element
+     */
+    public boolean next() {
+        if (index >= size()) {
+            return false;
+        }
+
+        index++;
+
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (Entry e : this) {
+            sb.append(e.toString() + "\n");
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.history;
+
+import java.io.IOException;
+
+/**
+ * Persistent {@link History}.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.3
+ */
+public interface PersistentHistory
+    extends History
+{
+    /**
+     * Flush all items to persistent storage.
+     *
+     * @throws IOException  Flush failed
+     */
+    void flush() throws IOException;
+
+    /**
+     * Purge persistent storage and {@link #clear}.
+     *
+     * @throws IOException  Purge failed
+     */
+    void purge() throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * Console history support.
+ *
+ * @since 2.0
+ */
+package jdk.internal.jline.console.history;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.internal;
+
+import jdk.internal.jline.console.ConsoleReader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.util.Enumeration;
+
+// FIXME: Clean up API and move to jline.console.runner package
+
+/**
+ * An {@link InputStream} implementation that wraps a {@link ConsoleReader}.
+ * It is useful for setting up the {@link System#in} for a generic console.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @since 2.7
+ */
+class ConsoleReaderInputStream
+    extends SequenceInputStream
+{
+    private static InputStream systemIn = System.in;
+
+    public static void setIn() throws IOException {
+        setIn(new ConsoleReader());
+    }
+
+    public static void setIn(final ConsoleReader reader) {
+        System.setIn(new ConsoleReaderInputStream(reader));
+    }
+
+    /**
+     * Restore the original {@link System#in} input stream.
+     */
+    public static void restoreIn() {
+        System.setIn(systemIn);
+    }
+
+    public ConsoleReaderInputStream(final ConsoleReader reader) {
+        super(new ConsoleEnumeration(reader));
+    }
+
+    private static class ConsoleEnumeration
+        implements Enumeration<InputStream>
+    {
+        private final ConsoleReader reader;
+        private ConsoleLineInputStream next = null;
+        private ConsoleLineInputStream prev = null;
+
+        public ConsoleEnumeration(final ConsoleReader reader) {
+            this.reader = reader;
+        }
+
+        public InputStream nextElement() {
+            if (next != null) {
+                InputStream n = next;
+                prev = next;
+                next = null;
+
+                return n;
+            }
+
+            return new ConsoleLineInputStream(reader);
+        }
+
+        public boolean hasMoreElements() {
+            // the last line was null
+            if ((prev != null) && (prev.wasNull == true)) {
+                return false;
+            }
+
+            if (next == null) {
+                next = (ConsoleLineInputStream) nextElement();
+            }
+
+            return next != null;
+        }
+    }
+
+    private static class ConsoleLineInputStream
+        extends InputStream
+    {
+        private final ConsoleReader reader;
+        private String line = null;
+        private int index = 0;
+        private boolean eol = false;
+        protected boolean wasNull = false;
+
+        public ConsoleLineInputStream(final ConsoleReader reader) {
+            this.reader = reader;
+        }
+
+        public int read() throws IOException {
+            if (eol) {
+                return -1;
+            }
+
+            if (line == null) {
+                line = reader.readLine();
+            }
+
+            if (line == null) {
+                wasNull = true;
+                return -1;
+            }
+
+            if (index >= line.length()) {
+                eol = true;
+                return '\n'; // lines are ended with a newline
+            }
+
+            return line.charAt(index++);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.console.internal;
+
+import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.completer.ArgumentCompleter;
+import jdk.internal.jline.console.completer.Completer;
+import jdk.internal.jline.console.history.FileHistory;
+import jdk.internal.jline.internal.Configuration;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringTokenizer;
+
+// FIXME: Clean up API and move to jline.console.runner package
+
+/**
+ * A pass-through application that sets the system input stream to a
+ * {@link ConsoleReader} and invokes the specified main method.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @since 2.7
+ */
+public class ConsoleRunner
+{
+    public static final String property = "jline.history";
+
+    // FIXME: This is really ugly... re-write this
+
+    public static void main(final String[] args) throws Exception {
+        List<String> argList = new ArrayList<String>(Arrays.asList(args));
+        if (argList.size() == 0) {
+            usage();
+            return;
+        }
+
+        String historyFileName = System.getProperty(ConsoleRunner.property, null);
+
+        String mainClass = argList.remove(0);
+        ConsoleReader reader = new ConsoleReader();
+
+        if (historyFileName != null) {
+            reader.setHistory(new FileHistory(new File(Configuration.getUserHome(),
+                String.format(".jline-%s.%s.history", mainClass, historyFileName))));
+        }
+        else {
+            reader.setHistory(new FileHistory(new File(Configuration.getUserHome(),
+                String.format(".jline-%s.history", mainClass))));
+        }
+
+        String completors = System.getProperty(ConsoleRunner.class.getName() + ".completers", "");
+        List<Completer> completorList = new ArrayList<Completer>();
+
+        for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) {
+            Object obj = Class.forName(tok.nextToken()).newInstance();
+            completorList.add((Completer) obj);
+        }
+
+        if (completorList.size() > 0) {
+            reader.addCompleter(new ArgumentCompleter(completorList));
+        }
+
+        ConsoleReaderInputStream.setIn(reader);
+
+        try {
+            Class<?> type = Class.forName(mainClass);
+            Method method = type.getMethod("main", String[].class);
+            method.invoke(null);
+        }
+        finally {
+            // just in case this main method is called from another program
+            ConsoleReaderInputStream.restoreIn();
+        }
+    }
+
+    private static void usage() {
+        System.out.println("Usage: \n   java " + "[-Djline.history='name'] "
+            + ConsoleRunner.class.getName()
+            + " <target class name> [args]"
+            + "\n\nThe -Djline.history option will avoid history"
+            + "\nmangling when running ConsoleRunner on the same application."
+            + "\n\nargs will be passed directly to the target class name.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * Console support.
+ *
+ * @since 2.0
+ */
+package jdk.internal.jline.console;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.Properties;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Provides access to configuration values.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.4
+ */
+public class Configuration
+{
+    /**
+     * System property which can point to a file or URL containing configuration properties to load.
+     *
+     * @since 2.7
+     */
+    public static final String JLINE_CONFIGURATION = "jline.configuration";
+
+    /**
+     * Default configuration file name loaded from user's home directory.
+     */
+    public static final String JLINE_RC = ".jline.rc";
+
+    private static volatile Properties properties;
+
+    private static Properties initProperties() {
+        URL url = determineUrl();
+        Properties props = new Properties();
+        try {
+            loadProperties(url, props);
+        }
+        catch (IOException e) {
+            // debug here instead of warn, as this can happen normally if default jline.rc file is missing
+            Log.debug("Unable to read configuration from: ", url, e);
+        }
+        return props;
+    }
+
+    private static void loadProperties(final URL url, final Properties props) throws IOException {
+        Log.debug("Loading properties from: ", url);
+        InputStream input = url.openStream();
+        try {
+            props.load(new BufferedInputStream(input));
+        }
+        finally {
+            try {
+                input.close();
+            }
+            catch (IOException e) {
+                // ignore
+            }
+        }
+
+        if (Log.DEBUG) {
+            Log.debug("Loaded properties:");
+            for (Map.Entry<Object,Object> entry : props.entrySet()) {
+                Log.debug("  ", entry.getKey(), "=", entry.getValue());
+            }
+        }
+    }
+
+    private static URL determineUrl() {
+        // See if user has customized the configuration location via sysprop
+        String tmp = System.getProperty(JLINE_CONFIGURATION);
+        if (tmp != null) {
+            return Urls.create(tmp);
+        }
+        else {
+            // Otherwise try the default
+            File file = new File(getUserHome(), JLINE_RC);
+            return Urls.create(file);
+        }
+    }
+
+    /**
+     * @since 2.7
+     */
+    public static void reset() {
+        Log.debug("Resetting");
+        properties = null;
+
+        // force new properties to load
+        getProperties();
+    }
+
+    /**
+     * @since 2.7
+     */
+    public static Properties getProperties() {
+        // Not sure its worth to guard this with any synchronization, volatile field probably sufficient
+        if (properties == null) {
+            properties = initProperties();
+        }
+        return properties;
+    }
+
+    public static String getString(final String name, final String defaultValue) {
+        checkNotNull(name);
+
+        String value;
+
+        // Check sysprops first, it always wins
+        value = System.getProperty(name);
+
+        if (value == null) {
+            // Next try userprops
+            value = getProperties().getProperty(name);
+
+            if (value == null) {
+                // else use the default
+                value = defaultValue;
+            }
+        }
+
+        return value;
+    }
+
+    public static String getString(final String name) {
+        return getString(name, null);
+    }
+
+    public static boolean getBoolean(final String name, final boolean defaultValue) {
+        String value = getString(name);
+        if (value == null) {
+            return defaultValue;
+        }
+        return value.length() == 0
+            || value.equalsIgnoreCase("1")
+            || value.equalsIgnoreCase("on")
+            || value.equalsIgnoreCase("true");
+    }
+
+    /**
+     * @since 2.6
+     */
+    public static int getInteger(final String name, final int defaultValue) {
+        String str = getString(name);
+        if (str == null) {
+            return defaultValue;
+        }
+        return Integer.parseInt(str);
+    }
+
+    /**
+     * @since 2.6
+     */
+    public static long getLong(final String name, final long defaultValue) {
+        String str = getString(name);
+        if (str == null) {
+            return defaultValue;
+        }
+        return Long.parseLong(str);
+    }
+
+    //
+    // System property helpers
+    //
+
+    /**
+     * @since 2.7
+     */
+    public static String getLineSeparator() {
+        return System.getProperty("line.separator");
+    }
+
+    public static File getUserHome() {
+        return new File(System.getProperty("user.home"));
+    }
+
+    public static String getOsName() {
+        return System.getProperty("os.name").toLowerCase();
+    }
+
+    /**
+     * @since 2.7
+     */
+    public static boolean isWindows() {
+        return getOsName().startsWith("windows");
+    }
+
+    // FIXME: Sort out use of property access of file.encoding in InputStreamReader, consolidate should configuration access here
+
+    public static String getFileEncoding() {
+        return System.getProperty("file.encoding");
+    }
+
+    /**
+     * Get the default encoding.  Will first look at the LC_CTYPE environment variable, then the input.encoding
+     * system property, then the default charset according to the JVM.
+     *
+     * @return The default encoding to use when none is specified.
+     */
+    public static String getEncoding() {
+        // LC_CTYPE is usually in the form en_US.UTF-8
+        String envEncoding = extractEncodingFromCtype(System.getenv("LC_CTYPE"));
+        if (envEncoding != null) {
+            return envEncoding;
+        }
+        return System.getProperty("input.encoding", Charset.defaultCharset().name());
+    }
+
+    /**
+     * Parses the LC_CTYPE value to extract the encoding according to the POSIX standard, which says that the LC_CTYPE
+     * environment variable may be of the format <code>[language[_territory][.codeset][@modifier]]</code>
+     *
+     * @param ctype The ctype to parse, may be null
+     * @return The encoding, if one was present, otherwise null
+     */
+    static String extractEncodingFromCtype(String ctype) {
+        if (ctype != null && ctype.indexOf('.') > 0) {
+            String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1);
+            if (encodingAndModifier.indexOf('@') > 0) {
+                return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@'));
+            } else {
+                return encodingAndModifier;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+
+/**
+ *
+ * NOTE for JLine: the default InputStreamReader that comes from the JRE
+ * usually read more bytes than needed from the input stream, which
+ * is not usable in a character per character model used in the console.
+ * We thus use the harmony code which only reads the minimal number of bytes,
+ * with a modification to ensure we can read larger characters (UTF-16 has
+ * up to 4 bytes, and UTF-32, rare as it is, may have up to 8).
+ */
+/**
+ * A class for turning a byte stream into a character stream. Data read from the
+ * source input stream is converted into characters by either a default or a
+ * provided character converter. The default encoding is taken from the
+ * "file.encoding" system property. {@code InputStreamReader} contains a buffer
+ * of bytes read from the source stream and converts these into characters as
+ * needed. The buffer size is 8K.
+ *
+ * @see OutputStreamWriter
+ */
+public class InputStreamReader extends Reader {
+    private InputStream in;
+
+    private static final int BUFFER_SIZE = 8192;
+
+    private boolean endOfInput = false;
+
+    String encoding;
+
+    CharsetDecoder decoder;
+
+    ByteBuffer bytes = ByteBuffer.allocate(BUFFER_SIZE);
+
+    /**
+     * Constructs a new {@code InputStreamReader} on the {@link InputStream}
+     * {@code in}. This constructor sets the character converter to the encoding
+     * specified in the "file.encoding" property and falls back to ISO 8859_1
+     * (ISO-Latin-1) if the property doesn't exist.
+     *
+     * @param in
+     *            the input stream from which to read characters.
+     */
+    public InputStreamReader(InputStream in) {
+        super(in);
+        this.in = in;
+        // FIXME: This should probably use Configuration.getFileEncoding()
+        encoding = System.getProperty("file.encoding", "ISO8859_1"); //$NON-NLS-1$//$NON-NLS-2$
+        decoder = Charset.forName(encoding).newDecoder().onMalformedInput(
+                CodingErrorAction.REPLACE).onUnmappableCharacter(
+                CodingErrorAction.REPLACE);
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in}. The
+     * character converter that is used to decode bytes into characters is
+     * identified by name by {@code enc}. If the encoding cannot be found, an
+     * UnsupportedEncodingException error is thrown.
+     *
+     * @param in
+     *            the InputStream from which to read characters.
+     * @param enc
+     *            identifies the character converter to use.
+     * @throws NullPointerException
+     *             if {@code enc} is {@code null}.
+     * @throws UnsupportedEncodingException
+     *             if the encoding specified by {@code enc} cannot be found.
+     */
+    public InputStreamReader(InputStream in, final String enc)
+            throws UnsupportedEncodingException {
+        super(in);
+        if (enc == null) {
+            throw new NullPointerException();
+        }
+        this.in = in;
+        try {
+            decoder = Charset.forName(enc).newDecoder().onMalformedInput(
+                    CodingErrorAction.REPLACE).onUnmappableCharacter(
+                    CodingErrorAction.REPLACE);
+        } catch (IllegalArgumentException e) {
+            throw (UnsupportedEncodingException)
+                    new UnsupportedEncodingException(enc).initCause(e);
+        }
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in} and
+     * CharsetDecoder {@code dec}.
+     *
+     * @param in
+     *            the source InputStream from which to read characters.
+     * @param dec
+     *            the CharsetDecoder used by the character conversion.
+     */
+    public InputStreamReader(InputStream in, CharsetDecoder dec) {
+        super(in);
+        dec.averageCharsPerByte();
+        this.in = in;
+        decoder = dec;
+        bytes.limit(0);
+    }
+
+    /**
+     * Constructs a new InputStreamReader on the InputStream {@code in} and
+     * Charset {@code charset}.
+     *
+     * @param in
+     *            the source InputStream from which to read characters.
+     * @param charset
+     *            the Charset that defines the character converter
+     */
+    public InputStreamReader(InputStream in, Charset charset) {
+        super(in);
+        this.in = in;
+        decoder = charset.newDecoder().onMalformedInput(
+                CodingErrorAction.REPLACE).onUnmappableCharacter(
+                CodingErrorAction.REPLACE);
+        bytes.limit(0);
+    }
+
+    /**
+     * Closes this reader. This implementation closes the source InputStream and
+     * releases all local storage.
+     *
+     * @throws IOException
+     *             if an error occurs attempting to close this reader.
+     */
+    @Override
+    public void close() throws IOException {
+        synchronized (lock) {
+            decoder = null;
+            if (in != null) {
+                in.close();
+                in = null;
+            }
+        }
+    }
+
+    /**
+     * Returns the name of the encoding used to convert bytes into characters.
+     * The value {@code null} is returned if this reader has been closed.
+     *
+     * @return the name of the character converter or {@code null} if this
+     *         reader is closed.
+     */
+    public String getEncoding() {
+        if (!isOpen()) {
+            return null;
+        }
+        return encoding;
+    }
+
+    /**
+     * Reads a single character from this reader and returns it as an integer
+     * with the two higher-order bytes set to 0. Returns -1 if the end of the
+     * reader has been reached. The byte value is either obtained from
+     * converting bytes in this reader's buffer or by first filling the buffer
+     * from the source InputStream and then reading from the buffer.
+     *
+     * @return the character read or -1 if the end of the reader has been
+     *         reached.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public int read() throws IOException {
+        synchronized (lock) {
+            if (!isOpen()) {
+                throw new IOException("InputStreamReader is closed.");
+            }
+
+            char buf[] = new char[4];
+            return read(buf, 0, 4) != -1 ? Character.codePointAt(buf, 0) : -1;
+        }
+    }
+
+    /**
+     * Reads at most {@code length} characters from this reader and stores them
+     * at position {@code offset} in the character array {@code buf}. Returns
+     * the number of characters actually read or -1 if the end of the reader has
+     * been reached. The bytes are either obtained from converting bytes in this
+     * reader's buffer or by first filling the buffer from the source
+     * InputStream and then reading from the buffer.
+     *
+     * @param buf
+     *            the array to store the characters read.
+     * @param offset
+     *            the initial position in {@code buf} to store the characters
+     *            read from this reader.
+     * @param length
+     *            the maximum number of characters to read.
+     * @return the number of characters read or -1 if the end of the reader has
+     *         been reached.
+     * @throws IndexOutOfBoundsException
+     *             if {@code offset < 0} or {@code length < 0}, or if
+     *             {@code offset + length} is greater than the length of
+     *             {@code buf}.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public int read(char[] buf, int offset, int length) throws IOException {
+        synchronized (lock) {
+            if (!isOpen()) {
+                throw new IOException("InputStreamReader is closed.");
+            }
+            if (offset < 0 || offset > buf.length - length || length < 0) {
+                throw new IndexOutOfBoundsException();
+            }
+            if (length == 0) {
+                return 0;
+            }
+
+            CharBuffer out = CharBuffer.wrap(buf, offset, length);
+            CoderResult result = CoderResult.UNDERFLOW;
+
+            // bytes.remaining() indicates number of bytes in buffer
+            // when 1-st time entered, it'll be equal to zero
+            boolean needInput = !bytes.hasRemaining();
+
+            while (out.hasRemaining()) {
+                // fill the buffer if needed
+                if (needInput) {
+                    try {
+                        if ((in.available() == 0)
+                            && (out.position() > offset)) {
+                            // we could return the result without blocking read
+                            break;
+                        }
+                    } catch (IOException e) {
+                        // available didn't work so just try the read
+                    }
+
+                    int to_read = bytes.capacity() - bytes.limit();
+                    int off = bytes.arrayOffset() + bytes.limit();
+                    int was_red = in.read(bytes.array(), off, to_read);
+
+                    if (was_red == -1) {
+                        endOfInput = true;
+                        break;
+                    } else if (was_red == 0) {
+                        break;
+                    }
+                    bytes.limit(bytes.limit() + was_red);
+                    needInput = false;
+                }
+
+                // decode bytes
+                result = decoder.decode(bytes, out, false);
+
+                if (result.isUnderflow()) {
+                    // compact the buffer if no space left
+                    if (bytes.limit() == bytes.capacity()) {
+                        bytes.compact();
+                        bytes.limit(bytes.position());
+                        bytes.position(0);
+                    }
+                    needInput = true;
+                } else {
+                    break;
+                }
+            }
+
+            if (result == CoderResult.UNDERFLOW && endOfInput) {
+                result = decoder.decode(bytes, out, true);
+                decoder.flush(out);
+                decoder.reset();
+            }
+            if (result.isMalformed()) {
+                throw new MalformedInputException(result.length());
+            } else if (result.isUnmappable()) {
+                throw new UnmappableCharacterException(result.length());
+            }
+
+            return out.position() - offset == 0 ? -1 : out.position() - offset;
+        }
+    }
+
+    /*
+     * Answer a boolean indicating whether or not this InputStreamReader is
+     * open.
+     */
+    private boolean isOpen() {
+        return in != null;
+    }
+
+    /**
+     * Indicates whether this reader is ready to be read without blocking. If
+     * the result is {@code true}, the next {@code read()} will not block. If
+     * the result is {@code false} then this reader may or may not block when
+     * {@code read()} is called. This implementation returns {@code true} if
+     * there are bytes available in the buffer or the source stream has bytes
+     * available.
+     *
+     * @return {@code true} if the receiver will not block when {@code read()}
+     *         is called, {@code false} if unknown or blocking will occur.
+     * @throws IOException
+     *             if this reader is closed or some other I/O error occurs.
+     */
+    @Override
+    public boolean ready() throws IOException {
+        synchronized (lock) {
+            if (in == null) {
+                throw new IOException("InputStreamReader is closed.");
+            }
+            try {
+                return bytes.hasRemaining() || in.available() > 0;
+            } catch (IOException e) {
+                return false;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.PrintStream;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Internal logger.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.0
+ */
+public final class Log
+{
+    ///CLOVER:OFF
+
+    public static enum Level
+    {
+        TRACE,
+        DEBUG,
+        INFO,
+        WARN,
+        ERROR
+    }
+
+    @SuppressWarnings({"StringConcatenation"})
+    public static final boolean TRACE = Boolean.getBoolean(Log.class.getName() + ".trace");
+
+    @SuppressWarnings({"StringConcatenation"})
+    public static final boolean DEBUG = TRACE || Boolean.getBoolean(Log.class.getName() + ".debug");
+
+    private static PrintStream output = System.err;
+
+    public static PrintStream getOutput() {
+        return output;
+    }
+
+    public static void setOutput(final PrintStream out) {
+        output = checkNotNull(out);
+    }
+
+    /**
+     * Helper to support rendering messages.
+     */
+    @TestAccessible
+    static void render(final PrintStream out, final Object message) {
+        if (message.getClass().isArray()) {
+            Object[] array = (Object[]) message;
+
+            out.print("[");
+            for (int i = 0; i < array.length; i++) {
+                out.print(array[i]);
+                if (i + 1 < array.length) {
+                    out.print(",");
+                }
+            }
+            out.print("]");
+        }
+        else {
+            out.print(message);
+        }
+    }
+
+    @TestAccessible
+    static void log(final Level level, final Object... messages) {
+        //noinspection SynchronizeOnNonFinalField
+        synchronized (output) {
+            output.format("[%s] ", level);
+
+            for (int i=0; i<messages.length; i++) {
+                // Special handling for the last message if its a throwable, render its stack on the next line
+                if (i + 1 == messages.length && messages[i] instanceof Throwable) {
+                    output.println();
+                    ((Throwable)messages[i]).printStackTrace(output);
+                }
+                else {
+                    render(output, messages[i]);
+                }
+            }
+
+            output.println();
+            output.flush();
+        }
+    }
+
+    public static void trace(final Object... messages) {
+        if (TRACE) {
+            log(Level.TRACE, messages);
+        }
+    }
+
+    public static void debug(final Object... messages) {
+        if (TRACE || DEBUG) {
+            log(Level.DEBUG, messages);
+        }
+    }
+
+    /**
+     * @since 2.7
+     */
+    public static void info(final Object... messages) {
+        log(Level.INFO, messages);
+    }
+
+    public static void warn(final Object... messages) {
+        log(Level.WARN, messages);
+    }
+
+    public static void error(final Object... messages) {
+        log(Level.ERROR, messages);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/NonBlockingInputStream.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class wraps a regular input stream and allows it to appear as if it
+ * is non-blocking; that is, reads can be performed against it that timeout
+ * if no data is seen for a period of time.  This effect is achieved by having
+ * a separate thread perform all non-blocking read requests and then
+ * waiting on the thread to complete.
+ *
+ * <p>VERY IMPORTANT NOTES
+ * <ul>
+ *   <li> This class is not thread safe. It expects at most one reader.
+ *   <li> The {@link #shutdown()} method must be called in order to shut down
+ *          the thread that handles blocking I/O.
+ * </ul>
+ * @since 2.7
+ * @author Scott C. Gray <scottgray1@gmail.com>
+ */
+public class NonBlockingInputStream
+    extends InputStream
+    implements Runnable
+{
+    private InputStream in;               // The actual input stream
+    private int    ch   = -2;             // Recently read character
+
+    private boolean     threadIsReading      = false;
+    private boolean     isShutdown           = false;
+    private IOException exception            = null;
+    private boolean     nonBlockingEnabled;
+
+    /**
+     * Creates a <code>NonBlockingInputStream</code> out of a normal blocking
+     * stream. Note that this call also spawn a separate thread to perform the
+     * blocking I/O on behalf of the thread that is using this class. The
+     * {@link #shutdown()} method must be called in order to shut this thread down.
+     * @param in The input stream to wrap
+     * @param isNonBlockingEnabled If true, then the non-blocking methods
+     *   {@link #read(long)} and {@link #peek(long)} will be available and,
+     *   more importantly, the thread will be started to provide support for the
+     *   feature.  If false, then this class acts as a clean-passthru for the
+     *   underlying I/O stream and provides very little overhead.
+     */
+    public NonBlockingInputStream (InputStream in, boolean isNonBlockingEnabled) {
+        this.in                 = in;
+        this.nonBlockingEnabled = isNonBlockingEnabled;
+
+        if (isNonBlockingEnabled) {
+            Thread t = new Thread(this);
+            t.setName("NonBlockingInputStreamThread");
+            t.setDaemon(true);
+            t.start();
+        }
+    }
+
+    /**
+     * Shuts down the thread that is handling blocking I/O. Note that if the
+     * thread is currently blocked waiting for I/O it will not actually
+     * shut down until the I/O is received.  Shutting down the I/O thread
+     * does not prevent this class from being used, but causes the
+     * non-blocking methods to fail if called and causes {@link #isNonBlockingEnabled()}
+     * to return false.
+     */
+    public synchronized void shutdown() {
+        if (!isShutdown && nonBlockingEnabled) {
+            isShutdown = true;
+            notify();
+        }
+    }
+
+    /**
+     * Non-blocking is considered enabled if the feature is enabled and the
+     * I/O thread has not been shut down.
+     * @return true if non-blocking mode is enabled.
+     */
+    public boolean isNonBlockingEnabled() {
+        return nonBlockingEnabled && !isShutdown;
+    }
+
+    @Override
+    public void close() throws IOException {
+        /*
+         * The underlying input stream is closed first. This means that if the
+         * I/O thread was blocked waiting on input, it will be woken for us.
+         */
+        in.close();
+        shutdown();
+    }
+
+    @Override
+    public int read() throws IOException {
+        if (nonBlockingEnabled)
+            return read(0L, false);
+        return in.read ();
+    }
+
+    /**
+     * Peeks to see if there is a byte waiting in the input stream without
+     * actually consuming the byte.
+     *
+     * @param timeout The amount of time to wait, 0 == forever
+     * @return -1 on eof, -2 if the timeout expired with no available input
+     *   or the character that was read (without consuming it).
+     * @throws IOException
+     */
+    public int peek(long timeout) throws IOException {
+        if (!nonBlockingEnabled || isShutdown) {
+            throw new UnsupportedOperationException ("peek() "
+                + "cannot be called as non-blocking operation is disabled");
+        }
+        return read(timeout, true);
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     * @param timeout The amount of time to wait for the character
+     * @return The character read, -1 if EOF is reached, or -2 if the
+     *   read timed out.
+     * @throws IOException
+     */
+    public int read(long timeout) throws IOException {
+        if (!nonBlockingEnabled || isShutdown) {
+            throw new UnsupportedOperationException ("read() with timeout "
+                + "cannot be called as non-blocking operation is disabled");
+        }
+        return read(timeout, false);
+    }
+
+    /**
+     * Attempts to read a character from the input stream for a specific
+     * period of time.
+     * @param timeout The amount of time to wait for the character
+     * @return The character read, -1 if EOF is reached, or -2 if the
+     *   read timed out.
+     * @throws IOException
+     */
+    private synchronized int read(long timeout, boolean isPeek) throws IOException {
+        /*
+         * If the thread hit an IOException, we report it.
+         */
+        if (exception != null) {
+            assert ch == -2;
+            IOException toBeThrown = exception;
+            if (!isPeek)
+                exception = null;
+            throw toBeThrown;
+        }
+
+        /*
+         * If there was a pending character from the thread, then
+         * we send it. If the timeout is 0L or the thread was shut down
+         * then do a local read.
+         */
+        if (ch >= -1) {
+            assert exception == null;
+        }
+        else if ((timeout == 0L || isShutdown) && !threadIsReading) {
+            ch = in.read();
+        }
+        else {
+            /*
+             * If the thread isn't reading already, then ask it to do so.
+             */
+            if (!threadIsReading) {
+                threadIsReading = true;
+                notify();
+            }
+
+            boolean isInfinite = (timeout <= 0L);
+
+            /*
+             * So the thread is currently doing the reading for us. So
+             * now we play the waiting game.
+             */
+            while (isInfinite || timeout > 0L)  {
+                long start = System.currentTimeMillis ();
+
+                try {
+                    wait(timeout);
+                }
+                catch (InterruptedException e) {
+                    /* IGNORED */
+                }
+
+                if (exception != null) {
+                    assert ch == -2;
+
+                    IOException toBeThrown = exception;
+                    if (!isPeek)
+                        exception = null;
+                    throw toBeThrown;
+                }
+
+                if (ch >= -1) {
+                    assert exception == null;
+                    break;
+                }
+
+                if (!isInfinite) {
+                    timeout -= System.currentTimeMillis() - start;
+                }
+            }
+        }
+
+        /*
+         * ch is the character that was just read. Either we set it because
+         * a local read was performed or the read thread set it (or failed to
+         * change it).  We will return it's value, but if this was a peek
+         * operation, then we leave it in place.
+         */
+        int ret = ch;
+        if (!isPeek) {
+            ch = -2;
+        }
+        return ret;
+    }
+
+    /**
+     * This version of read() is very specific to jline's purposes, it
+     * will always always return a single byte at a time, rather than filling
+     * the entire buffer.
+     */
+    @Override
+    public int read (byte[] b, int off, int len) throws IOException {
+        if (b == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || len < 0 || len > b.length - off) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return 0;
+        }
+
+        int c;
+        if (nonBlockingEnabled)
+            c = this.read(0L);
+        else
+            c = in.read();
+
+        if (c == -1) {
+            return -1;
+        }
+        b[off] = (byte)c;
+        return 1;
+    }
+
+    //@Override
+    public void run () {
+        Log.debug("NonBlockingInputStream start");
+        boolean needToShutdown = false;
+        boolean needToRead = false;
+
+        while (!needToShutdown) {
+
+            /*
+             * Synchronize to grab variables accessed by both this thread
+             * and the accessing thread.
+             */
+            synchronized (this) {
+                needToShutdown = this.isShutdown;
+                needToRead     = this.threadIsReading;
+
+                try {
+                    /*
+                     * Nothing to do? Then wait.
+                     */
+                    if (!needToShutdown && !needToRead) {
+                        wait(0);
+                    }
+                }
+                catch (InterruptedException e) {
+                    /* IGNORED */
+                }
+            }
+
+            /*
+             * We're not shutting down, but we need to read. This cannot
+             * happen while we are holding the lock (which we aren't now).
+             */
+            if (!needToShutdown && needToRead) {
+                int          charRead = -2;
+                IOException  failure = null;
+                try {
+                    charRead = in.read();
+                }
+                catch (IOException e) {
+                    failure = e;
+                }
+
+                /*
+                 * Re-grab the lock to update the state.
+                 */
+                synchronized (this) {
+                    exception       = failure;
+                    ch              = charRead;
+                    threadIsReading = false;
+                    notify();
+                }
+            }
+        }
+
+        Log.debug("NonBlockingInputStream shutdown");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.lang.annotation.*;
+
+/**
+ * Marker for reference which can be a null value.
+ *
+ * @since 2.7
+ */
+@Documented
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
+public @interface Nullable
+{
+    String value() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+// Some bits lifted from Guava's ( http://code.google.com/p/guava-libraries/ ) Preconditions.
+
+/**
+ * Preconditions.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.7
+ */
+public class Preconditions
+{
+    public static <T> T checkNotNull(final T reference) {
+        if (reference == null) {
+            throw new NullPointerException();
+        }
+        return reference;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Manages the JLine shutdown-hook thread and tasks to execute on shutdown.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @since 2.7
+ */
+public class ShutdownHooks
+{
+    public static final String JLINE_SHUTDOWNHOOK = "jline.shutdownhook";
+
+    private static final boolean enabled = Configuration.getBoolean(JLINE_SHUTDOWNHOOK, true);
+
+    private static final List<Task> tasks = new ArrayList<Task>();
+
+    private static Thread hook;
+
+    public static synchronized <T extends Task> T add(final T task) {
+        checkNotNull(task);
+
+        // If not enabled ignore
+        if (!enabled) {
+            Log.debug("Shutdown-hook is disabled; not installing: ", task);
+            return task;
+        }
+
+        // Install the hook thread if needed
+        if (hook == null) {
+            hook = addHook(new Thread("JLine Shutdown Hook")
+            {
+                @Override
+                public void run() {
+                    runTasks();
+                }
+            });
+        }
+
+        // Track the task
+        Log.debug("Adding shutdown-hook task: ", task);
+        tasks.add(task);
+
+        return task;
+    }
+
+    private static synchronized void runTasks() {
+        Log.debug("Running all shutdown-hook tasks");
+
+        // Iterate through copy of tasks list
+        for (Task task : tasks.toArray(new Task[tasks.size()])) {
+            Log.debug("Running task: ", task);
+            try {
+                task.run();
+            }
+            catch (Throwable e) {
+                Log.warn("Task failed", e);
+            }
+        }
+
+        tasks.clear();
+    }
+
+    private static Thread addHook(final Thread thread) {
+        Log.debug("Registering shutdown-hook: ", thread);
+        try {
+            Runtime.getRuntime().addShutdownHook(thread);
+        }
+        catch (AbstractMethodError e) {
+            // JDK 1.3+ only method. Bummer.
+            Log.debug("Failed to register shutdown-hook", e);
+        }
+        return thread;
+    }
+
+    public static synchronized void remove(final Task task) {
+        checkNotNull(task);
+
+        // ignore if not enabled or hook never installed
+        if (!enabled || hook == null) {
+            return;
+        }
+
+        // Drop the task
+        tasks.remove(task);
+
+        // If there are no more tasks, then remove the hook thread
+        if (tasks.isEmpty()) {
+            removeHook(hook);
+            hook = null;
+        }
+    }
+
+    private static void removeHook(final Thread thread) {
+        Log.debug("Removing shutdown-hook: ", thread);
+
+        try {
+            Runtime.getRuntime().removeShutdownHook(thread);
+        }
+        catch (AbstractMethodError e) {
+            // JDK 1.3+ only method. Bummer.
+            Log.debug("Failed to remove shutdown-hook", e);
+        }
+        catch (IllegalStateException e) {
+            // The VM is shutting down, not a big deal; ignore
+        }
+    }
+
+    /**
+     * Essentially a {@link Runnable} which allows running to throw an exception.
+     */
+    public static interface Task
+    {
+        void run() throws Exception;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static jdk.internal.jline.internal.Preconditions.checkNotNull;
+
+/**
+ * Provides access to terminal line settings via <tt>stty</tt>.
+ *
+ * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
+ * @author <a href="mailto:dwkemp@gmail.com">Dale Kemp</a>
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:jbonofre@apache.org">Jean-Baptiste Onofr\u00E9</a>
+ * @since 2.0
+ */
+public final class TerminalLineSettings
+{
+    public static final String JLINE_STTY = "jline.stty";
+
+    public static final String DEFAULT_STTY = "stty";
+
+    public static final String JLINE_SH = "jline.sh";
+
+    public static final String DEFAULT_SH = "sh";
+
+    private String sttyCommand;
+
+    private String shCommand;
+
+    private String config;
+    private String initialConfig;
+
+    private long configLastFetched;
+
+    public TerminalLineSettings() throws IOException, InterruptedException {
+        sttyCommand = Configuration.getString(JLINE_STTY, DEFAULT_STTY);
+        shCommand = Configuration.getString(JLINE_SH, DEFAULT_SH);
+        initialConfig = get("-g").trim();
+        config = get("-a");
+        configLastFetched = System.currentTimeMillis();
+
+        Log.debug("Config: ", config);
+
+        // sanity check
+        if (config.length() == 0) {
+            throw new IOException(MessageFormat.format("Unrecognized stty code: {0}", config));
+        }
+    }
+
+    public String getConfig() {
+        return config;
+    }
+
+    public void restore() throws IOException, InterruptedException {
+        set(initialConfig);
+    }
+
+    public String get(final String args) throws IOException, InterruptedException {
+        return stty(args);
+    }
+
+    public void set(final String args) throws IOException, InterruptedException {
+        stty(args);
+    }
+
+    /**
+     * <p>
+     * Get the value of a stty property, including the management of a cache.
+     * </p>
+     *
+     * @param name the stty property.
+     * @return the stty property value.
+     */
+    public int getProperty(String name) {
+        checkNotNull(name);
+        long currentTime = System.currentTimeMillis();
+        try {
+            // tty properties are cached so we don't have to worry too much about getting term width/height
+            if (config == null || currentTime - configLastFetched > 1000) {
+                config = get("-a");
+            }
+        } catch (Exception e) {
+            if (e instanceof InterruptedException) {
+                Thread.currentThread().interrupt();
+            }
+            Log.debug("Failed to query stty ", name, "\n", e);
+            if (config == null) {
+                return -1;
+            }
+        }
+
+        // always update the last fetched time and try to parse the output
+        if (currentTime - configLastFetched > 1000) {
+            configLastFetched = currentTime;
+        }
+
+        return getProperty(name, config);
+    }
+
+    /**
+     * <p>
+     * Parses a stty output (provided by stty -a) and return the value of a given property.
+     * </p>
+     *
+     * @param name property name.
+     * @param stty string resulting of stty -a execution.
+     * @return value of the given property.
+     */
+    protected static int getProperty(String name, String stty) {
+        // try the first kind of regex
+        Pattern pattern = Pattern.compile(name + "\\s+=\\s+(.*?)[;\\n\\r]");
+        Matcher matcher = pattern.matcher(stty);
+        if (!matcher.find()) {
+            // try a second kind of regex
+            pattern = Pattern.compile(name + "\\s+([^;]*)[;\\n\\r]");
+            matcher = pattern.matcher(stty);
+            if (!matcher.find()) {
+                // try a second try of regex
+                pattern = Pattern.compile("(\\S*)\\s+" + name);
+                matcher = pattern.matcher(stty);
+                if (!matcher.find()) {
+                    return -1;
+                }
+            }
+        }
+        return parseControlChar(matcher.group(1));
+    }
+
+    private static int parseControlChar(String str) {
+        // under
+        if ("<undef>".equals(str)) {
+            return -1;
+        }
+        // octal
+        if (str.charAt(0) == '0') {
+            return Integer.parseInt(str, 8);
+        }
+        // decimal
+        if (str.charAt(0) >= '1' && str.charAt(0) <= '9') {
+            return Integer.parseInt(str, 10);
+        }
+        // control char
+        if (str.charAt(0) == '^') {
+            if (str.charAt(1) == '?') {
+                return 127;
+            } else {
+                return str.charAt(1) - 64;
+            }
+        } else if (str.charAt(0) == 'M' && str.charAt(1) == '-') {
+            if (str.charAt(2) == '^') {
+                if (str.charAt(3) == '?') {
+                    return 127 + 128;
+                } else {
+                    return str.charAt(3) - 64 + 128;
+                }
+            } else {
+                return str.charAt(2) + 128;
+            }
+        } else {
+            return str.charAt(0);
+        }
+    }
+
+    private String stty(final String args) throws IOException, InterruptedException {
+        checkNotNull(args);
+        return exec(String.format("%s %s < /dev/tty", sttyCommand, args));
+    }
+
+    private String exec(final String cmd) throws IOException, InterruptedException {
+        checkNotNull(cmd);
+        return exec(shCommand, "-c", cmd);
+    }
+
+    private String exec(final String... cmd) throws IOException, InterruptedException {
+        checkNotNull(cmd);
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+        Log.trace("Running: ", cmd);
+
+        Process p = Runtime.getRuntime().exec(cmd);
+
+        InputStream in = null;
+        InputStream err = null;
+        OutputStream out = null;
+        try {
+            int c;
+            in = p.getInputStream();
+            while ((c = in.read()) != -1) {
+                bout.write(c);
+            }
+            err = p.getErrorStream();
+            while ((c = err.read()) != -1) {
+                bout.write(c);
+            }
+            out = p.getOutputStream();
+            p.waitFor();
+        }
+        finally {
+            close(in, out, err);
+        }
+
+        String result = bout.toString();
+
+        Log.trace("Result: ", result);
+
+        return result;
+    }
+
+    private static void close(final Closeable... closeables) {
+        for (Closeable c : closeables) {
+            try {
+                c.close();
+            }
+            catch (Exception e) {
+                // Ignore
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Marker annotation for members which are exposed for testing access.
+ *
+ * @since 2.7
+ */
+@Retention(RUNTIME)
+@Target({TYPE, CONSTRUCTOR, METHOD, FIELD, PARAMETER})
+@Documented
+public @interface TestAccessible
+{
+    // empty
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+package jdk.internal.jline.internal;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * URL helpers.
+ *
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
+ * @since 2.7
+ */
+public class Urls
+{
+    public static URL create(final String input) {
+        if (input == null) {
+            return null;
+        }
+        try {
+            return new URL(input);
+        }
+        catch (MalformedURLException e) {
+            return create(new File(input));
+        }
+    }
+
+    public static URL create(final File file) {
+        try {
+            return file != null ? file.toURI().toURL() : null;
+        }
+        catch (MalformedURLException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * Internal support.
+ *
+ * @since 2.0
+ */
+package jdk.internal.jline.internal;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2002-2012, the original author or authors.
+ *
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
+ *
+ * http://www.opensource.org/licenses/bsd-license.php
+ */
+/**
+ * JLine 2.
+ *
+ * @since 2.0
+ */
+package jdk.internal.jline;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jdk_internal_jline_WindowsTerminal.h"
+
+#include <stdlib.h>
+#include <Wincon.h>
+#include <Winuser.h>
+
+static jclass recordClass;
+static jmethodID recordConstructor;
+
+JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_initIDs
+  (JNIEnv *env, jclass) {
+    jclass cls = env->FindClass("jdk/internal/jline/WindowsTerminal$KEY_EVENT_RECORD");
+    CHECK_NULL(cls);
+    recordClass = (jclass) env->NewGlobalRef(cls);
+    CHECK_NULL(recordClass);
+    recordConstructor = env->GetMethodID(cls, "<init>", "(ZCIII)V");
+    CHECK_NULL(recordConstructor);
+}
+
+JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleMode
+  (JNIEnv *, jobject) {
+    HANDLE hStdIn;
+    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+        return -1;
+    }
+    DWORD fdwMode;
+    if (! GetConsoleMode(hStdIn, &fdwMode)) {
+        return -1;
+    }
+    return fdwMode;
+}
+
+JNIEXPORT void JNICALL Java_jdk_internal_jline_WindowsTerminal_setConsoleMode
+  (JNIEnv *, jobject, jint mode) {
+    HANDLE hStdIn;
+    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+        return ;
+    }
+    DWORD fdwMode = mode;
+    SetConsoleMode(hStdIn, fdwMode);
+}
+
+JNIEXPORT jobject JNICALL Java_jdk_internal_jline_WindowsTerminal_readKeyEvent
+  (JNIEnv *env, jobject) {
+    HANDLE hStdIn;
+    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+        return NULL;
+    }
+    INPUT_RECORD record;
+    DWORD n;
+    while (TRUE) {
+        if (ReadConsoleInput(hStdIn, &record, 1, &n) == 0) {
+            return NULL;
+        }
+        if (record.EventType == KEY_EVENT) {
+            jclass clazz = env->FindClass("jdk/internal/jline/WindowsTerminal$KEY_EVENT_RECORD");
+            jmethodID constr = env->GetMethodID(clazz, "<init>", "(ZCIII)V");
+            return env->NewObject(recordClass,
+                                  recordConstructor,
+                                  record.Event.KeyEvent.bKeyDown,
+                                  record.Event.KeyEvent.uChar.UnicodeChar,
+                                  record.Event.KeyEvent.dwControlKeyState,
+                                  record.Event.KeyEvent.wVirtualKeyCode,
+                                  record.Event.KeyEvent.wRepeatCount);
+        }
+        continue;
+    }
+}
+
+JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleOutputCodepage
+  (JNIEnv *, jobject) {
+    return GetConsoleCP();
+}
+
+JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth
+  (JNIEnv *, jobject) {
+    HANDLE hStdIn;
+    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+        return -1;
+    }
+    CONSOLE_SCREEN_BUFFER_INFO info;
+    if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+        return -1;
+    }
+    return info.dwSize.X;
+}
+
+JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalHeight
+  (JNIEnv *, jobject) {
+    HANDLE hStdIn;
+    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+        return -1;
+    }
+    CONSOLE_SCREEN_BUFFER_INFO info;
+    if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+        return -1;
+    }
+    return info.dwSize.Y;
+}
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Crypt.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Crypt.java	Wed Jul 05 20:41:30 2017 +0200
@@ -377,7 +377,7 @@
      *
      */
 
-    public static void main(String arg[]) {
+    public static void main(String[] arg) {
 
         if (arg.length!=2) {
             System.err.println("usage: Crypt password salt");
@@ -386,7 +386,7 @@
 
         Crypt c = new Crypt();
         try {
-            byte result[] = c.crypt
+            byte[] result = c.crypt
                 (arg[0].getBytes("ISO-8859-1"), arg[1].getBytes("ISO-8859-1"));
             for (int i=0; i<result.length; i++) {
                 System.out.println(" "+i+" "+(char)result[i]);
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java	Wed Jul 05 20:41:30 2017 +0200
@@ -729,8 +729,8 @@
 
         Crypt c = new Crypt();
         try {
-            byte oldCrypt[] = encryptedPassword.getBytes("UTF8");
-            byte newCrypt[] = c.crypt(password.getBytes("UTF8"),
+            byte[] oldCrypt = encryptedPassword.getBytes("UTF8");
+            byte[] newCrypt = c.crypt(password.getBytes("UTF8"),
                                       oldCrypt);
             if (newCrypt.length != oldCrypt.length)
                 return false;
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTLoginModule.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTLoginModule.java	Wed Jul 05 20:41:30 2017 +0200
@@ -81,7 +81,7 @@
     private NTDomainPrincipal userDomain;               // user domain
     private NTSidDomainPrincipal domainSID;             // domain SID
     private NTSidPrimaryGroupPrincipal primaryGroup;    // primary group
-    private NTSidGroupPrincipal groups[];               // supplementary groups
+    private NTSidGroupPrincipal[] groups;               // supplementary groups
     private NTNumericCredential iToken;                 // impersonation token
 
     /**
@@ -194,7 +194,7 @@
         if (ntSystem.getGroupIDs() != null &&
             ntSystem.getGroupIDs().length > 0) {
 
-            String groupSIDs[] = ntSystem.getGroupIDs();
+            String[] groupSIDs = ntSystem.getGroupIDs();
             groups = new NTSidGroupPrincipal[groupSIDs.length];
             for (int i = 0; i < groupSIDs.length; i++) {
                 groups[i] = new NTSidGroupPrincipal(groupSIDs[i]);
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTSystem.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/NTSystem.java	Wed Jul 05 20:41:30 2017 +0200
@@ -40,7 +40,7 @@
     private String domain;
     private String domainSID;
     private String userSID;
-    private String groupIDs[];
+    private String[] groupIDs;
     private String primaryGroupID;
     private long   impersonationToken;
 
--- a/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/FactoryImpl.java	Wed Jul 05 20:41:30 2017 +0200
@@ -38,10 +38,10 @@
   * @author Rosanna Lee
   */
 public final class FactoryImpl implements SaslClientFactory, SaslServerFactory {
-    private static final String myMechs[] = {
+    private static final String[] myMechs = {
         "GSSAPI"};
 
-    private static final int mechPolicies[] = {
+    private static final int[] mechPolicies = {
         PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS|PolicyUtils.NOACTIVE
     };
 
--- a/jdk/test/TEST.groups	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/TEST.groups	Wed Jul 05 20:41:30 2017 +0200
@@ -243,6 +243,7 @@
     javax/xml \
     -javax/xml/crypto \
     jdk/asm \
+    jdk/internal/jline \
     com/sun/jndi \
     com/sun/corba \
     lib/testlibrary \
--- a/jdk/test/java/lang/ProcessHandle/InfoTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -32,24 +32,24 @@
 import java.nio.file.attribute.UserPrincipal;
 import java.time.Duration;
 import java.time.Instant;
-import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Random;
-import java.util.Scanner;
-import java.util.StringTokenizer;
 import java.util.concurrent.TimeUnit;
 
 import jdk.testlibrary.Platform;
+import jdk.testlibrary.Utils;
+
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import org.testng.TestNG;
 
 /*
  * @test
+ * @build jdk.testlibrary.*
  * @library /lib/testlibrary
  * @summary Functions of ProcessHandle.Info
  * @author Roger Riggs
@@ -91,16 +91,16 @@
                 "test runner is included.");
         ProcessHandle self = ProcessHandle.current();
 
-        Duration somecpu = Duration.ofMillis(200L);
-        Instant end = Instant.now().plus(somecpu);
+        Duration someCPU = Duration.ofMillis(200L);
+        Instant end = Instant.now().plus(someCPU);
         while (Instant.now().isBefore(end)) {
             // waste the cpu
         }
         ProcessHandle.Info info = self.info();
         System.out.printf(" info: %s%n", info);
         Optional<Duration> totalCpu = info.totalCpuDuration();
-        if (totalCpu.isPresent() && (totalCpu.get().compareTo(somecpu) < 0)) {
-            Assert.fail("reported cputime less than expected: " + somecpu + ", " +
+        if (totalCpu.isPresent() && (totalCpu.get().compareTo(someCPU) < 0)) {
+            Assert.fail("reported cputime less than expected: " + someCPU + ", " +
                     "actual: " + info.totalCpuDuration());
         }
     }
@@ -111,17 +111,16 @@
     @Test
     public static void test2() {
         try {
-            long cpulooptime = 1 << 8;
+            long cpuLoopTime = 100;             // 100 ms
             String[] extraArgs = {"pid", "parent", "stdin"};
-            Instant beforeStart = Instant.now().truncatedTo(ChronoUnit.SECONDS);
             JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs);
             Instant afterStart = Instant.now();
 
             try (BufferedReader lines = p1.outputReader()) {
                 Duration lastCpu = Duration.ofMillis(0L);
-                for (int j = 0; j < 20; j++) {
+                for (int j = 0; j < 10; j++) {
 
-                    p1.sendAction("cpuloop", cpulooptime);
+                    p1.sendAction("cpuloop", cpuLoopTime);
                     p1.sendAction("cputime", "");
 
                     // Read cputime from child
@@ -187,17 +186,21 @@
                     if (info.totalCpuDuration().isPresent()) {
                         Duration totalCPU = info.totalCpuDuration().get();
                         Duration epsilon = Duration.ofMillis(200L);
-                        Assert.assertTrue(totalCPU.toNanos() > 0L,
-                                "total cpu time expected > 0ms, actual: " + totalCPU);
-                        Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + 10_000_000_000L,
-                                "total cpu time expected < 10s more than previous iteration, actual: " + totalCPU);
                         if (childCpuTime != null) {
                             System.out.printf(" info.totalCPU: %s, childCpuTime: %s, diff: %s%n",
-                                    totalCPU.toNanos(), childCpuTime.toNanos(), childCpuTime.toNanos() - totalCPU.toNanos());
+                                    totalCPU.toNanos(), childCpuTime.toNanos(),
+                                    childCpuTime.toNanos() - totalCPU.toNanos());
                             Assert.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon),
                                     childCpuTime + " should be within " +
                                             epsilon + " of " + totalCPU);
                         }
+                        Assert.assertTrue(totalCPU.toNanos() > 0L,
+                                "total cpu time expected > 0ms, actual: " + totalCPU);
+                        long t = Utils.adjustTimeout(10L);  // Adjusted timeout seconds
+                        Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L,
+                                "total cpu time expected < " + t
+                                        + " seconds more than previous iteration, actual: "
+                                        + (totalCPU.toNanos() - lastCpu.toNanos()));
                         lastCpu = totalCPU;
                     }
 
@@ -209,7 +212,7 @@
                     }
                 }
             }
-            p1.waitFor(5, TimeUnit.SECONDS);
+            p1.waitFor(Utils.adjustTimeout(5), TimeUnit.SECONDS);
         } catch (IOException | InterruptedException ie) {
             ie.printStackTrace(System.out);
             Assert.fail("unexpected exception", ie);
@@ -252,7 +255,7 @@
                 Assert.assertTrue(p.waitFor(15, TimeUnit.SECONDS));
             }
         } catch (IOException | InterruptedException ex) {
-            ex.printStackTrace(System.out);;
+            ex.printStackTrace(System.out);
         } finally {
             // Destroy any children that still exist
             ProcessUtil.destroyProcessTree(ProcessHandle.current());
@@ -274,7 +277,7 @@
 
         if (dur1.isPresent() && dur2.isPresent()) {
             Duration total1 = dur1.get();
-            Duration total2 = dur2.get();       ;
+            Duration total2 = dur2.get();
             System.out.printf(" total1 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n",
                     Objects.toString(total1), myCputime1, myCputime1.minus(total1));
             System.out.printf(" total2 vs. mbean: %s, getProcessCpuTime: %s, diff: %s%n",
@@ -326,7 +329,7 @@
      * @param d1 a Duration - presumed to be shorter
      * @param d2 a 2nd Duration - presumed to be greater (or within Epsilon)
      * @param epsilon Epsilon the amount of overlap allowed
-     * @return
+     * @return true if d2 is greater than d1 or within epsilon, false otherwise
      */
     static boolean checkEpsilon(Duration d1, Duration d2, Duration epsilon) {
         if (d1.toNanos() <= d2.toNanos()) {
@@ -339,7 +342,7 @@
     /**
      * Spawn a native process with the provided arguments.
      * @param command the executable of native process
-     * @args
+     * @param args to start a new process
      * @return the Process that was started
      * @throws IOException thrown by ProcessBuilder.start
      */
--- a/jdk/test/java/lang/ProcessHandle/JavaChild.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/lang/ProcessHandle/JavaChild.java	Wed Jul 05 20:41:30 2017 +0200
@@ -281,12 +281,12 @@
                         sendResult(action, Integer.toString(millis));
                         break;
                     case "cpuloop":
-                        long times = Long.valueOf(args[nextArg++]);
-                        Instant end = Instant.now().plusMillis(times);
-                        while (Instant.now().isBefore(end)) {
-                            // burn the cpu til the time is up
+                        long cpuMillis = Long.valueOf(args[nextArg++]);
+                        long cpuTarget = getCpuTime() + cpuMillis * 1_000_000L;
+                        while (getCpuTime() < cpuTarget) {
+                            // burn the cpu until the time is up
                         }
-                        sendResult(action, times);
+                        sendResult(action, cpuMillis);
                         break;
                     case "cputime":
                         sendResult(action, getCpuTime());
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -27,16 +27,19 @@
 import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
+
+import jdk.testlibrary.Utils;
+
 import org.testng.annotations.Test;
 import org.testng.Assert;
 import org.testng.TestNG;
 
 /*
  * @test
+ * @build jdk.testlibrary.Utils
  * @summary Functions of Process.onExit and ProcessHandle.onExit
  * @author Roger Riggs
  */
@@ -88,6 +91,7 @@
      */
     @Test
     public static void test2() {
+        ProcessHandle procHandle = null;
         try {
             ConcurrentHashMap<ProcessHandle, ProcessHandle> processes = new ConcurrentHashMap<>();
             List<ProcessHandle> children = getChildren(ProcessHandle.current());
@@ -96,7 +100,7 @@
                     "Expected to start with zero children; " + children);
 
             JavaChild proc = JavaChild.spawnJavaChild("stdin");
-            ProcessHandle procHandle = proc.toHandle();
+            procHandle = proc.toHandle();
             printf(" spawned: %d%n", proc.getPid());
 
             proc.forEachOutputLine((s) -> {
@@ -114,7 +118,8 @@
 
             // Poll until all 9 child processes exist or the timeout is reached
             int expected = 9;
-            Instant endTimeout = Instant.now().plusSeconds(10L);
+            long timeout = Utils.adjustTimeout(10L);
+            Instant endTimeout = Instant.now().plusSeconds(timeout);
             do {
                 Thread.sleep(200L);
                 printf(" subprocess count: %d, waiting for %d%n", processes.size(), expected);
@@ -123,16 +128,17 @@
 
             children = getAllChildren(procHandle);
 
-            ArrayBlockingQueue<ProcessHandle> completions = new ArrayBlockingQueue<>(expected + 1);
+            ConcurrentHashMap<ProcessHandle, CompletableFuture<ProcessHandle>> completions =
+                    new ConcurrentHashMap<>();
             Instant startTime = Instant.now();
             // Create a future for each of the 9 children
             processes.forEach( (p, parent) -> {
-                        p.onExit().whenComplete((ph, ex) -> {
+                        CompletableFuture<ProcessHandle> cf = p.onExit().whenComplete((ph, ex) -> {
                             Duration elapsed = Duration.between(startTime, Instant.now());
-                            completions.add(ph);
                             printf("whenComplete: pid: %s, exception: %s, thread: %s, elapsed: %s%n",
                                     ph, ex, Thread.currentThread(), elapsed);
                         });
+                        completions.put(p, cf);
                     });
 
             // Check that each of the spawned processes is included in the children
@@ -153,20 +159,23 @@
             proc.destroy();  // kill off the parent
             proc.waitFor();
 
-            // Wait for all the processes to be completed
+            // Wait for all the processes and corresponding onExit CF to be completed
             processes.forEach((p, parent) -> {
                 try {
                     p.onExit().get();
+                    completions.get(p).join();
                 } catch (InterruptedException | ExecutionException ex) {
                     // ignore
                 }
             });
 
-            // Verify that all 9 exit handlers were called
-            processes.forEach((p, parent) ->
-                Assert.assertTrue(completions.contains(p), "Child onExit not called: " + p
-                        + ", parent: " + parent
-                        + ": " + p.info()));
+            // Verify that all 9 exit handlers were called with the correct ProcessHandle
+            processes.forEach((p, parent) -> {
+                ProcessHandle value = completions.get(p).getNow(null);
+                Assert.assertEquals(p, value, "onExit.get value expected: " + p
+                        + ", actual: " + value
+                        + ": " + p.info());
+            });
 
             // Show the status of the original children
             children.forEach(p -> printProcess(p, "after onExit:"));
@@ -176,13 +185,12 @@
             List<ProcessHandle> children2 = getAllChildren(procHandle);
             printf(" children2: %s%n", children2.toString());
             Assert.assertEquals(children2.size(), 0, "After onExit, expected no children");
-
-            Assert.assertEquals(remaining.size(), 0, "Unaccounted for children");
-
         } catch (IOException | InterruptedException ex) {
             Assert.fail(ex.getMessage());
         } finally {
-            destroyProcessTree(ProcessHandle.current());
+            if (procHandle != null) {
+                destroyProcessTree(procHandle);
+            }
         }
     }
 
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -75,10 +75,12 @@
                 spawned.add(JavaChild.spawnJavaChild("pid", "stdin"));
             }
 
-            List<ProcessHandle> subprocesses = getChildren(self);
-            subprocesses.forEach(ProcessUtil::printProcess);
-            count = subprocesses.size();
-            Assert.assertEquals(count, MAXCHILDREN, "Wrong number of spawned children");
+            // Verify spawned Process is in list of children
+            final List<ProcessHandle> initialChildren = getChildren(self);
+            spawned.stream()
+                    .map(Process::toHandle)
+                    .filter(p -> !initialChildren.contains(p))
+                    .forEach(p -> Assert.fail("Spawned process missing from children: " + p));
 
             // Send exit command to each spawned Process
             spawned.forEach(p -> {
@@ -102,20 +104,25 @@
                 });
 
             // Verify that ProcessHandle.isAlive sees each of them as not alive
-            for (ProcessHandle ph : subprocesses) {
+            for (Process p : spawned) {
+                ProcessHandle ph = p.toHandle();
                 Assert.assertFalse(ph.isAlive(),
                         "ProcessHandle.isAlive for exited process: " + ph);
             }
 
-            // Verify no current children are visible
-            count = getChildren(self).size();
-            Assert.assertEquals(count, 0, "Children destroyed, should be zero");
+            // Verify spawned processes are not visible as children
+            final List<ProcessHandle> afterChildren = getChildren(self);
+            spawned.stream()
+                    .map(Process::toHandle)
+                    .filter(p -> afterChildren.contains(p))
+                    .forEach(p -> Assert.fail("Spawned process missing from children: " + p));
 
         } catch (IOException ioe) {
             Assert.fail("unable to spawn process", ioe);
         } finally {
             // Cleanup any left over processes
-            spawned.stream().map(Process::toHandle)
+            spawned.stream()
+                    .map(Process::toHandle)
                     .filter(ProcessHandle::isAlive)
                     .forEach(ph -> printDeep(ph, "test1 cleanup: "));
             destroyProcessTree(ProcessHandle.current());
@@ -127,7 +134,6 @@
      */
     @Test
     public static void test2() {
-        ProcessHandle p1Handle = null;
         try {
             ProcessHandle self = ProcessHandle.current();
             List<ProcessHandle> initialChildren = getChildren(self);
@@ -138,7 +144,7 @@
             }
 
             JavaChild p1 = JavaChild.spawnJavaChild("stdin");
-            p1Handle = p1.toHandle();
+            ProcessHandle p1Handle = p1.toHandle();
             printf("  p1 pid: %d%n", p1.getPid());
 
             int spawnNew = 3;
@@ -187,9 +193,6 @@
             throw new RuntimeException(t);
         } finally {
             // Cleanup any left over processes
-            if (p1Handle.isAlive()) {
-                printDeep(p1Handle, "test2 cleanup: ");
-            }
             destroyProcessTree(ProcessHandle.current());
         }
     }
@@ -205,7 +208,10 @@
             JavaChild p1 = JavaChild.spawnJavaChild("stdin");
             ProcessHandle p1Handle = p1.toHandle();
             printf(" p1: %s%n", p1.getPid());
-            long count = getChildren(self).size();
+
+            List<ProcessHandle> subprocesses = getChildren(self);
+            subprocesses.forEach(ProcessUtil::printProcess);
+            long count = subprocesses.size();
             Assert.assertEquals(count, 1, "Wrong number of spawned children");
 
             int newChildren = 3;
@@ -213,7 +219,7 @@
             p1.sendAction("spawn", newChildren, "stdin");
 
             // Wait for the new processes and save the list
-            List<ProcessHandle> subprocesses = waitForAllChildren(p1Handle, newChildren);
+            subprocesses = waitForAllChildren(p1Handle, newChildren);
             printDeep(p1Handle, "allChildren");
 
             Assert.assertEquals(subprocesses.size(), newChildren, "Wrong number of children");
@@ -249,6 +255,9 @@
             Assert.fail("Spawn of subprocess failed", ioe);
         } catch (InterruptedException inte) {
             Assert.fail("InterruptedException", inte);
+        } finally {
+            // Cleanup any left over processes
+            destroyProcessTree(ProcessHandle.current());
         }
     }
 
@@ -299,16 +308,15 @@
     }
 
     /**
-     * A test for scale; launch a large number (39) of subprocesses.
+     * A test for scale; launch a large number (14) of subprocesses.
      */
     @Test
     public static void test5() {
         int factor = 2;
-        ProcessHandle p1Handle = null;
         Instant start = Instant.now();
         try {
             JavaChild p1 = JavaChild.spawnJavaChild("stdin");
-            p1Handle = p1.toHandle();
+            ProcessHandle p1Handle = p1.toHandle();
 
             printf("Spawning %d x %d x %d processes, pid: %d%n",
                     factor, factor, factor, p1.getPid());
@@ -325,18 +333,14 @@
             int newChildren = factor * (1 + factor * (1 + factor));
             List<ProcessHandle> children = ProcessUtil.waitForAllChildren(p1Handle, newChildren);
 
-            Assert.assertEquals(p1.children()
-                    .filter(ProcessUtil::isNotWindowsConsole)
-                    .count(), factor, "expected direct children");
-            Assert.assertEquals(p1.allChildren()
-                    .filter(ProcessUtil::isNotWindowsConsole)
-                    .count(),
-                    factor * factor * factor + factor * factor + factor,
-                    "expected all children");
+            Assert.assertEquals(getChildren(p1Handle).size(),
+                    factor, "expected direct children");
+            long count = getAllChildren(p1Handle).size();
+            long totalChildren = factor * factor * factor + factor * factor + factor;
+            Assert.assertTrue(count >= totalChildren,
+                    "expected at least " + totalChildren + ", actual: " + count);
 
-            List<ProcessHandle> subprocesses = p1.allChildren()
-                    .filter(ProcessUtil::isNotWindowsConsole)
-                    .collect(Collectors.toList());
+            List<ProcessHandle> subprocesses = getAllChildren(p1Handle);
             printf(" allChildren:  %s%n",
                     subprocesses.stream().map(p -> p.getPid())
                     .collect(Collectors.toList()));
@@ -347,10 +351,6 @@
             Assert.fail("Unexpected Exception", ex);
         } finally {
             printf("Duration: %s%n", Duration.between(start, Instant.now()));
-            // Cleanup any left over processes
-            if (p1Handle.isAlive()) {
-                printDeep(p1Handle, "test5 cleanup: ");
-            }
             destroyProcessTree(ProcessHandle.current());
         }
     }
--- a/jdk/test/java/net/Socks/SocksProxyVersion.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/net/Socks/SocksProxyVersion.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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 6964547 5001942
+ * @bug 6964547 5001942 8129444
  * @run main/othervm SocksProxyVersion
  * @summary test socksProxyVersion system property
  */
@@ -32,13 +32,15 @@
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
-import java.io.DataInputStream;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Proxy;
 
 public class SocksProxyVersion implements Runnable {
     final ServerSocket ss;
     volatile boolean failed;
+    volatile boolean stopped = false;
+    volatile int expected;
 
     public static void main(String[] args) throws Exception {
         if (InetAddress.getLocalHost().isLoopbackAddress()) {
@@ -48,21 +50,26 @@
         new SocksProxyVersion();
     }
 
-    @SuppressWarnings("try")
     public SocksProxyVersion() throws Exception {
         ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
+        Thread serverThread = new Thread(this);
+        serverThread.start();
         try (ServerSocket socket = ss) {
-            runTest();
+            runTest(port);
+        } finally {
+            stopped = true;
+        }
+
+        serverThread.join();
+        if (failed) {
+            throw new RuntimeException("socksProxyVersion not being set correctly");
         }
     }
 
-    void runTest() throws Exception {
-        int port = ss.getLocalPort();
-        Thread serverThread = new Thread(this);
-        serverThread.start();
-
+    final void runTest(int port) throws Exception {
         /*
-         * Retreving the IP Address of the machine
+         * Retrieving the IP Address of the machine
          * since "localhost" is bypassed as a non-proxy host
          */
         String addr = InetAddress.getLocalHost().getHostAddress();
@@ -70,46 +77,54 @@
         System.setProperty("socksProxyHost", addr);
         System.setProperty("socksProxyPort", Integer.toString(port));
 
+        Proxy proxy = new Proxy(Proxy.Type.SOCKS,
+                                new InetSocketAddress(addr, port));
+
         // SOCKS V4
         System.setProperty("socksProxyVersion", Integer.toString(4));
-        try (Socket s = new Socket()) {
-            s.connect(new InetSocketAddress(addr, port));
+        this.expected = 4;
+        check(new Socket(), addr, port);
+        check(new Socket(proxy), addr, port);
+
+        // SOCKS V5
+        System.setProperty("socksProxyVersion", Integer.toString(5));
+        this.expected = 5;
+        check(new Socket(), addr, port);
+        check(new Socket(proxy), addr, port);
+    }
+
+    private void check(Socket socket, String addr, int port)
+        throws IOException
+    {
+        try (Socket s = socket) {
+            socket.connect(new InetSocketAddress(addr, port));
         } catch (SocketException e) {
             // java.net.SocketException: Malformed reply from SOCKS server
             // This exception is OK, since the "server" does not implement
             // the socks protocol. It just verifies the version and closes.
         }
-
-        // SOCKS V5
-        System.setProperty("socksProxyVersion", Integer.toString(5));
-        try (Socket s = new Socket()) {
-            s.connect(new InetSocketAddress(addr, port));
-        } catch (SocketException e) { /* OK */ }
-
-        serverThread.join();
-        if (failed) {
-            throw new RuntimeException("socksProxyVersion not being set correctly");
-        }
     }
 
+    @Override
     public void run() {
+        int count = 0;
         try {
-            try (Socket s = ss.accept()) {
-                int version = (s.getInputStream()).read();
-                if (version != 4) {
-                    System.out.println("Got " + version + ", expected 4");
-                    failed = true;
+            while (!stopped) {
+                try (Socket s = ss.accept()) {
+                    int version = (s.getInputStream()).read();
+                    if (version != expected) {
+                        System.out.printf("Iteration: %d, Got: %d, expected: %d%n",
+                                          count, version, expected);
+                        failed = true;
+                    }
                 }
-            }
-            try (Socket s = ss.accept()) {
-                int version = (s.getInputStream()).read();
-                if (version != 5) {
-                    System.out.println("Got " + version + ", expected 5");
-                    failed = true;
-                }
+                count++;
             }
         } catch (IOException e) {
-            e.printStackTrace();
+            if (!ss.isClosed()) {
+                e.printStackTrace();
+            }
+            // ignore, server socket was closed
         }
     }
 }
--- a/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/util/Collection/MOAT.java	Wed Jul 05 20:41:30 2017 +0200
@@ -356,13 +356,7 @@
             }
 
             check(c.toArray().length == c.size());
-            check(c.toArray().getClass() == Object[].class
-                  ||
-                  // !!!!
-                  // 6260652: (coll) Arrays.asList(x).toArray().getClass()
-                  // should be Object[].class
-                  (c.getClass().getName().equals("java.util.Arrays$ArrayList"))
-                  );
+            check(c.toArray().getClass() == Object[].class);
             for (int size : new int[]{0,1,c.size(), c.size()+1}) {
                 Integer[] a = c.toArray(new Integer[size]);
                 check((size > c.size()) || a.length == c.size());
--- a/jdk/test/java/util/logging/LoggingDeadlock2.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/java/util/logging/LoggingDeadlock2.java	Wed Jul 05 20:41:30 2017 +0200
@@ -57,35 +57,59 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.LogManager;
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.util.concurrent.TimeUnit;
 
 public class LoggingDeadlock2 {
 
+    // ask child process to dumpstack after 60secs
+    public static final long DUMP_STACK_FREQUENCY_MS = 60000;
+
+    // A marker that allows to validate the subprocess output.
+    public static final String MARKER = "$";
+
     public static void realMain(String arg[]) throws Throwable {
         try {
             System.out.println(javaChildArgs);
             ProcessBuilder pb = new ProcessBuilder(javaChildArgs);
             ProcessResults r = run(pb.start());
             equal(r.exitValue(), 99);
-            equal(r.out(), "");
+
+            // output of subprocess should end with "$"
+            final String out = r.out();
+            final String trailingOutput = out.indexOf(MARKER) > -1
+                    ? out.substring(out.indexOf(MARKER)+MARKER.length())
+                    : out;
+            equal(trailingOutput, "");
             equal(r.err(), "");
+            equal(out.startsWith("JavaChild started"), true);
+            equal(out.endsWith("$"), true);
         } catch (Throwable t) { unexpected(t); }
     }
 
     public static class JavaChild {
         public static void main(String args[]) throws Throwable {
+            System.out.println("JavaChild started");
+
             final CyclicBarrier startingGate = new CyclicBarrier(2);
             final Throwable[] thrown = new Throwable[1];
 
             // Some random variation, to help tickle races.
             final Random rnd = new Random();
+            final long seed = rnd.nextLong();
+            rnd.setSeed(seed);
+            System.out.println("seed=" + seed);
             final boolean dojoin = rnd.nextBoolean();
             final int JITTER = 1024;
             final int iters1 = rnd.nextInt(JITTER);
             final int iters2 = JITTER - iters1;
             final AtomicInteger counter = new AtomicInteger(0);
+            System.out.println("dojoin=" + dojoin);
+            System.out.println("iters1=" + iters1);
+            System.out.println("iters2=" + iters2);
 
             Thread exiter = new Thread() {
                 public void run() {
@@ -101,6 +125,12 @@
                 }};
             exiter.start();
 
+            System.out.println("exiter started");
+
+            // signal end of verbose output
+            System.out.print(MARKER);
+            System.out.flush();
+
             startingGate.await();
             for (int i = 0; i < iters2; i++)
                 counter.getAndIncrement();
@@ -124,6 +154,9 @@
     private static final String javaExe =
         System.getProperty("java.home") +
         File.separator + "bin" + File.separator + "java";
+    private static final String jstackExe =
+        System.getProperty("java.home") +
+        File.separator + "bin" + File.separator + "jstack";
 
     private static final String classpath =
         System.getProperty("java.class.path");
@@ -182,10 +215,15 @@
         public void run() {
             try {
                 Reader r = new InputStreamReader(is);
-                char[] buf = new char[4096];
                 int n;
-                while ((n = r.read(buf)) > 0) {
-                    sb.append(buf,0,n);
+                while ((n = r.read()) > 0) {
+                    sb.append((char)n);
+
+                    // prints everything immediately to System.out so that we can
+                    // see the traces even in the event of a test timeout
+                    System.out.write((char)n);
+                    System.out.flush();
+
                 }
             } catch (Throwable t) {
                 throwable = t;
@@ -196,6 +234,56 @@
         }
     }
 
+    /**
+     * If the child process deadlocks, then the parent may fail in timeout.
+     * In that case, we won't have any interesting traces, unless we manage
+     * to get a thread dump from the child.
+     * It is unsure whether obtaining a thread dump from a deadlocked child
+     * will work - but maybe we could see something if the timeout is a false
+     * positive (the child has not deadlocked but hasn't managed to fully start
+     * yet, for instance).
+     * The idea here is to periodically try to obtain a thread dump from the
+     * child, every 60sec - which should be always less than the jtreg timeout.
+     */
+    private static class TimeoutThread extends Thread {
+        final long ms;
+        final Process process;
+        TimeoutThread(long ms, Process p) {
+            super("TimeoutThread");
+            setDaemon(true);
+            this.ms = ms;
+            this.process = p;
+        }
+
+        @Override
+        public void run() {
+            long start = System.nanoTime();
+            try {
+                while (true) {
+                    sleep(ms);
+                    System.err.println("Timeout reached: " + ms);
+                    if (process.isAlive()) {
+                        long pid = process.getPid();
+                        ProcessBuilder jstack = new ProcessBuilder(jstackExe, String.valueOf(pid));
+                        System.err.println("Dumping subprocess stack: " + pid);
+                        Process p = jstack.inheritIO().start();
+                        p.waitFor(ms, TimeUnit.MILLISECONDS);
+                    } else {
+                        System.err.println("Process is not alive!");
+                        break;
+                    }
+                }
+            } catch (InterruptedException ex) {
+                System.err.println("Interrupted: " + ex);
+            } catch (IOException io) {
+                System.err.println("Failed to get stack from subprocess");
+                io.printStackTrace();
+            }
+        }
+
+
+    }
+
     private static ProcessResults run(Process p) {
         Throwable throwable = null;
         int exitValue = -1;
@@ -208,10 +296,15 @@
             new StreamAccumulator(p.getErrorStream());
 
         try {
+            System.out.println("Waiting for child process to exit");
             outAccumulator.start();
             errAccumulator.start();
 
+            // ask subprocess to dump stack every 60 secs.
+            new TimeoutThread(DUMP_STACK_FREQUENCY_MS, p).start();
+
             exitValue = p.waitFor();
+            System.out.println("\nChild exited with status: " + exitValue);
 
             outAccumulator.join();
             errAccumulator.join();
--- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java	Wed Jul 05 20:41:30 2017 +0200
@@ -46,8 +46,8 @@
  * An example to show the way to use SSLEngine in datagram connections.
  */
 public class DTLSOverDatagram {
-    private static int MAX_HANDSHAKE_LOOPS = 60;
-    private static int MAX_APP_READ_LOOPS = 10;
+    private static int MAX_HANDSHAKE_LOOPS = 200;
+    private static int MAX_APP_READ_LOOPS = 60;
 
     /*
      * The following is to set up the keystores.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/jline/KeyConversionTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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 8080679
+ * @summary Verify the conversion from key events to escape sequences works properly.
+ * @requires os.family == "windows"
+ */
+
+import jdk.internal.jline.WindowsTerminal;
+import jdk.internal.jline.WindowsTerminal.KEY_EVENT_RECORD;
+
+public class KeyConversionTest {
+    public static void main(String... args) throws Exception {
+        new KeyConversionTest().run();
+    }
+
+    void run() throws Exception {
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 37, 1), "\033[D"); //LEFT
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 37, 1), "\033[1;5D"); //Ctrl-LEFT
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 37, 1), "\033[1;3D"); //Alt-LEFT
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 256, 46, 1), "\033[3~"); //delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 264, 46, 1), "\033[3;5~"); //Ctrl-delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 258, 46, 1), "\033[3;3~"); //Alt-delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 272, 46, 1), "\033[3;2~"); //Shift-delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 280, 46, 1), "\033[3;6~"); //Ctrl-Shift-delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 274, 46, 1), "\033[3;4~"); //Alt-Shift-delete
+        checkKeyConversion(new KEY_EVENT_RECORD(true, '\0', 282, 46, 1), "\033[3;8~"); //Ctrl-Alt-Shift-delete
+    }
+
+    void checkKeyConversion(KEY_EVENT_RECORD event, String expected) {
+        String actual = WindowsTerminal.convertKeys(event);
+
+        if (!expected.equals(actual)) {
+            throw new AssertionError("Expected: " + expected + "; actual: " + actual);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/jline/console/StripAnsiTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * 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 8080679
+ * @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Method;
+import jdk.internal.jline.console.ConsoleReader;
+
+public class StripAnsiTest {
+    public static void main(String... args) throws Exception {
+        new StripAnsiTest().run();
+    }
+
+    void run() throws Exception {
+        ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ConsoleReader reader = new ConsoleReader(in, out);
+
+        String withAnsi = "0\033[s1\033[2J2\033[37;4m3";
+        String expected = "0123";
+
+        Method stripAnsi = ConsoleReader.class.getDeclaredMethod("stripAnsi", String.class);
+        stripAnsi.setAccessible(true);
+        String actual = (String) stripAnsi.invoke(reader, withAnsi);
+
+        if (!expected.equals(actual)) {
+            throw new IllegalStateException("Did not correctly strip escape sequences: " + actual);
+        }
+    }
+}
--- a/jdk/test/sun/security/krb5/auto/BadKdc1.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/jdk/test/sun/security/krb5/auto/BadKdc1.java	Wed Jul 05 20:41:30 2017 +0200
@@ -53,7 +53,7 @@
                // k3 off k2 on
                "(122212(22){1,2}|1222323232-)", // 1
                // k1 on
-               "(12(12){1,2}|122232-)"  // empty
+               "(12(12){1,2}|122212|122232-)"  // empty
        );
    }
 }
--- a/langtools/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -314,3 +314,4 @@
 931ec7dd6cd9e4a92bde7b2cd26e9a9fb0ecdb56 jdk9-b69
 d732d6dfa72743e3aa96375c6e33f1388dbaa5c6 jdk9-b70
 dc35e315436d21eab68ef44909922fb3424917f3 jdk9-b71
+832e51533706b633d37a77282ae94d016b95e649 jdk9-b72
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 05 20:41:30 2017 +0200
@@ -4140,12 +4140,7 @@
 
     public void visitAnnotatedType(JCAnnotatedType tree) {
         attribAnnotationTypes(tree.annotations, env);
-        JCExpression underlyingTypeTree = tree.getUnderlyingType();
-        Type underlyingType = attribTree(underlyingTypeTree, env,
-                                               new ResultInfo(KindSelector.TYP_PCK, Type.noType));
-        if (!chk.checkAnnotableType(underlyingType, tree.annotations, underlyingTypeTree.pos())) {
-            underlyingType = underlyingTypeTree.type = syms.errType;
-        }
+        Type underlyingType = attribType(tree.underlyingType, env);
         Type annotatedType = underlyingType.annotatedType(Annotations.TO_BE_SET);
 
         if (!env.info.isNewClass)
@@ -4636,7 +4631,16 @@
                     }
                 } else if (enclTr.hasTag(ANNOTATED_TYPE)) {
                     JCAnnotatedType at = (JCTree.JCAnnotatedType) enclTr;
-                    if (!chk.checkAnnotableType(enclTy, at.getAnnotations(), at.underlyingType.pos())) {
+                    if (enclTy == null || enclTy.hasTag(NONE)) {
+                        if (at.getAnnotations().size() == 1) {
+                            log.error(at.underlyingType.pos(), "cant.type.annotate.scoping.1", at.getAnnotations().head.attribute);
+                        } else {
+                            ListBuffer<Attribute.Compound> comps = new ListBuffer<>();
+                            for (JCAnnotation an : at.getAnnotations()) {
+                                comps.add(an.attribute);
+                            }
+                            log.error(at.underlyingType.pos(), "cant.type.annotate.scoping", comps.toList());
+                        }
                         repeat = false;
                     }
                     enclTr = at.underlyingType;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Jul 05 20:41:30 2017 +0200
@@ -63,8 +63,6 @@
 import static com.sun.tools.javac.code.TypeTag.*;
 import static com.sun.tools.javac.code.TypeTag.WILDCARD;
 
-import static com.sun.tools.javac.resources.CompilerProperties.Errors.CantTypeAnnotateScoping;
-import static com.sun.tools.javac.resources.CompilerProperties.Errors.CantTypeAnnotateScoping1;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /** Type checking helper class for the attribution phase.
@@ -2694,29 +2692,6 @@
  * Check annotations
  **************************************************************************/
 
-    /** Verify that a component of a qualified type name being type annotated
-     * can indeed be legally be annotated. For example, package names and type
-     * names used to access static members cannot be annotated.
-     *
-     * @param typeComponent the component of the qualified name being annotated
-     * @param annotations the annotations
-     * @param pos diagnostic position
-     * @return true if all is swell, false otherwise.
-     */
-    boolean checkAnnotableType(Type typeComponent, List<JCAnnotation> annotations, DiagnosticPosition pos) {
-        if (typeComponent == null || typeComponent.hasTag(PACKAGE) || typeComponent.hasTag(NONE)) {
-            ListBuffer<Symbol> lb = new ListBuffer<>();
-            for (JCAnnotation annotation : annotations) {
-                lb.append(annotation.annotationType.type.tsym);
-            }
-            List<Symbol> symbols = lb.toList();
-            log.error(pos,
-                    symbols.size() > 1 ? CantTypeAnnotateScoping(symbols)
-                            : CantTypeAnnotateScoping1(symbols.get(0)));
-            return false;
-        }
-        return true;
-    }
     /**
      * Recursively validate annotations values
      */
--- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1,12 +1,12 @@
 /*
  * @test /nodynamiccopyright/
- * @bug 8026564 8074346
+ * @bug 8026564
  * @summary The parts of a fully-qualified type can't be annotated.
  * @author Werner Dietl
+ * @ignore 8057679 clarify error messages trying to annotate scoping
  * @compile/fail/ref=CantAnnotatePackages.out -XDrawDiagnostics CantAnnotatePackages.java
  */
 
-
 import java.lang.annotation.*;
 import java.util.List;
 
@@ -21,8 +21,6 @@
     java. @TA lang.Object of3;
     List<java. @TA lang.Object> of4;
 
-    List<@CantAnnotatePackages_TB java.lang.Object> of5; // test that we do reasonable things for missing types.
-
     // TODO: also note the order of error messages.
 }
 
--- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.out	Wed Jul 05 20:40:53 2017 +0200
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.out	Wed Jul 05 20:41:30 2017 +0200
@@ -1,7 +1,5 @@
-CantAnnotatePackages.java:20:14: compiler.err.cant.type.annotate.scoping.1: TA
-CantAnnotatePackages.java:21:9: compiler.err.cant.type.annotate.scoping.1: TA
-CantAnnotatePackages.java:22:14: compiler.err.cant.type.annotate.scoping.1: TA
-CantAnnotatePackages.java:24:11: compiler.err.cant.resolve.location: kindname.class, CantAnnotatePackages_TB, , , (compiler.misc.location: kindname.class, CantAnnotatePackages, null)
-CantAnnotatePackages.java:24:35: compiler.err.cant.type.annotate.scoping.1: CantAnnotatePackages_TB
-CantAnnotatePackages.java:15:18: compiler.err.cant.type.annotate.scoping.1: @TA
-6 errors
+CantAnnotatePackages.java:14:13: compiler.err.cant.type.annotate.scoping.1: @TA
+CantAnnotatePackages.java:19:18: compiler.err.cant.type.annotate.scoping.1: @TA
+CantAnnotatePackages.java:20:19: compiler.err.cant.type.annotate.scoping.1: @TA
+CantAnnotatePackages.java:21:24: compiler.err.cant.type.annotate.scoping.1: @TA
+4 errors
--- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.java	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 8074346
- * @author sadayapalam
- * @summary Test that type annotation on a qualified type doesn't cause spurious 'cannot find symbol' errors
- * @compile/fail/ref=T8074346.out -XDrawDiagnostics T8074346.java
-*/
-
-abstract class T8074346 implements
-        @T8074346_TA @T8074346_TB java.util.Map<@T8074346_TA java.lang.String, java.lang.@T8074346_TA String>,
-        java.util.@T8074346_TA List {
-}
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE)
-@interface T8074346_TA { }
-
-@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE)
-@interface T8074346_TB { }
\ No newline at end of file
--- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/T8074346.out	Wed Jul 05 20:40:53 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-T8074346.java:10:35: compiler.err.cant.type.annotate.scoping: T8074346_TA,T8074346_TB
-T8074346.java:10:62: compiler.err.cant.type.annotate.scoping.1: T8074346_TA
-2 errors
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8078024/T8078024.java	Wed Jul 05 20:41:30 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8078024
+ * @summary before the patch for JDK-8078024 this code wasn't accepted by the compiler. After the
+ *          mentioned patch the second method is selected as applicable and the code is accepted.
+ * @compile T8078024.java
+ */
+
+import java.util.Arrays;
+import java.util.List;
+
+class T8078024 {
+    public static <A> List<List<A>> cartesianProduct(List<? extends A>... lists) {
+        return cartesianProduct(Arrays.asList(lists));
+    }
+
+    public static <B> List<List<B>> cartesianProduct(List<? extends List<? extends B>> lists) {
+        return null;
+    }
+}
--- a/make/CompileJavaModules.gmk	Wed Jul 05 20:40:53 2017 +0200
+++ b/make/CompileJavaModules.gmk	Wed Jul 05 20:41:30 2017 +0200
@@ -368,6 +368,10 @@
 
 ################################################################################
 
+jdk.internal.le_COPY := .properties
+
+################################################################################
+
 jdk.jcmd_COPY := _options
 
 ################################################################################
--- a/make/Images.gmk	Wed Jul 05 20:40:53 2017 +0200
+++ b/make/Images.gmk	Wed Jul 05 20:41:30 2017 +0200
@@ -46,7 +46,7 @@
                jdk.naming.dns jdk.naming.rmi jdk.scripting.nashorn jdk.zipfs
 
 # tools
-TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.javadoc jdk.jcmd jdk.jconsole \
+TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.internal.le jdk.javadoc jdk.jcmd jdk.jconsole \
                jdk.hotspot.agent jdk.hprof.agent jdk.jartool jdk.jdeps jdk.jdi jdk.jdwp.agent \
                jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws
 
--- a/modules.xml	Wed Jul 05 20:40:53 2017 +0200
+++ b/modules.xml	Wed Jul 05 20:41:30 2017 +0200
@@ -1625,6 +1625,26 @@
     </export>
   </module>
   <module>
+    <name>jdk.internal.le</name>
+    <depend>java.base</depend>
+    <export>
+      <name>jdk.internal.jline</name>
+      <to>jdk.scripting.nashorn.shell</to>
+    </export>
+    <export>
+      <name>jdk.internal.jline.console</name>
+      <to>jdk.scripting.nashorn.shell</to>
+    </export>
+    <export>
+      <name>jdk.internal.jline.console.completer</name>
+      <to>jdk.scripting.nashorn.shell</to>
+    </export>
+    <export>
+      <name>jdk.internal.jline.console.history</name>
+      <to>jdk.scripting.nashorn.shell</to>
+    </export>
+  </module>
+  <module>
     <name>jdk.jartool</name>
     <depend>java.base</depend>
     <export>
--- a/nashorn/.hgtags	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/.hgtags	Wed Jul 05 20:41:30 2017 +0200
@@ -305,3 +305,4 @@
 194b74467afcab3ca0096f04570def424977215d jdk9-b69
 3379235149c0e14e59e05c4ab8df450f5777b552 jdk9-b70
 7066af6e7b06f3c6ebf449c88fc1064d2181237a jdk9-b71
+d017877b3b8cd39337f1bdc00d958f821433c4c3 jdk9-b72
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java	Wed Jul 05 20:41:30 2017 +0200
@@ -39,7 +39,7 @@
  */
 public final class MemberInfo implements Cloneable {
     // class loader of this class
-    private static ClassLoader myLoader = MemberInfo.class.getClassLoader();
+    private static final ClassLoader MY_LOADER = MemberInfo.class.getClassLoader();
 
     /**
      * The different kinds of available class annotations
@@ -493,7 +493,7 @@
 
         if (type.getSort() == Type.OBJECT) {
             try {
-                final Class<?> clazz = Class.forName(type.getClassName(), false, myLoader);
+                final Class<?> clazz = Class.forName(type.getClassName(), false, MY_LOADER);
                 return ScriptObject.class.isAssignableFrom(clazz);
             } catch (final ClassNotFoundException cnfe) {
                 return false;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java	Wed Jul 05 20:41:30 2017 +0200
@@ -156,14 +156,14 @@
         return null;
     }
 
-    private static MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get",
+    private static final MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get",
             MethodType.methodType(Object.class, int.class));
 
-    private static MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get",
+    private static final MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get",
             MethodType.methodType(Object.class, Object.class));
 
-    private static MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
-    private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
+    private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
+    private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
 
     private enum CollectionType {
         ARRAY, LIST, MAP
@@ -287,7 +287,7 @@
                     if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinites trigger IOOBE
                         return null; // not an exact integer
                     }
-                    return Integer.valueOf(intIndex);
+                    return intIndex;
                 } catch(Exception|Error e) {
                     throw e;
                 } catch(final Throwable t) {
@@ -343,9 +343,9 @@
         }
     }
 
-    private static MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class);
-    private static MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class);
-    private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
+    private static final MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class);
+    private static final MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class);
+    private static final MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
             MethodType.methodType(boolean.class, Object.class));
 
     private static MethodHandle findRangeCheck(final Class<?> collectionType) {
@@ -353,7 +353,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static final boolean rangeCheck(final Object array, final Object index) {
+    private static boolean rangeCheck(final Object array, final Object index) {
         if(!(index instanceof Number)) {
             return false;
         }
@@ -370,7 +370,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static final boolean rangeCheck(final List<?> list, final Object index) {
+    private static boolean rangeCheck(final List<?> list, final Object index) {
         if(!(index instanceof Number)) {
             return false;
         }
@@ -386,10 +386,10 @@
         throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size());
     }
 
-    private static MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set",
+    private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set",
             MethodType.methodType(Object.class, int.class, Object.class));
 
-    private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
+    private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
             MethodType.methodType(Object.class, Object.class, Object.class));
 
     private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor,
@@ -471,16 +471,16 @@
                 gic.getValidatorClass(), gic.getValidationType());
     }
 
-    private static MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength",
+    private static final MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength",
             MethodType.methodType(int.class, Object.class));
 
-    private static MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
+    private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
             MethodType.methodType(int.class));
 
-    private static MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size",
+    private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size",
             MethodType.methodType(int.class));
 
-    private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
+    private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
 
     private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) {
         assertParameterCount(callSiteDescriptor, 1);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java	Wed Jul 05 20:41:30 2017 +0200
@@ -164,7 +164,7 @@
             }
         }
         if(b == null) {
-            return name.toString();
+            return name;
         }
         assert lastEscape != -1;
         b.append(name, lastEscape + 1, l);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java	Wed Jul 05 20:41:30 2017 +0200
@@ -166,7 +166,7 @@
         }
     };
 
-    private static final ClassLoader getClassLoader(final Class<?> clazz) {
+    private static ClassLoader getClassLoader(final Class<?> clazz) {
         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
             @Override
             public ClassLoader run() {
@@ -298,7 +298,7 @@
      * @return true if there can be a conversion, false if there can not.
      */
     public boolean canConvert(final Class<?> from, final Class<?> to) {
-        return canAutoConvert(from, to) || canConvert.get(from).get(to).booleanValue();
+        return canAutoConvert(from, to) || canConvert.get(from).get(to);
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/Formatter.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/Formatter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -170,7 +170,7 @@
      * @return true if '&lt;' is in the string, else false
      */
     private static boolean isPreviousArgument(final String s) {
-        return (s != null && s.indexOf('<') >= 0) ? true : false;
+        return (s != null && s.indexOf('<') >= 0);
     }
 
     // %[argument_index$][flags][width][.precision][t]conversion
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ClassEmitter.java	Wed Jul 05 20:41:30 2017 +0200
@@ -705,7 +705,7 @@
         /** private access */
         PRIVATE(ACC_PRIVATE);
 
-        private int value;
+        private final int value;
 
         private Flag(final int value) {
             this.value = value;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -213,7 +213,7 @@
     private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
     private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
 
-    private static final Integer INT_ZERO = Integer.valueOf(0);
+    private static final Integer INT_ZERO = 0;
 
     /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
      *  by reflection in class installation */
@@ -742,7 +742,7 @@
         method.convert(Type.NUMBER);
     }
 
-    private static final Type undefinedToNumber(final Type type) {
+    private static Type undefinedToNumber(final Type type) {
         return type == Type.UNDEFINED ? Type.NUMBER : type;
     }
 
@@ -4877,7 +4877,7 @@
             if(propertyValue instanceof String || propertyValue == null) {
                 method.load((String)propertyValue);
             } else if(propertyValue instanceof Integer) {
-                method.load(((Integer)propertyValue).intValue());
+                method.load(((Integer)propertyValue));
                 method.convert(Type.OBJECT);
             } else {
                 throw new AssertionError();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java	Wed Jul 05 20:41:30 2017 +0200
@@ -56,7 +56,7 @@
 
     private transient Class<?> clazz;
 
-    private transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
+    private final transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
 
     private transient boolean isUsed;
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java	Wed Jul 05 20:41:30 2017 +0200
@@ -437,7 +437,7 @@
 
         baseName = baseName.replace('.', '_').replace('-', '_');
         if (!env._loader_per_compile) {
-            baseName = baseName + installer.getUniqueScriptId();
+            baseName += installer.getUniqueScriptId();
         }
 
         // ASM's bytecode verifier does not allow JVM allowed safe escapes using '\' as escape char.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ConstantData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ConstantData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -162,7 +162,7 @@
         final Integer value = stringMap.get(string);
 
         if (value != null) {
-            return value.intValue();
+            return value;
         }
 
         constants.add(string);
@@ -191,7 +191,7 @@
         final Integer value = objectMap.get(entry);
 
         if (value != null) {
-            return value.intValue();
+            return value;
         }
 
         constants.add(object);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/DumpBytecode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/DumpBytecode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -51,7 +51,7 @@
             if (env._print_code) {
 
                 final StringBuilder sb = new StringBuilder();
-                sb.append("class: " + className).
+                sb.append("class: ").append(className).
                     append('\n').
                     append(ClassEmitter.disassemble(bytecode)).
                     append("=====");
@@ -88,7 +88,7 @@
             }
 
 
-            // should code be dumped to disk - only valid in compile_only mode?
+            // should code be dumped to disk
             if (env._dest_dir != null) {
                 final String fileName = className.replace('.', File.separatorChar) + ".class";
                 final int    index    = fileName.lastIndexOf(File.separatorChar);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java	Wed Jul 05 20:41:30 2017 +0200
@@ -121,11 +121,9 @@
 
     private static boolean definedInBlock(final Block block, final Symbol symbol) {
         if (symbol.isGlobal()) {
-            if (block.isGlobalScope()) {
-                return true;
-            }
             //globals cannot be defined anywhere else
-            return false;
+
+            return block.isGlobalScope();
         }
         return block.getExistingSymbol(symbol.getName()) == symbol;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -272,12 +272,12 @@
     }
 
     private static class SymbolConversions {
-        private static byte I2L = 1 << 0;
-        private static byte I2D = 1 << 1;
-        private static byte I2O = 1 << 2;
-        private static byte L2D = 1 << 3;
-        private static byte L2O = 1 << 4;
-        private static byte D2O = 1 << 5;
+        private static final byte I2L = 1 << 0;
+        private static final byte I2D = 1 << 1;
+        private static final byte I2O = 1 << 2;
+        private static final byte L2D = 1 << 3;
+        private static final byte L2O = 1 << 4;
+        private static final byte D2O = 1 << 5;
 
         private byte conversions;
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Wed Jul 05 20:41:30 2017 +0200
@@ -101,7 +101,7 @@
 
     // Conservative pattern to test if element names consist of characters valid for identifiers.
     // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit.
-    private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*");
+    private static final Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*");
 
     /**
      * Constructor.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -69,7 +69,6 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
 import jdk.nashorn.internal.runtime.logging.Logger;
-import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * Generates the ScriptObject subclass structure with fields for a user objects.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java	Wed Jul 05 20:41:30 2017 +0200
@@ -89,7 +89,7 @@
     public Type ldc(final MethodVisitor method, final Object c) {
         assert c instanceof Integer;
 
-        final int value = ((Integer) c).intValue();
+        final int value = ((Integer) c);
 
         switch (value) {
         case -1:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornClassReader.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornClassReader.java	Wed Jul 05 20:41:30 2017 +0200
@@ -88,7 +88,7 @@
             c = bytecode[i++];
             switch (st) {
             case 0:
-                c = c & 0xFF;
+                c &= 0xFF;
                 if (c < 0x80) { // 0xxxxxxx
                     buf[strLen++] = (char) c;
                 } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
@@ -457,7 +457,7 @@
 
         @SuppressWarnings("unused")
         final String getType() {
-            String str = type[tag];
+            String str = TYPE[tag];
             while (str.length() < 16) {
                 str += " ";
             }
@@ -507,7 +507,7 @@
         }
     }
 
-    private static String type[] = {
+    private static final String[] TYPE = {
         //0
         "<error>",
         //1
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java	Wed Jul 05 20:41:30 2017 +0200
@@ -535,7 +535,7 @@
         addText(sb);
     }
 
-    private static final boolean noFallThru(final int opcode) {
+    private static boolean noFallThru(final int opcode) {
         switch (opcode) {
         case Opcodes.GOTO:
         case Opcodes.ATHROW:
@@ -901,7 +901,7 @@
                     appendDescriptor(sb, INTERNAL_NAME, desc);
                 }
             } else if (o[i] instanceof Integer) {
-                switch (((Integer)o[i]).intValue()) {
+                switch (((Integer)o[i])) {
                 case 0:
                     appendDescriptor(sb, FIELD_DESCRIPTOR, "T");
                     break;
@@ -1090,7 +1090,7 @@
         public String toString() {
 
             final StringBuilder sb = new StringBuilder();
-            sb.append("digraph " + dottyFriendly(name) + " {");
+            sb.append("digraph ").append(dottyFriendly(name)).append(" {");
             sb.append("\n");
             sb.append("\tgraph [fontname=courier]\n");
             sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java	Wed Jul 05 20:41:30 2017 +0200
@@ -450,7 +450,7 @@
                 for (final Object mp : memoryPoolMXBeans) {
                     final Object usage = getUsage.invoke(mp);
                     final Object max = getMax.invoke(usage);
-                    maxMemory += ((Long)max).longValue();
+                    maxMemory += ((Long)max);
                 }
             } catch (IllegalAccessException |
                      IllegalArgumentException |
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Wed Jul 05 20:41:30 2017 +0200
@@ -88,14 +88,14 @@
  */
 @ScriptClass("Global")
 public final class Global extends Scope {
-    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
-    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
+    // This special value is used to flag a lazily initialized global property.
+    // This also serves as placeholder value used in place of a location property
+    // (__FILE__, __DIR__, __LINE__)
+    private static final Object LAZY_SENTINEL = new Object();
+
     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
 
-    // placeholder value for lazily initialized global objects
-    private static final Object LAZY_SENTINEL = new Object();
-
     /**
      * Optimistic builtin names that require switchpoint invalidation
      * upon assignment. Overly conservative, but works for now, to avoid
@@ -182,15 +182,15 @@
 
     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final double NaN = Double.NaN;
+    public static final double NaN = Double.NaN;
 
     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final double Infinity = Double.POSITIVE_INFINITY;
+    public static final double Infinity = Double.POSITIVE_INFINITY;
 
     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object undefined = UNDEFINED;
+    public static final Object undefined = UNDEFINED;
 
     /** ECMA 15.1.2.1 eval(x) */
     @Property(attributes = Attribute.NOT_ENUMERABLE)
@@ -830,15 +830,15 @@
 
     /** Nashorn extension: current script's file name */
     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __FILE__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current script's directory */
     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __DIR__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current source line number being executed */
     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __LINE__ = LAZY_SENTINEL;
 
     private volatile NativeDate DEFAULT_DATE;
 
@@ -1768,38 +1768,10 @@
         return ScriptFunction.getPrototype(getBuiltinFloat64Array());
     }
 
-    private ScriptFunction getBuiltinArray() {
-        return builtinArray;
-    }
-
     ScriptFunction getTypeErrorThrower() {
         return typeErrorThrower;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin array has not been overridden
-     */
-    public static boolean isBuiltinArray() {
-        final Global instance = Global.instance();
-        return instance.array == instance.getBuiltinArray();
-    }
-
-    private ScriptFunction getBuiltinBoolean() {
-        return builtinBoolean;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin boolean has not been overridden
-     */
-    public static boolean isBuiltinBoolean() {
-        final Global instance = Global.instance();
-        return instance._boolean == instance.getBuiltinBoolean();
-    }
-
     private synchronized ScriptFunction getBuiltinDate() {
         if (this.builtinDate == null) {
             this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
@@ -1810,30 +1782,6 @@
         return this.builtinDate;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin date has not been overridden
-     */
-    public static boolean isBuiltinDate() {
-        final Global instance = Global.instance();
-        return instance.date == LAZY_SENTINEL || instance.date == instance.getBuiltinDate();
-    }
-
-    private ScriptFunction getBuiltinError() {
-        return builtinError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin error has not been overridden
-     */
-    public static boolean isBuiltinError() {
-        final Global instance = Global.instance();
-        return instance.error == instance.getBuiltinError();
-    }
-
     private synchronized ScriptFunction getBuiltinEvalError() {
         if (this.builtinEvalError == null) {
             this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
@@ -1841,31 +1789,11 @@
         return this.builtinEvalError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin eval error has not been overridden
-     */
-    public static boolean isBuiltinEvalError() {
-        final Global instance = Global.instance();
-        return instance.evalError == LAZY_SENTINEL || instance.evalError == instance.getBuiltinEvalError();
-    }
-
     private ScriptFunction getBuiltinFunction() {
         return builtinFunction;
     }
 
     /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin function has not been overridden
-     */
-    public static boolean isBuiltinFunction() {
-        final Global instance = Global.instance();
-        return instance.function == instance.getBuiltinFunction();
-    }
-
-    /**
      * Get the switchpoint used to check property changes for Function.prototype.apply
      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
      */
@@ -1906,16 +1834,6 @@
         return builtinJSAdapter;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSAdapter has not been overridden
-     */
-    public static boolean isBuiltinJSAdapter() {
-        final Global instance = Global.instance();
-        return instance.jsadapter == LAZY_SENTINEL || instance.jsadapter == instance.getBuiltinJSAdapter();
-    }
-
     private synchronized ScriptObject getBuiltinJSON() {
         if (this.builtinJSON == null) {
             this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
@@ -1923,44 +1841,6 @@
         return this.builtinJSON;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSON has has not been overridden
-     */
-    public static boolean isBuiltinJSON() {
-        final Global instance = Global.instance();
-        return instance.json == LAZY_SENTINEL || instance.json == instance.getBuiltinJSON();
-    }
-
-    private ScriptObject getBuiltinJava() {
-        return builtinJava;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinJava() {
-        final Global instance = Global.instance();
-        return instance.java == instance.getBuiltinJava();
-    }
-
-    private ScriptObject getBuiltinJavax() {
-        return builtinJavax;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Javax has not been overridden
-     */
-    public static boolean isBuiltinJavax() {
-        final Global instance = Global.instance();
-        return instance.javax == instance.getBuiltinJavax();
-    }
-
     private synchronized ScriptFunction getBuiltinJavaImporter() {
         if (this.builtinJavaImporter == null) {
             this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
@@ -1975,68 +1855,6 @@
         return this.builtinJavaApi;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java importer has not been overridden
-     */
-    public static boolean isBuiltinJavaImporter() {
-        final Global instance = Global.instance();
-        return instance.javaImporter == LAZY_SENTINEL || instance.javaImporter == instance.getBuiltinJavaImporter();
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin math has not been overridden
-     */
-    public static boolean isBuiltinMath() {
-        final Global instance = Global.instance();
-        return instance.math == instance.builtinMath;
-    }
-
-    private ScriptFunction getBuiltinNumber() {
-        return builtinNumber;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin number has not been overridden
-     */
-    public static boolean isBuiltinNumber() {
-        final Global instance = Global.instance();
-        return instance.number == instance.getBuiltinNumber();
-    }
-
-    private ScriptFunction getBuiltinObject() {
-        return builtinObject;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin object has not been overridden
-     */
-    public static boolean isBuiltinObject() {
-        final Global instance = Global.instance();
-        return instance.object == instance.getBuiltinObject();
-    }
-
-    private ScriptObject getBuiltinPackages() {
-        return builtinPackages;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin package has not been overridden
-     */
-    public static boolean isBuiltinPackages() {
-        final Global instance = Global.instance();
-        return instance.packages == instance.getBuiltinPackages();
-    }
-
     private synchronized ScriptFunction getBuiltinRangeError() {
         if (this.builtinRangeError == null) {
             this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
@@ -2044,30 +1862,6 @@
         return builtinRangeError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin range error has not been overridden
-     */
-    public static boolean isBuiltinRangeError() {
-        final Global instance = Global.instance();
-        return instance.rangeError == LAZY_SENTINEL || instance.rangeError == instance.getBuiltinRangeError();
-    }
-
-    private synchronized ScriptFunction getBuiltinReferenceError() {
-        return builtinReferenceError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin reference error has not been overridden
-     */
-    public static boolean isBuiltinReferenceError() {
-        final Global instance = Global.instance();
-        return instance.referenceError == instance.getBuiltinReferenceError();
-    }
-
     private synchronized ScriptFunction getBuiltinRegExp() {
         if (this.builtinRegExp == null) {
             this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
@@ -2081,58 +1875,6 @@
         return builtinRegExp;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin regexp has not been overridden
-     */
-    public static boolean isBuiltinRegExp() {
-        final Global instance = Global.instance();
-        return instance.regexp == LAZY_SENTINEL || instance.regexp == instance.getBuiltinRegExp();
-    }
-
-    private ScriptFunction getBuiltinString() {
-        return builtinString;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinString() {
-        final Global instance = Global.instance();
-        return instance.string == instance.getBuiltinString();
-    }
-
-    private ScriptFunction getBuiltinSyntaxError() {
-        return builtinSyntaxError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin syntax error has not been overridden
-     */
-    public static boolean isBuiltinSyntaxError() {
-        final Global instance = Global.instance();
-        return instance.syntaxError == instance.getBuiltinSyntaxError();
-    }
-
-    private ScriptFunction getBuiltinTypeError() {
-        return builtinTypeError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin type error has not been overridden
-     */
-    public static boolean isBuiltinTypeError() {
-        final Global instance = Global.instance();
-        return instance.typeError == instance.getBuiltinTypeError();
-    }
-
     private synchronized ScriptFunction getBuiltinURIError() {
         if (this.builtinURIError == null) {
             this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
@@ -2140,16 +1882,6 @@
         return this.builtinURIError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin URI error has not been overridden
-     */
-    public static boolean isBuiltinURIError() {
-        final Global instance = Global.instance();
-        return instance.uriError == LAZY_SENTINEL || instance.uriError == instance.getBuiltinURIError();
-    }
-
     @Override
     public String getClassName() {
         return "global";
@@ -2288,7 +2020,7 @@
      * @return true if the value is a placeholder, false otherwise.
      */
     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
-        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+        return placeholder == LAZY_SENTINEL;
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1874,7 +1874,7 @@
     //TODO - fold these into the Link logics, but I'll do that as a later step, as I want to do a checkin
     //where everything works first
 
-    private static final <T> ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class<T> clazz) {
+    private static <T> ContinuousArrayData getContinuousNonEmptyArrayDataCCE(final Object self, final Class<T> clazz) {
         try {
             @SuppressWarnings("unchecked")
             final ContinuousArrayData data = (ContinuousArrayData)(T)((NativeArray)self).getArray();
@@ -1887,7 +1887,7 @@
         throw new ClassCastException();
     }
 
-    private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self) {
+    private static ContinuousArrayData getContinuousArrayDataCCE(final Object self) {
         try {
             return (ContinuousArrayData)((NativeArray)self).getArray();
          } catch (final NullPointerException e) {
@@ -1895,7 +1895,7 @@
          }
     }
 
-    private static final ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) {
+    private static ContinuousArrayData getContinuousArrayDataCCE(final Object self, final Class<?> elementType) {
         try {
            return (ContinuousArrayData)((NativeArray)self).getArray(elementType); //ensure element type can fit "elementType"
         } catch (final NullPointerException e) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDate.java	Wed Jul 05 20:41:30 2017 +0200
@@ -218,7 +218,7 @@
 
     @Override
     public String toString() {
-        return isValidDate() ? toString(this).toString() : INVALID_DATE;
+        return isValidDate() ? toString(this) : INVALID_DATE;
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 05 20:41:30 2017 +0200
@@ -803,7 +803,7 @@
 
     private static final Object REPLACE_VALUE = new Object();
 
-    private static final MethodHandle getReplaceValueInvoker() {
+    private static MethodHandle getReplaceValueInvoker() {
         return Global.instance().getDynamicInvoker(REPLACE_VALUE,
                 new Callable<MethodHandle>() {
                     @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java	Wed Jul 05 20:41:30 2017 +0200
@@ -1044,9 +1044,9 @@
         try {
             final long value = Long.parseLong(valueString, radix);
             if(value >= MIN_INT_L && value <= MAX_INT_L) {
-                return Integer.valueOf((int)value);
+                return (int)value;
             }
-            return Long.valueOf(value);
+            return value;
         } catch (final NumberFormatException e) {
             if (radix == 10) {
                 return Double.valueOf(valueString);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java	Wed Jul 05 20:41:30 2017 +0200
@@ -907,7 +907,7 @@
         OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
             this.data = data;
             this.log  = data.getLogger();
-            this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap<Integer, Type>() : invalidatedProgramPoints;
+            this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap<>() : invalidatedProgramPoints;
             newOptimisticAssumptions();
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java	Wed Jul 05 20:41:30 2017 +0200
@@ -994,7 +994,7 @@
      * @return a long
      */
     public static long toLong(final Object obj) {
-        return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj));
+        return obj instanceof Long ? ((Long)obj) : toLong(toNumber(obj));
     }
 
     /**
@@ -1056,7 +1056,7 @@
      */
     public static int toInt32Optimistic(final Object obj, final int programPoint) {
         if (obj != null && obj.getClass() == Integer.class) {
-            return ((Integer)obj).intValue();
+            return ((Integer)obj);
         }
         throw new UnwarrantedOptimismException(obj, programPoint);
     }
@@ -1954,11 +1954,11 @@
     public static MethodHandle unboxConstant(final Object o) {
         if (o != null) {
             if (o.getClass() == Integer.class) {
-                return MH.constant(int.class, ((Integer)o).intValue());
+                return MH.constant(int.class, ((Integer)o));
             } else if (o.getClass() == Long.class) {
-                return MH.constant(long.class, ((Long)o).longValue());
+                return MH.constant(long.class, ((Long)o));
             } else if (o.getClass() == Double.class) {
-                return MH.constant(double.class, ((Double)o).doubleValue());
+                return MH.constant(double.class, ((Double)o));
             }
         }
         return MH.constant(Object.class, o);
@@ -1983,7 +1983,7 @@
         }
     }
 
-    private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) {
+    private static List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) {
         return Collections.unmodifiableList(Arrays.asList(methodHandles));
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NashornLoader.java	Wed Jul 05 20:41:30 2017 +0200
@@ -156,7 +156,7 @@
         }
         // If the file does not exist, then assume that it's a directory
         if (!file.isFile()) {
-            name = name + "/";
+            name += "/";
         }
         try {
             return new URL("file", "", name);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java	Wed Jul 05 20:41:30 2017 +0200
@@ -260,7 +260,7 @@
             final Class<?> c = arg.getClass();
             if (c == Long.class) {
                 // Must check for Long separately, as Long.doubleValue() isn't precise.
-                return ((Long)arg).longValue();
+                return ((Long)arg);
             } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class ||
                     c == Byte.class) {
                 return ensureLong(((Number)arg).doubleValue(), programPoint);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java	Wed Jul 05 20:41:30 2017 +0200
@@ -562,8 +562,8 @@
 
     @Override
     public int hashCode() {
-        final Class<?> type = getLocalType();
-        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
+        final Class<?> t = getLocalType();
+        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (t == null ? 0 : t.hashCode());
     }
 
     @Override
@@ -588,7 +588,7 @@
                 getKey().equals(otherProperty.getKey());
     }
 
-    private static final String type(final Class<?> type) {
+    private static String type(final Class<?> type) {
         if (type == null) {
             return "undef";
         } else if (type == int.class) {
@@ -608,8 +608,8 @@
      */
     public final String toStringShort() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
-        sb.append(getKey()).append(" (").append(type(type)).append(')');
+        final Class<?>      t = getLocalType();
+        sb.append(getKey()).append(" (").append(type(t)).append(')');
         return sb.toString();
     }
 
@@ -625,7 +625,7 @@
     @Override
     public String toString() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
+        final Class<?>      t = getLocalType();
 
         sb.append(indent(getKey(), 20)).
             append(" id=").
@@ -635,7 +635,7 @@
             append(") ").
             append(getClass().getSimpleName()).
             append(" {").
-            append(indent(type(type), 5)).
+            append(indent(type(t), 5)).
             append('}');
 
         if (slot != -1) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Jul 05 20:41:30 2017 +0200
@@ -999,10 +999,10 @@
            for (final Property p : map0.getProperties()) {
                final Property p2 = map1.findProperty(p.getKey());
                if (p2 == null) {
-                   sb.append("FIRST ONLY : [" + p + "]");
+                   sb.append("FIRST ONLY : [").append(p).append("]");
                    found = true;
                } else if (p2 != p) {
-                   sb.append("DIFFERENT  : [" + p + "] != [" + p2 + "]");
+                   sb.append("DIFFERENT  : [").append(p).append("] != [").append(p2).append("]");
                    found = true;
                }
            }
@@ -1010,7 +1010,7 @@
            for (final Property p2 : map1.getProperties()) {
                final Property p1 = map0.findProperty(p2.getKey());
                if (p1 == null) {
-                   sb.append("SECOND ONLY: [" + p2 + "]");
+                   sb.append("SECOND ONLY: [").append(p2).append("]");
                    found = true;
                }
            }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RewriteException.java	Wed Jul 05 20:41:30 2017 +0200
@@ -359,9 +359,9 @@
         if (returnValue instanceof String) {
             str = '\'' + str + '\'';
         } else if (returnValue instanceof Double) {
-            str = str + 'd';
+            str += 'd';
         } else if (returnValue instanceof Long) {
-            str = str + 'l';
+            str += 'l';
         }
         return str;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java	Wed Jul 05 20:41:30 2017 +0200
@@ -611,7 +611,7 @@
                 obj = ((ScriptObject)obj).get(property);
                 if(Global.isLocationPropertyPlaceholder(obj)) {
                     if(CompilerConstants.__LINE__.name().equals(property)) {
-                        obj = Integer.valueOf(0);
+                        obj = 0;
                     } else {
                         obj = "";
                     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Source.java	Wed Jul 05 20:41:30 2017 +0200
@@ -995,7 +995,7 @@
         return initLogger(Context.getContextTrusted());
     }
 
-    private File dumpFile(final String dir) {
+    private File dumpFile(final File dirFile) {
         final URL u = getURL();
         final StringBuilder buf = new StringBuilder();
         // make it unique by prefixing current date & time
@@ -1010,11 +1010,17 @@
             buf.append(getName());
         }
 
-        return new File(dir, buf.toString());
+        return new File(dirFile, buf.toString());
     }
 
     void dump(final String dir) {
-        final File file = dumpFile(dir);
+        final File dirFile = new File(dir);
+        final File file = dumpFile(dirFile);
+        if (!dirFile.exists() && !dirFile.mkdirs()) {
+            debug("Skipping source dump for " + name);
+            return;
+        }
+
         try (final FileOutputStream fos = new FileOutputStream(file)) {
             final PrintWriter pw = new PrintWriter(fos);
             pw.print(data.toString());
@@ -1025,7 +1031,7 @@
                     ": " +
                     ECMAErrors.getMessage(
                         "io.error.cant.write",
-                        dir.toString() +
+                        dir +
                         " : " + ioExp.toString()));
         }
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -215,11 +215,8 @@
                     int.class);
 
     @SuppressWarnings("unused")
-    private static final boolean guard(final Class<? extends ContinuousArrayData> clazz, final ScriptObject sobj) {
-        if (sobj != null && sobj.getArray().getClass() == clazz) {
-            return true;
-        }
-        return false;
+    private static boolean guard(final Class<? extends ContinuousArrayData> clazz, final ScriptObject sobj) {
+        return sobj != null && sobj.getArray().getClass() == clazz;
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -138,7 +138,7 @@
         final Object[] oarray = new Object[trim ? len : array.length];
 
         for (int index = 0; index < len; index++) {
-            oarray[index] = Integer.valueOf(array[index]);
+            oarray[index] = array[index];
         }
 
         return oarray;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -91,7 +91,7 @@
         final Object[] oarray = new Object[trim ? len : array.length];
 
         for (int index = 0; index < len; index++) {
-            oarray[index] = Long.valueOf(array[index]);
+            oarray[index] = array[index];
         }
 
         return oarray;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -91,7 +91,7 @@
         final Object[] oarray = new Object[trim ? len : array.length];
 
         for (int index = 0; index < len; index++) {
-            oarray[index] = Double.valueOf(array[index]);
+            oarray[index] = array[index];
         }
         return oarray;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Wed Jul 05 20:41:30 2017 +0200
@@ -95,11 +95,11 @@
         final TreeMap<Long, Object> newSparseMap = new TreeMap<>();
 
         for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
-            final long newIndex = entry.getKey().longValue() - by;
+            final long newIndex = entry.getKey() - by;
             if (newIndex < maxDenseLength) {
                 underlying = underlying.set((int) newIndex, entry.getValue(), false);
             } else if (newIndex >= 0) {
-                newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
+                newSparseMap.put(newIndex, entry.getValue());
             }
         }
 
@@ -114,7 +114,7 @@
         if (len + by > maxDenseLength) {
             for (long i = maxDenseLength - by; i < len; i++) {
                 if (underlying.has((int) i)) {
-                    newSparseMap.put(Long.valueOf(i + by), underlying.getObject((int) i));
+                    newSparseMap.put(i + by, underlying.getObject((int) i));
                 }
             }
             underlying = underlying.shrink((int) (maxDenseLength - by));
@@ -123,8 +123,8 @@
         underlying.shiftRight(by);
 
         for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
-            final long newIndex = entry.getKey().longValue() + by;
-            newSparseMap.put(Long.valueOf(newIndex), entry.getValue());
+            final long newIndex = entry.getKey() + by;
+            newSparseMap.put(newIndex, entry.getValue());
         }
 
         sparseMap = newSparseMap;
@@ -158,7 +158,7 @@
             setLength(newLength);
         }
 
-        sparseMap.subMap(Long.valueOf(newLength), Long.MAX_VALUE).clear();
+        sparseMap.subMap(newLength, Long.MAX_VALUE).clear();
         setLength(newLength);
         return this;
     }
@@ -333,7 +333,7 @@
     }
 
     private static Long indexToKey(final int index) {
-        return Long.valueOf(ArrayIndex.toLongIndex(index));
+        return ArrayIndex.toLongIndex(index);
     }
 
     @Override
@@ -355,7 +355,7 @@
             return result;
         }
         setLength(len - 1);
-        final Long key = Long.valueOf(len - 1);
+        final Long key = len - 1;
         return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java	Wed Jul 05 20:41:30 2017 +0200
@@ -47,7 +47,6 @@
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.objects.ScriptFunctionImpl;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java	Wed Jul 05 20:41:30 2017 +0200
@@ -107,7 +107,7 @@
         if (o instanceof Number) {
             final int ival = ((Number)o).intValue();
             if (ival >= Character.MIN_VALUE && ival <= Character.MAX_VALUE) {
-                return Character.valueOf((char) ival);
+                return (char) ival;
             }
 
             throw typeError("cant.convert.number.to.char");
@@ -196,13 +196,13 @@
                 return ((Integer)obj).longValue();
             } else if (obj instanceof Double) {
                 final Double d = (Double)obj;
-                if(Double.isInfinite(d.doubleValue())) {
+                if(Double.isInfinite(d)) {
                     return 0L;
                 }
                 return d.longValue();
             } else if (obj instanceof Float) {
                 final Float f = (Float)obj;
-                if(Float.isInfinite(f.floatValue())) {
+                if(Float.isInfinite(f)) {
                     return 0L;
                 }
                 return f.longValue();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java	Wed Jul 05 20:41:30 2017 +0200
@@ -101,9 +101,7 @@
     }
 
     public void copy(final BitSet other) {
-        for (int i=0; i<BITSET_SIZE; i++) {
-            bits[i] = other.bits[i];
-        }
+        System.arraycopy(other.bits, 0, bits, 0, BITSET_SIZE);
     }
 
     public int numOn() {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Region.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Region.java	Wed Jul 05 20:41:30 2017 +0200
@@ -38,7 +38,7 @@
         final StringBuilder sb = new StringBuilder();
         sb.append("Region: \n");
         for (int i=0; i<beg.length; i++) {
-            sb.append(" " + i + ": (" + beg[i] + "-" + end[i] + ")");
+            sb.append(" ").append(i).append(": (").append(beg[i]).append("-").append(end[i]).append(")");
         }
         return sb.toString();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -60,8 +60,8 @@
     @Override
     public String toString(final int level) {
         final StringBuilder value = new StringBuilder();
-        value.append("\n  type: " + typeToString());
-        value.append("\n  target: " + pad(target, level + 1));
+        value.append("\n  type: ").append(typeToString());
+        value.append("\n  target: ").append(pad(target, level + 1));
         return value.toString();
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -124,9 +124,9 @@
     @Override
     public String toString(final int level) {
         final StringBuilder value = new StringBuilder();
-        value.append("\n  flags: " + flagsToString());
-        value.append("\n  bs: " + pad(bs, level + 1));
-        value.append("\n  mbuf: " + pad(mbuf, level + 1));
+        value.append("\n  flags: ").append(flagsToString());
+        value.append("\n  bs: ").append(pad(bs, level + 1));
+        value.append("\n  mbuf: ").append(pad(mbuf, level + 1));
 
         return value.toString();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -148,8 +148,8 @@
     @Override
     public String toString(final int level) {
         final StringBuilder value = new StringBuilder();
-        value.append("\n  car: " + pad(car, level + 1));
-        value.append("\n  cdr: " + (cdr == null ? "NULL" : cdr.toString()));
+        value.append("\n  car: ").append(pad(car, level + 1));
+        value.append("\n  cdr: ").append(cdr == null ? "NULL" : cdr.toString());
 
         return value.toString();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -80,15 +80,15 @@
     @Override
     public String toString(final int level) {
         final StringBuilder value = new StringBuilder(super.toString(level));
-        value.append("\n  type: " + typeToString());
-        value.append("\n  regNum: " + regNum);
-        value.append("\n  option: " + Option.toString(option));
-        value.append("\n  target: " + pad(target, level + 1));
-        value.append("\n  callAddr: " + callAddr);
-        value.append("\n  minLength: " + minLength);
-        value.append("\n  maxLength: " + maxLength);
-        value.append("\n  charLength: " + charLength);
-        value.append("\n  optCount: " + optCount);
+        value.append("\n  type: ").append(typeToString());
+        value.append("\n  regNum: ").append(regNum);
+        value.append("\n  option: ").append(Option.toString(option));
+        value.append("\n  target: ").append(pad(target, level + 1));
+        value.append("\n  callAddr: ").append(callAddr);
+        value.append("\n  minLength: ").append(minLength);
+        value.append("\n  maxLength: ").append(maxLength);
+        value.append("\n  charLength: ").append(charLength);
+        value.append("\n  optCount: ").append(optCount);
 
         return value.toString();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java	Wed Jul 05 20:41:30 2017 +0200
@@ -85,7 +85,7 @@
     @Override
     public final String toString() {
         final StringBuilder s = new StringBuilder();
-        s.append("<" + getAddressName() + " (" + (parent == null ? "NULL" : parent.getAddressName())  + ")>");
+        s.append("<").append(getAddressName()).append(" (").append(parent == null ? "NULL" : parent.getAddressName()).append(")>");
         return s + toString(0);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -118,14 +118,14 @@
     @Override
     public String toString(final int level) {
         final StringBuilder value = new StringBuilder(super.toString(level));
-        value.append("\n  target: " + pad(target, level + 1));
-        value.append("\n  lower: " + lower);
-        value.append("\n  upper: " + upper);
-        value.append("\n  greedy: " + greedy);
-        value.append("\n  targetEmptyInfo: " + targetEmptyInfo);
-        value.append("\n  headExact: " + pad(headExact, level + 1));
-        value.append("\n  nextHeadExact: " + pad(nextHeadExact, level + 1));
-        value.append("\n  isRefered: " + isRefered);
+        value.append("\n  target: ").append(pad(target, level + 1));
+        value.append("\n  lower: ").append(lower);
+        value.append("\n  upper: ").append(upper);
+        value.append("\n  greedy: ").append(greedy);
+        value.append("\n  targetEmptyInfo: ").append(targetEmptyInfo);
+        value.append("\n  headExact: ").append(pad(headExact, level + 1));
+        value.append("\n  nextHeadExact: ").append(pad(nextHeadExact, level + 1));
+        value.append("\n  isRefered: ").append(isRefered);
 
         return value.toString();
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java	Wed Jul 05 20:41:30 2017 +0200
@@ -71,7 +71,7 @@
             final char[] tmp = new char[len + NODE_STR_MARGIN];
             System.arraycopy(chars, p, tmp, 0, end - p);
             chars = tmp;
-            end = end - p;
+            end -= p;
             p = 0;
             clearShared();
         } else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Wed Jul 05 20:41:30 2017 +0200
@@ -54,7 +54,6 @@
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/ShellFunctions.java	Wed Jul 05 20:41:30 2017 +0200
@@ -29,10 +29,8 @@
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.io.BufferedReader;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import jdk.nashorn.internal.runtime.JSType;
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java	Wed Jul 05 20:41:30 2017 +0200
@@ -176,7 +176,7 @@
     }
 
     public Boolean booleanBoxingMethod(final Boolean arg) {
-        return !arg.booleanValue();
+        return !arg;
     }
 
     public boolean[] booleanArrayMethod(final boolean arg[]) {
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -573,7 +573,7 @@
     }
 
     // properties that can be read by any code
-    private static String[] propNames = {
+    private static final String[] PROP_NAMES = {
         "java.version",
         "java.vendor",
         "java.vendor.url",
@@ -601,7 +601,7 @@
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
 
-        for (final String name : propNames) {
+        for (final String name : PROP_NAMES) {
             checkProperty(e, name);
         }
     }
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -278,7 +278,7 @@
 
         ScriptObjectMirror obj = (ScriptObjectMirror)e.eval(
             "({ valueOf: function() { return 42 } })");
-        assertEquals(Double.valueOf(42.0), obj.to(Double.class));
+        assertEquals(42.0, obj.to(Double.class));
 
         obj = (ScriptObjectMirror)e.eval(
             "({ toString: function() { return 'foo' } })");
--- a/nashorn/test/src/jdk/nashorn/api/tree/test/ParseAPITest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/api/tree/test/ParseAPITest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -67,7 +67,7 @@
             parseTestSet(TEST262_SUITE_DIR, new TestFilter() {
                 @Override
                 public boolean exclude(final File file, final String content) {
-                    return content.indexOf("@negative") != -1;
+                    return content.contains("@negative");
                 }
             });
         }
--- a/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java	Wed Jul 05 20:41:30 2017 +0200
@@ -272,10 +272,10 @@
         Double nashornToRhino = null;
         Double nashornToV8 = null;
         if (rhino != null && rhino != 0) {
-            nashornToRhino = nashorn.doubleValue() / rhino.doubleValue();
+            nashornToRhino = nashorn / rhino;
         }
         if (v8 != null && rhino != 0) {
-            nashornToV8 = nashorn.doubleValue() / v8.doubleValue();
+            nashornToV8 = nashorn / v8;
         }
         final String normalizedBenchmark=benchmark.replace("-", "");
         System.out.println("benchmark-" + normalizedBenchmark + "-nashorn=" + nashorn);
@@ -300,20 +300,12 @@
 
     boolean checkRhinoPresence() {
         final String rhinojar = System.getProperty("rhino.jar");
-        if (rhinojar != null) {
-            // System.out.println("Rhino jar found; performing comparison testing");
-            return true;
-        }
-        return false;
+        return rhinojar != null;
     }
 
     boolean checkV8Presence() {
         final String v8shell = System.getProperty("v8.shell.full.path");
-        if (v8shell != null) {
-            // System.out.println("d8 found; performing comparison testing");
-            return true;
-        }
-        return false;
+        return v8shell != null;
     }
 
 }
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java	Wed Jul 05 20:41:30 2017 +0200
@@ -62,7 +62,7 @@
 
     @Test
     public void unwarrantedOptimismExceptionNotSerializable() {
-        tryToSerialize(new UnwarrantedOptimismException(new Double(1.0), 128));
+        tryToSerialize(new UnwarrantedOptimismException(1.0, 128));
     }
 
     private static void tryToSerialize(final Object obj) {
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java	Wed Jul 05 20:41:30 2017 +0200
@@ -159,7 +159,7 @@
         forkJVMOptions = (vmOptions != null)? vmOptions.split(" ") : new String[0];
     }
 
-    private static ThreadLocal<ScriptEvaluator> evaluators = new ThreadLocal<>();
+    private static final ThreadLocal<ScriptEvaluator> EVALUATORS = new ThreadLocal<>();
 
     /**
      * Create a script evaluator or return from cache
@@ -167,7 +167,7 @@
      */
     protected ScriptEvaluator getEvaluator() {
         synchronized (AbstractScriptRunnable.class) {
-            ScriptEvaluator evaluator = evaluators.get();
+            ScriptEvaluator evaluator = EVALUATORS.get();
             if (evaluator == null) {
                 if (sharedContext) {
                     final String[] args;
@@ -177,10 +177,10 @@
                         args = new String[] { framework };
                     }
                     evaluator = new SharedContextEvaluator(args);
-                    evaluators.set(evaluator);
+                    EVALUATORS.set(evaluator);
                 } else {
                     evaluator = new SeparateContextEvaluator();
-                    evaluators.set(evaluator);
+                    EVALUATORS.set(evaluator);
                 }
             }
             return evaluator;
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java	Wed Jul 05 20:41:30 2017 +0200
@@ -378,7 +378,7 @@
      * @return true if optimistic type override has been set by test suite
      */
     public static boolean hasOptimisticOverride() {
-        return Boolean.valueOf(OPTIMISTIC_OVERRIDE).toString().equals(System.getProperty("optimistic.override"));
+        return Boolean.toString(OPTIMISTIC_OVERRIDE).equals(System.getProperty("optimistic.override"));
     }
 
     /**
@@ -391,8 +391,8 @@
     public static String[] addExplicitOptimisticTypes(final String[] args) {
         if (hasOptimisticOverride()) {
             final List<String> newList = new ArrayList<>(Arrays.asList(args));
-            newList.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
-            return newList.toArray(new String[0]);
+            newList.add("--optimistic-types=" + OPTIMISTIC_OVERRIDE);
+            return newList.toArray(new String[newList.size()]);
         }
         return args;
     }
@@ -405,7 +405,7 @@
      */
     public static void addExplicitOptimisticTypes(final List<String> args) {
         if (hasOptimisticOverride()) {
-            args.add("--optimistic-types=" + Boolean.valueOf(OPTIMISTIC_OVERRIDE));
+            args.add("--optimistic-types=" + OPTIMISTIC_OVERRIDE);
         }
     }
 
--- a/nashorn/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java	Wed Jul 05 20:40:53 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java	Wed Jul 05 20:41:30 2017 +0200
@@ -64,9 +64,9 @@
 
     private static void walkCollection(final Collection<Object> c) {
         final Iterator<Object> it = c.iterator();
-        assertEquals(it.next(), Integer.valueOf(1));
-        assertEquals(it.next(), Integer.valueOf(2));
-        assertEquals(it.next(), Double.valueOf(3.3));
+        assertEquals(it.next(), 1);
+        assertEquals(it.next(), 2);
+        assertEquals(it.next(), 3.3);
         assertEquals(it.next(), "foo");
         assertFalse(it.hasNext());
     }