diff --git a/make/hotspot_distro b/make/hotspot_distro index 51bad9748eb3e48957f7b15b4a0a856906123a90..bb0a6952a728a277e2d223538dc8d3510be9184f 100644 --- a/make/hotspot_distro +++ b/make/hotspot_distro @@ -28,5 +28,5 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_DISTRO=Java HotSpot(TM) -COMPANY_NAME=Sun Microsystems, Inc. +COMPANY_NAME=Oracle Corporation PRODUCT_NAME=Java(TM) Platform SE diff --git a/src/os/linux/vm/attachListener_linux.cpp b/src/os/linux/vm/attachListener_linux.cpp index 93a85678688d7893c55c0b8b545605f5f857ae68..7999828fa74c2e10ba3e390f6d93132061acc81f 100644 --- a/src/os/linux/vm/attachListener_linux.cpp +++ b/src/os/linux/vm/attachListener_linux.cpp @@ -461,7 +461,7 @@ bool AttachListener::is_init_trigger() { if (init_at_startup() || is_initialized()) { return false; // initialized at startup or already initialized } - char fn[128]; + char fn[PATH_MAX+1]; sprintf(fn, ".attach_pid%d", os::current_process_id()); int ret; struct stat64 st; diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp index 478d34e7170d695e8de05fe7ddff47a7d89cb579..4dfcff7b607d33198b960b6163c92d75347f49e5 100644 --- a/src/os/linux/vm/os_linux.cpp +++ b/src/os/linux/vm/os_linux.cpp @@ -2305,7 +2305,7 @@ void linux_wrap_code(char* base, size_t size) { return; } - char buf[40]; + char buf[PATH_MAX+1]; int num = Atomic::add(1, &cnt); snprintf(buf, sizeof(buf), "%s/hs-vm-%d-%d", diff --git a/src/os/solaris/vm/attachListener_solaris.cpp b/src/os/solaris/vm/attachListener_solaris.cpp index c3f73da353cd1a5772b46f8104a52dcaee54849b..6ba1a897dff753b35d485b132438fa6c3844c1d8 100644 --- a/src/os/solaris/vm/attachListener_solaris.cpp +++ b/src/os/solaris/vm/attachListener_solaris.cpp @@ -592,7 +592,7 @@ bool AttachListener::is_init_trigger() { if (init_at_startup() || is_initialized()) { return false; // initialized at startup or already initialized } - char fn[128]; + char fn[PATH_MAX+1]; sprintf(fn, ".attach_pid%d", os::current_process_id()); int ret; struct stat64 st; diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp index 07ef9a8b9a51ae20f936f8e77a6d460cb6d4ac72..9e281f0d482a3d8a3437ae358d7632bc0110fadd 100644 --- a/src/share/vm/oops/methodOop.cpp +++ b/src/share/vm/oops/methodOop.cpp @@ -1114,6 +1114,20 @@ extern "C" { return ( a < b ? -1 : (a == b ? 0 : 1)); } + // We implement special compare versions for narrow oops to avoid + // testing for UseCompressedOops on every comparison. + static int method_compare_narrow(narrowOop* a, narrowOop* b) { + methodOop m = (methodOop)oopDesc::load_decode_heap_oop(a); + methodOop n = (methodOop)oopDesc::load_decode_heap_oop(b); + return m->name()->fast_compare(n->name()); + } + + static int method_compare_narrow_idempotent(narrowOop* a, narrowOop* b) { + int i = method_compare_narrow(a, b); + if (i != 0) return i; + return ( a < b ? -1 : (a == b ? 0 : 1)); + } + typedef int (*compareFn)(const void*, const void*); } @@ -1166,7 +1180,7 @@ void methodOopDesc::sort_methods(objArrayOop methods, // Use a simple bubble sort for small number of methods since // qsort requires a functional pointer call for each comparison. - if (UseCompressedOops || length < 8) { + if (length < 8) { bool sorted = true; for (int i=length-1; i>0; i--) { for (int j=0; jbase(), length, heapOopSize, compare); } diff --git a/test/runtime/6925573/SortMethodsTest.java b/test/runtime/6925573/SortMethodsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..33638c39ff8eeaee2f35f608c9317df18bc4c6a9 --- /dev/null +++ b/test/runtime/6925573/SortMethodsTest.java @@ -0,0 +1,190 @@ +/* + * Copyright 2008-2010 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Arrays; +import java.util.Vector; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/* + * @test SortMethodsTest + * @bug 6925573 + * @summary verify that class loading does not need quadratic time with regard to the number of class +methods. + * @run main SortMethodsTest + * @author volker.simonis@gmail.com +*/ + +public class SortMethodsTest { + + static String createClass(String name, int nrOfMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.println("public class " + name + "{"); + for (int i = 0; i < nrOfMethods; i++) { + pw.println(" public void m" + i + "() {}"); + } + pw.println(" public static String sayHello() {"); + pw.println(" return \"Hello from class \" + " + name + + ".class.getName() + \" with \" + " + name + + ".class.getDeclaredMethods().length + \" methods\";"); + pw.println(" }"); + pw.println("}"); + pw.close(); + return sw.toString(); + } + + public static void main(String args[]) { + + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + DiagnosticCollector diags = new DiagnosticCollector(); + final String cName = new String("ManyMethodsClass"); + Vector results = new Vector(); + + for (int i = 6; i < 600000; i*=10) { + String klass = createClass(cName, i); + JavaMemoryFileObject file = new JavaMemoryFileObject(cName, klass); + MemoryFileManager mfm = new MemoryFileManager(comp.getStandardFileManager(diags, null, null), file); + CompilationTask task = comp.getTask(null, mfm, diags, null, null, Arrays.asList(file)); + + if (task.call()) { + try { + MemoryClassLoader mcl = new MemoryClassLoader(file); + long start = System.nanoTime(); + Class c = Class.forName(cName, true, mcl); + long end = System.nanoTime(); + results.add(end - start); + Method m = c.getDeclaredMethod("sayHello", new Class[0]); + String ret = (String)m.invoke(null, new Object[0]); + System.out.println(ret + " (loaded and resloved in " + (end - start) + "ns)"); + } catch (Exception e) { + System.err.println(e); + } + } + else { + System.out.println(klass); + System.out.println(); + for (Diagnostic diag : diags.getDiagnostics()) { + System.out.println(diag.getCode() + "\n" + diag.getKind() + "\n" + diag.getPosition()); + System.out.println(diag.getSource() + "\n" + diag.getMessage(null)); + } + } + } + + long lastRatio = 0; + for (int i = 2; i < results.size(); i++) { + long normalized1 = Math.max(results.get(i-1) - results.get(0), 1); + long normalized2 = Math.max(results.get(i) - results.get(0), 1); + long ratio = normalized2/normalized1; + lastRatio = ratio; + System.out.println("10 x more methods requires " + ratio + " x more time"); + } + // The following is just vague estimation but seems to work on current x86_64 and sparcv9 machines + if (lastRatio > 80) { + throw new RuntimeException("ATTENTION: it seems that class loading needs quadratic time with regard to the number of class methods!!!"); + } + } +} + +class JavaMemoryFileObject extends SimpleJavaFileObject { + + private final String code; + private ByteArrayOutputStream byteCode; + + JavaMemoryFileObject(String name, String code) { + super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } + + @Override + public OutputStream openOutputStream() { + byteCode = new ByteArrayOutputStream(); + return byteCode; + } + + byte[] getByteCode() { + return byteCode.toByteArray(); + } +} + +class MemoryClassLoader extends ClassLoader { + + private final JavaMemoryFileObject jfo; + + public MemoryClassLoader(JavaMemoryFileObject jfo) { + this.jfo = jfo; + } + + public Class findClass(String name) { + byte[] b = jfo.getByteCode(); + return defineClass(name, b, 0, b.length); + } +} + +class MemoryFileManager extends ForwardingJavaFileManager { + + private final JavaFileObject jfo; + + public MemoryFileManager(StandardJavaFileManager jfm, JavaFileObject jfo) { + super(jfm); + this.jfo = jfo; + } + + @Override + public FileObject getFileForInput(Location location, String packageName, + String relativeName) throws IOException { + return jfo; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, + Kind kind, FileObject outputFile) throws IOException { + return jfo; + } + +}