8081800: AbstractMethodError when evaluating a private method in an interface via debugger
authordholmes
Mon, 03 Oct 2016 21:48:21 -0400
changeset 41669 2091069b6851
parent 41668 e9c6bbf513e5
child 41670 ee918e29fc47
8081800: AbstractMethodError when evaluating a private method in an interface via debugger Reviewed-by: acorn, dcubed, coleenp
hotspot/make/test/JtregNative.gmk
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/ci/ciInstanceKlass.cpp
hotspot/src/share/vm/ci/ciInstanceKlass.hpp
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/classfile/classFileParser.hpp
hotspot/src/share/vm/classfile/defaultMethods.cpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/klassVtable.cpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/prims/jni.cpp
hotspot/test/runtime/RedefineTests/RedefineInterfaceMethods.java
hotspot/test/runtime/jni/PrivateInterfaceMethods/PrivateInterfaceMethods.java
hotspot/test/runtime/jni/PrivateInterfaceMethods/libPrivateInterfaceMethods.c
hotspot/test/runtime/logging/ItablesTest.java
--- a/hotspot/make/test/JtregNative.gmk	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/make/test/JtregNative.gmk	Mon Oct 03 21:48:21 2016 -0400
@@ -45,6 +45,7 @@
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/checked \
+    $(HOTSPOT_TOPDIR)/test/runtime/jni/PrivateInterfaceMethods \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
     $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
     $(HOTSPOT_TOPDIR)/test/runtime/SameObject \
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -1929,7 +1929,7 @@
         // number of implementors for decl_interface is 0 or 1. If
         // it's 0 then no class implements decl_interface and there's
         // no point in inlining.
-        if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_default_methods()) {
+        if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_nonstatic_concrete_methods()) {
           singleton = NULL;
         }
       }
@@ -4308,7 +4308,7 @@
 void GraphBuilder::profile_call(ciMethod* callee, Value recv, ciKlass* known_holder, Values* obj_args, bool inlined) {
   assert(known_holder == NULL || (known_holder->is_instance_klass() &&
                                   (!known_holder->is_interface() ||
-                                   ((ciInstanceKlass*)known_holder)->has_default_methods())), "should be default method");
+                                   ((ciInstanceKlass*)known_holder)->has_nonstatic_concrete_methods())), "should be non-static concrete method");
   if (known_holder != NULL) {
     if (known_holder->exact_klass() == NULL) {
       known_holder = compilation()->cha_exact_type(known_holder);
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -58,7 +58,7 @@
   _init_state = ik->init_state();
   _nonstatic_field_size = ik->nonstatic_field_size();
   _has_nonstatic_fields = ik->has_nonstatic_fields();
-  _has_default_methods = ik->has_default_methods();
+  _has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods();
   _is_anonymous = ik->is_anonymous();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
   _has_injected_fields = -1;
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Mon Oct 03 21:48:21 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, 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
@@ -52,7 +52,7 @@
   bool                   _has_finalizer;
   bool                   _has_subklass;
   bool                   _has_nonstatic_fields;
-  bool                   _has_default_methods;
+  bool                   _has_nonstatic_concrete_methods;
   bool                   _is_anonymous;
 
   ciFlags                _flags;
@@ -174,9 +174,9 @@
       return 2;
     }
   }
