hotspot/src/share/vm/oops/instanceKlass.cpp
changeset 30222 bfe6be3c4ef8
parent 29792 8c6fa07f0869
child 30227 fdb68fee3e41
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Mon Apr 13 18:49:59 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Apr 14 18:03:43 2015 +0300
@@ -2712,6 +2712,57 @@
   return false;
 }
 
+bool InstanceKlass::find_inner_classes_attr(instanceKlassHandle k, int* ooff, int* noff, TRAPS) {
+  constantPoolHandle i_cp(THREAD, k->constants());
+  for (InnerClassesIterator iter(k); !iter.done(); iter.next()) {
+    int ioff = iter.inner_class_info_index();
+    if (ioff != 0) {
+      // Check to see if the name matches the class we're looking for
+      // before attempting to find the class.
+      if (i_cp->klass_name_at_matches(k, ioff)) {
+        Klass* inner_klass = i_cp->klass_at(ioff, CHECK_false);
+        if (k() == inner_klass) {
+          *ooff = iter.outer_class_info_index();
+          *noff = iter.inner_name_index();
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+Klass* InstanceKlass::compute_enclosing_class_impl(instanceKlassHandle k, bool* inner_is_member, TRAPS) {
+  instanceKlassHandle outer_klass;
+  *inner_is_member = false;
+  int ooff = 0, noff = 0;
+  if (find_inner_classes_attr(k, &ooff, &noff, THREAD)) {
+    constantPoolHandle i_cp(THREAD, k->constants());
+    if (ooff != 0) {
+      Klass* ok = i_cp->klass_at(ooff, CHECK_NULL);
+      outer_klass = instanceKlassHandle(THREAD, ok);
+      *inner_is_member = true;
+    }
+    if (outer_klass.is_null()) {
+      // It may be anonymous; try for that.
+      int encl_method_class_idx = k->enclosing_method_class_index();
+      if (encl_method_class_idx != 0) {
+        Klass* ok = i_cp->klass_at(encl_method_class_idx, CHECK_NULL);
+        outer_klass = instanceKlassHandle(THREAD, ok);
+        *inner_is_member = false;
+      }
+    }
+  }
+
+  // If no inner class attribute found for this class.
+  if (outer_klass.is_null())  return NULL;
+
+  // Throws an exception if outer klass has not declared k as an inner klass
+  // We need evidence that each klass knows about the other, or else
+  // the system could allow a spoof of an inner class to gain access rights.
+  Reflection::check_for_inner_class(outer_klass, k, *inner_is_member, CHECK_NULL);
+  return outer_klass();
+}
 
 jint InstanceKlass::compute_modifier_flags(TRAPS) const {
   jint access = access_flags().as_int();