hotspot/src/share/vm/classfile/classLoader.cpp
changeset 34666 1c7168ea0034
parent 34319 9d6dd3c5ca23
child 35498 392b50de06c6
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Tue Dec 08 05:50:46 2015 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Tue Dec 08 20:04:03 2015 +0100
@@ -23,13 +23,13 @@
  */
 
 #include "precompiled.hpp"
-#include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/classLoaderExt.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/jimage.hpp"
+#include "classfile/klassFactory.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "compiler/compileBroker.hpp"
@@ -170,17 +170,13 @@
 }
 
 
-ClassPathEntry::ClassPathEntry() {
-  set_next(NULL);
-}
-
-
 ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
   char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
   strcpy(copy, dir);
   _dir = copy;
 }
 
+
 ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
   // construct full path name
   char path[JVM_MAXPATHLEN];
@@ -211,14 +207,17 @@
         if (UsePerfData) {
           ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read);
         }
-        return new ClassFileStream(buffer, st.st_size, _dir);    // Resource allocated
+        // Resource allocated
+        return new ClassFileStream(buffer,
+                                   st.st_size,
+                                   _dir,
+                                   ClassFileStream::verify);
       }
     }
   }
   return NULL;
 }
 
-
 ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
   _zip = zip;
   char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
@@ -269,14 +268,18 @@
 
 ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
   jint filesize;
-  u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
+  const u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
   if (buffer == NULL) {
     return NULL;
   }
   if (UsePerfData) {
     ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
   }
-  return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated
+  // Resource allocated
+  return new ClassFileStream(buffer,
+                             filesize,
+                             _zip_name,
+                             ClassFileStream::verify);
 }
 
 // invoke function for each entry in the zip file
@@ -366,7 +369,11 @@
     }
     char* data = NEW_RESOURCE_ARRAY(char, size);
     (*JImageGetResource)(_jimage, location, data, size);
-    return new ClassFileStream((u1*)data, (int)size, _name);  // Resource allocated
+    // Resource allocated
+    return new ClassFileStream((u1*)data,
+                               (int)size,
+                               _name,
+                               ClassFileStream::verify);
   }
 
   return NULL;
@@ -996,74 +1003,94 @@
   return result();
 }
 
+// caller needs ResourceMark
+const char* ClassLoader::file_name_for_class_name(const char* class_name,
+                                                  int class_name_len) {
+  assert(class_name != NULL, "invariant");
+  assert((int)strlen(class_name) == class_name_len, "invariant");
 
-instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
-  ResourceMark rm(THREAD);
-  const char* class_name = h_name->as_C_string();
+  static const char class_suffix[] = ".class";
+
+  char* const file_name = NEW_RESOURCE_ARRAY(char,
+                                             class_name_len +
+                                             sizeof(class_suffix)); // includes term NULL
+
+  strncpy(file_name, class_name, class_name_len);
+  strncpy(&file_name[class_name_len], class_suffix, sizeof(class_suffix));
+
+  return file_name;
+}
+
+instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
+
+  assert(name != NULL, "invariant");
+  assert(THREAD->is_Java_thread(), "must be a JavaThread");
+
+  ResourceMark rm;
+  HandleMark hm;
+
+  const char* const class_name = name->as_C_string();
+
   EventMark m("loading class %s", class_name);
   ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
 
-  stringStream st;
-  // st.print() uses too much stack space while handling a StackOverflowError
-  // st.print("%s.class", h_name->as_utf8());
-  st.print_raw(h_name->as_utf8());
-  st.print_raw(".class");
-  const char* file_name = st.as_string();
+  const char* const file_name = file_name_for_class_name(class_name,
+                                                         name->utf8_length());
+  assert(file_name != NULL, "invariant");
+
   ClassLoaderExt::Context context(class_name, file_name, THREAD);
 
-  // Lookup stream for parsing .class file
+  // Lookup stream
   ClassFileStream* stream = NULL;
   int classpath_index = 0;
-  ClassPathEntry* e = NULL;
-  instanceKlassHandle h;
+  ClassPathEntry* e = _first_entry;
   {
     PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
-                               ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
-                               PerfClassTraceTime::CLASS_LOAD);
-    e = _first_entry;
-    while (e != NULL) {
+      ((JavaThread*)THREAD)->get_thread_stat()->perf_timers_addr(),
+      PerfClassTraceTime::CLASS_LOAD);
+
+    for (; e != NULL; e = e->next(), ++classpath_index) {
       stream = e->open_stream(file_name, CHECK_NULL);
+      if (NULL == stream) {
+        continue;
+      }
       if (!context.check(stream, classpath_index)) {
-        return h; // NULL
+        return NULL;
       }
-      if (stream != NULL) {
-        break;
-      }
-      e = e->next();
-      ++classpath_index;
+      break;
     }
   }
 
-  if (stream != NULL) {
-    // class file found, parse it
-    ClassFileParser parser(stream);
-    ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
-    Handle protection_domain;
-    TempNewSymbol parsed_name = NULL;
-    instanceKlassHandle result = parser.parseClassFile(h_name,
-                                                       loader_data,
-                                                       protection_domain,
-                                                       parsed_name,
-                                                       context.should_verify(classpath_index),
-                                                       THREAD);
-    if (HAS_PENDING_EXCEPTION) {
-      ResourceMark rm;
-      if (DumpSharedSpaces) {
-        tty->print_cr("Preload Error: Failed to load %s", class_name);
-      }
-      return h;
-    }
-    h = context.record_result(classpath_index, e, result, THREAD);
-  } else {
+  if (NULL == stream) {
     if (DumpSharedSpaces) {
       tty->print_cr("Preload Warning: Cannot find %s", class_name);
     }
+    return NULL;
   }
 
-  return h;
+  stream->set_verify(context.should_verify(classpath_index));
+
+  ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+  Handle protection_domain;
+
+  instanceKlassHandle result = KlassFactory::create_from_stream(stream,
+                                                                name,
+                                                                loader_data,
+                                                                protection_domain,
+                                                                NULL, // host_klass
+                                                                NULL, // cp_patches
+                                                                NULL, // parsed_name
+                                                                THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    if (DumpSharedSpaces) {
+      tty->print_cr("Preload Error: Failed to load %s", class_name);
+    }
+    return NULL;
+  }
+
+  return context.record_result(classpath_index, e, result, THREAD);
 }
 
-
 void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
                                             int number_of_entries) {
   assert(_package_hash_table == NULL, "One package info table allowed.");