-  bool has_default_methods()  {
+  bool has_nonstatic_concrete_methods()  {
     assert(is_loaded(), "must be loaded");
-    return _has_default_methods;
+    return _has_nonstatic_concrete_methods;
   }
 
   bool is_anonymous() {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -798,11 +798,11 @@
 void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
                                        const int itfs_len,
                                        ConstantPool* const cp,
-                                       bool* const has_default_methods,
+                                       bool* const has_nonstatic_concrete_methods,
                                        TRAPS) {
   assert(stream != NULL, "invariant");
   assert(cp != NULL, "invariant");
-  assert(has_default_methods != NULL, "invariant");
+  assert(has_nonstatic_concrete_methods != NULL, "invariant");
 
   if (itfs_len == 0) {
     _local_interfaces = Universe::the_empty_klass_array();
@@ -844,8 +844,8 @@
                    "Implementing class");
       }
 
-      if (InstanceKlass::cast(interf())->has_default_methods()) {
-        *has_default_methods = true;
+      if (InstanceKlass::cast(interf())->has_nonstatic_concrete_methods()) {
+        *has_nonstatic_concrete_methods = true;
       }
       _local_interfaces->at_put(index, interf());
     }
@@ -2830,12 +2830,12 @@
                                     bool is_interface,
                                     AccessFlags* promoted_flags,
                                     bool* has_final_method,
-                                    bool* declares_default_methods,
+                                    bool* declares_nonstatic_concrete_methods,
                                     TRAPS) {
   assert(cfs != NULL, "invariant");
   assert(promoted_flags != NULL, "invariant");
   assert(has_final_method != NULL, "invariant");
-  assert(declares_default_methods != NULL, "invariant");
+  assert(declares_nonstatic_concrete_methods != NULL, "invariant");
 
   assert(NULL == _methods, "invariant");
 
@@ -2860,11 +2860,11 @@
       if (method->is_final()) {
         *has_final_method = true;
       }
-      // declares_default_methods: declares concrete instance methods, any access flags
+      // declares_nonstatic_concrete_methods: declares concrete instance methods, any access flags
       // used for interface initialization, and default method inheritance analysis
-      if (is_interface && !(*declares_default_methods)
+      if (is_interface && !(*declares_nonstatic_concrete_methods)
         && !method->is_abstract() && !method->is_static()) {
-        *declares_default_methods = true;
+        *declares_nonstatic_concrete_methods = true;
       }
       _methods->at_put(index, method);
     }
@@ -5250,8 +5250,8 @@
 
   ik->set_minor_version(_minor_version);
   ik->set_major_version(_major_version);
-  ik->set_has_default_methods(_has_default_methods);
-  ik->set_declares_default_methods(_declares_default_methods);
+  ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);
+  ik->set_declares_nonstatic_concrete_methods(_declares_nonstatic_concrete_methods);
 
   if (_host_klass != NULL) {
     assert (ik->is_anonymous(), "should be the same");
@@ -5311,12 +5311,9 @@
   // check if this class overrides any final method
   check_final_method_override(ik, CHECK);
 
-  // check that if this class is an interface then it doesn't have static methods
-  if (ik->is_interface()) {
-    /* An interface in a JAVA 8 classfile can be static */
-    if (_major_version < JAVA_8_VERSION) {
-      check_illegal_static_method(ik, CHECK);
-    }
+  // reject static interface methods prior to Java 8
+  if (ik->is_interface() && _major_version < JAVA_8_VERSION) {
+    check_illegal_static_method(ik, CHECK);
   }
 
   // Obtain this_klass' module entry
@@ -5336,9 +5333,9 @@
 
   assert(_all_mirandas != NULL, "invariant");
 
-  // Generate any default methods - default methods are interface methods
-  // that have a default implementation.  This is new with Lambda project.
-  if (_has_default_methods ) {
+  // Generate any default methods - default methods are public interface methods
+  // that have a default implementation.  This is new with Java 8.
+  if (_has_nonstatic_concrete_methods) {
     DefaultMethods::generate_default_methods(ik,
                                              _all_mirandas,
                                              CHECK);
@@ -5523,8 +5520,8 @@
   _java_fields_count(0),
   _need_verify(false),
   _relax_verify(false),
-  _has_default_methods(false),
-  _declares_default_methods(false),
+  _has_nonstatic_concrete_methods(false),
+  _declares_nonstatic_concrete_methods(false),
   _has_final_method(false),
   _has_finalizer(false),
   _has_empty_finalizer(false),
@@ -5798,7 +5795,7 @@
   parse_interfaces(stream,
                    _itfs_len,
                    cp,
-                   &_has_default_methods,
+                   &_has_nonstatic_concrete_methods,
                    CHECK);
 
   assert(_local_interfaces != NULL, "invariant");
@@ -5821,7 +5818,7 @@
                 _access_flags.is_interface(),
                 &promoted_flags,
                 &_has_final_method,
-                &_declares_default_methods,
+                &_declares_nonstatic_concrete_methods,
                 CHECK);
 
   assert(_methods != NULL, "invariant");
@@ -5829,8 +5826,8 @@
   // promote flags from parse_methods() to the klass' flags
   _access_flags.add_promoted_flags(promoted_flags.as_int());
 
-  if (_declares_default_methods) {
-    _has_default_methods = true;
+  if (_declares_nonstatic_concrete_methods) {
+    _has_nonstatic_concrete_methods = true;
   }
 
   // Additional attributes/annotations
@@ -5879,8 +5876,8 @@
   }
 
   if (_super_klass != NULL) {
-    if (_super_klass->has_default_methods()) {
-      _has_default_methods = true;
+    if (_super_klass->has_nonstatic_concrete_methods()) {
+      _has_nonstatic_concrete_methods = true;
     }
 
     if (_super_klass->is_interface()) {
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Mon Oct 03 21:48:21 2016 -0400
@@ -139,8 +139,8 @@
   bool _need_verify;
   bool _relax_verify;
 
-  bool _has_default_methods;
-  bool _declares_default_methods;
+  bool _has_nonstatic_concrete_methods;
+  bool _declares_nonstatic_concrete_methods;
   bool _has_final_method;
 
   // precomputed flags
@@ -186,7 +186,7 @@
   void parse_interfaces(const ClassFileStream* const stream,
                         const int itfs_len,
                         ConstantPool* const cp,
-                        bool* has_default_methods,
+                        bool* has_nonstatic_concrete_methods,
                         TRAPS);
 
   const InstanceKlass* parse_super_class(ConstantPool* const cp,
@@ -224,7 +224,7 @@
                      bool is_interface,
                      AccessFlags* const promoted_flags,
                      bool* const has_final_method,
-                     bool* const declares_default_methods,
+                     bool* const declares_nonstatic_concrete_methods,
                      TRAPS);
 
   const u2* parse_exception_table(const ClassFileStream* const stream,
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -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
@@ -914,7 +914,7 @@
       BytecodeBuffer buffer;
 
       if (log_is_enabled(Debug, defaultmethods)) {
-        ResourceMark rm;
+        ResourceMark rm(THREAD);
         outputStream* logstream = Log(defaultmethods)::debug_stream();
         logstream->print("for slot: ");
         slot->print_on(logstream);
@@ -929,6 +929,7 @@
       if (method->has_target()) {
         Method* selected = method->get_selected_target();
         if (selected->method_holder()->is_interface()) {
+          assert(!selected->is_private(), "pushing private interface method as default");
           defaults.push(selected);
         }
       } else if (method->throws_exception()) {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -858,8 +858,10 @@
   }
 
   if (log_develop_is_enabled(Trace, itables)) {
-    trace_method_resolution("invokeinterface resolved method: caller-class",
-                            link_info.current_klass(), resolved_klass,
+    char buf[200];
+    jio_snprintf(buf, sizeof(buf), "%s resolved interface method: caller-class:",
+                 Bytecodes::name(code));
+    trace_method_resolution(buf, link_info.current_klass(), resolved_klass,
                             resolved_method, true);
   }
 
@@ -1424,7 +1426,7 @@
   }
 
   if (log_develop_is_enabled(Trace, itables)) {
-    trace_method_resolution("invokeinterface selected method: receiver-class",
+    trace_method_resolution("invokeinterface selected method: receiver-class:",
                             recv_klass, resolved_klass, sel_method, true);
   }
   // setup result
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -674,20 +674,20 @@
 
 // Eagerly initialize superinterfaces that declare default methods (concrete instance: any access)
 void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) {
-  assert (this_k->has_default_methods(), "caller should have checked this");
+  assert (this_k->has_nonstatic_concrete_methods(), "caller should have checked this");
   for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
     Klass* iface = this_k->local_interfaces()->at(i);
     InstanceKlass* ik = InstanceKlass::cast(iface);
 
     // Initialization is depth first search ie. we start with top of the inheritance tree
-    // has_default_methods drives searching superinterfaces since it
-    // means has_default_methods in its superinterface hierarchy
-    if (ik->has_default_methods()) {
+    // has_nonstatic_concrete_methods drives searching superinterfaces since it
+    // means has_nonstatic_concrete_methods in its superinterface hierarchy
+    if (ik->has_nonstatic_concrete_methods()) {
       ik->initialize_super_interfaces(ik, CHECK);
     }
 
     // Only initialize() interfaces that "declare" concrete methods.
-    if (ik->should_be_initialized() && ik->declares_default_methods()) {
+    if (ik->should_be_initialized() && ik->declares_nonstatic_concrete_methods()) {
       ik->initialize(CHECK);
     }
   }
@@ -761,11 +761,11 @@
     if (super_klass != NULL && super_klass->should_be_initialized()) {
       super_klass->initialize(THREAD);
     }
-    // If C implements any interfaces that declares a non-abstract, non-static method,
+    // If C implements any interface that declares a non-static, concrete method,
     // the initialization of C triggers initialization of its super interfaces.
-    // Only need to recurse if has_default_methods which includes declaring and
-    // inheriting default methods
-    if (!HAS_PENDING_EXCEPTION && this_k->has_default_methods()) {
+    // Only need to recurse if has_nonstatic_concrete_methods which includes declaring and
+    // having a superinterface that declares, non-static, concrete methods
+    if (!HAS_PENDING_EXCEPTION && this_k->has_nonstatic_concrete_methods()) {
       this_k->initialize_super_interfaces(this_k, THREAD);
     }
 
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Mon Oct 03 21:48:21 2016 -0400
@@ -207,18 +207,18 @@
 
   // Start after _misc_kind field.
   enum {
-    _misc_rewritten                = 1 << 2,  // methods rewritten.
-    _misc_has_nonstatic_fields     = 1 << 3,  // for sizing with UseCompressedOops
-    _misc_should_verify_class      = 1 << 4,  // allow caching of preverification
-    _misc_is_anonymous             = 1 << 5,  // has embedded _host_klass field
-    _misc_is_contended             = 1 << 6,  // marked with contended annotation
-    _misc_has_default_methods      = 1 << 7,  // class/superclass/implemented interfaces has default methods
-    _misc_declares_default_methods = 1 << 8,  // directly declares default methods (any access)
-    _misc_has_been_redefined       = 1 << 9,  // class has been redefined
-    _misc_is_scratch_class         = 1 << 10, // class is the redefined scratch class
-    _misc_is_shared_boot_class     = 1 << 11, // defining class loader is boot class loader
-    _misc_is_shared_platform_class = 1 << 12, // defining class loader is platform class loader
-    _misc_is_shared_app_class      = 1 << 13  // defining class loader is app class loader
+    _misc_rewritten                           = 1 << 2,  // methods rewritten.
+    _misc_has_nonstatic_fields                = 1 << 3,  // for sizing with UseCompressedOops
+    _misc_should_verify_class                 = 1 << 4,  // allow caching of preverification
+    _misc_is_anonymous                        = 1 << 5,  // has embedded _host_klass field
+    _misc_is_contended                        = 1 << 6,  // marked with contended annotation
+    _misc_has_nonstatic_concrete_methods      = 1 << 7,  // class/superclass/implemented interfaces has non-static, concrete methods
+    _misc_declares_nonstatic_concrete_methods = 1 << 8,  // directly declares non-static, concrete methods
+    _misc_has_been_redefined                  = 1 << 9,  // class has been redefined
+    _misc_is_scratch_class                    = 1 << 10, // class is the redefined scratch class
+    _misc_is_shared_boot_class                = 1 << 11, // defining class loader is boot class loader
+    _misc_is_shared_platform_class            = 1 << 12, // defining class loader is platform class loader
+    _misc_is_shared_app_class                 = 1 << 13  // defining class loader is app class loader
   };
   u2 loader_type_bits() {
     return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
@@ -814,25 +814,25 @@
 
 #endif // INCLUDE_JVMTI
 
-  bool has_default_methods() const {
-    return (_misc_flags & _misc_has_default_methods) != 0;
+  bool has_nonstatic_concrete_methods() const {
+    return (_misc_flags & _misc_has_nonstatic_concrete_methods) != 0;
   }
-  void set_has_default_methods(bool b) {
+  void set_has_nonstatic_concrete_methods(bool b) {
     if (b) {
-      _misc_flags |= _misc_has_default_methods;
+      _misc_flags |= _misc_has_nonstatic_concrete_methods;
     } else {
-      _misc_flags &= ~_misc_has_default_methods;
+      _misc_flags &= ~_misc_has_nonstatic_concrete_methods;
     }
   }
 
-  bool declares_default_methods() const {
-    return (_misc_flags & _misc_declares_default_methods) != 0;
+  bool declares_nonstatic_concrete_methods() const {
+    return (_misc_flags & _misc_declares_nonstatic_concrete_methods) != 0;
   }
-  void set_declares_default_methods(bool b) {
+  void set_declares_nonstatic_concrete_methods(bool b) {
     if (b) {
-      _misc_flags |= _misc_declares_default_methods;
+      _misc_flags |= _misc_declares_nonstatic_concrete_methods;
     } else {
-      _misc_flags &= ~_misc_declares_default_methods;
+      _misc_flags &= ~_misc_declares_nonstatic_concrete_methods;
     }
   }
 
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -226,7 +226,7 @@
           HandleMark hm(THREAD);
           assert(default_methods->at(i)->is_method(), "must be a Method*");
           methodHandle mh(THREAD, default_methods->at(i));
-
+          assert(!mh->is_private(), "private interface method in the default method list");
           bool needs_new_entry = update_inherited_vtable(ik(), mh, super_vtable_len, i, checkconstraints, CHECK);
 
           // needs new entry
@@ -362,14 +362,16 @@
 
   Array<int>* def_vtable_indices = NULL;
   bool is_default = false;
-  // default methods are concrete methods in superinterfaces which are added to the vtable
-  // with their real method_holder
+
+  // default methods are non-private concrete methods in superinterfaces which are added
+  // to the vtable with their real method_holder.
   // Since vtable and itable indices share the same storage, don't touch
-  // the default method's real vtable/itable index
+  // the default method's real vtable/itable index.
   // default_vtable_indices stores the vtable value relative to this inheritor
   if (default_index >= 0 ) {
     is_default = true;
     def_vtable_indices = klass->default_vtable_indices();
+    assert(!target_method()->is_private(), "private interface method flagged as default");
     assert(def_vtable_indices != NULL, "def vtable alloc?");
     assert(default_index <= def_vtable_indices->length(), "def vtable len?");
   } else {
@@ -395,12 +397,15 @@
     // This method will either be assigned its own itable index later,
     // or be assigned an inherited vtable index in the loop below.
     // default methods inherited by classes store their vtable indices
-    // in the inheritor's default_vtable_indices
+    // in the inheritor's default_vtable_indices.
     // default methods inherited by interfaces may already have a
-    // valid itable index, if so, don't change it
-    // overpass methods in an interface will be assigned an itable index later
-    // by an inheriting class
-    if (!is_default || !target_method()->has_itable_index()) {
+    // valid itable index, if so, don't change it.
+    // Overpass methods in an interface will be assigned an itable index later
+    // by an inheriting class.
+    // Private interface methods have no itable index and are always invoked nonvirtually,
+    // so they retain their nonvirtual_vtable_index value, and therefore can_be_statically_bound()
+    // will return true.
+    if ((!is_default || !target_method()->has_itable_index()) && !target_method()->is_private()) {
       target_method()->set_vtable_index(Method::pending_itable_index);
     }
   }
@@ -597,7 +602,9 @@
   // abstract method entries using default inheritance rules
   if (target_method()->method_holder() != NULL &&
       target_method()->method_holder()->is_interface()  &&
-      !target_method()->is_abstract() ) {
+      !target_method()->is_abstract()) {
+    assert(target_method()->is_default_method() || target_method()->is_private(),
+           "unexpected interface method type");
     return false;
   }
 
@@ -606,10 +613,8 @@
     return true;
   }
 
-  // private methods in classes always have a new entry in the vtable
-  // specification interpretation since classic has
-  // private methods not overriding
-  // JDK8 adds private  methods in interfaces which require invokespecial
+  // private methods in classes always have a new entry in the vtable.
+  // Specification interpretation since classic has private methods not overriding.
   if (target_method()->is_private()) {
     return true;
   }
@@ -1088,6 +1093,7 @@
 inline bool interface_method_needs_itable_index(Method* m) {
   if (m->is_static())           return false;   // e.g., Stream.empty
   if (m->is_initializer())      return false;   // <init> or <clinit>
+  if (m->is_private())          return false;   // requires invokeSpecial
   // If an interface redeclares a method from java.lang.Object,
   // it should already have a vtable index, don't touch it.
   // e.g., CharSequence.toString (from initialize_vtable)
--- a/hotspot/src/share/vm/oops/method.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/oops/method.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -277,7 +277,8 @@
 }
 
 address Method::bcp_from(int bci) const {
-  assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci: %d", bci);
+  assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()),
+         "illegal bci: %d for %s method", bci, is_native() ? "native" : "non-native");
   address bcp = code_base() + bci;
   assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
   return bcp;
@@ -558,7 +559,7 @@
 bool Method::is_final_method(AccessFlags class_access_flags) const {
   // or "does_not_require_vtable_entry"
   // default method or overpass can occur, is not final (reuses vtable entry)
-  // private methods get vtable entries for backward class compatibility.
+  // private methods in classes get vtable entries for backward class compatibility.
   if (is_overpass() || is_default_method())  return false;
   return is_final() || class_access_flags.is_final();
 }
@@ -570,7 +571,7 @@
 bool Method::is_default_method() const {
   if (method_holder() != NULL &&
       method_holder()->is_interface() &&
-      !is_abstract()) {
+      !is_abstract() && !is_private()) {
     return true;
   } else {
     return false;
@@ -583,7 +584,9 @@
   ResourceMark rm;
   bool is_nonv = (vtable_index() == nonvirtual_vtable_index);
   if (class_access_flags.is_interface()) {
-    assert(is_nonv == is_static(), "is_nonv=%s", name_and_sig_as_C_string());
+      assert(is_nonv == is_static() || is_nonv == is_private(),
+             "nonvirtual unexpected for non-static, non-private: %s",
+             name_and_sig_as_C_string());
   }
 #endif
   assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question");
--- a/hotspot/src/share/vm/oops/method.hpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/oops/method.hpp	Mon Oct 03 21:48:21 2016 -0400
@@ -584,6 +584,7 @@
   // checks method and its method holder
   bool is_final_method() const;
   bool is_final_method(AccessFlags class_access_flags) const;
+  // interface method declared with 'default' - excludes private interface methods
   bool is_default_method() const;
 
   // true if method needs no dynamic dispatch (final and/or no vtable entry)
--- a/hotspot/src/share/vm/prims/jni.cpp	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/src/share/vm/prims/jni.cpp	Mon Oct 03 21:48:21 2016 -0400
@@ -1173,7 +1173,7 @@
   args->set_java_argument_object(&java_args);
 
   // handle arguments
-  assert(!method->is_static(), "method should not be static");
+  assert(!method->is_static(), "method %s should not be static", method->name_and_sig_as_C_string());
   args->push_receiver(h_recv); // Push jobject handle
 
   // Fill out JavaCallArguments object
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineInterfaceMethods.java	Mon Oct 03 21:48:21 2016 -0400
@@ -0,0 +1,104 @@
+/*
+ * 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 8081800
+ * @summary Redefine private and default interface methods
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
+ */
+public class RedefineInterfaceMethods {
+
+    static final int RET = -2;
+
+    static interface B {
+        int ORIGINAL_RETURN = 1;
+        int NEW_RETURN = 2;
+        private int privateMethod() {
+            return ORIGINAL_RETURN;
+        }
+        public default int defaultMethod() {
+            return privateMethod();
+        }
+    }
+
+    public static String redefinedPrivateMethod =
+        "interface RedefineInterfaceMethods$B {" +
+        "    int ORIGINAL_RETURN = 1;" +
+        "    int NEW_RETURN = 2;" +
+        "    private int privateMethod() {" +
+        "        return NEW_RETURN;" +
+        "    }" +
+        "    public default int defaultMethod() {" +
+        "       return privateMethod();" +
+        "    }" +
+        "}";
+
+    public static String redefinedDefaultMethod =
+        "interface RedefineInterfaceMethods$B {" +
+        "    int ORIGINAL_RETURN = 1;" +
+        "    int NEW_RETURN = 2;" +
+        "    private int privateMethod() {" +
+        "        return ORIGINAL_RETURN;" +
+        "    }" +
+        "    public default int defaultMethod() {" +
+        "       return RedefineInterfaceMethods.RET;" +
+        "    }" +
+        "}";
+
+    static class Impl implements B {
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        Impl impl = new Impl();
+
+        int res = impl.defaultMethod();
+        if (res != B.ORIGINAL_RETURN)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + B.ORIGINAL_RETURN);
+
+        RedefineClassHelper.redefineClass(B.class, redefinedPrivateMethod);
+
+        res = impl.defaultMethod();
+        if (res != B.NEW_RETURN)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + B.NEW_RETURN);
+
+        System.gc();
+
+        RedefineClassHelper.redefineClass(B.class, redefinedDefaultMethod);
+
+        res = impl.defaultMethod();
+        if (res != RET)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + RET);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/PrivateInterfaceMethods/PrivateInterfaceMethods.java	Mon Oct 03 21:48:21 2016 -0400
@@ -0,0 +1,130 @@
+/*
+ * 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 8081800
+ * @summary Add JNI invocation tests for private interface methods
+ * @run main/native PrivateInterfaceMethods
+ */
+
+public class PrivateInterfaceMethods {
+
+    static {
+        System.loadLibrary("PrivateInterfaceMethods");
+    }
+
+    static native int callIntVoid(Object target, String definingClassName, String methodName, boolean virtual);
+
+    static interface A {
+        static final int AmResult = 1;
+        private int m() { return AmResult; }
+    }
+
+    static interface B extends A {
+        // No m() here
+    }
+
+    static interface C extends B {
+        static final int CmResult = 2;
+        private int m() { return CmResult; }  // unrelated to A.m
+    }
+
+    public static class Impl implements C {
+        static final int ImplmResult = 3;
+        private int m() { return ImplmResult; } // unrelated to A.m or C.m
+    }
+
+    // We found that itable/vtable construction was affected by whether or not the
+    // implementation class declared a method with the same signature as the
+    // private interface method, so we test both variants.
+
+    public static class Impl2 implements C {
+    }
+
+    public static void main(String[] args) {
+        Impl impl = new Impl();
+
+        // Note: JNI doesn't enforce access control so we can make
+        //       private calls not possible in Java code.
+        //       Also it doesn't check that the receiver is a type that
+        //       defines the method!
+
+        // test: ((A)impl).m() - should succeed
+        test(impl, A.class.getName(), "m", A.AmResult, true, null);
+        test(impl, A.class.getName(), "m", A.AmResult, false, null);
+
+        // test: ((B)impl).m() - should fail: NoSuchMethodError
+        test(impl, B.class.getName(), "m", -1, true, NoSuchMethodError.class);
+        test(impl, B.class.getName(), "m", -1, false, NoSuchMethodError.class);
+
+        // test: ((C)impl).m() - should succeed
+        test(impl, C.class.getName(), "m", C.CmResult, true, null);
+        test(impl, C.class.getName(), "m", C.CmResult, false, null);
+
+        // test: impl.m() - should succeed
+        test(impl, Impl.class.getName(), "m", Impl.ImplmResult, true, null);
+        test(impl, Impl.class.getName(), "m", Impl.ImplmResult, false, null);
+
+        // ---
+
+        Impl2 impl2 = new Impl2();
+
+        // test: ((A)impl2).m() - should succeed
+        test(impl2, A.class.getName(), "m", A.AmResult, true, null);
+        test(impl2, A.class.getName(), "m", A.AmResult, false, null);
+
+        // test: ((B)impl2).m() - should fail: NoSuchMethodError
+        test(impl2, B.class.getName(), "m", -1, true, NoSuchMethodError.class);
+        test(impl2, B.class.getName(), "m", -1, false, NoSuchMethodError.class);
+
+        // test: ((C)impl2).m() - should succeed
+        test(impl2, C.class.getName(), "m", C.CmResult, true, null);
+        test(impl2, C.class.getName(), "m", C.CmResult, false, null);
+
+        // test: impl2.m() - should fail: NoSuchMethodError
+        test(impl2, Impl2.class.getName(), "m", -1, true, NoSuchMethodError.class);
+        test(impl2, Impl2.class.getName(), "m", -1, false, NoSuchMethodError.class);
+    }
+
+    static void test(Object target, String definingClass, String method,
+                     int expected, boolean virtual, Class<?> expectedException) {
+
+        String desc = (virtual ? "Virtual" : "Nonvirtual") + " Invocation of " +
+                       definingClass + "." + method + " on instance of class " +
+                       target.getClass().getName();
+        try {
+            int res = callIntVoid(target, definingClass, method, virtual);
+            if (expectedException != null)
+                throw new Error(desc + " succeeded - but expected exception " + expectedException.getSimpleName());
+            if (res != expected)
+                throw new Error(desc + " got wrong result: " + res + " instead of " + expected);
+            System.out.println(desc + " - passed");
+        }
+        catch (Throwable t) {
+           if (t.getClass() != expectedException)
+               throw new Error(desc + " failed", t);
+           else
+              System.out.println(desc + " threw " + expectedException.getSimpleName() + " as expected");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/PrivateInterfaceMethods/libPrivateInterfaceMethods.c	Mon Oct 03 21:48:21 2016 -0400
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+
+// Private interface methods call test
+JNIEXPORT jint JNICALL
+Java_PrivateInterfaceMethods_callIntVoid(JNIEnv *env, jclass unused, jobject impl, jstring defining_class_name,
+                                         jstring method_name, jboolean virtual) {
+
+    // Lookup int method_name() in defining_class_name, and if it exists call impl.method_name()
+    // using a virtual or non-virtual invocation as indicated
+
+    jmethodID m_id = NULL;
+    jclass clazz = NULL;
+    const char* name = NULL;
+
+    name = (*env)->GetStringUTFChars(env, defining_class_name, NULL);
+    if (name == NULL) return -1;
+    clazz = (*env)->FindClass(env, name);
+    (*env)->ReleaseStringUTFChars(env, defining_class_name, name);
+    if ((*env)->ExceptionCheck(env)) return -1;
+
+    name = (*env)->GetStringUTFChars(env, method_name, NULL);
+    if (name == NULL) return -1;
+    m_id = (*env)->GetMethodID(env, clazz, name, "()I");
+    (*env)->ReleaseStringUTFChars(env, method_name, name);
+    if ((*env)->ExceptionCheck(env)) return -1;
+
+    if (!virtual)
+        return (*env)->CallNonvirtualIntMethod(env, impl, clazz, m_id);
+    else
+        return (*env)->CallIntMethod(env, impl, m_id);
+}
--- a/hotspot/test/runtime/logging/ItablesTest.java	Wed Sep 28 18:40:50 2016 +0300
+++ b/hotspot/test/runtime/logging/ItablesTest.java	Mon Oct 03 21:48:21 2016 -0400
@@ -47,7 +47,7 @@
             output.shouldContain(": Initializing itable indices for interface ");
             output.shouldContain("itable index ");
             output.shouldContain("target: ClassB.Method1()V, method_holder: ClassB target_method flags: public");
-            output.shouldContain("invokeinterface resolved method: caller-class");
+            output.shouldContain("invokeinterface resolved interface method: caller-class");
             output.shouldContain("invokespecial resolved method: caller-class:ClassB");
             output.shouldContain("invokespecial selected method: resolved-class:ClassB");
             output.shouldContain("invokeinterface selected method: receiver-class");