< prev index next >

src/share/vm/classfile/classFileParser.cpp

Print this page

@@ -389,10 +389,11 @@
     // a bad CP entry has been detected previously so stop parsing and just return.
     return;
   }
 
   int index = 1;  // declared outside of loops for portability
+  int num_klasses = 0;
 
   // first verification pass - validate cross references
   // and fixup class and string constants
   for (index = 1; index < length; index++) {          // Index 0 is unused
     const jbyte tag = cp->tag_at(index).value();

@@ -457,11 +458,11 @@
       case JVM_CONSTANT_ClassIndex: {
         const int class_index = cp->klass_index_at(index);
         check_property(valid_symbol_at(class_index),
           "Invalid constant pool index %u in class file %s",
           class_index, CHECK);
-        cp->unresolved_klass_at_put(index, cp->symbol_at(class_index));
+        cp->unresolved_klass_at_put(index, class_index, num_klasses++);
         break;
       }
       case JVM_CONSTANT_StringIndex: {
         const int string_index = cp->string_index_at(index);
         check_property(valid_symbol_at(string_index),

@@ -548,12 +549,23 @@
         break;
       }
     } // switch(tag)
   } // end of for
 
+  _first_patched_klass_resolved_index = num_klasses;
+  cp->allocate_resolved_klasses(_loader_data, num_klasses + _max_num_patched_klasses, CHECK);
+
   if (_cp_patches != NULL) {
     // need to treat this_class specially...
+
+    // Add dummy utf8 entries in the space reserved for names of patched classes. We'll use "*"
+    // for now. These will be replaced with actual names of the patched classes in patch_class().
+    Symbol* s = vmSymbols::star_name();
+    for (int n=_orig_cp_size; n<cp->length(); n++) {
+      cp->symbol_at_put(n, s);
+    }
+    
     int this_class_index;
     {
       stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
       const u1* const mark = stream->current();
       stream->skip_u2_fast(1); // skip flags

@@ -699,10 +711,18 @@
       }
     }  // switch(tag)
   }  // end of for
 }
 
+void ClassFileParser::patch_class(ConstantPool* cp, int class_index, Klass* k, Symbol* name) {
+  int name_index = _orig_cp_size + _num_patched_klasses;
+  int resolved_klass_index = _first_patched_klass_resolved_index + _num_patched_klasses;
+
+  cp->klass_at_put(class_index, name_index, resolved_klass_index, k, name);
+  _num_patched_klasses ++;
+}
+
 void ClassFileParser::patch_constant_pool(ConstantPool* cp,
                                           int index,
                                           Handle patch,
                                           TRAPS) {
   assert(cp != NULL, "invariant");

@@ -716,17 +736,18 @@
       // The name in the constant pool is ignored.
       if (java_lang_Class::is_instance(patch())) {
         guarantee_property(!java_lang_Class::is_primitive(patch()),
                            "Illegal class patch at %d in class file %s",
                            index, CHECK);
-        cp->klass_at_put(index, java_lang_Class::as_Klass(patch()));
+        Klass* k = java_lang_Class::as_Klass(patch());
+        patch_class(cp, index, k, k->name());
       } else {
         guarantee_property(java_lang_String::is_instance(patch()),
                            "Illegal class patch at %d in class file %s",
                            index, CHECK);
         Symbol* const name = java_lang_String::as_symbol(patch(), CHECK);
-        cp->unresolved_klass_at_put(index, name);
+        patch_class(cp, index, NULL, name);
       }
       break;
     }
 
     case JVM_CONSTANT_String: {

@@ -5339,11 +5360,11 @@
 
   ik->set_name(_class_name);
 
   if (is_anonymous()) {
     // I am well known to myself
-    ik->constants()->klass_at_put(_this_class_index, ik); // eagerly resolve
+    patch_class(ik->constants(), _this_class_index, ik, ik->name()); // eagerly resolve
   }
 
   ik->set_minor_version(_minor_version);
   ik->set_major_version(_major_version);
   ik->set_has_nonstatic_concrete_methods(_has_nonstatic_concrete_methods);

@@ -5575,10 +5596,14 @@
   _stream(stream),
   _requested_name(name),
   _loader_data(loader_data),
   _host_klass(host_klass),
   _cp_patches(cp_patches),
+  _num_patched_klasses(0),
+  _max_num_patched_klasses(0),
+  _orig_cp_size(0),
+  _first_patched_klass_resolved_index(0),
   _super_klass(),
   _cp(NULL),
   _fields(NULL),
   _methods(NULL),
   _inner_classes(NULL),

@@ -5645,10 +5670,32 @@
   }
   else {
     _need_verify = Verifier::should_verify_for(_loader_data->class_loader(),
                                                stream->need_verify());
   }
+  // reserve space for names of the patches classes
+  if (is_anonymous()) {
+    _max_num_patched_klasses ++; // for patching the <this> class index
+  }
+  if (_cp_patches != NULL) {
+    int len = _cp_patches->length();
+    for (int i=0; i<len; i++) {
+      if (has_cp_patch_at(i)) {
+        Handle patch = cp_patch_at(i);
+        if (java_lang_String::is_instance(patch()) || java_lang_Class::is_instance(patch())) {
+          // We need to append the names of the patched classes to the end of the constant pool,
+          // because a patched class may have a Utf8 name that's not already included in the
+          // original constant pool.
+          //
+          // Note that a String in cp_patch_at(i) may be used to patch a Utf8, a String, or a Class.
+          // At this point, we don't know the tag for index i yet, because we haven't parsed the
+          // constant pool. So we can only assume the worst -- every String is used to patch a Class.
+          _max_num_patched_klasses ++;
+        }
+      }
+    }
+  }
 
   // synch back verification state to stream
   stream->set_verify(_need_verify);
 
   // Check if verification needs to be relaxed for this class file

@@ -5774,23 +5821,29 @@
       JAVA_MAX_SUPPORTED_MINOR_VERSION);
     return;
   }
 
   stream->guarantee_more(3, CHECK); // length, first cp tag
-  const u2 cp_size = stream->get_u2_fast();
+  u2 cp_size = stream->get_u2_fast();
 
   guarantee_property(
     cp_size >= 1, "Illegal constant pool size %u in class file %s",
     cp_size, CHECK);
 
+  _orig_cp_size = cp_size;
+  if (int(cp_size) + _max_num_patched_klasses > 0xffff) {
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes");
+  }
+  cp_size += _max_num_patched_klasses;
+
   _cp = ConstantPool::allocate(_loader_data,
                                cp_size,
                                CHECK);
 
   ConstantPool* const cp = _cp;
 
-  parse_constant_pool(stream, cp, cp_size, CHECK);
+  parse_constant_pool(stream, cp, _orig_cp_size, CHECK);
 
   assert(cp_size == (const u2)cp->length(), "invariant");
 
   // ACCESS FLAGS
   stream->guarantee_more(8, CHECK);  // flags, this_class, super_class, infs_len
< prev index next >