Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 16207a2..cf8ccea 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -667,3 +667,18 @@
 14388b14d4847c3eacce677eae37980e6fa545cd jdk8u112-b16
 1a7a5fe22a028e438a724d909d27da2ea96c6d86 jdk8u112-b31
 911c506096560e49442a4c8f598f7f43c2339720 jdk8u112-b32
+8e27761a403ff4b237219cfb22731e127a1d1744 jdk8u112-b33
+58ac6fce1d10c1fba366ad58950a6a54b27a5bcb jdk8u121-b00
+a2c5309f998f8aa207a6e381464263e9a7dd50e0 jdk8u121-b01
+a2aa2e98905609a0b5809a38163239a7c97d31c1 jdk8u121-b02
+863cc5f631621da7026ae42828016a8070a1056d jdk8u121-b03
+c14b6b6d51d86fb36c8af1021e0bdf55f9cf7440 jdk8u121-b04
+ee85a5feaf10020ca74f071c609f44d8c4b2866c jdk8u121-b05
+7fdb1ca64ac7f62e3b17c699e493568da38ea4f3 jdk8u121-b06
+22eb8db7bf5b140e5d84fd91c7ea16c02736cd13 jdk8u121-b07
+b9e523138b2dc4e8456c3ac295f9bb57d21f1f77 jdk8u121-b08
+6eb8178c697ef3d55d99f222121093e6ad0363c4 jdk8u121-b09
+51c053cb4468768757cb25e687edd8e021ff2eb3 jdk8u121-b10
+bfe05759587ddc30a32c00637180588cec309ee3 jdk8u121-b11
+97c858f7f7c827730d05eb69134ac89e156f8685 jdk8u121-b12
+f2b5b6ab1f5544b92074adb5bb80cc031649d0e7 jdk8u121-b13
diff --git a/corba/.hgtags b/corba/.hgtags
index d5a4508..d63b288 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -702,3 +702,18 @@
 8ef3cc2bbc7dc687e9502ae957337b1ded1b32d4 jdk8u112-b16
 7d4291146927c3430652a07f506d530c2eff7eb9 jdk8u112-b31
 46db19bfd51b4039cff4dae563c3b5d3f70d64da jdk8u112-b32
+d52e17760c1dafa4fa17ec388aeaaf8fcacb444b jdk8u112-b33
+3a25f8a752524bad7e78800158c485b890be3982 jdk8u121-b00
+1ebd97292358cd158b6f7d5884526207fbfe796e jdk8u121-b01
+349d130d7a7f2bcaaed8dd2696030022eb4e7b75 jdk8u121-b02
+2090928e4b80e849fff4797ee05b99c076f14667 jdk8u121-b03
+a80781c494079d7d92f806f1f4cf57e856435781 jdk8u121-b04
+cf1b7263a217eb891597aa5b64edde94970600c6 jdk8u121-b05
+f98001da328ffdb5de76c4ba6672f3bda4c22e51 jdk8u121-b06
+367d1b35f2b2ccf47ba0c1c565613c4741b58056 jdk8u121-b07
+43598d9344e383d039eabeb3ee59316d0cc3e4c6 jdk8u121-b08
+c0210b2071599fa54aec59576ca942461ed8160a jdk8u121-b09
+e24a55876a79b630e8cfca7a1b38a0ee372f8533 jdk8u121-b10
+acbfa2934b2411dd20aacb42d1c8dd198fe9f8e9 jdk8u121-b11
+cc9a5d631b77582d52aceaf6d6066e99533d1756 jdk8u121-b12
+386e9b79fcf5bfad5ff7b0fc991a7c6c5cbfed17 jdk8u121-b13
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index c8a4426..874dc9e 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -932,3 +932,18 @@
 e134dc1879b72124e478be01680b0646a2fbf585 jdk8u112-b16
 87440ed4e1de7753a436f957d35555d8b4e26f1d jdk8u112-b31
 ba25f5833a128b8062e597f794efda26b30f095d jdk8u112-b32
+919ffdca10c2721ee0f6f233e704709174556510 jdk8u112-b33
+3b0e5f01891f5ebbf67797b1aae786196f1bb4f6 jdk8u121-b00
+251a2493b1857f2ff4f11eab2dfd8b2fe8ed441b jdk8u121-b01
+70c4a50f576a01ec975d0a02b3642ee33db39ed8 jdk8u121-b02
+fa3bb4153a28b45a7a80cbf1058979b8f1c8b104 jdk8u121-b03
+35cff8508ca15dc18c598501cab160aee7220d44 jdk8u121-b04
+f71447f104ce7b018a08bf1cf385438525744d13 jdk8u121-b05
+49a2fc91c46f3d73aac7dbd420a4a007fe453ef8 jdk8u121-b06
+f31c7533cfcb55acfb8dc5b31779d3a64708f5ce jdk8u121-b07
+02a3d0dcbeddd8507d9a4b1f5a9f83aca75e5acb jdk8u121-b08
+8cae1bdbd73cb1a84afad07a8e18467f56560bc4 jdk8u121-b09
+f26f6895c9dfb32dfb4c228d69b371d8ab118536 jdk8u121-b10
+11f91811e4d7e5ddfaf938dcf386ec8fe5bf7b7c jdk8u121-b11
+b132b08b28bf23a26329928cf6b4ffda5857f4d3 jdk8u121-b12
+90f94521c3515e5f27af0ab9b31d036e88bb322a jdk8u121-b13
diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
index 9678287..33a289f 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
@@ -944,11 +944,12 @@
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
         parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           parsed_annotations,
                           CHECK);
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         runtime_invisible_annotations_length = attribute_length;
         runtime_invisible_annotations = cfs->get_u1_buffer();
@@ -1655,6 +1656,11 @@
   return index;
 }
 
+// Safely increment index by val if does not pass limit
+#define SAFE_ADD(index, limit, val) \
+if (index >= limit - val) return limit; \
+index += val;
+
 // Skip an annotation value.  Return >=limit if there is any problem.
 int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
   // value := switch (tag:u1) {
@@ -1665,19 +1671,19 @@
   //   case @: annotation;
   //   case s: s_con:u2;
   // }
-  if ((index += 1) >= limit)  return limit;  // read tag
+  SAFE_ADD(index, limit, 1); // read tag
   u1 tag = buffer[index-1];
   switch (tag) {
   case 'B': case 'C': case 'I': case 'S': case 'Z':
   case 'D': case 'F': case 'J': case 'c': case 's':
-    index += 2;  // skip con or s_con
+    SAFE_ADD(index, limit, 2);  // skip con or s_con
     break;
   case 'e':
-    index += 4;  // skip e_class, e_name
+    SAFE_ADD(index, limit, 4);  // skip e_class, e_name
     break;
   case '[':
     {
-      if ((index += 2) >= limit)  return limit;  // read nval
+      SAFE_ADD(index, limit, 2);  // read nval
       int nval = Bytes::get_Java_u2(buffer+index-2);
       while (--nval >= 0 && index < limit) {
         index = skip_annotation_value(buffer, limit, index);
@@ -1699,8 +1705,8 @@
                                         ClassFileParser::AnnotationCollector* coll,
                                         TRAPS) {
   // annotations := do(nann:u2) {annotation}
-  int index = 0;
-  if ((index += 2) >= limit)  return;  // read nann
+  int index = 2;
+  if (index >= limit)  return;  // read nann
   int nann = Bytes::get_Java_u2(buffer+index-2);
   enum {  // initial annotation layout
     atype_off = 0,      // utf8 such as 'Ljava/lang/annotation/Retention;'
@@ -1719,7 +1725,8 @@
       s_size = 9,
     min_size = 6        // smallest possible size (zero members)
   };
-  while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
+  // Cannot add min_size to index in case of overflow MAX_INT
+  while ((--nann) >= 0 && (index-2 <= limit - min_size)) {
     int index0 = index;
     index = skip_annotation(buffer, limit, index);
     u1* abase = buffer + index0;
@@ -2324,10 +2331,11 @@
         runtime_visible_annotations_length = method_attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK_(nullHandle));
         parse_annotations(runtime_visible_annotations,
             runtime_visible_annotations_length, &parsed_annotations,
             CHECK_(nullHandle));
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
         runtime_invisible_annotations_length = method_attribute_length;
         runtime_invisible_annotations = cfs->get_u1_buffer();
@@ -2953,11 +2961,12 @@
         runtime_visible_annotations_length = attribute_length;
         runtime_visible_annotations = cfs->get_u1_buffer();
         assert(runtime_visible_annotations != NULL, "null visible annotations");
+        cfs->guarantee_more(runtime_visible_annotations_length, CHECK);
         parse_annotations(runtime_visible_annotations,
                           runtime_visible_annotations_length,
                           parsed_annotations,
                           CHECK);
-        cfs->skip_u1(runtime_visible_annotations_length, CHECK);
+        cfs->skip_u1_fast(runtime_visible_annotations_length);
       } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
         runtime_invisible_annotations_length = attribute_length;
         runtime_invisible_annotations = cfs->get_u1_buffer();
diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.cpp b/hotspot/src/share/vm/classfile/stackMapFrame.cpp
index 1332a08..f5d108b 100644
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -155,47 +155,8 @@
   return i;
 }
 
-bool StackMapFrame::has_flag_match_exception(
-    const StackMapFrame* target) const {
-  // We allow flags of {UninitThis} to assign to {} if-and-only-if the
-  // target frame does not depend upon the current type.
-  // This is slightly too strict, as we need only enforce that the
-  // slots that were initialized by the <init> (the things that were
-  // UninitializedThis before initialize_object() converted them) are unused.
-  // However we didn't save that information so we'll enforce this upon
-  // anything that might have been initialized.  This is a rare situation
-  // and javac never generates code that would end up here, but some profilers
-  // (such as NetBeans) might, when adding exception handlers in <init>
-  // methods to cover the invokespecial instruction.  See 7020118.
-
-  assert(max_locals() == target->max_locals() &&
-         stack_size() == target->stack_size(), "StackMap sizes must match");
-
-  VerificationType top = VerificationType::top_type();
-  VerificationType this_type = verifier()->current_type();
-
-  if (!flag_this_uninit() || target->flags() != 0) {
-    return false;
-  }
-
-  for (int i = 0; i < target->locals_size(); ++i) {
-    if (locals()[i] == this_type && target->locals()[i] != top) {
-      return false;
-    }
-  }
-
-  for (int i = 0; i < target->stack_size(); ++i) {
-    if (stack()[i] == this_type && target->stack()[i] != top) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
 bool StackMapFrame::is_assignable_to(
-    const StackMapFrame* target, bool is_exception_handler,
-    ErrorContext* ctx, TRAPS) const {
+    const StackMapFrame* target, ErrorContext* ctx, TRAPS) const {
   if (_max_locals != target->max_locals()) {
     *ctx = ErrorContext::locals_size_mismatch(
         _offset, (StackMapFrame*)this, (StackMapFrame*)target);
@@ -226,8 +187,7 @@
     return false;
   }
 
-  bool match_flags = (_flags | target->flags()) == target->flags();
-  if (match_flags || is_exception_handler && has_flag_match_exception(target)) {
+  if ((_flags | target->flags()) == target->flags()) {
     return true;
   } else {
     *ctx = ErrorContext::bad_flags(target->offset(),
diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp
index 24cbae3..d6e18ae 100644
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,8 +167,7 @@
 
   // Return true if this stack map frame is assignable to target.
   bool is_assignable_to(
-      const StackMapFrame* target, bool is_exception_handler,
-      ErrorContext* ctx, TRAPS) const;
+      const StackMapFrame* target, ErrorContext* ctx, TRAPS) const;
 
   inline void set_mark() {
 #ifdef ASSERT
@@ -290,8 +289,6 @@
   int is_assignable_to(
     VerificationType* src, VerificationType* target, int32_t len, TRAPS) const;
 
-  bool has_flag_match_exception(const StackMapFrame* target) const;
-
   TypeOrigin stack_top_ctx();
 
   void print_on(outputStream* str) const;
diff --git a/hotspot/src/share/vm/classfile/stackMapTable.cpp b/hotspot/src/share/vm/classfile/stackMapTable.cpp
index 1c92b61..547dcf6 100644
--- a/hotspot/src/share/vm/classfile/stackMapTable.cpp
+++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,26 +70,25 @@
 
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   int index = get_index_from_offset(target);
-  return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD);
+  return match_stackmap(frame, target, index, match, update, ctx, THREAD);
 }
 
 // Match and/or update current_frame to the frame in stackmap table with
 // specified offset and frame index. Return true if the two frames match.
-// handler is true if the frame in stackmap_table is for an exception handler.
 //
-// The values of match and update are:                  _match__update__handler
+// The values of match and update are:                  _match__update
 //
-// checking a branch target:                             true   false   false
-// checking an exception handler:                        true   false   true
+// checking a branch target:                             true   false
+// checking an exception handler:                        true   false
 // linear bytecode verification following an
-// unconditional branch:                                 false  true    false
+// unconditional branch:                                 false  true
 // linear bytecode verification not following an
-// unconditional branch:                                 true   true    false
+// unconditional branch:                                 true   true
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target, int32_t frame_index,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, ErrorContext* ctx, TRAPS) const {
   if (frame_index < 0 || frame_index >= _frame_count) {
     *ctx = ErrorContext::missing_stackmap(frame->offset());
     frame->verifier()->verify_error(
@@ -102,7 +101,7 @@
   if (match) {
     // Has direct control flow from last instruction, need to match the two
     // frames.
-    result = frame->is_assignable_to(stackmap_frame, handler,
+    result = frame->is_assignable_to(stackmap_frame,
         ctx, CHECK_VERIFY_(frame->verifier(), result));
   }
   if (update) {
@@ -126,7 +125,7 @@
     StackMapFrame* frame, int32_t target, TRAPS) const {
   ErrorContext ctx;
   bool match = match_stackmap(
-    frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier()));
+    frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
   if (!match || (target < 0 || target >= _code_length)) {
     frame->verifier()->verify_error(ctx,
         "Inconsistent stackmap frames at branch target %d", target);
diff --git a/hotspot/src/share/vm/classfile/stackMapTable.hpp b/hotspot/src/share/vm/classfile/stackMapTable.hpp
index 5354a0b..2ee1f5f 100644
--- a/hotspot/src/share/vm/classfile/stackMapTable.hpp
+++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,12 +74,12 @@
   // specified offset. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
   // Match and/or update current_frame to the frame in stackmap table with
   // specified offset and frame index. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
-    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, ErrorContext* ctx, TRAPS) const;
 
   // Check jump instructions. Make sure there are no uninitialized
   // instances on backward branch.
diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp
index 58bd4f7..17a9959 100644
--- a/hotspot/src/share/vm/classfile/verifier.cpp
+++ b/hotspot/src/share/vm/classfile/verifier.cpp
@@ -504,19 +504,13 @@
     stack_map_frame* sm_frame = sm_table->entries();
     streamIndentor si2(ss);
     int current_offset = -1;
-    // Subtract two from StackMapAttribute length because the length includes
-    // two bytes for number of table entries.
-    size_t sm_table_space = method->stackmap_data()->length() - 2;
+    address end_of_sm_table = (address)sm_table + method->stackmap_data()->length();
     for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
       ss->indent();
-      size_t sm_frame_size = sm_frame->size();
-      // If the size of the next stackmap exceeds the length of the entire
-      // stackmap table then print a truncated message and return.
-      if (sm_frame_size > sm_table_space) {
+      if (!sm_frame->verify((address)sm_frame, end_of_sm_table)) {
         sm_frame->print_truncated(ss, current_offset);
         return;
       }
-      sm_table_space -= sm_frame_size;
       sm_frame->print_on(ss, current_offset);
       ss->cr();
       current_offset += sm_frame->offset_delta();
@@ -1820,7 +1814,7 @@
       // If matched, current_frame will be updated by this method.
       bool matches = stackmap_table->match_stackmap(
         current_frame, this_offset, stackmap_index,
-        !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0));
+        !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0));
       if (!matches) {
         // report type error
         verify_error(ctx, "Instruction type does not match stack map");
@@ -1867,7 +1861,7 @@
       }
       ErrorContext ctx;
       bool matches = stackmap_table->match_stackmap(
-        new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this));
+        new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this));
       if (!matches) {
         verify_error(ctx, "Stack map does not match the one at "
             "exception handler %d", handler_pc);
diff --git a/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java b/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
index 5fc7268..9c3e8f7 100644
--- a/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
+++ b/hotspot/test/runtime/handlerInTry/LoadHandlerInTry.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 8075118
- * @summary Allow a ctor to call super() from a switch bytecode.
+ * @summary JVM stuck in infinite loop during verification
  * @compile HandlerInTry.jasm
  * @compile IsolatedHandlerInTry.jasm
  * @run main/othervm -Xverify:all LoadHandlerInTry
@@ -70,9 +70,10 @@
         System.out.println("Regression test for bug 8075118");
         try {
             Class newClass = Class.forName("HandlerInTry");
-        } catch (Exception e) {
-            System.out.println("Failed: Exception was thrown: " + e.toString());
-            throw e;
+            throw new RuntimeException(
+                 "Failed to throw VerifyError for HandlerInTry");
+        } catch (java.lang.VerifyError e) {
+            System.out.println("Passed: VerifyError exception was thrown");
         }
 
         try {
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 91d5ce6..83c19d2 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -672,3 +672,18 @@
 66ef33852d93fe8469724cbdbbdd57dd0e506a6f jdk8u112-b16
 376ba5ed85cc43ef8f13eddc592126e42887ac60 jdk8u112-b31
 a7e8e66d1e88a32c50e71cc324834e750cfe33f3 jdk8u112-b32
+cc98f1eeb44bb0c54b6ff44108fef3620f4b5d35 jdk8u112-b33
+9bbba018c96a17c5b5583e26a38d3c1e910178ef jdk8u121-b00
+21da1526aeaf09fde06ec0a5504b564b591f7d03 jdk8u121-b01
+a0ad630d453b3b3c5b1185056a9216281f3085cd jdk8u121-b02
+e76bf2e89efd4b98fa399e4c7db489fc86275257 jdk8u121-b03
+05ac2cb9826a084578dd3b52582323b2473da631 jdk8u121-b04
+49e1091960832ddb247de2825414577d398ba15f jdk8u121-b05
+e31f5ceba6bf5ab6ddfdd1bffef3536e6af8f78b jdk8u121-b06
+d12a9b165b4789915a6ef267099db9721a9887f8 jdk8u121-b07
+c7325d95eaba9e5ef329527107bafc68346d4264 jdk8u121-b08
+f805dcb18704a7028b9d193e8fe661381d473213 jdk8u121-b09
+989c624fdc1f306f1b6068b0529268a46e21ee6b jdk8u121-b10
+77c3d617ae4c28c6e29d51411ab2b2c9eb24683f jdk8u121-b11
+f9cb265fd35fc60dccd75075614f8e897af92ab3 jdk8u121-b12
+b8d4e47240711ff66f9347483d20c84466d75c89 jdk8u121-b13
diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java
index 5894996..09061ea 100644
--- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java
+++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/compiler/Stylesheet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -31,6 +31,7 @@
 import com.sun.org.apache.bcel.internal.generic.GETSTATIC;
 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
+import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
 import com.sun.org.apache.bcel.internal.generic.ISTORE;
 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
@@ -1252,6 +1253,10 @@
                                 classGen.getConstantPool());
         transf.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException");
 
+        // call resetPrefixIndex at the beginning of transform
+        final int check = cpg.addMethodref(BASIS_LIBRARY_CLASS, "resetPrefixIndex", "()V");
+        il.append(new INVOKESTATIC(check));
+
         // Define and initialize current with the root node
         final LocalVariableGen current =
             transf.addLocalVariable("current",
diff --git a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
index dc3a3ce..804b154 100644
--- a/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
+++ b/jaxp/src/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -48,6 +48,7 @@
 import java.text.NumberFormat;
 import java.util.Locale;
 import java.util.ResourceBundle;
+import java.util.concurrent.atomic.AtomicInteger;
 import javax.xml.transform.dom.DOMSource;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
@@ -1530,16 +1531,25 @@
     }
 
     /**
-     * This function is used in the execution of xsl:element
+     * These functions are used in the execution of xsl:element to generate
+     * and reset namespace prefix index local to current transformation process
      */
-    private static int prefixIndex = 0;
-
     public static String generatePrefix() {
-        synchronized (BasisLibrary.class) {
-            return ("ns" + prefixIndex++);
-        }
+        return ("ns" + threadLocalPrefixIndex.get().getAndIncrement());
     }
 
+    public static void resetPrefixIndex() {
+        threadLocalPrefixIndex.get().set(0);
+    }
+
+    private static final ThreadLocal<AtomicInteger> threadLocalPrefixIndex =
+        new ThreadLocal<AtomicInteger>() {
+            @Override
+            protected AtomicInteger initialValue() {
+                return new AtomicInteger();
+            }
+        };
+
     public static final String RUN_TIME_INTERNAL_ERR =
                                            "RUN_TIME_INTERNAL_ERR";
     public static final String RUN_TIME_COPY_ERR =
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index ee1b585..210bb12 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -661,3 +661,18 @@
 d82dd7a24a496e26987caa328d1fb4fc794a4770 jdk8u112-b16
 021da5d50285a523d4622a727ea1a7019f2b52e4 jdk8u112-b31
 4d1398900b3745c3181450e981ed45696a1c97fc jdk8u112-b32
+424b6ee9ade3f63228867933fe8a995880379b97 jdk8u112-b33
+452662a83e5bc6dc7e9425ddd10f6c8fc98d50d8 jdk8u121-b00
+9cd16be39ca6f2c8f7cc99ad07a77bb9d0696c75 jdk8u121-b01
+f092b9a890ceeca4a2f4d55cf7d6f3f113cdb462 jdk8u121-b02
+c1b0f76c9fe9657d3f5cdd1e23bfd1d499018431 jdk8u121-b03
+44674172423a0d361466e34eedcaec18a8810b13 jdk8u121-b04
+18da635b5919a0b7cdde8573a0d502efdbf3673e jdk8u121-b05
+5b76a2126855f8949ab8fbadfa3ee2f29da9c21c jdk8u121-b06
+f10aa5b29848eab891bdd173540d91fd31f9ff20 jdk8u121-b07
+105d3bbf5e3b2b24da665b332d2dbf44980c87f2 jdk8u121-b08
+9f2588382771f855c4450f59b470d069a1cb1d01 jdk8u121-b09
+c317f0eacd602a8765d25b0fcd382f76af3697a5 jdk8u121-b10
+89aa912be940d6c30f59b80c826f212541912a56 jdk8u121-b11
+52b3f9fb54ee4304a9c34a2fe07f0c9a49472185 jdk8u121-b12
+5b8834cc3bb9e24153319c766e04e194945a61b9 jdk8u121-b13
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 8b4dc20..b8a7ca4 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -665,3 +665,18 @@
 5dd7e4bae5c2f1ee4f80c5570e7e3e2f715f7a32 jdk8u112-b16
 41fac11792c1ee6945f56721ee558a7424395a81 jdk8u112-b31
 548a51660ee94aeb77b2432594aeb87f87c21697 jdk8u112-b32
+a334b0815d34948188537a177a32cee27007ea2c jdk8u112-b33
+ab5ff8f1e52c5e3ca02e988f4d978af63ceca5b8 jdk8u121-b00
+5f0839ac7e0d25dd1ae705df496b12ca76c26d59 jdk8u121-b01
+f91e3aa155b3c6774afb456db15fb358313d5771 jdk8u121-b02
+ecdb635eaf4886829089b987c339e35dfb5ea0e8 jdk8u121-b03
+d54219144844fb358f87f4a37255242aae9782fa jdk8u121-b04
+fb4e3a7375c91e02bd1c0a764dfb53fba3839c18 jdk8u121-b05
+3bc671481026decc460e636e8b2f19a36bfe89af jdk8u121-b06
+a2c2fbc61674869e85d5345804cff4834cc010d1 jdk8u121-b07
+392209fbe127896df2749344ea127f2c0a62da55 jdk8u121-b08
+494d27357b8cfc6b6c4346a814c8717a8502d769 jdk8u121-b09
+d66de7e2f672a1ff6947846818412fa899456972 jdk8u121-b10
+ec72a941be0a50ab77f5375cf710bc06e4f118d3 jdk8u121-b11
+9561afc12df843ef21ecd9d7b3633371e7a2bfc4 jdk8u121-b12
+2974746e56192cdd14fc2dd43179bcf28e4faf4a jdk8u121-b13
diff --git a/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java b/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
index f63441b..94b5429 100644
--- a/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
+++ b/jdk/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java
@@ -121,7 +121,7 @@
         }
 
         // grab the pointer to the CMenuBar, and retain it in native
-        nativeSetDefaultMenuBar(((CMenuBar)peer).getModel());
+        ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar);
     }
 
     void setAboutMenuItemVisible(final boolean present) {
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
index da53c30..d21de34 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,29 +26,28 @@
 package sun.lwawt.macosx;
 
 import java.awt.CheckboxMenuItem;
-import java.awt.EventQueue;
 import java.awt.event.ItemEvent;
 import java.awt.peer.CheckboxMenuItemPeer;
 
 import sun.awt.SunToolkit;
 
 public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer {
-    boolean fAutoToggle = true;
-    boolean fIsIndeterminate = false;
+    volatile boolean fAutoToggle = true;
+    volatile boolean fIsIndeterminate = false;
 
     private native void nativeSetState(long modelPtr, boolean state);
     private native void nativeSetIsCheckbox(long modelPtr);
 
-    CCheckboxMenuItem(CheckboxMenuItem target) {
+    CCheckboxMenuItem(final CheckboxMenuItem target) {
         super(target);
-        nativeSetIsCheckbox(getModel());
+        execute(this::nativeSetIsCheckbox);
         setState(target.getState());
     }
 
     // MenuItemPeer implementation
     @Override
-    public void setState(boolean state) {
-        nativeSetState(getModel(), state);
+    public void setState(final boolean state) {
+        execute(ptr -> nativeSetState(ptr, state));
     }
 
     public void handleAction(final boolean state) {
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
index cec76f5..f69ad20 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java
@@ -23,7 +23,6 @@
  * questions.
  */
 
-
 package sun.lwawt.macosx;
 
 /**
@@ -34,6 +33,7 @@
     private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread);
 
     private final boolean disposeOnAppKitThread;
+    // TODO this pointer should be private and accessed via CFNativeAction class
     protected volatile long ptr;
 
     /**
@@ -70,8 +70,72 @@
         nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block
     }
 
+    /**
+     * The interface which allows to execute some native operations with
+     * assumption that the native pointer will be valid till the end.
+     */
+    public interface CFNativeAction {
+
+        /**
+         * The native operation should be called from this method.
+         *
+         * @param  ptr the pointer to the native data
+         */
+        void run(long ptr);
+    }
+
+    /**
+     * The interface which allows to execute some native operations and get a
+     * result with assumption that the native pointer will be valid till the
+     * end.
+     */
+    interface CFNativeActionGet {
+
+        /**
+         * The native operation should be called from this method.
+         *
+         * @param  ptr the pointer to the native data
+         * @return result of the native operation
+         */
+        long run(long ptr);
+    }
+
+    /**
+     * This is utility method which should be used instead of the direct access
+     * to the {@link #ptr}, because this method guaranteed that the pointer will
+     * not be zero and will be valid till the end of the operation.It is highly
+     * recomended to not use any external lock in action. If the current
+     * {@link #ptr} is {@code 0} then action will be ignored.
+     *
+     * @param  action The native operation
+     */
+    public final synchronized void execute(final CFNativeAction action) {
+        if (ptr != 0) {
+            action.run(ptr);
+        }
+    }
+
+    /**
+     * This is utility method which should be used instead of the direct access
+     * to the {@link #ptr}, because this method guaranteed that the pointer will
+     * not be zero and will be valid till the end of the operation. It is highly
+     * recomended to not use any external lock in action. If the current
+     * {@link #ptr} is {@code 0} then action will be ignored and {@code} is
+     * returned.
+     *
+     * @param  action the native operation
+     * @return result of the native operation, usually the native pointer to
+     *         some other data
+     */
+    final synchronized long executeGet(final CFNativeActionGet action) {
+        if (ptr != 0) {
+            return action.run(ptr);
+        }
+        return 0;
+    }
+
     @Override
-    protected void finalize() throws Throwable {
+    protected final void finalize() throws Throwable {
         dispose();
     }
 }
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
index 9e1499b..4f2fc96 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 
 package sun.lwawt.macosx;
 
-import java.awt.*;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
 import java.awt.peer.MenuItemPeer;
 import java.awt.peer.MenuPeer;
 
@@ -37,7 +39,7 @@
 
     // This way we avoiding invocation of the setters twice
     @Override
-    protected void initialize(MenuItem target) {
+    protected final void initialize(MenuItem target) {
         setLabel(target.getLabel());
         setEnabled(target.isEnabled());
     }
@@ -57,52 +59,50 @@
     }
 
     @Override
-    protected long createModel() {
+    long createModel() {
         CMenuComponent parent = (CMenuComponent)
             LWCToolkit.targetToPeer(getTarget().getParent());
 
-        if (parent instanceof CMenu ||
-            parent instanceof CPopupMenu)
-        {
-            return nativeCreateSubMenu(parent.getModel());
-        } else if (parent instanceof CMenuBar) {
+        if (parent instanceof CMenu) {
+            return parent.executeGet(this::nativeCreateSubMenu);
+        }
+        if (parent instanceof CMenuBar) {
             MenuBar parentContainer = (MenuBar)getTarget().getParent();
             boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget();
             int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex();
-            return nativeCreateMenu(parent.getModel(),
-                                    isHelpMenu, insertionLocation);
-        } else {
-            throw new InternalError("Parent must be CMenu or CMenuBar");
+            return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu,
+                                                             insertionLocation));
         }
+        throw new InternalError("Parent must be CMenu or CMenuBar");
     }
 
     @Override
-    public void addItem(MenuItem item) {
+    public final void addItem(MenuItem item) {
         // Nothing to do here -- we added it when we created the
         // menu item's peer.
     }
 
     @Override
-    public void delItem(int index) {
-        nativeDeleteItem(getModel(), index);
+    public final void delItem(final int index) {
+        execute(ptr -> nativeDeleteItem(ptr, index));
     }
 
     @Override
-    public void setLabel(String label) {
-        nativeSetMenuTitle(getModel(), label);
+    public final void setLabel(final String label) {
+        execute(ptr->nativeSetMenuTitle(ptr, label));
         super.setLabel(label);
     }
 
     // Note that addSeparator is never called directly from java.awt.Menu,
     // though it is required in the MenuPeer interface.
     @Override
-    public void addSeparator() {
-        nativeAddSeparator(getModel());
+    public final void addSeparator() {
+        execute(this::nativeAddSeparator);
     }
 
     // Used by ScreenMenuBar to get to the native menu for event handling.
-    public long getNativeMenu() {
-        return nativeGetNSMenu(getModel());
+    public final long getNativeMenu() {
+        return executeGet(this::nativeGetNSMenu);
     }
 
     private native long nativeCreateMenu(long parentMenuPtr,
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
index 0bed715..6e80370 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,9 @@
 import java.awt.MenuBar;
 import java.awt.peer.MenuBarPeer;
 
-public class CMenuBar extends CMenuComponent implements MenuBarPeer {
+import sun.awt.AWTAccessor;
+
+public final class CMenuBar extends CMenuComponent implements MenuBarPeer {
 
     private int nextInsertionIndex = -1;
 
@@ -38,15 +40,16 @@
     }
 
     @Override
-    protected long createModel() {
+    long createModel() {
         return nativeCreateMenuBar();
     }
 
     @Override
-    public void addHelpMenu(Menu m) {
-        CMenu cMenu = (CMenu)m.getPeer();
-        nativeSetHelpMenu(getModel(), cMenu.getModel());
-    }
+    public void addHelpMenu(final Menu m) {
+        final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m);
+        execute(parentPtr -> cMenu.execute(
+                menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr)));
+     }
 
     public int getNextInsertionIndex() {
         return nextInsertionIndex;
@@ -63,8 +66,8 @@
     }
 
     @Override
-    public void delMenu(int index) {
-        nativeDelMenu(getModel(), index);
+    public void delMenu(final int index) {
+        execute(ptr -> nativeDelMenu(ptr, index));
     }
 
     private native long nativeCreateMenuBar();
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
index 2dbc923..6100916 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,36 +29,32 @@
 import java.awt.MenuComponent;
 import java.awt.peer.MenuComponentPeer;
 
-public abstract class CMenuComponent implements MenuComponentPeer {
+abstract class CMenuComponent extends CFRetainedResource
+        implements MenuComponentPeer {
 
-    private MenuComponent target;
-    private long modelPtr;
+    private final MenuComponent target;
 
-    CMenuComponent(MenuComponent target) {
+    CMenuComponent(final MenuComponent target) {
+        super(0, true);
         this.target = target;
-        this.modelPtr = createModel();
+        setPtr(createModel());
     }
 
-    MenuComponent getTarget() {
+    final MenuComponent getTarget() {
         return target;
     }
 
-    public long getModel() {
-        return modelPtr;
-    }
+    abstract long createModel();
 
-    protected abstract long createModel();
-
-    public void dispose() {
+    @Override
+    public final void dispose() {
+        super.dispose();
         LWCToolkit.targetDisposedPeer(target, this);
-        nativeDispose(modelPtr);
-        target = null;
     }
 
-    private native void nativeDispose(long modelPtr);
-
     // 1.5 peer method
-    public void setFont(Font f) {
+    @Override
+    public final void setFont(final Font f) {
         // no-op, as we don't currently support menu fonts
         // c.f. radar 4032912
     }
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
index dbe6a8c..01427db 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,16 +25,17 @@
 
 package sun.lwawt.macosx;
 
-import sun.awt.SunToolkit;
-import sun.lwawt.LWToolkit;
-
-import java.awt.MenuContainer;
 import java.awt.MenuItem;
 import java.awt.MenuShortcut;
-import java.awt.event.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
 import java.awt.peer.MenuItemPeer;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import sun.awt.SunToolkit;
+import sun.lwawt.LWToolkit;
+
 public class CMenuItem extends CMenuComponent implements MenuItemPeer {
 
     private final AtomicBoolean enabled = new AtomicBoolean(true);
@@ -58,9 +59,9 @@
     }
 
     @Override
-    protected long createModel() {
+    long createModel() {
         CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent());
-        return nativeCreate(parent.getModel(), isSeparator());
+        return parent.executeGet(ptr->nativeCreate(ptr, isSeparator()));
     }
 
     public void setLabel(String label, char keyChar, int keyCode, int modifiers) {
@@ -90,7 +91,12 @@
             keyChar = 0;
         }
 
-        nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask);
+        final String finalLabel = label;
+        final char finalKeyChar = keyChar;
+        final int finalKeyCode = keyCode;
+        final int finalKeyMask = keyMask;
+        execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar,
+                                      finalKeyCode, finalKeyMask));
     }
 
     @Override
@@ -105,16 +111,16 @@
      * There isn't a need to expose this except in a instanceof because
      * it isn't defined in the peer api.
      */
-    public void setImage(java.awt.Image img) {
+    public final void setImage(final java.awt.Image img) {
         CImage cimg = CImage.getCreator().createFromImage(img);
-        nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr);
+        execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr));
     }
 
     /**
      * New API for tooltips
      */
-    public void setToolTipText(String text) {
-        nativeSetTooltip(getModel(), text);
+    public final void setToolTipText(final String text) {
+        execute(ptr -> nativeSetTooltip(ptr, text));
     }
 
 //    @Override
@@ -138,7 +144,8 @@
             b &= ((CMenuItem) parent).isEnabled();
         }
         if (enabled.compareAndSet(!b, b)) {
-            nativeSetEnabled(getModel(), b);
+            final boolean finalB = b;
+            execute(ptr->nativeSetEnabled(ptr, finalB));
         }
     }
 
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
index 7626fb0..7fe07c9 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
@@ -209,6 +209,8 @@
     private volatile boolean isFullScreenMode;
     private boolean isFullScreenAnimationOn;
 
+    private volatile boolean isIconifyAnimationActive;
+
     private Window target;
     private LWWindowPeer peer;
     protected CPlatformView contentView;
@@ -423,7 +425,7 @@
         final long nsWindowPtr = getNSWindowPtr();
         CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb);
         if (mbPeer != null) {
-            nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel());
+            mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr));
         } else {
             nativeSetNSWindowMenuBar(nsWindowPtr, 0);
         }
@@ -950,6 +952,9 @@
         if (peer != null) {
             peer.notifyIconify(iconify);
         }
+        if (iconify) {
+            isIconifyAnimationActive = false;
+        }
     }
 
     private void deliverZoom(final boolean isZoomed) {
@@ -1019,6 +1024,17 @@
         return true;
     }
 
+    private boolean isIconified() {
+        boolean isIconified = false;
+        if (target instanceof Frame) {
+            int state = ((Frame)target).getExtendedState();
+            if ((state & Frame.ICONIFIED) != 0) {
+                isIconified = true;
+            }
+        }
+        return isIconifyAnimationActive || isIconified;
+    }
+
     private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
         while (window != null) {
             if (this == window) {
@@ -1042,11 +1058,14 @@
         // the windows are ordered above their nearest owner; ancestors of the window,
         // which is going to become 'main window', are placed above their siblings.
         CPlatformWindow rootOwner = getRootOwner();
-        if (rootOwner.isVisible()) {
+        if (rootOwner.isVisible() && !rootOwner.isIconified()) {
             CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
         }
-        final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
-        orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+        // Do not order child windows of iconified owner.
+        if (!rootOwner.isIconified()) {
+            final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
+            orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+        }
     }
 
     private void orderAboveSiblingsImpl(Window[] windows) {
@@ -1057,10 +1076,12 @@
 
         // Go through the list of windows and perform ordering.
         for (Window w : windows) {
+            boolean iconified = false;
             final Object p = componentAccessor.getPeer(w);
             if (p instanceof LWWindowPeer) {
                 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
-                if (pw != null && pw.isVisible()) {
+                iconified = isIconified();
+                if (pw != null && pw.isVisible() && !iconified) {
                     // If the window is one of ancestors of 'main window' or is going to become main by itself,
                     // the window should be ordered above its siblings; otherwise the window is just ordered
                     // above its nearest parent.
@@ -1073,10 +1094,13 @@
                     pw.applyWindowLevel(w);
                 }
             }
-            // Retrieve the child windows for each window from the list and store them for future use.
+            // Retrieve the child windows for each window from the list except iconified ones
+            // and store them for future use.
             // Note: we collect data about child windows even for invisible owners, since they may have
             // visible children.
-            childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+            if (!iconified) {
+                childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+            }
         }
         // If some windows, which have just been ordered, have any child windows, let's start new iteration
         // and order these child windows.
@@ -1097,6 +1121,10 @@
     //                          NATIVE CALLBACKS
     // ----------------------------------------------------------------------
 
+    private void windowWillMiniaturize() {
+        isIconifyAnimationActive = true;
+    }
+
     private void windowDidBecomeMain() {
         assert CThreading.assertAppKit();
 
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
index 67ddf91..b73f67a 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,18 +25,20 @@
 
 package sun.lwawt.macosx;
 
-import java.awt.*;
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.Point;
+import java.awt.PopupMenu;
 import java.awt.peer.PopupMenuPeer;
 
-import sun.lwawt.LWWindowPeer;
+final class CPopupMenu extends CMenu implements PopupMenuPeer {
 
-public class CPopupMenu extends CMenu implements PopupMenuPeer {
     CPopupMenu(PopupMenu target) {
         super(target);
     }
 
     @Override
-    protected long createModel() {
+    long createModel() {
         return nativeCreatePopupMenu();
     }
 
@@ -50,7 +52,7 @@
             Point loc = origin.getLocationOnScreen();
             e.x += loc.x;
             e.y += loc.y;
-            nativeShowPopupMenu(getModel(), e.x, e.y);
+            execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y));
         }
     }
 }
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
index 8e2a18f..ff1648d 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -104,7 +104,10 @@
                 return 0L;
             }
         }
-        return checkAndCreatePopupPeer().getModel();
+        // This method is executed on Appkit, so if ptr is not zero means that,
+        // it is still not deallocated(even if we call NSApp postRunnableEvent)
+        // and sent CFRelease to the native queue
+        return checkAndCreatePopupPeer().ptr;
     }
 
     /**
diff --git a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
index d12908c..8b0d576 100644
--- a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
+++ b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,8 +103,6 @@
 
         CALayer *windowLayer = jlong_to_ptr(windowLayerPtr);
         surfaceLayers = [[AWTSurfaceLayers alloc] initWithWindowLayer: windowLayer];
-        CFRetain(surfaceLayers);
-        [surfaceLayers release];
     }];
     
 JNF_COCOA_EXIT(env);
diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m
index 0808580..35c9440 100644
--- a/jdk/src/macosx/native/sun/awt/AWTView.m
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m
@@ -114,9 +114,9 @@
             remoteLayer.parentLayer = parentLayer;
             remoteLayer.remoteLayer = NULL;
             remoteLayer.jrsRemoteLayer = [remoteLayer createRemoteLayerBoundTo:JRSRemotePort];
-            CFRetain(remoteLayer);  // REMIND
+            [remoteLayer retain];  // REMIND
             remoteLayer.frame = CGRectMake(0, 0, 720, 500); // REMIND
-            CFRetain(remoteLayer.jrsRemoteLayer); // REMIND
+            [remoteLayer.jrsRemoteLayer retain]; // REMIND
             int layerID = [remoteLayer.jrsRemoteLayer layerID];
             NSLog(@"layer id to send = %d", layerID);
             sendLayerID(layerID);
@@ -1341,12 +1341,9 @@
     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 
         CALayer *windowLayer = jlong_to_ptr(windowLayerPtr);
-        AWTView *view = [[AWTView alloc] initWithRect:rect
-                                         platformView:cPlatformView
-                                         windowLayer:windowLayer];
-        CFRetain(view);
-        [view release]; // GC
-        newView = view;
+        newView = [[AWTView alloc] initWithRect:rect
+                                   platformView:cPlatformView
+                                    windowLayer:windowLayer];
     }];
 
 JNF_COCOA_EXIT(env);
diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m
index 9238305..035f667 100644
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -326,10 +326,44 @@
     return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
 }
 
+// Retrieves the list of possible window layers (levels)
++ (NSArray*) getWindowLayers {
+    static NSArray *windowLayers;
+    static dispatch_once_t token;
+
+    // Initialize the list of possible window layers
+    dispatch_once(&token, ^{
+        // The layers are ordered from front to back, (i.e. the toppest one is the first)
+        windowLayers = [NSArray arrayWithObjects:
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)],
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)],
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)],
+                            nil
+                       ];
+        [windowLayers retain];
+    });
+    return windowLayers;
+}
+
+
 // returns id for the topmost window under mouse
 + (NSInteger) getTopmostWindowUnderMouseID {
     NSInteger result = -1;
-    
+
+    NSArray *windowLayers = [AWTWindow getWindowLayers];
+    // Looking for the window under mouse starting from the toppest layer
+    for (NSNumber *layer in windowLayers) {
+        result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]];
+        if (result != -1) {
+            break;
+        }
+    }
+    return result;
+}
+
++ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer {
+    NSInteger result = -1;
+
     NSRect screenRect = [[NSScreen mainScreen] frame];
     NSPoint nsMouseLocation = [NSEvent mouseLocation];
     CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
@@ -338,7 +372,7 @@
 
     for (NSDictionary *window in windows) {
         NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
-        if (layer == 0) {
+        if (layer == windowLayer) {
             CGRect rect;
             CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
             if (CGRectContainsPoint(rect, cgMouseLocation)) {
@@ -614,6 +648,14 @@
 AWT_ASSERT_APPKIT_THREAD;
 
     self.isMinimizing = YES;
+
+    JNIEnv *env = [ThreadUtilities getJNIEnv];
+    jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
+    if (platformWindow != NULL) {
+        static JNF_MEMBER_CACHE(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
+        JNFCallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
+        (*env)->DeleteLocalRef(env, platformWindow);
+    }
     // Excplicitly make myself a key window to avoid possible
     // negative visual effects during iconify operation
     [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
@@ -916,7 +958,7 @@
                                                contentView:contentView];
         // the window is released is CPlatformWindow.nativeDispose()
 
-        if (window) CFRetain(window.nsWindow);
+        if (window) [window.nsWindow retain];
     }];
 
 JNF_COCOA_EXIT(env);
diff --git a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
index 8195575..dcad651 100644
--- a/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
+++ b/jdk/src/macosx/native/sun/awt/ApplicationDelegate.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -255,8 +255,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; } // GC
-
 
 #pragma mark Callbacks from AppKit
 
@@ -623,8 +621,7 @@
 JNF_COCOA_ENTER(env);
 
     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
-        image = [ApplicationDelegate _dockIconImage];
-        CFRetain(image);
+        image = [[ApplicationDelegate _dockIconImage] retain];
     }];
 
 JNF_COCOA_EXIT(env);
diff --git a/jdk/src/macosx/native/sun/awt/CClipboard.m b/jdk/src/macosx/native/sun/awt/CClipboard.m
index dde4ed8..543ed20 100644
--- a/jdk/src/macosx/native/sun/awt/CClipboard.m
+++ b/jdk/src/macosx/native/sun/awt/CClipboard.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (NSData *)data {
     return fData;
diff --git a/jdk/src/macosx/native/sun/awt/CDesktopPeer.m b/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
index ef9bdb6..ae44084 100644
--- a/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
+++ b/jdk/src/macosx/native/sun/awt/CDesktopPeer.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
 
     LSApplicationParameters params = {0, flags, NULL, NULL, NULL, NULL, NULL};
     status = LSOpenURLsWithRole((CFArrayRef)[NSArray arrayWithObject:url], kLSRolesAll, NULL, &params, NULL, 0);
-    CFRelease(url);
+    [url release];
 
 JNF_COCOA_EXIT(env);
     return status;
diff --git a/jdk/src/macosx/native/sun/awt/CDragSource.m b/jdk/src/macosx/native/sun/awt/CDragSource.m
index da67762..1f6d9b0 100644
--- a/jdk/src/macosx/native/sun/awt/CDragSource.m
+++ b/jdk/src/macosx/native/sun/awt/CDragSource.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -193,7 +193,7 @@
         fFormatMap = NULL;
     }
 
-    CFRelease(self); // GC
+    [self release];
 }
 
 - (void)dealloc
@@ -209,8 +209,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
-
 
 // Appropriated from Windows' awt_DataTransferer.cpp:
 //
diff --git a/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m b/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
index e1a7ab3..890c51c 100644
--- a/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
+++ b/jdk/src/macosx/native/sun/awt/CDragSourceContextPeer.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,10 +67,6 @@
     }];
 JNF_COCOA_EXIT(env);
 
-    if (dragSource) {
-        CFRetain(dragSource); // GC
-        [dragSource release];
-    }
     return ptr_to_jlong(dragSource);
 }
 
diff --git a/jdk/src/macosx/native/sun/awt/CDropTarget.m b/jdk/src/macosx/native/sun/awt/CDropTarget.m
index 7c2c0e1..0b3b184 100644
--- a/jdk/src/macosx/native/sun/awt/CDropTarget.m
+++ b/jdk/src/macosx/native/sun/awt/CDropTarget.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -171,7 +171,7 @@
         fDropTargetContextPeer = NULL;
     }
 
-    CFRelease(self);
+    [self release];
 }
 
 - (void)dealloc
@@ -187,7 +187,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (NSInteger) getDraggingSequenceNumber
 {
@@ -724,10 +723,6 @@
     dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent peer:jpeer control:controlObj];
 JNF_COCOA_EXIT(env);
 
-    if (dropTarget) {
-        CFRetain(dropTarget); // GC
-        [dropTarget release];
-    }
     return ptr_to_jlong(dropTarget);
 }
 
diff --git a/jdk/src/macosx/native/sun/awt/CFileDialog.m b/jdk/src/macosx/native/sun/awt/CFileDialog.m
index 7dc8202..ee75309 100644
--- a/jdk/src/macosx/native/sun/awt/CFileDialog.m
+++ b/jdk/src/macosx/native/sun/awt/CFileDialog.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (void)safeSaveOrLoad {
     NSSavePanel *thePanel = nil;
@@ -168,9 +167,9 @@
     }
 
     // ask the file filter up in Java
-    CFStringRef filePath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle);
-    BOOL shouldEnableFile = [self askFilenameFilter:(NSString *)filePath];
-    CFRelease(filePath);
+    NSString* filePath = (NSString*)CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle);
+    BOOL shouldEnableFile = [self askFilenameFilter:filePath];
+    [filePath release];
     return shouldEnableFile;
 }
 
diff --git a/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m b/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
index c8044d1..ace6c8e 100644
--- a/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
+++ b/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -163,8 +163,7 @@
 
 JNF_COCOA_ENTER(env);
 
-    JNFWeakJObjectWrapper *wrapper = [JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env];
-    CFRetain(wrapper); // pin from ObjC-GC
+    JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain];
 
     /* Register the callback */
     if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
@@ -204,8 +203,7 @@
     }
 
     [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear
-
-    CFRelease(wrapper);
+    [wrapper release];
 
 JNF_COCOA_EXIT(env);
 }
diff --git a/jdk/src/macosx/native/sun/awt/CImage.m b/jdk/src/macosx/native/sun/awt/CImage.m
index ae93d56..eedb31e 100644
--- a/jdk/src/macosx/native/sun/awt/CImage.m
+++ b/jdk/src/macosx/native/sun/awt/CImage.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,14 +115,9 @@
     
     NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height);
     if (imageRep) {
-        NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
+        NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] retain];
         [nsImage addRepresentation:imageRep];
         [imageRep release];
-
-        if (nsImage != nil) {
-            CFRetain(nsImage); // GC
-        }
-
         result = ptr_to_jlong(nsImage);
     }
 
@@ -165,13 +160,8 @@
         (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT);
     }
     if ([reps count]) {
-        NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)];
+        NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(0, 0)] retain];
         [nsImage addRepresentations: reps];
-
-        if (nsImage != nil) {
-            CFRetain(nsImage); // GC
-        }
-
         result = ptr_to_jlong(nsImage);
     }
 
@@ -194,8 +184,7 @@
 
     IconRef iconRef;
     if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) {
-        image = [[NSImage alloc] initWithIconRef:iconRef];
-        if (image) CFRetain(image); // GC
+        image = [[[NSImage alloc] initWithIconRef:iconRef] retain];
         ReleaseIconRef(iconRef);
     }
 
@@ -217,8 +206,7 @@
 JNF_COCOA_ENTER(env);
 
     NSString *path = JNFNormalizedNSStringForPath(env, file);
-    image = [[NSImage alloc] initByReferencingFile:path];
-    if (image) CFRetain(image); // GC
+    image = [[[NSImage alloc] initByReferencingFile:path] retain];
 
 JNF_COCOA_EXIT(env);
 
@@ -239,9 +227,8 @@
 
     NSString *path = JNFNormalizedNSStringForPath(env, file);
     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
-        image = [[NSWorkspace sharedWorkspace] iconForFile:path];
+        image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain];
         [image setScalesWhenResized:TRUE];
-        if (image) CFRetain(image); // GC
     }];
 
 JNF_COCOA_EXIT(env);
@@ -261,8 +248,7 @@
 
 JNF_COCOA_ENTER(env);
 
-    image = [NSImage imageNamed:JNFJavaToNSString(env, name)];
-    if (image) CFRetain(image); // GC
+    image = [[NSImage imageNamed:JNFJavaToNSString(env, name)] retain];
 
 JNF_COCOA_EXIT(env);
 
diff --git a/jdk/src/macosx/native/sun/awt/CMenu.m b/jdk/src/macosx/native/sun/awt/CMenu.m
index e2db11c..fe42ac7 100644
--- a/jdk/src/macosx/native/sun/awt/CMenu.m
+++ b/jdk/src/macosx/native/sun/awt/CMenu.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
 - (id)initWithPeer:(jobject)peer {
 AWT_ASSERT_APPKIT_THREAD;
     // Create the new NSMenu
-    self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
+    self = [super initWithPeer:peer asSeparator:NO];
     if (self) {
         fMenu = [NSMenu javaMenuWithTitle:@""];
         [fMenu retain];
@@ -52,7 +52,6 @@
     fMenu = nil;
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (void)addJavaSubmenu:(CMenu *)submenu {
     [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES];
@@ -134,14 +133,13 @@
 
 CMenu * createCMenu (jobject cPeerObjGlobal) {
 
-    CMenu *aCMenu = nil;
+    __block CMenu *aCMenu = nil;
 
-    // We use an array here only to be able to get a return value
-    NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 
-    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
-
-    aCMenu = (CMenu *)[args objectAtIndex: 0];
+        aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal];
+        // the aCMenu is released in CMenuComponent.dispose()
+    }];
 
     if (aCMenu == nil) {
         return 0L;
@@ -169,10 +167,6 @@
 
     // Add it to the parent menu
     [((CMenu *)jlong_to_ptr(parentMenu)) addJavaSubmenu: aCMenu];
-    if (aCMenu) {
-        CFRetain(aCMenu); // GC
-        [aCMenu release];
-    }
 
 JNF_COCOA_EXIT(env);
 
@@ -209,10 +203,6 @@
         [parent javaSetHelpMenu: aCMenu];
     }
 
-    if (aCMenu) {
-        CFRetain(aCMenu); // GC
-        [aCMenu release];
-    }
 JNF_COCOA_EXIT(env);
     return ptr_to_jlong(aCMenu);
 }
@@ -275,13 +265,9 @@
     NSMenu* nsMenu = NULL;
 
 JNF_COCOA_ENTER(env);
-    nsMenu = [((CMenu *)jlong_to_ptr(menuObject)) menu];
-JNF_COCOA_EXIT(env);
-
     // Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners
-    if (nsMenu) {
-        CFRetain(nsMenu); // GC
-    }
+    nsMenu = [[((CMenu *)jlong_to_ptr(menuObject)) menu] retain];
+JNF_COCOA_EXIT(env);
 
     return ptr_to_jlong(nsMenu);
 }
diff --git a/jdk/src/macosx/native/sun/awt/CMenuBar.m b/jdk/src/macosx/native/sun/awt/CMenuBar.m
index 3bf4f77..2de86be 100644
--- a/jdk/src/macosx/native/sun/awt/CMenuBar.m
+++ b/jdk/src/macosx/native/sun/awt/CMenuBar.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -383,32 +383,21 @@
 Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
     (JNIEnv *env, jobject peer)
 {
-    CMenuBar *aCMenuBar = nil;
+    __block CMenuBar *aCMenuBar = nil;
     JNF_COCOA_ENTER(env);
 
     jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
 
-    // We use an array here only to be able to get a return value
-    NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
 
-    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
-
-    aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
-
+        aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal];
+        // the aCMenuBar is released in CMenuComponent.dispose()
+    }];
     if (aCMenuBar == nil) {
         return 0L;
     }
 
-    // [args release];
-
-    // A strange memory managment after that.
-
-
     JNF_COCOA_EXIT(env);
-    if (aCMenuBar) {
-        CFRetain(aCMenuBar); // GC
-        [aCMenuBar release];
-    }
     return ptr_to_jlong(aCMenuBar);
 }
 
diff --git a/jdk/src/macosx/native/sun/awt/CMenuComponent.m b/jdk/src/macosx/native/sun/awt/CMenuComponent.m
index c8b3766..6847f9b 100644
--- a/jdk/src/macosx/native/sun/awt/CMenuComponent.m
+++ b/jdk/src/macosx/native/sun/awt/CMenuComponent.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,49 +41,11 @@
     return self;
 }
 
--(void) cleanup {
-    // Used by subclasses
-}
-
--(void) disposer {
+-(void) dealloc {
     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
     JNFDeleteGlobalRef(env, fPeer);
     fPeer = NULL;
 
-    [self cleanup];
-
-    CFRelease(self); // GC
+    [super dealloc];
 }
-
-// The method is used by all subclasses, since the process of the creation
-// is the same. The only exception is the CMenuItem class.
-- (void) _create_OnAppKitThread: (NSMutableArray *)argValue {
-    jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
-    CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal];
-    [argValue removeAllObjects];
-    [argValue addObject: aCMenuItem];
-}
-
-//-(void) dealloc { [super dealloc]; }
-//- (void)finalize { [super finalize]; }
-
 @end
-
-/*
- * Class:     sun_lwawt_macosx_CMenuComponent
- * Method:    nativeDispose
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL
-Java_sun_lwawt_macosx_CMenuComponent_nativeDispose
-(JNIEnv *env, jobject peer, jlong menuItemObj)
-{
-JNF_COCOA_ENTER(env);
-
-    [ThreadUtilities performOnMainThread:@selector(disposer)
-                                      on:((id)jlong_to_ptr(menuItemObj))
-                              withObject:nil
-                           waitUntilDone:NO];
-
-JNF_COCOA_EXIT(env);
-}
diff --git a/jdk/src/macosx/native/sun/awt/CMenuItem.h b/jdk/src/macosx/native/sun/awt/CMenuItem.h
index 60a0565..e2c72f2 100644
--- a/jdk/src/macosx/native/sun/awt/CMenuItem.h
+++ b/jdk/src/macosx/native/sun/awt/CMenuItem.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 }
 
 // Setup
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator;
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator;
 - (void) setIsCheckbox;
 
 // Events
diff --git a/jdk/src/macosx/native/sun/awt/CMenuItem.m b/jdk/src/macosx/native/sun/awt/CMenuItem.m
index 219cc5b..12ab99c 100644
--- a/jdk/src/macosx/native/sun/awt/CMenuItem.m
+++ b/jdk/src/macosx/native/sun/awt/CMenuItem.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,11 +39,11 @@
 
 @implementation CMenuItem
 
-- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{
+- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{
 AWT_ASSERT_APPKIT_THREAD;
     self = [super initWithPeer:peer];
     if (self) {
-        if ([asSeparator boolValue]) {
+        if (asSeparator) {
             fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem];
             [fMenuItem retain];
         } else {
@@ -199,12 +199,9 @@
     }];
 }
 
-- (void)cleanup {
+- (void)dealloc {
     [fMenuItem setAction:NULL];
     [fMenuItem setTarget:nil];
-}
-
-- (void)dealloc {
     [fMenuItem release];
     fMenuItem = nil;
 
@@ -223,14 +220,6 @@
     fIsCheckbox = YES;
 }
 
-- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue {
-    jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue];
-    NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1];
-    CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator];
-    [argValue removeAllObjects];
-    [argValue addObject: aCMenuItem];
-}
-
 - (NSString *)description {
     return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem];
 }
@@ -392,24 +381,18 @@
     (JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
 {
 
-    CMenuItem *aCMenuItem = nil;
+    __block CMenuItem *aCMenuItem = nil;
+    BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO;
     CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
 JNF_COCOA_ENTER(env);
 
     jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
 
-    NSMutableArray *args = nil;
-
-    // Create a new item....
-    if (isSeparator == JNI_TRUE) {
-        args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES],  nil];
-    } else {
-        args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO],  nil];
-    }
-
-    [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
-
-    aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
+     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+        aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal
+                                         asSeparator: asSeparator];
+        // the CMenuItem is released in CMenuComponent.dispose()
+    }];
 
     if (aCMenuItem == nil) {
         return 0L;
@@ -420,11 +403,6 @@
 
     // setLabel will be called after creation completes.
 
-    if (aCMenuItem) {
-        CFRetain(aCMenuItem); // GC
-        [aCMenuItem release];
-    }
-
 JNF_COCOA_EXIT(env);
     return ptr_to_jlong(aCMenuItem);
 }
diff --git a/jdk/src/macosx/native/sun/awt/CPopupMenu.m b/jdk/src/macosx/native/sun/awt/CPopupMenu.m
index 287e97a..cf45651 100644
--- a/jdk/src/macosx/native/sun/awt/CPopupMenu.m
+++ b/jdk/src/macosx/native/sun/awt/CPopupMenu.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,8 +66,6 @@
 
     [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
         aCPopupMenu = [[CPopupMenu alloc] initWithPeer:cPeerObjGlobal];
-        CFRetain(aCPopupMenu);
-        [aCPopupMenu release];
     }];
 
 JNF_COCOA_EXIT(env);
diff --git a/jdk/src/macosx/native/sun/awt/CPrinterJob.m b/jdk/src/macosx/native/sun/awt/CPrinterJob.m
index 219f65b..dfcbc1f 100644
--- a/jdk/src/macosx/native/sun/awt/CPrinterJob.m
+++ b/jdk/src/macosx/native/sun/awt/CPrinterJob.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -469,8 +469,6 @@
     //  safety is assured by the java side of this call.
 
     NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL);
-    if (printInfo) CFRetain(printInfo); // GC
-    [printInfo release];
 
     result = ptr_to_jlong(printInfo);
 
@@ -490,7 +488,7 @@
     if (nsPrintInfo != -1)
     {
         NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo);
-        if (printInfo) CFRelease(printInfo); // GC
+        [printInfo release];
     }
 JNF_COCOA_EXIT(env);
 }
diff --git a/jdk/src/macosx/native/sun/awt/CSystemColors.m b/jdk/src/macosx/native/sun/awt/CSystemColors.m
index 0f3fab5..6c73c82 100644
--- a/jdk/src/macosx/native/sun/awt/CSystemColors.m
+++ b/jdk/src/macosx/native/sun/awt/CSystemColors.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
         sColors = (NSColor**)malloc(sizeof(NSColor*) * java_awt_SystemColor_NUM_COLORS);
     } else {
         for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
-            if (sColors[i] != NULL) CFRelease(sColors[i]); // GC
+            if (sColors[i] != NULL) [sColors[i] release];
         }
     }
 
@@ -108,14 +108,14 @@
     sColors[java_awt_SystemColor_INFO_TEXT] =                [NSColor textColor];
 
     for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) {
-        if (sColors[i] != NULL) CFRetain(sColors[i]); // GC
+        [sColors[i] retain];
     }
 
     if (appleColors == nil) {
         appleColors = (NSColor**)malloc(sizeof(NSColor*) * sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS);
     } else {
         for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) {
-            if (appleColors[i] != NULL) CFRelease(appleColors[i]); // GC
+            if (appleColors[i] != NULL) [appleColors[i] release];
         }
     }
 
@@ -124,7 +124,7 @@
     appleColors[sun_lwawt_macosx_LWCToolkit_INACTIVE_SELECTION_FOREGROUND_COLOR] =    [NSColor controlDarkShadowColor];
 
     for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) {
-        if (appleColors[i] != NULL) CFRetain(appleColors[i]); // GC
+        [appleColors[i] retain];
     }
 }
 
diff --git a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
index df2d98d..4dcbf07 100644
--- a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
+++ b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1497,7 +1497,7 @@
     }
 
     if (isdo->nsRef) {
-        CFRelease(isdo->nsRef); // GC
+        [isdo->nsRef release];
         isdo->nsRef = nil;
     }
 
diff --git a/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m b/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
index 2078e1d..ffdf8b5 100644
--- a/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
+++ b/jdk/src/macosx/native/sun/awt/JavaAccessibilityAction.m
@@ -55,19 +55,6 @@
     [super dealloc];
 }
 
-- (void)finalize
-{
-    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
-    JNFDeleteWeakGlobalRef(env, fAccessibleAction);
-    fAccessibleAction = NULL;
-
-    JNFDeleteWeakGlobalRef(env, fComponent);
-    fComponent = NULL;
-
-    [super finalize];
-}
-
 
 - (NSString *)getDescription
 {
@@ -127,19 +114,6 @@
     [super dealloc];
 }
 
-- (void)finalize
-{
-    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
-    JNFDeleteWeakGlobalRef(env, fTabGroup);
-    fTabGroup = NULL;
-
-    JNFDeleteWeakGlobalRef(env, fComponent);
-    fComponent = NULL;
-
-    [super finalize];
-}
-
 - (NSString *)getDescription
 {
     return @"click";
diff --git a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
index d37a480..b740d05 100644
--- a/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
+++ b/jdk/src/macosx/native/sun/awt/JavaComponentAccessibility.m
@@ -194,20 +194,6 @@
 
     [super dealloc];
 }
-- (void)finalize
-{
-    [self unregisterFromCocoaAXSystem];
-
-    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
-    (*env)->DeleteWeakGlobalRef(env, fAccessible);
-    fAccessible = NULL;
-
-    (*env)->DeleteWeakGlobalRef(env, fComponent);
-    fComponent = NULL;
-
-    [super finalize];
-}
 
 - (void)postValueChanged
 {
@@ -371,8 +357,8 @@
     // must init freshly -alloc'd object
     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
 
-    // must hard CFRetain() pointer poked into Java object
-    CFRetain(newChild);
+    // must hard retain pointer poked into Java object
+    [newChild retain];
     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
     (*env)->DeleteLocalRef(env, jCAX);
 
@@ -1498,18 +1484,6 @@
     [super dealloc];
 }
 
-- (void)finalize
-{
-    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
-
-    if (fTabGroupAxContext != NULL) {
-        JNFDeleteWeakGlobalRef(env, fTabGroupAxContext);
-        fTabGroupAxContext = NULL;
-    }
-
-    [super finalize];
-}
-
 - (id)accessibilityValueAttribute
 {
     JNIEnv *env = [ThreadUtilities getJNIEnv];
diff --git a/jdk/src/macosx/native/sun/awt/LWCToolkit.m b/jdk/src/macosx/native/sun/awt/LWCToolkit.m
index 8f0a290..871f319 100644
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -273,17 +273,15 @@
 {
 AWT_ASSERT_APPKIT_THREAD;
 
-    AWTRunLoopObject *o = nil;
+    jlong result;
 
+JNF_COCOA_ENTER(env);
     // We double retain because this object is owned by both main thread and "other" thread
     // We release in both doAWTRunLoop and stopAWTRunLoop
-    o = [[AWTRunLoopObject alloc] init];
-    if (o) {
-        CFRetain(o); // GC
-        CFRetain(o); // GC
-        [o release];
-    }
-    return ptr_to_jlong(o);
+    result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]);
+JNF_COCOA_EXIT(env);
+
+    return result;
 }
 
 /*
@@ -320,10 +318,7 @@
 
         }
     }
-
-   
-    CFRelease(mediatorObject);
-
+    [mediatorObject release];
 JNF_COCOA_EXIT(env);
 }
 
@@ -341,7 +336,7 @@
 
     [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
 
-    CFRelease(mediatorObject);
+    [mediatorObject release];
 
 JNF_COCOA_EXIT(env);
 }
diff --git a/jdk/src/macosx/native/sun/awt/PrintModel.m b/jdk/src/macosx/native/sun/awt/PrintModel.m
index 8a172d7..bc20285 100644
--- a/jdk/src/macosx/native/sun/awt/PrintModel.m
+++ b/jdk/src/macosx/native/sun/awt/PrintModel.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (BOOL)runPageSetup {
     __block BOOL fResult = NO;
@@ -86,8 +85,8 @@
         fResult = [self safePrintLoop:printerView withEnv:env];
     } else {
         // Retain these so they don't go away while we're in Java
-        CFRetain(self); // GC
-        if (printerView) CFRetain(printerView); // GC
+        [self retain];
+        [printerView retain];
 
         static JNF_CLASS_CACHE(jc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob");
         static JNF_STATIC_MEMBER_CACHE(jm_detachPrintLoop, jc_CPrinterJob, "detachPrintLoop", "(JJ)V");
@@ -134,8 +133,8 @@
     [model safePrintLoop:arg withEnv:env];
 
     // These are to match the retains in runPrintLoopWithView:
-    if (model) CFRelease(model); // GC
-    if (arg) CFRelease(arg); // GC
+    [model release];
+    [arg release];
 
 JNF_COCOA_EXIT(env);
 }
diff --git a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
index 5df99a4..39c50af 100644
--- a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
+++ b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,6 @@
 
     [super dealloc];
 }
-//- (void)finalize { [super finalize]; }
 
 - (void)finishLaunching
 {
diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
index 13f2d93..7da36e1 100644
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
@@ -729,7 +729,11 @@
                     parse_iCCP_chunk(chunkLength);
                     break;
                 case iTXt_TYPE:
-                    parse_iTXt_chunk(chunkLength);
+                    if (ignoreMetadata) {
+                        stream.skipBytes(chunkLength);
+                    } else {
+                        parse_iTXt_chunk(chunkLength);
+                    }
                     break;
                 case pHYs_TYPE:
                     parse_pHYs_chunk();
@@ -753,7 +757,11 @@
                     parse_tRNS_chunk(chunkLength);
                     break;
                 case zTXt_TYPE:
-                    parse_zTXt_chunk(chunkLength);
+                    if (ignoreMetadata) {
+                        stream.skipBytes(chunkLength);
+                    } else {
+                        parse_zTXt_chunk(chunkLength);
+                    }
                     break;
                 default:
                     // Read an unknown chunk
diff --git a/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java b/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
index ae5c61d..77db225 100644
--- a/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
+++ b/jdk/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java
@@ -33,6 +33,8 @@
 
 import org.omg.CosNaming.*;
 
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
 /**
   * Implements the JNDI NamingEnumeration interface for COS
   * Naming. Gets hold of a list of bindings from the COS Naming Server
@@ -212,7 +214,10 @@
         Name cname = CNNameParser.cosNameToName(bndg.binding_name);
 
         try {
+            // Check whether object factory codebase is trusted
+            if (CorbaUtils.isObjectFactoryTrusted(obj)) {
             obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
+            }
         } catch (NamingException e) {
             throw e;
         } catch (Exception e) {
diff --git a/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java b/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
index 800c0a5..27dc14e 100644
--- a/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
+++ b/jdk/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java
@@ -36,6 +36,8 @@
 import java.io.InputStreamReader;
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import org.omg.CosNaming.*;
 import org.omg.CosNaming.NamingContextPackage.*;
@@ -82,6 +84,19 @@
     private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
     boolean federation = false;
 
+    /**
+     * Determines whether classes may be loaded from an arbitrary URL code base.
+     */
+    public static final boolean trustURLCodebase;
+    static {
+        // System property to control whether classes may be loaded from an
+        // arbitrary URL code base
+        PrivilegedAction<String> act = () -> System.getProperty(
+            "com.sun.jndi.cosnaming.object.trustURLCodebase", "false");
+        String trust = AccessController.doPrivileged(act);
+        trustURLCodebase = "true".equalsIgnoreCase(trust);
+    }
+
     // Reference counter for tracking _orb references
     OrbReuseTracker orbTracker = null;
     int enumCount;
@@ -534,12 +549,16 @@
             if (name.size() == 0 )
                 return this; // %%% should clone() so that env can be changed
             NameComponent[] path = CNNameParser.nameToCosName(name);
+            java.lang.Object answer = null;
 
             try {
-                java.lang.Object answer = callResolve(path);
-
+                answer = callResolve(path);
                 try {
-                    return NamingManager.getObjectInstance(answer, name, this, _env);
+                    // Check whether object factory codebase is trusted
+                    if (CorbaUtils.isObjectFactoryTrusted(answer)) {
+                        answer = NamingManager.getObjectInstance(
+                            answer, name, this, _env);
+                    }
                 } catch (NamingException e) {
                     throw e;
                 } catch (Exception e) {
@@ -552,6 +571,7 @@
                 javax.naming.Context cctx = getContinuationContext(cpe);
                 return cctx.lookup(cpe.getRemainingName());
             }
+            return answer;
     }
 
     /**
diff --git a/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java b/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
index a1e9fd6..f2c91a0 100644
--- a/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
+++ b/jdk/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java
@@ -33,6 +33,8 @@
 import org.omg.CosNaming.NamingContextPackage.*;
 import org.omg.CORBA.*;
 
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
 /**
   * A convenience class to map the COS Naming exceptions to the JNDI exceptions.
   * @author Raj Krishnamurthy
@@ -202,10 +204,13 @@
             // Not a context, use object factory to transform object.
 
             Name cname = CNNameParser.cosNameToName(resolvedName);
-            java.lang.Object resolvedObj2;
+            java.lang.Object resolvedObj2 = null;
             try {
+                // Check whether object factory codebase is trusted
+                if (CorbaUtils.isObjectFactoryTrusted(resolvedObj)) {
                 resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
                     cname, ctx, ctx._env);
+                }
             } catch (NamingException ge) {
                 throw ge;
             } catch (Exception ge) {
diff --git a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
index 2990ed8..8b38394 100644
--- a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
+++ b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java
@@ -32,6 +32,8 @@
 import java.rmi.server.*;
 import java.rmi.registry.Registry;
 import java.rmi.registry.LocateRegistry;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 import javax.naming.*;
 import javax.naming.spi.NamingManager;
@@ -52,6 +54,18 @@
     private int port;
     private static final NameParser nameParser = new AtomicNameParser();
     private static final String SOCKET_FACTORY = "com.sun.jndi.rmi.factory.socket";
+    /**
+     * Determines whether classes may be loaded from an arbitrary URL code base.
+     */
+    static final boolean trustURLCodebase;
+    static {
+        // System property to control whether classes may be loaded from an
+        // arbitrary URL codebase
+        PrivilegedAction<String> act = () -> System.getProperty(
+            "com.sun.jndi.rmi.object.trustURLCodebase", "false");
+        String trust = AccessController.doPrivileged(act);
+        trustURLCodebase = "true".equalsIgnoreCase(trust);
+    }
 
     Reference reference = null; // ref used to create this context, if any
 
@@ -461,6 +475,27 @@
             Object obj = (r instanceof RemoteReference)
                         ? ((RemoteReference)r).getReference()
                         : (Object)r;
+
+            /*
+             * Classes may only be loaded from an arbitrary URL codebase when
+             * the system property com.sun.jndi.rmi.object.trustURLCodebase
+             * has been set to "true".
+             */
+
+            // Use reference if possible
+            Reference ref = null;
+            if (obj instanceof Reference) {
+                ref = (Reference) obj;
+            } else if (obj instanceof Referenceable) {
+                ref = ((Referenceable)(obj)).getReference();
+            }
+
+            if (ref != null && ref.getFactoryClassLocation() != null &&
+                !trustURLCodebase) {
+                throw new ConfigurationException(
+                    "The object factory is untrusted. Set the system property" +
+                    " 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'.");
+            }
             return NamingManager.getObjectInstance(obj, name, this,
                                                    environment);
         } catch (NamingException e) {
diff --git a/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java b/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
index dd32fef..cb92e1b 100644
--- a/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
+++ b/jdk/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java
@@ -36,8 +36,9 @@
 
 import org.omg.CORBA.ORB;
 
-import javax.naming.Context;
-import javax.naming.ConfigurationException;
+import javax.naming.*;
+
+import com.sun.jndi.cosnaming.CNCtx;
 
 /**
   * Contains utilities for performing CORBA-related tasks:
@@ -204,6 +205,32 @@
     }
 
     /**
+     * Check whether object factory code base is trusted.
+     * Classes may only be loaded from an arbitrary URL code base when
+     * the system property com.sun.jndi.rmi.object.trustURLCodebase
+     * has been set to "true".
+     */
+    public static boolean isObjectFactoryTrusted(Object obj)
+        throws NamingException {
+
+        // Extract Reference, if possible
+        Reference ref = null;
+        if (obj instanceof Reference) {
+            ref = (Reference) obj;
+        } else if (obj instanceof Referenceable) {
+            ref = ((Referenceable)(obj)).getReference();
+        }
+
+        if (ref != null && ref.getFactoryClassLocation() != null &&
+                !CNCtx.trustURLCodebase) {
+            throw new ConfigurationException(
+                "The object factory is untrusted. Set the system property" +
+                " 'com.sun.jndi.cosnaming.object.trustURLCodebase' to 'true'.");
+        }
+        return true;
+    }
+
+    /**
      * This method returns a new ORB instance for the given applet
      * without creating a static dependency on java.applet.
      */
diff --git a/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
index e161b0e..edcdfa6 100644
--- a/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
+++ b/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java
@@ -426,7 +426,6 @@
             constraints = new SearchControls();
             constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
             constraints.setReturningAttributes(new String[0]); //return no attrs
-            constraints.setReturningObjFlag(true); // to get the full DN
         }
 
         authzIdentity = (String)options.get(AUTHZ_IDENTITY);
@@ -886,11 +885,7 @@
             // (Use the first entry if more than one is returned)
             if (results.hasMore()) {
                 SearchResult entry = results.next();
-
-                // %%% - use the SearchResult.getNameInNamespace method
-                //        available in JDK 1.5 and later.
-                //        (can remove call to constraints.setReturningObjFlag)
-                userDN = ((Context)entry.getObject()).getNameInNamespace();
+                userDN = entry.getNameInNamespace();
 
                 if (debug) {
                     System.out.println("\t\t[LdapLoginModule] found entry: " +
diff --git a/jdk/src/share/classes/java/awt/MenuComponent.java b/jdk/src/share/classes/java/awt/MenuComponent.java
index b65c843..e1b3a7d6 100644
--- a/jdk/src/share/classes/java/awt/MenuComponent.java
+++ b/jdk/src/share/classes/java/awt/MenuComponent.java
@@ -145,6 +145,10 @@
                 public Font getFont_NoClientCode(MenuComponent menuComp) {
                     return menuComp.getFont_NoClientCode();
                 }
+                @SuppressWarnings("unchecked")
+                public <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp) {
+                    return (T) menuComp.peer;
+                }
             });
     }
 
diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java
index 9da6182..b5cb828 100644
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java
@@ -37,13 +37,18 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+
 import static java.io.ObjectStreamClass.processQueue;
+
+import sun.misc.ObjectInputFilter;
 import sun.misc.ObjectStreamClassValidator;
 import sun.misc.SharedSecrets;
-import sun.misc.Unsafe;
 import sun.reflect.misc.ReflectUtil;
+import sun.misc.JavaOISAccess;
+import sun.util.logging.PlatformLogger;
 
 /**
  * An ObjectInputStream deserializes primitive data and objects previously
@@ -239,12 +244,48 @@
             new ReferenceQueue<>();
     }
 
+    static {
+        /* Setup access so sun.misc can invoke package private functions. */
+        sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() {
+            public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {
+                stream.setInternalObjectInputFilter(filter);
+            }
+
+            public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
+                return stream.getInternalObjectInputFilter();
+            }
+        });
+    }
+
+    /*
+     * Separate class to defer initialization of logging until needed.
+     */
+    private static class Logging {
+
+        /*
+         * Logger for ObjectInputFilter results.
+         * Setup the filter logger if it is set to INFO or WARNING.
+         * (Assuming it will not change).
+         */
+        private static final PlatformLogger traceLogger;
+        private static final PlatformLogger infoLogger;
+        static {
+            PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");
+            infoLogger = (filterLog != null &&
+                filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;
+            traceLogger = (filterLog != null &&
+                filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null;
+        }
+    }
+
     /** filter stream for handling block data conversion */
     private final BlockDataInputStream bin;
     /** validation callback list */
     private final ValidationList vlist;
     /** recursion depth */
-    private int depth;
+    private long depth;
+    /** Total number of references to any type of object, class, enum, proxy, etc. */
+    private long totalObjectRefs;
     /** whether stream is closed */
     private boolean closed;
 
@@ -271,6 +312,12 @@
     private SerialCallbackContext curContext;
 
     /**
+     * Filter of class descriptors and classes read from the stream;
+     * may be null.
+     */
+    private ObjectInputFilter serialFilter;
+
+    /**
      * Creates an ObjectInputStream that reads from the specified InputStream.
      * A serialization stream header is read from the stream and verified.
      * This constructor will block until the corresponding ObjectOutputStream
@@ -297,6 +344,7 @@
         bin = new BlockDataInputStream(in);
         handles = new HandleTable(10);
         vlist = new ValidationList();
+        serialFilter = ObjectInputFilter.Config.getSerialFilter();
         enableOverride = false;
         readStreamHeader();
         bin.setBlockDataMode(true);
@@ -327,6 +375,7 @@
         bin = null;
         handles = null;
         vlist = null;
+        serialFilter = ObjectInputFilter.Config.getSerialFilter();
         enableOverride = true;
     }
 
@@ -334,7 +383,7 @@
      * Read an object from the ObjectInputStream.  The class of the object, the
      * signature of the class, and the values of the non-transient and
      * non-static fields of the class and all of its supertypes are read.
-     * Default deserializing for a class can be overriden using the writeObject
+     * Default deserializing for a class can be overridden using the writeObject
      * and readObject methods.  Objects referenced by this object are read
      * transitively so that a complete equivalent graph of objects is
      * reconstructed by readObject.
@@ -1076,6 +1125,138 @@
     }
 
     /**
+     * Returns the serialization filter for this stream.
+     * The serialization filter is the most recent filter set in
+     * {@link #setInternalObjectInputFilter setInternalObjectInputFilter} or
+     * the initial process-wide filter from
+     * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}.
+     *
+     * @return the serialization filter for the stream; may be null
+     */
+    private final ObjectInputFilter getInternalObjectInputFilter() {
+        return serialFilter;
+    }
+
+    /**
+     * Set the serialization filter for the stream.
+     * The filter's {@link ObjectInputFilter#checkInput checkInput} method is called
+     * for each class and reference in the stream.
+     * The filter can check any or all of the class, the array length, the number
+     * of references, the depth of the graph, and the size of the input stream.
+     * <p>
+     * If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},
+     * {@code null} or throws a {@link RuntimeException},
+     * the active {@code readObject} or {@code readUnshared}
+     * throws {@link InvalidClassException}, otherwise deserialization
+     * continues uninterrupted.
+     * <p>
+     * The serialization filter is initialized to the value of
+     * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}
+     * when the {@code  ObjectInputStream} is constructed and can be set
+     * to a custom filter only once.
+     *
+     * @implSpec
+     * The filter, when not {@code null}, is invoked during {@link #readObject readObject}
+     * and {@link #readUnshared readUnshared} for each object
+     * (regular or class) in the stream including the following:
+     * <ul>
+     *     <li>each object reference previously deserialized from the stream
+     *     (class is {@code null}, arrayLength is -1),
+     *     <li>each regular class (class is not {@code null}, arrayLength is -1),
+     *     <li>each interface of a dynamic proxy and the dynamic proxy class itself
+     *     (class is not {@code null}, arrayLength is -1),
+     *     <li>each array is filtered using the array type and length of the array
+     *     (class is the array type, arrayLength is the requested length),
+     *     <li>each object replaced by its class' {@code readResolve} method
+     *         is filtered using the replacement object's class, if not {@code null},
+     *         and if it is an array, the arrayLength, otherwise -1,
+     *     <li>and each object replaced by {@link #resolveObject resolveObject}
+     *         is filtered using the replacement object's class, if not {@code null},
+     *         and if it is an array, the arrayLength, otherwise -1.
+     * </ul>
+     *
+     * When the {@link ObjectInputFilter#checkInput checkInput} method is invoked
+     * it is given access to the current class, the array length,
+     * the current number of references already read from the stream,
+     * the depth of nested calls to {@link #readObject readObject} or
+     * {@link #readUnshared readUnshared},
+     * and the implementation dependent number of bytes consumed from the input stream.
+     * <p>
+     * Each call to {@link #readObject readObject} or
+     * {@link #readUnshared readUnshared} increases the depth by 1
+     * before reading an object and decreases by 1 before returning
+     * normally or exceptionally.
+     * The depth starts at {@code 1} and increases for each nested object and
+     * decrements when each nested call returns.
+     * The count of references in the stream starts at {@code 1} and
+     * is increased before reading an object.
+     *
+     * @param filter the filter, may be null
+     * @throws SecurityException if there is security manager and the
+     *       {@code SerializablePermission("serialFilter")} is not granted
+     * @throws IllegalStateException if the {@linkplain #getInternalObjectInputFilter() current filter}
+     *       is not {@code null} and is not the process-wide filter
+     */
+    private final void setInternalObjectInputFilter(ObjectInputFilter filter) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new SerializablePermission("serialFilter"));
+        }
+        // Allow replacement of the process-wide filter if not already set
+        if (serialFilter != null &&
+                serialFilter != ObjectInputFilter.Config.getSerialFilter()) {
+            throw new IllegalStateException("filter can not be set more than once");
+        }
+        this.serialFilter = filter;
+    }
+
+    /**
+     * Invoke the serialization filter if non-null.
+     * If the filter rejects or an exception is thrown, throws InvalidClassException.
+     *
+     * @param clazz the class; may be null
+     * @param arrayLength the array length requested; use {@code -1} if not creating an array
+     * @throws InvalidClassException if it rejected by the filter or
+     *        a {@link RuntimeException} is thrown
+     */
+    private void filterCheck(Class<?> clazz, int arrayLength)
+            throws InvalidClassException {
+        if (serialFilter != null) {
+            RuntimeException ex = null;
+            ObjectInputFilter.Status status;
+            try {
+                status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,
+                        totalObjectRefs, depth, bin.getBytesRead()));
+            } catch (RuntimeException e) {
+                // Preventive interception of an exception to log
+                status = ObjectInputFilter.Status.REJECTED;
+                ex = e;
+            }
+            if (status == null  ||
+                    status == ObjectInputFilter.Status.REJECTED) {
+                // Debug logging of filter checks that fail
+                if (Logging.infoLogger != null) {
+                    Logging.infoLogger.info(
+                            "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
+                            status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
+                            Objects.toString(ex, "n/a"));
+                }
+                InvalidClassException ice = new InvalidClassException("filter status: " + status);
+                ice.initCause(ex);
+                throw ice;
+            } else {
+                // Trace logging for those that succeed
+                if (Logging.traceLogger != null) {
+                    Logging.traceLogger.finer(
+                            "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
+                            status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
+                            Objects.toString(ex, "n/a"));
+                }
+            }
+        }
+    }
+
+    /**
      * Provide access to the persistent fields read from the input stream.
      */
     public static abstract class GetField {
@@ -1324,6 +1505,7 @@
         }
 
         depth++;
+        totalObjectRefs++;
         try {
             switch (tc) {
                 case TC_NULL:
@@ -1400,6 +1582,15 @@
         }
         Object rep = resolveObject(obj);
         if (rep != obj) {
+            // The type of the original object has been filtered but resolveObject
+            // may have replaced it;  filter the replacement's type
+            if (rep != null) {
+                if (rep.getClass().isArray()) {
+                    filterCheck(rep.getClass(), Array.getLength(rep));
+                } else {
+                    filterCheck(rep.getClass(), -1);
+                }
+            }
             handles.setObject(passHandle, rep);
         }
         return rep;
@@ -1470,6 +1661,7 @@
             throw new InvalidObjectException(
                 "cannot read back reference to unshared object");
         }
+        filterCheck(null, -1);       // just a check for number of references, depth, no class
         return obj;
     }
 
@@ -1574,6 +1766,10 @@
                 ReflectUtil.checkProxyPackageAccess(
                         getClass().getClassLoader(),
                         cl.getInterfaces());
+                // Filter the interfaces
+                for (Class<?> clazz : cl.getInterfaces()) {
+                    filterCheck(clazz, -1);
+                }
             }
         } catch (ClassNotFoundException ex) {
             resolveEx = ex;
@@ -1582,6 +1778,9 @@
 
         desc.initProxy(cl, resolveEx, readClassDesc(false));
 
+        // Call filterCheck on the definition
+        filterCheck(desc.forClass(), -1);
+
         handles.finish(descHandle);
         passHandle = descHandle;
         return desc;
@@ -1629,8 +1828,12 @@
 
         desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
 
+        // Call filterCheck on the definition
+        filterCheck(desc.forClass(), -1);
+
         handles.finish(descHandle);
         passHandle = descHandle;
+
         return desc;
     }
 
@@ -1671,6 +1874,8 @@
         ObjectStreamClass desc = readClassDesc(false);
         int len = bin.readInt();
 
+        filterCheck(desc.forClass(), len);
+
         Object array = null;
         Class<?> cl, ccl = null;
         if ((cl = desc.forClass()) != null) {
@@ -1819,6 +2024,14 @@
                 rep = cloneArray(rep);
             }
             if (rep != obj) {
+                // Filter the replacement object
+                if (rep != null) {
+                    if (rep.getClass().isArray()) {
+                        filterCheck(rep.getClass(), Array.getLength(rep));
+                    } else {
+                        filterCheck(rep.getClass(), -1);
+                    }
+                }
                 handles.setObject(passHandle, obj = rep);
             }
         }
@@ -2009,22 +2222,22 @@
             desc.setPrimFieldValues(obj, primVals);
         }
 
-            int objHandle = passHandle;
-            ObjectStreamField[] fields = desc.getFields(false);
+        int objHandle = passHandle;
+        ObjectStreamField[] fields = desc.getFields(false);
         Object[] objVals = new Object[desc.getNumObjFields()];
-            int numPrimFields = fields.length - objVals.length;
-            for (int i = 0; i < objVals.length; i++) {
-                ObjectStreamField f = fields[numPrimFields + i];
-                objVals[i] = readObject0(f.isUnshared());
-                if (f.getField() != null) {
-                    handles.markDependency(objHandle, passHandle);
-                }
+        int numPrimFields = fields.length - objVals.length;
+        for (int i = 0; i < objVals.length; i++) {
+            ObjectStreamField f = fields[numPrimFields + i];
+            objVals[i] = readObject0(f.isUnshared());
+            if (f.getField() != null) {
+                handles.markDependency(objHandle, passHandle);
             }
+        }
         if (obj != null) {
             desc.setObjFieldValues(obj, objVals);
         }
-            passHandle = objHandle;
-        }
+        passHandle = objHandle;
+    }
 
     /**
      * Reads in and returns IOException that caused serialization to abort.
@@ -2297,6 +2510,51 @@
     }
 
     /**
+     * Hold a snapshot of values to be passed to an ObjectInputFilter.
+     */
+    static class FilterValues implements ObjectInputFilter.FilterInfo {
+        final Class<?> clazz;
+        final long arrayLength;
+        final long totalObjectRefs;
+        final long depth;
+        final long streamBytes;
+
+        public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,
+                            long depth, long streamBytes) {
+            this.clazz = clazz;
+            this.arrayLength = arrayLength;
+            this.totalObjectRefs = totalObjectRefs;
+            this.depth = depth;
+            this.streamBytes = streamBytes;
+        }
+
+        @Override
+        public Class<?> serialClass() {
+            return clazz;
+        }
+
+        @Override
+        public long arrayLength() {
+            return arrayLength;
+        }
+
+        @Override
+        public long references() {
+            return totalObjectRefs;
+        }
+
+        @Override
+        public long depth() {
+            return depth;
+        }
+
+        @Override
+        public long streamBytes() {
+            return streamBytes;
+        }
+    }
+
+    /**
      * Input stream supporting single-byte peek operations.
      */
     private static class PeekInputStream extends InputStream {
@@ -2305,6 +2563,8 @@
         private final InputStream in;
         /** peeked byte */
         private int peekb = -1;
+        /** total bytes read from the stream */
+        private long totalBytesRead = 0;
 
         /**
          * Creates new PeekInputStream on top of given underlying stream.
@@ -2318,7 +2578,12 @@
          * that it does not consume the read value.
          */
         int peek() throws IOException {
-            return (peekb >= 0) ? peekb : (peekb = in.read());
+            if (peekb >= 0) {
+                return peekb;
+            }
+            peekb = in.read();
+            totalBytesRead += peekb >= 0 ? 1 : 0;
+            return peekb;
         }
 
         public int read() throws IOException {
@@ -2327,21 +2592,27 @@
                 peekb = -1;
                 return v;
             } else {
-                return in.read();
+                int nbytes = in.read();
+                totalBytesRead += nbytes >= 0 ? 1 : 0;
+                return nbytes;
             }
         }
 
         public int read(byte[] b, int off, int len) throws IOException {
+            int nbytes;
             if (len == 0) {
                 return 0;
             } else if (peekb < 0) {
-                return in.read(b, off, len);
+                nbytes = in.read(b, off, len);
+                totalBytesRead += nbytes >= 0 ? nbytes : 0;
+                return nbytes;
             } else {
                 b[off++] = (byte) peekb;
                 len--;
                 peekb = -1;
-                int n = in.read(b, off, len);
-                return (n >= 0) ? (n + 1) : 1;
+                nbytes = in.read(b, off, len);
+                totalBytesRead += nbytes >= 0 ? nbytes : 0;
+                return (nbytes >= 0) ? (nbytes + 1) : 1;
             }
         }
 
@@ -2366,7 +2637,9 @@
                 skipped++;
                 n--;
             }
-            return skipped + skip(n);
+            n = skipped + in.skip(n);
+            totalBytesRead += n;
+            return n;
         }
 
         public int available() throws IOException {
@@ -2376,6 +2649,10 @@
         public void close() throws IOException {
             in.close();
         }
+
+        public long getBytesRead() {
+            return totalBytesRead;
+        }
     }
 
     /**
@@ -3231,6 +3508,14 @@
                     throw new UTFDataFormatException();
             }
         }
+
+        /**
+         * Returns the number of bytes read from the input stream.
+         * @return the number of bytes read from the input stream
+         */
+        long getBytesRead() {
+            return in.getBytesRead();
+        }
     }
 
     /**
diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
index acac29b..7b9353a 100644
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java
@@ -680,7 +680,9 @@
             // disallow lookup more restricted packages
             if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
                 if (name.startsWith("java.") ||
-                        (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
+                        (name.startsWith("sun.")
+                                && !name.startsWith("sun.invoke.")
+                                && !name.equals("sun.reflect.ReflectionFactory"))) {
                     throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
                 }
             }
diff --git a/jdk/src/share/classes/java/net/SocketInputStream.java b/jdk/src/share/classes/java/net/SocketInputStream.java
index 41b18bd..f9a50a0 100644
--- a/jdk/src/share/classes/java/net/SocketInputStream.java
+++ b/jdk/src/share/classes/java/net/SocketInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -155,11 +155,12 @@
         }
 
         // bounds check
-        if (length <= 0 || off < 0 || off + length > b.length) {
+        if (length <= 0 || off < 0 || length > b.length - off) {
             if (length == 0) {
                 return 0;
             }
-            throw new ArrayIndexOutOfBoundsException();
+            throw new ArrayIndexOutOfBoundsException("length == " + length
+                    + " off == " + off + " buffer length == " + b.length);
         }
 
         boolean gotReset = false;
diff --git a/jdk/src/share/classes/java/net/SocketOutputStream.java b/jdk/src/share/classes/java/net/SocketOutputStream.java
index 2404e95..20a63e6 100644
--- a/jdk/src/share/classes/java/net/SocketOutputStream.java
+++ b/jdk/src/share/classes/java/net/SocketOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,11 +97,13 @@
      */
     private void socketWrite(byte b[], int off, int len) throws IOException {
 
-        if (len <= 0 || off < 0 || off + len > b.length) {
+
+        if (len <= 0 || off < 0 || len > b.length - off) {
             if (len == 0) {
                 return;
             }
-            throw new ArrayIndexOutOfBoundsException();
+            throw new ArrayIndexOutOfBoundsException("len == " + len
+                    + " off == " + off + " buffer length == " + b.length);
         }
 
         FileDescriptor fd = impl.acquireFD();
diff --git a/jdk/src/share/classes/java/net/URL.java b/jdk/src/share/classes/java/net/URL.java
index a6cbcbc..919825a 100644
--- a/jdk/src/share/classes/java/net/URL.java
+++ b/jdk/src/share/classes/java/net/URL.java
@@ -1364,9 +1364,6 @@
                 path = file;
         }
 
-        if (port == -1) {
-            port = 0;
-        }
         // Set the object fields.
         this.protocol = protocol;
         this.host = host;
diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java
index a3038e2..c2394c7 100644
--- a/jdk/src/share/classes/java/net/URLClassLoader.java
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java
@@ -103,8 +103,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
+        ucp = new URLClassPath(urls, acc);
     }
 
     URLClassLoader(URL[] urls, ClassLoader parent,
@@ -115,8 +115,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
         this.acc = acc;
+        ucp = new URLClassPath(urls, acc);
     }
 
     /**
@@ -147,8 +147,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
+        ucp = new URLClassPath(urls, acc);
     }
 
     URLClassLoader(URL[] urls, AccessControlContext acc) {
@@ -158,8 +158,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
         this.acc = acc;
+        ucp = new URLClassPath(urls, acc);
     }
 
     /**
@@ -191,8 +191,8 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls, factory);
         acc = AccessController.getContext();
+        ucp = new URLClassPath(urls, factory, acc);
     }
 
     /* A map (used as a set) to keep track of closeable local resources
diff --git a/jdk/src/share/classes/java/net/URLStreamHandler.java b/jdk/src/share/classes/java/net/URLStreamHandler.java
index a77c5ed..5130559 100644
--- a/jdk/src/share/classes/java/net/URLStreamHandler.java
+++ b/jdk/src/share/classes/java/net/URLStreamHandler.java
@@ -161,9 +161,9 @@
             (spec.charAt(start + 1) == '/')) {
             start += 2;
             i = spec.indexOf('/', start);
-            if (i < 0) {
+            if (i < 0 || i > limit) {
                 i = spec.indexOf('?', start);
-                if (i < 0)
+                if (i < 0 || i > limit)
                     i = limit;
             }
 
@@ -171,8 +171,14 @@
 
             int ind = authority.indexOf('@');
             if (ind != -1) {
-                userInfo = authority.substring(0, ind);
-                host = authority.substring(ind+1);
+                if (ind != authority.lastIndexOf('@')) {
+                    // more than one '@' in authority. This is not server based
+                    userInfo = null;
+                    host = null;
+                } else {
+                    userInfo = authority.substring(0, ind);
+                    host = authority.substring(ind+1);
+                }
             } else {
                 userInfo = null;
             }
diff --git a/jdk/src/share/classes/java/rmi/MarshalledObject.java b/jdk/src/share/classes/java/rmi/MarshalledObject.java
index b5f8b73..18f4aba 100644
--- a/jdk/src/share/classes/java/rmi/MarshalledObject.java
+++ b/jdk/src/share/classes/java/rmi/MarshalledObject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,14 @@
 import java.io.ObjectStreamConstants;
 import java.io.OutputStream;
 import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import sun.rmi.server.MarshalInputStream;
 import sun.rmi.server.MarshalOutputStream;
 
+import sun.misc.ObjectInputFilter;
+
 /**
  * A <code>MarshalledObject</code> contains a byte stream with the serialized
  * representation of an object given to its constructor.  The <code>get</code>
@@ -90,6 +95,9 @@
      */
     private int hash;
 
+    /** Filter used when creating the instance from a stream; may be null. */
+    private transient ObjectInputFilter objectInputFilter = null;
+
     /** Indicate compatibility with 1.2 version of class. */
     private static final long serialVersionUID = 8988374069173025854L;
 
@@ -133,6 +141,20 @@
     }
 
     /**
+     * Reads in the state of the object and saves the stream's
+     * serialization filter to be used when the object is deserialized.
+     *
+     * @param stream the stream
+     * @throws IOException if an I/O error occurs
+     * @throws ClassNotFoundException if a class cannot be found
+     */
+    private void readObject(ObjectInputStream stream)
+        throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();     // read in all fields
+        objectInputFilter = ObjectInputFilter.Config.getObjectInputFilter(stream);
+    }
+
+    /**
      * Returns a new copy of the contained marshalledobject.  The internal
      * representation is deserialized with the semantics used for
      * unmarshaling parameters for RMI calls.
@@ -155,7 +177,7 @@
         ByteArrayInputStream lin =
             (locBytes == null ? null : new ByteArrayInputStream(locBytes));
         MarshalledObjectInputStream in =
-            new MarshalledObjectInputStream(bin, lin);
+            new MarshalledObjectInputStream(bin, lin, objectInputFilter);
         @SuppressWarnings("unchecked")
         T obj = (T) in.readObject();
         in.close();
@@ -295,11 +317,24 @@
          * <code>null</code>, then all annotations will be
          * <code>null</code>.
          */
-        MarshalledObjectInputStream(InputStream objIn, InputStream locIn)
+        MarshalledObjectInputStream(InputStream objIn, InputStream locIn,
+                    ObjectInputFilter filter)
             throws IOException
         {
             super(objIn);
             this.locIn = (locIn == null ? null : new ObjectInputStream(locIn));
+            if (filter != null) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    @Override
+                    public Void run() {
+                        ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this, filter);
+                        if (MarshalledObjectInputStream.this.locIn != null) {
+                            ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this.locIn, filter);
+                        }
+                        return null;
+                    }
+                });
+            }
         }
 
         /**
diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index c10abcc..990f3e8 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -40,6 +40,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 import sun.reflect.CallerSensitive;
@@ -410,7 +411,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -432,6 +443,21 @@
         }
 
         /**
+         * Returns true if the two classes have the same class loader and
+         * package qualifier
+         */
+        private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+            return class1.getClassLoader() == class2.getClassLoader()
+                   && Objects.equals(getPackageName(class1), getPackageName(class2));
+        }
+
+        private static String getPackageName(Class<?> cls) {
+            String cn = cls.getName();
+            int dot = cn.lastIndexOf('.');
+            return (dot != -1) ? cn.substring(0, dot) : "";
+        }
+
+        /**
          * Checks that target argument is instance of cclass.  On
          * failure, throws cause.
          */
diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index e701c67..b1d14c5 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -40,6 +40,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 import sun.reflect.CallerSensitive;
@@ -408,7 +409,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -539,7 +550,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -620,4 +641,19 @@
         } while (acl != null);
         return false;
     }
+
+    /**
+     * Returns true if the two classes have the same class loader and
+     * package qualifier
+     */
+    private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+        return class1.getClassLoader() == class2.getClassLoader()
+               && Objects.equals(getPackageName(class1), getPackageName(class2));
+}
+
+    private static String getPackageName(Class<?> cls) {
+        String cn = cls.getName();
+        int dot = cn.lastIndexOf('.');
+        return (dot != -1) ? cn.substring(0, dot) : "";
+    }
 }
diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 76fa0a7..cd18e48 100644
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -40,6 +40,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 import sun.reflect.CallerSensitive;
@@ -346,7 +347,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.vclass = vclass;
             this.offset = U.objectFieldOffset(field);
@@ -369,6 +380,21 @@
         }
 
         /**
+         * Returns true if the two classes have the same class loader and
+         * package qualifier
+         */
+        private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+            return class1.getClassLoader() == class2.getClassLoader()
+                   && Objects.equals(getPackageName(class1), getPackageName(class2));
+        }
+
+        private static String getPackageName(Class<?> cls) {
+            String cn = cls.getName();
+            int dot = cn.lastIndexOf('.');
+            return (dot != -1) ? cn.substring(0, dot) : "";
+        }
+
+        /**
          * Checks that target argument is instance of cclass.  On
          * failure, throws cause.
          */
diff --git a/jdk/src/share/classes/java/util/logging/Level.java b/jdk/src/share/classes/java/util/logging/Level.java
index f4e66ef..e42336d 100644
--- a/jdk/src/share/classes/java/util/logging/Level.java
+++ b/jdk/src/share/classes/java/util/logging/Level.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -599,11 +599,14 @@
             if (list != null) {
                 for (KnownLevel level : list) {
                     Level other = level.mirroredLevel;
+                    Class<? extends Level> type = level.levelObject.getClass();
                     if (l.value == other.value &&
                            (l.resourceBundleName == other.resourceBundleName ||
                                (l.resourceBundleName != null &&
                                 l.resourceBundleName.equals(other.resourceBundleName)))) {
-                        return level;
+                        if (type == l.getClass()) {
+                            return level;
+                        }
                     }
                 }
             }
diff --git a/jdk/src/share/classes/java/util/logging/LogRecord.java b/jdk/src/share/classes/java/util/logging/LogRecord.java
index d9255f4..9080bbc 100644
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -502,13 +502,21 @@
             throw new IOException("LogRecord: bad version: " + major + "." + minor);
         }
         int len = in.readInt();
-        if (len == -1) {
+        if (len < -1) {
+            throw new NegativeArraySizeException();
+        } else if (len == -1) {
             parameters = null;
-        } else {
+        } else if (len < 255) {
             parameters = new Object[len];
             for (int i = 0; i < parameters.length; i++) {
                 parameters[i] = in.readObject();
             }
+        } else {
+            List<Object> params = new ArrayList<>(Math.min(len, 1024));
+            for (int i = 0; i < len; i++) {
+                params.add(in.readObject());
+            }
+            parameters = params.toArray(new Object[params.size()]);
         }
         // If necessary, try to regenerate the resource bundle.
         if (resourceBundleName != null) {
diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
index d886cb6..b1f3815 100644
--- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
+++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -349,7 +349,7 @@
                   +", unwrapping parameters using classLoaderWithRepository.");
 
         values =
-            nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class));
+            nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
 
         try {
             final Object params2[] =
@@ -413,7 +413,7 @@
         values = nullIsEmpty(unwrap(params,
                                     getClassLoader(loaderName),
                                     defaultClassLoader,
-                                    Object[].class));
+                                    Object[].class,delegationSubject));
 
         try {
             final Object params2[] =
@@ -524,7 +524,7 @@
                  "connectionId=" + connectionId
                  +" unwrapping query with defaultClassLoader.");
 
-        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
 
         try {
             final Object params[] = new Object[] { name, queryValue };
@@ -559,7 +559,7 @@
                  "connectionId=" + connectionId
                  +" unwrapping query with defaultClassLoader.");
 
-        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class);
+        queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
 
         try {
             final Object params[] = new Object[] { name, queryValue };
@@ -709,7 +709,7 @@
         attr = unwrap(attribute,
                       getClassLoaderFor(name),
                       defaultClassLoader,
-                      Attribute.class);
+                      Attribute.class, delegationSubject);
 
         try {
             final Object params[] = new Object[] { name, attr };
@@ -760,7 +760,7 @@
             unwrap(attributes,
                    getClassLoaderFor(name),
                    defaultClassLoader,
-                   AttributeList.class);
+                   AttributeList.class, delegationSubject);
 
         try {
             final Object params[] = new Object[] { name, attrlist };
@@ -812,7 +812,7 @@
         values = nullIsEmpty(unwrap(params,
                                     getClassLoaderFor(name),
                                     defaultClassLoader,
-                                    Object[].class));
+                                    Object[].class, delegationSubject));
 
         try {
             final Object params2[] =
@@ -992,7 +992,7 @@
 
                 filterValues[i] =
                     unwrap(filters[i], targetCl, defaultClassLoader,
-                           NotificationFilter.class);
+                           NotificationFilter.class, sbjs[i]);
 
                 if (debug) logger.debug("addNotificationListener"+
                                         "(ObjectName,NotificationFilter)",
@@ -1060,7 +1060,7 @@
                  +" unwrapping filter with target extended ClassLoader.");
 
         filterValue =
-            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
 
         if (debug) logger.debug("addNotificationListener"+
                  "(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1068,7 +1068,7 @@
                  +" unwrapping handback with target extended ClassLoader.");
 
         handbackValue =
-            unwrap(handback, targetCl, defaultClassLoader, Object.class);
+            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
 
         try {
             final Object params[] =
@@ -1199,7 +1199,7 @@
                  +" unwrapping filter with target extended ClassLoader.");
 
         filterValue =
-            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class);
+            unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
 
         if (debug) logger.debug("removeNotificationListener"+
                  "(ObjectName,ObjectName,NotificationFilter,Object)",
@@ -1207,7 +1207,7 @@
                  +" unwrapping handback with target extended ClassLoader.");
 
         handbackValue =
-            unwrap(handback, targetCl, defaultClassLoader, Object.class);
+            unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
 
         try {
             final Object params[] =
@@ -1551,20 +1551,38 @@
         }
     }
 
-    private static <T> T unwrap(final MarshalledObject<?> mo,
+    private <T> T unwrap(final MarshalledObject<?> mo,
                                 final ClassLoader cl,
-                                final Class<T> wrappedClass)
+                                final Class<T> wrappedClass,
+                                Subject delegationSubject)
             throws IOException {
         if (mo == null) {
             return null;
         }
         try {
             final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
-            try {
-                return wrappedClass.cast(mo.get());
-            } catch (ClassNotFoundException cnfe) {
-                throw new UnmarshalException(cnfe.toString(), cnfe);
-            } finally {
+            try{
+                final AccessControlContext reqACC;
+                if (delegationSubject == null)
+                    reqACC = acc;
+                else {
+                    if (subject == null) {
+                        final String msg =
+                            "Subject delegation cannot be enabled unless " +
+                            "an authenticated subject is put in place";
+                        throw new SecurityException(msg);
+                    }
+                    reqACC = subjectDelegator.delegatedContext(
+                        acc, delegationSubject, removeCallerContext);
+                }
+                if(reqACC != null){
+                    return AccessController.doPrivileged(
+                            (PrivilegedExceptionAction<T>) () ->
+                                    wrappedClass.cast(mo.get()), reqACC);
+                }else{
+                    return wrappedClass.cast(mo.get());
+                }
+            }finally{
                 AccessController.doPrivileged(new SetCcl(old));
             }
         } catch (PrivilegedActionException pe) {
@@ -1577,14 +1595,19 @@
             }
             logger.warning("unwrap", "Failed to unmarshall object: " + e);
             logger.debug("unwrap", e);
+        }catch (ClassNotFoundException ex) {
+            logger.warning("unwrap", "Failed to unmarshall object: " + ex);
+            logger.debug("unwrap", ex);
+            throw new UnmarshalException(ex.toString(), ex);
         }
         return null;
     }
 
-    private static <T> T unwrap(final MarshalledObject<?> mo,
+    private <T> T unwrap(final MarshalledObject<?> mo,
                                 final ClassLoader cl1,
                                 final ClassLoader cl2,
-                                final Class<T> wrappedClass)
+                                final Class<T> wrappedClass,
+                                Subject delegationSubject)
         throws IOException {
         if (mo == null) {
             return null;
@@ -1598,7 +1621,7 @@
                     }
                 }
             );
-            return unwrap(mo, orderCL, wrappedClass);
+            return unwrap(mo, orderCL, wrappedClass,delegationSubject);
         } catch (PrivilegedActionException pe) {
             Exception e = extractException(pe);
             if (e instanceof IOException) {
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
index f5cdec5..b7de1ff 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $
@@ -38,7 +38,6 @@
 
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
 import com.sun.org.apache.xml.internal.security.transforms.Transform;
-import com.sun.org.apache.xml.internal.security.transforms.Transforms;
 
 import javax.xml.crypto.*;
 import javax.xml.crypto.dom.DOMCryptoContext;
@@ -150,7 +149,7 @@
 
         if (Utils.secureValidation(xc)) {
             String algorithm = getAlgorithm();
-            if (Transforms.TRANSFORM_XSLT.equals(algorithm)) {
+            if (Policy.restrictAlg(algorithm)) {
                 throw new TransformException(
                     "Transform " + algorithm + " is forbidden when secure validation is enabled"
                 );
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
index bbc483b..d8fc21c 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -113,9 +113,10 @@
                                            localName + ", expected Reference");
             }
             refs.add(new DOMReference(refElem, context, provider));
-            if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) {
-                String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " "
-                    + "references per Manifest are allowed with secure validation";
+            if (secVal && Policy.restrictNumReferences(refs.size())) {
+                String error = "A maximum of " + Policy.maxReferences()
+                    + " references per Manifest are allowed when"
+                    + " secure validation is enabled";
                 throw new MarshalException(error);
             }
             refElem = DOMUtils.getNextSiblingElement(refElem);
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
index 5896183..dbb9be5 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -51,7 +51,6 @@
 import org.w3c.dom.Node;
 
 import org.jcp.xml.dsig.internal.DigesterOutputStream;
-import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm;
 import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
 import com.sun.org.apache.xml.internal.security.utils.Base64;
@@ -67,11 +66,6 @@
     implements Reference, DOMURIReference {
 
    /**
-    * The maximum number of transforms per reference, if secure validation is enabled.
-    */
-   public static final int MAXIMUM_TRANSFORM_COUNT = 5;
-
-   /**
     * Look up useC14N11 system property. If true, an explicit C14N11 transform
     * will be added if necessary when generating the signature. See section
     * 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info.
@@ -217,9 +211,10 @@
                 }
                 transforms.add
                     (new DOMTransform(transformElem, context, provider));
-                if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) {
-                    String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " "
-                        + "transforms per Reference are allowed with secure validation";
+                if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+                    String error = "A maximum of " + Policy.maxTransforms()
+                        + " transforms per Reference are allowed when"
+                        + " secure validation is enabled";
                     throw new MarshalException(error);
                 }
                 transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -236,10 +231,10 @@
         Element dmElem = nextSibling;
         this.digestMethod = DOMDigestMethod.unmarshal(dmElem);
         String digestMethodAlgorithm = this.digestMethod.getAlgorithm();
-        if (secVal
-            && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) {
+        if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) {
             throw new MarshalException(
-                "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled"
+                "It is forbidden to use algorithm " + digestMethodAlgorithm +
+                " when secure validation is enabled"
             );
         }
 
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
index 2e8ccbe..73d8019 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -154,9 +154,10 @@
                 }
                 transforms.add
                     (new DOMTransform(transformElem, context, provider));
-                if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) {
-                    String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " "
-                        + "transforms per Reference are allowed with secure validation";
+                if (secVal && Policy.restrictNumTransforms(transforms.size())) {
+                    String error = "A maximum of " + Policy.maxTransforms()
+                        + " transforms per Reference are allowed when"
+                        + " secure validation is enabled";
                     throw new MarshalException(error);
                 }
                 transformElem = DOMUtils.getNextSiblingElement(transformElem);
@@ -243,7 +244,8 @@
         }
 
         // guard against RetrievalMethod loops
-        if ((data instanceof NodeSetData) && Utils.secureValidation(context)) {
+        if ((data instanceof NodeSetData) && Utils.secureValidation(context)
+            && Policy.restrictRetrievalMethodLoops()) {
             NodeSetData nsd = (NodeSetData)data;
             Iterator i = nsd.iterator();
             if (i.hasNext()) {
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
index bb615d2..bc90eab 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMSignatureMethod.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -41,6 +41,7 @@
 import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA;
 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
 import org.jcp.xml.dsig.internal.SignerOutputStream;
+import sun.security.util.KeyUtil;
 
 /**
  * DOM-based abstract implementation of SignatureMethod.
@@ -162,6 +163,7 @@
         if (!(key instanceof PublicKey)) {
             throw new InvalidKeyException("key must be PublicKey");
         }
+        checkKeySize(context, key);
         if (signature == null) {
             try {
                 Provider p = (Provider)context.getProperty
@@ -197,6 +199,37 @@
         }
     }
 
+    /**
+     * If secure validation mode is enabled, checks that the key size is
+     * restricted.
+     *
+     * @param context the context
+     * @param key the key to check
+     * @throws XMLSignatureException if the key size is restricted
+     */
+    private static void checkKeySize(XMLCryptoContext context, Key key)
+        throws XMLSignatureException {
+        if (Utils.secureValidation(context)) {
+            int size = KeyUtil.getKeySize(key);
+            if (size == -1) {
+                // key size cannot be determined, so we cannot check against
+                // restrictions. Note that a DSA key w/o params will be
+                // rejected later if the certificate chain is validated.
+                if (log.isLoggable(java.util.logging.Level.FINE)) {
+                    log.log(java.util.logging.Level.FINE, "Size for " +
+                            key.getAlgorithm() + " key cannot be determined");
+                }
+                return;
+            }
+            if (Policy.restrictKey(key.getAlgorithm(), size)) {
+                throw new XMLSignatureException(key.getAlgorithm() +
+                    " keys less than " +
+                    Policy.minKeySize(key.getAlgorithm()) + " bits are" +
+                    " forbidden when secure validation is enabled");
+            }
+        }
+    }
+
     byte[] sign(Key key, SignedInfo si, XMLSignContext context)
         throws InvalidKeyException, XMLSignatureException
     {
@@ -207,6 +240,7 @@
         if (!(key instanceof PrivateKey)) {
             throw new InvalidKeyException("key must be PrivateKey");
         }
+        checkKeySize(context, key);
         if (signature == null) {
             try {
                 Provider p = (Provider)context.getProperty
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
index d86dd1b..3e2f799 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $
@@ -45,7 +45,6 @@
 import org.w3c.dom.Node;
 
 import com.sun.org.apache.xml.internal.security.utils.Base64;
-import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
 
 /**
@@ -55,22 +54,9 @@
  */
 public final class DOMSignedInfo extends DOMStructure implements SignedInfo {
 
-    /**
-     * The maximum number of references per Manifest, if secure validation is enabled.
-     */
-    public static final int MAXIMUM_REFERENCE_COUNT = 30;
-
     private static java.util.logging.Logger log =
         java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
 
-    /** Signature - NOT Recommended RSAwithMD5 */
-    private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 =
-        Constants.MoreAlgorithmsSpecNS + "rsa-md5";
-
-    /** HMAC - NOT Recommended HMAC-MD5 */
-    private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 =
-        Constants.MoreAlgorithmsSpecNS + "hmac-md5";
-
     private List<Reference> references;
     private CanonicalizationMethod canonicalizationMethod;
     private SignatureMethod signatureMethod;
@@ -163,10 +149,10 @@
         boolean secVal = Utils.secureValidation(context);
 
         String signatureMethodAlgorithm = signatureMethod.getAlgorithm();
-        if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm)
-                || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) {
+        if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) {
             throw new MarshalException(
-                "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled"
+                "It is forbidden to use algorithm " + signatureMethodAlgorithm +
+                " when secure validation is enabled"
             );
         }
 
@@ -184,9 +170,10 @@
             }
             refList.add(new DOMReference(refElem, context, provider));
 
-            if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) {
-                String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " "
-                    + "references per Manifest are allowed with secure validation";
+            if (secVal && Policy.restrictNumReferences(refList.size())) {
+                String error = "A maximum of " + Policy.maxReferences()
+                    + " references per Manifest are allowed when"
+                    + " secure validation is enabled";
                 throw new MarshalException(error);
             }
             refElem = DOMUtils.getNextSiblingElement(refElem);
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
index 209de66..72791df 100644
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java
@@ -73,6 +73,11 @@
 
         boolean secVal = Utils.secureValidation(context);
 
+        if (secVal && Policy.restrictReferenceUriScheme(uri)) {
+            throw new URIReferenceException(
+                "Uri " + uri + " is forbidden when secure validation is enabled");
+        }
+
         // Check if same-document URI and already registered on the context
         if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') {
             String id = uri.substring(1);
@@ -83,12 +88,19 @@
                 id = id.substring(i1+1, i2);
             }
 
-            Node referencedElem = dcc.getElementById(id);
+            // check if element is registered by Id
+            Node referencedElem = uriAttr.getOwnerDocument().getElementById(id);
+            if (referencedElem == null) {
+               // see if element is registered in DOMCryptoContext
+               referencedElem = dcc.getElementById(id);
+            }
             if (referencedElem != null) {
-                if (secVal) {
+                if (secVal && Policy.restrictDuplicateIds()) {
                     Element start = referencedElem.getOwnerDocument().getDocumentElement();
                     if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) {
-                        String error = "Multiple Elements with the same ID " + id + " were detected";
+                        String error = "Multiple Elements with the same ID "
+                            + id + " detected when secure validation"
+                            + " is enabled";
                         throw new URIReferenceException(error);
                     }
                 }
@@ -110,9 +122,9 @@
 
         try {
             ResourceResolver apacheResolver =
-                ResourceResolver.getInstance(uriAttr, baseURI, secVal);
+                ResourceResolver.getInstance(uriAttr, baseURI, false);
             XMLSignatureInput in = apacheResolver.resolve(uriAttr,
-                                                          baseURI, secVal);
+                                                          baseURI, false);
             if (in.isOctetStream()) {
                 return new ApacheOctetStreamData(in);
             } else {
diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java
new file mode 100644
index 0000000..1608ad8
--- /dev/null
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 org.jcp.xml.dsig.internal.dom;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The secure validation policy as specified by the
+ * jdk.xml.dsig.secureValidationPolicy security property.
+ */
+public final class Policy {
+
+    // all restrictions are initialized to be unconstrained
+    private static Set<URI> disallowedAlgs = new HashSet<>();
+    private static int maxTrans = Integer.MAX_VALUE;
+    private static int maxRefs = Integer.MAX_VALUE;
+    private static Set<String> disallowedRefUriSchemes = new HashSet<>();
+    private static Map<String, Integer> minKeyMap = new HashMap<>();
+    private static boolean noDuplicateIds = false;
+    private static boolean noRMLoops = false;
+
+    static {
+        try {
+            initialize();
+        } catch (Exception e) {
+            throw new SecurityException(
+                "Cannot initialize the secure validation policy", e);
+        }
+    }
+
+    private Policy() {}
+
+    private static void initialize() {
+        String prop =
+            AccessController.doPrivileged((PrivilegedAction<String>) () ->
+                Security.getProperty("jdk.xml.dsig.secureValidationPolicy"));
+        if (prop == null || prop.isEmpty()) {
+            // no policy specified, so don't enforce any restrictions
+            return;
+        }
+        String[] entries = prop.split(",");
+        for (String entry : entries) {
+            String[] tokens = entry.split("\\s");
+            String type = tokens[0];
+            switch(type) {
+                case "disallowAlg":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    disallowedAlgs.add(URI.create(tokens[1]));
+                    break;
+                case "maxTransforms":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    maxTrans = Integer.parseUnsignedInt(tokens[1]);
+                    break;
+                case "maxReferences":
+                    if (tokens.length != 2) {
+                        error(entry);
+                    }
+                    maxRefs = Integer.parseUnsignedInt(tokens[1]);
+                    break;
+                case "disallowReferenceUriSchemes":
+                    if (tokens.length == 1) {
+                        error(entry);
+                    }
+                    for (int i = 1; i < tokens.length; i++) {
+                        String scheme = tokens[i];
+                        disallowedRefUriSchemes.add(
+                            scheme.toLowerCase(Locale.ROOT));
+                    }
+                    break;
+                case "minKeySize":
+                    if (tokens.length != 3) {
+                        error(entry);
+                    }
+                    minKeyMap.put(tokens[1],
+                                  Integer.parseUnsignedInt(tokens[2]));
+                    break;
+                case "noDuplicateIds":
+                    if (tokens.length != 1) {
+                        error(entry);
+                    }
+                    noDuplicateIds = true;
+                    break;
+                case "noRetrievalMethodLoops":
+                    if (tokens.length != 1) {
+                        error(entry);
+                    }
+                    noRMLoops = true;
+                    break;
+                default:
+                    error(entry);
+            }
+        }
+    }
+
+    public static boolean restrictAlg(String alg) {
+        try {
+            URI uri = new URI(alg);
+            return disallowedAlgs.contains(uri);
+        } catch (URISyntaxException use) {
+            return false;
+        }
+    }
+
+    public static boolean restrictNumTransforms(int numTrans) {
+        return (numTrans > maxTrans);
+    }
+
+    public static boolean restrictNumReferences(int numRefs) {
+        return (numRefs > maxRefs);
+    }
+
+    public static boolean restrictReferenceUriScheme(String uri) {
+        if (uri != null) {
+            String scheme = java.net.URI.create(uri).getScheme();
+            if (scheme != null) {
+                return disallowedRefUriSchemes.contains(
+                    scheme.toLowerCase(Locale.ROOT));
+            }
+        }
+        return false;
+    }
+
+    public static boolean restrictKey(String type, int size) {
+        return (size < minKeyMap.getOrDefault(type, 0));
+    }
+
+    public static boolean restrictDuplicateIds() {
+        return noDuplicateIds;
+    }
+
+    public static boolean restrictRetrievalMethodLoops() {
+        return noRMLoops;
+    }
+
+    public static Set<URI> disabledAlgs() {
+        return Collections.<URI>unmodifiableSet(disallowedAlgs);
+    }
+
+    public static int maxTransforms() {
+        return maxTrans;
+    }
+
+    public static int maxReferences() {
+        return maxRefs;
+    }
+
+    public static Set<String> disabledReferenceUriSchemes() {
+        return Collections.<String>unmodifiableSet(disallowedRefUriSchemes);
+    }
+
+    public static int minKeySize(String type) {
+        return minKeyMap.getOrDefault(type, 0);
+    }
+
+    private static void error(String entry) {
+        throw new IllegalArgumentException(
+            "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry);
+    }
+}
diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java
index 0470dad..45d806b 100644
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java
@@ -36,6 +36,7 @@
 import java.awt.event.KeyEvent;
 import java.awt.geom.Point2D;
 import java.awt.peer.ComponentPeer;
+import java.awt.peer.MenuComponentPeer;
 
 import java.lang.reflect.InvocationTargetException;
 import java.security.AccessControlContext;
@@ -469,6 +470,11 @@
          * Gets the font used for this menu component.
          */
         Font getFont_NoClientCode(MenuComponent menuComp);
+
+        /**
+         * Returns the peer of the menu component.
+         */
+        <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp);
     }
 
     /**
diff --git a/jdk/src/share/classes/sun/misc/JarIndex.java b/jdk/src/share/classes/sun/misc/JarIndex.java
index e43b9ee..6e08cf2 100644
--- a/jdk/src/share/classes/sun/misc/JarIndex.java
+++ b/jdk/src/share/classes/sun/misc/JarIndex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,11 @@
 package sun.misc;
 
 import java.io.*;
+import java.security.AccessController;
 import java.util.*;
 import java.util.jar.*;
 import java.util.zip.*;
+import sun.security.action.GetPropertyAction;
 
 /**
  * This class is used to maintain mappings from packages, classes
@@ -72,7 +74,8 @@
      * be added to the index. Otherwise, just the directory names are added.
      */
     private static final boolean metaInfFilenames =
-        "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+        "true".equals(AccessController.doPrivileged(
+             new GetPropertyAction("sun.misc.JarIndex.metaInfFilenames")));
 
     /**
      * Constructs a new, empty jar index.
diff --git a/jdk/src/share/classes/sun/misc/JavaOISAccess.java b/jdk/src/share/classes/sun/misc/JavaOISAccess.java
new file mode 100644
index 0000000..8be96eb
--- /dev/null
+++ b/jdk/src/share/classes/sun/misc/JavaOISAccess.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 sun.misc;
+
+import java.io.ObjectInputStream;
+
+public interface JavaOISAccess {
+    void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter);
+    ObjectInputFilter getObjectInputFilter(ObjectInputStream stream);
+}
diff --git a/jdk/src/share/classes/sun/misc/Launcher.java b/jdk/src/share/classes/sun/misc/Launcher.java
index f72f60e..0f33139 100644
--- a/jdk/src/share/classes/sun/misc/Launcher.java
+++ b/jdk/src/share/classes/sun/misc/Launcher.java
@@ -408,7 +408,7 @@
             } else {
                 urls = new URL[0];
             }
-            bcp = new URLClassPath(urls, factory);
+            bcp = new URLClassPath(urls, factory, null);
             bcp.initLookupCache(null);
         }
     }
diff --git a/jdk/src/share/classes/sun/misc/ObjectInputFilter.java b/jdk/src/share/classes/sun/misc/ObjectInputFilter.java
new file mode 100644
index 0000000..467f7b7
--- /dev/null
+++ b/jdk/src/share/classes/sun/misc/ObjectInputFilter.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 sun.misc;
+
+import java.io.ObjectInputStream;
+import java.io.SerializablePermission;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * Filter classes, array lengths, and graph metrics during deserialization.
+ * If set on an {@link ObjectInputStream}, the {@link #checkInput checkInput(FilterInfo)}
+ * method is called to validate classes, the length of each array,
+ * the number of objects being read from the stream, the depth of the graph,
+ * and the total number of bytes read from the stream.
+ * <p>
+ * A filter can be set via {@link ObjectInputStream#setObjectInputFilter setObjectInputFilter}
+ * for an individual ObjectInputStream.
+ * A filter can be set via {@link Config#setSerialFilter(ObjectInputFilter) Config.setSerialFilter}
+ * to affect every {@code ObjectInputStream} that does not otherwise set a filter.
+ * <p>
+ * A filter determines whether the arguments are {@link Status#ALLOWED ALLOWED}
+ * or {@link Status#REJECTED REJECTED} and should return the appropriate status.
+ * If the filter cannot determine the status it should return
+ * {@link Status#UNDECIDED UNDECIDED}.
+ * Filters should be designed for the specific use case and expected types.
+ * A filter designed for a particular use may be passed a class that is outside
+ * of the scope of the filter. If the purpose of the filter is to black-list classes
+ * then it can reject a candidate class that matches and report UNDECIDED for others.
+ * A filter may be called with class equals {@code null}, {@code arrayLength} equal -1,
+ * the depth, number of references, and stream size and return a status
+ * that reflects only one or only some of the values.
+ * This allows a filter to specific about the choice it is reporting and
+ * to use other filters without forcing either allowed or rejected status.
+ *
+ * <p>
+ * Typically, a custom filter should check if a process-wide filter
+ * is configured and defer to it if so. For example,
+ * <pre>{@code
+ * ObjectInputFilter.Status checkInput(FilterInfo info) {
+ *     ObjectInputFilter serialFilter = ObjectInputFilter.Config.getSerialFilter();
+ *     if (serialFilter != null) {
+ *         ObjectInputFilter.Status status = serialFilter.checkInput(info);
+ *         if (status != ObjectInputFilter.Status.UNDECIDED) {
+ *             // The process-wide filter overrides this filter
+ *             return status;
+ *         }
+ *     }
+ *     if (info.serialClass() != null &&
+ *         Remote.class.isAssignableFrom(info.serialClass())) {
+ *         return Status.REJECTED;      // Do not allow Remote objects
+ *     }
+ *     return Status.UNDECIDED;
+ * }
+ *}</pre>
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a
+ * method in this interface and its nested classes will cause a
+ * {@link NullPointerException} to be thrown.
+ *
+ * @since 8u
+ */
+@FunctionalInterface
+public interface ObjectInputFilter {
+
+    /**
+     * Check the class, array length, number of object references, depth,
+     * stream size, and other available filtering information.
+     * Implementations of this method check the contents of the object graph being created
+     * during deserialization. The filter returns {@link Status#ALLOWED Status.ALLOWED},
+     * {@link Status#REJECTED Status.REJECTED}, or {@link Status#UNDECIDED Status.UNDECIDED}.
+     *
+     * @param filterInfo provides information about the current object being deserialized,
+     *             if any, and the status of the {@link ObjectInputStream}
+     * @return  {@link Status#ALLOWED Status.ALLOWED} if accepted,
+     *          {@link Status#REJECTED Status.REJECTED} if rejected,
+     *          {@link Status#UNDECIDED Status.UNDECIDED} if undecided.
+     */
+    Status checkInput(FilterInfo filterInfo);
+
+    /**
+     * FilterInfo provides access to information about the current object
+     * being deserialized and the status of the {@link ObjectInputStream}.
+     * @since 9
+     */
+    interface FilterInfo {
+        /**
+         * The class of an object being deserialized.
+         * For arrays, it is the array type.
+         * For example, the array class name of a 2 dimensional array of strings is
+         * "{@code [[Ljava.lang.String;}".
+         * To check the array's element type, iteratively use
+         * {@link Class#getComponentType() Class.getComponentType} while the result
+         * is an array and then check the class.
+         * The {@code serialClass is null} in the case where a new object is not being
+         * created and to give the filter a chance to check the depth, number of
+         * references to existing objects, and the stream size.
+         *
+         * @return class of an object being deserialized; may be null
+         */
+        Class<?> serialClass();
+
+        /**
+         * The number of array elements when deserializing an array of the class.
+         *
+         * @return the non-negative number of array elements when deserializing
+         * an array of the class, otherwise -1
+         */
+        long arrayLength();
+
+        /**
+         * The current depth.
+         * The depth starts at {@code 1} and increases for each nested object and
+         * decrements when each nested object returns.
+         *
+         * @return the current depth
+         */
+        long depth();
+
+        /**
+         * The current number of object references.
+         *
+         * @return the non-negative current number of object references
+         */
+        long references();
+
+        /**
+         * The current number of bytes consumed.
+         * @implSpec  {@code streamBytes} is implementation specific
+         * and may not be directly related to the object in the stream
+         * that caused the callback.
+         *
+         * @return the non-negative current number of bytes consumed
+         */
+        long streamBytes();
+    }
+
+    /**
+     * The status of a check on the class, array length, number of references,
+     * depth, and stream size.
+     *
+     * @since 8u
+     */
+    enum Status {
+        /**
+         * The status is undecided, not allowed and not rejected.
+         */
+        UNDECIDED,
+        /**
+         * The status is allowed.
+         */
+        ALLOWED,
+        /**
+         * The status is rejected.
+         */
+        REJECTED;
+    }
+
+    /**
+     * A utility class to set and get the process-wide filter or create a filter
+     * from a pattern string. If a process-wide filter is set, it will be
+     * used for each {@link ObjectInputStream} that does not set its own filter.
+     * <p>
+     * When setting the filter, it should be stateless and idempotent,
+     * reporting the same result when passed the same arguments.
+     * <p>
+     * The filter is configured using the {@link java.security.Security}
+     * property {@code jdk.serialFilter} and can be overridden by
+     * the System property {@code jdk.serialFilter}.
+     *
+     * The syntax is the same as for the {@link #createFilter(String) createFilter} method.
+     *
+     * @since 8u
+     */
+    final class Config {
+        /* No instances. */
+        private Config() {}
+
+        /**
+         * Lock object for process-wide filter.
+         */
+        private final static Object serialFilterLock = new Object();
+
+        /**
+         * Debug: Logger
+         */
+        private final static PlatformLogger configLog;
+
+        /**
+         * Logger for debugging.
+         */
+        static void filterLog(PlatformLogger.Level level, String msg, Object... args) {
+            if (configLog != null) {
+                if (PlatformLogger.Level.INFO.equals(level)) {
+                    configLog.info(msg, args);
+                } else if (PlatformLogger.Level.WARNING.equals(level)) {
+                    configLog.warning(msg, args);
+                } else {
+                    configLog.severe(msg, args);
+                }
+            }
+        }
+
+        /**
+         * The name for the process-wide deserialization filter.
+         * Used as a system property and a java.security.Security property.
+         */
+        private final static String SERIAL_FILTER_PROPNAME = "jdk.serialFilter";
+
+        /**
+         * The process-wide filter; may be null.
+         * Lookup the filter in java.security.Security or
+         * the system property.
+         */
+        private final static ObjectInputFilter configuredFilter;
+
+        static {
+            configuredFilter = AccessController
+                    .doPrivileged((PrivilegedAction<ObjectInputFilter>) () -> {
+                        String props = System.getProperty(SERIAL_FILTER_PROPNAME);
+                        if (props == null) {
+                            props = Security.getProperty(SERIAL_FILTER_PROPNAME);
+                        }
+                        if (props != null) {
+                            PlatformLogger log = PlatformLogger.getLogger("java.io.serialization");
+                            log.info("Creating serialization filter from {0}", props);
+                            try {
+                                return createFilter(props);
+                            } catch (RuntimeException re) {
+                                log.warning("Error configuring filter: {0}", re);
+                            }
+                        }
+                        return null;
+                    });
+            configLog = (configuredFilter != null) ? PlatformLogger.getLogger("java.io.serialization") : null;
+        }
+
+        /**
+         * Current configured filter.
+         */
+        private static ObjectInputFilter serialFilter = configuredFilter;
+
+        /**
+         * Get the filter for classes being deserialized on the ObjectInputStream.
+         *
+         * @param inputStream ObjectInputStream from which to get the filter; non-null
+         * @throws RuntimeException if the filter rejects
+         */
+        public static ObjectInputFilter getObjectInputFilter(ObjectInputStream inputStream) {
+            Objects.requireNonNull(inputStream, "inputStream");
+            return sun.misc.SharedSecrets.getJavaOISAccess().getObjectInputFilter(inputStream);
+        }
+
+        /**
+         * Set the process-wide filter if it has not already been configured or set.
+         *
+         * @param inputStream ObjectInputStream on which to set the filter; non-null
+         * @param filter the serialization filter to set as the process-wide filter; not null
+         * @throws SecurityException if there is security manager and the
+         *       {@code SerializablePermission("serialFilter")} is not granted
+         * @throws IllegalStateException if the filter has already been set {@code non-null}
+         */
+        public static void setObjectInputFilter(ObjectInputStream inputStream,
+                                                ObjectInputFilter filter) {
+            Objects.requireNonNull(inputStream, "inputStream");
+            sun.misc.SharedSecrets.getJavaOISAccess().setObjectInputFilter(inputStream, filter);
+        }
+
+        /**
+         * Returns the process-wide serialization filter or {@code null} if not configured.
+         *
+         * @return the process-wide serialization filter or {@code null} if not configured
+         */
+        public static ObjectInputFilter getSerialFilter() {
+            synchronized (serialFilterLock) {
+                return serialFilter;
+            }
+        }
+
+        /**
+         * Set the process-wide filter if it has not already been configured or set.
+         *
+         * @param filter the serialization filter to set as the process-wide filter; not null
+         * @throws SecurityException if there is security manager and the
+         *       {@code SerializablePermission("serialFilter")} is not granted
+         * @throws IllegalStateException if the filter has already been set {@code non-null}
+         */
+        public static void setSerialFilter(ObjectInputFilter filter) {
+            Objects.requireNonNull(filter, "filter");
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPermission(new SerializablePermission("serialFilter"));
+            }
+            synchronized (serialFilterLock) {
+                if (serialFilter != null) {
+                    throw new IllegalStateException("Serial filter can only be set once");
+                }
+                serialFilter = filter;
+            }
+        }
+
+        /**
+         * Returns an ObjectInputFilter from a string of patterns.
+         * <p>
+         * Patterns are separated by ";" (semicolon). Whitespace is significant and
+         * is considered part of the pattern.
+         * If a pattern includes an equals assignment, "{@code =}" it sets a limit.
+         * If a limit appears more than once the last value is used.
+         * <ul>
+         *     <li>maxdepth={@code value} - the maximum depth of a graph</li>
+         *     <li>maxrefs={@code value}  - the maximum number of internal references</li>
+         *     <li>maxbytes={@code value} - the maximum number of bytes in the input stream</li>
+         *     <li>maxarray={@code value} - the maximum array length allowed</li>
+         * </ul>
+         * <p>
+         * Other patterns match or reject class or package name
+         * as returned from {@link Class#getName() Class.getName()}.
+         * Note that for arrays the element type is used in the pattern,
+         * not the array type.
+         * <ul>
+         * <li>If the pattern starts with "!", the class is rejected if the remaining pattern is matched;
+         *     otherwise the class is allowed if the pattern matches.
+         * <li>If the pattern ends with ".**" it matches any class in the package and all subpackages.
+         * <li>If the pattern ends with ".*" it matches any class in the package.
+         * <li>If the pattern ends with "*", it matches any class with the pattern as a prefix.
+         * <li>If the pattern is equal to the class name, it matches.
+         * <li>Otherwise, the pattern is not matched.
+         * </ul>
+         * <p>
+         * The resulting filter performs the limit checks and then
+         * tries to match the class, if any. If any of the limits are exceeded,
+         * the filter returns {@link Status#REJECTED Status.REJECTED}.
+         * If the class is an array type, the class to be matched is the element type.
+         * Arrays of any number of dimensions are treated the same as the element type.
+         * For example, a pattern of "{@code !example.Foo}",
+         * rejects creation of any instance or array of {@code example.Foo}.
+         * The first pattern that matches, working from left to right, determines
+         * the {@link Status#ALLOWED Status.ALLOWED}
+         * or {@link Status#REJECTED Status.REJECTED} result.
+         * If nothing matches, the result is {@link Status#UNDECIDED Status.UNDECIDED}.
+         *
+         * @param pattern the pattern string to parse; not null
+         * @return a filter to check a class being deserialized; may be null;
+         *          {@code null} if no patterns
+         * @throws IllegalArgumentException
+         *                if a limit is missing the name, or the long value
+         *                is not a number or is negative,
+         *                or if the package is missing for ".*" and ".**"
+         */
+        public static ObjectInputFilter createFilter(String pattern) {
+            Objects.requireNonNull(pattern, "pattern");
+            return Global.createFilter(pattern);
+        }
+
+        /**
+         * Implementation of ObjectInputFilter that performs the checks of
+         * the process-wide serialization filter. If configured, it will be
+         * used for all ObjectInputStreams that do not set their own filters.
+         *
+         */
+        final static class Global implements ObjectInputFilter {
+            /**
+             * The pattern used to create the filter.
+             */
+            private final String pattern;
+            /**
+             * The list of class filters.
+             */
+            private final List<Function<Class<?>, Status>> filters;
+            /**
+             * Maximum allowed bytes in the stream.
+             */
+            private long maxStreamBytes;
+            /**
+             * Maximum depth of the graph allowed.
+             */
+            private long maxDepth;
+            /**
+             * Maximum number of references in a graph.
+             */
+            private long maxReferences;
+            /**
+             * Maximum length of any array.
+             */
+            private long maxArrayLength;
+
+            /**
+             * Returns an ObjectInputFilter from a string of patterns.
+             *
+             * @param pattern the pattern string to parse
+             * @return a filter to check a class being deserialized; not null
+             * @throws IllegalArgumentException if the parameter is malformed
+             *                if the pattern is missing the name, the long value
+             *                is not a number or is negative.
+             */
+            static ObjectInputFilter createFilter(String pattern) {
+                Global filter = new Global(pattern);
+                return filter.isEmpty() ? null : filter;
+            }
+
+            /**
+             * Construct a new filter from the pattern String.
+             *
+             * @param pattern a pattern string of filters
+             * @throws IllegalArgumentException if the pattern is malformed
+             */
+            private Global(String pattern) {
+                this.pattern = pattern;
+
+                maxArrayLength = Long.MAX_VALUE; // Default values are unlimited
+                maxDepth = Long.MAX_VALUE;
+                maxReferences = Long.MAX_VALUE;
+                maxStreamBytes = Long.MAX_VALUE;
+
+                String[] patterns = pattern.split(";");
+                filters = new ArrayList<>(patterns.length);
+                for (int i = 0; i < patterns.length; i++) {
+                    String p = patterns[i];
+                    int nameLen = p.length();
+                    if (nameLen == 0) {
+                        continue;
+                    }
+                    if (parseLimit(p)) {
+                        // If the pattern contained a limit setting, i.e. type=value
+                        continue;
+                    }
+                    boolean negate = p.charAt(0) == '!';
+
+                    if (p.indexOf('/') >= 0) {
+                        throw new IllegalArgumentException("invalid character \"/\" in: \"" + pattern + "\"");
+                    }
+
+                    if (p.endsWith("*")) {
+                        // Wildcard cases
+                        if (p.endsWith(".*")) {
+                            // Pattern is a package name with a wildcard
+                            final String pkg = p.substring(negate ? 1 : 0, nameLen - 1);
+                            if (pkg.length() < 2) {
+                                throw new IllegalArgumentException("package missing in: \"" + pattern + "\"");
+                            }
+                            if (negate) {
+                                // A Function that fails if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> matchesPackage(c, pkg) ? Status.REJECTED : Status.UNDECIDED);
+                            } else {
+                                // A Function that succeeds if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> matchesPackage(c, pkg) ? Status.ALLOWED : Status.UNDECIDED);
+                            }
+                        } else if (p.endsWith(".**")) {
+                            // Pattern is a package prefix with a double wildcard
+                            final String pkgs = p.substring(negate ? 1 : 0, nameLen - 2);
+                            if (pkgs.length() < 2) {
+                                throw new IllegalArgumentException("package missing in: \"" + pattern + "\"");
+                            }
+                            if (negate) {
+                                // A Function that fails if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> c.getName().startsWith(pkgs) ? Status.REJECTED : Status.UNDECIDED);
+                            } else {
+                                // A Function that succeeds if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> c.getName().startsWith(pkgs) ? Status.ALLOWED : Status.UNDECIDED);
+                            }
+                        } else {
+                            // Pattern is a classname (possibly empty) with a trailing wildcard
+                            final String className = p.substring(negate ? 1 : 0, nameLen - 1);
+                            if (negate) {
+                                // A Function that fails if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> c.getName().startsWith(className) ? Status.REJECTED : Status.UNDECIDED);
+                            } else {
+                                // A Function that succeeds if the class starts with the pattern, otherwise don't care
+                                filters.add(c -> c.getName().startsWith(className) ? Status.ALLOWED : Status.UNDECIDED);
+                            }
+                        }
+                    } else {
+                        final String name = p.substring(negate ? 1 : 0);
+                        if (name.isEmpty()) {
+                            throw new IllegalArgumentException("class or package missing in: \"" + pattern + "\"");
+                        }
+                        // Pattern is a class name
+                        if (negate) {
+                            // A Function that fails if the class equals the pattern, otherwise don't care
+                            filters.add(c -> c.getName().equals(name) ? Status.REJECTED : Status.UNDECIDED);
+                        } else {
+                            // A Function that succeeds if the class equals the pattern, otherwise don't care
+                            filters.add(c -> c.getName().equals(name) ? Status.ALLOWED : Status.UNDECIDED);
+                        }
+
+                    }
+                }
+            }
+
+            /**
+             * Returns if this filter has any checks.
+             * @return {@code true} if the filter has any checks, {@code false} otherwise
+             */
+            private boolean isEmpty() {
+                return filters.isEmpty() &&
+                        maxArrayLength == Long.MAX_VALUE &&
+                        maxDepth == Long.MAX_VALUE &&
+                        maxReferences == Long.MAX_VALUE &&
+                        maxStreamBytes == Long.MAX_VALUE;
+            }
+
+            /**
+             * Parse out a limit for one of maxarray, maxdepth, maxbytes, maxreferences.
+             *
+             * @param pattern a string with a type name, '=' and a value
+             * @return {@code true} if a limit was parsed, else {@code false}
+             * @throws IllegalArgumentException if the pattern is missing
+             *                the name, the Long value is not a number or is negative.
+             */
+            private boolean parseLimit(String pattern) {
+                int eqNdx = pattern.indexOf('=');
+                if (eqNdx < 0) {
+                    // not a limit pattern
+                    return false;
+                }
+                String valueString = pattern.substring(eqNdx + 1);
+                if (pattern.startsWith("maxdepth=")) {
+                    maxDepth = parseValue(valueString);
+                } else if (pattern.startsWith("maxarray=")) {
+                    maxArrayLength = parseValue(valueString);
+                } else if (pattern.startsWith("maxrefs=")) {
+                    maxReferences = parseValue(valueString);
+                } else if (pattern.startsWith("maxbytes=")) {
+                    maxStreamBytes = parseValue(valueString);
+                } else {
+                    throw new IllegalArgumentException("unknown limit: " + pattern.substring(0, eqNdx));
+                }
+                return true;
+            }
+
+            /**
+             * Parse the value of a limit and check that it is non-negative.
+             * @param string inputstring
+             * @return the parsed value
+             * @throws IllegalArgumentException if parsing the value fails or the value is negative
+             */
+            private static long parseValue(String string) throws IllegalArgumentException {
+                // Parse a Long from after the '=' to the end
+                long value = Long.parseLong(string);
+                if (value < 0) {
+                    throw new IllegalArgumentException("negative limit: " + string);
+                }
+                return value;
+            }
+
+            /**
+             * {@inheritDoc}
+             */
+            @Override
+            public Status checkInput(FilterInfo filterInfo) {
+                if (filterInfo.references() < 0
+                        || filterInfo.depth() < 0
+                        || filterInfo.streamBytes() < 0
+                        || filterInfo.references() > maxReferences
+                        || filterInfo.depth() > maxDepth
+                        || filterInfo.streamBytes() > maxStreamBytes) {
+                    return Status.REJECTED;
+                }
+
+                Class<?> clazz = filterInfo.serialClass();
+                if (clazz != null) {
+                    if (clazz.isArray()) {
+                        if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > maxArrayLength) {
+                            // array length is too big
+                            return Status.REJECTED;
+                        }
+                        do {
+                            // Arrays are decided based on the component type
+                            clazz = clazz.getComponentType();
+                        } while (clazz.isArray());
+                    }
+
+                    if (clazz.isPrimitive())  {
+                        // Primitive types are undecided; let someone else decide
+                        return Status.UNDECIDED;
+                    } else {
+                        // Find any filter that allowed or rejected the class
+                        final Class<?> cl = clazz;
+                        Optional<Status> status = filters.stream()
+                                .map(f -> f.apply(cl))
+                                .filter(p -> p != Status.UNDECIDED)
+                                .findFirst();
+                        return status.orElse(Status.UNDECIDED);
+                    }
+                }
+                return Status.UNDECIDED;
+            }
+
+            /**
+             * Returns {@code true} if the class is in the package.
+             *
+             * @param c   a class
+             * @param pkg a package name (including the trailing ".")
+             * @return {@code true} if the class is in the package,
+             * otherwise {@code false}
+             */
+            private static boolean matchesPackage(Class<?> c, String pkg) {
+                String n = c.getName();
+                return n.startsWith(pkg) && n.lastIndexOf('.') == pkg.length() - 1;
+            }
+
+            /**
+             * Returns the pattern used to create this filter.
+             * @return the pattern used to create this filter
+             */
+            @Override
+            public String toString() {
+                return pattern;
+            }
+        }
+    }
+}
diff --git a/jdk/src/share/classes/sun/misc/SharedSecrets.java b/jdk/src/share/classes/sun/misc/SharedSecrets.java
index 2f995da..3539962 100644
--- a/jdk/src/share/classes/sun/misc/SharedSecrets.java
+++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java
@@ -25,6 +25,7 @@
 
 package sun.misc;
 
+import java.io.ObjectInputStream;
 import java.util.jar.JarFile;
 import java.io.Console;
 import java.io.FileDescriptor;
@@ -56,6 +57,7 @@
     private static JavaSecurityAccess javaSecurityAccess;
     private static JavaUtilZipFileAccess javaUtilZipFileAccess;
     private static JavaAWTAccess javaAWTAccess;
+    private static JavaOISAccess javaOISAccess;
     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
@@ -141,6 +143,18 @@
         return javaIOFileDescriptorAccess;
     }
 
+    public static void setJavaOISAccess(JavaOISAccess access) {
+        javaOISAccess = access;
+    }
+
+    public static JavaOISAccess getJavaOISAccess() {
+        if (javaOISAccess == null)
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+
+        return javaOISAccess;
+    }
+
+
     public static void setJavaSecurityProtectionDomainAccess
         (JavaSecurityProtectionDomainAccess jspda) {
             javaSecurityProtectionDomainAccess = jspda;
diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java
index f92b1de..5f56056 100644
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
 import java.net.URLStreamHandler;
 import java.net.URLStreamHandlerFactory;
 import java.io.*;
+import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.AccessControlException;
 import java.security.CodeSigner;
@@ -67,6 +68,7 @@
     private static final boolean DEBUG;
     private static final boolean DEBUG_LOOKUP_CACHE;
     private static final boolean DISABLE_JAR_CHECKING;
+    private static final boolean DISABLE_ACC_CHECKING;
 
     static {
         JAVA_VERSION = java.security.AccessController.doPrivileged(
@@ -78,6 +80,10 @@
         String p = java.security.AccessController.doPrivileged(
             new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
         DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+        p = AccessController.doPrivileged(
+            new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions"));
+        DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
     }
 
     /* The original search path of URLs. */
@@ -98,6 +104,11 @@
     /* Whether this URLClassLoader has been closed yet */
     private boolean closed = false;
 
+    /* The context to be used when loading classes and resources.  If non-null
+     * this is the context that was captured during the creation of the
+     * URLClassLoader. null implies no additional security restrictions. */
+    private final AccessControlContext acc;
+
     /**
      * Creates a new URLClassPath for the given URLs. The URLs will be
      * searched in the order specified for classes and resources. A URL
@@ -107,8 +118,12 @@
      * @param urls the directory and JAR file URLs to search for classes
      *        and resources
      * @param factory the URLStreamHandlerFactory to use when creating new URLs
+     * @param acc the context to be used when loading classes and resources, may
+     *            be null
      */
-    public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+    public URLClassPath(URL[] urls,
+                        URLStreamHandlerFactory factory,
+                        AccessControlContext acc) {
         for (int i = 0; i < urls.length; i++) {
             path.add(urls[i]);
         }
@@ -116,10 +131,22 @@
         if (factory != null) {
             jarHandler = factory.createURLStreamHandler("jar");
         }
+        if (DISABLE_ACC_CHECKING)
+            this.acc = null;
+        else
+            this.acc = acc;
     }
 
+    /**
+     * Constructs a URLClassPath with no additional security restrictions.
+     * Used by code that implements the class path.
+     */
     public URLClassPath(URL[] urls) {
-        this(urls, null);
+        this(urls, null, null);
+    }
+
+    public URLClassPath(URL[] urls, AccessControlContext acc) {
+        this(urls, null, acc);
     }
 
     public synchronized List<IOException> closeLoaders() {
@@ -499,6 +526,14 @@
             } catch (IOException e) {
                 // Silently ignore for now...
                 continue;
+            } catch (SecurityException se) {
+                // Always silently ignore. The context, if there is one, that
+                // this URLClassPath was given during construction will never
+                // have permission to access the URL.
+                if (DEBUG) {
+                    System.err.println("Failed to access " + url + ", " + se );
+                }
+                continue;
             }
             // Finally, add the Loader to the search path.
             validateLookupCache(loaders.size(), urlNoFragString);
@@ -527,10 +562,10 @@
                             return new Loader(url);
                         }
                     } else {
-                        return new JarLoader(url, jarHandler, lmap);
+                        return new JarLoader(url, jarHandler, lmap, acc);
                     }
                 }
-            });
+            }, acc);
         } catch (java.security.PrivilegedActionException pae) {
             throw (IOException)pae.getException();
         }
@@ -755,11 +790,12 @@
      */
     static class JarLoader extends Loader {
         private JarFile jar;
-        private URL csu;
+        private final URL csu;
         private JarIndex index;
         private MetaIndex metaIndex;
         private URLStreamHandler handler;
-        private HashMap<String, Loader> lmap;
+        private final HashMap<String, Loader> lmap;
+        private final AccessControlContext acc;
         private boolean closed = false;
         private static final sun.misc.JavaUtilZipFileAccess zipAccess =
                 sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
@@ -769,13 +805,15 @@
          * a JAR file.
          */
         JarLoader(URL url, URLStreamHandler jarHandler,
-                  HashMap<String, Loader> loaderMap)
+                  HashMap<String, Loader> loaderMap,
+                  AccessControlContext acc)
             throws IOException
         {
             super(new URL("jar", "", -1, url + "!/", jarHandler));
             csu = url;
             handler = jarHandler;
             lmap = loaderMap;
+            this.acc = acc;
 
             if (!isOptimizable(url)) {
                 ensureOpen();
@@ -859,8 +897,7 @@
                                 }
                                 return null;
                             }
-                        }
-                    );
+                        }, acc);
                 } catch (java.security.PrivilegedActionException pae) {
                     throw (IOException)pae.getException();
                 }
@@ -1054,9 +1091,9 @@
                                 new PrivilegedExceptionAction<JarLoader>() {
                                     public JarLoader run() throws IOException {
                                         return new JarLoader(url, handler,
-                                            lmap);
+                                            lmap, acc);
                                     }
-                                });
+                                }, acc);
 
                             /* this newly opened jar file has its own index,
                              * merge it into the parent's index, taking into
diff --git a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
index dc26fab..95408bd 100644
--- a/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
+++ b/jdk/src/share/classes/sun/reflect/ReflectionFactory.java
@@ -25,16 +25,28 @@
 
 package sun.reflect;
 
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.Permission;
 import java.security.PrivilegedAction;
+import java.util.Objects;
+
 import sun.reflect.misc.ReflectUtil;
 
+
 /** <P> The master factory for all reflective objects, both those in
     java.lang.reflect (Fields, Methods, Constructors) as well as their
     delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
@@ -56,6 +68,9 @@
     // Provides access to package-private mechanisms in java.lang.reflect
     private static volatile LangReflectAccess langReflectAccess;
 
+    /* Method for static class initializer <clinit>, or null */
+    private static volatile Method hasStaticInitializerMethod;
+
     //
     // "Inflation" mechanism. Loading bytecodes to implement
     // Method.invoke() and Constructor.newInstance() currently costs
@@ -73,8 +88,7 @@
     private static boolean noInflation        = false;
     private static int     inflationThreshold = 15;
 
-    private ReflectionFactory() {
-    }
+    private ReflectionFactory() {}
 
     /**
      * A convenience class for acquiring the capability to instantiate
@@ -328,6 +342,14 @@
     //
     //
 
+    /**
+     * Returns an accessible constructor capable of creating instances
+     * of the given class, initialized by the given constructor.
+     *
+     * @param classToInstantiate the class to instantiate
+     * @param constructorToCall the constructor to call
+     * @return an accessible constructor
+     */
     public Constructor<?> newConstructorForSerialization
         (Class<?> classToInstantiate, Constructor<?> constructorToCall)
     {
@@ -335,6 +357,42 @@
         if (constructorToCall.getDeclaringClass() == classToInstantiate) {
             return constructorToCall;
         }
+        return generateConstructor(classToInstantiate, constructorToCall);
+    }
+
+    /**
+     * Returns an accessible no-arg constructor for a class.
+     * The no-arg constructor is found searching the class and its supertypes.
+     *
+     * @param cl the class to instantiate
+     * @return a no-arg constructor for the class or {@code null} if
+     *     the class or supertypes do not have a suitable no-arg constructor
+     */
+    public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
+        Class<?> initCl = cl;
+        while (Serializable.class.isAssignableFrom(initCl)) {
+            if ((initCl = initCl.getSuperclass()) == null) {
+                return null;
+            }
+        }
+        Constructor<?> constructorToCall;
+        try {
+            constructorToCall = initCl.getDeclaredConstructor();
+            int mods = constructorToCall.getModifiers();
+            if ((mods & Modifier.PRIVATE) != 0 ||
+                    ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
+                            !packageEquals(cl, initCl))) {
+                return null;
+            }
+        } catch (NoSuchMethodException ex) {
+            return null;
+        }
+        return generateConstructor(cl, constructorToCall);
+    }
+
+    private final Constructor<?> generateConstructor(Class<?> classToInstantiate,
+                                                     Constructor<?> constructorToCall) {
+
 
         ConstructorAccessor acc = new MethodAccessorGenerator().
             generateSerializationConstructor(classToInstantiate,
@@ -355,9 +413,222 @@
                                           langReflectAccess().
                                           getConstructorParameterAnnotations(constructorToCall));
         setConstructorAccessor(c, acc);
+        c.setAccessible(true);
         return c;
     }
 
+    /**
+     * Returns an accessible no-arg constructor for an externalizable class to be
+     * initialized using a public no-argument constructor.
+     *
+     * @param cl the class to instantiate
+     * @return A no-arg constructor for the class; returns {@code null} if
+     *     the class does not implement {@link java.io.Externalizable}
+     */
+    public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+        if (!Externalizable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+        try {
+            Constructor<?> cons = cl.getConstructor();
+            cons.setAccessible(true);
+            return cons;
+        } catch (NoSuchMethodException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readObject} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectInputStream} passed to
+     * {@code readObject}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code readObject} method of the class or
+     *          {@code null} if the class does not have a {@code readObject} method
+     */
+    public final MethodHandle readObjectForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readObjectNoData} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectInputStream} passed to
+     * {@code readObjectNoData}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code readObjectNoData} method
+     *          of the class or {@code null} if the class does not have a
+     *          {@code readObjectNoData} method
+     */
+    public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code writeObject} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectOutputStream} passed to
+     * {@code writeObject}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code writeObject} method of the class or
+     *          {@code null} if the class does not have a {@code writeObject} method
+     */
+    public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
+    }
+
+    private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
+                                                                   String methodName,
+                                                                   Class<?> streamClass) {
+        if (!Serializable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+
+        try {
+            Method meth = cl.getDeclaredMethod(methodName, streamClass);
+            int mods = meth.getModifiers();
+            if (meth.getReturnType() != Void.TYPE ||
+                    Modifier.isStatic(mods) ||
+                    !Modifier.isPrivate(mods)) {
+                return null;
+            }
+            meth.setAccessible(true);
+            return MethodHandles.lookup().unreflect(meth);
+        } catch (NoSuchMethodException ex) {
+            return null;
+        } catch (IllegalAccessException ex1) {
+            throw new InternalError("Error", ex1);
+        }
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readResolve} method on
+     * a serializable class.
+     * The single argument of {@link MethodHandle#invoke} is the serializable
+     * object.
+     *
+     * @param cl the Serializable class
+     * @return  a direct MethodHandle for the {@code readResolve} method of the class or
+     *          {@code null} if the class does not have a {@code readResolve} method
+     */
+    public final MethodHandle readResolveForSerialization(Class<?> cl) {
+        return getReplaceResolveForSerialization(cl, "readResolve");
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code writeReplace} method on
+     * a serializable class.
+     * The single argument of {@link MethodHandle#invoke} is the serializable
+     * object.
+     *
+     * @param cl the Serializable class
+     * @return  a direct MethodHandle for the {@code writeReplace} method of the class or
+     *          {@code null} if the class does not have a {@code writeReplace} method
+     */
+    public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+        return getReplaceResolveForSerialization(cl, "writeReplace");
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code writeReplace} method on
+     * a serializable class.
+     * The single argument of {@link MethodHandle#invoke} is the serializable
+     * object.
+     *
+     * @param cl the Serializable class
+     * @return  a direct MethodHandle for the {@code writeReplace} method of the class or
+     *          {@code null} if the class does not have a {@code writeReplace} method
+     */
+    private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
+                                                           String methodName) {
+        if (!Serializable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+
+        Class<?> defCl = cl;
+        while (defCl != null) {
+            try {
+                Method m = defCl.getDeclaredMethod(methodName);
+                if (m.getReturnType() != Object.class) {
+                    return null;
+                }
+                int mods = m.getModifiers();
+                if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
+                    return null;
+                } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
+                    // fall through
+                } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
+                    return null;
+                } else if (!packageEquals(cl, defCl)) {
+                    return null;
+                }
+                try {
+                    // Normal return
+                    m.setAccessible(true);
+                    return MethodHandles.lookup().unreflect(m);
+                } catch (IllegalAccessException ex0) {
+                    // setAccessible should prevent IAE
+                    throw new InternalError("Error", ex0);
+                }
+            } catch (NoSuchMethodException ex) {
+                defCl = defCl.getSuperclass();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the class has a static initializer.
+     * The presence of a static initializer is used to compute the serialVersionUID.
+     * @param cl a serializable classLook
+     * @return {@code true} if the class has a static initializer,
+     *          otherwise {@code false}
+     */
+    public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+        Method m = hasStaticInitializerMethod;
+        if (m == null) {
+            try {
+                m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
+                        new Class<?>[]{Class.class});
+                m.setAccessible(true);
+                hasStaticInitializerMethod = m;
+            } catch (NoSuchMethodException ex) {
+                throw new InternalError("No such method hasStaticInitializer on "
+                        + ObjectStreamClass.class, ex);
+            }
+        }
+        try {
+            return (Boolean) m.invoke(null, cl);
+        } catch (InvocationTargetException | IllegalAccessException ex) {
+            throw new InternalError("Exception invoking hasStaticInitializer", ex);
+        }
+    }
+
+    /**
+     * Returns a new OptionalDataException with {@code eof} set to {@code true}
+     * or {@code false}.
+     * @param bool the value of {@code eof} in the created OptionalDataException
+     * @return  a new OptionalDataException
+     */
+    public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+        try {
+            Constructor<OptionalDataException> boolCtor =
+                    OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
+            boolCtor.setAccessible(true);
+            return boolCtor.newInstance(bool);
+        } catch (NoSuchMethodException | InstantiationException|
+                IllegalAccessException|InvocationTargetException ex) {
+            throw new InternalError("unable to create OptionalDataException", ex);
+        }
+    }
+
     //--------------------------------------------------------------------------
     //
     // Internals only below this point
@@ -421,4 +692,17 @@
         }
         return langReflectAccess;
     }
+
+    /**
+     * Returns true if classes are defined in the classloader and same package, false
+     * otherwise.
+     * @param cl1 a class
+     * @param cl2 another class
+     * @returns true if the two classes are in the same classloader and package
+     */
+    private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
+        return cl1.getClassLoader() == cl2.getClassLoader() &&
+                Objects.equals(cl1.getPackage(), cl2.getPackage());
+    }
+
 }
diff --git a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
index f828055..e23379d 100644
--- a/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
+++ b/jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,11 +30,9 @@
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.io.FilePermission;
-import java.io.IOException;
 import java.net.*;
 import java.rmi.*;
 import java.rmi.server.ObjID;
-import java.rmi.server.RemoteServer;
 import java.rmi.server.ServerNotActiveException;
 import java.rmi.registry.Registry;
 import java.rmi.server.RMIClientSocketFactory;
@@ -47,14 +45,18 @@
 import java.security.PrivilegedExceptionAction;
 import java.security.PermissionCollection;
 import java.security.Permissions;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
+import java.security.Security;
 import java.text.MessageFormat;
-import sun.rmi.server.LoaderHandler;
+
+import sun.misc.ObjectInputFilter;
+
+import sun.rmi.runtime.Log;
+import sun.rmi.server.UnicastRef;
 import sun.rmi.server.UnicastServerRef;
 import sun.rmi.server.UnicastServerRef2;
 import sun.rmi.transport.LiveRef;
-import sun.rmi.transport.ObjectTable;
-import sun.rmi.transport.Target;
 
 /**
  * A "registry" exists on every node that allows RMI connections to
@@ -86,6 +88,47 @@
     private static ResourceBundle resources = null;
 
     /**
+     * Property name of the RMI Registry serial filter to augment
+     * the built-in list of allowed types.
+     * Setting the property in the {@code lib/security/java.security} file
+     * will enable the augmented filter.
+     */
+    private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter";
+
+    /** Registry max depth of remote invocations. **/
+    private static int REGISTRY_MAX_DEPTH = 5;
+
+    /** Registry maximum array size in remote invocations. **/
+    private static int REGISTRY_MAX_ARRAY_SIZE = 10000;
+
+    /**
+     * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"}
+     * property.
+     */
+    private static final ObjectInputFilter registryFilter =
+            AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter);
+
+    /**
+     * Initialize the registryFilter from the security properties or system property; if any
+     * @return an ObjectInputFilter, or null
+     */
+    private static ObjectInputFilter initRegistryFilter() {
+        ObjectInputFilter filter = null;
+        String props = System.getProperty(REGISTRY_FILTER_PROPNAME);
+        if (props == null) {
+            props = Security.getProperty(REGISTRY_FILTER_PROPNAME);
+        }
+        if (props != null) {
+            filter = ObjectInputFilter.Config.createFilter(props);
+            Log regLog = Log.getLog("sun.rmi.registry", "registry", -1);
+            if (regLog.isLoggable(Log.BRIEF)) {
+                regLog.log(Log.BRIEF, "registryFilter = " + filter);
+            }
+        }
+        return filter;
+    }
+
+    /**
      * Construct a new RegistryImpl on the specified port with the
      * given custom socket factory pair.
      */
@@ -100,7 +143,7 @@
                 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                     public Void run() throws RemoteException {
                         LiveRef lref = new LiveRef(id, port, csf, ssf);
-                        setup(new UnicastServerRef2(lref));
+                        setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
                         return null;
                     }
                 }, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -109,7 +152,7 @@
             }
         } else {
             LiveRef lref = new LiveRef(id, port, csf, ssf);
-            setup(new UnicastServerRef2(lref));
+            setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter));
         }
     }
 
@@ -125,7 +168,7 @@
                 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                     public Void run() throws RemoteException {
                         LiveRef lref = new LiveRef(id, port);
-                        setup(new UnicastServerRef(lref));
+                        setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
                         return null;
                     }
                 }, null, new SocketPermission("localhost:"+port, "listen,accept"));
@@ -134,7 +177,7 @@
             }
         } else {
             LiveRef lref = new LiveRef(id, port);
-            setup(new UnicastServerRef(lref));
+            setup(new UnicastServerRef(lref, RegistryImpl::registryFilter));
         }
     }
 
@@ -155,7 +198,7 @@
     /**
      * Returns the remote object for specified name in the registry.
      * @exception RemoteException If remote operation failed.
-     * @exception NotBound If name is not currently bound.
+     * @exception NotBoundException If name is not currently bound.
      */
     public Remote lookup(String name)
         throws RemoteException, NotBoundException
@@ -188,7 +231,7 @@
     /**
      * Unbind the name.
      * @exception RemoteException If remote operation failed.
-     * @exception NotBound If name is not currently bound.
+     * @exception NotBoundException If name is not currently bound.
      */
     public void unbind(String name)
         throws RemoteException, NotBoundException, AccessException
@@ -333,6 +376,60 @@
     }
 
     /**
+     * ObjectInputFilter to filter Registry input objects.
+     * The list of acceptable classes is limited to classes normally
+     * stored in a registry.
+     *
+     * @param filterInfo access to the class, array length, etc.
+     * @return  {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+     *          {@link ObjectInputFilter.Status#REJECTED} if rejected,
+     *          otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+     */
+    private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) {
+        if (registryFilter != null) {
+            ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo);
+            if (status != ObjectInputFilter.Status.UNDECIDED) {
+                // The Registry filter can override the built-in white-list
+                return status;
+            }
+        }
+
+        if (filterInfo.depth() > REGISTRY_MAX_DEPTH) {
+            return ObjectInputFilter.Status.REJECTED;
+        }
+        Class<?> clazz = filterInfo.serialClass();
+        if (clazz != null) {
+            if (clazz.isArray()) {
+                if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) {
+                    return ObjectInputFilter.Status.REJECTED;
+                }
+                do {
+                    // Arrays are allowed depending on the component type
+                    clazz = clazz.getComponentType();
+                } while (clazz.isArray());
+            }
+            if (clazz.isPrimitive()) {
+                // Arrays of primitives are allowed
+                return ObjectInputFilter.Status.ALLOWED;
+            }
+            if (String.class == clazz
+                    || java.lang.Number.class.isAssignableFrom(clazz)
+                    || Remote.class.isAssignableFrom(clazz)
+                    || java.lang.reflect.Proxy.class.isAssignableFrom(clazz)
+                    || UnicastRef.class.isAssignableFrom(clazz)
+                    || RMIClientSocketFactory.class.isAssignableFrom(clazz)
+                    || RMIServerSocketFactory.class.isAssignableFrom(clazz)
+                    || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz)
+                    || java.rmi.server.UID.class.isAssignableFrom(clazz)) {
+                return ObjectInputFilter.Status.ALLOWED;
+            } else {
+                return ObjectInputFilter.Status.REJECTED;
+            }
+        }
+        return ObjectInputFilter.Status.UNDECIDED;
+    }
+
+    /**
      * Main program to start a registry. <br>
      * The port number can be specified on the command line.
      */
diff --git a/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java b/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
index afb726e..66f9146 100644
--- a/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
+++ b/jdk/src/share/classes/sun/rmi/server/UnicastServerRef.java
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.io.ObjectInput;
+import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
 import java.io.ObjectStreamClass;
 import java.lang.reflect.InvocationTargetException;
@@ -53,8 +54,8 @@
 import java.util.Map;
 import java.util.WeakHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
+import sun.misc.ObjectInputFilter;
 import sun.rmi.runtime.Log;
-import static sun.rmi.server.UnicastRef.marshalValue;
 import sun.rmi.transport.LiveRef;
 import sun.rmi.transport.Target;
 import sun.rmi.transport.tcp.TCPTransport;
@@ -64,6 +65,10 @@
  * UnicastServerRef implements the remote reference layer server-side
  * behavior for remote objects exported with the "UnicastRef" reference
  * type.
+ * If an {@link ObjectInputFilter ObjectInputFilter} is supplied it is
+ * invoked during deserialization to filter the arguments,
+ * otherwise the default filter of {@link ObjectInputStream ObjectInputStream}
+ * applies.
  *
  * @author  Ann Wollrath
  * @author  Roger Riggs
@@ -106,6 +111,9 @@
      */
     private transient Skeleton skel;
 
+    // The ObjectInputFilter for checking the invocation arguments
+    private final transient ObjectInputFilter filter;
+
     /** maps method hash to Method object for each remote method */
     private transient Map<Long,Method> hashToMethod_Map = null;
 
@@ -124,16 +132,29 @@
 
     /**
      * Create a new (empty) Unicast server remote reference.
+     * The filter is null to defer to the  default ObjectInputStream filter, if any.
      */
     public UnicastServerRef() {
+        this.filter = null;
     }
 
     /**
      * Construct a Unicast server remote reference for a specified
      * liveRef.
+     * The filter is null to defer to the  default ObjectInputStream filter, if any.
      */
     public UnicastServerRef(LiveRef ref) {
         super(ref);
+        this.filter = null;
+    }
+
+    /**
+     * Construct a Unicast server remote reference for a specified
+     * liveRef and filter.
+     */
+    public UnicastServerRef(LiveRef ref, ObjectInputFilter filter) {
+        super(ref);
+        this.filter = filter;
     }
 
     /**
@@ -142,6 +163,7 @@
      */
     public UnicastServerRef(int port) {
         super(new LiveRef(port));
+        this.filter = null;
     }
 
     /**
@@ -366,9 +388,26 @@
         }
     }
 
+    /**
+     * Sets a filter for invocation arguments, if a filter has been set.
+     * Called by dispatch before the arguments are read.
+     */
     protected void unmarshalCustomCallData(ObjectInput in)
-        throws IOException, ClassNotFoundException
-    {}
+            throws IOException, ClassNotFoundException {
+        if (filter != null &&
+                in instanceof ObjectInputStream) {
+            // Set the filter on the stream
+            ObjectInputStream ois = (ObjectInputStream) in;
+
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                @Override
+                public Void run() {
+                    ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+                    return null;
+                }
+            });
+        }
+    }
 
     /**
      * Handle server-side dispatch using the RMI 1.1 stub/skeleton
diff --git a/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java b/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
index 1eb0805..d6103d7 100644
--- a/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
+++ b/jdk/src/share/classes/sun/rmi/server/UnicastServerRef2.java
@@ -25,12 +25,15 @@
 
 package sun.rmi.server;
 
-import java.io.IOException;
+
 import java.io.ObjectOutput;
-import java.rmi.*;
-import java.rmi.server.*;
-import sun.rmi.transport.*;
-import sun.rmi.transport.tcp.*;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteRef;
+
+import sun.misc.ObjectInputFilter;
+
+import sun.rmi.transport.LiveRef;
 
 /**
  * Server-side ref for a remote impl that uses a custom socket factory.
@@ -59,6 +62,16 @@
     }
 
     /**
+     * Construct a Unicast server remote reference for a specified
+     * liveRef and filter.
+     */
+    public UnicastServerRef2(LiveRef ref,
+                             ObjectInputFilter filter)
+    {
+        super(ref, filter);
+    }
+
+    /**
      * Construct a Unicast server remote reference to be exported
      * on the specified port.
      */
@@ -70,6 +83,18 @@
     }
 
     /**
+     * Construct a Unicast server remote reference to be exported
+     * on the specified port.
+     */
+    public UnicastServerRef2(int port,
+                             RMIClientSocketFactory csf,
+                             RMIServerSocketFactory ssf,
+                             ObjectInputFilter filter)
+    {
+        super(new LiveRef(port, csf, ssf), filter);
+    }
+
+    /**
      * Returns the class of the ref type to be serialized
      */
     public String getRefClass(ObjectOutput out)
diff --git a/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java b/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
index 7cf4bba..af1cf04 100644
--- a/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
+++ b/jdk/src/share/classes/sun/rmi/transport/DGCImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,11 +34,13 @@
 import java.rmi.server.ObjID;
 import java.rmi.server.RemoteServer;
 import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UID;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.Permissions;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
+import java.security.Security;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.HashMap;
@@ -49,6 +51,9 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+
+import sun.misc.ObjectInputFilter;
+
 import sun.rmi.runtime.Log;
 import sun.rmi.runtime.RuntimeUtil;
 import sun.rmi.server.UnicastRef;
@@ -102,6 +107,45 @@
     }
 
     /**
+     * Property name of the DGC serial filter to augment
+     * the built-in list of allowed types.
+     * Setting the property in the {@code lib/security/java.security} file
+     * will enable the augmented filter.
+     */
+    private static final String DGC_FILTER_PROPNAME = "sun.rmi.transport.dgcFilter";
+
+    /** Registry max depth of remote invocations. **/
+    private static int DGC_MAX_DEPTH = 5;
+
+    /** Registry maximum array size in remote invocations. **/
+    private static int DGC_MAX_ARRAY_SIZE = 10000;
+    /**
+     * The dgcFilter created from the value of the {@code  "sun.rmi.transport.dgcFilter"}
+     * property.
+     */
+    private static final ObjectInputFilter dgcFilter =
+            AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)DGCImpl::initDgcFilter);
+
+    /**
+     * Initialize the dgcFilter from the security properties or system property; if any
+     * @return an ObjectInputFilter, or null
+     */
+    private static ObjectInputFilter initDgcFilter() {
+        ObjectInputFilter filter = null;
+        String props = System.getProperty(DGC_FILTER_PROPNAME);
+        if (props == null) {
+            props = Security.getProperty(DGC_FILTER_PROPNAME);
+        }
+        if (props != null) {
+            filter = ObjectInputFilter.Config.createFilter(props);
+            if (dgcLog.isLoggable(Log.BRIEF)) {
+                dgcLog.log(Log.BRIEF, "dgcFilter = " + filter);
+            }
+        }
+        return filter;
+    }
+
+    /**
      * Construct a new server-side remote object collector at
      * a particular port. Disallow construction from outside.
      */
@@ -295,7 +339,8 @@
                         dgc = new DGCImpl();
                         ObjID dgcID = new ObjID(ObjID.DGC_ID);
                         LiveRef ref = new LiveRef(dgcID, 0);
-                        UnicastServerRef disp = new UnicastServerRef(ref);
+                        UnicastServerRef disp = new UnicastServerRef(ref,
+                                DGCImpl::checkInput);
                         Remote stub =
                             Util.createProxy(DGCImpl.class,
                                              new UnicastRef(ref), true);
@@ -326,6 +371,53 @@
         });
     }
 
+    /**
+     * ObjectInputFilter to filter DGC input objects.
+     * The list of acceptable classes is very short and explicit.
+     * The depth and array sizes are limited.
+     *
+     * @param filterInfo access to class, arrayLength, etc.
+     * @return  {@link ObjectInputFilter.Status#ALLOWED} if allowed,
+     *          {@link ObjectInputFilter.Status#REJECTED} if rejected,
+     *          otherwise {@link ObjectInputFilter.Status#UNDECIDED}
+     */
+    private static ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo filterInfo) {
+        if (dgcFilter != null) {
+            ObjectInputFilter.Status status = dgcFilter.checkInput(filterInfo);
+            if (status != ObjectInputFilter.Status.UNDECIDED) {
+                // The DGC filter can override the built-in white-list
+                return status;
+            }
+        }
+
+        if (filterInfo.depth() > DGC_MAX_DEPTH) {
+            return ObjectInputFilter.Status.REJECTED;
+        }
+        Class<?> clazz = filterInfo.serialClass();
+        if (clazz != null) {
+            while (clazz.isArray()) {
+                if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > DGC_MAX_ARRAY_SIZE) {
+                    return ObjectInputFilter.Status.REJECTED;
+                }
+                // Arrays are allowed depending on the component type
+                clazz = clazz.getComponentType();
+            }
+            if (clazz.isPrimitive()) {
+                // Arrays of primitives are allowed
+                return ObjectInputFilter.Status.ALLOWED;
+            }
+            return (clazz == ObjID.class ||
+                    clazz == UID.class ||
+                    clazz == VMID.class ||
+                    clazz == Lease.class)
+                    ? ObjectInputFilter.Status.ALLOWED
+                    : ObjectInputFilter.Status.REJECTED;
+        }
+        // Not a class, not size limited
+        return ObjectInputFilter.Status.UNDECIDED;
+    }
+
+
     private static class LeaseInfo {
         VMID vmid;
         long expiration;
diff --git a/jdk/src/share/classes/sun/security/ec/ECDSASignature.java b/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
index e20120b..2abc262 100644
--- a/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
+++ b/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package sun.security.ec;
 
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.math.BigInteger;
 
@@ -363,13 +364,22 @@
     }
 
     // Convert the DER encoding of R and S into a concatenation of R and S
-    private byte[] decodeSignature(byte[] signature) throws SignatureException {
+    private byte[] decodeSignature(byte[] sig) throws SignatureException {
 
         try {
-            DerInputStream in = new DerInputStream(signature);
+            // Enforce strict DER checking for signatures
+            DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
             DerValue[] values = in.getSequence(2);
+
+            // check number of components in the read sequence
+            // and trailing data
+            if ((values.length != 2) || (in.available() != 0)) {
+                throw new IOException("Invalid encoding for signature");
+            }
+
             BigInteger r = values[0].getPositiveBigInteger();
             BigInteger s = values[1].getPositiveBigInteger();
+
             // trim leading zeroes
             byte[] rBytes = trimZeroes(r.toByteArray());
             byte[] sBytes = trimZeroes(s.toByteArray());
@@ -383,7 +393,7 @@
             return result;
 
         } catch (Exception e) {
-            throw new SignatureException("Could not decode signature", e);
+            throw new SignatureException("Invalid encoding for signature", e);
         }
     }
 
diff --git a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
index d93a09f..78d3f63 100644
--- a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
+++ b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
@@ -498,6 +498,23 @@
         return unauthenticatedAttributes;
     }
 
+    /**
+     * Returns the timestamp PKCS7 data unverified.
+     * @return a PKCS7 object
+     */
+    public PKCS7 getTsToken() throws IOException {
+        if (unauthenticatedAttributes == null) {
+            return null;
+        }
+        PKCS9Attribute tsTokenAttr =
+                unauthenticatedAttributes.getAttribute(
+                        PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+        if (tsTokenAttr == null) {
+            return null;
+        }
+        return new PKCS7((byte[])tsTokenAttr.getValue());
+    }
+
     /*
      * Extracts a timestamp from a PKCS7 SignerInfo.
      *
@@ -525,19 +542,12 @@
         if (timestamp != null || !hasTimestamp)
             return timestamp;
 
-        if (unauthenticatedAttributes == null) {
-            hasTimestamp = false;
-            return null;
-        }
-        PKCS9Attribute tsTokenAttr =
-            unauthenticatedAttributes.getAttribute(
-                PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
-        if (tsTokenAttr == null) {
+        PKCS7 tsToken = getTsToken();
+        if (tsToken == null) {
             hasTimestamp = false;
             return null;
         }
 
-        PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
         // Extract the content (an encoded timestamp token info)
         byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
         // Extract the signer (the Timestamping Authority)
diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
index 1bac22c..0809ee4 100644
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -705,12 +705,21 @@
         }
     }
 
-    private static byte[] asn1ToDSA(byte[] signature) throws SignatureException {
+    private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
         try {
-            DerInputStream in = new DerInputStream(signature);
+            // Enforce strict DER checking for signatures
+            DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
             DerValue[] values = in.getSequence(2);
+
+            // check number of components in the read sequence
+            // and trailing data
+            if ((values.length != 2) || (in.available() != 0)) {
+                throw new IOException("Invalid encoding for signature");
+            }
+
             BigInteger r = values[0].getPositiveBigInteger();
             BigInteger s = values[1].getPositiveBigInteger();
+
             byte[] br = toByteArray(r, 20);
             byte[] bs = toByteArray(s, 20);
             if ((br == null) || (bs == null)) {
@@ -720,16 +729,25 @@
         } catch (SignatureException e) {
             throw e;
         } catch (Exception e) {
-            throw new SignatureException("invalid encoding for signature", e);
+            throw new SignatureException("Invalid encoding for signature", e);
         }
     }
 
-    private byte[] asn1ToECDSA(byte[] signature) throws SignatureException {
+    private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
         try {
-            DerInputStream in = new DerInputStream(signature);
+            // Enforce strict DER checking for signatures
+            DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
             DerValue[] values = in.getSequence(2);
+
+            // check number of components in the read sequence
+            // and trailing data
+            if ((values.length != 2) || (in.available() != 0)) {
+                throw new IOException("Invalid encoding for signature");
+            }
+
             BigInteger r = values[0].getPositiveBigInteger();
             BigInteger s = values[1].getPositiveBigInteger();
+
             // trim leading zeroes
             byte[] br = KeyUtil.trimZeroes(r.toByteArray());
             byte[] bs = KeyUtil.trimZeroes(s.toByteArray());
@@ -740,7 +758,7 @@
             System.arraycopy(bs, 0, res, res.length - bs.length, bs.length);
             return res;
         } catch (Exception e) {
-            throw new SignatureException("invalid encoding for signature", e);
+            throw new SignatureException("Invalid encoding for signature", e);
         }
     }
 
diff --git a/jdk/src/share/classes/sun/security/provider/DSA.java b/jdk/src/share/classes/sun/security/provider/DSA.java
index 071b5b0..3a13e91 100644
--- a/jdk/src/share/classes/sun/security/provider/DSA.java
+++ b/jdk/src/share/classes/sun/security/provider/DSA.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -267,14 +267,20 @@
         BigInteger s = null;
         // first decode the signature.
         try {
-            DerInputStream in = new DerInputStream(signature, offset, length);
+            // Enforce strict DER checking for signatures
+            DerInputStream in =
+                new DerInputStream(signature, offset, length, false);
             DerValue[] values = in.getSequence(2);
 
+            // check number of components in the read sequence
+            // and trailing data
+            if ((values.length != 2) || (in.available() != 0)) {
+                throw new IOException("Invalid encoding for signature");
+            }
             r = values[0].getBigInteger();
             s = values[1].getBigInteger();
-
         } catch (IOException e) {
-            throw new SignatureException("invalid encoding for signature");
+            throw new SignatureException("Invalid encoding for signature", e);
         }
 
         // some implementations do not correctly encode values in the ASN.1
@@ -366,13 +372,49 @@
         return t5.mod(q);
     }
 
-    // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1.
     protected BigInteger generateK(BigInteger q) {
+        // Implementation defined in FIPS 186-4 AppendixB.2.1.
         SecureRandom random = getSigningRandom();
         byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];
 
         random.nextBytes(kValue);
-        return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+        BigInteger k = new BigInteger(1, kValue).mod(
+                q.subtract(BigInteger.ONE)).add(BigInteger.ONE);
+
+        // Using an equivalent exponent of fixed length (same as q or 1 bit
+        // less than q) to keep the kG timing relatively constant.
+        //
+        // Note that this is an extra step on top of the approach defined in
+        // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K.
+        k = k.add(q).divide(BigInteger.valueOf(2));
+
+        // An alternative implementation based on FIPS 186-4 AppendixB2.2
+        // with fixed-length K.
+        //
+        // Please keep it here as we may need to switch to it in the future.
+        //
+        // SecureRandom random = getSigningRandom();
+        // byte[] kValue = new byte[(q.bitLength() + 7)/8];
+        // BigInteger d = q.subtract(BigInteger.TWO);
+        // BigInteger k;
+        // do {
+        //     random.nextBytes(kValue);
+        //     BigInteger c = new BigInteger(1, kValue);
+        //     if (c.compareTo(d) <= 0) {
+        //         k = c.add(BigInteger.ONE);
+        //         // Using an equivalent exponent of fixed length to keep
+        //         // the g^k timing relatively constant.
+        //         //
+        //         // Note that this is an extra step on top of the approach
+        //         // defined in FIPS 186-4 AppendixB.2.2 so as to make a
+        //         // fixed length K.
+        //         if (k.bitLength() >= q.bitLength()) {
+        //             break;
+        //         }
+        //     }
+        // } while (true);
+
+        return k;
     }
 
     // Use the application-specified SecureRandom Object if provided.
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
index b826101..7303156 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,10 @@
 import java.util.Collections;
 import java.util.Set;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.math.BigInteger;
 import java.security.PublicKey;
 import java.security.KeyFactory;
 import java.security.AlgorithmParameters;
-import java.security.NoSuchAlgorithmException;
 import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
 import java.security.cert.X509CRL;
@@ -48,10 +46,13 @@
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CertPathValidatorException.BasicReason;
 import java.security.cert.PKIXReason;
-import java.io.IOException;
-import java.security.interfaces.*;
-import java.security.spec.*;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
 
+import sun.security.util.AnchorCertificates;
+import sun.security.util.CertConstraintParameters;
+import sun.security.util.Debug;
 import sun.security.util.DisabledAlgorithmConstraints;
 import sun.security.x509.X509CertImpl;
 import sun.security.x509.X509CRLImpl;
@@ -69,6 +70,7 @@
  * @see PKIXParameters
  */
 final public class AlgorithmChecker extends PKIXCertPathChecker {
+    private static final Debug debug = Debug.getInstance("certpath");
 
     private final AlgorithmConstraints constraints;
     private final PublicKey trustedPubKey;
@@ -88,6 +90,14 @@
         certPathDefaultConstraints = new DisabledAlgorithmConstraints(
             DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 
+    // If there is no "cacerts" keyword, then disable anchor checking
+    private static final boolean publicCALimits =
+            certPathDefaultConstraints.checkProperty("jdkCA");
+
+    // If anchor checking enabled, this will be true if the trust anchor
+    // has a match in the cacerts file
+    private boolean trustedMatch = false;
+
     /**
      * Create a new <code>AlgorithmChecker</code> with the algorithm
      * constraints specified in security property
@@ -136,6 +146,11 @@
 
         if (anchor.getTrustedCert() != null) {
             this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+            // Check for anchor certificate restrictions
+            trustedMatch = checkFingerprint(anchor.getTrustedCert());
+            if (trustedMatch && debug != null) {
+                debug.println("trustedMatch = true");
+            }
         } else {
             this.trustedPubKey = anchor.getCAPublicKey();
         }
@@ -144,6 +159,19 @@
         this.constraints = constraints;
     }
 
+    // Check this 'cert' for restrictions in the AnchorCertificates
+    // trusted certificates list
+    private static boolean checkFingerprint(X509Certificate cert) {
+        if (!publicCALimits) {
+            return false;
+        }
+
+        if (debug != null) {
+            debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
+        }
+        return AnchorCertificates.contains(cert);
+    }
+
     @Override
     public void init(boolean forward) throws CertPathValidatorException {
         //  Note that this class does not support forward mode.
@@ -181,36 +209,8 @@
             return;
         }
 
-        X509CertImpl x509Cert = null;
-        try {
-            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
-        } catch (CertificateException ce) {
-            throw new CertPathValidatorException(ce);
-        }
-
-        PublicKey currPubKey = x509Cert.getPublicKey();
-        String currSigAlg = x509Cert.getSigAlgName();
-
-        AlgorithmId algorithmId = null;
-        try {
-            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
-        } catch (CertificateException ce) {
-            throw new CertPathValidatorException(ce);
-        }
-
-        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
-
-        // Check the current signature algorithm
-        if (!constraints.permits(
-                SIGNATURE_PRIMITIVE_SET,
-                currSigAlg, currSigAlgParams)) {
-            throw new CertPathValidatorException(
-                "Algorithm constraints check failed: " + currSigAlg,
-                null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
-        }
-
         // check the key usage and key size
-        boolean[] keyUsage = x509Cert.getKeyUsage();
+        boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
         if (keyUsage != null && keyUsage.length < 9) {
             throw new CertPathValidatorException(
                 "incorrect KeyUsage extension",
@@ -248,28 +248,69 @@
 
             if (primitives.isEmpty()) {
                 throw new CertPathValidatorException(
-                    "incorrect KeyUsage extension",
+                    "incorrect KeyUsage extension bits",
                     null, null, -1, PKIXReason.INVALID_KEY_USAGE);
             }
         }
 
+        PublicKey currPubKey = cert.getPublicKey();
+
+        if (constraints instanceof DisabledAlgorithmConstraints) {
+            // Check against DisabledAlgorithmConstraints certpath constraints.
+            // permits() will throw exception on failure.
+            ((DisabledAlgorithmConstraints)constraints).permits(primitives,
+                new CertConstraintParameters((X509Certificate)cert,
+                        trustedMatch));
+            // If there is no previous key, set one and exit
+            if (prevPubKey == null) {
+                prevPubKey = currPubKey;
+                return;
+            }
+        }
+
+        X509CertImpl x509Cert;
+        AlgorithmId algorithmId;
+        try {
+            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+        String currSigAlg = x509Cert.getSigAlgName();
+
+        // If 'constraints' is not of DisabledAlgorithmConstraints, check all
+        // everything individually
+        if (!(constraints instanceof DisabledAlgorithmConstraints)) {
+            // Check the current signature algorithm
+            if (!constraints.permits(
+                    SIGNATURE_PRIMITIVE_SET,
+                    currSigAlg, currSigAlgParams)) {
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on signature " +
+                                "algorithm: " + currSigAlg, null, null, -1,
+                        BasicReason.ALGORITHM_CONSTRAINED);
+            }
+
         if (!constraints.permits(primitives, currPubKey)) {
             throw new CertPathValidatorException(
-                "algorithm constraints check failed",
+                        "Algorithm constraints check failed on keysize: " +
+                                sun.security.util.KeyUtil.getKeySize(currPubKey),
                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
+        }
 
         // Check with previous cert for signature algorithm and public key
         if (prevPubKey != null) {
-            if (currSigAlg != null) {
                 if (!constraints.permits(
                         SIGNATURE_PRIMITIVE_SET,
                         currSigAlg, prevPubKey, currSigAlgParams)) {
                     throw new CertPathValidatorException(
-                        "Algorithm constraints check failed: " + currSigAlg,
+                    "Algorithm constraints check failed on " +
+                            "signature algorithm: " + currSigAlg,
                         null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
                 }
-            }
 
             // Inherit key parameters from previous key
             if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) {
@@ -282,7 +323,7 @@
                 DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
                 if (params == null) {
                     throw new CertPathValidatorException(
-                                    "Key parameters missing");
+                        "Key parameters missing from public key.");
                 }
 
                 try {
@@ -330,6 +371,11 @@
             // Don't bother to change the trustedPubKey.
             if (anchor.getTrustedCert() != null) {
                 prevPubKey = anchor.getTrustedCert().getPublicKey();
+                // Check for anchor certificate restrictions
+                trustedMatch = checkFingerprint(anchor.getTrustedCert());
+                if (trustedMatch && debug != null) {
+                    debug.println("trustedMatch = true");
+                }
             } else {
                 prevPubKey = anchor.getCAPublicKey();
             }
@@ -370,7 +416,8 @@
         if (!certPathDefaultConstraints.permits(
                 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
             throw new CertPathValidatorException(
-                "algorithm check failed: " + sigAlgName + " is disabled",
+                "Algorithm constraints check failed on signature algorithm: " +
+                sigAlgName + " is disabled",
                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
     }
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
index cfffba8..e85ef2d 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
@@ -131,8 +131,8 @@
 
                 } catch (CertPathValidatorException cpve) {
                     throw new CertPathValidatorException(cpve.getMessage(),
-                        cpve.getCause(), cpOriginal, cpSize - (i + 1),
-                        cpve.getReason());
+                        (cpve.getCause() != null) ? cpve.getCause() : cpve,
+                            cpOriginal, cpSize - (i + 1), cpve.getReason());
                 }
             }
 
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java
new file mode 100644
index 0000000..34b4971
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 sun.security.provider.certpath;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.Timestamp;
+import java.security.cert.CertSelector;
+import java.security.cert.CertStore;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.TrustAnchor;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is a wrapper for PKIXBuilderParameters so that a Timestamp object
+ * can be passed alone when PKIXCertPath is checking signed jar files.
+ */
+
+public class PKIXTimestampParameters extends PKIXBuilderParameters {
+
+    private final PKIXBuilderParameters p;
+    private Timestamp jarTimestamp;
+
+    public PKIXTimestampParameters(PKIXBuilderParameters params,
+            Timestamp timestamp) throws InvalidAlgorithmParameterException {
+        super(params.getTrustAnchors(), null);
+        p = params;
+        jarTimestamp = timestamp;
+    }
+
+    public Timestamp getTimestamp() {
+        return jarTimestamp;
+    }
+    public void setTimestamp(Timestamp t) {
+        jarTimestamp = t;
+    }
+
+    @Override
+    public void setDate(Date d) {
+        p.setDate(d);
+    }
+
+    @Override
+    public void addCertPathChecker(PKIXCertPathChecker c) {
+        p.addCertPathChecker(c);
+    }
+
+    @Override
+    public void setMaxPathLength(int maxPathLength) {
+        p.setMaxPathLength(maxPathLength);
+    }
+
+    @Override
+    public int getMaxPathLength() {
+        return p.getMaxPathLength();
+    }
+
+    @Override
+    public String toString() {
+        return p.toString();
+    }
+
+    @Override
+    public Set<TrustAnchor> getTrustAnchors() {
+        return p.getTrustAnchors();
+    }
+
+    @Override
+    public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
+            throws InvalidAlgorithmParameterException {
+        // To avoid problems with PKIXBuilderParameter's constructors
+        if (p == null) {
+            return;
+        }
+        p.setTrustAnchors(trustAnchors);
+    }
+
+    @Override
+    public Set<String> getInitialPolicies() {
+        return p.getInitialPolicies();
+    }
+
+    @Override
+    public void setInitialPolicies(Set<String> initialPolicies) {
+        p.setInitialPolicies(initialPolicies);
+    }
+
+    @Override
+    public void setCertStores(List<CertStore> stores) {
+        p.setCertStores(stores);
+    }
+
+    @Override
+    public void addCertStore(CertStore store) {
+        p.addCertStore(store);
+    }
+
+    @Override
+    public List<CertStore> getCertStores() {
+        return p.getCertStores();
+    }
+
+    @Override
+    public void setRevocationEnabled(boolean val) {
+        p.setRevocationEnabled(val);
+    }
+
+    @Override
+    public boolean isRevocationEnabled() {
+        return p.isRevocationEnabled();
+    }
+
+    @Override
+    public void setExplicitPolicyRequired(boolean val) {
+        p.setExplicitPolicyRequired(val);
+    }
+
+    @Override
+    public boolean isExplicitPolicyRequired() {
+        return p.isExplicitPolicyRequired();
+    }
+
+    @Override
+    public void setPolicyMappingInhibited(boolean val) {
+        p.setPolicyMappingInhibited(val);
+    }
+
+    @Override
+    public boolean isPolicyMappingInhibited() {
+        return p.isPolicyMappingInhibited();
+    }
+
+    @Override
+    public void setAnyPolicyInhibited(boolean val) {
+        p.setAnyPolicyInhibited(val);
+    }
+
+    @Override
+    public boolean isAnyPolicyInhibited() {
+        return p.isAnyPolicyInhibited();
+    }
+
+    @Override
+    public void setPolicyQualifiersRejected(boolean qualifiersRejected) {
+        p.setPolicyQualifiersRejected(qualifiersRejected);
+    }
+
+    @Override
+    public boolean getPolicyQualifiersRejected() {
+        return p.getPolicyQualifiersRejected();
+    }
+
+    @Override
+    public Date getDate() {
+        return p.getDate();
+    }
+
+    @Override
+    public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
+        p.setCertPathCheckers(checkers);
+    }
+
+    @Override
+    public List<PKIXCertPathChecker> getCertPathCheckers() {
+        return p.getCertPathCheckers();
+    }
+
+    @Override
+    public String getSigProvider() {
+        return p.getSigProvider();
+    }
+
+    @Override
+    public void setSigProvider(String sigProvider) {
+        p.setSigProvider(sigProvider);
+    }
+
+    @Override
+    public CertSelector getTargetCertConstraints() {
+        return p.getTargetCertConstraints();
+    }
+
+    @Override
+    public void setTargetCertConstraints(CertSelector selector) {
+        // To avoid problems with PKIXBuilderParameter's constructors
+        if (p == null) {
+            return;
+        }
+        p.setTargetCertConstraints(selector);
+    }
+
+}
diff --git a/jdk/src/share/classes/sun/security/rsa/RSASignature.java b/jdk/src/share/classes/sun/security/rsa/RSASignature.java
index f1572f7..379d401 100644
--- a/jdk/src/share/classes/sun/security/rsa/RSASignature.java
+++ b/jdk/src/share/classes/sun/security/rsa/RSASignature.java
@@ -223,9 +223,10 @@
      * Decode the signature data. Verify that the object identifier matches
      * and return the message digest.
      */
-    public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature)
+    public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig)
             throws IOException {
-        DerInputStream in = new DerInputStream(signature);
+        // Enforce strict DER checking for signatures
+        DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
         DerValue[] values = in.getSequence(2);
         if ((values.length != 2) || (in.available() != 0)) {
             throw new IOException("SEQUENCE length error");
diff --git a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
index 677a7e1..687eaee 100644
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -326,36 +326,38 @@
     static enum KeyExchange {
 
         // key exchange algorithms
-        K_NULL       ("NULL",       false),
-        K_RSA        ("RSA",        true),
-        K_RSA_EXPORT ("RSA_EXPORT", true),
-        K_DH_RSA     ("DH_RSA",     false),
-        K_DH_DSS     ("DH_DSS",     false),
-        K_DHE_DSS    ("DHE_DSS",    true),
-        K_DHE_RSA    ("DHE_RSA",    true),
-        K_DH_ANON    ("DH_anon",    true),
+        K_NULL       ("NULL",       false,      false),
+        K_RSA        ("RSA",        true,       false),
+        K_RSA_EXPORT ("RSA_EXPORT", true,       false),
+        K_DH_RSA     ("DH_RSA",     false,      false),
+        K_DH_DSS     ("DH_DSS",     false,      false),
+        K_DHE_DSS    ("DHE_DSS",    true,       false),
+        K_DHE_RSA    ("DHE_RSA",    true,       false),
+        K_DH_ANON    ("DH_anon",    true,       false),
 
-        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC),
-        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC),
-        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC),
-        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC),
-        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC),
+        K_ECDH_ECDSA ("ECDH_ECDSA",  ALLOW_ECC, true),
+        K_ECDH_RSA   ("ECDH_RSA",    ALLOW_ECC, true),
+        K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true),
+        K_ECDHE_RSA  ("ECDHE_RSA",   ALLOW_ECC, true),
+        K_ECDH_ANON  ("ECDH_anon",   ALLOW_ECC, true),
 
         // Kerberos cipher suites
-        K_KRB5       ("KRB5", true),
-        K_KRB5_EXPORT("KRB5_EXPORT", true),
+        K_KRB5       ("KRB5", true,             false),
+        K_KRB5_EXPORT("KRB5_EXPORT", true,      false),
 
         // renegotiation protection request signaling cipher suite
-        K_SCSV       ("SCSV",        true);
+        K_SCSV       ("SCSV",        true,      false);
 
         // name of the key exchange algorithm, e.g. DHE_DSS
         final String name;
         final boolean allowed;
+        final boolean isEC;
         private final boolean alwaysAvailable;
 
-        KeyExchange(String name, boolean allowed) {
+        KeyExchange(String name, boolean allowed, boolean isEC) {
             this.name = name;
             this.allowed = allowed;
+            this.isEC = isEC;
             this.alwaysAvailable = allowed &&
                 (!name.startsWith("EC")) && (!name.startsWith("KRB"));
         }
@@ -365,7 +367,7 @@
                 return true;
             }
 
-            if (name.startsWith("EC")) {
+            if (isEC) {
                 return (allowed && JsseJce.isEcAvailable());
             } else if (name.startsWith("KRB")) {
                 return (allowed && JsseJce.isKerberosAvailable());
diff --git a/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java b/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
index 491bffa..a114f4a 100644
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,20 +112,15 @@
     boolean containsEC() {
         if (containsEC == null) {
             for (CipherSuite c : cipherSuites) {
-                switch (c.keyExchange) {
-                case K_ECDH_ECDSA:
-                case K_ECDH_RSA:
-                case K_ECDHE_ECDSA:
-                case K_ECDHE_RSA:
-                case K_ECDH_ANON:
+                if (c.keyExchange.isEC) {
                     containsEC = true;
                     return true;
-                default:
-                    break;
                 }
             }
+
             containsEC = false;
         }
+
         return containsEC;
     }
 
diff --git a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
index b16ff81..0d55552 100644
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
@@ -621,8 +621,11 @@
             } else {
                 // we wanted to resume, but the server refused
                 //
-                // Invalidate the session in case of reusing next time.
-                session.invalidate();
+                // Invalidate the session for initial handshake in case
+                // of reusing next time.
+                if (isInitialHandshake) {
+                    session.invalidate();
+                }
                 session = null;
                 if (!enableNewSession) {
                     throw new SSLException("New session creation is disabled");
@@ -762,30 +765,33 @@
                 String typeName;
 
                 switch (certRequest.types[i]) {
-                case CertificateRequest.cct_rsa_sign:
-                    typeName = "RSA";
-                    break;
+                    case CertificateRequest.cct_rsa_sign:
+                        typeName = "RSA";
+                        break;
 
-                case CertificateRequest.cct_dss_sign:
-                    typeName = "DSA";
-                    break;
+                    case CertificateRequest.cct_dss_sign:
+                        typeName = "DSA";
+                            break;
 
-                case CertificateRequest.cct_ecdsa_sign:
-                    // ignore if we do not have EC crypto available
-                    typeName = JsseJce.isEcAvailable() ? "EC" : null;
-                    break;
+                    case CertificateRequest.cct_ecdsa_sign:
+                        // ignore if we do not have EC crypto available
+                        typeName = JsseJce.isEcAvailable() ? "EC" : null;
+                        break;
 
-                // Fixed DH/ECDH client authentication not supported
-                case CertificateRequest.cct_rsa_fixed_dh:
-                case CertificateRequest.cct_dss_fixed_dh:
-                case CertificateRequest.cct_rsa_fixed_ecdh:
-                case CertificateRequest.cct_ecdsa_fixed_ecdh:
-                // Any other values (currently not used in TLS)
-                case CertificateRequest.cct_rsa_ephemeral_dh:
-                case CertificateRequest.cct_dss_ephemeral_dh:
-                default:
-                    typeName = null;
-                    break;
+                    // Fixed DH/ECDH client authentication not supported
+                    //
+                    // case CertificateRequest.cct_rsa_fixed_dh:
+                    // case CertificateRequest.cct_dss_fixed_dh:
+                    // case CertificateRequest.cct_rsa_fixed_ecdh:
+                    // case CertificateRequest.cct_ecdsa_fixed_ecdh:
+                    //
+                    // Any other values (currently not used in TLS)
+                    //
+                    // case CertificateRequest.cct_rsa_ephemeral_dh:
+                    // case CertificateRequest.cct_dss_ephemeral_dh:
+                    default:
+                        typeName = null;
+                        break;
                 }
 
                 if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
@@ -813,18 +819,6 @@
                 X509Certificate[] certs = km.getCertificateChain(alias);
                 if ((certs != null) && (certs.length != 0)) {
                     PublicKey publicKey = certs[0].getPublicKey();
-                    // for EC, make sure we use a supported named curve
-                    if (publicKey instanceof ECPublicKey) {
-                        ECParameterSpec params =
-                            ((ECPublicKey)publicKey).getParams();
-                        int index =
-                            SupportedEllipticCurvesExtension.getCurveIndex(
-                                params);
-                        if (!SupportedEllipticCurvesExtension.isSupported(
-                                index)) {
-                            publicKey = null;
-                        }
-                    }
                     if (publicKey != null) {
                         m1 = new CertificateMsg(certs);
                         signingKey = km.getPrivateKey(alias);
@@ -1385,6 +1379,17 @@
                 sslContext.getSecureRandom(), maxProtocolVersion,
                 sessionId, cipherSuites);
 
+        // add elliptic curves and point format extensions
+        if (cipherSuites.containsEC()) {
+            SupportedEllipticCurvesExtension ece =
+                SupportedEllipticCurvesExtension.createExtension(algorithmConstraints);
+            if (ece != null) {
+                clientHelloMessage.extensions.add(ece);
+                clientHelloMessage.extensions.add(
+                   SupportedEllipticPointFormatsExtension.DEFAULT);
+            }
+        }
+
         // add signature_algorithm extension
         if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
             // we will always send the signature_algorithm extension
diff --git a/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java b/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
index b85c4c5..722c415 100644
--- a/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
+++ b/jdk/src/share/classes/sun/security/ssl/ECDHCrypt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,10 +56,11 @@
     }
 
     // Called by ServerHandshaker for ephemeral ECDH
-    ECDHCrypt(String curveName, SecureRandom random) {
+    ECDHCrypt(int curveId, SecureRandom random) {
         try {
             KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
-            ECGenParameterSpec params = new ECGenParameterSpec(curveName);
+            ECGenParameterSpec params =
+                    SupportedEllipticCurvesExtension.getECGenParamSpec(curveId);
             kpg.initialize(params, random);
             KeyPair kp = kpg.generateKeyPair();
             privateKey = kp.getPrivate();
diff --git a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
index 8ecaf78..a2312de 100644
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
@@ -230,11 +230,6 @@
         this.sessionId = sessionId;
         this.cipherSuites = cipherSuites;
 
-        if (cipherSuites.containsEC()) {
-            extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
-            extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
-        }
-
         clnt_random = new RandomCookie(generator);
         compression_methods = NULL_COMPRESSION;
     }
diff --git a/jdk/src/share/classes/sun/security/ssl/Handshaker.java b/jdk/src/share/classes/sun/security/ssl/Handshaker.java
index 7280d0d..38ecb29 100644
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -636,13 +636,41 @@
             ArrayList<CipherSuite> suites = new ArrayList<>();
             if (!(activeProtocols.collection().isEmpty()) &&
                     activeProtocols.min.v != ProtocolVersion.NONE.v) {
+                boolean checkedCurves = false;
+                boolean hasCurves = false;
                 for (CipherSuite suite : enabledCipherSuites.collection()) {
                     if (suite.obsoleted > activeProtocols.min.v &&
                             suite.supported <= activeProtocols.max.v) {
                         if (algorithmConstraints.permits(
                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                                 suite.name, null)) {
-                            suites.add(suite);
+                            boolean available = true;
+                            if (suite.keyExchange.isEC) {
+                                if (!checkedCurves) {
+                                    hasCurves = SupportedEllipticCurvesExtension
+                                        .hasActiveCurves(algorithmConstraints);
+                                    checkedCurves = true;
+
+                                    if (!hasCurves && debug != null &&
+                                                Debug.isOn("verbose")) {
+                                        System.out.println(
+                                           "No available elliptic curves");
+                                    }
+                                }
+
+                                available = hasCurves;
+
+                               if (!available && debug != null &&
+                                        Debug.isOn("verbose")) {
+                                    System.out.println(
+                                        "No active elliptic curves, ignore " +
+                                       suite);
+                                }
+                            }
+
+                            if (available) {
+                                suites.add(suite);
+                            }
                         }
                     } else if (debug != null && Debug.isOn("verbose")) {
                         if (suite.obsoleted <= activeProtocols.min.v) {
@@ -679,18 +707,10 @@
     ProtocolList getActiveProtocols() {
         if (activeProtocols == null) {
             boolean enabledSSL20Hello = false;
+            boolean checkedCurves = false;
+            boolean hasCurves = false;
             ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
             for (ProtocolVersion protocol : enabledProtocols.collection()) {
-                if (!algorithmConstraints.permits(
-                        EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                        protocol.name, null)) {
-                    if (debug != null && Debug.isOn("verbose")) {
-                        System.out.println(
-                            "Ignoring disabled protocol: " + protocol);
-                    }
-
-                    continue;
-                }
                 // Need not to check the SSL20Hello protocol.
                 if (protocol.v == ProtocolVersion.SSL20Hello.v) {
                     enabledSSL20Hello = true;
@@ -714,9 +734,36 @@
                         if (algorithmConstraints.permits(
                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                                 suite.name, null)) {
-                            protocols.add(protocol);
-                            found = true;
-                            break;
+
+                            boolean available = true;
+                            if (suite.keyExchange.isEC) {
+                                if (!checkedCurves) {
+                                    hasCurves = SupportedEllipticCurvesExtension
+                                        .hasActiveCurves(algorithmConstraints);
+                                    checkedCurves = true;
+
+                                    if (!hasCurves && debug != null &&
+                                                Debug.isOn("verbose")) {
+                                        System.out.println(
+                                            "No activated elliptic curves");
+                                    }
+                                }
+
+                                available = hasCurves;
+
+                                if (!available && debug != null &&
+                                        Debug.isOn("verbose")) {
+                                    System.out.println(
+                                        "No active elliptic curves, ignore " +
+                                        suite + " for " + protocol);
+                                }
+                            }
+
+                            if (available) {
+                                protocols.add(protocol);
+                                found = true;
+                                break;
+                            }
                         } else if (debug != null && Debug.isOn("verbose")) {
                             System.out.println(
                                 "Ignoring disabled cipher suite: " + suite +
diff --git a/jdk/src/share/classes/sun/security/ssl/JsseJce.java b/jdk/src/share/classes/sun/security/ssl/JsseJce.java
index 923ae8e..d3262de 100644
--- a/jdk/src/share/classes/sun/security/ssl/JsseJce.java
+++ b/jdk/src/share/classes/sun/security/ssl/JsseJce.java
@@ -290,6 +290,15 @@
         }
     }
 
+    static AlgorithmParameters getAlgorithmParameters(String algorithm)
+            throws NoSuchAlgorithmException {
+        if (cryptoProvider == null) {
+            return AlgorithmParameters.getInstance(algorithm);
+        } else {
+            return AlgorithmParameters.getInstance(algorithm, cryptoProvider);
+        }
+    }
+
     static SecureRandom getSecureRandom() throws KeyManagementException {
         if (cryptoProvider == null) {
             return new SecureRandom();
@@ -409,6 +418,7 @@
                 JsseJce.getKeyAgreement("ECDH");
                 JsseJce.getKeyFactory("EC");
                 JsseJce.getKeyPairGenerator("EC");
+                JsseJce.getAlgorithmParameters("EC");
             } catch (Exception e) {
                 mediator = false;
             }
diff --git a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
index 373dc57..d983b60 100644
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
@@ -92,7 +92,8 @@
     // we remember it for the RSA premaster secret version check
     private ProtocolVersion clientRequestedVersion;
 
-    private SupportedEllipticCurvesExtension supportedCurves;
+    // client supported elliptic curves
+    private SupportedEllipticCurvesExtension requestedCurves;
 
     // the preferable signature algorithm used by ServerKeyExchange message
     SignatureAndHashAlgorithm preferableSignatureAlgorithm;
@@ -682,7 +683,7 @@
                 throw new SSLException("Client did not resume a session");
             }
 
-            supportedCurves = (SupportedEllipticCurvesExtension)
+            requestedCurves = (SupportedEllipticCurvesExtension)
                         mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
 
             // We only need to handle the "signature_algorithm" extension
@@ -1025,11 +1026,18 @@
             if (trySetCipherSuite(suite) == false) {
                 continue;
             }
+
+            if (debug != null && Debug.isOn("handshake")) {
+                System.out.println("Standard ciphersuite chosen: " + suite);
+            }
             return;
         }
 
         for (CipherSuite suite : legacySuites) {
             if (trySetCipherSuite(suite)) {
+                if (debug != null && Debug.isOn("handshake")) {
+                    System.out.println("Legacy ciphersuite chosen: " + suite);
+                }
                 return;
             }
         }
@@ -1412,26 +1420,15 @@
     // If we cannot continue because we do not support any of the curves that
     // the client requested, return false. Otherwise (all is well), return true.
     private boolean setupEphemeralECDHKeys() {
-        int index = -1;
-        if (supportedCurves != null) {
-            // if the client sent the supported curves extension, pick the
-            // first one that we support;
-            for (int curveId : supportedCurves.curveIds()) {
-                if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
-                    index = curveId;
-                    break;
-                }
-            }
-            if (index < 0) {
-                // no match found, cannot use this ciphersuite
-                return false;
-            }
-        } else {
-            // pick our preference
-            index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
+        int index = (requestedCurves != null) ?
+                requestedCurves.getPreferredCurve(algorithmConstraints) :
+                SupportedEllipticCurvesExtension.getActiveCurves(algorithmConstraints);
+        if (index < 0) {
+            // no match found, cannot use this ciphersuite
+            return false;
         }
-        String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
-        ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
+
+        ecdh = new ECDHCrypt(index, sslContext.getSecureRandom());
         return true;
     }
 
@@ -1480,11 +1477,9 @@
                 return false;
             }
             ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
-            int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
-            if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
-                return false;
-            }
-            if ((supportedCurves != null) && !supportedCurves.contains(index)) {
+            int id = SupportedEllipticCurvesExtension.getCurveIndex(params);
+            if ((id <= 0) || !SupportedEllipticCurvesExtension.isSupported(id) ||
+                ((requestedCurves != null) && !requestedCurves.contains(id))) {
                 return false;
             }
         }
diff --git a/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java b/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
index 8933fab..b7757d6 100644
--- a/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
+++ b/jdk/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java
@@ -27,39 +27,195 @@
 
 import java.io.IOException;
 import java.security.spec.ECParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.AlgorithmParameters;
+import java.security.AlgorithmConstraints;
+import java.security.CryptoPrimitive;
+import java.security.AccessController;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Map;
-
+import java.util.ArrayList;
 import javax.net.ssl.SSLProtocolException;
 
+import sun.security.action.GetPropertyAction;
+
 final class SupportedEllipticCurvesExtension extends HelloExtension {
 
-    // the extension value to send in the ClientHello message
-    static final SupportedEllipticCurvesExtension DEFAULT;
+    private static final int ARBITRARY_PRIME = 0xff01;
+    private static final int ARBITRARY_CHAR2 = 0xff02;
 
-    private static final boolean fips;
+    // speed up the searching
+    private static final Map<String, Integer> oidToIdMap = new HashMap<>();
+    private static final Map<Integer, String> idToOidMap = new HashMap<>();
 
-    static {
-        int[] ids;
-        fips = SunJSSE.isFIPS();
-        if (fips == false) {
-            ids = new int[] {
-                // NIST curves first
-                // prefer NIST P-256, rest in order of increasing key length
-                23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
-                // non-NIST curves
-                15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
-            };
-        } else {
-            ids = new int[] {
-                // same as above, but allow only NIST curves in FIPS mode
-                23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
-            };
+    // speed up the parameters construction
+    private static final Map<Integer,
+                AlgorithmParameters> idToParams = new HashMap<>();
+
+    // the supported elliptic curves
+    private static final int[] supportedCurveIds;
+
+    // the curves of the extension
+    private final int[] curveIds;
+
+    // See sun.security.util.CurveDB for the OIDs
+    private static enum NamedEllipticCurve {
+        T163_K1(1,  "sect163k1",    "1.3.132.0.1",      true),  // NIST K-163
+        T163_R1(2,  "sect163r1",    "1.3.132.0.2",      false),
+        T163_R2(3,  "sect163r2",    "1.3.132.0.15",     true),  // NIST B-163
+        T193_R1(4,  "sect193r1",    "1.3.132.0.24",     false),
+        T193_R2(5,  "sect193r2",    "1.3.132.0.25",     false),
+        T233_K1(6,  "sect233k1",    "1.3.132.0.26",     true),  // NIST K-233
+        T233_R1(7,  "sect233r1",    "1.3.132.0.27",     true),  // NIST B-233
+        T239_K1(8,  "sect239k1",    "1.3.132.0.3",      false),
+        T283_K1(9,  "sect283k1",    "1.3.132.0.16",     true),  // NIST K-283
+        T283_R1(10, "sect283r1",    "1.3.132.0.17",     true),  // NIST B-283
+        T409_K1(11, "sect409k1",    "1.3.132.0.36",     true),  // NIST K-409
+        T409_R1(12, "sect409r1",    "1.3.132.0.37",     true),  // NIST B-409
+        T571_K1(13, "sect571k1",    "1.3.132.0.38",     true),  // NIST K-571
+        T571_R1(14, "sect571r1",    "1.3.132.0.39",     true),  // NIST B-571
+
+        P160_K1(15, "secp160k1",    "1.3.132.0.9",      false),
+        P160_R1(16, "secp160r1",    "1.3.132.0.8",      false),
+        P160_R2(17, "secp160r2",    "1.3.132.0.30",     false),
+        P192_K1(18, "secp192k1",    "1.3.132.0.31",     false),
+        P192_R1(19, "secp192r1",    "1.2.840.10045.3.1.1", true), // NIST P-192
+        P224_K1(20, "secp224k1",    "1.3.132.0.32",     false),
+        P224_R1(21, "secp224r1",    "1.3.132.0.33",     true),  // NIST P-224
+        P256_K1(22, "secp256k1",    "1.3.132.0.10",     false),
+        P256_R1(23, "secp256r1",    "1.2.840.10045.3.1.7", true), // NIST P-256
+        P384_R1(24, "secp384r1",    "1.3.132.0.34",     true),  // NIST P-384
+        P521_R1(25, "secp521r1",    "1.3.132.0.35",     true);  // NIST P-521
+
+        int          id;
+        String       name;
+        String       oid;
+        boolean      isFips;
+
+        NamedEllipticCurve(int id, String name, String oid, boolean isFips) {
+            this.id = id;
+            this.name = name;
+            this.oid = oid;
+            this.isFips = isFips;
+
+            if (oidToIdMap.put(oid, id) != null ||
+                idToOidMap.put(id, oid) != null) {
+
+                throw new RuntimeException(
+                        "Duplicate named elliptic curve definition: " + name);
+            }
         }
-        DEFAULT = new SupportedEllipticCurvesExtension(ids);
+
+        static NamedEllipticCurve getCurve(String name, boolean requireFips) {
+            for (NamedEllipticCurve curve : NamedEllipticCurve.values()) {
+                if (curve.name.equals(name) && (!requireFips || curve.isFips)) {
+                    return curve;
+                }
+            }
+
+            return null;
+        }
     }
 
-    private final int[] curveIds;
+    static {
+        boolean requireFips = SunJSSE.isFIPS();
+
+        // hack code to initialize NamedEllipticCurve
+        NamedEllipticCurve nec =
+                NamedEllipticCurve.getCurve("secp256r1", false);
+
+        // The value of the System Property defines a list of enabled named
+        // curves in preference order, separated with comma.  For example:
+        //
+        //      jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1"
+        //
+        // If the System Property is not defined or the value is empty, the
+        // default curves and preferences will be used.
+        String property = AccessController.doPrivileged(
+                    new GetPropertyAction("jdk.tls.namedGroups"));
+        if (property != null && property.length() != 0) {
+            // remove double quote marks from beginning/end of the property
+            if (property.length() > 1 && property.charAt(0) == '"' &&
+                    property.charAt(property.length() - 1) == '"') {
+                property = property.substring(1, property.length() - 1);
+            }
+        }
+
+        ArrayList<Integer> idList;
+        if (property != null && property.length() != 0) {   // customized curves
+            String[] curves = property.split(",");
+            idList = new ArrayList<>(curves.length);
+            for (String curve : curves) {
+                curve = curve.trim();
+                if (!curve.isEmpty()) {
+                    NamedEllipticCurve namedCurve =
+                            NamedEllipticCurve.getCurve(curve, requireFips);
+                    if (namedCurve != null) {
+                        if (isAvailableCurve(namedCurve.id)) {
+                            idList.add(namedCurve.id);
+                        }
+                    }   // ignore unknown curves
+                }
+            }
+        } else {        // default curves
+            int[] ids;
+            if (requireFips) {
+                ids = new int[] {
+                    // only NIST curves in FIPS mode
+                    23, 24, 25, 9, 10, 11, 12, 13, 14,
+                };
+            } else {
+                ids = new int[] {
+                    // NIST curves first
+                    23, 24, 25, 9, 10, 11, 12, 13, 14,
+                    // non-NIST curves
+                    22,
+                };
+            }
+
+            idList = new ArrayList<>(ids.length);
+            for (int curveId : ids) {
+                if (isAvailableCurve(curveId)) {
+                    idList.add(curveId);
+                }
+            }
+        }
+
+        if (idList.isEmpty()) {
+            throw new IllegalArgumentException(
+                "System property jdk.tls.namedGroups(" + property + ") " +
+                "contains no supported elliptic curves");
+        } else {
+            supportedCurveIds = new int[idList.size()];
+            int i = 0;
+            for (Integer id : idList) {
+                supportedCurveIds[i++] = id;
+            }
+        }
+    }
+
+    // check whether the curve is supported by the underlying providers
+    private static boolean isAvailableCurve(int curveId) {
+        String oid = idToOidMap.get(curveId);
+        if (oid != null) {
+            AlgorithmParameters params = null;
+            try {
+                params = JsseJce.getAlgorithmParameters("EC");
+                params.init(new ECGenParameterSpec(oid));
+            } catch (Exception e) {
+                return false;
+            }
+
+            // cache the parameters
+            idToParams.put(curveId, params);
+
+            return true;
+        }
+
+        return false;
+    }
 
     private SupportedEllipticCurvesExtension(int[] curveIds) {
         super(ExtensionType.EXT_ELLIPTIC_CURVES);
@@ -73,12 +229,67 @@
         if (((len & 1) != 0) || (k + 2 != len)) {
             throw new SSLProtocolException("Invalid " + type + " extension");
         }
+
+        // Note: unknown curves will be ignored later.
         curveIds = new int[k >> 1];
         for (int i = 0; i < curveIds.length; i++) {
             curveIds[i] = s.getInt16();
         }
     }
 
+    // get the preferred active curve
+    static int getActiveCurves(AlgorithmConstraints constraints) {
+        return getPreferredCurve(supportedCurveIds, constraints);
+    }
+
+    static boolean hasActiveCurves(AlgorithmConstraints constraints) {
+        return getActiveCurves(constraints) >= 0;
+    }
+
+    static SupportedEllipticCurvesExtension createExtension(
+                AlgorithmConstraints constraints) {
+
+        ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length);
+        for (int curveId : supportedCurveIds) {
+            if (constraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                                "EC", idToParams.get(curveId))) {
+                idList.add(curveId);
+            }
+        }
+
+        if (!idList.isEmpty()) {
+            int[] ids = new int[idList.size()];
+            int i = 0;
+            for (Integer id : idList) {
+                ids[i++] = id;
+            }
+
+            return new SupportedEllipticCurvesExtension(ids);
+        }
+
+        return null;
+    }
+
+    // get the preferred activated curve
+    int getPreferredCurve(AlgorithmConstraints constraints) {
+        return getPreferredCurve(curveIds, constraints);
+    }
+
+    // get a preferred activated curve
+    private static int getPreferredCurve(int[] curves,
+                AlgorithmConstraints constraints) {
+        for (int curveId : curves) {
+            if (isSupported(curveId) && constraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                                "EC", idToParams.get(curveId))) {
+                return curveId;
+            }
+        }
+
+        return -1;
+    }
+
     boolean contains(int index) {
         for (int curveId : curveIds) {
             if (index == curveId) {
@@ -88,12 +299,6 @@
         return false;
     }
 
-    // Return a reference to the internal curveIds array.
-    // The caller must NOT modify the contents.
-    int[] curveIds() {
-        return curveIds;
-    }
-
     @Override
     int length() {
         return 6 + (curveIds.length << 1);
@@ -121,18 +326,9 @@
             } else {
                 sb.append(", ");
             }
-            // first check if it is a known named curve, then try other cases.
-            String oid = getCurveOid(curveId);
-            if (oid != null) {
-                ECParameterSpec spec = JsseJce.getECParameterSpec(oid);
-                // this toString() output will look nice for the current
-                // implementation of the ECParameterSpec class in the Sun
-                // provider, but may not look good for other implementations.
-                if (spec != null) {
-                    sb.append(spec.toString().split(" ")[0]);
-                } else {
-                    sb.append(oid);
-                }
+            String curveName = getCurveName(curveId);
+            if (curveName != null) {
+                sb.append(curveName);
             } else if (curveId == ARBITRARY_PRIME) {
                 sb.append("arbitrary_explicit_prime_curves");
             } else if (curveId == ARBITRARY_CHAR2) {
@@ -145,16 +341,15 @@
         return sb.toString();
     }
 
-    // Test whether we support the curve with the given index.
+    // Test whether the given curve is supported.
     static boolean isSupported(int index) {
-        if ((index <= 0) || (index >= NAMED_CURVE_OID_TABLE.length)) {
-            return false;
+        for (int curveId : supportedCurveIds) {
+            if (index == curveId) {
+                return true;
+            }
         }
-        if (fips == false) {
-            // in non-FIPS mode, we support all valid indices
-            return true;
-        }
-        return DEFAULT.contains(index);
+
+        return false;
     }
 
     static int getCurveIndex(ECParameterSpec params) {
@@ -162,57 +357,32 @@
         if (oid == null) {
             return -1;
         }
-        Integer n = curveIndices.get(oid);
+        Integer n = oidToIdMap.get(oid);
         return (n == null) ? -1 : n;
     }
 
     static String getCurveOid(int index) {
-        if ((index > 0) && (index < NAMED_CURVE_OID_TABLE.length)) {
-            return NAMED_CURVE_OID_TABLE[index];
+        return idToOidMap.get(index);
+    }
+
+    static ECGenParameterSpec getECGenParamSpec(int index) {
+        AlgorithmParameters params = idToParams.get(index);
+        try {
+            return params.getParameterSpec(ECGenParameterSpec.class);
+        } catch (InvalidParameterSpecException ipse) {
+            // should be unlikely
+            String curveOid = getCurveOid(index);
+            return new ECGenParameterSpec(curveOid);
         }
+    }
+
+    private static String getCurveName(int index) {
+        for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) {
+            if (namedCurve.id == index) {
+                return namedCurve.name;
+            }
+        }
+
         return null;
     }
-
-    private final static int ARBITRARY_PRIME = 0xff01;
-    private final static int ARBITRARY_CHAR2 = 0xff02;
-
-    // See sun.security.ec.NamedCurve for the OIDs
-    private final static String[] NAMED_CURVE_OID_TABLE = new String[] {
-        null,                   //  (0) unused
-        "1.3.132.0.1",          //  (1) sect163k1, NIST K-163
-        "1.3.132.0.2",          //  (2) sect163r1
-        "1.3.132.0.15",         //  (3) sect163r2, NIST B-163
-        "1.3.132.0.24",         //  (4) sect193r1
-        "1.3.132.0.25",         //  (5) sect193r2
-        "1.3.132.0.26",         //  (6) sect233k1, NIST K-233
-        "1.3.132.0.27",         //  (7) sect233r1, NIST B-233
-        "1.3.132.0.3",          //  (8) sect239k1
-        "1.3.132.0.16",         //  (9) sect283k1, NIST K-283
-        "1.3.132.0.17",         // (10) sect283r1, NIST B-283
-        "1.3.132.0.36",         // (11) sect409k1, NIST K-409
-        "1.3.132.0.37",         // (12) sect409r1, NIST B-409
-        "1.3.132.0.38",         // (13) sect571k1, NIST K-571
-        "1.3.132.0.39",         // (14) sect571r1, NIST B-571
-        "1.3.132.0.9",          // (15) secp160k1
-        "1.3.132.0.8",          // (16) secp160r1
-        "1.3.132.0.30",         // (17) secp160r2
-        "1.3.132.0.31",         // (18) secp192k1
-        "1.2.840.10045.3.1.1",  // (19) secp192r1, NIST P-192
-        "1.3.132.0.32",         // (20) secp224k1
-        "1.3.132.0.33",         // (21) secp224r1, NIST P-224
-        "1.3.132.0.10",         // (22) secp256k1
-        "1.2.840.10045.3.1.7",  // (23) secp256r1, NIST P-256
-        "1.3.132.0.34",         // (24) secp384r1, NIST P-384
-        "1.3.132.0.35",         // (25) secp521r1, NIST P-521
-    };
-
-    private final static Map<String,Integer> curveIndices;
-
-    static {
-        curveIndices = new HashMap<String,Integer>();
-        for (int i = 1; i < NAMED_CURVE_OID_TABLE.length; i++) {
-            curveIndices.put(NAMED_CURVE_OID_TABLE[i], i);
-        }
-    }
-
 }
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
index 961921c..07962dc 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java
@@ -53,6 +53,9 @@
 import java.security.cert.PKIXParameters;
 import java.security.cert.TrustAnchor;
 import java.util.Map.Entry;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.timestamp.TimestampToken;
 import sun.security.tools.KeyStoreUtil;
 import sun.security.tools.PathList;
 import sun.security.x509.*;
@@ -97,6 +100,15 @@
 
     private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
 
+    private static final DisabledAlgorithmConstraints DISABLED_CHECK =
+            new DisabledAlgorithmConstraints(
+                    DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
+    private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
+            .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+    private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
+            .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+
     // Attention:
     // This is the entry that get launched by the security tool jarsigner.
     public static void main(String args[]) throws Exception {
@@ -172,6 +184,8 @@
     private boolean badExtendedKeyUsage = false;
     private boolean badNetscapeCertType = false;
 
+    private boolean seeWeak = false;
+
     CertificateFactory certificateFactory;
     CertPathValidator validator;
     PKIXParameters pkixParameters;
@@ -577,6 +591,10 @@
     {
         boolean anySigned = false;  // if there exists entry inside jar signed
         JarFile jf = null;
+        Map<String,String> digestMap = new HashMap<>();
+        Map<String,PKCS7> sigMap = new HashMap<>();
+        Map<String,String> sigNameMap = new HashMap<>();
+        Map<String,String> unparsableSignatures = new HashMap<>();
 
         try {
             jf = new JarFile(jarName, true);
@@ -587,17 +605,44 @@
             while (entries.hasMoreElements()) {
                 JarEntry je = entries.nextElement();
                 entriesVec.addElement(je);
-                InputStream is = null;
+                try (InputStream is = jf.getInputStream(je)) {
+                    String name = je.getName();
+                    if (signatureRelated(name)
+                            && SignatureFileVerifier.isBlockOrSF(name)) {
+                        String alias = name.substring(name.lastIndexOf('/') + 1,
+                                name.lastIndexOf('.'));
                 try {
-                    is = jf.getInputStream(je);
-                    int n;
-                    while ((n = is.read(buffer, 0, buffer.length)) != -1) {
+                            if (name.endsWith(".SF")) {
+                                Manifest sf = new Manifest(is);
+                                boolean found = false;
+                                for (Object obj : sf.getMainAttributes().keySet()) {
+                                    String key = obj.toString();
+                                    if (key.endsWith("-Digest-Manifest")) {
+                                        digestMap.put(alias,
+                                                key.substring(0, key.length() - 16));
+                                        found = true;
+                                        break;
+                                    }
+                                }
+                                if (!found) {
+                                    unparsableSignatures.putIfAbsent(alias,
+                                        String.format(
+                                            rb.getString("history.unparsable"),
+                                            name));
+                                }
+                            } else {
+                                sigNameMap.put(alias, name);
+                                sigMap.put(alias, new PKCS7(is));
+                            }
+                        } catch (IOException ioe) {
+                            unparsableSignatures.putIfAbsent(alias, String.format(
+                                    rb.getString("history.unparsable"), name));
+                        }
+                    } else {
+                        while (is.read(buffer, 0, buffer.length) != -1) {
                         // we just read. this will throw a SecurityException
                         // if  a signature/digest check fails.
                     }
-                } finally {
-                    if (is != null) {
-                        is.close();
                     }
                 }
             }
@@ -756,13 +801,106 @@
                     System.out.println(rb.getString(
                         ".X.not.signed.by.specified.alias.es."));
                 }
+            }
+            if (man == null) {
+                System.out.println();
+                System.out.println(rb.getString("no.manifest."));
+            }
+
+            // Even if the verbose option is not specified, all out strings
+            // must be generated so seeWeak can be updated.
+            if (!digestMap.isEmpty()
+                    || !sigMap.isEmpty()
+                    || !unparsableSignatures.isEmpty()) {
+                if (verbose != null) {
                 System.out.println();
             }
-            if (man == null)
-                System.out.println(rb.getString("no.manifest."));
+                for (String s : sigMap.keySet()) {
+                    if (!digestMap.containsKey(s)) {
+                        unparsableSignatures.putIfAbsent(s, String.format(
+                                rb.getString("history.nosf"), s));
+                    }
+                }
+                for (String s : digestMap.keySet()) {
+                    PKCS7 p7 = sigMap.get(s);
+                    if (p7 != null) {
+                        String history;
+                        try {
+                            SignerInfo si = p7.getSignerInfos()[0];
+                            X509Certificate signer = si.getCertificate(p7);
+                            String digestAlg = digestMap.get(s);
+                            String sigAlg = AlgorithmId.makeSigAlg(
+                                    si.getDigestAlgorithmId().getName(),
+                                    si.getDigestEncryptionAlgorithmId().getName());
+                            PublicKey key = signer.getPublicKey();
+                            PKCS7 tsToken = si.getTsToken();
+                            if (tsToken != null) {
+                                SignerInfo tsSi = tsToken.getSignerInfos()[0];
+                                X509Certificate tsSigner = tsSi.getCertificate(tsToken);
+                                byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
+                                TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
+                                PublicKey tsKey = tsSigner.getPublicKey();
+                                String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
+                                String tsSigAlg = AlgorithmId.makeSigAlg(
+                                        tsSi.getDigestAlgorithmId().getName(),
+                                        tsSi.getDigestEncryptionAlgorithmId().getName());
+                                Calendar c = Calendar.getInstance(
+                                        TimeZone.getTimeZone("UTC"),
+                                        Locale.getDefault(Locale.Category.FORMAT));
+                                c.setTime(tsTokenInfo.getDate());
+                                history = String.format(
+                                        rb.getString("history.with.ts"),
+                                        signer.getSubjectX500Principal(),
+                                        withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+                                        withWeak(sigAlg, SIG_PRIMITIVE_SET),
+                                        withWeak(key),
+                                        c,
+                                        tsSigner.getSubjectX500Principal(),
+                                        withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET),
+                                        withWeak(tsSigAlg, SIG_PRIMITIVE_SET),
+                                        withWeak(tsKey));
+                            } else {
+                                history = String.format(
+                                        rb.getString("history.without.ts"),
+                                        signer.getSubjectX500Principal(),
+                                        withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
+                                        withWeak(sigAlg, SIG_PRIMITIVE_SET),
+                                        withWeak(key));
+                            }
+                        } catch (Exception e) {
+                            // The only usage of sigNameMap, remember the name
+                            // of the block file if it's invalid.
+                            history = String.format(
+                                    rb.getString("history.unparsable"),
+                                    sigNameMap.get(s));
+                        }
+                        if (verbose != null) {
+                            System.out.println(history);
+                        }
+                    } else {
+                        unparsableSignatures.putIfAbsent(s, String.format(
+                                rb.getString("history.nobk"), s));
+                    }
+                }
+                if (verbose != null) {
+                    for (String s : unparsableSignatures.keySet()) {
+                        System.out.println(unparsableSignatures.get(s));
+                    }
+                }
+            }
+            System.out.println();
 
             if (!anySigned) {
-                if (hasSignature) {
+                if (seeWeak) {
+                    if (verbose != null) {
+                        System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose"));
+                        System.out.println("\n  " +
+                                DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS +
+                                "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS));
+                    } else {
+                        System.out.println(rb.getString("jar.treated.unsigned.see.weak"));
+                    }
+                } else if (hasSignature) {
                     System.out.println(rb.getString("jar.treated.unsigned"));
                 } else {
                     System.out.println(rb.getString("jar.is.unsigned"));
@@ -869,6 +1007,26 @@
         System.exit(1);
     }
 
+    private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
+        if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
+            return alg;
+        } else {
+            seeWeak = true;
+            return String.format(rb.getString("with.weak"), alg);
+        }
+    }
+
+    private String withWeak(PublicKey key) {
+        if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
+            return String.format(
+                    rb.getString("key.bit"), KeyUtil.getKeySize(key));
+        } else {
+            seeWeak = true;
+            return String.format(
+                    rb.getString("key.bit.weak"), KeyUtil.getKeySize(key));
+        }
+    }
+
     private static MessageFormat validityTimeForm = null;
     private static MessageFormat notYetTimeForm = null;
     private static MessageFormat expiredTimeForm = null;
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
index 909d573..bff9dd7 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources.java
@@ -138,11 +138,26 @@
         {"jar.is.unsigned",
                 "jar is unsigned."},
         {"jar.treated.unsigned",
-                "Signature not parsable or verifiable. The jar will be treated as unsigned. The jar may have been signed with a weak algorithm that is now disabled. For more information, rerun jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+                "WARNING: Signature is either not parsable or not verifiable, and the jar will be treated as unsigned. For more information, re-run jarsigner with debug enabled (-J-Djava.security.debug=jar)."},
+        {"jar.treated.unsigned.see.weak",
+                "The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled.\n\nRe-run jarsigner with the -verbose option for more details."},
+        {"jar.treated.unsigned.see.weak.verbose",
+                "WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:"},
         {"jar.signed.", "jar signed."},
         {"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
         {"jar.verified.", "jar verified."},
         {"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
+
+        {"history.with.ts", "- Signed by \"%1$s\"\n    Digest algorithm: %2$s\n    Signature algorithm: %3$s, %4$s\n  Timestamped by \"%6$s\" on %5$tc\n    Timestamp digest algorithm: %7$s\n    Timestamp signature algorithm: %8$s, %9$s"},
+        {"history.without.ts", "- Signed by \"%1$s\"\n    Digest algorithm: %2$s\n    Signature algorithm: %3$s, %4$s"},
+        {"history.unparsable", "- Unparsable signature-related file %s"},
+        {"history.nosf", "- Missing signature-related file META-INF/%s.SF"},
+        {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"},
+
+        {"with.weak", "%s (weak)"},
+        {"key.bit", "%d-bit key"},
+        {"key.bit.weak", "%d-bit key (weak)"},
+
         {"jarsigner.", "jarsigner: "},
         {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
                 "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
index b471210..86b74b9 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java
@@ -135,12 +135,29 @@
         {"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"},
         {".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"},
         {".Unsigned.entries.", "(\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA)"},
-        {"jar.is.unsigned.signatures.missing.or.not.parsable.",
-                "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002(\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u304B\u3001\u69CB\u6587\u89E3\u6790\u3067\u304D\u307E\u305B\u3093)"},
+        {"jar.is.unsigned",
+                "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
+        {"jar.treated.unsigned",
+                "\u8B66\u544A: \u7F72\u540D\u304C\u69CB\u6587\u89E3\u6790\u3067\u304D\u306A\u3044\u304B\u691C\u8A3C\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u306Ejar\u306F\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001\u30C7\u30D0\u30C3\u30B0\u3092\u6709\u52B9\u306B\u3057\u3066(-J-Djava.security.debug=jar) jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+        {"jar.treated.unsigned.see.weak",
+                "\u3053\u306Ejar\u306F\u3001\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\n\n\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+        {"jar.treated.unsigned.see.weak.verbose",
+                "\u8B66\u544A: \u3053\u306Ejar\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u3088\u3063\u3066\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059:"},
         {"jar.signed.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F\u3002"},
         {"jar.signed.with.signer.errors.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"},
         {"jar.verified.", "jar\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F\u3002"},
         {"jar.verified.with.signer.errors.", "jar\u306F\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"},
+
+        {"history.with.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n    \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n    \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s\n  \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u4ED8\u52A0\u8005: \"%6$s\" \u65E5\u6642: %5$tc\n    \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %7$s\n    \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %8$s\u3001%9$s"},
+        {"history.without.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n    \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n    \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s"},
+        {"history.unparsable", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EB%s\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"},
+        {"history.nosf", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u304C\u3042\u308A\u307E\u305B\u3093"},
+        {"history.nobk", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u306E\u30D6\u30ED\u30C3\u30AF\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"},
+
+        {"with.weak", "%s (\u5F31)"},
+        {"key.bit", "%d\u30D3\u30C3\u30C8\u9375"},
+        {"key.bit.weak", "%d\u30D3\u30C3\u30C8\u9375(\u5F31)"},
+
         {"jarsigner.", "jarsigner: "},
         {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
                 "\u30B7\u30B0\u30CD\u30C1\u30E3\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u306B\u4F7F\u7528\u3067\u304D\u308B\u6587\u5B57\u306F\u3001A-Z\u30010-9\u3001_\u3001- \u306E\u307F\u3067\u3059\u3002"},
diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
index 76f88c1..e99405b 100644
--- a/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
+++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java
@@ -135,12 +135,29 @@
         {"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"},
         {".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"},
         {".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"},
-        {"jar.is.unsigned.signatures.missing.or.not.parsable.",
-                "jar \u672A\u7B7E\u540D\u3002(\u7F3A\u5C11\u7B7E\u540D\u6216\u65E0\u6CD5\u89E3\u6790\u7B7E\u540D)"},
+        {"jar.is.unsigned",
+                "jar \u672A\u7B7E\u540D\u3002"},
+        {"jar.treated.unsigned",
+                "\u8B66\u544A: \u7B7E\u540D\u65E0\u6CD5\u89E3\u6790\u6216\u9A8C\u8BC1, \u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u5728\u542F\u7528\u8C03\u8BD5\u7684\u60C5\u51B5\u4E0B\u91CD\u65B0\u8FD0\u884C jarsigner (-J-Djava.security.debug=jar)\u3002"},
+        {"jar.treated.unsigned.see.weak",
+                "\u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\n\n\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C jarsigner\u3002"},
+        {"jar.treated.unsigned.see.weak.verbose",
+                "\u8B66\u544A: \u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7531\u5B89\u5168\u5C5E\u6027\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D:"},
         {"jar.signed.", "jar \u5DF2\u7B7E\u540D\u3002"},
         {"jar.signed.with.signer.errors.", "jar \u5DF2\u7B7E\u540D, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"},
         {"jar.verified.", "jar \u5DF2\u9A8C\u8BC1\u3002"},
         {"jar.verified.with.signer.errors.", "jar \u5DF2\u9A8C\u8BC1, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"},
+
+        {"history.with.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n    \u6458\u8981\u7B97\u6CD5: %2$s\n    \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s\n  \u7531 \"%6$s\" \u4E8E %5$tc \u52A0\u65F6\u95F4\u6233\n    \u65F6\u95F4\u6233\u6458\u8981\u7B97\u6CD5: %7$s\n    \u65F6\u95F4\u6233\u7B7E\u540D\u7B97\u6CD5: %8$s, %9$s"},
+        {"history.without.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n    \u6458\u8981\u7B97\u6CD5: %2$s\n    \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s"},
+        {"history.unparsable", "- \u65E0\u6CD5\u89E3\u6790\u7684\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 %s"},
+        {"history.nosf", "- \u7F3A\u5C11\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF"},
+        {"history.nobk", "- \u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF \u7F3A\u5C11\u5757\u6587\u4EF6"},
+
+        {"with.weak", "%s (\u5F31)"},
+        {"key.bit", "%d \u4F4D\u5BC6\u94A5"},
+        {"key.bit.weak", "%d \u4F4D\u5BC6\u94A5 (\u5F31)"},
+
         {"jarsigner.", "jarsigner: "},
         {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
                 "\u7B7E\u540D\u6587\u4EF6\u540D\u5FC5\u987B\u5305\u542B\u4EE5\u4E0B\u5B57\u7B26: A-Z, 0-9, _ \u6216 -"},
diff --git a/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java b/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
index 4199ff4..f9eee0b 100644
--- a/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
+++ b/jdk/src/share/classes/sun/security/tools/policytool/Resources_sv.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
         {"Illegal.option.option", "Otill\u00E5tet alternativ: {0}"},
         {"Usage.policytool.options.", "Syntax: policytool [alternativ]"},
         {".file.file.policy.file.location",
-                "  [-file <fil>]    policyfilens plats"},
+                "  [-file <fil>]    policyfiladress"},
         {"New", "&Nytt"},
         {"Open", "&\u00D6ppna..."},
         {"Save", "S&para"},
diff --git a/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
index 6175fea..e7ed756 100644
--- a/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
+++ b/jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.security.AlgorithmConstraints;
 import java.security.PrivilegedAction;
 import java.security.Security;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -45,8 +44,7 @@
     }
 
     // Get algorithm constraints from the specified security property.
-    private static void loadAlgorithmsMap(Map<String, String[]> algorithmsMap,
-            String propertyName) {
+    static String[] getAlgorithms(String propertyName) {
         String property = AccessController.doPrivileged(
                 new PrivilegedAction<String>() {
                     @Override
@@ -72,18 +70,7 @@
         if (algorithmsInProperty == null) {
             algorithmsInProperty = new String[0];
         }
-        algorithmsMap.put(propertyName, algorithmsInProperty);
-    }
-
-    static String[] getAlgorithms(Map<String, String[]> algorithmsMap,
-            String propertyName) {
-        synchronized (algorithmsMap) {
-            if (!algorithmsMap.containsKey(propertyName)) {
-                loadAlgorithmsMap(algorithmsMap, propertyName);
-            }
-
-            return algorithmsMap.get(propertyName);
-        }
+        return algorithmsInProperty;
     }
 
     static boolean checkAlgorithm(String[] algorithms, String algorithm,
diff --git a/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java b/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
index 394b846..dae529a 100644
--- a/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
+++ b/jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,19 +38,7 @@
     private static final Pattern pattern =
                     Pattern.compile("with|and", Pattern.CASE_INSENSITIVE);
 
-    /**
-     * Decompose the standard algorithm name into sub-elements.
-     * <p>
-     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
-     * so that we can check the "SHA1" and "RSA" algorithm constraints
-     * separately.
-     * <p>
-     * Please override the method if need to support more name pattern.
-     */
-    public Set<String> decompose(String algorithm) {
-        if (algorithm == null || algorithm.length() == 0) {
-            return new HashSet<>();
-        }
+    private static Set<String> decomposeImpl(String algorithm) {
 
         // algorithm/mode/padding
         String[] transTockens = transPattern.split(algorithm);
@@ -76,6 +64,24 @@
                 elements.add(token);
             }
         }
+        return elements;
+    }
+
+    /**
+     * Decompose the standard algorithm name into sub-elements.
+     * <p>
+     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+     * so that we can check the "SHA1" and "RSA" algorithm constraints
+     * separately.
+     * <p>
+     * Please override the method if need to support more name pattern.
+     */
+    public Set<String> decompose(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<>();
+        }
+
+        Set<String> elements = decomposeImpl(algorithm);
 
         // In Java standard algorithm name specification, for different
         // purpose, the SHA-1 and SHA-2 algorithm names are different. For
@@ -127,4 +133,40 @@
         return elements;
     }
 
+    private static void hasLoop(Set<String> elements, String find, String replace) {
+        if (elements.contains(find)) {
+            if (!elements.contains(replace)) {
+                elements.add(replace);
+}
+            elements.remove(find);
+        }
+    }
+
+    /*
+     * This decomposes a standard name into sub-elements with a consistent
+     * message digest algorithm name to avoid overly complicated checking.
+     */
+    public static Set<String> decomposeOneHash(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<>();
+        }
+
+        Set<String> elements = decomposeImpl(algorithm);
+
+        hasLoop(elements, "SHA-1", "SHA1");
+        hasLoop(elements, "SHA-224", "SHA224");
+        hasLoop(elements, "SHA-256", "SHA256");
+        hasLoop(elements, "SHA-384", "SHA384");
+        hasLoop(elements, "SHA-512", "SHA512");
+
+        return elements;
+    }
+
+    /*
+     * The provided message digest algorithm name will return a consistent
+     * naming scheme.
+     */
+    public static String hashName(String algorithm) {
+        return algorithm.replace("-", "");
+    }
 }
diff --git a/jdk/src/share/classes/sun/security/util/AnchorCertificates.java b/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
new file mode 100644
index 0000000..8498342
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/util/AnchorCertificates.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 sun.security.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.PrivilegedAction;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * The purpose of this class is to determine the trust anchor certificates is in
+ * the cacerts file.  This is used for PKIX CertPath checking.
+ */
+public class AnchorCertificates {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+    private static final String HASH = "SHA-256";
+    private static HashSet<String> certs;
+
+    static  {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                File f = new File(System.getProperty("java.home"),
+                        "lib/security/cacerts");
+                KeyStore cacerts;
+                try {
+                    cacerts = KeyStore.getInstance("JKS");
+                    try (FileInputStream fis = new FileInputStream(f)) {
+                        cacerts.load(fis, null);
+                        certs = new HashSet<>();
+                        Enumeration<String> list = cacerts.aliases();
+                        String alias;
+                        while (list.hasMoreElements()) {
+                            alias = list.nextElement();
+                            // Check if this cert is labeled a trust anchor.
+                            if (alias.contains(" [jdk")) {
+                                X509Certificate cert = (X509Certificate) cacerts
+                                        .getCertificate(alias);
+                                certs.add(X509CertImpl.getFingerprint(HASH, cert));
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    if (debug != null) {
+                        debug.println("Error parsing cacerts");
+                    }
+                    e.printStackTrace();
+                }
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Checks if a certificate is a trust anchor.
+     *
+     * @param cert the certificate to check
+     * @return true if the certificate is trusted.
+     */
+    public static boolean contains(X509Certificate cert) {
+        String key = X509CertImpl.getFingerprint(HASH, cert);
+        boolean result = certs.contains(key);
+        if (result && debug != null) {
+            debug.println("AnchorCertificate.contains: matched " +
+                    cert.getSubjectDN());
+        }
+        return result;
+    }
+
+    private AnchorCertificates() {}
+}
diff --git a/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java b/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java
new file mode 100644
index 0000000..9f7a938
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/util/CertConstraintParameters.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 sun.security.util;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This class is a wrapper for keeping state and passing objects between PKIX,
+ * AlgorithmChecker, and DisabledAlgorithmConstraints.
+ */
+public class CertConstraintParameters {
+    // A certificate being passed to check against constraints.
+    private final X509Certificate cert;
+
+    // This is true if the trust anchor in the certificate chain matches a cert
+    // in AnchorCertificates
+    private final boolean trustedMatch;
+
+    public CertConstraintParameters(X509Certificate c, boolean match) {
+        cert = c;
+        trustedMatch = match;
+    }
+
+    public CertConstraintParameters(X509Certificate c) {
+        this(c, false);
+    }
+
+    // Returns if the trust anchor has a match if anchor checking is enabled.
+    public boolean isTrustedMatch() {
+        return trustedMatch;
+    }
+
+    public X509Certificate getCertificate() {
+        return cert;
+    }
+}
diff --git a/jdk/src/share/classes/sun/security/util/DerInputBuffer.java b/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
index 786e791..7d3ad55 100644
--- a/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
+++ b/jdk/src/share/classes/sun/security/util/DerInputBuffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -147,6 +147,11 @@
         System.arraycopy(buf, pos, bytes, 0, len);
         skip(len);
 
+        // check to make sure no extra leading 0s for DER
+        if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) {
+            throw new IOException("Invalid encoding: redundant leading 0s");
+        }
+
         if (makePositive) {
             return new BigInteger(1, bytes);
         } else {
diff --git a/jdk/src/share/classes/sun/security/util/DerInputStream.java b/jdk/src/share/classes/sun/security/util/DerInputStream.java
index fc4aee8..5af3cf4 100644
--- a/jdk/src/share/classes/sun/security/util/DerInputStream.java
+++ b/jdk/src/share/classes/sun/security/util/DerInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
      * @param data the buffer from which to create the string (CONSUMED)
      */
     public DerInputStream(byte[] data) throws IOException {
-        init(data, 0, data.length);
+        init(data, 0, data.length, true);
     }
 
     /**
@@ -92,23 +92,48 @@
      *          starting at "offset"
      */
     public DerInputStream(byte[] data, int offset, int len) throws IOException {
-        init(data, offset, len);
+        init(data, offset, len, true);
+    }
+
+    /**
+     * Create a DER input stream from part of a data buffer with
+     * additional arg to indicate whether to allow constructed
+     * indefinite-length encoding.
+     * The buffer is not copied, it is shared.  Accordingly, the
+     * buffer should be treated as read-only.
+     *
+     * @param data the buffer from which to create the string (CONSUMED)
+     * @param offset the first index of <em>data</em> which will
+     *          be read as DER input in the new stream
+     * @param len how long a chunk of the buffer to use,
+     *          starting at "offset"
+     * @param allowIndefiniteLength whether to allow constructed
+     *          indefinite-length encoding
+     */
+    public DerInputStream(byte[] data, int offset, int len,
+        boolean allowIndefiniteLength) throws IOException {
+        init(data, offset, len, allowIndefiniteLength);
     }
 
     /*
      * private helper routine
      */
-    private void init(byte[] data, int offset, int len) throws IOException {
+    private void init(byte[] data, int offset, int len,
+        boolean allowIndefiniteLength) throws IOException {
         if ((offset+2 > data.length) || (offset+len > data.length)) {
             throw new IOException("Encoding bytes too short");
         }
         // check for indefinite length encoding
         if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
-            byte[] inData = new byte[len];
-            System.arraycopy(data, offset, inData, 0, len);
+            if (!allowIndefiniteLength) {
+                throw new IOException("Indefinite length BER encoding found");
+            } else {
+                byte[] inData = new byte[len];
+                System.arraycopy(data, offset, inData, 0, len);
 
-            DerIndefLenConverter derIn = new DerIndefLenConverter();
-            buffer = new DerInputBuffer(derIn.convert(inData));
+                DerIndefLenConverter derIn = new DerIndefLenConverter();
+                buffer = new DerInputBuffer(derIn.convert(inData));
+            }
         } else
             buffer = new DerInputBuffer(data, offset, len);
         buffer.mark(Integer.MAX_VALUE);
@@ -233,12 +258,21 @@
          * First byte = number of excess bits in the last octet of the
          * representation.
          */
-        int validBits = length*8 - buffer.read();
+        int excessBits = buffer.read();
+        if (excessBits < 0) {
+            throw new IOException("Unused bits of bit string invalid");
+        }
+        int validBits = length*8 - excessBits;
+        if (validBits < 0) {
+            throw new IOException("Valid bits of bit string invalid");
+        }
 
         byte[] repn = new byte[length];
 
-        if ((length != 0) && (buffer.read(repn) != length))
-            throw new IOException("short read of DER bit string");
+        if ((length != 0) && (buffer.read(repn) != length)) {
+            throw new IOException("Short read of DER bit string");
+        }
+
         return new BitArray(validBits, repn);
     }
 
@@ -252,7 +286,7 @@
         int length = getLength(buffer);
         byte[] retval = new byte[length];
         if ((length != 0) && (buffer.read(retval) != length))
-            throw new IOException("short read of DER octet string");
+            throw new IOException("Short read of DER octet string");
 
         return retval;
     }
@@ -262,7 +296,7 @@
      */
     public void getBytes(byte[] val) throws IOException {
         if ((val.length != 0) && (buffer.read(val) != val.length)) {
-            throw new IOException("short read of DER octet string");
+            throw new IOException("Short read of DER octet string");
         }
     }
 
@@ -346,7 +380,7 @@
         DerInputStream  newstr;
 
         byte lenByte = (byte)buffer.read();
-        int len = getLength((lenByte & 0xff), buffer);
+        int len = getLength(lenByte, buffer);
 
         if (len == -1) {
            // indefinite length encoding found
@@ -392,7 +426,7 @@
         } while (newstr.available() > 0);
 
         if (newstr.available() != 0)
-            throw new IOException("extra data at end of vector");
+            throw new IOException("Extra data at end of vector");
 
         /*
          * Now stick them into the array we're returning.
@@ -483,7 +517,7 @@
         int length = getLength(buffer);
         byte[] retval = new byte[length];
         if ((length != 0) && (buffer.read(retval) != length))
-            throw new IOException("short read of DER " +
+            throw new IOException("Short read of DER " +
                                   stringName + " string");
 
         return new String(retval, enc);
@@ -544,7 +578,11 @@
      */
     static int getLength(int lenByte, InputStream in) throws IOException {
         int value, tmp;
+        if (lenByte == -1) {
+            throw new IOException("Short read of DER length");
+        }
 
+        String mdName = "DerInputStream.getLength(): ";
         tmp = lenByte;
         if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
             value = tmp;
@@ -558,17 +596,23 @@
             if (tmp == 0)
                 return -1;
             if (tmp < 0 || tmp > 4)
-                throw new IOException("DerInputStream.getLength(): lengthTag="
-                    + tmp + ", "
+                throw new IOException(mdName + "lengthTag=" + tmp + ", "
                     + ((tmp < 0) ? "incorrect DER encoding." : "too big."));
 
-            for (value = 0; tmp > 0; tmp --) {
+            value = 0x0ff & in.read();
+            tmp--;
+            if (value == 0) {
+                // DER requires length value be encoded in minimum number of bytes
+                throw new IOException(mdName + "Redundant length bytes found");
+            }
+            while (tmp-- > 0) {
                 value <<= 8;
                 value += 0x0ff & in.read();
             }
             if (value < 0) {
-                throw new IOException("DerInputStream.getLength(): "
-                        + "Invalid length bytes");
+                throw new IOException(mdName + "Invalid length bytes");
+            } else if (value <= 127) {
+                throw new IOException(mdName + "Should use short form for length");
             }
         }
         return value;
diff --git a/jdk/src/share/classes/sun/security/util/DerValue.java b/jdk/src/share/classes/sun/security/util/DerValue.java
index beb51c1..8cd989b 100644
--- a/jdk/src/share/classes/sun/security/util/DerValue.java
+++ b/jdk/src/share/classes/sun/security/util/DerValue.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -249,7 +249,7 @@
 
         tag = (byte)in.read();
         byte lenByte = (byte)in.read();
-        length = DerInputStream.getLength((lenByte & 0xff), in);
+        length = DerInputStream.getLength(lenByte, in);
         if (length == -1) {  // indefinite length encoding found
             DerInputBuffer inbuf = in.dup();
             int readLen = inbuf.available();
@@ -362,7 +362,7 @@
 
         tag = (byte)in.read();
         byte lenByte = (byte)in.read();
-        length = DerInputStream.getLength((lenByte & 0xff), in);
+        length = DerInputStream.getLength(lenByte, in);
         if (length == -1) { // indefinite length encoding found
             int readLen = in.available();
             int offset = 2;     // for tag and length bytes
diff --git a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
index a102187..af1f99b 100644
--- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,14 @@
 import java.security.CryptoPrimitive;
 import java.security.AlgorithmParameters;
 import java.security.Key;
-import java.util.Locale;
-import java.util.Set;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.X509Certificate;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 
@@ -44,6 +46,7 @@
  * for the syntax of the disabled algorithm string.
  */
 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
+    private static final Debug debug = Debug.getInstance("certpath");
 
     // the known security property, jdk.certpath.disabledAlgorithms
     public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
@@ -53,17 +56,12 @@
     public final static String PROPERTY_TLS_DISABLED_ALGS =
             "jdk.tls.disabledAlgorithms";
 
-    private final static Map<String, String[]> disabledAlgorithmsMap =
-                                                            new HashMap<>();
-    private final static Map<String, KeySizeConstraints> keySizeConstraintsMap =
-                                                            new HashMap<>();
-
     // the known security property, jdk.jar.disabledAlgorithms
     public static final String PROPERTY_JAR_DISABLED_ALGS =
             "jdk.jar.disabledAlgorithms";
 
     private final String[] disabledAlgorithms;
-    private final KeySizeConstraints keySizeConstraints;
+    private final Constraints algorithmConstraints;
 
     /**
      * Initialize algorithm constraints with the specified security property.
@@ -86,11 +84,14 @@
     public DisabledAlgorithmConstraints(String propertyName,
             AlgorithmDecomposer decomposer) {
         super(decomposer);
-        disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName);
-        keySizeConstraints = getKeySizeConstraints(disabledAlgorithms,
-                propertyName);
+        disabledAlgorithms = getAlgorithms(propertyName);
+        algorithmConstraints = new Constraints(disabledAlgorithms);
     }
 
+    /*
+     * This only checks if the algorithm has been completely disabled.  If
+     * there are keysize or other limit, this method allow the algorithm.
+     */
     @Override
     final public boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, AlgorithmParameters parameters) {
@@ -103,11 +104,19 @@
         return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
     }
 
+    /*
+     * Checks if the key algorithm has been disabled or constraints have been
+     * placed on the key.
+     */
     @Override
     final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
         return checkConstraints(primitives, "", key, null);
     }
 
+    /*
+     * Checks if the key algorithm has been disabled or if constraints have
+     * been placed on the key.
+     */
     @Override
     final public boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, Key key, AlgorithmParameters parameters) {
@@ -119,7 +128,39 @@
         return checkConstraints(primitives, algorithm, key, parameters);
     }
 
-    // Check algorithm constraints
+    /*
+     * Check if a x509Certificate object is permitted.  Check if all
+     * algorithms are allowed, certificate constraints, and the
+     * public key against key constraints.
+     *
+     * Uses new style permit() which throws exceptions.
+     */
+    public final void permits(Set<CryptoPrimitive> primitives,
+            CertConstraintParameters cp) throws CertPathValidatorException {
+        checkConstraints(primitives, cp);
+    }
+
+    /*
+     * Check if Certificate object is within the constraints.
+     * Uses new style permit() which throws exceptions.
+     */
+    public final void permits(Set<CryptoPrimitive> primitives,
+            X509Certificate cert) throws CertPathValidatorException {
+        checkConstraints(primitives, new CertConstraintParameters(cert));
+    }
+
+    // Check if a string is contained inside the property
+    public boolean checkProperty(String param) {
+        param = param.toLowerCase(Locale.ENGLISH);
+        for (String block : disabledAlgorithms) {
+            if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // Check algorithm constraints with key and algorithm
     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
             String algorithm, Key key, AlgorithmParameters parameters) {
 
@@ -128,7 +169,7 @@
             throw new IllegalArgumentException("The key cannot be null");
         }
 
-        // check the target algorithm
+        // check the signature algorithm
         if (algorithm != null && algorithm.length() != 0) {
             if (!permits(primitives, algorithm, parameters)) {
                 return false;
@@ -141,97 +182,203 @@
         }
 
         // check the key constraints
-        if (keySizeConstraints.disables(key)) {
-            return false;
-        }
-
-        return true;
+        return algorithmConstraints.permits(key);
     }
 
-    private static KeySizeConstraints getKeySizeConstraints(
-            String[] disabledAlgorithms, String propertyName) {
-        synchronized (keySizeConstraintsMap) {
-            if(!keySizeConstraintsMap.containsKey(propertyName)) {
-                // map the key constraints
-                KeySizeConstraints keySizeConstraints =
-                        new KeySizeConstraints(disabledAlgorithms);
-                keySizeConstraintsMap.put(propertyName, keySizeConstraints);
-            }
+    /*
+     * Check algorithm constraints with Certificate
+     * Uses new style permit() which throws exceptions.
+     */
+    private void checkConstraints(Set<CryptoPrimitive> primitives,
+            CertConstraintParameters cp) throws CertPathValidatorException {
 
-            return keySizeConstraintsMap.get(propertyName);
+        X509Certificate cert = cp.getCertificate();
+        String algorithm = cert.getSigAlgName();
+
+        // Check signature algorithm is not disabled
+        if (!permits(primitives, algorithm, null)) {
+            throw new CertPathValidatorException(
+                    "Algorithm constraints check failed on disabled "+
+                            "signature algorithm: " + algorithm,
+                    null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
+
+        // Check key algorithm is not disabled
+        if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) {
+            throw new CertPathValidatorException(
+                    "Algorithm constraints check failed on disabled "+
+                            "public key algorithm: " + algorithm,
+                    null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+        }
+
+        // Check the certificate and key constraints
+        algorithmConstraints.permits(cp);
+
     }
 
     /**
-     * key constraints
+     * Key and Certificate Constraints
+     *
+     * The complete disabling of an algorithm is not handled by Constraints or
+     * Constraint classes.  That is addressed with
+     *   permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
+     *
+     * When passing a Key to permit(), the boolean return values follow the
+     * same as the interface class AlgorithmConstraints.permit().  This is to
+     * maintain compatibility:
+     * 'true' means the operation is allowed.
+     * 'false' means it failed the constraints and is disallowed.
+     *
+     * When passing CertConstraintParameters through permit(), an exception
+     * will be thrown on a failure to better identify why the operation was
+     * disallowed.
      */
-    private static class KeySizeConstraints {
-        private static final Pattern pattern = Pattern.compile(
-                "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
 
-        private Map<String, Set<KeySizeConstraint>> constraintsMap =
-            Collections.synchronizedMap(
-                        new HashMap<String, Set<KeySizeConstraint>>());
+    private static class Constraints {
+        private Map<String, Set<Constraint>> constraintsMap = new HashMap<>();
+        private static final Pattern keySizePattern = Pattern.compile(
+                "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
 
-        public KeySizeConstraints(String[] restrictions) {
-            for (String restriction : restrictions) {
-                if (restriction == null || restriction.isEmpty()) {
+        public Constraints(String[] constraintArray) {
+            for (String constraintEntry : constraintArray) {
+                if (constraintEntry == null || constraintEntry.isEmpty()) {
                     continue;
                 }
 
-                Matcher matcher = pattern.matcher(restriction);
-                if (matcher.matches()) {
-                    String algorithm = matcher.group(1);
+                constraintEntry = constraintEntry.trim();
+                if (debug != null) {
+                    debug.println("Constraints: " + constraintEntry);
+                }
 
-                    KeySizeConstraint.Operator operator =
-                             KeySizeConstraint.Operator.of(matcher.group(2));
-                    int length = Integer.parseInt(matcher.group(3));
+                // Check if constraint is a complete disabling of an
+                // algorithm or has conditions.
+                String algorithm;
+                String policy;
+                int space = constraintEntry.indexOf(' ');
+                if (space > 0) {
+                    algorithm = AlgorithmDecomposer.hashName(
+                            constraintEntry.substring(0, space).
+                                    toUpperCase(Locale.ENGLISH));
+                    policy = constraintEntry.substring(space + 1);
+                } else {
+                    constraintsMap.putIfAbsent(
+                            constraintEntry.toUpperCase(Locale.ENGLISH),
+                            new HashSet<>());
+                    continue;
+                }
 
-                    algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+                // Convert constraint conditions into Constraint classes
+                Constraint c = null;
+                Constraint lastConstraint = null;
+                // Allow only one jdkCA entry per constraint entry
+                boolean jdkCALimit = false;
 
-                    synchronized (constraintsMap) {
-                        if (!constraintsMap.containsKey(algorithm)) {
-                            constraintsMap.put(algorithm,
-                                new HashSet<KeySizeConstraint>());
+                for (String entry : policy.split("&")) {
+                    entry = entry.trim();
+
+                    Matcher matcher = keySizePattern.matcher(entry);
+                    if (matcher.matches()) {
+                        if (debug != null) {
+                            debug.println("Constraints set to keySize: " +
+                                    entry);
                         }
+                        c = new KeySizeConstraint(algorithm,
+                                KeySizeConstraint.Operator.of(matcher.group(1)),
+                                Integer.parseInt(matcher.group(2)));
 
-                        Set<KeySizeConstraint> constraintSet =
-                            constraintsMap.get(algorithm);
-                        KeySizeConstraint constraint =
-                            new KeySizeConstraint(operator, length);
-                        constraintSet.add(constraint);
+                    } else if (entry.equalsIgnoreCase("jdkCA")) {
+                        if (debug != null) {
+                            debug.println("Constraints set to jdkCA.");
+                        }
+                        if (jdkCALimit) {
+                            throw new IllegalArgumentException("Only one " +
+                                    "jdkCA entry allowed in property. " +
+                                    "Constraint: " + constraintEntry);
+                        }
+                        c = new jdkCAConstraint(algorithm);
+                        jdkCALimit = true;
                     }
+
+                    // Link multiple conditions for a single constraint
+                    // into a linked list.
+                    if (lastConstraint == null) {
+                        if (!constraintsMap.containsKey(algorithm)) {
+                            constraintsMap.putIfAbsent(algorithm,
+                                    new HashSet<>());
+                        }
+                        if (c != null) {
+                            constraintsMap.get(algorithm).add(c);
+                        }
+                    } else {
+                        lastConstraint.nextConstraint = c;
+                    }
+                    lastConstraint = c;
                 }
             }
         }
 
-        // Does this KeySizeConstraints disable the specified key?
-        public boolean disables(Key key) {
-            String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
-            synchronized (constraintsMap) {
-                if (constraintsMap.containsKey(algorithm)) {
-                    Set<KeySizeConstraint> constraintSet =
-                                        constraintsMap.get(algorithm);
-                    for (KeySizeConstraint constraint : constraintSet) {
-                        if (constraint.disables(key)) {
-                            return true;
-                        }
-                    }
-                }
-            }
+        // Get applicable constraints based off the signature algorithm
+        private Set<Constraint> getConstraints(String algorithm) {
+            return constraintsMap.get(algorithm);
+        }
 
+        // Check if KeySizeConstraints permit the specified key
+        public boolean permits(Key key) {
+            Set<Constraint> set = getConstraints(key.getAlgorithm());
+            if (set == null) {
+                return true;
+            }
+            for (Constraint constraint : set) {
+                if (!constraint.permits(key)) {
+                    if (debug != null) {
+                        debug.println("keySizeConstraint: failed key " +
+                                "constraint check " + KeyUtil.getKeySize(key));
+                    }
             return false;
         }
+            }
+        return true;
     }
 
-    /**
-     * Key size constraint.
-     *
-     * e.g.  "keysize <= 1024"
-     */
-    private static class KeySizeConstraint {
+        // Check if constraints permit this cert.
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            X509Certificate cert = cp.getCertificate();
+
+            if (debug != null) {
+                debug.println("Constraints.permits(): " + cert.getSigAlgName());
+            }
+
+            // Get all signature algorithms to check for constraints
+            Set<String> algorithms =
+                    AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName());
+            if (algorithms == null || algorithms.isEmpty()) {
+                return;
+    }
+
+            // Attempt to add the public key algorithm to the set
+            algorithms.add(cert.getPublicKey().getAlgorithm());
+
+            // Check all applicable constraints
+            for (String algorithm : algorithms) {
+                Set<Constraint> set = getConstraints(algorithm);
+                if (set == null) {
+                    continue;
+                }
+                for (Constraint constraint : set) {
+                    constraint.permits(cp);
+                }
+            }
+        }
+                        }
+
+    // Abstract class for algorithm constraint checking
+    private abstract static class Constraint {
+        String algorithm;
+        Constraint nextConstraint = null;
+
         // operator
-        static enum Operator {
+        enum Operator {
             EQ,         // "=="
             NE,         // "!="
             LT,         // "<"
@@ -255,16 +402,77 @@
                         return GE;
                 }
 
-                throw new IllegalArgumentException(
-                        s + " is not a legal Operator");
+                throw new IllegalArgumentException("Error in security " +
+                        "property. " + s + " is not a legal Operator");
             }
         }
 
+        /**
+         * Check if an algorithm constraint permit this key to be used.
+         * @param key Public key
+         * @return true if constraints do not match
+         */
+        public boolean permits(Key key) {
+            return true;
+        }
+
+        /**
+         * Check if an algorithm constraint is permit this certificate to
+         * be used.
+         * @param cp CertificateParameter containing certificate and state info
+         * @return true if constraints do not match
+         */
+        public abstract void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException;
+    }
+
+    /*
+     * This class contains constraints dealing with the certificate chain
+     * of the certificate.
+     */
+    private static class jdkCAConstraint extends Constraint {
+        jdkCAConstraint(String algo) {
+            algorithm = algo;
+        }
+
+        /*
+         * Check if each constraint fails and check if there is a linked
+         * constraint  Any permitted constraint will exit the linked list
+         * to allow the operation.
+         */
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            if (debug != null) {
+                debug.println("jdkCAConstraints.permits(): " + algorithm);
+            }
+
+            // Return false if the chain has a trust anchor in cacerts
+            if (cp.isTrustedMatch()) {
+                if (nextConstraint != null) {
+                    nextConstraint.permits(cp);
+                    return;
+                }
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on certificate " +
+                                "anchor limits",
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
+        }
+    }
+
+
+    /*
+     * This class contains constraints dealing with the key size
+     * support limits per algorithm.   e.g.  "keySize <= 1024"
+     */
+    private static class KeySizeConstraint extends Constraint {
+
         private int minSize;            // the minimal available key size
         private int maxSize;            // the maximal available key size
         private int prohibitedSize = -1;    // unavailable key sizes
 
-        public KeySizeConstraint(Operator operator, int length) {
+        public KeySizeConstraint(String algo, Operator operator, int length) {
+            algorithm = algo;
             switch (operator) {
                 case EQ:      // an unavailable key size
                     this.minSize = 0;
@@ -298,21 +506,59 @@
             }
         }
 
-        // Does this key constraint disable the specified key?
-        public boolean disables(Key key) {
-            int size = KeyUtil.getKeySize(key);
+        /*
+         * If we are passed a certificate, extract the public key and use it.
+         *
+         * Check if each constraint fails and check if there is a linked
+         * constraint  Any permitted constraint will exit the linked list
+         * to allow the operation.
+         */
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            if (!permitsImpl(cp.getCertificate().getPublicKey())) {
+                if (nextConstraint != null) {
+                    nextConstraint.permits(cp);
+                    return;
+                }
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on keysize limits",
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
+        }
 
+
+        // Check if key constraint disable the specified key
+        // Uses old style permit()
+        public boolean permits(Key key) {
+            // If we recursively find a constraint that permits us to use
+            // this key, return true and skip any other constraint checks.
+            if (nextConstraint != null && nextConstraint.permits(key)) {
+                return true;
+            }
+            if (debug != null) {
+                debug.println("KeySizeConstraints.permits(): " + algorithm);
+            }
+
+            return permitsImpl(key);
+        }
+
+        private boolean permitsImpl(Key key) {
+            // Verify this constraint is for this public key algorithm
+            if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
+                return true;
+            }
+
+            int size = KeyUtil.getKeySize(key);
             if (size == 0) {
-                return true;    // we don't allow any key of size 0.
+                return false;    // we don't allow any key of size 0.
             } else if (size > 0) {
-                return ((size < minSize) || (size > maxSize) ||
+                return !((size < minSize) || (size > maxSize) ||
                     (prohibitedSize == size));
             }   // Otherwise, the key size is not accessible. Conservatively,
                 // please don't disable such keys.
 
-            return false;
+            return true;
+        }
         }
     }
 
-}
-
diff --git a/jdk/src/share/classes/sun/security/util/KeyUtil.java b/jdk/src/share/classes/sun/security/util/KeyUtil.java
index 67a9e45..9a4d0b4 100644
--- a/jdk/src/share/classes/sun/security/util/KeyUtil.java
+++ b/jdk/src/share/classes/sun/security/util/KeyUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 import java.security.interfaces.ECKey;
 import java.security.interfaces.RSAKey;
 import java.security.interfaces.DSAKey;
+import java.security.interfaces.DSAParams;
 import java.security.SecureRandom;
 import java.security.spec.KeySpec;
 import javax.crypto.SecretKey;
@@ -87,7 +88,8 @@
             size = pubk.getParams().getOrder().bitLength();
         } else if (key instanceof DSAKey) {
             DSAKey pubk = (DSAKey)key;
-            size = pubk.getParams().getP().bitLength();
+            DSAParams params = pubk.getParams();    // params can be null
+            size = (params != null) ? params.getP().bitLength() : -1;
         } else if (key instanceof DHKey) {
             DHKey pubk = (DHKey)key;
             size = pubk.getParams().getP().bitLength();
diff --git a/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java b/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
index 106ec78..ea688da 100644
--- a/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
+++ b/jdk/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import java.security.AlgorithmParameters;
 import java.security.CryptoPrimitive;
 import java.security.Key;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Set;
 import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms;
 
@@ -42,15 +40,12 @@
     public final static String PROPERTY_TLS_LEGACY_ALGS =
             "jdk.tls.legacyAlgorithms";
 
-    private final static Map<String, String[]> legacyAlgorithmsMap =
-                                                          new HashMap<>();
-
     private final String[] legacyAlgorithms;
 
     public LegacyAlgorithmConstraints(String propertyName,
             AlgorithmDecomposer decomposer) {
         super(decomposer);
-        legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName);
+        legacyAlgorithms = getAlgorithms(propertyName);
     }
 
     @Override
diff --git a/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java b/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
index 66038a3..97dc9c5 100644
--- a/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
+++ b/jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
@@ -255,7 +255,13 @@
                 + " (tag = " +  type_id + ")"
                 );
 
-        encoding = new byte[in.getLength()];
+        int len = in.getLength();
+        if (len > in.available()) {
+            throw new IOException("ObjectIdentifier() -- length exceeds" +
+                    "data available.  Length: " + len + ", Available: " +
+                    in.available());
+        }
+        encoding = new byte[len];
         in.getBytes(encoding);
         check(encoding);
     }
diff --git a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
index fdbdd3c..ab1c450 100644
--- a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
+++ b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java
@@ -1932,18 +1932,19 @@
 
     public String getFingerprint(String algorithm) {
         return fingerprints.computeIfAbsent(algorithm,
-                x -> getCertificateFingerPrint(x));
+                x -> getFingerprint(x, this));
     }
 
     /**
      * Gets the requested finger print of the certificate. The result
      * only contains 0-9 and A-F. No small case, no colon.
      */
-    private String getCertificateFingerPrint(String mdAlg) {
+    public static String getFingerprint(String algorithm,
+            X509Certificate cert) {
         String fingerPrint = "";
         try {
-            byte[] encCertInfo = getEncoded();
-            MessageDigest md = MessageDigest.getInstance(mdAlg);
+            byte[] encCertInfo = cert.getEncoded();
+            MessageDigest md = MessageDigest.getInstance(algorithm);
             byte[] digest = md.digest(encCertInfo);
             StringBuffer buf = new StringBuffer();
             for (int i = 0; i < digest.length; i++) {
diff --git a/jdk/src/share/lib/security/java.security-aix b/jdk/src/share/lib/security/java.security-aix
index ae47914..8f9cf76 100644
--- a/jdk/src/share/lib/security/java.security-aix
+++ b/jdk/src/share/lib/security/java.security-aix
@@ -429,13 +429,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -452,6 +452,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -474,6 +477,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted.  jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -481,7 +507,45 @@
 #   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
 #
 #
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+    DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation.  For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm.  This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator KeyLength
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
 
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
 # (SSL/TLS) processing
@@ -504,12 +568,13 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+    EC keySize < 224
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -523,7 +588,7 @@
 # During SSL/TLS security parameters negotiation, legacy algorithms will
 # not be negotiated unless there are no other candidates.
 #
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
 # BNF-style:
 #   LegacyAlgorithms:
 #       " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -553,7 +618,7 @@
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 # There is no guarantee the property will continue to exist or be of the
 # same syntax in future releases.
@@ -566,7 +631,8 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
+        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+        3DES_EDE_CBC
 
 # The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
 # parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -625,39 +691,111 @@
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
 
-# Algorithm restrictions for signed JAR files
 #
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation.  For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm.  This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
 #
-# The syntax of the disabled algorithm string is described as follows:
-#   DisabledAlgorithms:
-#       " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-#   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
-#
-#   AlgorithmName:
-#       (see below)
-#
+#   Policy:
+#       Constraint {"," Constraint }
 #   Constraint:
-#       KeySizeConstraint
-#
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
 #   KeySizeConstraint:
-#       keySize Operator KeyLength
+#       "minKeySize" KeyAlg Integer
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
 #
-#   Operator:
-#       <= | < | == | != | >= | >
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
 #
-#   KeyLength:
-#       Integer value of the algorithm's key length in bits
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
 #
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    minKeySize RSA 1024,\
+    minKeySize DSA 1024,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
+
 #
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+#   maxdepth=value - the maximum depth of a graph
+#   maxrefs=value  - the maximum number of internal references
+#   maxbytes=value - the maximum number of bytes in the input stream
+#   maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+#   is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+#    java.rmi.server.ObjID;\
+#    java.rmi.server.UID;\
+#    java.rmi.dgc.VMID;\
+#    java.rmi.dgc.Lease;\
+#    maxdepth=5;maxarray=10000
diff --git a/jdk/src/share/lib/security/java.security-linux b/jdk/src/share/lib/security/java.security-linux
index ae47914..fb18f70 100644
--- a/jdk/src/share/lib/security/java.security-linux
+++ b/jdk/src/share/lib/security/java.security-linux
@@ -429,13 +429,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -452,6 +452,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -474,6 +477,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted.  jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following:  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -481,7 +507,45 @@
 #   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
 #
 #
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+    DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation.  For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm.  This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator KeyLength
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
 
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
 # (SSL/TLS) processing
@@ -504,12 +568,13 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+    EC keySize < 224
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -523,7 +588,7 @@
 # During SSL/TLS security parameters negotiation, legacy algorithms will
 # not be negotiated unless there are no other candidates.
 #
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
 # BNF-style:
 #   LegacyAlgorithms:
 #       " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -553,7 +618,7 @@
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 # There is no guarantee the property will continue to exist or be of the
 # same syntax in future releases.
@@ -566,7 +631,8 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
+        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+        3DES_EDE_CBC
 
 # The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
 # parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -625,39 +691,111 @@
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
 
-# Algorithm restrictions for signed JAR files
 #
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation.  For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm.  This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
 #
-# The syntax of the disabled algorithm string is described as follows:
-#   DisabledAlgorithms:
-#       " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-#   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
-#
-#   AlgorithmName:
-#       (see below)
-#
+#   Policy:
+#       Constraint {"," Constraint }
 #   Constraint:
-#       KeySizeConstraint
-#
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
 #   KeySizeConstraint:
-#       keySize Operator KeyLength
+#       "minKeySize" KeyAlg Integer
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
 #
-#   Operator:
-#       <= | < | == | != | >= | >
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
 #
-#   KeyLength:
-#       Integer value of the algorithm's key length in bits
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
 #
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    minKeySize RSA 1024,\
+    minKeySize DSA 1024,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
+
 #
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+#   maxdepth=value - the maximum depth of a graph
+#   maxrefs=value  - the maximum number of internal references
+#   maxbytes=value - the maximum number of bytes in the input stream
+#   maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+#   is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+#    java.rmi.server.ObjID;\
+#    java.rmi.server.UID;\
+#    java.rmi.dgc.VMID;\
+#    java.rmi.dgc.Lease;\
+#    maxdepth=5;maxarray=10000
diff --git a/jdk/src/share/lib/security/java.security-macosx b/jdk/src/share/lib/security/java.security-macosx
index 2e25f91..ef02672 100644
--- a/jdk/src/share/lib/security/java.security-macosx
+++ b/jdk/src/share/lib/security/java.security-macosx
@@ -432,13 +432,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -455,6 +455,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -477,6 +480,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted. jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following:  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -484,7 +510,45 @@
 #   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
 #
 #
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+    DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation.  For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm.  This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator KeyLength
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
 
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
 # (SSL/TLS) processing
@@ -507,12 +571,13 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+    EC keySize < 224
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -526,7 +591,7 @@
 # During SSL/TLS security parameters negotiation, legacy algorithms will
 # not be negotiated unless there are no other candidates.
 #
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
 # BNF-style:
 #   LegacyAlgorithms:
 #       " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -556,7 +621,7 @@
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 # There is no guarantee the property will continue to exist or be of the
 # same syntax in future releases.
@@ -569,7 +634,8 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
+        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+        3DES_EDE_CBC
 
 # The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
 # parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -628,39 +694,111 @@
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
 
-# Algorithm restrictions for signed JAR files
 #
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation.  For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm.  This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
 #
-# The syntax of the disabled algorithm string is described as follows:
-#   DisabledAlgorithms:
-#       " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-#   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
-#
-#   AlgorithmName:
-#       (see below)
-#
+#   Policy:
+#       Constraint {"," Constraint }
 #   Constraint:
-#       KeySizeConstraint
-#
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
 #   KeySizeConstraint:
-#       keySize Operator KeyLength
+#       "minKeySize" KeyAlg Integer
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
 #
-#   Operator:
-#       <= | < | == | != | >= | >
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
 #
-#   KeyLength:
-#       Integer value of the algorithm's key length in bits
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
 #
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    minKeySize RSA 1024,\
+    minKeySize DSA 1024,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
+
 #
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+#   maxdepth=value - the maximum depth of a graph
+#   maxrefs=value  - the maximum number of internal references
+#   maxbytes=value - the maximum number of bytes in the input stream
+#   maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+#   is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+#    java.rmi.server.ObjID;\
+#    java.rmi.server.UID;\
+#    java.rmi.dgc.VMID;\
+#    java.rmi.dgc.Lease;\
+#    maxdepth=5;maxarray=10000
diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris
index 078fd66..537386c 100644
--- a/jdk/src/share/lib/security/java.security-solaris
+++ b/jdk/src/share/lib/security/java.security-solaris
@@ -431,13 +431,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -454,6 +454,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -476,6 +479,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted. jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following:  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -483,7 +509,45 @@
 #   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
 #
 #
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+    DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation.  For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm.  This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator KeyLength
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
 
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
 # (SSL/TLS) processing
@@ -506,12 +570,13 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+    EC keySize < 224
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -525,7 +590,7 @@
 # During SSL/TLS security parameters negotiation, legacy algorithms will
 # not be negotiated unless there are no other candidates.
 #
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
 # BNF-style:
 #   LegacyAlgorithms:
 #       " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -555,7 +620,7 @@
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 # There is no guarantee the property will continue to exist or be of the
 # same syntax in future releases.
@@ -568,7 +633,8 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
+        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+        3DES_EDE_CBC
 
 # The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
 # parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -627,39 +693,111 @@
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
 
-# Algorithm restrictions for signed JAR files
 #
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation.  For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm.  This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
 #
-# The syntax of the disabled algorithm string is described as follows:
-#   DisabledAlgorithms:
-#       " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-#   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
-#
-#   AlgorithmName:
-#       (see below)
-#
+#   Policy:
+#       Constraint {"," Constraint }
 #   Constraint:
-#       KeySizeConstraint
-#
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
 #   KeySizeConstraint:
-#       keySize Operator KeyLength
+#       "minKeySize" KeyAlg Integer
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
 #
-#   Operator:
-#       <= | < | == | != | >= | >
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
 #
-#   KeyLength:
-#       Integer value of the algorithm's key length in bits
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
 #
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    minKeySize RSA 1024,\
+    minKeySize DSA 1024,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
+
 #
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+#   maxdepth=value - the maximum depth of a graph
+#   maxrefs=value  - the maximum number of internal references
+#   maxbytes=value - the maximum number of bytes in the input stream
+#   maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+#   is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+#    java.rmi.server.ObjID;\
+#    java.rmi.server.UID;\
+#    java.rmi.dgc.VMID;\
+#    java.rmi.dgc.Lease;\
+#    maxdepth=5;maxarray=10000
diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows
index d2ddbe5..7bdda16 100644
--- a/jdk/src/share/lib/security/java.security-windows
+++ b/jdk/src/share/lib/security/java.security-windows
@@ -432,13 +432,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -455,6 +455,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -477,6 +480,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted.  jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following:  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -484,7 +510,45 @@
 #   jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048
 #
 #
-jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
+jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
+    DSA keySize < 1024, EC keySize < 224
+
+# Algorithm restrictions for signed JAR files
+#
+# In some environments, certain algorithms or key lengths may be undesirable
+# for signed JAR validation.  For example, "MD2" is generally no longer
+# considered to be a secure hash algorithm.  This section describes the
+# mechanism for disabling algorithms based on algorithm name and/or key length.
+# JARs signed with any of the disabled algorithms or key sizes will be treated
+# as unsigned.
+#
+# The syntax of the disabled algorithm string is described as follows:
+#   DisabledAlgorithms:
+#       " DisabledAlgorithm { , DisabledAlgorithm } "
+#
+#   DisabledAlgorithm:
+#       AlgorithmName [Constraint]
+#
+#   AlgorithmName:
+#       (see below)
+#
+#   Constraint:
+#       KeySizeConstraint
+#
+#   KeySizeConstraint:
+#       keySize Operator KeyLength
+#
+#   Operator:
+#       <= | < | == | != | >= | >
+#
+#   KeyLength:
+#       Integer value of the algorithm's key length in bits
+#
+# Note: This property is currently used by the JDK Reference
+# implementation. It is not guaranteed to be examined and used by other
+# implementations.
+#
+jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
 
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
 # (SSL/TLS) processing
@@ -507,12 +571,13 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768
+jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \
+    EC keySize < 224
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -526,7 +591,7 @@
 # During SSL/TLS security parameters negotiation, legacy algorithms will
 # not be negotiated unless there are no other candidates.
 #
-# The syntax of the disabled algorithm string is described as this Java
+# The syntax of the legacy algorithms string is described as this Java
 # BNF-style:
 #   LegacyAlgorithms:
 #       " LegacyAlgorithm { , LegacyAlgorithm } "
@@ -556,7 +621,7 @@
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
 #
-# Note: This property is currently used by Oracle's JSSE implementation.
+# Note: This property is currently used by the JDK Reference implementation.
 # It is not guaranteed to be examined and used by other implementations.
 # There is no guarantee the property will continue to exist or be of the
 # same syntax in future releases.
@@ -569,7 +634,8 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
+        RC4_128, RC4_40, DES_CBC, DES40_CBC, \
+        3DES_EDE_CBC
 
 # The pre-defined default finite field Diffie-Hellman ephemeral (DHE)
 # parameters for Transport Layer Security (SSL/TLS/DTLS) processing.
@@ -628,39 +694,111 @@
 #       EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \
 #       FFFFFFFF FFFFFFFF, 2}
 
-# Algorithm restrictions for signed JAR files
 #
-# In some environments, certain algorithms or key lengths may be undesirable
-# for signed JAR validation.  For example, "MD2" is generally no longer
-# considered to be a secure hash algorithm.  This section describes the
-# mechanism for disabling algorithms based on algorithm name and/or key length.
-# JARs signed with any of the disabled algorithms or key sizes will be treated
-# as unsigned.
+# The policy for the XML Signature secure validation mode. The mode is
+# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to
+# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method,
+# or by running the code with a SecurityManager.
 #
-# The syntax of the disabled algorithm string is described as follows:
-#   DisabledAlgorithms:
-#       " DisabledAlgorithm { , DisabledAlgorithm } "
-#
-#   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
-#
-#   AlgorithmName:
-#       (see below)
-#
+#   Policy:
+#       Constraint {"," Constraint }
 #   Constraint:
-#       KeySizeConstraint
-#
+#       AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint |
+#       ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint
+#   AlgConstraint
+#       "disallowAlg" Uri
+#   MaxTransformsConstraint:
+#       "maxTransforms" Integer
+#   MaxReferencesConstraint:
+#       "maxReferences" Integer
+#   ReferenceUriSchemeConstraint:
+#       "disallowReferenceUriSchemes" String { String }
 #   KeySizeConstraint:
-#       keySize Operator KeyLength
+#       "minKeySize" KeyAlg Integer
+#   OtherConstraint:
+#       "noDuplicateIds" | "noRetrievalMethodLoops"
 #
-#   Operator:
-#       <= | < | == | != | >= | >
+# For AlgConstraint, Uri is the algorithm URI String that is not allowed.
+# See the XML Signature Recommendation for more information on algorithm
+# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm
+# name of the key type (ex: "RSA"). If the MaxTransformsConstraint,
+# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is
+# specified more than once, only the last entry is enforced.
 #
-#   KeyLength:
-#       Integer value of the algorithm's key length in bits
+# Note: This property is currently used by the JDK Reference implementation. It
+# is not guaranteed to be examined and used by other implementations.
 #
-# Note: This property is currently used by the JDK Reference
-# implementation. It is not guaranteed to be examined and used by other
-# implementations.
+jdk.xml.dsig.secureValidationPolicy=\
+    disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\
+    disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\
+    maxTransforms 5,\
+    maxReferences 30,\
+    disallowReferenceUriSchemes file http https,\
+    minKeySize RSA 1024,\
+    minKeySize DSA 1024,\
+    noDuplicateIds,\
+    noRetrievalMethodLoops
+
 #
-jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024
+# Serialization process-wide filter
+#
+# A filter, if configured, is used by java.io.ObjectInputStream during
+# deserialization to check the contents of the stream.
+# A filter is configured as a sequence of patterns, each pattern is either
+# matched against the name of a class in the stream or defines a limit.
+# Patterns are separated by ";" (semicolon).
+# Whitespace is significant and is considered part of the pattern.
+#
+# If a pattern includes a "=", it sets a limit.
+# If a limit appears more than once the last value is used.
+# Limits are checked before classes regardless of the order in the sequence of patterns.
+# If any of the limits are exceeded, the filter status is REJECTED.
+#
+#   maxdepth=value - the maximum depth of a graph
+#   maxrefs=value  - the maximum number of internal references
+#   maxbytes=value - the maximum number of bytes in the input stream
+#   maxarray=value - the maximum array length allowed
+#
+# Other patterns, from left to right, match the class or package name as
+# returned from Class.getName.
+# If the class is an array type, the class or package to be matched is the element type.
+# Arrays of any number of dimensions are treated the same as the element type.
+# For example, a pattern of "!example.Foo", rejects creation of any instance or
+# array of example.Foo.
+#
+# If the pattern starts with "!", the status is REJECTED if the remaining pattern
+#   is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".*" it matches any class in the package.
+# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern is equal to the class name, it matches.
+# Otherwise, the status is UNDECIDED.
+#
+#jdk.serialFilter=pattern;pattern
+
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+#    java.rmi.server.ObjID;\
+#    java.rmi.server.UID;\
+#    java.rmi.dgc.VMID;\
+#    java.rmi.dgc.Lease;\
+#    maxdepth=5;maxarray=10000
diff --git a/jdk/src/share/native/sun/security/ec/impl/ec.c b/jdk/src/share/native/sun/security/ec/impl/ec.c
index 2f26390..2561237 100644
--- a/jdk/src/share/native/sun/security/ec/impl/ec.c
+++ b/jdk/src/share/native/sun/security/ec/impl/ec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -34,7 +34,7 @@
  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
- * Last Modified Date from the Original Code: April 2015
+ * Last Modified Date from the Original Code: November 2016
  *********************************************************************** */
 
 #include "mplogic.h"
@@ -714,6 +714,16 @@
     }
 
     /*
+     * Using an equivalent exponent of fixed length (same as n or 1 bit less
+     * than n) to keep the kG timing relatively constant.
+     *
+     * Note that this is an extra step on top of the approach defined in
+     * ANSI X9.62 so as to make a fixed length K.
+     */
+    CHECK_MPI_OK( mp_add(&k, &n, &k) );
+    CHECK_MPI_OK( mp_div_2(&k, &k) );
+
+    /*
     ** ANSI X9.62, Section 5.3.2, Step 2
     **
     ** Compute kG
diff --git a/jdk/src/solaris/native/java/net/SocketOutputStream.c b/jdk/src/solaris/native/java/net/SocketOutputStream.c
index d6e01ff..16d68c2 100644
--- a/jdk/src/solaris/native/java/net/SocketOutputStream.c
+++ b/jdk/src/solaris/native/java/net/SocketOutputStream.c
@@ -103,31 +103,35 @@
         int llen = chunkLen;
         (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
 
-        while(llen > 0) {
-            int n = NET_Send(fd, bufP + loff, llen, 0);
-            if (n > 0) {
-                llen -= n;
-                loff += n;
-                continue;
-            }
-            if (n == JVM_IO_INTR) {
-                JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
-            } else {
-                if (errno == ECONNRESET) {
-                    JNU_ThrowByName(env, "sun/net/ConnectionResetException",
-                        "Connection reset");
-                } else {
-                    NET_ThrowByNameWithLastError(env, "java/net/SocketException",
-                        "Write failed");
+        if ((*env)->ExceptionCheck(env)) {
+            break;
+        } else {
+            while(llen > 0) {
+                int n = NET_Send(fd, bufP + loff, llen, 0);
+                if (n > 0) {
+                    llen -= n;
+                    loff += n;
+                    continue;
                 }
+                if (n == JVM_IO_INTR) {
+                    JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
+                } else {
+                    if (errno == ECONNRESET) {
+                        JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+                            "Connection reset");
+                    } else {
+                        NET_ThrowByNameWithLastError(env, "java/net/SocketException",
+                            "Write failed");
+                    }
+                }
+                if (bufP != BUF) {
+                    free(bufP);
+                }
+                return;
             }
-            if (bufP != BUF) {
-                free(bufP);
-            }
-            return;
+            len -= chunkLen;
+            off += chunkLen;
         }
-        len -= chunkLen;
-        off += chunkLen;
     }
 
     if (bufP != BUF) {
diff --git a/jdk/src/windows/native/java/net/SocketOutputStream.c b/jdk/src/windows/native/java/net/SocketOutputStream.c
index 4bcfbc3..daec520 100644
--- a/jdk/src/windows/native/java/net/SocketOutputStream.c
+++ b/jdk/src/windows/native/java/net/SocketOutputStream.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,66 +100,69 @@
         int retry = 0;
 
         (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
-
-        while(llen > 0) {
-            int n = send(fd, bufP + loff, llen, 0);
-            if (n > 0) {
-                llen -= n;
-                loff += n;
-                continue;
-            }
-
-            /*
-             * Due to a bug in Windows Sockets (observed on NT and Windows
-             * 2000) it may be necessary to retry the send. The issue is that
-             * on blocking sockets send/WSASend is supposed to block if there
-             * is insufficient buffer space available. If there are a large
-             * number of threads blocked on write due to congestion then it's
-             * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
-             * The workaround we use is to retry the send. If we have a
-             * large buffer to send (>2k) then we retry with a maximum of
-             * 2k buffer. If we hit the issue with <=2k buffer then we backoff
-             * for 1 second and retry again. We repeat this up to a reasonable
-             * limit before bailing out and throwing an exception. In load
-             * conditions we've observed that the send will succeed after 2-3
-             * attempts but this depends on network buffers associated with
-             * other sockets draining.
-             */
-            if (WSAGetLastError() == WSAENOBUFS) {
-                if (llen > MAX_BUFFER_LEN) {
-                    buflen = MAX_BUFFER_LEN;
-                    chunkLen = MAX_BUFFER_LEN;
-                    llen = MAX_BUFFER_LEN;
+        if ((*env)->ExceptionCheck(env)) {
+            break;
+        } else {
+            while(llen > 0) {
+                int n = send(fd, bufP + loff, llen, 0);
+                if (n > 0) {
+                    llen -= n;
+                    loff += n;
                     continue;
                 }
-                if (retry >= 30) {
-                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "No buffer space available - exhausted attempts to queue buffer");
-                    if (bufP != BUF) {
-                        free(bufP);
-                    }
-                    return;
-                }
-                Sleep(1000);
-                retry++;
-                continue;
-            }
 
-            /*
-             * Send failed - can be caused by close or write error.
-             */
-            if (WSAGetLastError() == WSAENOTSOCK) {
-                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
-            } else {
-                NET_ThrowCurrent(env, "socket write error");
+                /*
+                 * Due to a bug in Windows Sockets (observed on NT and Windows
+                 * 2000) it may be necessary to retry the send. The issue is that
+                 * on blocking sockets send/WSASend is supposed to block if there
+                 * is insufficient buffer space available. If there are a large
+                 * number of threads blocked on write due to congestion then it's
+                 * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
+                 * The workaround we use is to retry the send. If we have a
+                 * large buffer to send (>2k) then we retry with a maximum of
+                 * 2k buffer. If we hit the issue with <=2k buffer then we backoff
+                 * for 1 second and retry again. We repeat this up to a reasonable
+                 * limit before bailing out and throwing an exception. In load
+                 * conditions we've observed that the send will succeed after 2-3
+                 * attempts but this depends on network buffers associated with
+                 * other sockets draining.
+                 */
+                if (WSAGetLastError() == WSAENOBUFS) {
+                    if (llen > MAX_BUFFER_LEN) {
+                        buflen = MAX_BUFFER_LEN;
+                        chunkLen = MAX_BUFFER_LEN;
+                        llen = MAX_BUFFER_LEN;
+                        continue;
+                    }
+                    if (retry >= 30) {
+                        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                            "No buffer space available - exhausted attempts to queue buffer");
+                        if (bufP != BUF) {
+                            free(bufP);
+                        }
+                        return;
+                    }
+                    Sleep(1000);
+                    retry++;
+                    continue;
+                }
+
+                /*
+                 * Send failed - can be caused by close or write error.
+                 */
+                if (WSAGetLastError() == WSAENOTSOCK) {
+                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+                } else {
+                    NET_ThrowCurrent(env, "socket write error");
+                }
+                if (bufP != BUF) {
+                    free(bufP);
+                }
+                return;
             }
-            if (bufP != BUF) {
-                free(bufP);
-            }
-            return;
+            len -= chunkLen;
+            off += chunkLen;
         }
-        len -= chunkLen;
-        off += chunkLen;
     }
 
     if (bufP != BUF) {
diff --git a/jdk/src/windows/native/sun/windows/awt_Component.cpp b/jdk/src/windows/native/sun/windows/awt_Component.cpp
index 0128972..9d239a0 100644
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp
@@ -98,7 +98,6 @@
 HWND AwtComponent::sm_focusOwner = NULL;
 HWND AwtComponent::sm_focusedWindow = NULL;
 BOOL AwtComponent::sm_bMenuLoop = FALSE;
-AwtComponent* AwtComponent::sm_getComponentCache = NULL;
 BOOL AwtComponent::sm_inSynthesizeFocus = FALSE;
 
 /************************************************************************/
@@ -272,10 +271,6 @@
      * handle.
      */
     DestroyHWnd();
-
-    if (sm_getComponentCache == this) {
-        sm_getComponentCache = NULL;
-    }
 }
 
 void AwtComponent::Dispose()
@@ -348,9 +343,6 @@
     if (hWnd == AwtToolkit::GetInstance().GetHWnd()) {
         return NULL;
     }
-    if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) {
-        return sm_getComponentCache;
-    }
 
     // check that it's an AWT component from the same toolkit as the caller
     if (::IsWindow(hWnd) &&
@@ -358,7 +350,7 @@
     {
         DASSERT(WmAwtIsComponent != 0);
         if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) {
-            return sm_getComponentCache = GetComponentImpl(hWnd);
+            return GetComponentImpl(hWnd);
         }
     }
     return NULL;
diff --git a/jdk/test/java/awt/Frame/NormalToIconified/NormalToIconifiedTest.java b/jdk/test/java/awt/Frame/NormalToIconified/NormalToIconifiedTest.java
new file mode 100644
index 0000000..ca4c592
--- /dev/null
+++ b/jdk/test/java/awt/Frame/NormalToIconified/NormalToIconifiedTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8171949
+ * @summary Tests that bitwise mask is set and state listener is notified during state transition.
+ * @author Dmitry Markov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main NormalToIconifiedTest
+ */
+
+import java.awt.Frame;
+import java.awt.Robot;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowStateListener;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class NormalToIconifiedTest {
+    private static final AtomicBoolean listenerNotified = new AtomicBoolean(false);
+
+    public static void main(String[] args) {
+        Robot robot = Util.createRobot();
+
+        Frame testFrame = new Frame("Test Frame");
+        testFrame.setSize(200, 200);
+        testFrame.addWindowStateListener(new WindowStateListener() {
+            @Override
+            public void windowStateChanged(WindowEvent e) {
+                listenerNotified.set(true);
+                synchronized (listenerNotified) {
+                    listenerNotified.notifyAll();
+                }
+            }
+        });
+        testFrame.setVisible(true);
+
+        Frame mainFrame = new Frame("Main Frame");
+        mainFrame.setSize(200, 200);
+        mainFrame.setLocationRelativeTo(null);
+        mainFrame.setVisible(true);
+
+        Util.waitForIdle(robot);
+
+        try {
+            Util.clickOnComp(mainFrame, robot);
+            Util.waitForIdle(robot);
+
+            // NORMAL -> ICONIFIED
+            listenerNotified.set(false);
+            testFrame.setExtendedState(Frame.ICONIFIED);
+            Util.waitForIdle(robot);
+
+            Util.waitForCondition(listenerNotified, 2000);
+            if (!listenerNotified.get()) {
+                throw new RuntimeException("Test FAILED! Window state listener was not notified during NORMAL to" +
+                        "ICONIFIED transition");
+            }
+            if (testFrame.getExtendedState() != Frame.ICONIFIED) {
+                throw new RuntimeException("Test FAILED! Frame is not in ICONIFIED state");
+            }
+
+            // ICONIFIED -> NORMAL
+            listenerNotified.set(false);
+            testFrame.setExtendedState(Frame.NORMAL);
+            Util.waitForIdle(robot);
+
+            Util.waitForCondition(listenerNotified, 2000);
+            if (!listenerNotified.get()) {
+                throw new RuntimeException("Test FAILED! Window state listener was not notified during ICONIFIED to" +
+                        "NORMAL transition");
+            }
+            if (testFrame.getExtendedState() != Frame.NORMAL) {
+                throw new RuntimeException("Test FAILED! Frame is not in NORMAL state");
+            }
+        } finally {
+            testFrame.dispose();
+            mainFrame.dispose();
+        }
+    }
+}
+
diff --git a/jdk/test/java/awt/Frame/ObscuredFrame/ObscuredFrameTest.java b/jdk/test/java/awt/Frame/ObscuredFrame/ObscuredFrameTest.java
new file mode 100644
index 0000000..762d672
--- /dev/null
+++ b/jdk/test/java/awt/Frame/ObscuredFrame/ObscuredFrameTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8171952
+ * @summary Tests that getMousePosition() returns null for obscured component.
+ * @author Dmitry Markov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main ObscuredFrameTest
+ */
+
+import java.awt.*;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class ObscuredFrameTest {
+    public static void main(String[] args) {
+        Robot robot = Util.createRobot();
+
+        Frame frame = new Frame("Obscured Frame");
+        frame.setSize(200, 200);
+        frame.setLocationRelativeTo(null);
+        Button button = new Button("Button");
+        frame.add(button);
+
+        Dialog dialog = new Dialog(frame, "Visible Dialog", false);
+        dialog.setSize(200, 200);
+        dialog.setLocationRelativeTo(null);
+        dialog.setVisible(true);
+
+        frame.setVisible(true);
+
+        Util.waitForIdle(robot);
+
+        Util.pointOnComp(button, robot);
+        Util.waitForIdle(robot);
+        robot.delay(2000);
+
+        try {
+            if (button.getMousePosition() != null) {
+                throw new RuntimeException("Test Failed! Mouse position is not null for obscured component.");
+            }
+        } finally {
+            frame.dispose();
+            dialog.dispose();
+        }
+    }
+}
+
diff --git a/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java b/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java
new file mode 100644
index 0000000..802ccb3
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Security;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+/* @test
+ * @build CheckInputOrderTest SerialFilterTest
+ * @run testng/othervm CheckInputOrderTest
+ *
+ * @summary Test that when both global filter and specific filter are set,
+ *          global filter will not affect specific filter.
+ */
+
+public class CheckInputOrderTest implements Serializable {
+    private static final long serialVersionUID = 12345678901L;
+
+    @DataProvider(name="Patterns")
+    Object[][] patterns() {
+        return new Object[][] {
+                new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long;maxarray=0", false },
+                new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long", true },
+                new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxdepth=0", false },
+                new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxbytes=0", false },
+                new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxrefs=0", false },
+
+                new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long", true },
+
+                new Object[] { Long.MAX_VALUE, "!java.**;java.lang.*;java.lang.Long", false },
+                new Object[] { Long.MAX_VALUE, "java.**;!java.lang.*;java.lang.Long", true },
+
+                new Object[] { Long.MAX_VALUE, "!java.lang.*;java.**;java.lang.Long", false },
+                new Object[] { Long.MAX_VALUE, "java.lang.*;!java.**;java.lang.Long", true },
+
+                new Object[] { Long.MAX_VALUE, "!java.lang.Long;java.**;java.lang.*", false },
+                new Object[] { Long.MAX_VALUE, "java.lang.Long;java.**;!java.lang.*", true },
+
+                new Object[] { Long.MAX_VALUE, "java.lang.Long;!java.**;java.lang.*", false },
+                new Object[] { Long.MAX_VALUE, "java.lang.Long;java.lang.Number;!java.**;java.lang.*", true },
+        };
+    }
+
+    /**
+     * Test:
+     *   "global filter reject" + "specific ObjectInputStream filter is empty" => should reject
+     *   "global filter reject" + "specific ObjectInputStream filter allow"    => should allow
+     */
+    @Test(dataProvider="Patterns")
+    public void testRejectedInGlobal(Object toDeserialized, String pattern, boolean allowed) throws Exception {
+        byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+            Object o = ois.readObject();
+            assertTrue(allowed, "filter should have thrown an exception");
+        } catch (InvalidClassException ice) {
+            assertFalse(allowed, "filter should have thrown an exception");
+        }
+    }
+}
diff --git a/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java
new file mode 100644
index 0000000..7c03f91
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.security.AccessControlException;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+/* @test
+ * @build FilterWithSecurityManagerTest SerialFilterTest
+ * @run testng/othervm FilterWithSecurityManagerTest
+ * @run testng/othervm/policy=security.policy.without.globalFilter
+ *          -Djava.security.manager=default FilterWithSecurityManagerTest
+ * @run testng/othervm/policy=security.policy
+ *          -Djava.security.manager=default
+ *          -Djdk.serialFilter=java.lang.Integer FilterWithSecurityManagerTest
+ *
+ * @summary Test that setting specific filter is checked by security manager,
+ *          setting process-wide filter is checked by security manager.
+ */
+
+@Test
+public class FilterWithSecurityManagerTest {
+
+    byte[] bytes;
+    boolean setSecurityManager;
+    ObjectInputFilter filter;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        setSecurityManager = System.getSecurityManager() != null;
+        Object toDeserialized = Long.MAX_VALUE;
+        bytes = SerialFilterTest.writeObjects(toDeserialized);
+        filter = ObjectInputFilter.Config.createFilter("java.lang.Long");
+    }
+
+    /**
+     * Test that setting process-wide filter is checked by security manager.
+     */
+    @Test
+    public void testGlobalFilter() throws Exception {
+        if (ObjectInputFilter.Config.getSerialFilter() == null) {
+            return;
+        }
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setSerialFilter(filter);
+            assertFalse(setSecurityManager,
+                    "When SecurityManager exists, without "
+                    + "java.security.SerializablePermission(serialFilter) Exception should be thrown");
+            Object o = ois.readObject();
+        } catch (AccessControlException ex) {
+            assertTrue(setSecurityManager);
+            assertTrue(ex.getMessage().contains("java.io.SerializablePermission"));
+            assertTrue(ex.getMessage().contains("serialFilter"));
+        }
+    }
+
+    /**
+     * Test that setting specific filter is checked by security manager.
+     */
+    @Test(dependsOnMethods = { "testGlobalFilter" })
+    public void testSpecificFilter() throws Exception {
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+            Object o = ois.readObject();
+        } catch (AccessControlException ex) {
+            assertTrue(setSecurityManager);
+            assertTrue(ex.getMessage().contains("java.io.SerializablePermission"));
+            assertTrue(ex.getMessage().contains("serialFilter"));
+        }
+    }
+}
diff --git a/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java
new file mode 100644
index 0000000..20503d1
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/GlobalFilterTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+
+import java.io.SerializablePermission;
+import java.security.Security;
+import java.util.Objects;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+import sun.misc.ObjectInputFilter;
+
+/* @test
+ * @build GlobalFilterTest SerialFilterTest
+ * @run testng/othervm GlobalFilterTest
+ * @run testng/othervm -Djdk.serialFilter=java.** GlobalFilterTest
+ * @run testng/othervm/policy=security.policy GlobalFilterTest
+ * @run testng/othervm/policy=security.policy
+ *        -Djava.security.properties=${test.src}/java.security-extra1
+ *        -Djava.security.debug=properties GlobalFilterTest
+ *
+ * @summary Test Global Filters
+ */
+@Test
+public class GlobalFilterTest {
+
+    /**
+     * DataProvider of patterns and objects derived from the configured process-wide filter.
+     * @return Array of arrays of pattern, object, allowed boolean, and API factory
+     */
+    @DataProvider(name="globalPatternElements")
+    Object[][] globalPatternElements() {
+        String globalFilter =
+                System.getProperty("jdk.serialFilter",
+                        Security.getProperty("jdk.serialFilter"));
+        if (globalFilter == null) {
+            return new Object[0][];
+        }
+
+        String[] patterns = globalFilter.split(";");
+        Object[][] objects = new Object[patterns.length][];
+
+        for (int i = 0; i < patterns.length; i++) {
+            Object o;
+            boolean allowed;
+            String pattern = patterns[i].trim();
+            if (pattern.contains("=")) {
+                allowed = false;
+                o = SerialFilterTest.genTestObject(pattern, false);
+            } else {
+                allowed = !pattern.startsWith("!");
+                o = (allowed)
+                    ? SerialFilterTest.genTestObject(pattern, true)
+                    : SerialFilterTest.genTestObject(pattern.substring(1), false);
+
+                Assert.assertNotNull(o, "fail generation failed");
+            }
+            objects[i] = new Object[3];
+            objects[i][0] = pattern;
+            objects[i][1] = allowed;
+            objects[i][2] = o;
+        }
+        return objects;
+    }
+
+    /**
+     * Test that the process-wide filter is set when the properties are set
+     * and has the toString matching the configured pattern.
+     */
+    @Test()
+    static void globalFilter() {
+        String pattern =
+                System.getProperty("jdk.serialFilter",
+                        Security.getProperty("jdk.serialFilter"));
+        ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter();
+        System.out.printf("global pattern: %s, filter: %s%n", pattern, filter);
+        Assert.assertEquals(pattern, Objects.toString(filter, null),
+                "process-wide filter pattern does not match");
+    }
+
+    /**
+     * If the Global filter is already set, it should always refuse to be
+     * set again.
+     * If there is a security manager, setting the serialFilter should fail
+     * without the appropriate permission.
+     * If there is no security manager then setting it should work.
+     */
+    @Test()
+    static void setGlobalFilter() {
+        SecurityManager sm = System.getSecurityManager();
+        ObjectInputFilter filter = new SerialFilterTest.Validator();
+        ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter();
+        if (global != null) {
+            // once set, can never be re-set
+            try {
+                ObjectInputFilter.Config.setSerialFilter(filter);
+                Assert.fail("set only once process-wide filter");
+            } catch (IllegalStateException ise) {
+                if (sm != null) {
+                    Assert.fail("wrong exception when security manager is set", ise);
+                }
+            } catch (SecurityException se) {
+                if (sm == null) {
+                    Assert.fail("wrong exception when security manager is not set", se);
+                }
+            }
+        } else {
+            if (sm == null) {
+                // no security manager
+                try {
+                    ObjectInputFilter.Config.setSerialFilter(filter);
+                    // Note once set, it can not be reset; so other tests
+                    System.out.printf("Global Filter set to Validator%n");
+                } catch (SecurityException se) {
+                    Assert.fail("setGlobalFilter should not get SecurityException", se);
+                }
+                try {
+                    // Try to set it again, expecting it to throw
+                    ObjectInputFilter.Config.setSerialFilter(filter);
+                    Assert.fail("set only once process-wide filter");
+                } catch (IllegalStateException ise) {
+                    // Normal case
+                }
+            } else {
+                // Security manager
+                SecurityException expectSE = null;
+                try {
+                    sm.checkPermission(new SerializablePermission("serialFilter"));
+                } catch (SecurityException se1) {
+                    expectSE = se1;
+                }
+                SecurityException actualSE = null;
+                try {
+                    ObjectInputFilter.Config.setSerialFilter(filter);
+                } catch (SecurityException se2) {
+                    actualSE = se2;
+                }
+                if (expectSE == null | actualSE == null) {
+                    Assert.assertEquals(expectSE, actualSE, "SecurityException");
+                } else {
+                    Assert.assertEquals(expectSE.getClass(), actualSE.getClass(),
+                            "SecurityException class");
+                }
+            }
+        }
+    }
+
+    /**
+     * For each pattern in the process-wide filter test a generated object
+     * against the default process-wide filter.
+     *
+     * @param pattern a pattern extracted from the configured global pattern
+     */
+    @Test(dataProvider = "globalPatternElements")
+    static void globalFilterElements(String pattern, boolean allowed,Object obj) {
+        testGlobalPattern(pattern, obj, allowed);
+    }
+
+    /**
+     * Serialize and deserialize an object using the default process-wide filter
+     * and check allowed or reject.
+     *
+     * @param pattern the pattern
+     * @param object the test object
+     * @param allowed the expected result from ObjectInputStream (exception or not)
+     */
+    static void testGlobalPattern(String pattern, Object object, boolean allowed) {
+        try {
+//            System.out.printf("global %s pattern: %s, obj: %s%n", (allowed ? "allowed" : "not allowed"), pattern, object);
+            byte[] bytes = SerialFilterTest.writeObjects(object);
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                 ObjectInputStream ois = new ObjectInputStream(bais)) {
+                Object o = ois.readObject();
+            } catch (EOFException eof) {
+                // normal completion
+            } catch (ClassNotFoundException cnf) {
+                Assert.fail("Deserializing", cnf);
+            }
+            Assert.assertTrue(allowed, "filter should have thrown an exception");
+        } catch (IllegalArgumentException iae) {
+            Assert.fail("bad format pattern", iae);
+        } catch (InvalidClassException ice) {
+            Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice);
+        } catch (IOException ioe) {
+            Assert.fail("Unexpected IOException", ioe);
+        }
+    }
+}
diff --git a/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java b/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java
new file mode 100644
index 0000000..f5aeb01
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/MixedFiltersTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Security;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/* @test
+ * @build MixedFiltersTest SerialFilterTest
+ * @run testng/othervm -Djdk.serialFilter=!java.**;!java.lang.Long;maxdepth=5;maxarray=5;maxbytes=90;maxrefs=5          MixedFiltersTest
+ * @run testng/othervm -Djdk.serialFilter=java.**;java.lang.Long;maxdepth=1000;maxarray=1000;maxbytes=1000;maxrefs=1000 MixedFiltersTest
+ *
+ * @summary Test that when both global filter and specific filter are set,
+ *          global filter will not affect specific filter.
+ */
+
+public class MixedFiltersTest implements Serializable {
+
+    private static final long serialVersionUID = 1234567890L;
+
+
+    boolean globalRejected;
+
+    @BeforeClass
+    public void setup() {
+        String pattern = System.getProperty("jdk.serialFilter",
+                Security.getProperty("jdk.serialFilter"));
+        globalRejected = pattern.startsWith("!");
+    }
+
+    @DataProvider(name="RejectedInGlobal")
+    Object[][] rejectedInGlobal() {
+        if (!globalRejected) {
+            return new Object[0][];
+        }
+        return new Object[][] {
+                new Object[] { Long.MAX_VALUE, "java.**" },
+                new Object[] { Long.MAX_VALUE, "java.lang.Long" },
+                new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "java.lang.**" },
+                new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=100" },
+                new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=100" },
+                new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=1000" },
+                new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=100" },
+        };
+    }
+
+    /**
+     * Test:
+     *   "global filter reject" + "specific ObjectInputStream filter is empty" => should reject
+     *   "global filter reject" + "specific ObjectInputStream filter allow"    => should allow
+     */
+    @Test(dataProvider="RejectedInGlobal")
+    public void testRejectedInGlobal(Object toDeserialized, String pattern) throws Exception {
+        byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            Object o = ois.readObject();
+            fail("filter should have thrown an exception");
+        } catch (InvalidClassException expected) { }
+
+        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+            Object o = ois.readObject();
+        }
+    }
+
+    @DataProvider(name="AllowedInGlobal")
+    Object[][] allowedInGlobal() {
+        if (globalRejected) {
+            return new Object[0][];
+        }
+
+        return new Object[][] {
+                new Object[] { Long.MAX_VALUE, "!java.**" },
+                new Object[] { Long.MAX_VALUE, "!java.lang.Long" },
+                new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "!java.lang.**" },
+                new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=5" },
+                new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=5" },
+                new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=5" },
+                new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=5" },
+            };
+    }
+
+    /**
+     * Test:
+     *   "global filter allow" + "specific ObjectInputStream filter is empty" => should allow
+     *   "global filter allow" + "specific ObjectInputStream filter reject"   => should reject
+     */
+    @Test(dataProvider="AllowedInGlobal")
+    public void testAllowedInGlobal(Object toDeserialized, String pattern) throws Exception {
+        byte[] bytes = SerialFilterTest.writeObjects(toDeserialized);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            Object o = ois.readObject();
+        }
+
+        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+            Object o = ois.readObject();
+            assertTrue(false, "filter should have thrown an exception");
+        } catch (InvalidClassException expected) { }
+    }
+}
diff --git a/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java b/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java
new file mode 100644
index 0000000..0ab3246
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
+
+import sun.misc.ObjectInputFilter;
+
+import javax.lang.model.SourceVersion;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/* @test
+ * @build SerialFilterTest
+ * @run testng/othervm  SerialFilterTest
+ *
+ * @summary Test ObjectInputFilters
+ */
+@Test
+public class SerialFilterTest implements Serializable {
+
+    private static final long serialVersionUID = -6999613679881262446L;
+
+    /**
+     * Enable three arg lambda.
+     * @param <T> The pattern
+     * @param <U> The test object
+     * @param <V> Boolean for if the filter should allow or reject
+     */
+    interface TriConsumer< T, U, V> {
+        void accept(T t, U u, V v);
+    }
+
+    /**
+     * Misc object to use that should always be accepted.
+     */
+    private static final Object otherObject = Integer.valueOf(0);
+
+    /**
+     * DataProvider for the individual patterns to test.
+     * Expand the patterns into cases for each of the Std and Compatibility APIs.
+     * @return an array of arrays of the parameters including factories
+     */
+    @DataProvider(name="Patterns")
+    static Object[][] patterns() {
+        Object[][] patterns = new Object[][]{
+                {"java.util.Hashtable"},
+                {"java.util.Hash*"},
+                {"javax.lang.model.*"},
+                {"javax.lang.**"},
+                {"*"},
+                {"maxarray=47"},
+                {"maxdepth=5"},
+                {"maxrefs=10"},
+                {"maxbytes=100"},
+                {"maxbytes=72"},
+                {"maxbytes=+1024"},
+        };
+        return patterns;
+    }
+
+    @DataProvider(name="InvalidPatterns")
+    static Object[][] invalidPatterns() {
+        return new Object [][] {
+                {"maxrefs=-1"},
+                {"maxdepth=-1"},
+                {"maxbytes=-1"},
+                {"maxarray=-1"},
+                {"xyz=0"},
+                {"xyz=-1"},
+                {"maxrefs=0xabc"},
+                {"maxrefs=abc"},
+                {"maxrefs="},
+                {"maxrefs=+"},
+                {".*"},
+                {".**"},
+                {"!"},
+                {"/java.util.Hashtable"},
+                {"java.base/"},
+                {"/"},
+        };
+    }
+
+    @DataProvider(name="Limits")
+    static Object[][] limits() {
+        // The numbers are arbitrary > 1
+        return new Object[][]{
+                {"maxrefs", 10},
+                {"maxdepth", 5},
+                {"maxbytes", 100},
+                {"maxarray", 16},
+        };
+    }
+
+    /**
+     * DataProvider of individual objects. Used to check the information
+     * available to the filter.
+     * @return  Arrays of parameters with objects
+     */
+    @DataProvider(name="Objects")
+    static Object[][] objects() {
+        byte[] byteArray = new byte[0];
+        Object[] objArray = new Object[7];
+        objArray[objArray.length - 1] = objArray;
+
+        Class<?> serClass = null;
+        String className = "java.util.concurrent.atomic.LongAdder$SerializationProxy";
+        try {
+            serClass = Class.forName(className);
+        } catch (Exception e) {
+            Assert.fail("missing class: " + className, e);
+        }
+
+        Class<?>[] interfaces = {Runnable.class};
+        Runnable proxy = (Runnable) Proxy.newProxyInstance(null,
+                interfaces, (p, m, args) -> p);
+
+        Runnable runnable = (Runnable & Serializable) SerialFilterTest::noop;
+        Object[][] objects = {
+                { null, 0, -1, 0, 0, 0,
+                        new HashSet<>()},        // no callback, no values
+                { objArray, 3, 7, 8, 2, 55,
+                        new HashSet<>(Arrays.asList(objArray.getClass()))},
+                { Object[].class, 1, -1, 1, 1, 40,
+                        new HashSet<>(Arrays.asList(Object[].class))},
+                { new SerialFilterTest(), 1, -1, 1, 1, 37,
+                        new HashSet<>(Arrays.asList(SerialFilterTest.class))},
+                { new LongAdder(), 2, -1, 1, 1, 93,
+                        new HashSet<>(Arrays.asList(LongAdder.class, serClass))},
+                { new byte[14], 2, 14, 1, 1, 27,
+                        new HashSet<>(Arrays.asList(byteArray.getClass()))},
+                { runnable, 13, 0, 10, 2, 514,
+                        new HashSet<>(Arrays.asList(java.lang.invoke.SerializedLambda.class,
+                                SerialFilterTest.class,
+                                objArray.getClass()))},
+                { deepHashSet(10), 48, -1, 49, 11, 619,
+                        new HashSet<>(Arrays.asList(HashSet.class))},
+                { proxy.getClass(), 3, -1, 1, 1, 114,
+                        new HashSet<>(Arrays.asList(Runnable.class,
+                                java.lang.reflect.Proxy.class))},
+        };
+        return objects;
+    }
+
+    @DataProvider(name="Arrays")
+    static Object[][] arrays() {
+        return new Object[][]{
+                {new Object[16], 16},
+                {new boolean[16], 16},
+                {new byte[16], 16},
+                {new char[16], 16},
+                {new int[16], 16},
+                {new long[16], 16},
+                {new short[16], 16},
+                {new float[16], 16},
+                {new double[16], 16},
+        };
+    }
+
+
+    /**
+     * Test each object and verify the classes identified by the filter,
+     * the count of calls to the filter, the max array size, max refs, max depth,
+     * max bytes.
+     * This test ignores/is not dependent on the global filter settings.
+     *
+     * @param object a Serializable object
+     * @param count the expected count of calls to the filter
+     * @param maxArray the maximum array size
+     * @param maxRefs the maximum references
+     * @param maxDepth the maximum depth
+     * @param maxBytes the maximum stream size
+     * @param classes  the expected (unique) classes
+     * @throws IOException
+     */
+    @Test(dataProvider="Objects")
+    public static void t1(Object object,
+                          long count, long maxArray, long maxRefs, long maxDepth, long maxBytes,
+                          Set<Class<?>> classes) throws IOException {
+        byte[] bytes = writeObjects(object);
+        Validator validator = new Validator();
+        validate(bytes, validator);
+        System.out.printf("v: %s%n", validator);
+        Assert.assertEquals(validator.count, count, "callback count wrong");
+        Assert.assertEquals(validator.classes, classes, "classes mismatch");
+        Assert.assertEquals(validator.maxArray, maxArray, "maxArray mismatch");
+        Assert.assertEquals(validator.maxRefs, maxRefs, "maxRefs wrong");
+        Assert.assertEquals(validator.maxDepth, maxDepth, "depth wrong");
+        Assert.assertEquals(validator.maxBytes, maxBytes, "maxBytes wrong");
+    }
+
+    /**
+     * Test each pattern with an appropriate object.
+     * A filter is created from the pattern and used to serialize and
+     * deserialize a generated object with both the positive and negative case.
+     * This test ignores/is not dependent on the global filter settings.
+     *
+     * @param pattern a pattern
+     */
+    @Test(dataProvider="Patterns")
+    static void testPatterns(String pattern) {
+        evalPattern(pattern, (p, o, neg) -> testPatterns(p, o, neg));
+    }
+
+    /**
+     * Test that the filter on a OIS can be set only on a fresh OIS,
+     * before deserializing any objects.
+     * This test is agnostic the global filter being set or not.
+     */
+    @Test
+    static void nonResettableFilter() {
+        Validator validator1 = new Validator();
+        Validator validator2 = new Validator();
+
+        try {
+            byte[] bytes = writeObjects("text1");    // an object
+
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                 ObjectInputStream ois = new ObjectInputStream(bais)) {
+                // Check the initial filter is the global filter; may be null
+                ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter();
+                ObjectInputFilter initial = ObjectInputFilter.Config.getObjectInputFilter(ois);
+                Assert.assertEquals(global, initial, "initial filter should be the global filter");
+
+                // Check if it can be set to null
+                ObjectInputFilter.Config.setObjectInputFilter(ois, null);
+                ObjectInputFilter filter = ObjectInputFilter.Config.getObjectInputFilter(ois);
+                Assert.assertNull(filter, "set to null should be null");
+
+                ObjectInputFilter.Config.setObjectInputFilter(ois, validator1);
+                Object o = ois.readObject();
+                try {
+                    ObjectInputFilter.Config.setObjectInputFilter(ois, validator2);
+                    Assert.fail("Should not be able to set filter twice");
+                } catch (IllegalStateException ise) {
+                    // success, the exception was expected
+                }
+            } catch (EOFException eof) {
+                Assert.fail("Should not reach end-of-file", eof);
+            } catch (ClassNotFoundException cnf) {
+                Assert.fail("Deserializing", cnf);
+            }
+        } catch (IOException ex) {
+            Assert.fail("Unexpected IOException", ex);
+        }
+    }
+
+    /**
+     * Test that if an Objects readReadResolve method returns an array
+     * that the callback to the filter includes the proper array length.
+     * @throws IOException if an error occurs
+     */
+    @Test(dataProvider="Arrays")
+    static void testReadResolveToArray(Object array, int length) throws IOException {
+        ReadResolveToArray object = new ReadResolveToArray(array, length);
+        byte[] bytes = writeObjects(object);
+        Object o = validate(bytes, object);    // the object is its own filter
+        Assert.assertEquals(o.getClass(), array.getClass(), "Filter not called with the array");
+    }
+
+    /**
+     * Test repeated limits use the last value.
+     * Construct a filter with the limit and the limit repeated -1.
+     * Invoke the filter with the limit to make sure it is rejected.
+     * Invoke the filter with the limit -1 to make sure it is accepted.
+     * @param name the name of the limit to test
+     * @param value a test value
+     */
+    @Test(dataProvider="Limits")
+    static void testLimits(String name, int value) {
+        Class<?> arrayClass = new int[0].getClass();
+        String pattern = String.format("%s=%d;%s=%d", name, value, name, value - 1);
+        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+        Assert.assertEquals(
+                filter.checkInput(new FilterValues(arrayClass, value, value, value, value)),
+                ObjectInputFilter.Status.REJECTED,
+                "last limit value not used: " + filter);
+        Assert.assertEquals(
+                filter.checkInput(new FilterValues(arrayClass, value-1, value-1, value-1, value-1)),
+                ObjectInputFilter.Status.UNDECIDED,
+                "last limit value not used: " + filter);
+    }
+
+    /**
+     * Test that returning null from a filter causes deserialization to fail.
+     */
+    @Test(expectedExceptions=InvalidClassException.class)
+    static void testNullStatus() throws IOException {
+        byte[] bytes = writeObjects(0); // an Integer
+        try {
+            Object o = validate(bytes, new ObjectInputFilter() {
+                public ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo f) {
+                    return null;
+                }
+            });
+        } catch (InvalidClassException ice) {
+            System.out.printf("Success exception: %s%n", ice);
+            throw ice;
+        }
+    }
+
+    /**
+     * Verify that malformed patterns throw IAE.
+     * @param pattern pattern from the data source
+     */
+    @Test(dataProvider="InvalidPatterns", expectedExceptions=IllegalArgumentException.class)
+    static void testInvalidPatterns(String pattern) {
+        try {
+            ObjectInputFilter.Config.createFilter(pattern);
+        } catch (IllegalArgumentException iae) {
+            System.out.printf("    success exception: %s%n", iae);
+            throw iae;
+        }
+    }
+
+    /**
+     * Test that Config.create returns null if the argument does not contain any patterns or limits.
+     */
+    @Test()
+    static void testEmptyPattern() {
+        ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("");
+        Assert.assertNull(filter, "empty pattern did not return null");
+
+        filter = ObjectInputFilter.Config.createFilter(";;;;");
+        Assert.assertNull(filter, "pattern with only delimiters did not return null");
+    }
+
+    /**
+     * Read objects from the serialized stream, validated with the filter.
+     *
+     * @param bytes a byte array to read objects from
+     * @param filter the ObjectInputFilter
+     * @return the object deserialized if any
+     * @throws IOException can be thrown
+     */
+    static Object validate(byte[] bytes,
+                         ObjectInputFilter filter) throws IOException {
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+             ObjectInputStream ois = new ObjectInputStream(bais)) {
+            ObjectInputFilter.Config.setObjectInputFilter(ois, filter);
+
+            Object o = ois.readObject();
+            return o;
+        } catch (EOFException eof) {
+            // normal completion
+        } catch (ClassNotFoundException cnf) {
+            Assert.fail("Deserializing", cnf);
+        }
+        return null;
+    }
+
+    /**
+     * Write objects and return a byte array with the bytes.
+     *
+     * @param objects zero or more objects to serialize
+     * @return the byte array of the serialized objects
+     * @throws IOException if an exception occurs
+     */
+    static byte[] writeObjects(Object... objects)  throws IOException {
+        byte[] bytes;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            for (Object o : objects) {
+                oos.writeObject(o);
+            }
+            bytes = baos.toByteArray();
+        }
+        return bytes;
+    }
+
+    /**
+     * A filter that accumulates information about the checkInput callbacks
+     * that can be checked after readObject completes.
+     */
+    static class Validator implements ObjectInputFilter {
+        long count;          // Count of calls to checkInput
+        HashSet<Class<?>> classes = new HashSet<>();
+        long maxArray = -1;
+        long maxRefs;
+        long maxDepth;
+        long maxBytes;
+
+        Validator() {
+        }
+
+        @Override
+        public ObjectInputFilter.Status checkInput(FilterInfo filter) {
+            count++;
+            if (filter.serialClass() != null) {
+                if (filter.serialClass().getName().contains("$$Lambda$")) {
+                    // TBD: proper identification of serialized Lambdas?
+                    // Fold the serialized Lambda into the SerializedLambda type
+                    classes.add(SerializedLambda.class);
+                } else if (Proxy.isProxyClass(filter.serialClass())) {
+                    classes.add(Proxy.class);
+                } else {
+                    classes.add(filter.serialClass());
+                }
+
+            }
+            this.maxArray = Math.max(this.maxArray, filter.arrayLength());
+            this.maxRefs = Math.max(this.maxRefs, filter.references());
+            this.maxDepth = Math.max(this.maxDepth, filter.depth());
+            this.maxBytes = Math.max(this.maxBytes, filter.streamBytes());
+            return ObjectInputFilter.Status.UNDECIDED;
+        }
+
+        public String toString(){
+            return "count: " + count
+                    + ", classes: " + classes.toString()
+                    + ", maxArray: " + maxArray
+                    + ", maxRefs: " + maxRefs
+                    + ", maxDepth: " + maxDepth
+                    + ", maxBytes: " + maxBytes;
+        }
+    }
+
+
+    /**
+     * Create a filter from a pattern and API factory, then serialize and
+     * deserialize an object and check allowed or reject.
+     *
+     * @param pattern the pattern
+     * @param object the test object
+     * @param allowed the expected result from ObjectInputStream (exception or not)
+     */
+    static void testPatterns(String pattern, Object object, boolean allowed) {
+        try {
+            byte[] bytes = SerialFilterTest.writeObjects(object);
+            ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern);
+            validate(bytes, filter);
+            Assert.assertTrue(allowed, "filter should have thrown an exception");
+        } catch (IllegalArgumentException iae) {
+            Assert.fail("bad format pattern", iae);
+        } catch (InvalidClassException ice) {
+            Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice);
+        } catch (IOException ioe) {
+            Assert.fail("Unexpected IOException", ioe);
+        }
+    }
+
+    /**
+     * For a filter pattern, generate and apply a test object to the action.
+     * @param pattern a pattern
+     * @param action an action to perform on positive and negative cases
+     */
+    static void evalPattern(String pattern, TriConsumer<String, Object, Boolean> action) {
+        Object o = genTestObject(pattern, true);
+        Assert.assertNotNull(o, "success generation failed");
+        action.accept(pattern, o, true);
+
+        // Test the negative pattern
+        o = genTestObject(pattern, false);
+        Assert.assertNotNull(o, "fail generation failed");
+        String negPattern = pattern.contains("=") ? pattern : "!" + pattern;
+        action.accept(negPattern, o, false);
+    }
+
+    /**
+     * Generate a test object based on the pattern.
+     * Handles each of the forms of the pattern, wildcards,
+     * class name, various limit forms.
+     * @param pattern a pattern
+     * @param allowed a boolean indicating to generate the allowed or disallowed case
+     * @return an object or {@code null} to indicate no suitable object could be generated
+     */
+    static Object genTestObject(String pattern, boolean allowed) {
+        if (pattern.contains("=")) {
+            return genTestLimit(pattern, allowed);
+        } else if (pattern.endsWith("*")) {
+            return genTestObjectWildcard(pattern, allowed);
+        } else {
+            // class
+            try {
+                Class<?> clazz = Class.forName(pattern);
+                Constructor<?> cons = clazz.getConstructor();
+                return cons.newInstance();
+            } catch (ClassNotFoundException ex) {
+                Assert.fail("no such class available: " + pattern);
+            } catch (InvocationTargetException
+                    | NoSuchMethodException
+                    | InstantiationException
+                    | IllegalAccessException ex1) {
+                Assert.fail("newInstance: " + ex1);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Generate an object to be used with the various wildcard pattern forms.
+     * Explicitly supports only specific package wildcards with specific objects.
+     * @param pattern a wildcard pattern ending in "*"
+     * @param allowed a boolean indicating to generate the allowed or disallowed case
+     * @return an object within or outside the wildcard
+     */
+    static Object genTestObjectWildcard(String pattern, boolean allowed) {
+        if (pattern.endsWith(".**")) {
+            // package hierarchy wildcard
+            if (pattern.startsWith("javax.lang.")) {
+                return SourceVersion.RELEASE_5;
+            }
+            if (pattern.startsWith("java.")) {
+                return 4;
+            }
+            if (pattern.startsWith("javax.")) {
+                return SourceVersion.RELEASE_6;
+            }
+            return otherObject;
+        } else if (pattern.endsWith(".*")) {
+            // package wildcard
+            if (pattern.startsWith("javax.lang.model")) {
+                return SourceVersion.RELEASE_6;
+            }
+        } else {
+            // class wildcard
+            if (pattern.equals("*")) {
+                return otherObject; // any object will do
+            }
+            if (pattern.startsWith("java.util.Hash")) {
+                return new Hashtable<String, String>();
+            }
+        }
+        Assert.fail("Object could not be generated for pattern: "
+                + pattern
+                + ", allowed: " + allowed);
+        return null;
+    }
+
+    /**
+     * Generate a limit test object for the pattern.
+     * For positive cases, the object exactly hits the limit.
+     * For negative cases, the object is 1 greater than the limit
+     * @param pattern the pattern, containing "=" and a maxXXX keyword
+     * @param allowed a boolean indicating to generate the allowed or disallowed case
+     * @return a sitable object
+     */
+    static Object genTestLimit(String pattern, boolean allowed) {
+        int ndx = pattern.indexOf('=');
+        Assert.assertNotEquals(ndx, -1, "missing value in limit");
+        long value = Long.parseUnsignedLong(pattern.substring(ndx+1));
+        if (pattern.startsWith("maxdepth=")) {
+            // Return an object with the requested depth (or 1 greater)
+            long depth = allowed ? value : value + 1;
+            Object[] array = new Object[1];
+            for (int i = 1; i < depth; i++) {
+                Object[] n = new Object[1];
+                n[0] = array;
+                array = n;
+            }
+            return array;
+        } else if (pattern.startsWith("maxbytes=")) {
+            // Return a byte array that when written to OOS creates
+            // a stream of exactly the size requested.
+            return genMaxBytesObject(allowed, value);
+        } else if (pattern.startsWith("maxrefs=")) {
+            Object[] array = new Object[allowed ? (int)value - 1 : (int)value];
+            for (int i = 0; i < array.length; i++) {
+                array[i] = otherObject;
+            }
+            return array;
+        } else if (pattern.startsWith("maxarray=")) {
+            return allowed ? new int[(int)value] : new int[(int)value+1];
+        }
+        Assert.fail("Object could not be generated for pattern: "
+                + pattern
+                + ", allowed: " + allowed);
+        return null;
+    }
+
+    /**
+     * Generate an an object that will be serialized to some number of bytes.
+     * Or 1 greater if allowed is false.
+     * It returns a two element Object array holding a byte array sized
+     * to achieve the desired total size.
+     * @param allowed true if the stream should be allowed at that size,
+     *                false if the stream should be larger
+     * @param maxBytes the number of bytes desired in the stream;
+     *                 should not be less than 72 (due to protocol overhead).
+     * @return a object that will be serialized to the length requested
+     */
+    private static Object genMaxBytesObject(boolean allowed, long maxBytes) {
+        Object[] holder = new Object[2];
+        long desiredSize = allowed ? maxBytes : maxBytes + 1;
+        long actualSize = desiredSize;
+        long byteSize = desiredSize - 72;  // estimate needed array size
+        do {
+            byteSize += (desiredSize - actualSize);
+            byte[] a = new byte[(int)byteSize];
+            holder[0] = a;
+            holder[1] = a;
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                 ObjectOutputStream os = new ObjectOutputStream(baos)) {
+                os.writeObject(holder);
+                os.flush();
+                actualSize = baos.size();
+            } catch (IOException ie) {
+                Assert.fail("exception generating stream", ie);
+            }
+        } while (actualSize != desiredSize);
+        return holder;
+    }
+
+    /**
+     * Returns a HashSet of a requested depth.
+     * @param depth the depth
+     * @return a HashSet of HashSets...
+     */
+    static HashSet<Object> deepHashSet(int depth) {
+        HashSet<Object> hashSet = new HashSet<>();
+        HashSet<Object> s1 = hashSet;
+        HashSet<Object> s2 = new HashSet<>();
+        for (int i = 0; i < depth; i++ ) {
+            HashSet<Object> t1 = new HashSet<>();
+            HashSet<Object> t2 = new HashSet<>();
+            // make t1 not equal to t2
+            t1.add("by Jimminy");
+            s1.add(t1);
+            s1.add(t2);
+            s2.add(t1);
+            s2.add(t2);
+            s1 = t1;
+            s2 = t2;
+        }
+        return hashSet;
+    }
+
+    /**
+     * Simple method to use with Serialized Lambda.
+     */
+    private static void noop() {}
+
+
+    /**
+     * Class that returns an array from readResolve and also implements
+     * the ObjectInputFilter to check that it has the expected length.
+     */
+    static class ReadResolveToArray implements Serializable, ObjectInputFilter {
+        private static final long serialVersionUID = 123456789L;
+
+        private final Object array;
+        private final int length;
+
+        ReadResolveToArray(Object array, int length) {
+            this.array = array;
+            this.length = length;
+        }
+
+        Object readResolve() {
+            return array;
+        }
+
+        @Override
+        public ObjectInputFilter.Status checkInput(FilterInfo filter) {
+            if (ReadResolveToArray.class.isAssignableFrom(filter.serialClass())) {
+                return ObjectInputFilter.Status.ALLOWED;
+            }
+            if (filter.serialClass() != array.getClass() ||
+                    (filter.arrayLength() >= 0 && filter.arrayLength() != length)) {
+                return ObjectInputFilter.Status.REJECTED;
+            }
+            return ObjectInputFilter.Status.UNDECIDED;
+        }
+
+    }
+
+    /**
+     * Hold a snapshot of values to be passed to an ObjectInputFilter.
+     */
+    static class FilterValues implements ObjectInputFilter.FilterInfo {
+        private final Class<?> clazz;
+        private final long arrayLength;
+        private final long depth;
+        private final long references;
+        private final long streamBytes;
+
+        public FilterValues(Class<?> clazz, long arrayLength, long depth, long references, long streamBytes) {
+            this.clazz = clazz;
+            this.arrayLength = arrayLength;
+            this.depth = depth;
+            this.references = references;
+            this.streamBytes = streamBytes;
+        }
+
+        @Override
+        public Class<?> serialClass() {
+            return clazz;
+        }
+
+        public long arrayLength() {
+            return arrayLength;
+        }
+
+        public long depth() {
+            return depth;
+        }
+
+        public long references() {
+            return references;
+        }
+
+        public long streamBytes() {
+            return streamBytes;
+        }
+    }
+}
diff --git a/jdk/test/java/io/Serializable/serialFilter/java.security-extra1 b/jdk/test/java/io/Serializable/serialFilter/java.security-extra1
new file mode 100644
index 0000000..7a52040
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/java.security-extra1
@@ -0,0 +1,4 @@
+# Serialization Input Process-wide Filter
+# See conf/security/java.security for pattern synatx
+#
+jdk.serialFilter=java.**;javax.**;maxarray=34;maxdepth=7
diff --git a/jdk/test/java/io/Serializable/serialFilter/security.policy b/jdk/test/java/io/Serializable/serialFilter/security.policy
new file mode 100644
index 0000000..f986e25
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/security.policy
@@ -0,0 +1,17 @@
+// Individual Permissions to for GlobalFilterTest
+grant {
+        // Specific permission under test
+        permission java.security.SerializablePermission "serialFilter";
+        // Permissions needed to run the test
+        permission java.util.PropertyPermission "*", "read";
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.security.SecurityPermission "*";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+};
+
+// Standard extensions get all permissions by default
+grant codeBase "file:${{java.ext.dirs}}/*" {
+        permission java.security.AllPermission;
+};
diff --git a/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter b/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter
new file mode 100644
index 0000000..2f80b82
--- /dev/null
+++ b/jdk/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter
@@ -0,0 +1,15 @@
+// Individual Permissions for FilterWithSecurityManagerTest
+grant {
+        // Permissions needed to run the test
+        permission java.util.PropertyPermission "*", "read";
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+};
+
+// Standard extensions get all permissions by default
+grant codeBase "file:${{java.ext.dirs}}/*" {
+        permission java.security.AllPermission;
+};
+
diff --git a/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java b/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java
new file mode 100644
index 0000000..ae9f8e3
--- /dev/null
+++ b/jdk/test/java/rmi/MarshalledObject/MOFilterTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InvalidClassException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.rmi.MarshalledObject;
+import java.util.Objects;
+
+import sun.misc.ObjectInputFilter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+
+/* @test
+ * @run testng/othervm  MOFilterTest
+ *
+ * @summary Test MarshalledObject applies ObjectInputFilter
+ */
+@Test
+public class MOFilterTest {
+
+    /**
+     * Two cases are tested.
+     * The filter = null and a filter set to verify the calls to the filter.
+     * @return array objects with test parameters for each test case
+     */
+    @DataProvider(name = "FilterCases")
+    public static Object[][] filterCases() {
+        return new Object[][] {
+                {true},     // run the test with the filter
+                {false},    // run the test without the filter
+
+        };
+    }
+
+    /**
+     * Test that MarshalledObject inherits the ObjectInputFilter from
+     * the stream it was deserialized from.
+     */
+    @Test(dataProvider="FilterCases")
+    static void delegatesToMO(boolean withFilter) {
+        try {
+            Serializable testobj = Integer.valueOf(5);
+            MarshalledObject<Serializable> mo = new MarshalledObject<>(testobj);
+            Assert.assertEquals(mo.get(), testobj, "MarshalledObject.get returned a non-equals test object");
+
+            byte[] bytes = writeObjects(mo);
+
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+                 ObjectInputStream ois = new ObjectInputStream(bais)) {
+
+                CountingFilter filter1 = new CountingFilter();
+                ObjectInputFilter.Config.setObjectInputFilter(ois, withFilter ? filter1 : null);
+                MarshalledObject<?> actualMO = (MarshalledObject<?>)ois.readObject();
+                int count = filter1.getCount();
+
+                actualMO.get();
+                int expectedCount = withFilter ? count + 2 : count;
+                int actualCount = filter1.getCount();
+                Assert.assertEquals(actualCount, expectedCount, "filter called wrong number of times during get()");
+            }
+        } catch (IOException ioe) {
+            Assert.fail("Unexpected IOException", ioe);
+        } catch (ClassNotFoundException cnf) {
+            Assert.fail("Deserializing", cnf);
+        }
+    }
+
+    /**
+     * Write objects and return a byte array with the bytes.
+     *
+     * @param objects zero or more objects to serialize
+     * @return the byte array of the serialized objects
+     * @throws IOException if an exception occurs
+     */
+    static byte[] writeObjects(Object... objects)  throws IOException {
+        byte[] bytes;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            for (Object o : objects) {
+                oos.writeObject(o);
+            }
+            bytes = baos.toByteArray();
+        }
+        return bytes;
+    }
+
+
+    static class CountingFilter implements ObjectInputFilter {
+
+        private int count;      // count of calls to the filter
+
+        CountingFilter() {
+            count = 0;
+        }
+
+        int getCount() {
+            return count;
+        }
+
+        /**
+         * Filter that rejects class Integer and allows others
+         *
+         * @param filterInfo access to the class, arrayLength, etc.
+         * @return {@code STATUS.REJECTED}
+         */
+        public ObjectInputFilter.Status checkInput(FilterInfo filterInfo) {
+            count++;
+            return ObjectInputFilter.Status.ALLOWED;
+        }
+    }
+
+}
diff --git a/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java b/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java
new file mode 100644
index 0000000..e29e24a
--- /dev/null
+++ b/jdk/test/java/rmi/registry/serialFilter/RegistryFilterTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.rmi.MarshalledObject;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Objects;
+import java.security.Security;
+
+import org.testng.Assert;
+import org.testng.TestNG;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /java/rmi/testlibrary
+ * @modules java.rmi/sun.rmi.registry
+ *          java.rmi/sun.rmi.server
+ *          java.rmi/sun.rmi.transport
+ *          java.rmi/sun.rmi.transport.tcp
+ * @build TestLibrary
+ * @summary Test filters for the RMI Registry
+ * @run testng/othervm RegistryFilterTest
+ * @run testng/othervm
+ *        -Dsun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+ *        RegistryFilterTest
+ * @run testng/othervm/policy=security.policy
+ *        -Djava.security.properties=${test.src}/java.security-extra1
+ *        RegistryFilterTest
+ */
+public class RegistryFilterTest {
+    private static Registry impl;
+    private static int port;
+    private static Registry registry;
+
+    static final int REGISTRY_MAX_ARRAY = 10000;
+
+    static final String registryFilter =
+            System.getProperty("sun.rmi.registry.registryFilter",
+                    Security.getProperty("sun.rmi.registry.registryFilter"));
+
+    @DataProvider(name = "bindAllowed")
+    static Object[][] bindAllowedObjects() {
+        Object[][] objects = {
+        };
+        return objects;
+    }
+
+    /**
+     * Data RMI Regiry bind test.
+     * - name
+     * - Object
+     * - true/false if object is blacklisted by a filter (implicit or explicit)
+     * @return array of test data
+     */
+    @DataProvider(name = "bindData")
+    static Object[][] bindObjects() {
+        Object[][] data = {
+                { "byte[max]", new XX(new byte[REGISTRY_MAX_ARRAY]), false },
+                { "String", new XX("now is the time"), false},
+                { "String[]", new XX(new String[3]), false},
+                { "Long[4]", new XX(new Long[4]), registryFilter != null },
+                { "rej-byte[toobig]", new XX(new byte[REGISTRY_MAX_ARRAY + 1]), true },
+                { "rej-MarshalledObject", createMarshalledObject(), true },
+                { "rej-RejectableClass", new RejectableClass(), registryFilter != null},
+        };
+        return data;
+    }
+
+    static XX createMarshalledObject() {
+        try {
+            return new XX(new MarshalledObject<>(null));
+        } catch (IOException ioe) {
+            return new XX(ioe);
+        }
+    }
+
+    @BeforeSuite
+    static void setupRegistry() {
+        try {
+            impl = TestLibrary.createRegistryOnEphemeralPort();
+            port = TestLibrary.getRegistryPort(impl);
+            registry = LocateRegistry.getRegistry("localhost", port);
+        } catch (RemoteException ex) {
+            Assert.fail("initialization of registry", ex);
+        }
+
+        System.out.printf("RMI Registry filter: %s%n", registryFilter);
+    }
+
+
+    /*
+     * Test registry rejects an object with the max array size  + 1.
+     */
+    @Test(dataProvider="bindData")
+    public void simpleBind(String name, Remote obj, boolean blacklisted) throws RemoteException, AlreadyBoundException, NotBoundException {
+        try {
+            registry.bind(name, obj);
+            Assert.assertFalse(blacklisted, "Registry filter did not reject (but should have) ");
+            registry.unbind(name);
+        } catch (Exception rex) {
+            Assert.assertTrue(blacklisted, "Registry filter should not have rejected");
+        }
+    }
+
+    /*
+    * Test registry rejects an object with a well known class
+    * if blacklisted in the security properties.
+    */
+    @Test
+    public void simpleRejectableClass() throws RemoteException, AlreadyBoundException, NotBoundException {
+        RejectableClass r1 = null;
+        try {
+            String name = "reject1";
+            r1 = new RejectableClass();
+            registry.bind(name, r1);
+            registry.unbind(name);
+            Assert.assertNull(registryFilter, "Registry filter should not have rejected");
+        } catch (Exception rex) {
+            Assert.assertNotNull(registryFilter, "Registry filter should have rejected");
+        }
+    }
+
+    /**
+     * A simple Serializable Remote object that is passed by value.
+     * It and its contents are checked by the Registry serial filter.
+     */
+    static class XX implements Serializable, Remote {
+        private static final long serialVersionUID = 362498820763181265L;
+
+        final Object obj;
+
+        XX(Object obj) {
+            this.obj = obj;
+        }
+
+        public String toString() {
+            return super.toString() + "//" + Objects.toString(obj);
+        }
+    }
+    /**
+     * A simple Serializable Remote object that is passed by value.
+     * It and its contents are checked by the Registry serial filter.
+     */
+    static class RejectableClass implements Serializable, Remote {
+        private static final long serialVersionUID = 362498820763181264L;
+
+        RejectableClass() {}
+    }
+
+}
diff --git a/jdk/test/java/rmi/registry/serialFilter/java.security-extra1 b/jdk/test/java/rmi/registry/serialFilter/java.security-extra1
new file mode 100644
index 0000000..2629e99
--- /dev/null
+++ b/jdk/test/java/rmi/registry/serialFilter/java.security-extra1
@@ -0,0 +1,8 @@
+# RMI Registry Input Serial Filter
+#
+# The filter pattern uses the same format as java.io.ObjectInputStream.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+sun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass
+
diff --git a/jdk/test/java/rmi/registry/serialFilter/security.policy b/jdk/test/java/rmi/registry/serialFilter/security.policy
new file mode 100644
index 0000000..554e9ea
--- /dev/null
+++ b/jdk/test/java/rmi/registry/serialFilter/security.policy
@@ -0,0 +1,4 @@
+grant {
+        permission java.security.AllPermission;
+};
+
diff --git a/jdk/test/java/security/Signature/SignatureLength.java b/jdk/test/java/security/Signature/SignatureLength.java
new file mode 100644
index 0000000..13c4a6d
--- /dev/null
+++ b/jdk/test/java/security/Signature/SignatureLength.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.*;
+
+/*
+ * @test
+ * @bug 8161571
+ * @summary Reject signatures presented for verification that contain extra
+ *          bytes.
+ * @run main SignatureLength
+ */
+public class SignatureLength {
+
+    public static void main(String[] args) throws Exception {
+        main0("EC", 256, "SHA256withECDSA", "SunEC");
+        main0("RSA", 2048, "SHA256withRSA", "SunRsaSign");
+        main0("DSA", 2048, "SHA256withDSA", "SUN");
+
+        if (System.getProperty("os.name").equals("SunOS")) {
+            main0("EC", 256, "SHA256withECDSA", null);
+            main0("RSA", 2048, "SHA256withRSA", null);
+        }
+    }
+
+    private static void main0(String keyAlgorithm, int keysize,
+            String signatureAlgorithm, String provider) throws Exception {
+        byte[] plaintext = "aaa".getBytes("UTF-8");
+
+        // Generate
+        KeyPairGenerator generator =
+            provider == null ?
+                (KeyPairGenerator) KeyPairGenerator.getInstance(keyAlgorithm) :
+                (KeyPairGenerator) KeyPairGenerator.getInstance(
+                                       keyAlgorithm, provider);
+        generator.initialize(keysize);
+        System.out.println("Generating " + keyAlgorithm + " keypair using " +
+            generator.getProvider().getName() + " JCE provider");
+        KeyPair keypair = generator.generateKeyPair();
+
+        // Sign
+        Signature signer =
+            provider == null ?
+                Signature.getInstance(signatureAlgorithm) :
+                Signature.getInstance(signatureAlgorithm, provider);
+        signer.initSign(keypair.getPrivate());
+        signer.update(plaintext);
+        System.out.println("Signing using " + signer.getProvider().getName() +
+            " JCE provider");
+        byte[] signature = signer.sign();
+
+        // Invalidate
+        System.out.println("Invalidating signature ...");
+        byte[] badSignature = new byte[signature.length + 5];
+        System.arraycopy(signature, 0, badSignature, 0, signature.length);
+        badSignature[signature.length] = 0x01;
+        badSignature[signature.length + 1] = 0x01;
+        badSignature[signature.length + 2] = 0x01;
+        badSignature[signature.length + 3] = 0x01;
+        badSignature[signature.length + 4] = 0x01;
+
+        // Verify
+        Signature verifier =
+            provider == null ?
+                Signature.getInstance(signatureAlgorithm) :
+                Signature.getInstance(signatureAlgorithm, provider);
+        verifier.initVerify(keypair.getPublic());
+        verifier.update(plaintext);
+        System.out.println("Verifying using " +
+            verifier.getProvider().getName() + " JCE provider");
+
+        try {
+            System.out.println("Valid? " + verifier.verify(badSignature));
+            throw new Exception(
+                "ERROR: expected a SignatureException but none was thrown");
+        } catch (SignatureException e) {
+            System.out.println("OK: caught expected exception: " + e);
+        }
+        System.out.println();
+    }
+}
diff --git a/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java b/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java
new file mode 100644
index 0000000..4532e83
--- /dev/null
+++ b/jdk/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8139565
+ * @summary Restrict certificates with DSA keys less than 1024 bits
+ *
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.2
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.2
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.1
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.1
+ * @run main/othervm DisabledShortDSAKeys PKIX TLSv1
+ * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1
+ * @run main/othervm DisabledShortDSAKeys PKIX SSLv3
+ * @run main/othervm DisabledShortDSAKeys SunX509 SSLv3
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.Security;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.util.Base64;
+
+
+public class DisabledShortDSAKeys {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    // Certificates and key used in the test.
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIDDjCCAs2gAwIBAgIJAO5/hbm1ByJOMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +
+        "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzcwMTI2MDQz\n" +
+        "NTQ2WjAfMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXhhbXBsZTCCAbgwggEsBgcq\n" +
+        "hkjOOAQBMIIBHwKBgQC4aSK8nBYdWJtuBkz6yoDyjZnNuGFSpDmx1ggKpLpcnPuw\n" +
+        "YKAbUhqdYhZtaIqQ4aO0T1ZS/HuOM0zvddnMUidFNX3RUvDkvdD/JYOnjqzCm+xW\n" +
+        "U0NFuPHZdapQY5KFk3ugkqZpHLY1StZbu0qugZOZjbBOMwB7cHAbMDuVpEr8DQIV\n" +
+        "AOi+ig+h3okFbWEE9MztiI2+DqNrAoGBAKh2EZbuWU9NoHglhVzfDUoz8CeyW6W6\n" +
+        "rUZuIOQsjWaYOeRPWX0UVAGq9ykIOfamEpurKt4H8ge/pHaL9iazJjonMHOXG12A\n" +
+        "0lALsMDGv22zVaJzXjOBvdPzc87opr0LIVgHASKOcDYjsICKNYPlS2cL3MJoD+bj\n" +
+        "NAR67b90VBbEA4GFAAKBgQCGrkRp2tdj2mZF7Qz0tO6p3xSysbEfN6QZxOJYPTvM\n" +
+        "yIYfLV9Yoy7XaRd/mCpJo/dqmsZMzowtyi+u+enuVpOLKiq/lyCktL+xUzZAjLT+\n" +
+        "9dafHlS1wR3pDSa1spo9xTEi4Ff/DQDHcdGalBxSXX/UdRtSecIYAp5/fkt3QZ5v\n" +
+        "0aOBkTCBjjAdBgNVHQ4EFgQUX4qbP5PgBx1J8BJ8qEgfoKVLSnQwTwYDVR0jBEgw\n" +
+        "RoAUX4qbP5PgBx1J8BJ8qEgfoKVLSnShI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
+        "VQQKEwdFeGFtcGxlggkA7n+FubUHIk4wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E\n" +
+        "BAMCAgQwCQYHKoZIzjgEAwMwADAtAhUAkr5bINXyy/McAx6qwhb6r0/QJUgCFFUP\n" +
+        "CZokA4/NqJIgq8ThpTQAE8SB\n" +
+        "-----END CERTIFICATE-----";
+
+    static String targetCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICUjCCAhGgAwIBAgIJAIiDrs/4W8rtMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +
+        "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzUxMTAzMDQz\n" +
+        "NTQ2WjA5MQswCQYDVQQGEwJVUzEQMA4GA1UECgwHRXhhbXBsZTEYMBYGA1UEAwwP\n" +
+        "d3d3LmV4YW1wbGUuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSv\n" +
+        "ThR/8GHpbL49KyWRJBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmp\n" +
+        "zYlUywIVAJLDcf4JXhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk\n" +
+        "5B8+ZHaHRi2KQ00ejilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14A0MA\n" +
+        "AkAYb+DYlFgStFhF1ip7rFzY8K6i/3ellkXI2umI/XVwxUQTHSlk5nFOep5Dfzm9\n" +
+        "pADJwuSe1qGHsHB5LpMZPVpto4GEMIGBMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgPo\n" +
+        "MB0GA1UdDgQWBBT8nsFyccF4q1dtpWE1dkNK5UiXtTAfBgNVHSMEGDAWgBRfips/\n" +
+        "k+AHHUnwEnyoSB+gpUtKdDAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
+        "CCsGAQUFBwMDMAkGByqGSM44BAMDMAAwLQIUIcIlxpIwaZXdpMC+U076unR1Mp8C\n" +
+        "FQCD/NE8O0xwq57nwFfp7tUvUHYMMA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8, key size is 512 bits.
+    static String targetPrivateKey =
+        "MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSvThR/8GHpbL49KyWR\n" +
+        "JBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmpzYlUywIVAJLDcf4J\n" +
+        "XhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk5B8+ZHaHRi2KQ00e\n" +
+        "jilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14BBYCFHB2Wek2g5hpNj5y\n" +
+        "RQfCc6CFO0dv";
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = generateSSLContext(null, targetCertStr,
+                                            targetPrivateKey);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket)sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
+            try (InputStream sslIS = sslSocket.getInputStream()) {
+                sslIS.read();
+            }
+
+            throw new Exception(
+                    "DSA keys shorter than 1024 bits should be disabled");
+        } catch (SSLHandshakeException sslhe) {
+            // the expected exception, ignore
+        }
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = generateSSLContext(trustedCertStr, null, null);
+        SSLSocketFactory sslsf = context.getSocketFactory();
+
+        try (SSLSocket sslSocket =
+            (SSLSocket)sslsf.createSocket("localhost", serverPort)) {
+
+            // only enable the target protocol
+            sslSocket.setEnabledProtocols(new String[] {enabledProtocol});
+
+            // enable a block cipher
+            sslSocket.setEnabledCipherSuites(
+                new String[] {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"});
+
+            try (OutputStream sslOS = sslSocket.getOutputStream()) {
+                sslOS.write('B');
+                sslOS.flush();
+            }
+
+            throw new Exception(
+                    "DSA keys shorter than 1024 bits should be disabled");
+        } catch (SSLHandshakeException sslhe) {
+            // the expected exception, ignore
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    private static String tmAlgorithm;        // trust manager
+    private static String enabledProtocol;    // the target protocol
+
+    private static void parseArguments(String[] args) {
+        tmAlgorithm = args[0];
+        enabledProtocol = args[1];
+    }
+
+    private static SSLContext generateSSLContext(String trustedCertStr,
+            String keyCertStr, String keySpecStr) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        Certificate trusedCert = null;
+        ByteArrayInputStream is = null;
+        if (trustedCertStr != null) {
+            is = new ByteArrayInputStream(trustedCertStr.getBytes());
+            trusedCert = cf.generateCertificate(is);
+            is.close();
+
+            ks.setCertificateEntry("DSA Export Signer", trusedCert);
+        }
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                                Base64.getMimeDecoder().decode(keySpecStr));
+            KeyFactory kf = KeyFactory.getInstance("DSA");
+            DSAPrivateKey priKey =
+                    (DSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            Certificate[] chain = null;
+            if (trusedCert != null) {
+                chain = new Certificate[2];
+                chain[0] = keyCert;
+                chain[1] = trusedCert;
+            } else {
+                chain = new Certificate[1];
+                chain[0] = keyCert;
+            }
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+        tmf.init(ks);
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        if (keyCertStr != null && !keyCertStr.isEmpty()) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            ks = null;
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        if (debug)
+            System.setProperty("javax.net.debug", "all");
+
+        /*
+         * Get the customized arguments.
+         */
+        parseArguments(args);
+
+        /*
+         * Start the tests.
+         */
+        new DisabledShortDSAKeys();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    DisabledShortDSAKeys() throws Exception {
+        Exception startException = null;
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            startException = e;
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            if (serverThread != null) {
+                serverThread.join();
+            }
+        } else {
+            if (clientThread != null) {
+                clientThread.join();
+            }
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+        } else {
+            remote = clientException;
+            local = serverException;
+        }
+
+        Exception exception = null;
+
+        /*
+         * Check various exception conditions.
+         */
+        if ((local != null) && (remote != null)) {
+            // If both failed, return the curthread's exception.
+            local.initCause(remote);
+            exception = local;
+        } else if (local != null) {
+            exception = local;
+        } else if (remote != null) {
+            exception = remote;
+        } else if (startException != null) {
+            exception = startException;
+        }
+
+        /*
+         * If there was an exception *AND* a startException,
+         * output it.
+         */
+        if (exception != null) {
+            if (exception != startException && startException != null) {
+                exception.addSuppressed(startException);
+            }
+            throw exception;
+        }
+
+        // Fall-through: no exception to throw!
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died...");
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died...");
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
diff --git a/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
index f686cf7..9a8e028 100644
--- a/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
+++ b/jdk/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java
@@ -41,7 +41,8 @@
  * @bug 8076221
  * @summary Check if weak cipher suites are disabled
  * @run main/othervm DisabledAlgorithms default
- * @run main/othervm DisabledAlgorithms empty
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,secp192r1"
+ *     DisabledAlgorithms empty
  */
 public class DisabledAlgorithms {
 
@@ -97,6 +98,11 @@
                 System.out.println("jdk.tls.disabledAlgorithms = "
                         + Security.getProperty("jdk.tls.disabledAlgorithms"));
 
+                // some of the certs in our test are weak; disable
+                Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+                System.out.println("jdk.certpath.disabledAlgorithms = "
+                        + Security.getProperty("jdk.cerpath.disabledAlgorithms"));
+
                 // check if RC4 cipher suites can be used
                 // if jdk.tls.disabledAlgorithms is empty
                 checkSuccess(rc4_ciphersuites);
@@ -224,6 +230,7 @@
                     socket.getSession().invalidate();
                 } catch (SSLHandshakeException e) {
                     System.out.println("Server: run: " + e);
+                    e.printStackTrace();
                     sslError = true;
                     stopped = true;
                 } catch (IOException e) {
diff --git a/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java b/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java
new file mode 100644
index 0000000..9e7e692
--- /dev/null
+++ b/jdk/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8148516
+ * @summary Improve the default strength of EC in JDK
+ * @run main/othervm ECCurvesconstraints PKIX
+ * @run main/othervm ECCurvesconstraints SunX509
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.Security;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.util.Base64;
+
+
+public class ECCurvesconstraints {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = false;
+
+    /*
+     * Where do we find the keystores?
+     */
+    // Certificates and key used in the test.
+    //
+    // EC curve: secp224k1
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBCzCBugIEVz2lcjAKBggqhkjOPQQDAjAaMRgwFgYDVQQDDA93d3cuZXhhbXBs\n" +
+        "ZS5vcmcwHhcNMTYwNTE5MTEzNzM5WhcNMTcwNTE5MTEzNzM5WjAaMRgwFgYDVQQD\n" +
+        "DA93d3cuZXhhbXBsZS5vcmcwTjAQBgcqhkjOPQIBBgUrgQQAIAM6AAT68uovMZ8f\n" +
+        "KARn5NOjvieJaq6h8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4\n" +
+        "djAKBggqhkjOPQQDAgNAADA9AhwMNIujM0R0llpPH6d89d1S3VRGH/78ovc+zw51\n" +
+        "Ah0AuZ1YlQkUbrJIzkuPSICxz5UfCWPe+7w4as+wiA==\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8
+    static String targetPrivateKey =
+        "MIGCAgEAMBAGByqGSM49AgEGBSuBBAAgBGswaQIBAQQdAPbckc86mgW/zexB1Ajq\n" +
+        "38HntWOjdxL6XSoiAsWgBwYFK4EEACChPAM6AAT68uovMZ8fKARn5NOjvieJaq6h\n" +
+        "8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4dg==";
+
+    static String[] serverCerts = {trustedCertStr};
+    static String[] serverKeys  = {targetPrivateKey};
+    static String[] clientCerts = {trustedCertStr};
+    static String[] clientKeys  = {targetPrivateKey};
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = generateSSLContext(false);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket)sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+        try {
+            sslSocket.setSoTimeout(5000);
+            sslSocket.setSoLinger(true, 5);
+
+            InputStream sslIS = sslSocket.getInputStream();
+            OutputStream sslOS = sslSocket.getOutputStream();
+
+            sslIS.read();
+            sslOS.write('A');
+            sslOS.flush();
+
+            throw new Exception("EC curve secp224k1 should be disabled");
+        } catch (SSLHandshakeException she) {
+            // expected exception: no cipher suites in common
+            System.out.println("Expected exception: " + she);
+        } finally {
+            sslSocket.close();
+            sslServerSocket.close();
+        }
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = generateSSLContext(true);
+        SSLSocketFactory sslsf = context.getSocketFactory();
+
+        SSLSocket sslSocket =
+            (SSLSocket)sslsf.createSocket("localhost", serverPort);
+
+        try {
+            sslSocket.setSoTimeout(5000);
+            sslSocket.setSoLinger(true, 5);
+
+            InputStream sslIS = sslSocket.getInputStream();
+            OutputStream sslOS = sslSocket.getOutputStream();
+
+            sslOS.write('B');
+            sslOS.flush();
+            sslIS.read();
+
+            throw new Exception("EC curve secp224k1 should be disabled");
+        } catch (SSLHandshakeException she) {
+            // expected exception: Received fatal alert
+            System.out.println("Expected exception: " + she);
+        } finally {
+            sslSocket.close();
+        }
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    private static String tmAlgorithm;             // trust manager
+
+    private static void parseArguments(String[] args) {
+        tmAlgorithm = args[0];
+    }
+
+    private static SSLContext generateSSLContext(boolean isClient)
+            throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trustedCertStr.getBytes());
+        Certificate trusedCert = cf.generateCertificate(is);
+        is.close();
+
+        ks.setCertificateEntry("Export Signer", trusedCert);
+
+        String[] certStrs = null;
+        String[] keyStrs = null;
+        if (isClient) {
+            certStrs = clientCerts;
+            keyStrs = clientKeys;
+        } else {
+            certStrs = serverCerts;
+            keyStrs = serverKeys;
+        }
+
+        for (int i = 0; i < certStrs.length; i++) {
+            // generate the private key.
+            String keySpecStr = keyStrs[i];
+            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                                Base64.getMimeDecoder().decode(keySpecStr));
+            KeyFactory kf = KeyFactory.getInstance("EC");
+            ECPrivateKey priKey =
+                    (ECPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            String keyCertStr = certStrs[i];
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = keyCert;
+            chain[1] = trusedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("key-entry-" + i, priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+        tmf.init(ks);
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+        kmf.init(ks, passphrase);
+
+        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        ks = null;
+
+        return ctx;
+    }
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+
+        /*
+         * Get the customized arguments.
+         */
+        parseArguments(args);
+
+        /*
+         * Start the tests.
+         */
+        new ECCurvesconstraints();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ECCurvesconstraints() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died, because of " + e);
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died, because of " + e);
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
diff --git a/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java
new file mode 100644
index 0000000..cc05b56
--- /dev/null
+++ b/jdk/test/javax/xml/crypto/dsig/SecureValidationPolicy.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8151893
+ * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property
+ * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom
+ */
+
+import java.security.Security;
+import java.util.List;
+import java.util.Arrays;
+import org.jcp.xml.dsig.internal.dom.Policy;
+
+public class SecureValidationPolicy {
+
+    public static void main(String[] args) throws Exception {
+
+        List<String> restrictedSchemes = Arrays.asList("file:/tmp/foo",
+            "http://java.com", "https://java.com");
+        List<String> restrictedAlgs = Arrays.asList(
+            "http://www.w3.org/TR/1999/REC-xslt-19991116",
+            "http://www.w3.org/2001/04/xmldsig-more#rsa-md5",
+            "http://www.w3.org/2001/04/xmldsig-more#hmac-md5",
+            "http://www.w3.org/2001/04/xmldsig-more#md5");
+
+        // Test expected defaults
+        System.out.println("Testing defaults");
+        if (!Policy.restrictNumTransforms(6)) {
+            throw new Exception("maxTransforms not enforced");
+        }
+        if (!Policy.restrictNumReferences(31)) {
+            throw new Exception("maxReferences not enforced");
+        }
+        for (String scheme : restrictedSchemes) {
+            if (!Policy.restrictReferenceUriScheme(scheme)) {
+                throw new Exception(scheme + " scheme not restricted");
+            }
+        }
+        for (String alg : restrictedAlgs) {
+            if (!Policy.restrictAlg(alg)) {
+                throw new Exception(alg + " alg not restricted");
+            }
+        }
+        if (!Policy.restrictDuplicateIds()) {
+            throw new Exception("noDuplicateIds not enforced");
+        }
+        if (!Policy.restrictRetrievalMethodLoops()) {
+            throw new Exception("noRetrievalMethodLoops not enforced");
+        }
+    }
+}
diff --git a/jdk/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java b/jdk/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java
new file mode 100644
index 0000000..6244641
--- /dev/null
+++ b/jdk/test/javax/xml/jaxp/transform/8167179/NamespacePrefixTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8167179
+ * @run testng/othervm NamespacePrefixTest
+ * @summary This class tests the generation of namespace prefixes
+ */
+public class NamespacePrefixTest {
+
+    @Test
+    public void testReuseTemplates() throws Exception {
+        final TransformerFactory tf = TransformerFactory.newInstance();
+        final Source xslsrc = new StreamSource(new StringReader(XSL));
+        final Templates tmpl = tf.newTemplates(xslsrc);
+        for (int i = 0; i < TRANSF_COUNT; i++) {
+            checkResult(doTransformation(tmpl.newTransformer()));
+        }
+    }
+
+    @Test
+    public void testReuseTransformer() throws Exception {
+        final TransformerFactory tf = TransformerFactory.newInstance();
+        final Source xslsrc = new StreamSource(new StringReader(XSL));
+        final Transformer t = tf.newTransformer(xslsrc);
+        for (int i = 0; i < TRANSF_COUNT; i++) {
+            checkResult(doTransformation(t));
+        }
+    }
+
+    @Test
+    public void testConcurrentTransformations() throws Exception {
+        final TransformerFactory tf = TransformerFactory.newInstance();
+        final Source xslsrc = new StreamSource(new StringReader(XSL));
+        final Templates tmpl = tf.newTemplates(xslsrc);
+        concurrentTestPassed.set(true);
+
+        // Execute multiple TestWorker tasks
+        for (int id = 0; id < THREADS_COUNT; id++) {
+            EXECUTOR.execute(new TransformerThread(tmpl.newTransformer(), id));
+        }
+        // Initiate shutdown of previously submitted task
+        EXECUTOR.shutdown();
+        // Wait for termination of submitted tasks
+        if (!EXECUTOR.awaitTermination(THREADS_COUNT, TimeUnit.SECONDS)) {
+            // If not all tasks terminates during the time out force them to shutdown
+            EXECUTOR.shutdownNow();
+        }
+        // Check if all transformation threads generated the correct namespace prefix
+        assertTrue(concurrentTestPassed.get());
+    }
+
+    // Do one transformation with the provided transformer
+    private static String doTransformation(Transformer t) throws Exception {
+        StringWriter resWriter = new StringWriter();
+        Source xmlSrc = new StreamSource(new StringReader(XML));
+        t.transform(xmlSrc, new StreamResult(resWriter));
+        return resWriter.toString();
+    }
+
+    // Check if the transformation result string contains the
+    // element with the exact namespace prefix generated.
+    private static void checkResult(String result) {
+        // Check prefix of 'Element2' element, it should always be the same
+        assertTrue(result.contains(EXPECTED_CONTENT));
+    }
+
+    // Check if the transformation result string contains the element with
+    // the exact namespace prefix generated by current thread.
+    // If the expected prefix is not found and there was no failures observed by
+    // other test threads then mark concurrent test as failed.
+    private static void checkThreadResult(String result, int id) {
+        boolean res = result.contains(EXPECTED_CONTENT);
+        System.out.printf("%d: transformation result: %s%n", id, res ? "Pass" : "Fail");
+        if (!res) {
+            System.out.printf("%d result:%s%n", id, result);
+        }
+        concurrentTestPassed.compareAndSet(true, res);
+    }
+
+    // TransformerThread task that does the transformation similar
+    // to testReuseTransformer test method
+    private class TransformerThread implements Runnable {
+
+        private final Transformer transformer;
+        private final int id;
+
+        TransformerThread(Transformer transformer, int id) {
+            this.transformer = transformer;
+            this.id = id;
+        }
+
+        @Override
+        public void run() {
+            try {
+                System.out.printf("%d: waiting for barrier%n", id);
+                //Synchronize startup of all tasks
+                BARRIER.await();
+                System.out.printf("%d: starting transformation%n", id);
+                checkThreadResult(doTransformation(transformer), id);
+            } catch (Exception ex) {
+                throw new RuntimeException("TransformerThread " + id + " failed", ex);
+            }
+        }
+    }
+
+    // Number of subsequent transformations
+    private static final int TRANSF_COUNT = 10;
+
+    // Number of transformer threads running concurently
+    private static final int THREADS_COUNT = 10;
+
+    // Variable for storing the concurrent transformation test result. It is
+    // updated by transformer threads
+    private static final AtomicBoolean concurrentTestPassed = new AtomicBoolean(true);
+
+    // Cyclic barrier for threads startup synchronization
+    private static final CyclicBarrier BARRIER = new CyclicBarrier(THREADS_COUNT);
+
+    // Thread pool
+    private static final ExecutorService EXECUTOR = Executors.newCachedThreadPool();
+
+    // XSL that transforms XML and produces unique namespace prefixes for each element
+    private final static String XSL = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
+            + " <xsl:template match=\"node()|@*\" priority=\"1\">\n"
+            + "     <xsl:copy>\n"
+            + "       <xsl:apply-templates select=\"node()|@*\"/>\n"
+            + "     </xsl:copy>\n"
+            + " </xsl:template>\n"
+            + " <xsl:template match=\"*\" priority=\"2\">\n"
+            + "  <xsl:element name=\"{name()}\" namespace=\"{namespace-uri()}\">\n"
+            + "   <xsl:apply-templates select=\"node()|@*\"/>\n"
+            + "  </xsl:element>\n"
+            + " </xsl:template>\n"
+            + "</xsl:stylesheet>";
+
+    // Simple XML content with root and two child elements
+    private final static String XML = "<TestRoot xmlns=\"test.xmlns\">\n"
+            + "  <Element1 xmlns=\"test.xmlns\">\n"
+            + "  </Element1>\n"
+            + "  <Element2 xmlns=\"test.xmlns\">\n"
+            + "  </Element2>\n"
+            + "</TestRoot>";
+
+    // With thread local namespace prefix index each transformation result should
+    // be the same and contain the same prefix for Element2
+    private final static String EXPECTED_CONTENT = "</ns2:Element2>";
+
+}
diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
index 13b07a5..327594d 100644
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
@@ -25,6 +25,7 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -43,7 +44,8 @@
 
 
     /**
-     * Create jar file with specified files from specified location.
+     * Create jar file with specified files. If a specified file does not exist,
+     * a new jar entry will be created with the file name itself as the content.
      */
     public static void createJar(String dest, Path filesLocation,
                                  String... fileNames) throws IOException {
@@ -63,6 +65,8 @@
                 }
                 try (FileInputStream fis = new FileInputStream(file)) {
                     Utils.transferBetweenStreams(fis, jos);
+                } catch (FileNotFoundException e) {
+                    jos.write(fileName.getBytes());
                 }
             }
         }
@@ -78,7 +82,17 @@
     }
 
     /**
-     * Add specified files to existing jar file.
+     * Add or remove specified files to existing jar file. If a specified file
+     * to be updated or added does not exist, the jar entry will be created
+     * with the file name itself as the content.
+     *
+     * @param src the original jar file name
+     * @param dest the new jar file name
+     * @param files the files to update. The list is broken into 2 groups
+     *              by a "-" string. The files before in the 1st group will
+     *              be either updated or added. The files in the 2nd group
+     *              will be removed. If no "-" exists, all files belong to
+     *              the 1st group.
      */
     public static void updateJar(String src, String dest, String... files)
             throws IOException {
@@ -94,8 +108,11 @@
                     JarEntry entry = entries.nextElement();
                     String name = entry.getName();
                     boolean found = false;
+                    boolean update = true;
                     for (String file : files) {
-                        if (name.equals(file)) {
+                        if (file.equals("-")) {
+                            update = false;
+                        } else if (name.equals(file)) {
                             updatedFiles.add(file);
                             found = true;
                             break;
@@ -103,11 +120,18 @@
                     }
 
                     if (found) {
+                        if (update) {
                         System.out.println(String.format("Updating %s with %s",
                                 dest, name));
                         jos.putNextEntry(new JarEntry(name));
                         try (FileInputStream fis = new FileInputStream(name)) {
                             Utils.transferBetweenStreams(fis, jos);
+                            } catch (FileNotFoundException e) {
+                                jos.write(name.getBytes());
+                            }
+                        } else {
+                            System.out.println(String.format("Removing %s from %s",
+                                    name, dest));
                         }
                     } else {
                         System.out.println(String.format("Copying %s to %s",
@@ -121,12 +145,17 @@
 
             // append new files
             for (String file : files) {
+                if (file.equals("-")) {
+                    break;
+                }
                 if (!updatedFiles.contains(file)) {
                     System.out.println(String.format("Adding %s with %s",
                             dest, file));
                     jos.putNextEntry(new JarEntry(file));
                     try (FileInputStream fis = new FileInputStream(file)) {
                         Utils.transferBetweenStreams(fis, jos);
+                    } catch (FileNotFoundException e) {
+                        jos.write(file.getBytes());
                     }
                 }
             }
diff --git a/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
new file mode 100644
index 0000000..68e0d49
--- /dev/null
+++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.reflect.ReflectionFactory;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @bug 8137058 8164908 8168980
+ * @run testng ReflectionFactoryTest
+ * @run testng/othervm/policy=security.policy ReflectionFactoryTest
+ * @summary Basic test for the unsupported ReflectionFactory
+ */
+
+public class ReflectionFactoryTest {
+
+    // Initialized by init()
+    static ReflectionFactory factory;
+
+    @DataProvider(name = "ClassConstructors")
+    static Object[][] classConstructors() {
+        return new Object[][] {
+                {Object.class},
+                {Foo.class},
+                {Bar.class},
+        };
+    }
+
+    @BeforeClass
+    static void init() {
+        factory = ReflectionFactory.getReflectionFactory();
+    }
+
+    /**
+     * Test that the correct Constructor is selected and run.
+     * @param type type of object to create
+     * @throws NoSuchMethodException - error
+     * @throws InstantiationException - error
+     * @throws IllegalAccessException - error
+     * @throws InvocationTargetException - error
+     */
+    @Test(dataProvider="ClassConstructors")
+    static void testConstructor(Class<?> type)
+        throws NoSuchMethodException, InstantiationException,
+            IllegalAccessException, InvocationTargetException
+    {
+        @SuppressWarnings("unchecked")
+        Constructor<?> c = factory.newConstructorForSerialization(type);
+
+        Object o = c.newInstance();
+        Assert.assertEquals(o.getClass(), type, "Instance is wrong type");
+        if (o instanceof Foo) {
+            Foo foo = (Foo)o;
+            foo.check();
+        }
+    }
+
+    @DataProvider(name = "NonSerialConstructors")
+    static Object[][] constructors() throws NoSuchMethodException {
+        return new Object[][] {
+                {Foo.class, Object.class.getDeclaredConstructor()},
+                {Foo.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Object.class.getDeclaredConstructor()},
+                {Baz.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Baz.class.getDeclaredConstructor()}
+        };
+    }
+
+    /**
+     * Tests that the given Constructor, in the hierarchy, is run.
+     */
+    @Test(dataProvider="NonSerialConstructors")
+    static void testNonSerializableConstructor(Class<?> cl,
+                                               Constructor<?> constructorToCall)
+        throws ReflectiveOperationException
+    {
+        @SuppressWarnings("unchecked")
+        Constructor<?> c = factory.newConstructorForSerialization(cl,
+                                                                  constructorToCall);
+
+        Object o = c.newInstance();
+        Assert.assertEquals(o.getClass(), cl, "Instance is wrong type");
+
+        int expectedFoo = 0;
+        int expectedBaz = 0;
+        if (constructorToCall.getName().equals("ReflectionFactoryTest$Foo")) {
+            expectedFoo = 1;
+        } else if (constructorToCall.getName().equals("ReflectionFactoryTest$Baz")) {
+            expectedFoo = 1;
+            expectedBaz = 4;
+        }
+
+        Assert.assertEquals(((Foo)o).foo(), expectedFoo);
+        if (o instanceof Baz) {
+            Assert.assertEquals(((Baz)o).baz(), expectedBaz);
+        }
+    }
+
+    static class Foo {
+        private int foo;
+        public Foo() {
+            this.foo = 1;
+        }
+
+        public String toString() {
+            return "foo: " + foo;
+        }
+
+        public void check() {
+            int expectedFoo = 1;
+            Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
+        }
+
+        public int foo() { return foo; }
+    }
+
+    static class Bar extends Foo implements Serializable {
+        private static final long serialVersionUID = 3L;
+
+        private int bar;
+        public Bar() {
+            this.bar = 1;
+        }
+
+        public String toString() {
+            return super.toString() + ", bar: " + bar;
+        }
+
+        public void check() {
+            super.check();
+            int expectedBar = 0;
+            Assert.assertEquals(bar, expectedBar, "bar() constructor not run");
+        }
+    }
+
+    static class Baz extends Foo {
+        private static final long serialVersionUID = 4L;
+
+        private final int baz;
+        public Baz() { this.baz = 4; }
+        public int baz() { return baz; }
+    }
+
+    /**
+     * Test newConstructorForExternalization returns the constructor and it can be called.
+     * @throws NoSuchMethodException - error
+     * @throws InstantiationException - error
+     * @throws IllegalAccessException - error
+     * @throws InvocationTargetException - error
+     */
+    @Test
+    static void newConstructorForExternalization()
+            throws NoSuchMethodException, InstantiationException,
+            IllegalAccessException, InvocationTargetException {
+        Constructor<?> cons = factory.newConstructorForExternalization(Ext.class);
+        Ext ext = (Ext)cons.newInstance();
+        Assert.assertEquals(ext.ext, 1, "Constructor not run");
+    }
+
+    static class Ext implements Externalizable {
+        private static final long serialVersionUID = 1L;
+
+        int ext;
+
+        public Ext() {
+            ext = 1;
+        }
+
+        @Override
+        public void writeExternal(ObjectOutput out) throws IOException {}
+
+        @Override
+        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
+    }
+
+    @Test
+    static void testReadWriteObjectForSerialization() throws Throwable {
+        MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class);
+        Assert.assertNotNull(readObjectMethod, "readObjectMethod not found");
+
+        MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class);
+        Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found");
+
+        MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class);
+        Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found");
+
+        MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class);
+        Assert.assertNotNull(readResolveMethod, "readResolveMethod not found");
+
+        MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class);
+        Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found");
+
+        byte[] data = null;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            Ser ser = new Ser();
+
+            writeReplaceMethod.invoke(ser);
+            Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called");
+            Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called");
+
+            writeObjectMethod.invoke(ser, oos);
+            Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called");
+            Assert.assertTrue(ser.writeObjectCalled, "writeObject not called");
+            oos.flush();
+            data = baos.toByteArray();
+        }
+
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+             ObjectInputStream ois = new ObjectInputStream(bais)) {
+            Ser ser2 = new Ser();
+
+            readObjectMethod.invoke(ser2, ois);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject not called");
+            Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called");
+            Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+            readObjectNoDataMethod.invoke(ser2, ois);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+            Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+            Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+            readResolveMethod.invoke(ser2);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+            Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+            Assert.assertTrue(ser2.readResolveCalled, "readResolve not called");
+        }
+    }
+
+    @Test
+    static void hasStaticInitializer() {
+        boolean actual = factory.hasStaticInitializerForSerialization(Ser.class);
+        Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong");
+    }
+
+    static class Ser implements Serializable {
+        private static final long serialVersionUID = 2L;
+        static {
+            // Define a static class initialization method
+        }
+
+        boolean readObjectCalled = false;
+        boolean readObjectNoDataCalled = false;
+        boolean writeObjectCalled = false;
+        boolean readResolveCalled = false;
+        boolean writeReplaceCalled = false;
+
+        public Ser() {}
+
+        private void readObject(ObjectInputStream ois) throws IOException {
+            Assert.assertFalse(writeObjectCalled, "readObject called too many times");
+            readObjectCalled = ois.readBoolean();
+        }
+
+        private void readObjectNoData(ObjectInputStream ois) throws IOException {
+            Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times");
+            readObjectNoDataCalled = true;
+        }
+
+        private void writeObject(ObjectOutputStream oos) throws IOException {
+            Assert.assertFalse(writeObjectCalled, "writeObject called too many times");
+            writeObjectCalled = true;
+            oos.writeBoolean(writeObjectCalled);
+        }
+
+        private Object writeReplace() {
+            Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times");
+            writeReplaceCalled = true;
+            return this;
+        }
+
+        private Object readResolve() {
+            Assert.assertFalse(readResolveCalled, "readResolve called too many times");
+            readResolveCalled = true;
+            return this;
+        }
+    }
+
+    /**
+     * Test the constructor of OptionalDataExceptions.
+     */
+    @Test
+    static void newOptionalDataException() {
+        OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true);
+        Assert.assertTrue(ode.eof, "eof wrong");
+        ode = factory.newOptionalDataExceptionForSerialization(false);
+        Assert.assertFalse(ode.eof, "eof wrong");
+
+    }
+
+
+
+    // Main can be used to run the tests from the command line with only testng.jar.
+    @SuppressWarnings("raw_types")
+    @Test(enabled = false)
+    public static void main(String[] args) {
+        Class<?>[] testclass = {ReflectionFactoryTest.class};
+        TestNG testng = new TestNG();
+        testng.setTestClasses(testclass);
+        testng.run();
+    }
+}
diff --git a/jdk/test/sun/reflect/ReflectionFactory/security.policy b/jdk/test/sun/reflect/ReflectionFactory/security.policy
new file mode 100644
index 0000000..8c30f3b
--- /dev/null
+++ b/jdk/test/sun/reflect/ReflectionFactory/security.policy
@@ -0,0 +1,11 @@
+// Individual Permissions for ReflectionFactoryTest
+grant {
+        // Permissions needed to run the test
+        permission java.util.PropertyPermission "*", "read";
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+        permission java.lang.RuntimePermission "reflectionFactoryAccess";
+};
diff --git a/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java b/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java
new file mode 100644
index 0000000..285a2b7
--- /dev/null
+++ b/jdk/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.InvalidClassException;
+import java.io.Serializable;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.UnmarshalException;
+
+import java.util.Objects;
+
+import sun.misc.ObjectInputFilter;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+import sun.rmi.transport.LiveRef;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @modules java.rmi/sun.rmi.registry
+ *          java.rmi/sun.rmi.server
+ *          java.rmi/sun.rmi.transport
+ *          java.rmi/sun.rmi.transport.tcp
+ * @run testng/othervm FilterUSRTest
+ * @summary Check objects exported with ObjectInputFilters via internal UnicastServerRef(2)
+ */
+public class FilterUSRTest {
+
+    /**
+     * Data to test serialFilter call counts.
+     * - name
+     * - Object
+     * - expected count of calls to checkInput.
+     *
+     * @return array of test data
+     */
+    @DataProvider(name = "bindData")
+    static Object[][] bindObjects() {
+        Object[][] data = {
+                {"SimpleString", "SimpleString", 0},
+                {"String", new XX("now is the time"), 1},
+                {"String[]", new XX(new String[3]), 3},
+                {"Long[4]", new XX(new Long[4]), 3},
+                {"RejectME", new XX(new RejectME()), -1},
+        };
+        return data;
+    }
+
+    /*
+     * Test exporting an object with a serialFilter using UnicastServerRef.exportObject().
+     * Send some objects and check the number of calls to the serialFilter.
+     */
+    @Test(dataProvider = "bindData")
+    public void UnicastServerRef(String name, Object obj, int expectedFilterCount) throws RemoteException {
+        try {
+            RemoteImpl impl = RemoteImpl.create();
+            UnicastServerRef ref = new UnicastServerRef(new LiveRef(0), impl.checker);
+
+            Echo client = (Echo) ref.exportObject(impl, null, false);
+
+            int count = client.filterCount(obj);
+            System.out.printf("count: %d, obj: %s%n", count, obj);
+            Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls");
+        } catch (RemoteException rex) {
+            if (expectedFilterCount == -1 &&
+                    UnmarshalException.class.equals(rex.getCause().getClass()) &&
+                    InvalidClassException.class.equals(rex.getCause().getCause().getClass())) {
+                return; // normal expected exception
+            }
+            rex.printStackTrace();
+            Assert.fail("unexpected remote exception", rex);
+        } catch (Exception ex) {
+            Assert.fail("unexpected exception", ex);
+        }
+    }
+
+    /*
+     * Test exporting an object with a serialFilter using UnicastServerRef2.exportObject()
+     * with explicit (but null) SocketFactories.
+     * Send some objects and check the number of calls to the serialFilter.
+     */
+    @Test(dataProvider = "bindData")
+    public void UnicastServerRef2(String name, Object obj, int expectedFilterCount) throws RemoteException {
+        try {
+            RemoteImpl impl = RemoteImpl.create();
+            UnicastServerRef2 ref = new UnicastServerRef2(0, null, null, impl.checker);
+
+            Echo client = (Echo) ref.exportObject(impl, null, false);
+
+            int count = client.filterCount(obj);
+            System.out.printf("count: %d, obj: %s%n", count, obj);
+            Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls");
+        } catch (RemoteException rex) {
+            if (expectedFilterCount == -1 &&
+                    UnmarshalException.class.equals(rex.getCause().getClass()) &&
+                    InvalidClassException.class.equals(rex.getCause().getCause().getClass())) {
+                return; // normal expected exception
+            }
+            rex.printStackTrace();
+            Assert.fail("unexpected remote exception", rex);
+        } catch (Exception rex) {
+            Assert.fail("unexpected exception", rex);
+        }
+    }
+
+    /**
+     * A simple Serializable holding an object that is passed by value.
+     * It and its contents are checked by the filter.
+     */
+    static class XX implements Serializable {
+        private static final long serialVersionUID = 362498820763181265L;
+
+        final Object obj;
+
+        XX(Object obj) {
+            this.obj = obj;
+        }
+
+        public String toString() {
+            return super.toString() + "//" + Objects.toString(obj);
+        }
+    }
+
+    interface Echo extends Remote {
+        int filterCount(Object obj) throws RemoteException;
+    }
+
+    /**
+     * This remote object just counts the calls to the serialFilter
+     * and returns it.  The caller can check the number against
+     * what was expected for the object passed as an argument.
+     * A new RemoteImpl is used for each test so the count starts at zero again.
+     */
+    static class RemoteImpl implements Echo {
+
+        private static final long serialVersionUID = 1L;
+
+        transient Checker checker;
+
+        static RemoteImpl create() throws RemoteException {
+            RemoteImpl impl = new RemoteImpl(new Checker());
+            return impl;
+        }
+
+        private RemoteImpl(Checker checker) throws RemoteException {
+            this.checker = checker;
+        }
+
+        public int filterCount(Object obj) throws RemoteException {
+            return checker.count();
+        }
+
+    }
+
+    /**
+     * A ObjectInputFilter that just counts when it is called.
+     */
+    static class Checker implements ObjectInputFilter {
+        int count;
+
+        @Override
+        public Status checkInput(ObjectInputFilter.FilterInfo info) {
+            if (info.serialClass() == RejectME.class) {
+                return Status.REJECTED;
+            }
+            count++;
+            return Status.UNDECIDED;
+        }
+
+        public int count() {
+            return count;
+        }
+    }
+
+    /**
+     * A class to be rejected by the filter.
+     */
+    static class RejectME implements Serializable {
+        private static final long serialVersionUID = 2L;
+    }
+
+}
diff --git a/jdk/test/sun/security/ec/TestEC.java b/jdk/test/sun/security/ec/TestEC.java
index 3dcad24..28d9648 100644
--- a/jdk/test/sun/security/ec/TestEC.java
+++ b/jdk/test/sun/security/ec/TestEC.java
@@ -35,7 +35,7 @@
  * @library ../pkcs11/sslecc
  * @library ../../../java/security/testlibrary
  * @compile -XDignore.symbol.file TestEC.java
- * @run main/othervm TestEC
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC
  */
 
 import java.security.NoSuchProviderException;
diff --git a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
index f754148..e19930b 100644
--- a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
+++ b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
@@ -33,7 +33,8 @@
  * @author Andreas Sterbenz
  * @library ..
  * @library ../../../../java/security/testlibrary
- * @run main/othervm ClientJSSEServerJSSE
+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1"
+ *      ClientJSSEServerJSSE
  */
 
 import java.security.*;
diff --git a/jdk/test/sun/security/smartcardio/TestChannel.java b/jdk/test/sun/security/smartcardio/TestChannel.java
index 3dc40297..4cc79da 100644
--- a/jdk/test/sun/security/smartcardio/TestChannel.java
+++ b/jdk/test/sun/security/smartcardio/TestChannel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,11 @@
 
     public static void main(String[] args) throws Exception {
         CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
 
         // establish a connection with the card
         Card card = terminal.connect("T=0");
diff --git a/jdk/test/sun/security/smartcardio/TestConnect.java b/jdk/test/sun/security/smartcardio/TestConnect.java
index b533b93..1dcd85b 100644
--- a/jdk/test/sun/security/smartcardio/TestConnect.java
+++ b/jdk/test/sun/security/smartcardio/TestConnect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,23 +39,12 @@
 public class TestConnect extends Utils {
 
     public static void main(String[] args) throws Exception {
-        TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null, "SunPCSC");
-        System.out.println(factory);
-
-        List<CardTerminal> terminals = factory.terminals().list();
-        System.out.println("Terminals: " + terminals);
-        if (terminals.isEmpty()) {
-            throw new Exception("No card terminals available");
+        CardTerminal terminal = getTerminal(args, "SunPCSC");
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
         }
-        CardTerminal terminal = terminals.get(0);
-
-        if (terminal.isCardPresent() == false) {
-            System.out.println("*** Insert card");
-            if (terminal.waitForCardPresent(20 * 1000) == false) {
-                throw new Exception("no card available");
-            }
-        }
-        System.out.println("card present: " + terminal.isCardPresent());
 
         Card card = terminal.connect("*");
         System.out.println("card: " + card);
diff --git a/jdk/test/sun/security/smartcardio/TestConnectAgain.java b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
index 9a2889e..24fac1c 100644
--- a/jdk/test/sun/security/smartcardio/TestConnectAgain.java
+++ b/jdk/test/sun/security/smartcardio/TestConnectAgain.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,11 @@
 
     public static void main(String[] args) throws Exception {
         CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
 
         Card card = terminal.connect("T=0");
         CardChannel channel = card.getBasicChannel();
diff --git a/jdk/test/sun/security/smartcardio/TestControl.java b/jdk/test/sun/security/smartcardio/TestControl.java
index 5160755..e5fb18f 100644
--- a/jdk/test/sun/security/smartcardio/TestControl.java
+++ b/jdk/test/sun/security/smartcardio/TestControl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,11 @@
 
     public static void main(String[] args) throws Exception {
         CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
 
         // establish a connection with the card
         Card card = terminal.connect("T=0");
diff --git a/jdk/test/sun/security/smartcardio/TestDefault.java b/jdk/test/sun/security/smartcardio/TestDefault.java
index 0808df4..eb345e9 100644
--- a/jdk/test/sun/security/smartcardio/TestDefault.java
+++ b/jdk/test/sun/security/smartcardio/TestDefault.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,12 @@
         TerminalFactory factory = TerminalFactory.getDefault();
         System.out.println("Type: " + factory.getType());
         List<CardTerminal> terminals = factory.terminals().list();
-        System.out.println("Terminals: " + terminals);
         if (terminals.isEmpty()) {
-            throw new Exception("no terminals");
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
         }
+        System.out.println("Terminals: " + terminals);
 
         System.out.println("OK.");
     }
diff --git a/jdk/test/sun/security/smartcardio/TestDirect.java b/jdk/test/sun/security/smartcardio/TestDirect.java
index 3dde7c3..5c09ea9 100644
--- a/jdk/test/sun/security/smartcardio/TestDirect.java
+++ b/jdk/test/sun/security/smartcardio/TestDirect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,10 +40,12 @@
     public static void main(String[] args) throws Exception {
         TerminalFactory terminalFactory = TerminalFactory.getDefault();
         List<CardTerminal> cardTerminals = terminalFactory.terminals().list();
-        System.out.println("Terminals: " + cardTerminals);
         if (cardTerminals.isEmpty()) {
-            throw new Exception("No card terminals available");
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
         }
+        System.out.println("Terminals: " + cardTerminals);
         CardTerminal cardTerminal = cardTerminals.get(0);
         Card card = cardTerminal.connect("DIRECT");
         card.disconnect(true);
diff --git a/jdk/test/sun/security/smartcardio/TestExclusive.java b/jdk/test/sun/security/smartcardio/TestExclusive.java
index a4c75e6..7187f7728 100644
--- a/jdk/test/sun/security/smartcardio/TestExclusive.java
+++ b/jdk/test/sun/security/smartcardio/TestExclusive.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,11 @@
 
     public static void main(String[] args) throws Exception {
         CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
 
         // establish a connection with the card
         Card card = terminal.connect("T=0");
diff --git a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
index 271cb21..cbbcc43 100644
--- a/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
+++ b/jdk/test/sun/security/smartcardio/TestMultiplePresent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,12 @@
 
     public static void main(String[] args) throws Exception {
         Utils.setLibrary(args);
-        TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
+        TerminalFactory factory = Utils.getTerminalFactory(null);
+        if (factory == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
         System.out.println(factory);
 
         CardTerminals terminals = factory.terminals();
@@ -49,7 +54,9 @@
         boolean multipleReaders = true;
         if (list.size() < 2) {
             if (list.isEmpty()) {
-                throw new Exception("no terminals");
+                System.out.println("Skipping the test: " +
+                        "no card terminals available");
+                return;
             }
             System.out.println("Only one reader present, using simplified test");
             multipleReaders = false;
diff --git a/jdk/test/sun/security/smartcardio/TestPresent.java b/jdk/test/sun/security/smartcardio/TestPresent.java
index fbfebd5..4e4c648 100644
--- a/jdk/test/sun/security/smartcardio/TestPresent.java
+++ b/jdk/test/sun/security/smartcardio/TestPresent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 import javax.smartcardio.CardTerminal;
 import javax.smartcardio.TerminalFactory;
 
-public class TestPresent {
+public class TestPresent extends Utils {
 
     private static class Timer {
         private long time = System.currentTimeMillis();
@@ -66,15 +66,12 @@
     }
 
     public static void main(String[] args) throws Exception {
-        TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
-        System.out.println(factory);
-
-        List<CardTerminal> terminals = factory.terminals().list();
-        System.out.println("Terminals: " + terminals);
-        if (terminals.isEmpty()) {
-            throw new Exception("No card terminals available");
+        CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
         }
-        CardTerminal terminal = terminals.get(0);
 
         while (terminal.isCardPresent()) {
             System.out.println("*** Remove card!");
diff --git a/jdk/test/sun/security/smartcardio/TestTransmit.java b/jdk/test/sun/security/smartcardio/TestTransmit.java
index 9092683..c49904b 100644
--- a/jdk/test/sun/security/smartcardio/TestTransmit.java
+++ b/jdk/test/sun/security/smartcardio/TestTransmit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,11 @@
 
     public static void main(String[] args) throws Exception {
         CardTerminal terminal = getTerminal(args);
+        if (terminal == null) {
+            System.out.println("Skipping the test: " +
+                    "no card terminals available");
+            return;
+        }
 
         Card card = terminal.connect("T=0");
         CardChannel channel = card.getBasicChannel();
diff --git a/jdk/test/sun/security/smartcardio/Utils.java b/jdk/test/sun/security/smartcardio/Utils.java
index b4edbcc..036b8dd 100644
--- a/jdk/test/sun/security/smartcardio/Utils.java
+++ b/jdk/test/sun/security/smartcardio/Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import java.io.StringReader;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 import java.util.List;
 import javax.smartcardio.CardTerminal;
@@ -43,26 +44,59 @@
         }
     }
 
+    static TerminalFactory getTerminalFactory(String provName) throws Exception {
+        try {
+            TerminalFactory factory = (provName == null)
+                    ? TerminalFactory.getInstance("PC/SC", null)
+                    : TerminalFactory.getInstance("PC/SC", null, provName);
+            System.out.println(factory);
+            return factory;
+        } catch (NoSuchAlgorithmException e) {
+            Throwable cause = e.getCause();
+            if (cause != null && cause.getMessage().startsWith("PC/SC not available")) {
+                return null;
+            }
+            throw e;
+        }
+    }
+
     static CardTerminal getTerminal(String[] args) throws Exception {
+        return getTerminal(args, null);
+    }
+
+    static CardTerminal getTerminal(String[] args, String provider) throws Exception {
         setLibrary(args);
 
-        TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
-        System.out.println(factory);
+        try {
+            TerminalFactory factory = (provider == null)
+                    ? TerminalFactory.getInstance("PC/SC", null)
+                    : TerminalFactory.getInstance("PC/SC", null, provider);
+            System.out.println(factory);
 
-        List<CardTerminal> terminals = factory.terminals().list();
-        System.out.println("Terminals: " + terminals);
-        if (terminals.isEmpty()) {
-            throw new Exception("No card terminals available");
-        }
-        CardTerminal terminal = terminals.get(0);
-
-        if (terminal.isCardPresent() == false) {
-            System.out.println("*** Insert card");
-            if (terminal.waitForCardPresent(20 * 1000) == false) {
-                throw new Exception("no card available");
+            List<CardTerminal> terminals = factory.terminals().list();
+            System.out.println("Terminals: " + terminals);
+            if (terminals.isEmpty()) {
+                return null;
             }
+            CardTerminal terminal = terminals.get(0);
+
+            if (terminal.isCardPresent() == false) {
+                System.out.println("*** Insert card");
+                if (terminal.waitForCardPresent(20 * 1000) == false) {
+                    throw new Exception("no card available");
+                }
+            }
+            System.out.println("card present: " + terminal.isCardPresent());
+
+            return terminal;
+
+        } catch (NoSuchAlgorithmException e) {
+            Throwable cause = e.getCause();
+            if (cause != null && cause.getMessage().startsWith("PC/SC not available")) {
+                return null;
+            }
+            throw e;
         }
-        return terminal;
     }
 
     static final byte[] C1 = parse("00 A4 04 00 07 A0 00 00 00 62 81 01 00");
diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
index 8a5db10..1cf22f0 100644
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,12 @@
 
 /*
  * @test
- * @bug 6916074
+ * @bug 6916074 8170131
  * @summary Add support for TLS 1.2
- * @run main/othervm PKIXExtendedTM
+ * @run main/othervm PKIXExtendedTM 0
+ * @run main/othervm PKIXExtendedTM 1
+ * @run main/othervm PKIXExtendedTM 2
+ * @run main/othervm PKIXExtendedTM 3
  */
 
 import java.net.*;
@@ -42,6 +45,7 @@
 import java.security.KeyFactory;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathValidatorException;
 import java.security.spec.*;
 import java.security.interfaces.*;
 import java.math.BigInteger;
@@ -792,20 +796,85 @@
     volatile Exception serverException = null;
     volatile Exception clientException = null;
 
-    public static void main(String args[]) throws Exception {
-        // MD5 is used in this test case, don't disable MD5 algorithm.
-        Security.setProperty("jdk.certpath.disabledAlgorithms",
-                "MD2, RSA keySize < 1024");
-        Security.setProperty("jdk.tls.disabledAlgorithms",
-                "SSLv3, RC4, DH keySize < 768");
+    static class Test {
+        String tlsDisAlgs;
+        String certPathDisAlgs;
+        boolean fail;
+        Test(String tlsDisAlgs, String certPathDisAlgs, boolean fail) {
+            this.tlsDisAlgs = tlsDisAlgs;
+            this.certPathDisAlgs = certPathDisAlgs;
+            this.fail = fail;
+        }
+    }
 
-        if (debug)
+    static Test[] tests = {
+        // MD5 is used in this test case, don't disable MD5 algorithm.
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, RSA keySize < 1024",
+            false),
+        // Disable MD5 but only if cert chains back to public root CA, should
+        // pass because the MD5 cert in this test case is issued by test CA
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, MD5 jdkCA, RSA keySize < 1024",
+            false),
+        // Disable MD5 alg via TLS property and expect failure
+        new Test(
+            "SSLv3, MD5, RC4, DH keySize < 768",
+            "MD2, RSA keySize < 1024",
+            true),
+        // Disable MD5 alg via certpath property and expect failure
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, MD5, RSA keySize < 1024",
+            true),
+    };
+
+    public static void main(String args[]) throws Exception {
+        if (args.length != 1) {
+            throw new Exception("Incorrect number of arguments");
+        }
+        Test test = tests[Integer.parseInt(args[0])];
+        Security.setProperty("jdk.tls.disabledAlgorithms", test.tlsDisAlgs);
+        Security.setProperty("jdk.certpath.disabledAlgorithms",
+                             test.certPathDisAlgs);
+
+        if (debug) {
             System.setProperty("javax.net.debug", "all");
+        }
 
         /*
          * Start the tests.
          */
-        new PKIXExtendedTM();
+        try {
+            new PKIXExtendedTM();
+            if (test.fail) {
+                throw new Exception("Expected MD5 certificate to be blocked");
+            }
+        } catch (Exception e) {
+            if (test.fail) {
+                // find expected cause
+                boolean correctReason = false;
+                Throwable cause = e.getCause();
+                while (cause != null) {
+                    if (cause instanceof CertPathValidatorException) {
+                        CertPathValidatorException cpve =
+                            (CertPathValidatorException)cause;
+                        if (cpve.getReason() == CertPathValidatorException.BasicReason.ALGORITHM_CONSTRAINED) {
+                            correctReason = true;
+                            break;
+                        }
+                    }
+                    cause = cause.getCause();
+                }
+                if (!correctReason) {
+                    throw new Exception("Unexpected exception", e);
+                }
+            } else {
+                throw e;
+            }
+        }
     }
 
     Thread clientThread = null;
diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java b/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
index 8c92a2b..516eb9c 100644
--- a/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
  * @bug 7188657
  * @summary There should be a way to reorder the JSSE ciphers
  * @run main/othervm UseCipherSuitesOrder
- *     TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ *     TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  */
 
 import java.io.*;
diff --git a/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java b/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
index 5e08f76..812732e 100644
--- a/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
+++ b/jdk/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java
@@ -26,7 +26,8 @@
  * @bug 4496785
  * @summary Verify that all ciphersuites work in all configurations
  * @author Andreas Sterbenz
- * @run main/othervm/timeout=300 ClientJSSEServerJSSE
+ * @run main/othervm/timeout=300 -Djdk.tls.namedGroups="secp256r1,secp192r1"
+ *      ClientJSSEServerJSSE
  */
 
 import java.security.Security;
diff --git a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
index bc4d6ed..321df20 100644
--- a/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
+++ b/jdk/test/sun/security/tools/jarsigner/TimestampCheck.java
@@ -22,25 +22,31 @@
  */
 
 import com.sun.net.httpserver.*;
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.security.KeyStore;
 import java.security.PrivateKey;
 import java.security.Signature;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
+import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
 import sun.misc.IOUtils;
+import jdk.testlibrary.*;
+import jdk.testlibrary.JarUtils;
 import sun.security.pkcs.ContentInfo;
 import sun.security.pkcs.PKCS7;
 import sun.security.pkcs.PKCS9Attribute;
@@ -52,11 +58,22 @@
 import sun.security.x509.AlgorithmId;
 import sun.security.x509.X500Name;
 
+/*
+ * @test
+ * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688
+ * @summary checking response of timestamp
+ * @modules java.base/sun.security.pkcs
+ *          java.base/sun.security.timestamp
+ *          java.base/sun.security.x509
+ *          java.base/sun.security.util
+ *          java.base/sun.security.tools.keytool
+ * @library /lib/testlibrary
+ * @run main/timeout=600 TimestampCheck
+ */
 public class TimestampCheck {
-    static final String TSKS = "tsks";
-    static final String JAR = "old.jar";
 
-    static final String defaultPolicyId = "2.3.4.5";
+    static final String defaultPolicyId = "2.3.4";
+    static String host = null;
 
     static class Handler implements HttpHandler, AutoCloseable {
 
@@ -75,11 +92,7 @@
             t.getRequestBody().read(input);
 
             try {
-                int path = 0;
-                if (t.getRequestURI().getPath().length() > 1) {
-                    path = Integer.parseInt(
-                            t.getRequestURI().getPath().substring(1));
-                }
+                String path = t.getRequestURI().getPath().substring(1);
                 byte[] output = sign(input, path);
                 Headers out = t.getResponseHeaders();
                 out.set("Content-Type", "application/timestamp-reply");
@@ -97,24 +110,9 @@
         /**
          * @param input The data to sign
          * @param path different cases to simulate, impl on URL path
-         * 0: normal
-         * 1: Missing nonce
-         * 2: Different nonce
-         * 3: Bad digets octets in messageImprint
-         * 4: Different algorithmId in messageImprint
-         * 5: whole chain in cert set
-         * 6: extension is missing
-         * 7: extension is non-critical
-         * 8: extension does not have timestamping
-         * 9: no cert in response
-         * 10: normal
-         * 11: always return default policy id
-         * 12: normal
-         * otherwise: normal
          * @returns the signed
          */
-        byte[] sign(byte[] input, int path) throws Exception {
-            // Read TSRequest
+        byte[] sign(byte[] input, String path) throws Exception {
             DerValue value = new DerValue(input);
             System.err.println("\nIncoming Request\n===================");
             System.err.println("Version: " + value.data.getInteger());
@@ -138,36 +136,35 @@
                 }
             }
 
-            // Write TSResponse
             System.err.println("\nResponse\n===================");
-            KeyStore ks = KeyStore.getInstance("JKS");
-            try (FileInputStream fis = new FileInputStream(keystore)) {
-                ks.load(fis, "changeit".toCharArray());
-            }
+            FileInputStream is = new FileInputStream(keystore);
+            KeyStore ks = KeyStore.getInstance("JCEKS");
+            ks.load(is, "changeit".toCharArray());
+            is.close();
 
             String alias = "ts";
-            if (path == 6) alias = "tsbad1";
-            if (path == 7) alias = "tsbad2";
-            if (path == 8) alias = "tsbad3";
+            if (path.startsWith("bad") || path.equals("weak")) {
+                alias = "ts" + path;
+            }
 
-            if (path == 11) {
+            if (path.equals("diffpolicy")) {
                 policyId = new ObjectIdentifier(defaultPolicyId);
             }
 
             DerOutputStream statusInfo = new DerOutputStream();
             statusInfo.putInteger(0);
 
-            DerOutputStream token = new DerOutputStream();
             AlgorithmId[] algorithms = {aid};
             Certificate[] chain = ks.getCertificateChain(alias);
-            X509Certificate[] signerCertificateChain = null;
+            X509Certificate[] signerCertificateChain;
             X509Certificate signer = (X509Certificate)chain[0];
-            if (path == 5) {   // Only case 5 uses full chain
+
+            if (path.equals("fullchain")) {   // Only case 5 uses full chain
                 signerCertificateChain = new X509Certificate[chain.length];
                 for (int i=0; i<chain.length; i++) {
                     signerCertificateChain[i] = (X509Certificate)chain[i];
                 }
-            } else if (path == 9) {
+            } else if (path.equals("nocert")) {
                 signerCertificateChain = new X509Certificate[0];
             } else {
                 signerCertificateChain = new X509Certificate[1];
@@ -179,11 +176,11 @@
             tst.putInteger(1);
             tst.putOID(policyId);
 
-            if (path != 3 && path != 4) {
+            if (!path.equals("baddigest") && !path.equals("diffalg")) {
                 tst.putDerValue(messageImprint);
             } else {
                 byte[] data = messageImprint.toByteArray();
-                if (path == 4) {
+                if (path.equals("diffalg")) {
                     data[6] = (byte)0x01;
                 } else {
                     data[data.length-1] = (byte)0x01;
@@ -198,10 +195,10 @@
             Calendar cal = Calendar.getInstance();
             tst.putGeneralizedTime(cal.getTime());
 
-            if (path == 2) {
+            if (path.equals("diffnonce")) {
                 tst.putInteger(1234);
-            } else if (path == 1) {
-                // do nothing
+            } else if (path.equals("nononce")) {
+                // no noce
             } else {
                 tst.putInteger(nonce);
             }
@@ -212,6 +209,8 @@
             DerOutputStream tstInfo2 = new DerOutputStream();
             tstInfo2.putOctetString(tstInfo.toByteArray());
 
+            // Always use the same algorithm at timestamp signing
+            // so it is different from the hash algorithm.
             Signature sig = Signature.getInstance("SHA1withRSA");
             sig.initSign((PrivateKey)(ks.getKey(
                     alias, "changeit".toCharArray())));
@@ -229,12 +228,11 @@
             SignerInfo signerInfo = new SignerInfo(
                     new X500Name(signer.getIssuerX500Principal().getName()),
                     signer.getSerialNumber(),
-                    aid, AlgorithmId.get("RSA"), sig.sign());
+                    AlgorithmId.get("SHA-1"), AlgorithmId.get("RSA"), sig.sign());
 
             SignerInfo[] signerInfos = {signerInfo};
-            PKCS7 p7 =
-                    new PKCS7(algorithms, contentInfo, signerCertificateChain,
-                    signerInfos);
+            PKCS7 p7 = new PKCS7(algorithms, contentInfo,
+                    signerCertificateChain, signerInfos);
             ByteArrayOutputStream p7out = new ByteArrayOutputStream();
             p7.encodeSignedData(p7out);
 
@@ -293,42 +291,79 @@
             stop();
         }
     }
-    public static void main(String[] args) throws Exception {
-        try (Handler tsa = Handler.init(0, TSKS);) {
+
+    public static void main(String[] args) throws Throwable {
+
+        prepare();
+
+        try (Handler tsa = Handler.init(0, "tsks");) {
             tsa.start();
             int port = tsa.getPort();
 
-            String cmd;
-            // Use -J-Djava.security.egd=file:/dev/./urandom to speed up
-            // nonce generation in timestamping request. Not avaibale on
-            // Windows and defaults to thread seed generator, not too bad.
-            if (System.getProperty("java.home").endsWith("jre")) {
-                cmd = System.getProperty("java.home") + "/../bin/jarsigner";
-            } else {
-                cmd = System.getProperty("java.home") + "/bin/jarsigner";
-            }
-
-            cmd += " -J-Djava.security.egd=file:/dev/./urandom"
-                    + " -debug -keystore " + TSKS + " -storepass changeit"
-                    + " -tsa http://localhost:" + port + "/%d"
-                    + " -signedjar new_%d.jar " + JAR + " old";
+            host = "http://localhost:" + port + "/";
 
             if (args.length == 0) {         // Run this test
-                jarsigner(cmd, 0, true);    // Success, normal call
-                jarsigner(cmd, 1, false);   // These 4 should fail
-                jarsigner(cmd, 2, false);
-                jarsigner(cmd, 3, false);
-                jarsigner(cmd, 4, false);
-                jarsigner(cmd, 5, true);    // Success, 6543440 solved.
-                jarsigner(cmd, 6, false);   // tsbad1
-                jarsigner(cmd, 7, false);   // tsbad2
-                jarsigner(cmd, 8, false);   // tsbad3
-                jarsigner(cmd, 9, false);   // no cert in timestamp
-                jarsigner(cmd + " -tsapolicyid 1.2.3.4", 10, true);
-                checkTimestamp("new_10.jar", "1.2.3.4", "SHA-256");
-                jarsigner(cmd + " -tsapolicyid 1.2.3.5", 11, false);
-                jarsigner(cmd + " -tsadigestalg SHA", 12, true);
-                checkTimestamp("new_12.jar", defaultPolicyId, "SHA-1");
+                sign("none")
+                        .shouldContain("is not timestamped")
+                        .shouldHaveExitValue(0);
+
+                sign("badku")
+                        .shouldHaveExitValue(0);
+                checkBadKU("badku.jar");
+
+                sign("normal")
+                        .shouldNotContain("is not timestamped")
+                        .shouldHaveExitValue(0);
+
+                sign("nononce")
+                        .shouldHaveExitValue(1);
+                sign("diffnonce")
+                        .shouldHaveExitValue(1);
+                sign("baddigest")
+                        .shouldHaveExitValue(1);
+                sign("diffalg")
+                        .shouldHaveExitValue(1);
+                sign("fullchain")
+                        .shouldHaveExitValue(0);   // Success, 6543440 solved.
+                sign("bad1")
+                        .shouldHaveExitValue(1);
+                sign("bad2")
+                        .shouldHaveExitValue(1);
+                sign("bad3")
+                        .shouldHaveExitValue(1);
+                sign("nocert")
+                        .shouldHaveExitValue(1);
+
+                sign("policy", "-tsapolicyid",  "1.2.3")
+                        .shouldHaveExitValue(0);
+                checkTimestamp("policy.jar", "1.2.3", "SHA-256");
+
+                sign("diffpolicy", "-tsapolicyid", "1.2.3")
+                        .shouldHaveExitValue(1);
+
+                sign("tsaalg", "-tsadigestalg", "SHA")
+                        .shouldHaveExitValue(0);
+                checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1");
+
+                sign("weak", "-digestalg", "MD2",
+                                "-sigalg", "MD2withRSA", "-tsadigestalg", "MD2")
+                        .shouldHaveExitValue(0);
+                checkWeak("weak.jar");
+
+                signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5")
+                        .shouldHaveExitValue(0);
+                checkHalfWeak("halfWeak.jar");
+
+                // sign with DSA key
+                signWithAliasAndTsa("sign1", "old.jar", "dsakey")
+                        .shouldHaveExitValue(0);
+                // sign with RSAkeysize < 1024
+                signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize")
+                        .shouldHaveExitValue(0);
+                checkMultiple("sign2.jar");
+
+                // When .SF or .RSA is missing or invalid
+                checkMissingOrInvalidFiles("normal.jar");
             } else {                        // Run as a standalone server
                 System.err.println("Press Enter to quit server");
                 System.in.read();
@@ -336,6 +371,132 @@
         }
     }
 
+    private static void checkMissingOrInvalidFiles(String s)
+            throws Throwable {
+        JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF");
+        verify("1.jar", "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldContain("Missing signature-related file META-INF/OLD.SF");
+        JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA");
+        verify("2.jar", "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldContain("Missing block file for signature-related file META-INF/OLD.SF");
+        JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF");
+        verify("3.jar", "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldContain("Unparsable signature-related file META-INF/OLD.SF");
+        JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA");
+        verify("4.jar", "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldContain("Unparsable signature-related file META-INF/OLD.RSA");
+    }
+
+    static OutputAnalyzer jarsigner(List<String> extra)
+            throws Throwable {
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
+                .addVMArg("-Duser.language=en")
+                .addVMArg("-Duser.country=US")
+                .addToolArg("-keystore")
+                .addToolArg("tsks")
+                .addToolArg("-storepass")
+                .addToolArg("changeit");
+        for (String s : extra) {
+            if (s.startsWith("-J")) {
+                launcher.addVMArg(s.substring(2));
+            } else {
+                launcher.addToolArg(s);
+            }
+        }
+        System.err.println("COMMAND: ");
+        for (String cmd : launcher.getCommand()) {
+            System.err.print(cmd + " ");
+        }
+        System.err.println();
+        return ProcessTools.executeCommand(launcher.getCommand());
+    }
+
+    static OutputAnalyzer verify(String file, String... extra)
+            throws Throwable {
+        List<String> args = new ArrayList<>();
+        args.add("-verify");
+        args.add(file);
+        args.addAll(Arrays.asList(extra));
+        return jarsigner(args);
+    }
+
+    static void checkBadKU(String file) throws Throwable {
+        System.err.println("BadKU: " + file);
+        verify(file)
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldContain("re-run jarsigner with debug enabled");
+        verify(file, "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("Signed by")
+                .shouldContain("treated as unsigned")
+                .shouldContain("re-run jarsigner with debug enabled");
+        verify(file, "-J-Djava.security.debug=jar")
+                .shouldHaveExitValue(0)
+                .shouldContain("SignatureException: Key usage restricted")
+                .shouldContain("treated as unsigned")
+                .shouldContain("re-run jarsigner with debug enabled");
+    }
+
+    static void checkWeak(String file) throws Throwable {
+        verify(file)
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldMatch("weak algorithm that is now disabled.")
+                .shouldMatch("Re-run jarsigner with the -verbose option for more details");
+        verify(file, "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldMatch("weak algorithm that is now disabled by")
+                .shouldMatch("Digest algorithm: .*weak")
+                .shouldMatch("Signature algorithm: .*weak")
+                .shouldMatch("Timestamp digest algorithm: .*weak")
+                .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
+                .shouldMatch("Timestamp signature algorithm: .*key.*weak");
+        verify(file, "-J-Djava.security.debug=jar")
+                .shouldHaveExitValue(0)
+                .shouldMatch("SignatureException:.*Disabled");
+    }
+
+    static void checkHalfWeak(String file) throws Throwable {
+        verify(file)
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldMatch("weak algorithm that is now disabled.")
+                .shouldMatch("Re-run jarsigner with the -verbose option for more details");
+        verify(file, "-verbose")
+                .shouldHaveExitValue(0)
+                .shouldContain("treated as unsigned")
+                .shouldMatch("weak algorithm that is now disabled by")
+                .shouldMatch("Digest algorithm: .*weak")
+                .shouldNotMatch("Signature algorithm: .*weak")
+                .shouldNotMatch("Timestamp digest algorithm: .*weak")
+                .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
+                .shouldNotMatch("Timestamp signature algorithm: .*key.*weak");
+     }
+
+    static void checkMultiple(String file) throws Throwable {
+        verify(file)
+                .shouldHaveExitValue(0)
+                .shouldContain("jar verified");
+        verify(file, "-verbose", "-certs")
+                .shouldHaveExitValue(0)
+                .shouldContain("jar verified")
+                .shouldMatch("X.509.*CN=dsakey")
+                .shouldNotMatch("X.509.*CN=weakkeysize")
+                .shouldMatch("Signed by .*CN=dsakey")
+                .shouldMatch("Signed by .*CN=weakkeysize")
+                .shouldMatch("Signature algorithm: .*key.*weak");
+     }
+
     static void checkTimestamp(String file, String policyId, String digestAlg)
             throws Exception {
         try (JarFile jf = new JarFile(file)) {
@@ -362,41 +523,75 @@
         }
     }
 
-    /**
-     * @param cmd the command line (with a hole to plug in)
-     * @param path the path in the URL, i.e, http://localhost/path
-     * @param expected if this command should succeed
-     */
-    static void jarsigner(String cmd, int path, boolean expected)
-            throws Exception {
-        System.err.println("Test " + path);
-        Process p = Runtime.getRuntime().exec(String.format(cmd, path, path));
-        BufferedReader reader = new BufferedReader(
-                new InputStreamReader(p.getErrorStream()));
-        while (true) {
-            String s = reader.readLine();
-            if (s == null) break;
-            System.err.println(s);
-        }
+    static int which = 0;
 
-        // Will not see noTimestamp warning
-        boolean seeWarning = false;
-        reader = new BufferedReader(
-                new InputStreamReader(p.getInputStream()));
-        while (true) {
-            String s = reader.readLine();
-            if (s == null) break;
-            System.err.println(s);
-            if (s.indexOf("Warning:") >= 0) {
-                seeWarning = true;
-            }
+    /**
+     * @param extra more args given to jarsigner
+     */
+    static OutputAnalyzer sign(String path, String... extra)
+            throws Throwable {
+        String alias = path.equals("badku") ? "badku" : "old";
+        return signWithAliasAndTsa(path, "old.jar", alias, extra);
+    }
+
+    static OutputAnalyzer signWithAliasAndTsa (String path, String jar,
+            String alias, String...extra) throws Throwable {
+        which++;
+        System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra));
+        List<String> args = new ArrayList<>();
+        args.add("-J-Djava.security.egd=file:/dev/./urandom");
+        args.add("-debug");
+        args.add("-signedjar");
+        args.add(path + ".jar");
+        args.add(jar);
+        args.add(alias);
+        if (!path.equals("none") && !path.equals("badku")) {
+            args.add("-tsa");
+            args.add(host + path);
+         }
+        args.addAll(Arrays.asList(extra));
+        return jarsigner(args);
+    }
+
+    static void prepare() throws Exception {
+        jdk.testlibrary.JarUtils.createJar("old.jar", "A");
+        Files.deleteIfExists(Paths.get("tsks"));
+        keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
+        keytool("-alias old -genkeypair -dname CN=old");
+        keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
+        keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize");
+        keytool("-alias badku -genkeypair -dname CN=badku");
+        keytool("-alias ts -genkeypair -dname CN=ts");
+        keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1");
+        keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
+        keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2");
+        keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
+
+        gencert("old");
+        gencert("dsakey");
+        gencert("weakkeysize");
+        gencert("badku", "-ext ku:critical=keyAgreement");
+        gencert("ts", "-ext eku:critical=ts");
+        gencert("tsweak", "-ext eku:critical=ts");
+        gencert("tsbad1");
+        gencert("tsbad2", "-ext eku=ts");
+        gencert("tsbad3", "-ext eku:critical=cs");
+    }
+
+    static void gencert(String alias, String... extra) throws Exception {
+        keytool("-alias " + alias + " -certreq -file " + alias + ".req");
+        String genCmd = "-gencert -alias ca -infile " +
+                alias + ".req -outfile " + alias + ".cert";
+        for (String s : extra) {
+            genCmd += " " + s;
         }
-        int result = p.waitFor();
-        if (expected && result != 0 || !expected && result == 0) {
-            throw new Exception("Failed");
-        }
-        if (seeWarning) {
-            throw new Exception("See warning");
-        }
+        keytool(genCmd);
+        keytool("-alias " + alias + " -importcert -file " + alias + ".cert");
+    }
+
+    static void keytool(String cmd) throws Exception {
+        cmd = "-keystore tsks -storepass changeit -keypass changeit " +
+                "-keyalg rsa -validity 200 " + cmd;
+        sun.security.tools.keytool.Main.main(cmd.split(" "));
     }
 }
diff --git a/jdk/test/sun/security/tools/jarsigner/ts.sh b/jdk/test/sun/security/tools/jarsigner/ts.sh
deleted file mode 100644
index 6cee680..0000000
--- a/jdk/test/sun/security/tools/jarsigner/ts.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-# 
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-# 
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-# 
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-# 
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6543842 6543440 6939248 8009636 8024302
-# @summary checking response of timestamp
-#
-# @run shell/timeout=600 ts.sh
-
-# Run for a long time because jarsigner with timestamp needs to create a
-# 64-bit random number and it might be extremely slow on a machine with
-# not enough entropy pool
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Windows_* )
-    FS="\\"
-    ;;
-  * )
-    FS="/"
-    ;;
-esac
-
-if [ "${TESTSRC}" = "" ] ; then
-  TESTSRC="."
-fi
-if [ "${TESTJAVA}" = "" ] ; then
-  JAVAC_CMD=`which javac`
-  TESTJAVA=`dirname $JAVAC_CMD`/..
-fi
-
-JAR="${TESTJAVA}${FS}bin${FS}jar"
-JAVA="${TESTJAVA}${FS}bin${FS}java"
-JAVAC="${TESTJAVA}${FS}bin${FS}javac"
-KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200"
-
-rm tsks
-echo Nothing > A
-rm old.jar
-$JAR cvf old.jar A
-
-# ca is CA
-# old is signer for code
-# ts is signer for timestamp
-# tsbad1 has no extendedKeyUsage
-# tsbad2's extendedKeyUsage is non-critical
-# tsbad3's extendedKeyUsage has no timestamping
-
-$KT -alias ca -genkeypair -ext bc -dname CN=CA
-$KT -alias old -genkeypair -dname CN=old
-$KT -alias ts -genkeypair -dname CN=ts
-$KT -alias tsbad1 -genkeypair -dname CN=tsbad1
-$KT -alias tsbad2 -genkeypair -dname CN=tsbad2
-$KT -alias tsbad3 -genkeypair -dname CN=tsbad3
-$KT -alias ts -certreq | \
-        $KT -alias ca -gencert -ext eku:critical=ts | \
-        $KT -alias ts -importcert
-$KT -alias tsbad1 -certreq | \
-        $KT -alias ca -gencert | \
-        $KT -alias tsbad1 -importcert
-$KT -alias tsbad2 -certreq | \
-        $KT -alias ca -gencert -ext eku=ts | \
-        $KT -alias tsbad2 -importcert
-$KT -alias tsbad3 -certreq | \
-        $KT -alias ca -gencert -ext eku:critical=cs | \
-        $KT -alias tsbad3 -importcert
-
-$JAVAC -XDignore.symbol.file -d . ${TESTSRC}/TimestampCheck.java
-$JAVA ${TESTVMOPTS} TimestampCheck
-
diff --git a/jdk/test/sun/security/tools/jarsigner/warnings/Test.java b/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
index 6018a6d..43ced17 100644
--- a/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
+++ b/jdk/test/sun/security/tools/jarsigner/warnings/Test.java
@@ -22,6 +22,11 @@
  */
 
 import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Base class.
@@ -175,4 +180,38 @@
         }
         analyzer.shouldContain(JAR_SIGNED);
     }
+
+    protected OutputAnalyzer keytool(String... cmd) throws Throwable {
+        return tool(KEYTOOL, cmd);
+    }
+
+    protected OutputAnalyzer jarsigner(String... cmd) throws Throwable {
+        return tool(JARSIGNER, cmd);
+    }
+
+    private OutputAnalyzer tool(String tool, String... args) throws Throwable {
+        List<String> cmd = new ArrayList<>();
+        cmd.add(tool);
+        cmd.add("-J-Duser.language=en");
+        cmd.add("-J-Duser.country=US");
+        cmd.addAll(Arrays.asList(args));
+        return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
+    }
+
+    protected OutputAnalyzer keytool(String... cmd) throws Throwable {
+        return tool(KEYTOOL, cmd);
+    }
+
+    protected OutputAnalyzer jarsigner(String... cmd) throws Throwable {
+        return tool(JARSIGNER, cmd);
+    }
+
+    private OutputAnalyzer tool(String tool, String... args) throws Throwable {
+        List<String> cmd = new ArrayList<>();
+        cmd.add(tool);
+        cmd.add("-J-Duser.language=en");
+        cmd.add("-J-Duser.country=US");
+        cmd.addAll(Arrays.asList(args));
+        return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
+    }
 }
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 74d02ac..1d02672 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -669,3 +669,18 @@
 ee37eafc48cb6fb20cb6c1e31cfecfe1ccc800da jdk8u112-b16
 de1c3df992adb0c704005583210d1ed6dac758cd jdk8u112-b31
 c94fd1b737d005962ba62fa03106de791692f39c jdk8u112-b32
+721ea56edf4196b37a081ac47206202d7560e16c jdk8u112-b33
+5710d574a99aeff3600c49a4aed34fa1b373f7b8 jdk8u121-b00
+ab5d32d8cf5f6d81482692f801385a869b2d83c1 jdk8u121-b01
+e260d46661d2da3ede78aae434d5420acce99950 jdk8u121-b02
+0acfd50d67d98259a25fbd51129b763bab56d068 jdk8u121-b03
+29a08aff06088cad98dafddef7628b51e324fcae jdk8u121-b04
+a933635275c33e37c9403767d600a12b9ee71df7 jdk8u121-b05
+dc1dd2e6cf8e094c4a8437d54ebc7bac1f7ab964 jdk8u121-b06
+6cd0cd4078e9ec8ad9fa167cabf9c671ed21fc66 jdk8u121-b07
+8efc10efbfe137ed5de6bf55875fdafd25bb6a1b jdk8u121-b08
+57a26fe61f2b435332c0697e92965a22246cd143 jdk8u121-b09
+53c94a674d6076ff390c62a7682ea0e87a893cdc jdk8u121-b10
+b634abfcd98fb8b201da9208e398ea17cabd2b32 jdk8u121-b11
+7fc347da372c8c4e5530a7fa32084b5dbc4ee8b6 jdk8u121-b12
+f634736433d9fc1cffbdc55611f97ecb2cd44059 jdk8u121-b13
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
index 10caa40..697ab82 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.StringUtils;
+import com.sun.tools.javadoc.JavaScriptScanner;
 import com.sun.tools.javadoc.RootDocImpl;
 
 /**
@@ -181,6 +182,11 @@
     public Set<String> doclintOpts = new LinkedHashSet<String>();
 
     /**
+     * Whether or not to check for JavaScript in doc comments.
+     */
+    private boolean allowScriptInComments;
+
+    /**
      * Unique Resource Handler for this package.
      */
     public final MessageRetriever standardmessage;
@@ -283,8 +289,11 @@
                 doclintOpts.add(null);
             } else if (opt.startsWith("-xdoclint:")) {
                 doclintOpts.add(opt.substring(opt.indexOf(":") + 1));
+            } else if (opt.equals("--allow-script-in-comments")) {
+                allowScriptInComments = true;
             }
         }
+
         if (root.specifiedClasses().length > 0) {
             Map<String,PackageDoc> map = new HashMap<String,PackageDoc>();
             PackageDoc pd;
@@ -301,9 +310,30 @@
 
         if (root instanceof RootDocImpl) {
             ((RootDocImpl) root).initDocLint(doclintOpts, tagletManager.getCustomTagNames());
+            JavaScriptScanner jss = ((RootDocImpl) root).initJavaScriptScanner(isAllowScriptInComments());
+            if (jss != null) {
+                // In a more object-oriented world, this would be done by methods on the Option objects.
+                // Note that -windowtitle silently removes any and all HTML elements, and so does not need
+                // to be handled here.
+                checkJavaScript(jss, "-header", header);
+                checkJavaScript(jss, "-footer", footer);
+                checkJavaScript(jss, "-top", top);
+                checkJavaScript(jss, "-bottom", bottom);
+                checkJavaScript(jss, "-doctitle", doctitle);
+                checkJavaScript(jss, "-packagesheader", packagesheader);
+            }
         }
     }
 
+    private void checkJavaScript(JavaScriptScanner jss, final String opt, String value) {
+        jss.parse(value, new JavaScriptScanner.Reporter() {
+            public void report() {
+                root.printError(getText("doclet.JavaScript_in_option", opt));
+                throw new FatalError();
+            }
+        });
+    }
+
     /**
      * Returns the "length" of a given option. If an option takes no
      * arguments, its length is one. If it takes one argument, it's
@@ -337,7 +367,8 @@
             option.equals("-nonavbar") ||
             option.equals("-nooverview") ||
             option.equals("-xdoclint") ||
-            option.startsWith("-xdoclint:")) {
+            option.startsWith("-xdoclint:") ||
+            option.equals("--allow-script-in-comments")) {
             return 1;
         } else if (option.equals("-help")) {
             // Uugh: first, this should not be hidden inside optionLength,
@@ -595,4 +626,13 @@
     public Content newContent() {
         return new ContentBuilder();
     }
+
+    /**
+     * Returns whether or not to allow JavaScript in comments.
+     * Default is off; can be set true from a command line option.
+     * @return the allowScriptInComments
+     */
+    public boolean isAllowScriptInComments() {
+        return allowScriptInComments;
+    }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
index 5cf8337..8377a14 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -190,6 +190,8 @@
                 }
             } catch (IOException e) {
                 throw new DocletAbortException(e);
+            } catch (FatalError fe) {
+                throw fe;
             } catch (DocletAbortException de) {
                 throw de;
             } catch (Exception e) {
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
index d15459e..84fec05 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -164,7 +164,9 @@
 
     public final Content descfrmInterfaceLabel;
 
-    private final Writer writer;
+    private final DocFile file;
+
+    private Writer writer;
 
     private Content script;
 
@@ -180,7 +182,7 @@
      */
     public HtmlWriter(Configuration configuration, DocPath path)
             throws IOException, UnsupportedEncodingException {
-        writer = DocFile.createFileForOutput(configuration, path).openWriter();
+        file = DocFile.createFileForOutput(configuration, path);
         this.configuration = configuration;
         this.memberDetailsListPrinted = false;
         profileTableHeader = new String[] {
@@ -239,6 +241,7 @@
     }
 
     public void write(Content c) throws IOException {
+        writer = file.openWriter();
         c.write(writer, true);
     }
 
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
index 39fde45..35f979d 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,8 @@
         } catch (Configuration.Fault f) {
             root.printError(f.getMessage());
             return false;
+        } catch (FatalError fe) {
+            return false;
         } catch (DocletAbortException e) {
             Throwable cause = e.getCause();
             if (cause != null) {
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
index 00f0b2b..b30e156 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,14 @@
             configuration.root.printError("Unknown element: " + component);
             throw new DocletAbortException(e);
         } catch (InvocationTargetException e) {
-            throw new DocletAbortException(e.getCause());
+            Throwable cause = e.getCause();
+            if (cause instanceof FatalError) {
+                throw (FatalError) cause;
+            } else if (cause instanceof DocletAbortException) {
+                throw (DocletAbortException) cause;
+            } else {
+                throw new DocletAbortException(cause);
+            }
         } catch (Exception e) {
             e.printStackTrace();
             configuration.root.printError("Exception " +
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
index 597dd35..dad5ab8 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties
@@ -29,6 +29,8 @@
 doclet.Building_Tree=Building tree for all the packages and classes...
 doclet.Building_Index=Building index for all the packages and classes...
 doclet.Building_Index_For_All_Classes=Building index for all classes...
+doclet.JavaScript_in_option=Argument for {0} contains JavaScript.\n\
+Use --allow-script-in-comments to allow use of JavaScript.
 doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
 doclet.Packages=Packages
 doclet.Profiles=Profiles
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
index 8051a49..3b6f660 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties
@@ -27,6 +27,7 @@
 doclet.Building_Tree=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u968E\u5C64\u30C4\u30EA\u30FC\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
 doclet.Building_Index=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
 doclet.Building_Index_For_All_Classes=\u5168\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059...
+doclet.JavaScript_in_option={0}\u306E\u5F15\u6570\u306BJavaScript\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
 doclet.sourcetab_warning=-sourcetab\u306E\u5F15\u6570\u306F0\u3088\u308A\u5927\u304D\u3044\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
 doclet.Packages=\u30D1\u30C3\u30B1\u30FC\u30B8
 doclet.Profiles=\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
index d67b248..3fff28a 100644
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties
@@ -27,6 +27,7 @@
 doclet.Building_Tree=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u6811...
 doclet.Building_Index=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u7D22\u5F15...
 doclet.Building_Index_For_All_Classes=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7C7B\u7684\u7D22\u5F15...
+doclet.JavaScript_in_option={0} \u7684\u53C2\u6570\u5305\u542B JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002
 doclet.sourcetab_warning=-sourcetab \u7684\u53C2\u6570\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002
 doclet.Packages=\u7A0B\u5E8F\u5305
 doclet.Profiles=\u914D\u7F6E\u6587\u4EF6
diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java
new file mode 100644
index 0000000..71248cb
--- /dev/null
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 com.sun.tools.doclets.internal.toolkit.util;
+
+/**
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+@Deprecated
+public class FatalError extends Error {
+    private static final long serialVersionUID = -9131058909576418984L;
+
+    public FatalError() { }
+}
diff --git a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
index e89a460..dd9f7f4 100644
--- a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
+++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,7 @@
         }
     }
 
-    private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
+    private final Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
     private HtmlTag currHeaderTag;
 
     private final int implicitHeaderLevel;
@@ -401,7 +401,16 @@
                 break;
 
             case OTHER:
-                env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
+                switch (t) {
+                    case SCRIPT:
+                        // <script> may or may not be allowed, depending on --allow-script-in-comments
+                        // but we allow it here, and rely on a separate scanner to detect all uses
+                        // of JavaScript, including <script> tags, and use in attributes, etc.
+                        break;
+
+                    default:
+                        env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
+                }
                 return;
         }
 
@@ -519,22 +528,27 @@
                 if (!first)
                     env.messages.error(HTML, tree, "dc.attr.repeated", name);
             }
-            AttrKind k = currTag.getAttrKind(name);
-            switch (k) {
-                case OK:
-                    break;
 
-                case INVALID:
-                    env.messages.error(HTML, tree, "dc.attr.unknown", name);
-                    break;
+            // for now, doclint allows all attribute names beginning with "on" as event handler names,
+            // without checking the validity or applicability of the name
+            if (!name.toString().startsWith("on")) {
+                AttrKind k = currTag.getAttrKind(name);
+                switch (k) {
+                    case OK:
+                        break;
 
-                case OBSOLETE:
-                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
-                    break;
+                    case INVALID:
+                        env.messages.error(HTML, tree, "dc.attr.unknown", name);
+                        break;
 
-                case USE_CSS:
-                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
-                    break;
+                    case OBSOLETE:
+                        env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
+                        break;
+
+                    case USE_CSS:
+                        env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
+                        break;
+                }
             }
 
             if (attr != null) {
@@ -643,6 +657,9 @@
     }
 
     private void checkURI(AttributeTree tree, String uri) {
+        // allow URIs beginning with javascript:, which would otherwise be rejected by the URI API.
+        if (uri.startsWith("javascript:"))
+            return;
         try {
             URI u = new URI(uri);
         } catch (URISyntaxException e) {
diff --git a/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java b/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
index 8de4327..99d384e 100644
--- a/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
+++ b/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -183,7 +183,8 @@
         }
     },
 
-    SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
+    SCRIPT(BlockType.OTHER, EndKind.REQUIRED,
+            attrs(AttrKind.OK, SRC)),
 
     SMALL(BlockType.INLINE, EndKind.REQUIRED,
             EnumSet.of(Flag.EXPECT_CONTENT)),
diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 9cdb462..e61ea49 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -585,7 +585,7 @@
     /**
      * Ident = IDENTIFIER
      */
-    Name ident() {
+    public Name ident() {
         if (token.kind == IDENTIFIER) {
             Name name = token.name();
             nextToken();
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
index 49933a8..3db4597 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -86,7 +86,7 @@
     JavadocEnter enter;
 
     /** The name table. */
-    Names names;
+    private final Names names;
 
     /** The encoding name. */
     private String encoding;
@@ -109,6 +109,7 @@
     JavaFileManager fileManager;
     Context context;
     DocLint doclint;
+    JavaScriptScanner javaScriptScanner;
 
     WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>();
 
@@ -834,6 +835,15 @@
         doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
     }
 
+    JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
+        if (allowScriptInComments) {
+            javaScriptScanner = null;
+        } else {
+            javaScriptScanner = new JavaScriptScanner();
+        }
+        return javaScriptScanner;
+    }
+
     boolean showTagMessages() {
         return (doclint == null);
     }
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
index e5b3f6c..83f5581 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 
 import com.sun.javadoc.*;
 import com.sun.source.util.TreePath;
+import com.sun.tools.doclets.internal.toolkit.util.FatalError;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.util.Position;
@@ -127,6 +128,15 @@
     Comment comment() {
         if (comment == null) {
             String d = documentation();
+            if (env.javaScriptScanner != null) {
+                env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() {
+                    @Override
+                    public void report() {
+                        env.error(DocImpl.this, "javadoc.JavaScript_in_comment");
+                        throw new FatalError();
+                    }
+                });
+            }
             if (env.doclint != null
                     && treePath != null
                     && d.equals(getCommentText(treePath))) {
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java
new file mode 100644
index 0000000..2ef0d7a
--- /dev/null
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 com.sun.tools.javadoc;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import com.sun.tools.javadoc.JavaScriptScanner.TagParser.Kind;
+
+import static com.sun.tools.javac.util.LayoutCharacters.EOI;
+
+/**
+ * Parser to detect use of JavaScript in documentation comments.
+ */
+@Deprecated
+public class JavaScriptScanner {
+    public static interface Reporter {
+        void report();
+    }
+
+    static class ParseException extends Exception {
+        private static final long serialVersionUID = 0;
+        ParseException(String key) {
+            super(key);
+        }
+    }
+
+    private Reporter reporter;
+
+    /** The input buffer, index of most recent character read,
+     *  index of one past last character in buffer.
+     */
+    protected char[] buf;
+    protected int bp;
+    protected int buflen;
+
+    /** The current character.
+     */
+    protected char ch;
+
+    private boolean newline = true;
+
+    Map<String, TagParser> tagParsers;
+    Set<String> eventAttrs;
+    Set<String> uriAttrs;
+
+    public JavaScriptScanner() {
+        initTagParsers();
+        initEventAttrs();
+        initURIAttrs();
+    }
+
+    public void parse(String comment, Reporter r) {
+        reporter = r;
+        String c = comment;
+        buf = new char[c.length() + 1];
+        c.getChars(0, c.length(), buf, 0);
+        buf[buf.length - 1] = EOI;
+        buflen = buf.length - 1;
+        bp = -1;
+        newline = true;
+        nextChar();
+
+        blockContent();
+        blockTags();
+    }
+
+    private void checkHtmlTag(String tag) {
+        if (tag.equalsIgnoreCase("script")) {
+            reporter.report();
+        }
+    }
+
+    private void checkHtmlAttr(String name, String value) {
+        String n = name.toLowerCase(Locale.ENGLISH);
+        if (eventAttrs.contains(n)
+                || uriAttrs.contains(n)
+                    && value != null && value.toLowerCase(Locale.ENGLISH).trim().startsWith("javascript:")) {
+            reporter.report();
+        }
+    }
+
+    void nextChar() {
+        ch = buf[bp < buflen ? ++bp : buflen];
+        switch (ch) {
+            case '\f': case '\n': case '\r':
+                newline = true;
+        }
+    }
+
+    /**
+     * Read block content, consisting of text, html and inline tags.
+     * Terminated by the end of input, or the beginning of the next block tag:
+     * i.e. @ as the first non-whitespace character on a line.
+     */
+    @SuppressWarnings("fallthrough")
+    protected void blockContent() {
+
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n': case '\r': case '\f':
+                    newline = true;
+                    // fallthrough
+
+                case ' ': case '\t':
+                    nextChar();
+                    break;
+
+                case '&':
+                    entity(null);
+                    break;
+
+                case '<':
+                    html();
+                    break;
+
+                case '>':
+                    newline = false;
+                    nextChar();
+                    break;
+
+                case '{':
+                    inlineTag(null);
+                    break;
+
+                case '@':
+                    if (newline) {
+                        break loop;
+                    }
+                    // fallthrough
+
+                default:
+                    newline = false;
+                    nextChar();
+            }
+        }
+    }
+
+    /**
+     * Read a series of block tags, including their content.
+     * Standard tags parse their content appropriately.
+     * Non-standard tags are represented by {@link UnknownBlockTag}.
+     */
+    protected void blockTags() {
+        while (ch == '@')
+            blockTag();
+    }
+
+    /**
+     * Read a single block tag, including its content.
+     * Standard tags parse their content appropriately.
+     * Non-standard tags are represented by {@link UnknownBlockTag}.
+     */
+    protected void blockTag() {
+        int p = bp;
+        try {
+            nextChar();
+            if (isIdentifierStart(ch)) {
+                String name = readTagName();
+                TagParser tp = tagParsers.get(name);
+                if (tp == null) {
+                    blockContent();
+                } else {
+                    switch (tp.getKind()) {
+                        case BLOCK:
+                            tp.parse(p);
+                            return;
+                        case INLINE:
+                            return;
+                    }
+                }
+            }
+            blockContent();
+        } catch (ParseException e) {
+            blockContent();
+        }
+    }
+
+    protected void inlineTag(Void list) {
+        newline = false;
+        nextChar();
+        if (ch == '@') {
+            inlineTag();
+        }
+    }
+
+    /**
+     * Read a single inline tag, including its content.
+     * Standard tags parse their content appropriately.
+     * Non-standard tags are represented by {@link UnknownBlockTag}.
+     * Malformed tags may be returned as {@link Erroneous}.
+     */
+    protected void inlineTag() {
+        int p = bp - 1;
+        try {
+            nextChar();
+            if (isIdentifierStart(ch)) {
+                String name = readTagName();
+                TagParser tp = tagParsers.get(name);
+
+                if (tp == null) {
+                    skipWhitespace();
+                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL);
+                    nextChar();
+                } else {
+                    skipWhitespace();
+                    if (tp.getKind() == TagParser.Kind.INLINE) {
+                        tp.parse(p);
+                    } else { // handle block tags (ex: @see) in inline content
+                        inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip content
+                        nextChar();
+                    }
+                }
+            }
+        } catch (ParseException e) {
+        }
+    }
+
+    private static enum WhitespaceRetentionPolicy {
+        RETAIN_ALL,
+        REMOVE_FIRST_SPACE,
+        REMOVE_ALL
+    }
+
+    /**
+     * Read plain text content of an inline tag.
+     * Matching pairs of { } are skipped; the text is terminated by the first
+     * unmatched }. It is an error if the beginning of the next tag is detected.
+     */
+    private void inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException {
+        switch (whitespacePolicy) {
+            case REMOVE_ALL:
+                skipWhitespace();
+                break;
+            case REMOVE_FIRST_SPACE:
+                if (ch == ' ')
+                    nextChar();
+                break;
+            case RETAIN_ALL:
+            default:
+                // do nothing
+                break;
+
+        }
+        int pos = bp;
+        int depth = 1;
+
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n': case '\r': case '\f':
+                    newline = true;
+                    break;
+
+                case ' ': case '\t':
+                    break;
+
+                case '{':
+                    newline = false;
+                    depth++;
+                    break;
+
+                case '}':
+                    if (--depth == 0) {
+                        return;
+                    }
+                    newline = false;
+                    break;
+
+                case '@':
+                    if (newline)
+                        break loop;
+                    newline = false;
+                    break;
+
+                default:
+                    newline = false;
+                    break;
+            }
+            nextChar();
+        }
+        throw new ParseException("dc.unterminated.inline.tag");
+    }
+
+    /**
+     * Read Java class name, possibly followed by member
+     * Matching pairs of {@literal < >} are skipped. The text is terminated by the first
+     * unmatched }. It is an error if the beginning of the next tag is detected.
+     */
+    // TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
+    // TODO: improve quality of parse to forbid bad constructions.
+    // TODO: update to use ReferenceParser
+    @SuppressWarnings("fallthrough")
+    protected void reference(boolean allowMember) throws ParseException {
+        int pos = bp;
+        int depth = 0;
+
+        // scan to find the end of the signature, by looking for the first
+        // whitespace not enclosed in () or <>, or the end of the tag
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n': case '\r': case '\f':
+                    newline = true;
+                    // fallthrough
+
+                case ' ': case '\t':
+                    if (depth == 0)
+                        break loop;
+                    break;
+
+                case '(':
+                case '<':
+                    newline = false;
+                    depth++;
+                    break;
+
+                case ')':
+                case '>':
+                    newline = false;
+                    --depth;
+                    break;
+
+                case '}':
+                    if (bp == pos)
+                        return;
+                    newline = false;
+                    break loop;
+
+                case '@':
+                    if (newline)
+                        break loop;
+                    // fallthrough
+
+                default:
+                    newline = false;
+
+            }
+            nextChar();
+        }
+
+        if (depth != 0)
+            throw new ParseException("dc.unterminated.signature");
+    }
+
+    /**
+     * Read Java identifier
+     * Matching pairs of { } are skipped; the text is terminated by the first
+     * unmatched }. It is an error if the beginning of the next tag is detected.
+     */
+    @SuppressWarnings("fallthrough")
+    protected void identifier() throws ParseException {
+        skipWhitespace();
+        int pos = bp;
+
+        if (isJavaIdentifierStart(ch)) {
+            readJavaIdentifier();
+            return;
+        }
+
+        throw new ParseException("dc.identifier.expected");
+    }
+
+    /**
+     * Read a quoted string.
+     * It is an error if the beginning of the next tag is detected.
+     */
+    @SuppressWarnings("fallthrough")
+    protected void quotedString() {
+        int pos = bp;
+        nextChar();
+
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n': case '\r': case '\f':
+                    newline = true;
+                    break;
+
+                case ' ': case '\t':
+                    break;
+
+                case '"':
+                    nextChar();
+                    // trim trailing white-space?
+                    return;
+
+                case '@':
+                    if (newline)
+                        break loop;
+
+            }
+            nextChar();
+        }
+    }
+
+    /**
+     * Read a term ie. one word.
+     * It is an error if the beginning of the next tag is detected.
+     */
+    @SuppressWarnings("fallthrough")
+    protected void inlineWord() {
+        int pos = bp;
+        int depth = 0;
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n':
+                    newline = true;
+                    // fallthrough
+
+                case '\r': case '\f': case ' ': case '\t':
+                    return;
+
+                case '@':
+                    if (newline)
+                        break loop;
+
+                case '{':
+                    depth++;
+                    break;
+
+                case '}':
+                    if (depth == 0 || --depth == 0)
+                        return;
+                    break;
+            }
+            newline = false;
+            nextChar();
+        }
+    }
+
+    /**
+     * Read general text content of an inline tag, including HTML entities and elements.
+     * Matching pairs of { } are skipped; the text is terminated by the first
+     * unmatched }. It is an error if the beginning of the next tag is detected.
+     */
+    @SuppressWarnings("fallthrough")
+    private void inlineContent() {
+
+        skipWhitespace();
+        int pos = bp;
+        int depth = 1;
+
+        loop:
+        while (bp < buflen) {
+
+            switch (ch) {
+                case '\n': case '\r': case '\f':
+                    newline = true;
+                    // fall through
+
+                case ' ': case '\t':
+                    nextChar();
+                    break;
+
+                case '&':
+                    entity(null);
+                    break;
+
+                case '<':
+                    newline = false;
+                    html();
+                    break;
+
+                case '{':
+                    newline = false;
+                    depth++;
+                    nextChar();
+                    break;
+
+                case '}':
+                    newline = false;
+                    if (--depth == 0) {
+                        nextChar();
+                        return;
+                    }
+                    nextChar();
+                    break;
+
+                case '@':
+                    if (newline)
+                        break loop;
+                    // fallthrough
+
+                default:
+                    nextChar();
+                    break;
+            }
+        }
+
+    }
+
+    protected void entity(Void list) {
+        newline = false;
+        entity();
+    }
+
+    /**
+     * Read an HTML entity.
+     * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; }
+     */
+    protected void entity() {
+        nextChar();
+        String name = null;
+        if (ch == '#') {
+            int namep = bp;
+            nextChar();
+            if (isDecimalDigit(ch)) {
+                nextChar();
+                while (isDecimalDigit(ch))
+                    nextChar();
+                name = new String(buf, namep, bp - namep);
+            } else if (ch == 'x' || ch == 'X') {
+                nextChar();
+                if (isHexDigit(ch)) {
+                    nextChar();
+                    while (isHexDigit(ch))
+                        nextChar();
+                    name = new String(buf, namep, bp - namep);
+                }
+            }
+        } else if (isIdentifierStart(ch)) {
+            name = readIdentifier();
+        }
+
+        if (name != null) {
+            if (ch != ';')
+                return;
+            nextChar();
+        }
+    }
+
+    /**
+     * Read the start or end of an HTML tag, or an HTML comment
+     * {@literal <identifier attrs> } or {@literal </identifier> }
+     */
+    protected void html() {
+        int p = bp;
+        nextChar();
+        if (isIdentifierStart(ch)) {
+            String name = readIdentifier();
+            checkHtmlTag(name);
+            htmlAttrs();
+            if (ch == '/') {
+                nextChar();
+            }
+            if (ch == '>') {
+                nextChar();
+                return;
+            }
+        } else if (ch == '/') {
+            nextChar();
+            if (isIdentifierStart(ch)) {
+                readIdentifier();
+                skipWhitespace();
+                if (ch == '>') {
+                    nextChar();
+                    return;
+                }
+            }
+        } else if (ch == '!') {
+            nextChar();
+            if (ch == '-') {
+                nextChar();
+                if (ch == '-') {
+                    nextChar();
+                    while (bp < buflen) {
+                        int dash = 0;
+                        while (ch == '-') {
+                            dash++;
+                            nextChar();
+                        }
+                        // Strictly speaking, a comment should not contain "--"
+                        // so dash > 2 is an error, dash == 2 implies ch == '>'
+                        // See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments
+                        // for more details.
+                        if (dash >= 2 && ch == '>') {
+                            nextChar();
+                            return;
+                        }
+
+                        nextChar();
+                    }
+                }
+            }
+        }
+
+        bp = p + 1;
+        ch = buf[bp];
+    }
+
+    /**
+     * Read a series of HTML attributes, terminated by {@literal > }.
+     * Each attribute is of the form {@literal identifier[=value] }.
+     * "value" may be unquoted, single-quoted, or double-quoted.
+     */
+    protected void htmlAttrs() {
+        skipWhitespace();
+
+        loop:
+        while (isIdentifierStart(ch)) {
+            int namePos = bp;
+            String name = readAttributeName();
+            skipWhitespace();
+            StringBuilder value = new StringBuilder();
+            if (ch == '=') {
+                nextChar();
+                skipWhitespace();
+                if (ch == '\'' || ch == '"') {
+                    char quote = ch;
+                    nextChar();
+                    while (bp < buflen && ch != quote) {
+                        if (newline && ch == '@') {
+                            // No point trying to read more.
+                            // In fact, all attrs get discarded by the caller
+                            // and superseded by a malformed.html node because
+                            // the html tag itself is not terminated correctly.
+                            break loop;
+                        }
+                        value.append(ch);
+                        nextChar();
+                    }
+                    nextChar();
+                } else {
+                    while (bp < buflen && !isUnquotedAttrValueTerminator(ch)) {
+                        value.append(ch);
+                        nextChar();
+                    }
+                }
+                skipWhitespace();
+            }
+            checkHtmlAttr(name, value.toString());
+        }
+    }
+
+    protected void attrValueChar(Void list) {
+        switch (ch) {
+            case '&':
+                entity(list);
+                break;
+
+            case '{':
+                inlineTag(list);
+                break;
+
+            default:
+                nextChar();
+        }
+    }
+
+    protected boolean isIdentifierStart(char ch) {
+        return Character.isUnicodeIdentifierStart(ch);
+    }
+
+    protected String readIdentifier() {
+        int start = bp;
+        nextChar();
+        while (bp < buflen && Character.isUnicodeIdentifierPart(ch))
+            nextChar();
+        return new String(buf, start, bp - start);
+    }
+
+    protected String readAttributeName() {
+        int start = bp;
+        nextChar();
+        while (bp < buflen && (Character.isUnicodeIdentifierPart(ch) || ch == '-'))
+            nextChar();
+        return new String(buf, start, bp - start);
+    }
+
+    protected String readTagName() {
+        int start = bp;
+        nextChar();
+        while (bp < buflen
+                && (Character.isUnicodeIdentifierPart(ch) || ch == '.'
+                || ch == '-' || ch == ':')) {
+            nextChar();
+        }
+        return new String(buf, start, bp - start);
+    }
+
+    protected boolean isJavaIdentifierStart(char ch) {
+        return Character.isJavaIdentifierStart(ch);
+    }
+
+    protected String readJavaIdentifier() {
+        int start = bp;
+        nextChar();
+        while (bp < buflen && Character.isJavaIdentifierPart(ch))
+            nextChar();
+        return new String(buf, start, bp - start);
+    }
+
+    protected boolean isDecimalDigit(char ch) {
+        return ('0' <= ch && ch <= '9');
+    }
+
+    protected boolean isHexDigit(char ch) {
+        return ('0' <= ch && ch <= '9')
+                || ('a' <= ch && ch <= 'f')
+                || ('A' <= ch && ch <= 'F');
+    }
+
+    protected boolean isUnquotedAttrValueTerminator(char ch) {
+        switch (ch) {
+            case '\f': case '\n': case '\r': case '\t':
+            case ' ':
+            case '"': case '\'': case '`':
+            case '=': case '<': case '>':
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    protected boolean isWhitespace(char ch) {
+        return Character.isWhitespace(ch);
+    }
+
+    protected void skipWhitespace() {
+        while (isWhitespace(ch)) {
+            nextChar();
+        }
+    }
+
+    /**
+     * @param start position of first character of string
+     * @param end position of character beyond last character to be included
+     */
+    String newString(int start, int end) {
+        return new String(buf, start, end - start);
+    }
+
+    static abstract class TagParser {
+        enum Kind { INLINE, BLOCK }
+
+        final Kind kind;
+        final String name;
+
+
+        TagParser(Kind k, String tk) {
+            kind = k;
+            name = tk;
+        }
+
+        TagParser(Kind k, String tk, boolean retainWhiteSpace) {
+            this(k, tk);
+        }
+
+        Kind getKind() {
+            return kind;
+        }
+
+        String getName() {
+            return name;
+        }
+
+        abstract void parse(int pos) throws ParseException;
+    }
+
+    /**
+     * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a>
+     */
+    @SuppressWarnings("deprecation")
+    private void initTagParsers() {
+        TagParser[] parsers = {
+            // @author name-text
+            new TagParser(Kind.BLOCK, "author") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // {@code text}
+            new TagParser(Kind.INLINE, "code", true) {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
+                    nextChar();
+                }
+            },
+
+            // @deprecated deprecated-text
+            new TagParser(Kind.BLOCK, "deprecated") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // {@docRoot}
+            new TagParser(Kind.INLINE, "docRoot") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    if (ch == '}') {
+                        nextChar();
+                        return;
+                    }
+                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
+                    nextChar();
+                    throw new ParseException("dc.unexpected.content");
+                }
+            },
+
+            // @exception class-name description
+            new TagParser(Kind.BLOCK, "exception") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    reference(false);
+                    blockContent();
+                }
+            },
+
+            // @hidden hidden-text
+            new TagParser(Kind.BLOCK, "hidden") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // @index search-term options-description
+            new TagParser(Kind.INLINE, "index") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    if (ch == '}') {
+                        throw new ParseException("dc.no.content");
+                    }
+                    if (ch == '"') quotedString(); else inlineWord();
+                    skipWhitespace();
+                    if (ch != '}') {
+                        inlineContent();
+                    } else {
+                        nextChar();
+                    }
+                }
+            },
+
+            // {@inheritDoc}
+            new TagParser(Kind.INLINE, "inheritDoc") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    if (ch == '}') {
+                        nextChar();
+                        return;
+                    }
+                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
+                    nextChar();
+                    throw new ParseException("dc.unexpected.content");
+                }
+            },
+
+            // {@link package.class#member label}
+            new TagParser(Kind.INLINE, "link") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    reference(true);
+                    inlineContent();
+                }
+            },
+
+            // {@linkplain package.class#member label}
+            new TagParser(Kind.INLINE, "linkplain") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    reference(true);
+                    inlineContent();
+                }
+            },
+
+            // {@literal text}
+            new TagParser(Kind.INLINE, "literal", true) {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
+                    nextChar();
+                }
+            },
+
+            // @param parameter-name description
+            new TagParser(Kind.BLOCK, "param") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+
+                    boolean typaram = false;
+                    if (ch == '<') {
+                        typaram = true;
+                        nextChar();
+                    }
+
+                    identifier();
+
+                    if (typaram) {
+                        if (ch != '>')
+                            throw new ParseException("dc.gt.expected");
+                        nextChar();
+                    }
+
+                    skipWhitespace();
+                    blockContent();
+                }
+            },
+
+            // @return description
+            new TagParser(Kind.BLOCK, "return") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // @see reference | quoted-string | HTML
+            new TagParser(Kind.BLOCK, "see") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    switch (ch) {
+                        case '"':
+                            quotedString();
+                            skipWhitespace();
+                            if (ch == '@'
+                                    || ch == EOI && bp == buf.length - 1) {
+                                return;
+                            }
+                            break;
+
+                        case '<':
+                            blockContent();
+                            return;
+
+                        case '@':
+                            if (newline)
+                                throw new ParseException("dc.no.content");
+                            break;
+
+                        case EOI:
+                            if (bp == buf.length - 1)
+                                throw new ParseException("dc.no.content");
+                            break;
+
+                        default:
+                            if (isJavaIdentifierStart(ch) || ch == '#') {
+                                reference(true);
+                                blockContent();
+                            }
+                    }
+                    throw new ParseException("dc.unexpected.content");
+                }
+            },
+
+            // @serialData data-description
+            new TagParser(Kind.BLOCK, "@serialData") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // @serialField field-name field-type description
+            new TagParser(Kind.BLOCK, "serialField") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    identifier();
+                    skipWhitespace();
+                    reference(false);
+                    if (isWhitespace(ch)) {
+                        skipWhitespace();
+                        blockContent();
+                    }
+                }
+            },
+
+            // @serial field-description | include | exclude
+            new TagParser(Kind.BLOCK, "serial") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // @since since-text
+            new TagParser(Kind.BLOCK, "since") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+
+            // @throws class-name description
+            new TagParser(Kind.BLOCK, "throws") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    reference(false);
+                    blockContent();
+                }
+            },
+
+            // {@value package.class#field}
+            new TagParser(Kind.INLINE, "value") {
+                @Override
+                public void parse(int pos) throws ParseException {
+                    reference(true);
+                    skipWhitespace();
+                    if (ch == '}') {
+                        nextChar();
+                        return;
+                    }
+                    nextChar();
+                    throw new ParseException("dc.unexpected.content");
+                }
+            },
+
+            // @version version-text
+            new TagParser(Kind.BLOCK, "version") {
+                @Override
+                public void parse(int pos) {
+                    blockContent();
+                }
+            },
+        };
+
+        tagParsers = new HashMap<>();
+        for (TagParser p: parsers)
+            tagParsers.put(p.getName(), p);
+
+    }
+
+    private void initEventAttrs() {
+        eventAttrs = new HashSet<>(Arrays.asList(
+            // See https://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.event-handler
+            "onabort",  "onblur",  "oncanplay",  "oncanplaythrough",
+            "onchange",  "onclick",  "oncontextmenu",  "ondblclick",
+            "ondrag",  "ondragend",  "ondragenter",  "ondragleave",
+            "ondragover",  "ondragstart",  "ondrop",  "ondurationchange",
+            "onemptied",  "onended",  "onerror",  "onfocus",  "oninput",
+            "oninvalid",  "onkeydown",  "onkeypress",  "onkeyup",
+            "onload",  "onloadeddata",  "onloadedmetadata",  "onloadstart",
+            "onmousedown",  "onmousemove",  "onmouseout",  "onmouseover",
+            "onmouseup",  "onmousewheel",  "onpause",  "onplay",
+            "onplaying",  "onprogress",  "onratechange",  "onreadystatechange",
+            "onreset",  "onscroll",  "onseeked",  "onseeking",
+            "onselect",  "onshow",  "onstalled",  "onsubmit",  "onsuspend",
+            "ontimeupdate",  "onvolumechange",  "onwaiting",
+
+            // See https://www.w3.org/TR/html4/sgml/dtd.html
+            // Most of the attributes that take a %Script are also defined as event handlers
+            // in HTML 5. The one exception is onunload.
+            // "onchange",  "onclick",   "ondblclick",  "onfocus",
+            // "onkeydown",  "onkeypress",  "onkeyup",  "onload",
+            // "onmousedown",  "onmousemove",  "onmouseout",  "onmouseover",
+            // "onmouseup",  "onreset",  "onselect",  "onsubmit",
+            "onunload"
+        ));
+    }
+
+    private void initURIAttrs() {
+        uriAttrs = new HashSet<>(Arrays.asList(
+            // See https://www.w3.org/TR/html4/sgml/dtd.html
+            //     https://www.w3.org/TR/html5/
+            // These are all the attributes that take a %URI or a valid URL potentially surrounded
+            // by spaces
+            "action",  "cite",  "classid",  "codebase",  "data",
+            "datasrc",  "for",  "href",  "longdesc",  "profile",
+            "src",  "usemap"
+        ));
+    }
+
+}
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
index 678557b..ab7c272 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -381,6 +381,10 @@
         env.initDoclint(opts, customTagNames);
     }
 
+    public JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
+        return env.initJavaScriptScanner(allowScriptInComments);
+    }
+
     public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
         return annotationDesc.annotationType().qualifiedName().equals(
                 env.syms.functionalInterfaceType.toString()) && env.source.allowLambda();
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
index 8ac2c34..adf73c6 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -110,6 +110,8 @@
 javadoc.Body_missing_from_html_file=Body tag missing from HTML file
 javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file
 javadoc.Multiple_package_comments=Multiple sources of package comments found for package "{0}"
+javadoc.JavaScript_in_comment=JavaScript found in documentation comment.\n\
+    Use --allow-script-in-comments to allow use of JavaScript.
 javadoc.class_not_found=Class {0} not found.
 javadoc.error=error
 javadoc.warning=warning
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
index 1c5f3f7..b71ca8d 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@
 javadoc.Body_missing_from_html_file=HTML\u306Bbody\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
 javadoc.End_body_missing_from_html_file=HTML\u30D5\u30A1\u30A4\u30EB\u306Bbody\u306E\u9589\u3058\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
 javadoc.Multiple_package_comments=\u30D1\u30C3\u30B1\u30FC\u30B8"{0}"\u306B\u8907\u6570\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B3\u30E1\u30F3\u30C8\u306E\u30BD\u30FC\u30B9\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F
+javadoc.JavaScript_in_comment=\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u306BJavaScript\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
 javadoc.class_not_found=\u30AF\u30E9\u30B9{0}\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
 javadoc.error=\u30A8\u30E9\u30FC
 javadoc.warning=\u8B66\u544A
diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
index 591f577..2f6d5ce 100644
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,7 @@
 javadoc.Body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u6807\u8BB0
 javadoc.End_body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u7ED3\u675F\u6807\u8BB0
 javadoc.Multiple_package_comments=\u627E\u5230\u7A0B\u5E8F\u5305 "{0}" \u7684\u591A\u4E2A\u7A0B\u5E8F\u5305\u6CE8\u91CA\u6E90
+javadoc.JavaScript_in_comment=\u6587\u6863\u6CE8\u91CA\u4E2D\u53D1\u73B0 JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002
 javadoc.class_not_found=\u627E\u4E0D\u5230\u7C7B{0}\u3002
 javadoc.error=\u9519\u8BEF
 javadoc.warning=\u8B66\u544A
diff --git a/langtools/test/tools/doclint/html/OtherTagsTest.out b/langtools/test/tools/doclint/html/OtherTagsTest.out
index 3fbcb15..5cd00fc 100644
--- a/langtools/test/tools/doclint/html/OtherTagsTest.out
+++ b/langtools/test/tools/doclint/html/OtherTagsTest.out
@@ -19,10 +19,7 @@
 OtherTagsTest.java:20: error: element not allowed in documentation comments: <noframes>
      *  <noframes> </noframes>
         ^
-OtherTagsTest.java:21: error: element not allowed in documentation comments: <script>
-     *  <script> </script>
-        ^
 OtherTagsTest.java:22: error: element not allowed in documentation comments: <title>
      *  <title> </title>
         ^
-9 errors
+8 errors
diff --git a/langtools/test/tools/javadoc/TestScriptInComment.java b/langtools/test/tools/javadoc/TestScriptInComment.java
new file mode 100644
index 0000000..bda3aca
--- /dev/null
+++ b/langtools/test/tools/javadoc/TestScriptInComment.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 8138725
+ * @summary test --allow-script-in-comments
+ * @run main TestScriptInComment
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Combo-style test, exercising combinations of different HTML fragments that may contain
+ * JavaScript, different places to place those fragments, and whether or not to allow the use
+ * of JavaScript.
+ */
+public class TestScriptInComment {
+    public static void main(String... args) throws Exception {
+        new TestScriptInComment().run();
+    }
+
+    /**
+     * Representative samples of different fragments of HTML that may contain JavaScript.
+     * To facilitate checking the output manually in a browser, the text "#ALERT" will be
+     * replaced by a JavaScript call of "alert(msg)", using a message string that is specific
+     * to the test case.
+     */
+    enum Comment {
+        LC("<script>#ALERT</script>", true), // script tag in Lower Case
+        UC("<SCRIPT>#ALERT</script>", true), // script tag in Upper Case
+        WS("< script >#ALERT</script>", false, "-Xdoclint:none"), // script tag with invalid white space
+        SA("<script src=\"file\"> #ALERT </script>", true), // script tag with an attribute
+        ON("<a onclick='#ALERT'>x</a>", true), // event handler attribute
+        URI("<a href='javascript:#ALERT'>x</a>", true); // javadcript URI
+
+        /**
+         * Creates an HTML fragment to be injected into a template.
+         * @param text the HTML fragment to put into a doc comment or option.
+         * @param hasScript whether or not this fragment does contain legal JavaScript
+         * @param opts any additional options to be specified when javadoc is run
+         */
+        Comment(String text, boolean hasScript, String... opts) {
+            this.text = text;
+            this.hasScript = hasScript;
+            this.opts = Arrays.asList(opts);
+        }
+
+        final String text;
+        final boolean hasScript;
+        final List<String> opts;
+    };
+
+    /**
+     * Representative samples of positions in which javadoc may find JavaScript.
+     * Each template contains a series of strings, which are written to files or inferred as options.
+     * The first source file implies a corresponding output file which should not be written
+     * if the comment contains JavaScript and JavaScript is not allowed.
+     */
+    enum Template {
+        OVR("<html><body> overview #COMMENT </body></html>", "package p; public class C { }"),
+        PKGINFO("#COMMENT package p;", "package p; public class C { }"),
+        PKGHTML("<html><body>#COMMENT package p;</body></html>", "package p; public class C { }"),
+        CLS("package p; #COMMENT public class C { }"),
+        CON("package p; public class C { #COMMENT public C() { } }"),
+        FLD("package p; public class C { #COMMENT public int f; }"),
+        MTH("package p; public class C { #COMMENT public void m() { } }"),
+        TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"),
+        HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"),
+        FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"),
+        BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"),
+        DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"),
+        PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }");
+
+        Template(String... args) {
+            opts = new ArrayList<String>();
+            sources = new ArrayList<String>();
+            int i = 0;
+            while (args[i].startsWith("-")) {
+                // all options being tested have a single argument that follow the option
+                opts.add(args[i++]);
+                opts.add(args[i++]);
+            }
+            while(i < args.length) {
+                sources.add(args[i++]);
+            }
+        }
+
+        // groups: 1 <html> or not;  2: package name;  3: class name
+        private final Pattern pat =
+                Pattern.compile("(?i)(<html>)?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?");
+
+        /**
+         * Infer the file in which to write the given source.
+         * @param dir the base source directory
+         * @param src the source text
+         * @return the file in which the source should be written
+         */
+        File getSrcFile(File srcDir, String src) {
+            String f;
+            Matcher m = pat.matcher(src);
+            if (!m.matches())
+                throw new Error("match failed");
+            if (m.group(3) != null) {
+                f = m.group(2) + "/" + m.group(3) + ".java";
+            } else if (m.group(2) != null) {
+                f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html");
+            } else {
+                f = "overview.html";
+            }
+            return new File(srcDir, f);
+        }
+
+        /**
+         * Get the options to give to javadoc.
+         * @param srcDir the srcDir to use -overview is needed
+         * @return
+         */
+        List<String> getOpts(File srcDir) {
+            if (!opts.isEmpty()) {
+                return opts;
+            } else if (sources.get(0).contains("overview")) {
+                return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath());
+            } else {
+                return Collections.emptyList();
+            }
+        }
+
+        /**
+         * Gets the output file corresponding to the first source file.
+         * This file should not be written if the comment contains JavaScript and JavaScripot is
+         * not allowed.
+         * @param dir the base output directory
+         * @return the output file
+         */
+        File getOutFile(File outDir) {
+            String f;
+            Matcher m = pat.matcher(sources.get(0));
+            if (!m.matches())
+                throw new Error("match failed");
+            if (m.group(3) != null) {
+                f = m.group(2) + "/" + m.group(3) + ".html";
+            } else if (m.group(2) != null) {
+                f = m.group(2) + "/package-summary.html";
+            } else {
+                f = "overview-summary.html";
+            }
+            return new File(outDir, f);
+        }
+
+        final List<String> opts;
+        final List<String> sources;
+    };
+
+    enum Option {
+        OFF(null),
+        ON("--allow-script-in-comments");
+
+        Option(String text) {
+            this.text = text;
+        }
+
+        final String text;
+    };
+
+    private PrintStream out = System.err;
+
+    public void run() throws Exception {
+        int count = 0;
+        for (Template template: Template.values()) {
+            for (Comment comment: Comment.values()) {
+                for (Option option: Option.values()) {
+                    if (test(template, comment, option)) {
+                        count++;
+                    }
+                }
+            }
+        }
+
+        out.println(count + " test cases run");
+        if (errors > 0) {
+            throw new Exception(errors + " errors occurred");
+        }
+    }
+
+    boolean test(Template template, Comment comment, Option option) throws IOException {
+        if (option == Option.ON && !comment.hasScript) {
+            // skip --allowScriptInComments if comment does not contain JavaScript
+            return false;
+        }
+
+        String test = template + "-" + comment + "-" + option;
+        out.println("Test: " + test);
+
+        File dir = new File(test);
+        dir.mkdirs();
+        File srcDir = new File(dir, "src");
+        File outDir = new File(dir, "out");
+
+        String alert = "alert(\"" + test + "\");";
+        for (String src: template.sources) {
+            writeFile(template.getSrcFile(srcDir, src),
+                src.replace("#COMMENT",
+                        "/** " + comment.text.replace("#ALERT", alert) + " **/"));
+        }
+
+        List<String> opts = new ArrayList<String>();
+        opts.add("-sourcepath");
+        opts.add(srcDir.getPath());
+        opts.add("-d");
+        opts.add(outDir.getPath());
+        if (option.text != null)
+            opts.add(option.text);
+        for (String opt: template.getOpts(srcDir)) {
+            opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert)));
+        }
+        opts.addAll(comment.opts);
+        opts.add("-noindex");   // index not required; save time/space writing files
+        opts.add("p");
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        int rc = javadoc(opts, pw);
+        pw.close();
+        String log = sw.toString();
+        writeFile(new File(dir, "log.txt"), log);
+
+        out.println("opts: " + opts);
+        out.println("  rc: " + rc);
+        out.println(" log:");
+        out.println(log);
+
+        String ERROR = "Use --allow-script-in-comment";
+        File outFile = template.getOutFile(outDir);
+
+        boolean expectErrors = comment.hasScript && (option == Option.OFF);
+
+        if (expectErrors) {
+            check(rc != 0, "unexpected exit code: " + rc);
+            check(log.contains(ERROR), "expected error message not found");
+            check(!outFile.exists(), "output file found unexpectedly");
+        } else {
+            check(rc == 0, "unexpected exit code: " + rc);
+            check(!log.contains(ERROR), "error message found");
+            check(outFile.exists(), "output file not found");
+        }
+
+        out.println();
+        return true;
+    }
+
+    int javadoc(List<String> opts, PrintWriter pw) {
+        return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw,
+                "com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()]));
+    }
+
+    File writeFile(File f, String text) throws IOException {
+        f.getParentFile().mkdirs();
+        FileWriter fw = new FileWriter(f);
+        try {
+            fw.write(text);
+        } finally {
+            fw.close();
+        }
+        return f;
+    }
+
+    void check(boolean cond, String errMessage) {
+        if (!cond) {
+            error(errMessage);
+        }
+    }
+
+    void error(String message) {
+        out.println("Error: " + message);
+        errors++;
+    }
+
+    int errors = 0;
+}
+
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 3a16af7..6b08447 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -648,3 +648,18 @@
 d1f2cab06d35f6b7ac29f5c3eebd74a74a01b8fb jdk8u112-b16
 d4beac03b1230ff8c96af79dcd10c56bdc475ebb jdk8u112-b31
 5cd9541c75fd68f8b575cb8499d9d375bee1033c jdk8u112-b32
+ad155bea4b3c781cb7d421ac1164f68f3e6693d2 jdk8u112-b33
+1a484cc1d2ed0540543b0af4ebb8ad83bcb1c667 jdk8u121-b00
+8f5fafa7e43b0b2472b077ea8f9b241976e1ea82 jdk8u121-b01
+33bf988e6f1a2a2fa1dcec66da79a5411df6dcd5 jdk8u121-b02
+112c17eb13c7c1952b9ccb377185268f77edc97e jdk8u121-b03
+31dad6c4e1be1b0ec7e4365932bb783c643b7c53 jdk8u121-b04
+465b06ac76296f329049a34d33d1ec00c800511b jdk8u121-b05
+c8fe62b47c8f065029c710e35aa61562b6550da1 jdk8u121-b06
+a32b4f984a18a7f9f6b412bf91c1a382df40d5ab jdk8u121-b07
+937cd79f7cfb27134f4ae24ad9f57bd1d9ed0f83 jdk8u121-b08
+3b222c098080d9fba2ad028b64e0edfef4d9dfcd jdk8u121-b09
+23970322bf063b36c0aefe103540618bb64a82af jdk8u121-b10
+fe53d09bdd8f4309ce3f79e9dc4c512639de2610 jdk8u121-b11
+89c0a71eeb4ae2011e7ed10f36e79b5184c7827b jdk8u121-b12
+fd548ea7e156aba26836084b838df5e90b90b6ba jdk8u121-b13