7133093: Improve system dictionary performance
Summary: implement one dictionary per ClassLoaderData for faster lookup and removal during class unloading
Reviewed-by: iklam, acorn, jiangli
--- a/hotspot/src/jdk.hotspot.agent/doc/jsdb.html Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/doc/jsdb.html Fri Jul 28 10:48:35 2017 -0400
@@ -1108,11 +1108,6 @@
calls callback with Klass and initiating loader (Oop) for System dictionary
entry.
</dd>
-<dt>forEachPrimArrayKlass(callback)</dt>
-<dd>
-calls callback with Klass and initiating loader (Oop) for each
-primitive array Klass in the system.
-</dd>
<dt>findInstanceKlass(name)</dt>
<dd>
finds the first instance klass with given name from System dictionary
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -48,6 +48,7 @@
import sun.jvm.hotspot.code.NMethod;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.debugger.OopHandle;
+import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
import sun.jvm.hotspot.memory.SymbolTable;
import sun.jvm.hotspot.memory.SystemDictionary;
import sun.jvm.hotspot.memory.Universe;
@@ -853,8 +854,8 @@
} else {
String s = t.nextToken();
if (s.equals("-a")) {
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
- sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (k instanceof InstanceKlass) {
MethodArray methods = ((InstanceKlass)k).getMethods();
@@ -887,8 +888,8 @@
if (t.countTokens() != 0) {
usage();
} else {
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
- sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {
MethodArray methods = ((InstanceKlass)k).getMethods();
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -25,16 +25,16 @@
package sun.jvm.hotspot.classfile;
import java.io.PrintStream;
-import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
public class ClassLoaderData extends VMObject {
static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
+ VM.registerVMInitializedObserver(new java.util.Observer() {
+ public void update(java.util.Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
@@ -44,19 +44,26 @@
Type type = db.lookupType("ClassLoaderData");
classLoaderField = type.getOopField("_class_loader");
nextField = type.getAddressField("_next");
- klassesField = type.getAddressField("_klasses");
+ klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
+ dictionaryField = type.getAddressField("_dictionary");
}
private static sun.jvm.hotspot.types.OopField classLoaderField;
private static AddressField nextField;
- private static AddressField klassesField;
+ private static MetadataField klassesField;
private static CIntField isAnonymousField;
+ private static AddressField dictionaryField;
public ClassLoaderData(Address addr) {
super(addr);
}
+ public Dictionary dictionary() {
+ Address tmp = dictionaryField.getValue();
+ return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
+ }
+
public static ClassLoaderData instantiateWrapperFor(Address addr) {
if (addr == null) {
return null;
@@ -76,7 +83,30 @@
return instantiateWrapperFor(nextField.getValue(getAddress()));
}
- public Klass getKlasses() {
- return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress()));
+ public Klass getKlasses() { return (Klass)klassesField.getValue(this); }
+
+ /** Lookup an already loaded class. If not found null is returned. */
+ public Klass find(Symbol className) {
+ for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+ if (className.equals(l.getName())) {
+ return l;
+ }
+ }
+ return null;
+ }
+
+ /** Iterate over all klasses - including object, primitive
+ array klasses */
+ public void classesDo(ClassLoaderDataGraph.ClassVisitor v) {
+ for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+ v.visit(l);
+ }
+ }
+
+ /** Iterate over all klasses in the dictionary, including initiating loader. */
+ public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v) {
+ for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+ dictionary().allEntriesDo(v, getClassLoader());
+ }
}
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -27,6 +27,7 @@
import java.io.PrintStream;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
@@ -52,21 +53,43 @@
return ClassLoaderData.instantiateWrapperFor(headField.getValue());
}
- public static interface KlassVisitor {
+ /** Lookup an already loaded class in any class loader. */
+ public Klass find(String className) {
+ Symbol sym = VM.getVM().getSymbolTable().probe(className);
+ if (sym == null) return null;
+ for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+ Klass k = cld.find(sym);
+ if (k != null) {
+ return k;
+ }
+ }
+ return null;
+ }
+
+ /** Interface for iterating through all classes. */
+ public static interface ClassVisitor {
public void visit(Klass k);
}
- /** Iterate over all anonymous class loaders and the klasses in those */
- public void allAnonymousKlassesDo(final KlassVisitor v) {
- for (ClassLoaderData cl = getClassLoaderGraphHead();
- cl != null;
- cl = cl.next()) {
- if (cl.getIsAnonymous() == true) {
- for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) {
- v.visit(k);
- }
- }
+ /** Interface for iterating through all classes and their class
+ loaders in dictionary */
+ public static interface ClassAndLoaderVisitor {
+ public void visit(Klass k, Oop loader);
+ }
+
+ /** Iterate over all klasses - including object, primitive
+ array klasses */
+ public void classesDo(ClassVisitor v) {
+ for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+ cld.classesDo(v);
}
}
+ /** Iterate over all klasses - including object, primitive
+ array klasses, pass initiating loader. */
+ public void allEntriesDo(ClassAndLoaderVisitor v) {
+ for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+ cld.allEntriesDo(v);
+ }
+ }
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -26,12 +26,13 @@
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
-public class Dictionary extends TwoOopHashtable {
+public class Dictionary extends sun.jvm.hotspot.utilities.Hashtable {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@@ -55,56 +56,32 @@
return DictionaryEntry.class;
}
- /** Iterate over all klasses in dictionary; just the classes from
- declaring class loaders */
- public void classesDo(SystemDictionary.ClassVisitor v) {
- ObjectHeap heap = VM.getVM().getObjectHeap();
+ /** All classes, and their initiating class loader, passed in. */
+ public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v, Oop loader) {
int tblSize = tableSize();
for (int index = 0; index < tblSize; index++) {
for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
- probe = (DictionaryEntry) probe.next()) {
+ probe = (DictionaryEntry) probe.next()) {
Klass k = probe.klass();
- if (heap.equal(probe.loader(), ((InstanceKlass) k).getClassLoader())) {
- v.visit(k);
- }
+ v.visit(k, loader);
}
}
}
- /** All classes, and their class loaders */
- public void classesDo(SystemDictionary.ClassAndLoaderVisitor v) {
- int tblSize = tableSize();
- for (int index = 0; index < tblSize; index++) {
- for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
- probe = (DictionaryEntry) probe.next()) {
- Klass k = probe.klass();
- v.visit(k, probe.loader());
- }
- }
- }
-
- public Klass find(int index, long hash, Symbol className, Oop classLoader, Oop protectionDomain) {
- DictionaryEntry entry = getEntry(index, hash, className, classLoader);
- if (entry != null && entry.isValidProtectionDomain(protectionDomain)) {
- return entry.klass();
- }
- return null;
- }
-
// - Internals only below this point
- private DictionaryEntry getEntry(int index, long hash, Symbol className, Oop classLoader) {
+ private DictionaryEntry getEntry(int index, long hash, Symbol className) {
for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
entry = (DictionaryEntry) entry.next()) {
- if (entry.hash() == hash && entry.equals(className, classLoader)) {
+ if (entry.hash() == hash && entry.equals(className)) {
return entry;
}
}
return null;
}
- public boolean contains(Klass c, Oop classLoader) {
- long hash = computeHash(c.getName(), classLoader);
+ public boolean contains(Klass c) {
+ long hash = computeHash(c.getName());
int index = hashToIndex(hash);
for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -43,28 +43,6 @@
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("DictionaryEntry");
- pdSetField = type.getAddressField("_pd_set");
- loaderDataField = type.getAddressField("_loader_data");
- }
-
- // Fields
- private static AddressField pdSetField;
- private static AddressField loaderDataField;
-
- // Accessors
-
- public ProtectionDomainEntry pdSet() {
- Address tmp = pdSetField.getValue(addr);
- return (ProtectionDomainEntry) VMObjectFactory.newObject(
- ProtectionDomainEntry.class, tmp);
- }
-
- public Oop loader() {
- return loaderData().getClassLoader();
- }
-
- public ClassLoaderData loaderData() {
- return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
}
public Klass klass() {
@@ -75,38 +53,9 @@
super(addr);
}
- public boolean equals(Symbol className, Oop classLoader) {
+ public boolean equals(Symbol className) {
InstanceKlass ik = (InstanceKlass) klass();
- Oop loader = loader();
- if (! ik.getName().equals(className)) {
- return false;
- } else {
- return (loader == null)? (classLoader == null) :
- (loader.equals(classLoader));
- }
- }
-
- public boolean isValidProtectionDomain(Oop protectionDomain) {
- if (protectionDomain == null) {
- return true;
- } else {
- return containsProtectionDomain(protectionDomain);
- }
- }
-
- public boolean containsProtectionDomain(Oop protectionDomain) {
- InstanceKlass ik = (InstanceKlass) klass();
- // Currently unimplemented and not used.
- // if (protectionDomain.equals(ik.getJavaMirror().getProtectionDomain())) {
- // return true; // Succeeds trivially
- // }
- for (ProtectionDomainEntry current = pdSet(); current != null;
- current = current.next()) {
- if (protectionDomain.equals(current.protectionDomain())) {
- return true;
- }
- }
- return false;
+ return ik.getName().equals(className);
}
/* covariant return type :-(
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class LoaderConstraintEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("LoaderConstraintEntry");
- nameField = type.getAddressField("_name");
- numLoadersField = type.getCIntegerField("_num_loaders");
- maxLoadersField = type.getCIntegerField("_max_loaders");
- loadersField = type.getAddressField("_loaders");
- }
-
- // Fields
- private static AddressField nameField;
- private static CIntegerField numLoadersField;
- private static CIntegerField maxLoadersField;
- private static AddressField loadersField;
-
- // Accessors
-
- public Symbol name() {
- return Symbol.create(nameField.getValue(addr));
- }
-
- public int numLoaders() {
- return (int) numLoadersField.getValue(addr);
- }
-
- public int maxLoaders() {
- return (int) maxLoadersField.getValue(addr);
- }
-
- public Oop initiatingLoader(int i) {
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(i >= 0 && i < numLoaders(), "invalid index");
- }
- Address loaders = loadersField.getValue(addr);
- OopHandle loader = loaders.addOffsetToAsOopHandle(i * VM.getVM().getOopSize());
- return VM.getVM().getObjectHeap().newOop(loader);
- }
-
- public LoaderConstraintEntry(Address addr) {
- super(addr);
- }
-
- /* covariant return type :-(
- public LoaderConstraintEntry next() {
- return (LoaderConstraintEntry) super.next();
- }
- For now, let the caller cast it ..
- */
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class LoaderConstraintTable extends TwoOopHashtable {
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("LoaderConstraintTable");
- }
-
- public LoaderConstraintTable(Address addr) {
- super(addr);
- }
-
- // this is overriden here so that Hashtable.bucket will return
- // object of LoaderConstraintEntry.class
- protected Class getHashtableEntryClass() {
- return LoaderConstraintEntry.class;
- }
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.classfile.ClassLoaderData;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class PlaceholderEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("PlaceholderEntry");
- loaderDataField = type.getAddressField("_loader_data");
- }
-
- // Field
- private static AddressField loaderDataField;
-
- // Accessor
- public Oop loader() {
- return loaderData().getClassLoader();
- }
-
- public ClassLoaderData loaderData() {
- return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
- }
-
- public PlaceholderEntry(Address addr) {
- super(addr);
- }
-
- public Symbol klass() {
- return Symbol.create(literalValue());
- }
-
- /* covariant return type :-(
- public PlaceholderEntry next() {
- return (PlaceholderEntry) super.next();
- }
- For now, let the caller cast it ..
- */
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class PlaceholderTable extends TwoOopHashtable {
- public PlaceholderTable(Address addr) {
- super(addr);
- }
-
- // this is overriden here so that Hashtable.bucket will return
- // object of PlacholderEntry.class
- protected Class getHashtableEntryClass() {
- return PlaceholderEntry.class;
- }
-
- /** All array classes of primitive type, and their class loaders */
- public void primArrayClassesDo(SystemDictionary.ClassAndLoaderVisitor v) {
- ObjectHeap heap = VM.getVM().getObjectHeap();
- int tblSize = tableSize();
- for (int index = 0; index < tblSize; index++) {
- for (PlaceholderEntry probe = (PlaceholderEntry) bucket(index); probe != null;
- probe = (PlaceholderEntry) probe.next()) {
- Symbol sym = probe.klass();
- // array of primitive arrays are stored in system dictionary as placeholders
- FieldType ft = new FieldType(sym);
- if (ft.isArray()) {
- FieldType.ArrayInfo info = ft.getArrayInfo();
- if (info.elementBasicType() != BasicType.getTObject()) {
- Klass arrayKlass = heap.typeArrayKlassObj(info.elementBasicType());
- arrayKlass = arrayKlass.arrayKlassOrNull(info.dimension());
- v.visit(arrayKlass, probe.loader());
- }
- }
- }
- }
- }
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-public class ProtectionDomainCacheEntry extends VMObject {
- private static sun.jvm.hotspot.types.OopField protectionDomainField;
-
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("ProtectionDomainCacheEntry");
- protectionDomainField = type.getOopField("_literal");
- }
-
- public ProtectionDomainCacheEntry(Address addr) {
- super(addr);
- }
-
- public Oop protectionDomain() {
- return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr));
- }
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, 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.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-public class ProtectionDomainEntry extends VMObject {
- private static AddressField nextField;
- private static AddressField pdCacheField;
-
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("ProtectionDomainEntry");
-
- nextField = type.getAddressField("_next");
- pdCacheField = type.getAddressField("_pd_cache");
- }
-
- public ProtectionDomainEntry(Address addr) {
- super(addr);
- }
-
- public ProtectionDomainEntry next() {
- return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr));
- }
-
- public Oop protectionDomain() {
- ProtectionDomainCacheEntry pd_cache = (ProtectionDomainCacheEntry)
- VMObjectFactory.newObject(ProtectionDomainCacheEntry.class, pdCacheField.getValue(addr));
- return pd_cache.protectionDomain();
- }
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -26,15 +26,13 @@
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
public class SystemDictionary {
- private static AddressField dictionaryField;
private static AddressField sharedDictionaryField;
- private static AddressField placeholdersField;
- private static AddressField loaderConstraintTableField;
private static sun.jvm.hotspot.types.OopField javaSystemLoaderField;
private static AddressField objectKlassField;
@@ -56,10 +54,7 @@
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("SystemDictionary");
- dictionaryField = type.getAddressField("_dictionary");
sharedDictionaryField = type.getAddressField("_shared_dictionary");
- placeholdersField = type.getAddressField("_placeholders");
- loaderConstraintTableField = type.getAddressField("_loader_constraints");
javaSystemLoaderField = type.getOopField("_java_system_loader");
objectKlassField = type.getAddressField(WK_KLASS("Object_klass"));
@@ -81,26 +76,11 @@
return (kname+"_knum");
}
- public Dictionary dictionary() {
- Address tmp = dictionaryField.getValue();
- return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
- }
-
public Dictionary sharedDictionary() {
Address tmp = sharedDictionaryField.getValue();
return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
}
- public PlaceholderTable placeholders() {
- Address tmp = placeholdersField.getValue();
- return (PlaceholderTable) VMObjectFactory.newObject(PlaceholderTable.class, tmp);
- }
-
- public LoaderConstraintTable constraints() {
- Address tmp = placeholdersField.getValue();
- return (LoaderConstraintTable) VMObjectFactory.newObject(LoaderConstraintTable.class, tmp);
- }
-
// few well known classes -- not all are added here.
// add more if needed.
public static InstanceKlass getThreadKlass() {
@@ -132,8 +112,8 @@
}
public InstanceKlass getAbstractOwnableSynchronizerKlass() {
- return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer",
- null, null);
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ return (InstanceKlass) cldg.find("java/util/concurrent/locks/AbstractOwnableSynchronizer");
}
public static Oop javaSystemLoader() {
@@ -143,60 +123,4 @@
private static Oop newOop(OopHandle handle) {
return VM.getVM().getObjectHeap().newOop(handle);
}
-
- /** Lookup an already loaded class. If not found null is returned. */
- public Klass find(String className, Oop classLoader, Oop protectionDomain) {
- Symbol sym = VM.getVM().getSymbolTable().probe(className);
- if (sym == null) return null;
- return find(sym, classLoader, protectionDomain);
- }
-
- /** Lookup an already loaded class. If not found null is returned. */
- public Klass find(Symbol className, Oop classLoader, Oop protectionDomain) {
- Dictionary dict = dictionary();
- long hash = dict.computeHash(className, classLoader);
- int index = dict.hashToIndex(hash);
- return dict.find(index, hash, className, classLoader, protectionDomain);
- }
-
- /** Interface for iterating through all classes in dictionary */
- public static interface ClassVisitor {
- public void visit(Klass k);
- }
-
- /** Interface for iterating through all classes and their class
- loaders in dictionary */
- public static interface ClassAndLoaderVisitor {
- public void visit(Klass k, Oop loader);
- }
-
- /** Iterate over all klasses - including object, primitive
- array klasses */
- public void allClassesDo(final ClassVisitor v) {
- ClassVisitor visitor = new ClassVisitor() {
- public void visit(Klass k) {
- for (Klass l = k; l != null; l = l.arrayKlassOrNull()) {
- v.visit(l);
- }
- }
- };
- classesDo(visitor);
- VM.getVM().getUniverse().basicTypeClassesDo(visitor);
- }
-
- /** Iterate over all klasses in dictionary; just the classes from
- declaring class loaders */
- public void classesDo(ClassVisitor v) {
- dictionary().classesDo(v);
- }
-
- /** All classes, and their class loaders */
- public void classesDo(ClassAndLoaderVisitor v) {
- dictionary().classesDo(v);
- }
-
- /** All array classes of primitive type, and their class loaders */
- public void primArrayClassesDo(ClassAndLoaderVisitor v) {
- placeholders().primArrayClassesDo(v);
- }
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -164,18 +164,6 @@
return newOop(systemThreadGroupField.getValue());
}
- // iterate through the single dimensional primitive array klasses
- // refer to basic_type_classes_do(void f(Klass*)) in universe.cpp
- public void basicTypeClassesDo(SystemDictionary.ClassVisitor visitor) {
- visitor.visit(new TypeArrayKlass(boolArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(byteArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(charArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(intArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(shortArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(longArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(singleArrayKlassField.getValue()));
- visitor.visit(new TypeArrayKlass(doubleArrayKlassField.getValue()));
- }
public void print() { printOn(System.out); }
public void printOn(PrintStream tty) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Jul 28 10:48:35 2017 -0400
@@ -91,7 +91,6 @@
fields = type.getAddressField("_fields");
javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
constants = new MetadataField(type.getAddressField("_constants"), 0);
- classLoaderData = type.getAddressField("_class_loader_data");
sourceDebugExtension = type.getAddressField("_source_debug_extension");
innerClasses = type.getAddressField("_inner_classes");
sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
@@ -166,7 +165,6 @@
private static AddressField fields;
private static CIntField javaFieldsCount;
private static MetadataField constants;
- private static AddressField classLoaderData;
private static AddressField sourceDebugExtension;
private static AddressField innerClasses;
private static CIntField sourceFileNameIndex;
@@ -328,7 +326,7 @@
// MetaspaceObj in the CDS shared archive.
Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary();
if (sharedDictionary != null) {
- if (sharedDictionary.contains(this, null)) {
+ if (sharedDictionary.contains(this)) {
return true;
}
}
@@ -448,8 +446,6 @@
return allFieldsCount;
}
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
- public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
- public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); }
public Symbol getSourceFileName() { return getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); }
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -27,6 +27,7 @@
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
@@ -63,6 +64,7 @@
nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0);
nextLink = new MetadataField(type.getAddressField("_next_link"), 0);
vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0);
+ classLoaderData = type.getAddressField("_class_loader_data");
LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue();
LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue();
@@ -96,6 +98,7 @@
private static MetadataField nextLink;
private static sun.jvm.hotspot.types.Field traceIDField;
private static CIntField vtableLen;
+ private static AddressField classLoaderData;
private Address getValue(AddressField field) {
return addr.getAddressAt(field.getOffset());
@@ -110,7 +113,7 @@
public Klass getSuper() { return (Klass) superField.getValue(this); }
public Klass getJavaSuper() { return null; }
public int getLayoutHelper() { return (int) layoutHelper.getValue(this); }
- public Symbol getName() { return getSymbol(name); }
+ public Symbol getName() { return getSymbol(name); }
public long getAccessFlags() { return accessFlags.getValue(this); }
// Convenience routine
public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); }
@@ -119,6 +122,9 @@
public Klass getNextLinkKlass() { return (Klass) nextLink.getValue(this); }
public long getVtableLen() { return vtableLen.getValue(this); }
+ public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
+ public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); }
+
public long traceID() {
if (traceIDField == null) return 0;
return traceIDField.getJLong(addr);
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -28,6 +28,7 @@
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
@@ -106,8 +107,8 @@
err.print("computing per loader stat ..");
}
- SystemDictionary dict = VM.getVM().getSystemDictionary();
- dict.classesDo(new SystemDictionary.ClassVisitor() {
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (! (k instanceof InstanceKlass)) {
return;
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -29,6 +29,7 @@
import java.util.jar.JarOutputStream;
import java.util.jar.JarEntry;
import java.util.jar.Manifest;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.debugger.*;
@@ -100,9 +101,9 @@
setOutputDirectory(dirName);
}
- // walk through the system dictionary
- SystemDictionary dict = VM.getVM().getSystemDictionary();
- dict.classesDo(new SystemDictionary.ClassVisitor() {
+ // walk through the loaded classes
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (k instanceof InstanceKlass) {
try {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -27,6 +27,7 @@
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
public class Hashtable extends BasicHashtable {
@@ -48,6 +49,10 @@
return HashtableEntry.class;
}
+ public int computeHash(Symbol name) {
+ return (int) name.identityHash();
+ }
+
public int hashToIndex(long fullHash) {
return (int) (fullHash % tableSize());
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Jul 28 10:48:35 2017 -0400
@@ -586,23 +586,9 @@
}
private void writeClassDumpRecords() throws IOException {
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
- sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
- public void visit(Klass k) {
- try {
- writeHeapRecordPrologue();
- writeClassDumpRecord(k);
- writeHeapRecordEpilogue();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- });
- // Add the anonymous classes also which are not present in the
- // System Dictionary
- cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+ cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
try {
writeHeapRecordPrologue();
@@ -1088,26 +1074,9 @@
private void writeClasses() throws IOException {
// write class list (id, name) association
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
try {
- sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
- public void visit(Klass k) {
- try {
- Instance clazz = k.getJavaMirror();
- writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
- out.writeInt(serialNum);
- writeObjectID(clazz);
- KlassMap.add(serialNum - 1, k);
- out.writeInt(DUMMY_STACK_TRACE_ID);
- writeSymbolID(k.getName());
- serialNum++;
- } catch (IOException exp) {
- throw new RuntimeException(exp);
- }
- }
- });
- cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+ cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
try {
Instance clazz = k.getJavaMirror();
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -27,6 +27,7 @@
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.gc.shared.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
@@ -113,8 +114,8 @@
new RootVisitor("Weak global JNI handle root"));
// Do Java-level static fields
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
- sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (k instanceof InstanceKlass) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -25,6 +25,7 @@
package sun.jvm.hotspot.utilities;
import java.util.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
@@ -52,8 +53,8 @@
}
final Vector tmp = new Vector();
- SystemDictionary dict = VM.getVM().getSystemDictionary();
- dict.classesDo(new SystemDictionary.ClassVisitor() {
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass k) {
if (k instanceof InstanceKlass) {
InstanceKlass ik = (InstanceKlass) k;
@@ -100,42 +101,15 @@
public static InstanceKlass findInstanceKlass(String className) {
// convert to internal name
className = className.replace('.', '/');
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
-
- // check whether we have a bootstrap class of given name
- Klass klass = sysDict.find(className, null, null);
- if (klass != null) {
- return (InstanceKlass) klass;
- }
-
- // check whether we have a system class of given name
- klass = sysDict.find(className, sysDict.javaSystemLoader(), null);
- if (klass != null) {
- return (InstanceKlass) klass;
- }
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
- // didn't find bootstrap or system class of given name.
- // search through the entire dictionary..
- InstanceKlass[] tmpKlasses = getAllInstanceKlasses();
- // instance klass array is sorted by name. do binary search
- int low = 0;
- int high = tmpKlasses.length-1;
-
- int mid = -1;
- while (low <= high) {
- mid = (low + high) >> 1;
- InstanceKlass midVal = tmpKlasses[mid];
- int cmp = midVal.getName().asString().compareTo(className);
-
- if (cmp < 0) {
- low = mid + 1;
- } else if (cmp > 0) {
- high = mid - 1;
- } else { // match found
- return tmpKlasses[mid];
- }
+ // check whether we have a class of given name
+ Klass klass = cldg.find(className);
+ if (klass != null && klass instanceof InstanceKlass) {
+ return (InstanceKlass) klass;
+ } else {
+ // no match ..
+ return null;
}
- // no match ..
- return null;
}
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/TwoOopHashtable.java Thu Jul 27 17:47:57 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- *
- */
-
-package sun.jvm.hotspot.utilities;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-
-public class TwoOopHashtable extends Hashtable {
- public TwoOopHashtable(Address addr) {
- super(addr);
- }
-
- public long computeHash(Symbol name, Oop loader) {
- return ((int) name.identityHash()
- ^ (int) (loader == null ? 0 : loader.identityHash())) & 0xFFFFFFFFL;
- }
-
- public int indexFor(Symbol name, Oop loader) {
- return hashToIndex(computeHash(name, loader));
- }
-}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -27,6 +27,7 @@
import java.util.*;
import javax.script.ScriptException;
import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
@@ -166,11 +167,12 @@
}
final Callable finalFunc = func;
- SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+ ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
if (withLoader) {
- sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
- public void visit(Klass kls, Oop loader) {
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
+ public void visit(Klass kls) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
+ Oop loader = kls.getClassLoader();
if (jk == null) {
return;
}
@@ -189,7 +191,7 @@
});
} else {
- sysDict.classesDo(new SystemDictionary.ClassVisitor() {
+ cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass kls) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
if (jk == null) {
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -513,24 +513,18 @@
return sa.sysDict.javaSystemLoader();
}
-// iterate system dictionary for each 'Klass'
+// iterate class loader data for each 'Klass'
function forEachKlass(callback) {
- var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor;
+ var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassVisitor;
var visitor = new VisitorClass() { visit: callback };
- sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor);
+ sa.sysDict["classesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassVisitor)"](visitor);
}
// iterate system dictionary for each 'Klass' and initiating loader
function forEachKlassAndLoader(callback) {
- var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
+ var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor;
var visitor = new VisitorClass() { visit: callback };
- sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor);
-}
-
-// iterate system dictionary for each primitive array klass
-function forEachPrimArrayKlass(callback) {
- var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
- sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback });
+ sa.sysDict["allEntriesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor)"](visitor);
}
// 'oop' to higher-level java object wrapper in which for(i in o)
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -49,6 +49,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
+#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
@@ -114,6 +115,12 @@
} else {
_unnamed_module = NULL;
}
+
+ if (!is_anonymous) {
+ _dictionary = create_dictionary();
+ } else {
+ _dictionary = NULL;
+ }
TRACE_INIT_ID(this);
}
@@ -450,10 +457,82 @@
}
}
+// Class iterator used by the compiler. It gets some number of classes at
+// a safepoint to decay invocation counters on the methods.
+class ClassLoaderDataGraphKlassIteratorStatic {
+ ClassLoaderData* _current_loader_data;
+ Klass* _current_class_entry;
+ public:
+
+ ClassLoaderDataGraphKlassIteratorStatic() : _current_loader_data(NULL), _current_class_entry(NULL) {}
+
+ InstanceKlass* try_get_next_class() {
+ assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+ int max_classes = InstanceKlass::number_of_instance_classes();
+ for (int i = 0; i < max_classes; i++) {
+
+ if (_current_class_entry != NULL) {
+ Klass* k = _current_class_entry;
+ _current_class_entry = _current_class_entry->next_link();
+
+ if (k->is_instance_klass()) {
+ InstanceKlass* ik = InstanceKlass::cast(k);
+ // Only return loaded classes
+ if (ik->is_loaded()) {
+ return ik;
+ }
+ }
+ } else {
+ // Go to next CLD
+ if (_current_loader_data != NULL) {
+ _current_loader_data = _current_loader_data->next();
+ }
+ // Start at the beginning
+ if (_current_loader_data == NULL) {
+ _current_loader_data = ClassLoaderDataGraph::_head;
+ }
+
+ _current_class_entry = _current_loader_data->klasses();
+ }
+ }
+ // should never be reached: an InstanceKlass should be returned above
+ ShouldNotReachHere();
+ return NULL; // Object_klass not even loaded?
+ }
+
+ // If the current class for the static iterator is a class being unloaded or
+ // deallocated, adjust the current class.
+ void adjust_saved_class(ClassLoaderData* cld) {
+ if (_current_loader_data == cld) {
+ _current_loader_data = cld->next();
+ if (_current_loader_data != NULL) {
+ _current_class_entry = _current_loader_data->klasses();
+ } // else try_get_next_class will start at the head
+ }
+ }
+
+ void adjust_saved_class(Klass* klass) {
+ if (_current_class_entry == klass) {
+ _current_class_entry = klass->next_link();
+ }
+ }
+};
+
+static ClassLoaderDataGraphKlassIteratorStatic static_klass_iterator;
+
+InstanceKlass* ClassLoaderDataGraph::try_get_next_class() {
+ return static_klass_iterator.try_get_next_class();
+}
+
+
// Remove a klass from the _klasses list for scratch_class during redefinition
// or parsed class in the case of an error.
void ClassLoaderData::remove_class(Klass* scratch_class) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
+
+ // Adjust global class iterator.
+ static_klass_iterator.adjust_saved_class(scratch_class);
+
Klass* prev = NULL;
for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
if (k == scratch_class) {
@@ -493,6 +572,9 @@
// In some rare cases items added to this list will not be freed elsewhere.
// To keep it simple, just free everything in it here.
free_deallocate_list();
+
+ // Clean up global class iterator for compiler
+ static_klass_iterator.adjust_saved_class(this);
}
ModuleEntryTable* ClassLoaderData::modules() {
@@ -515,6 +597,45 @@
return modules;
}
+const int _boot_loader_dictionary_size = 1009;
+const int _default_loader_dictionary_size = 107;
+const int _prime_array_size = 8; // array of primes for system dictionary size
+const int _average_depth_goal = 3; // goal for lookup length
+const int _primelist[_prime_array_size] = {107, 1009, 2017, 4049, 5051, 10103, 20201, 40423};
+
+// Calculate a "good" dictionary size based
+// on predicted or current loaded classes count.
+static int calculate_dictionary_size(int classcount) {
+ int newsize = _primelist[0];
+ if (classcount > 0 && !DumpSharedSpaces) {
+ int index = 0;
+ int desiredsize = classcount/_average_depth_goal;
+ for (newsize = _primelist[index]; index < _prime_array_size -1;
+ newsize = _primelist[++index]) {
+ if (desiredsize <= newsize) {
+ break;
+ }
+ }
+ }
+ return newsize;
+}
+
+Dictionary* ClassLoaderData::create_dictionary() {
+ assert(!is_anonymous(), "anonymous class loader data do not have a dictionary");
+ int size;
+ if (_the_null_class_loader_data == NULL) {
+ size = _boot_loader_dictionary_size;
+ } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
+ size = 1; // there's only one class in relection class loader and no initiated classes
+ } else if (is_system_class_loader_data()) {
+ size = calculate_dictionary_size(PredictedLoadedClassCount);
+ } else {
+ size = _default_loader_dictionary_size;
+ }
+ return new Dictionary(this, size);
+}
+
+// Unloading support
oop ClassLoaderData::keep_alive_object() const {
assert_locked_or_safepoint(_metaspace_lock);
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
@@ -546,6 +667,13 @@
_modules = NULL;
}
+ // Release C heap allocated hashtable for the dictionary
+ if (_dictionary != NULL) {
+ // Destroy the table itself
+ delete _dictionary;
+ _dictionary = NULL;
+ }
+
if (_unnamed_module != NULL) {
_unnamed_module->delete_unnamed_module();
_unnamed_module = NULL;
@@ -974,6 +1102,46 @@
}
}
+#define FOR_ALL_DICTIONARY(X) for (ClassLoaderData* X = _head; X != NULL; X = X->next()) \
+ if (X->dictionary() != NULL)
+
+// Walk classes in the loaded class dictionaries in various forms.
+// Only walks the classes defined in this class loader.
+void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*)) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->classes_do(f);
+ }
+}
+
+// Only walks the classes defined in this class loader.
+void ClassLoaderDataGraph::dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->classes_do(f, CHECK);
+ }
+}
+
+// Walks all entries in the dictionary including entries initiated by this class loader.
+void ClassLoaderDataGraph::dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->all_entries_do(f);
+ }
+}
+
+void ClassLoaderDataGraph::verify_dictionary() {
+ FOR_ALL_DICTIONARY(cld) {
+ cld->dictionary()->verify();
+ }
+}
+
+void ClassLoaderDataGraph::print_dictionary(bool details) {
+ FOR_ALL_DICTIONARY(cld) {
+ tty->print("Dictionary for class loader ");
+ cld->print_value();
+ tty->cr();
+ cld->dictionary()->print(details);
+ }
+}
+
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
@@ -1074,14 +1242,19 @@
}
if (seen_dead_loader) {
- // Walk a ModuleEntry's reads and a PackageEntry's exports lists
- // to determine if there are modules on those lists that are now
- // dead and should be removed. A module's life cycle is equivalent
- // to its defining class loader's life cycle. Since a module is
- // considered dead if its class loader is dead, these walks must
- // occur after each class loader's aliveness is determined.
data = _head;
while (data != NULL) {
+ // Remove entries in the dictionary of live class loader that have
+ // initiated loading classes in a dead class loader.
+ if (data->dictionary() != NULL) {
+ data->dictionary()->do_unloading();
+ }
+ // Walk a ModuleEntry's reads, and a PackageEntry's exports
+ // lists to determine if there are modules on those lists that are now
+ // dead and should be removed. A module's life cycle is equivalent
+ // to its defining class loader's life cycle. Since a module is
+ // considered dead if its class loader is dead, these walks must
+ // occur after each class loader's aliveness is determined.
if (data->packages() != NULL) {
data->packages()->purge_all_package_exports();
}
@@ -1253,6 +1426,15 @@
}
}
+void ClassLoaderData::print_on(outputStream* out) const {
+ if (class_loader() == NULL) {
+ out->print("NULL class_loader");
+ } else {
+ out->print("class loader " INTPTR_FORMAT " ", p2i(this));
+ class_loader()->print_on(out);
+ }
+}
+
#if INCLUDE_TRACE
Ticks ClassLoaderDataGraph::_class_unload_time;
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -46,9 +46,8 @@
// used by the dynamic linker to allocate the runtime representation of all
// the types it defines.
//
-// ClassLoaderData are stored in the runtime representation of classes and the
-// system dictionary, are roots of garbage collection, and provides iterators
-// for root tracing and other GC operations.
+// ClassLoaderData are stored in the runtime representation of classes,
+// and provides iterators for root tracing and other GC operations.
class ClassLoaderData;
class JNIMethodBlock;
@@ -57,6 +56,8 @@
class PackageEntry;
class ModuleEntryTable;
class PackageEntryTable;
+class DictionaryEntry;
+class Dictionary;
// GC root for walking class loader data created
@@ -64,6 +65,7 @@
friend class ClassLoaderData;
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class ClassLoaderDataGraphKlassIteratorAtomic;
+ friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class VMStructs;
private:
// All CLDs (except the null CLD) can be reached by walking _head->_next->...
@@ -109,6 +111,22 @@
static void classes_unloading_do(void f(Klass* const));
static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
+ // dictionary do
+ // Iterate over all klasses in dictionary, but
+ // just the classes from defining class loaders.
+ static void dictionary_classes_do(void f(InstanceKlass*));
+ // Added for initialize_itable_for_klass to handle exceptions.
+ static void dictionary_classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
+
+ // Iterate all classes and their class loaders, including initiating class loaders.
+ static void dictionary_all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
+
+ // VM_CounterDecay iteration support
+ static InstanceKlass* try_get_next_class();
+
+ static void verify_dictionary();
+ static void print_dictionary(bool details);
+
// CMS support.
static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
static GrowableArray<ClassLoaderData*>* new_clds();
@@ -193,6 +211,7 @@
friend class ClassLoaderDataGraph;
friend class ClassLoaderDataGraphKlassIteratorAtomic;
+ friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class ClassLoaderDataGraphMetaspaceIterator;
friend class MetaDataFactory;
friend class Method;
@@ -221,8 +240,9 @@
Klass* volatile _klasses; // The classes defined by the class loader.
PackageEntryTable* volatile _packages; // The packages defined by the class loader.
+ ModuleEntryTable* volatile _modules; // The modules defined by the class loader.
ModuleEntry* _unnamed_module; // This class loader's unnamed module.
- ModuleEntryTable* volatile _modules; // The modules defined by the class loader.
+ Dictionary* _dictionary; // The loaded InstanceKlasses, including initiated by this class loader
// These method IDs are created for the class loader and set to NULL when the
// class loader is unloaded. They are rarely freed, only for redefine classes
@@ -269,6 +289,7 @@
// Allocate out of this class loader data
MetaWord* allocate(size_t size);
+ Dictionary* create_dictionary();
public:
bool is_alive(BoolObjectClosure* is_alive_closure) const;
@@ -324,17 +345,20 @@
void inc_keep_alive();
void dec_keep_alive();
- inline unsigned int identity_hash() const;
+ inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); }
// Used when tracing from klasses.
void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
void classes_do(KlassClosure* klass_closure);
+ Klass* klasses() { return _klasses; }
JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; }
void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; }
- void print_value() { print_value_on(tty); }
+ void print() { print_on(tty); }
+ void print_on(outputStream* out) const;
+ void print_value() { print_value_on(tty); }
void print_value_on(outputStream* out) const;
void dump(outputStream * const out) PRODUCT_RETURN;
void verify();
@@ -352,6 +376,9 @@
ModuleEntryTable* modules();
bool modules_defined() { return (_modules != NULL); }
+ // Loaded class dictionary
+ Dictionary* dictionary() const { return _dictionary; }
+
void add_to_deallocate_list(Metadata* m);
static ClassLoaderData* class_loader_data(oop loader);
--- a/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.inline.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -26,10 +26,6 @@
#include "classfile/javaClasses.hpp"
#include "oops/oop.inline.hpp"
-unsigned int ClassLoaderData::identity_hash() const {
- return _class_loader == NULL ? 0 : _class_loader->identity_hash();
-}
-
inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
if (loader == NULL) {
return ClassLoaderData::the_null_class_loader_data();
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -34,12 +34,10 @@
#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "utilities/hashtable.inline.hpp"
-DictionaryEntry* Dictionary::_current_class_entry = NULL;
-int Dictionary::_current_class_index = 0;
-
size_t Dictionary::entry_size() {
if (DumpSharedSpaces) {
return SystemDictionaryShared::dictionary_entry_size();
@@ -48,30 +46,33 @@
}
}
-Dictionary::Dictionary(int table_size)
- : TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
- _current_class_index = 0;
- _current_class_entry = NULL;
- _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
+Dictionary::Dictionary(ClassLoaderData* loader_data, int table_size)
+ : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
};
-Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
+Dictionary::Dictionary(ClassLoaderData* loader_data,
+ int table_size, HashtableBucket<mtClass>* t,
int number_of_entries)
- : TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
- _current_class_index = 0;
- _current_class_entry = NULL;
- _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
+ : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
};
-ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) {
- return _pd_cache_table->get(protection_domain);
+Dictionary::~Dictionary() {
+ DictionaryEntry* probe = NULL;
+ for (int index = 0; index < table_size(); index++) {
+ for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
+ probe = *p;
+ *p = probe->next();
+ free_entry(probe);
+ }
+ }
+ assert(number_of_entries() == 0, "should have removed all entries");
+ assert(new_entry_free_list() == NULL, "entry present on Dictionary's free list");
+ free_buckets();
}
-DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass,
- ClassLoaderData* loader_data) {
- DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
- entry->set_loader_data(loader_data);
+DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) {
+ DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::allocate_new_entry(hash, klass);
entry->set_pd_set(NULL);
assert(klass->is_instance_klass(), "Must be");
if (DumpSharedSpaces) {
@@ -88,13 +89,15 @@
entry->set_pd_set(to_delete->next());
delete to_delete;
}
- Hashtable<InstanceKlass*, mtClass>::free_entry(entry);
+ // Unlink from the Hashtable prior to freeing
+ unlink_entry(entry);
+ FREE_C_HEAP_ARRAY(char, entry);
}
bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
#ifdef ASSERT
- if (protection_domain == klass()->protection_domain()) {
+ if (protection_domain == instance_klass()->protection_domain()) {
// Ensure this doesn't show up in the pd_set (invariant)
bool in_pd_set = false;
for (ProtectionDomainEntry* current = _pd_set;
@@ -112,7 +115,7 @@
}
#endif /* ASSERT */
- if (protection_domain == klass()->protection_domain()) {
+ if (protection_domain == instance_klass()->protection_domain()) {
// Succeeds trivially
return true;
}
@@ -129,7 +132,7 @@
void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
assert_locked_or_safepoint(SystemDictionary_lock);
if (!contains_protection_domain(protection_domain())) {
- ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
+ ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
ProtectionDomainEntry* new_head =
new ProtectionDomainEntry(entry, _pd_set);
// Warning: Preserve store ordering. The SystemDictionary is read
@@ -149,86 +152,43 @@
void Dictionary::do_unloading() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- // Remove unloadable entries and classes from system dictionary
+ // The NULL class loader doesn't initiate loading classes from other class loaders
+ if (loader_data() == ClassLoaderData::the_null_class_loader_data()) {
+ return;
+ }
+
+ // Remove unloaded entries and classes from this dictionary
DictionaryEntry* probe = NULL;
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
probe = *p;
- Klass* e = probe->klass();
- ClassLoaderData* loader_data = probe->loader_data();
-
- InstanceKlass* ik = InstanceKlass::cast(e);
-
- // Only unload classes that are not strongly reachable
- if (!is_strongly_reachable(loader_data, e)) {
- // Entry was not visited in phase1 (negated test from phase1)
- assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
- ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
-
- // Do we need to delete this system dictionary entry?
- bool purge_entry = false;
+ InstanceKlass* ik = probe->instance_klass();
+ ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
- // Do we need to delete this system dictionary entry?
- if (loader_data->is_unloading()) {
- // If the loader is not live this entry should always be
- // removed (will never be looked up again).
- purge_entry = true;
- } else {
- // The loader in this entry is alive. If the klass is dead,
- // (determined by checking the defining class loader)
- // the loader must be an initiating loader (rather than the
- // defining loader). Remove this entry.
- if (k_def_class_loader_data->is_unloading()) {
- // If we get here, the class_loader_data must not be the defining
- // loader, it must be an initiating one.
- assert(k_def_class_loader_data != loader_data,
- "cannot have live defining loader and unreachable klass");
- // Loader is live, but class and its defining loader are dead.
- // Remove the entry. The class is going away.
- purge_entry = true;
- }
- }
-
- if (purge_entry) {
- *p = probe->next();
- if (probe == _current_class_entry) {
- _current_class_entry = NULL;
- }
- free_entry(probe);
- continue;
- }
+ // If the klass that this loader initiated is dead,
+ // (determined by checking the defining class loader)
+ // remove this entry.
+ if (k_def_class_loader_data->is_unloading()) {
+ assert(k_def_class_loader_data != loader_data(),
+ "cannot have live defining loader and unreachable klass");
+ *p = probe->next();
+ free_entry(probe);
+ continue;
}
p = probe->next_addr();
}
}
}
-void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
- // Do strong roots marking if the closures are the same.
- if (strong == weak || !ClassUnloading) {
- // Only the protection domain oops contain references into the heap. Iterate
- // over all of them.
- _pd_cache_table->oops_do(strong);
- } else {
- if (weak != NULL) {
- _pd_cache_table->oops_do(weak);
- }
- }
-}
-
-
void Dictionary::remove_classes_in_error_state() {
assert(DumpSharedSpaces, "supported only when dumping");
DictionaryEntry* probe = NULL;
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
probe = *p;
- InstanceKlass* ik = InstanceKlass::cast(probe->klass());
+ InstanceKlass* ik = probe->instance_klass();
if (ik->is_in_error_state()) { // purge this entry
*p = probe->next();
- if (probe == _current_class_entry) {
- _current_class_entry = NULL;
- }
free_entry(probe);
ResourceMark rm;
tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
@@ -241,13 +201,13 @@
}
// Just the classes from defining class loaders
-void Dictionary::classes_do(void f(Klass*)) {
+void Dictionary::classes_do(void f(InstanceKlass*)) {
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
- Klass* k = probe->klass();
- if (probe->loader_data() == k->class_loader_data()) {
+ InstanceKlass* k = probe->instance_klass();
+ if (loader_data() == k->class_loader_data()) {
f(k);
}
}
@@ -256,78 +216,50 @@
// Added for initialize_itable_for_klass to handle exceptions
// Just the classes from defining class loaders
-void Dictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
+void Dictionary::classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
- Klass* k = probe->klass();
- if (probe->loader_data() == k->class_loader_data()) {
+ InstanceKlass* k = probe->instance_klass();
+ if (loader_data() == k->class_loader_data()) {
f(k, CHECK);
}
}
}
}
-// All classes, and their class loaders
-// Don't iterate over placeholders
-void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
+// All classes, and their class loaders, including initiating class loaders
+void Dictionary::all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
for (int index = 0; index < table_size(); index++) {
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
- Klass* k = probe->klass();
- f(k, probe->loader_data());
+ InstanceKlass* k = probe->instance_klass();
+ f(k, loader_data());
}
}
}
-void Dictionary::oops_do(OopClosure* f) {
- // Only the protection domain oops contain references into the heap. Iterate
- // over all of them.
- _pd_cache_table->oops_do(f);
-}
-void Dictionary::unlink(BoolObjectClosure* is_alive) {
- // Only the protection domain cache table may contain references to the heap
- // that need to be unlinked.
- _pd_cache_table->unlink(is_alive);
-}
-
-InstanceKlass* Dictionary::try_get_next_class() {
- while (true) {
- if (_current_class_entry != NULL) {
- InstanceKlass* k = _current_class_entry->klass();
- _current_class_entry = _current_class_entry->next();
- return k;
- }
- _current_class_index = (_current_class_index + 1) % table_size();
- _current_class_entry = bucket(_current_class_index);
- }
- // never reached
-}
-
-// Add a loaded class to the system dictionary.
+// Add a loaded class to the dictionary.
// Readers of the SystemDictionary aren't always locked, so _buckets
// is volatile. The store of the next field in the constructor is
// also cast to volatile; we do this to ensure store order is maintained
// by the compilers.
-void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
+void Dictionary::add_klass(int index, unsigned int hash, Symbol* class_name,
InstanceKlass* obj) {
assert_locked_or_safepoint(SystemDictionary_lock);
assert(obj != NULL, "adding NULL obj");
assert(obj->name() == class_name, "sanity check on name");
- assert(loader_data != NULL, "Must be non-NULL");
- unsigned int hash = compute_hash(class_name, loader_data);
- int index = hash_to_index(hash);
- DictionaryEntry* entry = new_entry(hash, obj, loader_data);
+ DictionaryEntry* entry = new_entry(hash, obj);
add_entry(index, entry);
}
-// This routine does not lock the system dictionary.
+// This routine does not lock the dictionary.
//
// Since readers don't hold a lock, we must make sure that system
// dictionary entries are only removed at a safepoint (when only one
@@ -337,13 +269,14 @@
// Callers should be aware that an entry could be added just after
// _buckets[index] is read here, so the caller will not see the new entry.
DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
- Symbol* class_name,
- ClassLoaderData* loader_data) {
+ Symbol* class_name) {
for (DictionaryEntry* entry = bucket(index);
entry != NULL;
entry = entry->next()) {
- if (entry->hash() == hash && entry->equals(class_name, loader_data)) {
- return entry;
+ if (entry->hash() == hash && entry->equals(class_name)) {
+ if (!DumpSharedSpaces || SystemDictionaryShared::is_builtin(entry)) {
+ return entry;
+ }
}
}
return NULL;
@@ -351,10 +284,10 @@
InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name,
- ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
- DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
+ Handle protection_domain) {
+ DictionaryEntry* entry = get_entry(index, hash, name);
if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
- return entry->klass();
+ return entry->instance_klass();
} else {
return NULL;
}
@@ -362,12 +295,12 @@
InstanceKlass* Dictionary::find_class(int index, unsigned int hash,
- Symbol* name, ClassLoaderData* loader_data) {
+ Symbol* name) {
assert_locked_or_safepoint(SystemDictionary_lock);
- assert (index == index_for(name, loader_data), "incorrect index?");
+ assert (index == index_for(name), "incorrect index?");
- DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
- return (entry != NULL) ? entry->klass() : NULL;
+ DictionaryEntry* entry = get_entry(index, hash, name);
+ return (entry != NULL) ? entry->instance_klass() : NULL;
}
@@ -376,19 +309,19 @@
InstanceKlass* Dictionary::find_shared_class(int index, unsigned int hash,
Symbol* name) {
- assert (index == index_for(name, NULL), "incorrect index?");
+ assert (index == index_for(name), "incorrect index?");
- DictionaryEntry* entry = get_entry(index, hash, name, NULL);
- return (entry != NULL) ? entry->klass() : NULL;
+ DictionaryEntry* entry = get_entry(index, hash, name);
+ return (entry != NULL) ? entry->instance_klass() : NULL;
}
void Dictionary::add_protection_domain(int index, unsigned int hash,
InstanceKlass* klass,
- ClassLoaderData* loader_data, Handle protection_domain,
+ Handle protection_domain,
TRAPS) {
Symbol* klass_name = klass->name();
- DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data);
+ DictionaryEntry* entry = get_entry(index, hash, klass_name);
assert(entry != NULL,"entry must be present, we just created it");
assert(protection_domain() != NULL,
@@ -403,9 +336,8 @@
bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
Symbol* name,
- ClassLoaderData* loader_data,
Handle protection_domain) {
- DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
+ DictionaryEntry* entry = get_entry(index, hash, name);
return entry->is_valid_protection_domain(protection_domain);
}
@@ -432,13 +364,12 @@
DictionaryEntry* p = master_list;
master_list = master_list->next();
p->set_next(NULL);
- Symbol* class_name = p->klass()->name();
+ Symbol* class_name = p->instance_klass()->name();
// Since the null class loader data isn't copied to the CDS archive,
// compute the hash with NULL for loader data.
- unsigned int hash = compute_hash(class_name, NULL);
+ unsigned int hash = compute_hash(class_name);
int index = hash_to_index(hash);
p->set_hash(hash);
- p->set_loader_data(NULL); // loader_data isn't copied to CDS
p->set_next(bucket(index));
set_entry(index, p);
}
@@ -507,8 +438,9 @@
void Dictionary::print(bool details) {
ResourceMark rm;
+ assert(loader_data() != NULL, "loader data should not be null");
if (details) {
- tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
+ tty->print_cr("Java dictionary (table_size=%d, classes=%d)",
table_size(), number_of_entries());
tty->print_cr("^ indicates that initiating loader is different from "
"defining loader");
@@ -518,10 +450,9 @@
for (DictionaryEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
- Klass* e = probe->klass();
- ClassLoaderData* loader_data = probe->loader_data();
+ Klass* e = probe->instance_klass();
bool is_defining_class =
- (loader_data == e->class_loader_data());
+ (loader_data() == e->class_loader_data());
if (details) {
tty->print("%4d: ", index);
}
@@ -530,41 +461,36 @@
if (details) {
tty->print(", loader ");
- if (loader_data != NULL) {
- loader_data->print_value();
- } else {
- tty->print("NULL");
- }
+ e->class_loader_data()->print_value();
}
tty->cr();
}
}
-
- if (details) {
- tty->cr();
- _pd_cache_table->print();
- }
tty->cr();
}
void DictionaryEntry::verify() {
- Klass* e = klass();
+ Klass* e = instance_klass();
+ guarantee(e->is_instance_klass(),
+ "Verify of dictionary failed");
+ e->verify();
+ verify_protection_domain_set();
+}
+
+void Dictionary::verify() {
+ guarantee(number_of_entries() >= 0, "Verify of dictionary failed");
+
ClassLoaderData* cld = loader_data();
- guarantee(e->is_instance_klass(),
- "Verify of system dictionary failed");
// class loader must be present; a null class loader is the
// boostrap loader
guarantee(cld != NULL || DumpSharedSpaces ||
cld->class_loader() == NULL ||
cld->class_loader()->is_instance(),
"checking type of class_loader");
- e->verify();
- verify_protection_domain_set();
+
+ ResourceMark rm;
+ stringStream tempst;
+ tempst.print("System Dictionary for %s", cld->loader_name());
+ verify_table<DictionaryEntry>(tempst.as_string());
}
-void Dictionary::verify() {
- guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
- verify_table<DictionaryEntry>("System Dictionary");
- _pd_cache_table->verify();
-}
-
--- a/hotspot/src/share/vm/classfile/dictionary.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -36,21 +36,16 @@
class BoolObjectClosure;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// The data structure for the system dictionary (and the shared system
+// The data structure for the class loader data dictionaries (and the shared system
// dictionary).
-class Dictionary : public TwoOopHashtable<InstanceKlass*, mtClass> {
+class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
friend class VMStructs;
-private:
- // current iteration index.
- static int _current_class_index;
- // pointer to the current hash table entry.
- static DictionaryEntry* _current_class_entry;
- ProtectionDomainCacheTable* _pd_cache_table;
+ ClassLoaderData* _loader_data; // backpointer to owning loader
+ ClassLoaderData* loader_data() const { return _loader_data; }
- DictionaryEntry* get_entry(int index, unsigned int hash,
- Symbol* name, ClassLoaderData* loader_data);
+ DictionaryEntry* get_entry(int index, unsigned int hash, Symbol* name);
protected:
DictionaryEntry* bucket(int i) const {
@@ -66,61 +61,48 @@
Hashtable<InstanceKlass*, mtClass>::add_entry(index, (HashtableEntry<InstanceKlass*, mtClass>*)new_entry);
}
- static size_t entry_size();
-public:
- Dictionary(int table_size);
- Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
-
- DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass, ClassLoaderData* loader_data);
-
void free_entry(DictionaryEntry* entry);
- void add_klass(Symbol* class_name, ClassLoaderData* loader_data, InstanceKlass* obj);
+ static size_t entry_size();
+public:
+ Dictionary(ClassLoaderData* loader_data, int table_size);
+ Dictionary(ClassLoaderData* loader_data, int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
+ ~Dictionary();
- InstanceKlass* find_class(int index, unsigned int hash,
- Symbol* name, ClassLoaderData* loader_data);
+ DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass);
+
+ void add_klass(int index, unsigned int hash, Symbol* class_name, InstanceKlass* obj);
+
+ InstanceKlass* find_class(int index, unsigned int hash, Symbol* name);
InstanceKlass* find_shared_class(int index, unsigned int hash, Symbol* name);
- // Compiler support
- InstanceKlass* try_get_next_class();
-
// GC support
void oops_do(OopClosure* f);
void roots_oops_do(OopClosure* strong, OopClosure* weak);
- void classes_do(void f(Klass*));
- void classes_do(void f(Klass*, TRAPS), TRAPS);
- void classes_do(void f(Klass*, ClassLoaderData*));
+ void classes_do(void f(InstanceKlass*));
+ void classes_do(void f(InstanceKlass*, TRAPS), TRAPS);
+ void all_entries_do(void f(InstanceKlass*, ClassLoaderData*));
void unlink(BoolObjectClosure* is_alive);
void remove_classes_in_error_state();
- // Classes loaded by the bootstrap loader are always strongly reachable.
- // If we're not doing class unloading, all classes are strongly reachable.
- static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) {
- assert (klass != NULL, "should have non-null klass");
- return (loader_data->is_the_null_class_loader_data() || !ClassUnloading);
- }
-
- // Unload (that is, break root links to) all unmarked classes and loaders.
+ // Unload classes whose defining loaders are unloaded
void do_unloading();
// Protection domains
- InstanceKlass* find(int index, unsigned int hash, Symbol* name,
- ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
+ InstanceKlass* find(int index, unsigned int hash, Symbol* name, Handle protection_domain);
bool is_valid_protection_domain(int index, unsigned int hash,
- Symbol* name, ClassLoaderData* loader_data,
+ Symbol* name,
Handle protection_domain);
void add_protection_domain(int index, unsigned int hash,
- InstanceKlass* klass, ClassLoaderData* loader_data,
+ InstanceKlass* klass,
Handle protection_domain, TRAPS);
// Sharing support
void reorder_dictionary();
- ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
-
void print(bool details = true);
#ifdef ASSERT
void printPerformanceInfoDetails();
@@ -128,14 +110,14 @@
void verify();
};
-// An entry in the system dictionary, this describes a class as
-// { InstanceKlass*, loader, protection_domain }.
+// An entry in the class loader data dictionaries, this describes a class as
+// { InstanceKlass*, protection_domain }.
class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
friend class VMStructs;
private:
// Contains the set of approved protection domains that can access
- // this system dictionary entry.
+ // this dictionary entry.
//
// This protection domain set is a set of tuples:
//
@@ -155,7 +137,6 @@
// ClassLoader.checkPackageAccess().
//
ProtectionDomainEntry* _pd_set;
- ClassLoaderData* _loader_data;
public:
// Tells whether a protection is in the approved set.
@@ -163,7 +144,7 @@
// Adds a protection domain to the approved set.
void add_protection_domain(Dictionary* dict, Handle protection_domain);
- InstanceKlass* klass() const { return (InstanceKlass*)literal(); }
+ InstanceKlass* instance_klass() const { return literal(); }
DictionaryEntry* next() const {
return (DictionaryEntry*)HashtableEntry<InstanceKlass*, mtClass>::next();
@@ -173,13 +154,10 @@
return (DictionaryEntry**)HashtableEntry<InstanceKlass*, mtClass>::next_addr();
}
- ClassLoaderData* loader_data() const { return _loader_data; }
- void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; }
-
ProtectionDomainEntry* pd_set() const { return _pd_set; }
void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; }
- // Tells whether the initiating class' protection can access the this _klass
+ // Tells whether the initiating class' protection domain can access the klass in this entry
bool is_valid_protection_domain(Handle protection_domain) {
if (!ProtectionDomainVerification) return true;
if (!SystemDictionary::has_checkPackageAccess()) return true;
@@ -197,9 +175,9 @@
}
}
- bool equals(const Symbol* class_name, ClassLoaderData* loader_data) const {
+ bool equals(const Symbol* class_name) const {
InstanceKlass* klass = (InstanceKlass*)literal();
- return (klass->name() == class_name && _loader_data == loader_data);
+ return (klass->name() == class_name);
}
void print_count(outputStream *st) {
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/dictionary.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/loaderConstraints.hpp"
#include "logging/log.hpp"
@@ -36,8 +37,8 @@
set_loader_data(i, ClassLoaderData::class_loader_data(p));
}
-LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
- : Hashtable<InstanceKlass*, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
+LoaderConstraintTable::LoaderConstraintTable(int table_size)
+ : Hashtable<InstanceKlass*, mtClass>(table_size, sizeof(LoaderConstraintEntry)) {};
LoaderConstraintEntry* LoaderConstraintTable::new_entry(
@@ -425,10 +426,9 @@
}
-void LoaderConstraintTable::verify(Dictionary* dictionary,
- PlaceholderTable* placeholders) {
+void LoaderConstraintTable::verify(PlaceholderTable* placeholders) {
Thread *thread = Thread::current();
- for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
+ for (int cindex = 0; cindex < table_size(); cindex++) {
for (LoaderConstraintEntry* probe = bucket(cindex);
probe != NULL;
probe = probe->next()) {
@@ -437,17 +437,18 @@
guarantee(ik->name() == probe->name(), "name should match");
Symbol* name = ik->name();
ClassLoaderData* loader_data = ik->class_loader_data();
- unsigned int d_hash = dictionary->compute_hash(name, loader_data);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name);
int d_index = dictionary->hash_to_index(d_hash);
- InstanceKlass* k = dictionary->find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* k = dictionary->find_class(d_index, d_hash, name);
if (k != NULL) {
- // We found the class in the system dictionary, so we should
+ // We found the class in the dictionary, so we should
// make sure that the Klass* matches what we already have.
guarantee(k == probe->klass(), "klass should be in dictionary");
} else {
- // If we don't find the class in the system dictionary, it
+ // If we don't find the class in the dictionary, it
// has to be in the placeholders table.
- unsigned int p_hash = placeholders->compute_hash(name, loader_data);
+ unsigned int p_hash = placeholders->compute_hash(name);
int p_index = placeholders->hash_to_index(p_hash);
PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
name, loader_data);
@@ -471,8 +472,9 @@
void LoaderConstraintTable::print() {
ResourceMark rm;
assert_locked_or_safepoint(SystemDictionary_lock);
- tty->print_cr("Java loader constraints (entries=%d)", _loader_constraint_size);
- for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
+ tty->print_cr("Java loader constraints (entries=%d, constraints=%d)",
+ table_size(), number_of_entries());
+ for (int cindex = 0; cindex < table_size(); cindex++) {
for (LoaderConstraintEntry* probe = bucket(cindex);
probe != NULL;
probe = probe->next()) {
--- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -25,28 +25,22 @@
#ifndef SHARE_VM_CLASSFILE_LOADERCONSTRAINTS_HPP
#define SHARE_VM_CLASSFILE_LOADERCONSTRAINTS_HPP
-#include "classfile/dictionary.hpp"
#include "classfile/placeholders.hpp"
#include "utilities/hashtable.hpp"
+class ClassLoaderData;
class LoaderConstraintEntry;
class Symbol;
class LoaderConstraintTable : public Hashtable<InstanceKlass*, mtClass> {
- friend class VMStructs;
+
private:
-
- enum Constants {
- _loader_constraint_size = 107, // number of entries in constraint table
- _nof_buckets = 1009 // number of buckets in hash table
- };
-
LoaderConstraintEntry** find_loader_constraint(Symbol* name,
Handle loader);
public:
- LoaderConstraintTable(int nof_buckets);
+ LoaderConstraintTable(int table_size);
LoaderConstraintEntry* new_entry(unsigned int hash, Symbol* name,
InstanceKlass* klass, int num_loaders,
@@ -84,14 +78,13 @@
void purge_loader_constraints();
- void verify(Dictionary* dictionary, PlaceholderTable* placeholders);
+ void verify(PlaceholderTable* placeholders);
#ifndef PRODUCT
void print();
#endif
};
class LoaderConstraintEntry : public HashtableEntry<InstanceKlass*, mtClass> {
- friend class VMStructs;
private:
Symbol* _name; // class name
int _num_loaders;
--- a/hotspot/src/share/vm/classfile/moduleEntry.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -339,12 +339,7 @@
Symbol* version, Symbol* location,
ClassLoaderData* loader_data) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
- ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule);
-
- // Initialize everything BasicHashtable would
- entry->set_next(NULL);
- entry->set_hash(hash);
- entry->set_literal(name);
+ ModuleEntry* entry = (ModuleEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
// Initialize fields specific to a ModuleEntry
entry->init();
--- a/hotspot/src/share/vm/classfile/packageEntry.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -198,12 +198,7 @@
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
- PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtModule);
-
- // Initialize everything BasicHashtable would
- entry->set_next(NULL);
- entry->set_hash(hash);
- entry->set_literal(name);
+ PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
TRACE_INIT_ID(entry);
--- a/hotspot/src/share/vm/classfile/placeholders.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/placeholders.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -172,7 +172,7 @@
}
PlaceholderTable::PlaceholderTable(int table_size)
- : TwoOopHashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
+ : Hashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
}
#ifndef PRODUCT
--- a/hotspot/src/share/vm/classfile/placeholders.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/placeholders.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -34,8 +34,7 @@
// being loaded, as well as arrays of primitives.
//
-class PlaceholderTable : public TwoOopHashtable<Symbol*, mtClass> {
- friend class VMStructs;
+class PlaceholderTable : public Hashtable<Symbol*, mtClass> {
public:
PlaceholderTable(int table_size);
@@ -149,8 +148,6 @@
// The system dictionary is the only user of this class.
class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {
- friend class VMStructs;
-
private:
ClassLoaderData* _loader_data; // initiating loader
--- a/hotspot/src/share/vm/classfile/protectionDomainCache.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/protectionDomainCache.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -88,14 +88,14 @@
for (ProtectionDomainCacheEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
+ tty->print("%4d: ", index);
probe->print();
}
}
}
void ProtectionDomainCacheEntry::print() {
- tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " next " PTR_FORMAT,
- p2i(this), p2i(literal()), p2i(next()));
+ tty->print_cr("protection_domain: " PTR_FORMAT, p2i(literal()));
}
#endif
--- a/hotspot/src/share/vm/classfile/protectionDomainCache.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/protectionDomainCache.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -33,7 +33,7 @@
// Dictionary entry pd_set point to entries in this hashtable. Please refer
// to dictionary.hpp pd_set for more information about how protection domain entries
// are used.
-// This table is walked during GC, rather than the entire system dictionary
+// This table is walked during GC, rather than the class loader data graph dictionaries.
class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
friend class VMStructs;
public:
@@ -55,7 +55,7 @@
void verify();
};
-// The ProtectionDomainCacheTable contains all protection domain oops. The system
+// The ProtectionDomainCacheTable contains all protection domain oops. The
// dictionary entries reference its entries instead of having references to oops
// directly.
// This is used to speed up system dictionary iteration: the oops in the
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -35,6 +35,7 @@
#include "classfile/loaderConstraints.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/placeholders.hpp"
+#include "classfile/protectionDomainCache.hpp"
#include "classfile/resolutionErrors.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -88,19 +89,14 @@
#include "trace/tracing.hpp"
#endif
-Dictionary* SystemDictionary::_dictionary = NULL;
PlaceholderTable* SystemDictionary::_placeholders = NULL;
Dictionary* SystemDictionary::_shared_dictionary = NULL;
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
-
+ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL;
int SystemDictionary::_number_of_modifications = 0;
-int SystemDictionary::_sdgeneration = 0;
-const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,5051,10103,
- 20201,40423,99991};
-
oop SystemDictionary::_system_loader_lock_obj = NULL;
InstanceKlass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
@@ -116,6 +112,10 @@
// lazily initialized klass variables
InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
+// Default ProtectionDomainCacheSize value
+
+const int defaultProtectionDomainCacheSize = 1009;
+
// ----------------------------------------------------------------------------
// Java-level SystemLoader
@@ -343,32 +343,32 @@
#endif // INCLUDE_CDS
// Double-check, if child class is already loaded, just return super-class,interface
- // Don't add a placedholder if already loaded, i.e. already in system dictionary
+ // Don't add a placedholder if already loaded, i.e. already in appropriate class loader
+ // dictionary.
// Make sure there's a placeholder for the *child* before resolving.
// Used as a claim that this thread is currently loading superclass/classloader
// Used here for ClassCircularity checks and also for heap verification
- // (every InstanceKlass in the heap needs to be in the system dictionary
- // or have a placeholder).
- // Must check ClassCircularity before checking if super class is already loaded
+ // (every InstanceKlass needs to be in its class loader dictionary or have a placeholder).
+ // Must check ClassCircularity before checking if super class is already loaded.
//
// We might not already have a placeholder if this child_name was
// first seen via resolve_from_stream (jni_DefineClass or JVM_DefineClass);
// the name of the class might not be known until the stream is actually
// parsed.
// Bugs 4643874, 4715493
- // compute_hash can have a safepoint
ClassLoaderData* loader_data = class_loader_data(class_loader);
- unsigned int d_hash = dictionary()->compute_hash(child_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- unsigned int p_hash = placeholders()->compute_hash(child_name, loader_data);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(child_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ unsigned int p_hash = placeholders()->compute_hash(child_name);
int p_index = placeholders()->hash_to_index(p_hash);
// can't throw error holding a lock
bool child_already_loaded = false;
bool throw_circularity_error = false;
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- Klass* childk = find_class(d_index, d_hash, child_name, loader_data);
+ Klass* childk = find_class(d_index, d_hash, child_name, dictionary);
Klass* quicksuperk;
// to support // loading: if child done loading, just return superclass
// if class_name, & class_loader don't match:
@@ -445,13 +445,18 @@
ls.cr();
}
+ // This handle and the class_loader handle passed in keeps this class from
+ // being unloaded through several GC points.
+ // The class_loader handle passed in is the initiating loader.
+ Handle mirror(THREAD, klass->java_mirror());
+
InstanceKlass* system_loader = SystemDictionary::ClassLoader_klass();
JavaCalls::call_special(&result,
class_loader,
system_loader,
vmSymbols::checkPackageAccess_name(),
vmSymbols::class_protectiondomain_signature(),
- Handle(THREAD, klass->java_mirror()),
+ mirror,
protection_domain,
THREAD);
@@ -466,27 +471,16 @@
// If no exception has been thrown, we have validated the protection domain
// Insert the protection domain of the initiating class into the set.
{
- // We recalculate the entry here -- we've called out to java since
- // the last time it was calculated.
ClassLoaderData* loader_data = class_loader_data(class_loader);
+ Dictionary* dictionary = loader_data->dictionary();
Symbol* kn = klass->name();
- unsigned int d_hash = dictionary()->compute_hash(kn, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ unsigned int d_hash = dictionary->compute_hash(kn);
+ int d_index = dictionary->hash_to_index(d_hash);
MutexLocker mu(SystemDictionary_lock, THREAD);
- {
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
-
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- dictionary()->add_protection_domain(d_index, d_hash, klass, loader_data,
- protection_domain, THREAD);
- }
+ dictionary->add_protection_domain(d_index, d_hash, klass,
+ protection_domain, THREAD);
}
}
@@ -548,9 +542,10 @@
Handle protection_domain, Handle lockObject, TRAPS) {
ClassLoaderData* loader_data = class_loader_data(class_loader);
- unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ unsigned int p_hash = placeholders()->compute_hash(name);
int p_index = placeholders()->hash_to_index(p_hash);
// superk is not used, resolve_super called for circularity check only
@@ -573,7 +568,7 @@
if (!class_loader.is_null() && is_parallelCapable(class_loader)) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- return find_class(d_index, d_hash, name, loader_data);
+ return find_class(d_index, d_hash, name, dictionary);
}
// must loop to both handle other placeholder updates
@@ -583,7 +578,7 @@
while (super_load_in_progress) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
return check;
@@ -663,6 +658,7 @@
// Fix for 4474172; see evaluation for more details
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
+ Dictionary* dictionary = loader_data->dictionary();
// Do lookup to see if class already exist and the protection domain
// has the right access
@@ -670,10 +666,9 @@
// All subsequent calls use find_class, and set has_loaded_class so that
// before we return a result we call out to java to check for valid protection domain
// to allow returning the Klass* and add it to the pd_set if it is valid
- unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- Klass* probe = dictionary()->find(d_index, d_hash, name, loader_data,
- protection_domain, THREAD);
+ unsigned int d_hash = dictionary->compute_hash(name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ Klass* probe = dictionary->find(d_index, d_hash, name, protection_domain);
if (probe != NULL) return probe;
@@ -691,7 +686,7 @@
DoObjectLock = false;
}
- unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name);
int p_index = placeholders()->hash_to_index(p_hash);
// Class is not in SystemDictionary so we have to do loading.
@@ -710,7 +705,7 @@
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
class_has_been_loaded = true;
@@ -794,7 +789,7 @@
double_lock_wait(lockObject, THREAD);
}
// Check if classloading completed while we were waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
k = check;
@@ -819,7 +814,7 @@
// i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL
// one final check if the load has already completed
// class loaders holding the ObjectLock shouldn't find the class here
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so return it after checking/adding protection domain
k = check;
@@ -852,7 +847,7 @@
if (k == NULL && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just use it
k = check;
@@ -886,7 +881,7 @@
}
}
}
- } // load_instance_class loop
+ } // load_instance_class
if (load_instance_added == true) {
// clean up placeholder entries for LOAD_INSTANCE success or error
@@ -919,16 +914,8 @@
// Check the protection domain has the right access
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- if (dictionary()->is_valid_protection_domain(d_index, d_hash, name,
- loader_data,
- protection_domain)) {
+ if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
+ protection_domain)) {
return k;
}
}
@@ -968,20 +955,11 @@
return NULL;
}
- unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
-
- {
- // Note that we have an entry, and entries can be deleted only during GC,
- // so we cannot allow GC to occur while we're holding this entry.
- // We're using a NoSafepointVerifier to catch any place where we
- // might potentially do a GC at all.
- // Dictionary::do_unloading() asserts that classes in SD are only
- // unloaded at a safepoint. Anonymous classes are not in SD.
- NoSafepointVerifier nosafepoint;
- return dictionary()->find(d_index, d_hash, class_name, loader_data,
- protection_domain, THREAD);
- }
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(class_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ return dictionary->find(d_index, d_hash, class_name,
+ protection_domain);
}
@@ -1035,7 +1013,6 @@
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
- loader_data->record_dependency(host_klass, CHECK_NULL);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
}
@@ -1066,7 +1043,7 @@
// deoptimizations.
add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
- // But, do not add to system dictionary.
+ // But, do not add to dictionary.
// compiled code dependencies need to be validated anyway
notice_modification();
@@ -1189,9 +1166,10 @@
#if INCLUDE_CDS
void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
int number_of_entries) {
- assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
+ assert(length == _shared_dictionary_size * sizeof(HashtableBucket<mtClass>),
"bad shared dictionary size.");
- _shared_dictionary = new Dictionary(_nof_buckets, t, number_of_entries);
+ _shared_dictionary = new Dictionary(ClassLoaderData::the_null_class_loader_data(),
+ _shared_dictionary_size, t, number_of_entries);
}
@@ -1200,7 +1178,7 @@
InstanceKlass* SystemDictionary::find_shared_class(Symbol* class_name) {
if (shared_dictionary() != NULL) {
- unsigned int d_hash = shared_dictionary()->compute_hash(class_name, NULL);
+ unsigned int d_hash = shared_dictionary()->compute_hash(class_name);
int d_index = shared_dictionary()->hash_to_index(d_hash);
return shared_dictionary()->find_shared_class(d_index, d_hash, class_name);
@@ -1626,8 +1604,9 @@
// Parallel classloaders will call find_or_define_instance_class
// which will require a token to perform the define class
Symbol* name_h = k->name();
- unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name_h);
+ int d_index = dictionary->hash_to_index(d_hash);
check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
// Register class just loaded with class loader (placed in Vector)
@@ -1645,7 +1624,7 @@
// Add the new class. We need recompile lock during update of CHA.
{
- unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name_h);
int p_index = placeholders()->hash_to_index(p_hash);
MutexLocker mu_r(Compile_lock, THREAD);
@@ -1695,12 +1674,13 @@
Symbol* name_h = k->name(); // passed in class_name may be null
ClassLoaderData* loader_data = class_loader_data(class_loader);
+ Dictionary* dictionary = loader_data->dictionary();
- unsigned int d_hash = dictionary()->compute_hash(name_h, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
+ unsigned int d_hash = dictionary->compute_hash(name_h);
+ int d_index = dictionary->hash_to_index(d_hash);
// Hold SD lock around find_class and placeholder creation for DEFINE_CLASS
- unsigned int p_hash = placeholders()->compute_hash(name_h, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(name_h);
int p_index = placeholders()->hash_to_index(p_hash);
PlaceholderEntry* probe;
@@ -1708,7 +1688,7 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
// First check if class already defined
if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
- InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
if (check != NULL) {
return check;
}
@@ -1730,7 +1710,7 @@
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
SystemDictionary_lock->notify_all();
#ifdef ASSERT
- InstanceKlass* check = find_class(d_index, d_hash, name_h, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
assert(check != NULL, "definer missed recording success");
#endif
return probe->instance_klass();
@@ -1769,6 +1749,7 @@
return k;
}
+
Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) {
// If class_loader is NULL we synchronize on _system_loader_lock_obj
if (class_loader.is_null()) {
@@ -1806,12 +1787,9 @@
InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash,
Symbol* class_name,
- ClassLoaderData* loader_data) {
+ Dictionary* dictionary) {
assert_locked_or_safepoint(SystemDictionary_lock);
- assert (index == dictionary()->index_for(class_name, loader_data),
- "incorrect index?");
-
- return dictionary()->find_class(index, hash, class_name, loader_data);
+ return dictionary->find_class(index, hash, class_name);
}
@@ -1819,14 +1797,17 @@
Symbol* SystemDictionary::find_placeholder(Symbol* class_name,
ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock);
- unsigned int p_hash = placeholders()->compute_hash(class_name, loader_data);
+ unsigned int p_hash = placeholders()->compute_hash(class_name);
int p_index = placeholders()->hash_to_index(p_hash);
return placeholders()->find_entry(p_index, p_hash, class_name, loader_data);
}
// Used for assertions and verification only
+// Precalculating the hash and index is an optimization because there are many lookups
+// before adding the class.
InstanceKlass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_data) {
+ assert_locked_or_safepoint(SystemDictionary_lock);
#ifndef ASSERT
guarantee(VerifyBeforeGC ||
VerifyDuringGC ||
@@ -1834,18 +1815,11 @@
VerifyDuringStartup ||
VerifyAfterGC, "too expensive");
#endif
- assert_locked_or_safepoint(SystemDictionary_lock);
- // First look in the loaded class array
- unsigned int d_hash = dictionary()->compute_hash(class_name, loader_data);
- int d_index = dictionary()->hash_to_index(d_hash);
- return find_class(d_index, d_hash, class_name, loader_data);
-}
-
-
-// Get the next class in the dictionary.
-Klass* SystemDictionary::try_get_next_class() {
- return dictionary()->try_get_next_class();
+ Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(class_name);
+ int d_index = dictionary->hash_to_index(d_hash);
+ return find_class(d_index, d_hash, class_name, dictionary);
}
@@ -1872,33 +1846,10 @@
// ----------------------------------------------------------------------------
// GC support
-// Following roots during mark-sweep is separated in two phases.
-//
-// The first phase follows preloaded classes and all other system
-// classes, since these will never get unloaded anyway.
-//
-// The second phase removes (unloads) unreachable classes from the
-// system dictionary and follows the remaining classes' contents.
-
void SystemDictionary::always_strong_oops_do(OopClosure* blk) {
roots_oops_do(blk, NULL);
}
-// Calculate a "good" systemdictionary size based
-// on predicted or current loaded classes count
-int SystemDictionary::calculate_systemdictionary_size(int classcount) {
- int newsize = _old_default_sdsize;
- if ((classcount > 0) && !DumpSharedSpaces) {
- int desiredsize = classcount/_average_depth_goal;
- for (newsize = _primelist[_sdgeneration]; _sdgeneration < _prime_array_size -1;
- newsize = _primelist[++_sdgeneration]) {
- if (desiredsize <= newsize) {
- break;
- }
- }
- }
- return newsize;
-}
#ifdef ASSERT
class VerifySDReachableAndLiveClosure : public OopClosure {
@@ -1907,7 +1858,7 @@
template <class T> void do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
- guarantee(_is_alive->do_object_b(obj), "Oop in system dictionary must be live");
+ guarantee(_is_alive->do_object_b(obj), "Oop in protection domain cache table must be live");
}
public:
@@ -1936,20 +1887,20 @@
if (unloading_occurred) {
GCTraceTime(Debug, gc, phases) t("Dictionary", gc_timer);
- dictionary()->do_unloading();
constraints()->purge_loader_constraints();
resolution_errors()->purge_resolution_errors();
}
{
GCTraceTime(Debug, gc, phases) t("ProtectionDomainCacheTable", gc_timer);
- // Oops referenced by the system dictionary may get unreachable independently
+ // Oops referenced by the protection domain cache table may get unreachable independently
// of the class loader (eg. cached protection domain oops). So we need to
- // explicitly unlink them here instead of in Dictionary::do_unloading.
- dictionary()->unlink(is_alive);
+ // explicitly unlink them here.
+ _pd_cache_table->unlink(is_alive);
+
#ifdef ASSERT
VerifySDReachableAndLiveClosure cl(is_alive);
- dictionary()->oops_do(&cl);
+ _pd_cache_table->oops_do(&cl);
#endif
}
@@ -1966,8 +1917,16 @@
strong->do_oop(&_system_loader_lock_obj);
CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
- // Adjust dictionary
- dictionary()->roots_oops_do(strong, weak);
+ // Do strong roots marking if the closures are the same.
+ if (strong == weak || !ClassUnloading) {
+ // Only the protection domain oops contain references into the heap. Iterate
+ // over all of them.
+ _pd_cache_table->oops_do(strong);
+ } else {
+ if (weak != NULL) {
+ _pd_cache_table->oops_do(weak);
+ }
+ }
// Visit extra methods
invoke_method_table()->oops_do(strong);
@@ -1982,8 +1941,9 @@
f->do_oop(&_system_loader_lock_obj);
CDS_ONLY(SystemDictionaryShared::oops_do(f);)
- // Adjust dictionary
- dictionary()->oops_do(f);
+ // Only the protection domain oops contain references into the heap. Iterate
+ // over all of them.
+ _pd_cache_table->oops_do(f);
// Visit extra methods
invoke_method_table()->oops_do(f);
@@ -1991,25 +1951,6 @@
ResolvedMethodTable::oops_do(f);
}
-// Just the classes from defining class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*)) {
- dictionary()->classes_do(f);
-}
-
-// Added for initialize_itable_for_klass
-// Just the classes from defining class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
- dictionary()->classes_do(f, CHECK);
-}
-
-// All classes, and their class loaders
-// Don't iterate over placeholders
-void SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
- dictionary()->classes_do(f);
-}
-
void SystemDictionary::methods_do(void f(Method*)) {
// Walk methods in loaded classes
ClassLoaderDataGraph::methods_do(f);
@@ -2018,7 +1959,7 @@
}
void SystemDictionary::remove_classes_in_error_state() {
- dictionary()->remove_classes_in_error_state();
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->remove_classes_in_error_state();
}
// ----------------------------------------------------------------------------
@@ -2042,15 +1983,12 @@
void SystemDictionary::initialize(TRAPS) {
// Allocate arrays
- assert(dictionary() == NULL,
- "SystemDictionary should only be initialized once");
- _sdgeneration = 0;
- _dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount));
- _placeholders = new PlaceholderTable(_nof_buckets);
+ _placeholders = new PlaceholderTable(_placeholder_table_size);
_number_of_modifications = 0;
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
+ _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
// Allocate private object used as system class loader lock
_system_loader_lock_obj = oopFactory::new_intArray(0, CHECK);
@@ -2204,9 +2142,9 @@
// Constraints on class loaders. The details of the algorithm can be
// found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
// Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is
-// that the system dictionary needs to maintain a set of contraints that
+// that the dictionary needs to maintain a set of contraints that
// must be satisfied by all classes in the dictionary.
-// if defining is true, then LinkageError if already in systemDictionary
+// if defining is true, then LinkageError if already in dictionary
// if initiating loader, then ok if InstanceKlass matches existing entry
void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
@@ -2221,12 +2159,12 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data);
+ InstanceKlass* check = find_class(d_index, d_hash, name, loader_data->dictionary());
if (check != NULL) {
// if different InstanceKlass - duplicate class definition,
// else - ok, class loaded by a different thread in parallel,
// we should only have found it if it was done loading and ok to use
- // system dictionary only holds instance classes, placeholders
+ // dictionary only holds instance classes, placeholders
// also holds array classes
assert(check->is_instance_klass(), "noninstance in systemdictionary");
@@ -2267,7 +2205,7 @@
}
-// Update system dictionary - done after check_constraint and add_to_hierachy
+// Update class loader data dictionary - done after check_constraint and add_to_hierachy
// have been called.
void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
int p_index, unsigned int p_hash,
@@ -2280,40 +2218,41 @@
ClassLoaderData *loader_data = class_loader_data(class_loader);
{
- MutexLocker mu1(SystemDictionary_lock, THREAD);
+ MutexLocker mu1(SystemDictionary_lock, THREAD);
- // See whether biased locking is enabled and if so set it for this
- // klass.
- // Note that this must be done past the last potential blocking
- // point / safepoint. We enable biased locking lazily using a
- // VM_Operation to iterate the SystemDictionary and installing the
- // biasable mark word into each InstanceKlass's prototype header.
- // To avoid race conditions where we accidentally miss enabling the
- // optimization for one class in the process of being added to the
- // dictionary, we must not safepoint after the test of
- // BiasedLocking::enabled().
- if (UseBiasedLocking && BiasedLocking::enabled()) {
- // Set biased locking bit for all loaded classes; it will be
- // cleared if revocation occurs too often for this type
- // NOTE that we must only do this when the class is initally
- // defined, not each time it is referenced from a new class loader
- if (k->class_loader() == class_loader()) {
- k->set_prototype_header(markOopDesc::biased_locking_prototype());
+ // See whether biased locking is enabled and if so set it for this
+ // klass.
+ // Note that this must be done past the last potential blocking
+ // point / safepoint. We enable biased locking lazily using a
+ // VM_Operation to iterate the SystemDictionary and installing the
+ // biasable mark word into each InstanceKlass's prototype header.
+ // To avoid race conditions where we accidentally miss enabling the
+ // optimization for one class in the process of being added to the
+ // dictionary, we must not safepoint after the test of
+ // BiasedLocking::enabled().
+ if (UseBiasedLocking && BiasedLocking::enabled()) {
+ // Set biased locking bit for all loaded classes; it will be
+ // cleared if revocation occurs too often for this type
+ // NOTE that we must only do this when the class is initally
+ // defined, not each time it is referenced from a new class loader
+ if (k->class_loader() == class_loader()) {
+ k->set_prototype_header(markOopDesc::biased_locking_prototype());
+ }
}
- }
- // Make a new system dictionary entry.
- InstanceKlass* sd_check = find_class(d_index, d_hash, name, loader_data);
- if (sd_check == NULL) {
- dictionary()->add_klass(name, loader_data, k);
- notice_modification();
- }
-#ifdef ASSERT
- sd_check = find_class(d_index, d_hash, name, loader_data);
- assert (sd_check != NULL, "should have entry in system dictionary");
- // Note: there may be a placeholder entry: for circularity testing
- // or for parallel defines
-#endif
+ // Make a new dictionary entry.
+ Dictionary* dictionary = loader_data->dictionary();
+ InstanceKlass* sd_check = find_class(d_index, d_hash, name, dictionary);
+ if (sd_check == NULL) {
+ dictionary->add_klass(d_index, d_hash, name, k);
+ notice_modification();
+ }
+ #ifdef ASSERT
+ sd_check = find_class(d_index, d_hash, name, dictionary);
+ assert (sd_check != NULL, "should have entry in dictionary");
+ // Note: there may be a placeholder entry: for circularity testing
+ // or for parallel defines
+ #endif
SystemDictionary_lock->notify_all();
}
}
@@ -2383,21 +2322,21 @@
constraint_name = fd.object_key();
}
}
- unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, loader_data1);
- int d_index1 = dictionary()->hash_to_index(d_hash1);
- unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, loader_data2);
- int d_index2 = dictionary()->hash_to_index(d_hash2);
- {
- MutexLocker mu_s(SystemDictionary_lock, THREAD);
+ Dictionary* dictionary1 = loader_data1->dictionary();
+ unsigned int d_hash1 = dictionary1->compute_hash(constraint_name);
+ int d_index1 = dictionary1->hash_to_index(d_hash1);
- // Better never do a GC while we're holding these oops
- NoSafepointVerifier nosafepoint;
+ Dictionary* dictionary2 = loader_data2->dictionary();
+ unsigned int d_hash2 = dictionary2->compute_hash(constraint_name);
+ int d_index2 = dictionary2->hash_to_index(d_hash2);
- InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, loader_data1);
- InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, loader_data2);
- return constraints()->add_entry(constraint_name, klass1, class_loader1,
- klass2, class_loader2);
+ {
+ MutexLocker mu_s(SystemDictionary_lock, THREAD);
+ InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, dictionary1);
+ InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, dictionary2);
+ return constraints()->add_entry(constraint_name, klass1, class_loader1,
+ klass2, class_loader2);
}
}
@@ -2847,64 +2786,73 @@
return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
}
-// Since the identity hash code for symbols changes when the symbols are
-// moved from the regular perm gen (hash in the mark word) to the shared
-// spaces (hash is the address), the classes loaded into the dictionary
-// may be in the wrong buckets.
+// Protection domain cache table handling
+
+ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {
+ return _pd_cache_table->get(protection_domain);
+}
+
void SystemDictionary::reorder_dictionary() {
- dictionary()->reorder_dictionary();
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->reorder_dictionary();
}
void SystemDictionary::copy_buckets(char** top, char* end) {
- dictionary()->copy_buckets(top, end);
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_buckets(top, end);
}
void SystemDictionary::copy_table(char** top, char* end) {
- dictionary()->copy_table(top, end);
+ ClassLoaderData::the_null_class_loader_data()->dictionary()->copy_table(top, end);
}
-int SystemDictionary::number_of_classes() {
- return dictionary()->number_of_entries();
-}
-
-
// ----------------------------------------------------------------------------
void SystemDictionary::print_shared(bool details) {
shared_dictionary()->print(details);
}
void SystemDictionary::print(bool details) {
- dictionary()->print(details);
+ if (shared_dictionary() != NULL) {
+ tty->print_cr("Shared Dictionary");
+ shared_dictionary()->print(details);
+ }
+
+ GCMutexLocker mu(SystemDictionary_lock);
+
+ ClassLoaderDataGraph::print_dictionary(details);
// Placeholders
- GCMutexLocker mu(SystemDictionary_lock);
placeholders()->print();
+ tty->cr();
// loader constraints - print under SD_lock
constraints()->print();
+ tty->cr();
+
+ _pd_cache_table->print();
+ tty->cr();
}
void SystemDictionary::verify() {
- guarantee(dictionary() != NULL, "Verify of system dictionary failed");
guarantee(constraints() != NULL,
"Verify of loader constraints failed");
- guarantee(dictionary()->number_of_entries() >= 0 &&
- placeholders()->number_of_entries() >= 0,
- "Verify of system dictionary failed");
+ guarantee(placeholders()->number_of_entries() >= 0,
+ "Verify of placeholders failed");
+
+ GCMutexLocker mu(SystemDictionary_lock);
// Verify dictionary
- dictionary()->verify();
+ ClassLoaderDataGraph::verify_dictionary();
- GCMutexLocker mu(SystemDictionary_lock);
placeholders()->verify();
// Verify constraint table
guarantee(constraints() != NULL, "Verify of loader constraints failed");
- constraints()->verify(dictionary(), placeholders());
+ constraints()->verify(placeholders());
+
+ _pd_cache_table->verify();
}
// caller needs ResourceMark
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -35,31 +35,34 @@
#include "utilities/hashtable.hpp"
#include "utilities/hashtable.inline.hpp"
-// The system dictionary stores all loaded classes and maps:
+// The dictionary in each ClassLoaderData stores all loaded classes, either
+// initiatied by its class loader or defined by its class loader:
//
-// [class name,class loader] -> class i.e. [Symbol*,oop] -> Klass*
+// class loader -> ClassLoaderData -> [class, protection domain set]
//
// Classes are loaded lazily. The default VM class loader is
// represented as NULL.
-// The underlying data structure is an open hash table with a fixed number
-// of buckets. During loading the loader object is locked, (for the VM loader
-// a private lock object is used). Class loading can thus be done concurrently,
-// but only by different loaders.
+// The underlying data structure is an open hash table (Dictionary) per
+// ClassLoaderData with a fixed number of buckets. During loading the
+// class loader object is locked, (for the VM loader a private lock object is used).
+// The global SystemDictionary_lock is held for all additions into the ClassLoaderData
+// dictionaries. TODO: fix lock granularity so that class loading can
+// be done concurrently, but only by different loaders.
//
// During loading a placeholder (name, loader) is temporarily placed in
// a side data structure, and is used to detect ClassCircularityErrors
// and to perform verification during GC. A GC can occur in the midst
// of class loading, as we call out to Java, have to take locks, etc.
//
-// When class loading is finished, a new entry is added to the system
-// dictionary and the place holder is removed. Note that the protection
-// domain field of the system dictionary has not yet been filled in when
-// the "real" system dictionary entry is created.
+// When class loading is finished, a new entry is added to the dictionary
+// of the class loader and the placeholder is removed. Note that the protection
+// domain field of the dictionary entry has not yet been filled in when
+// the "real" dictionary entry is created.
//
// Clients of this class who are interested in finding if a class has
// been completely loaded -- not classes in the process of being loaded --
-// can read the SystemDictionary unlocked. This is safe because
+// can read the dictionary unlocked. This is safe because
// - entries are only deleted at safepoints
// - readers cannot come to a safepoint while actively examining
// an entry (an entry cannot be deleted from under a reader)
@@ -78,6 +81,8 @@
template <MEMFLAGS F> class HashtableBucket;
class ResolutionErrorTable;
class SymbolPropertyTable;
+class ProtectionDomainCacheTable;
+class ProtectionDomainCacheEntry;
class GCTimer;
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
@@ -281,7 +286,7 @@
bool is_superclass,
TRAPS);
- // Parse new stream. This won't update the system dictionary or
+ // Parse new stream. This won't update the dictionary or
// class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses.
// Also used by Unsafe_DefineAnonymousClass
static InstanceKlass* parse_stream(Symbol* class_name,
@@ -348,14 +353,6 @@
Handle class_loader,
TRAPS);
- // Iterate over all klasses in dictionary
- // Just the classes from defining class loaders
- static void classes_do(void f(Klass*));
- // Added for initialize_itable_for_klass to handle exceptions
- static void classes_do(void f(Klass*, TRAPS), TRAPS);
- // All classes, and their class loaders, including initiating class loaders
- static void classes_do(void f(Klass*, ClassLoaderData*));
-
// Iterate over all methods in all klasses
static void methods_do(void f(Method*));
@@ -394,11 +391,6 @@
static void print(bool details = true);
static void print_shared(bool details = true);
- // Number of contained klasses
- // This is both fully loaded classes and classes in the process
- // of being loaded
- static int number_of_classes();
-
// Monotonically increasing counter which grows as classes are
// loaded or modifications such as hot-swapping or setting/removing
// of breakpoints are performed
@@ -558,28 +550,21 @@
static Symbol* find_resolution_error(const constantPoolHandle& pool, int which,
Symbol** message);
+
+ static ProtectionDomainCacheEntry* cache_get(Handle protection_domain);
+
protected:
enum Constants {
_loader_constraint_size = 107, // number of entries in constraint table
_resolution_error_size = 107, // number of entries in resolution error table
_invoke_method_size = 139, // number of entries in invoke method table
- _nof_buckets = 1009, // number of buckets in hash table for placeholders
- _old_default_sdsize = 1009, // backward compat for system dictionary size
- _prime_array_size = 8, // array of primes for system dictionary size
- _average_depth_goal = 3 // goal for lookup length
+ _shared_dictionary_size = 1009, // number of entries in shared dictionary
+ _placeholder_table_size = 1009 // number of entries in hash table for placeholders
};
- // Static variables
-
- // hashtable sizes for system dictionary to allow growth
- // prime numbers for system dictionary size
- static int _sdgeneration;
- static const int _primelist[_prime_array_size];
-
- // Hashtable holding loaded classes.
- static Dictionary* _dictionary;
+ // Static tables owned by the SystemDictionary
// Hashtable holding placeholders for classes being loaded.
static PlaceholderTable* _placeholders;
@@ -588,7 +573,7 @@
static Dictionary* _shared_dictionary;
// Monotonically increasing counter which grows with
- // _number_of_classes as well as hot-swapping and breakpoint setting
+ // loading classes as well as hot-swapping and breakpoint setting
// and removal.
static int _number_of_modifications;
@@ -604,10 +589,8 @@
// Invoke methods (JSR 292)
static SymbolPropertyTable* _invoke_method_table;
-public:
- // for VM_CounterDecay iteration support
- friend class CounterDecay;
- static Klass* try_get_next_class();
+ // ProtectionDomain cache
+ static ProtectionDomainCacheTable* _pd_cache_table;
protected:
static void validate_protection_domain(InstanceKlass* klass,
@@ -616,7 +599,6 @@
friend class VM_PopulateDumpSharedSpace;
friend class TraversePlaceholdersClosure;
- static Dictionary* dictionary() { return _dictionary; }
static Dictionary* shared_dictionary() { return _shared_dictionary; }
static PlaceholderTable* placeholders() { return _placeholders; }
static LoaderConstraintTable* constraints() { return _loader_constraints; }
@@ -666,7 +648,7 @@
// Basic find on loaded classes
static InstanceKlass* find_class(int index, unsigned int hash,
- Symbol* name, ClassLoaderData* loader_data);
+ Symbol* name, Dictionary* dictionary);
static InstanceKlass* find_class(Symbol* class_name, ClassLoaderData* loader_data);
// Basic find on classes in the midst of being loaded
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -69,6 +69,7 @@
}
static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {}
+ static bool is_builtin(DictionaryEntry* entry) { return true; }
static InstanceKlass* lookup_from_stream(Symbol* class_name,
Handle class_loader,
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -548,14 +548,13 @@
}
-void initialize_itable_for_klass(Klass* k, TRAPS) {
- InstanceKlass::cast(k)->itable().initialize_itable(false, CHECK);
+void initialize_itable_for_klass(InstanceKlass* k, TRAPS) {
+ k->itable().initialize_itable(false, CHECK);
}
void Universe::reinitialize_itables(TRAPS) {
- SystemDictionary::classes_do(initialize_itable_for_klass, CHECK);
-
+ ClassLoaderDataGraph::dictionary_classes_do(initialize_itable_for_klass, CHECK);
}
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -1569,7 +1569,7 @@
}
static void compute() {
- SystemDictionary::classes_do(do_class);
+ ClassLoaderDataGraph::classes_do(do_class);
fixed = no_klasses * oopSize; // vtable length
// filler size is a conservative approximation
filler = oopSize * (no_klasses - no_instance_klasses) * (sizeof(InstanceKlass) - sizeof(ArrayKlass) - 1);
--- a/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -70,7 +70,7 @@
// The closure for GetClassLoaderClasses
class JvmtiGetLoadedClassesClosure : public StackObj {
- // Since the SystemDictionary::classes_do callback
+ // Since the ClassLoaderDataGraph::dictionary_all_entries_do callback
// doesn't pass a closureData pointer,
// we use a thread-local slot to hold a pointer to
// a stack allocated instance of this structure.
@@ -203,7 +203,7 @@
}
}
- static void increment_with_loader(Klass* k, ClassLoaderData* loader_data) {
+ static void increment_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
oop class_loader = loader_data->class_loader();
if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) {
@@ -213,7 +213,7 @@
}
}
- static void add_with_loader(Klass* k, ClassLoaderData* loader_data) {
+ static void add_with_loader(InstanceKlass* k, ClassLoaderData* loader_data) {
JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this();
if (that->available()) {
oop class_loader = loader_data->class_loader();
@@ -285,26 +285,26 @@
jvmtiError
JvmtiGetLoadedClasses::getClassLoaderClasses(JvmtiEnv *env, jobject initiatingLoader,
jint* classCountPtr, jclass** classesPtr) {
- // Since SystemDictionary::classes_do only takes a function pointer
+ // Since ClassLoaderDataGraph::dictionary_all_entries_do only takes a function pointer
// and doesn't call back with a closure data pointer,
// we can only pass static methods.
JvmtiGetLoadedClassesClosure closure(initiatingLoader);
{
// To get a consistent list of classes we need MultiArray_lock to ensure
// array classes aren't created, and SystemDictionary_lock to ensure that
- // classes aren't added to the system dictionary,
+ // classes aren't added to the class loader data dictionaries.
MutexLocker ma(MultiArray_lock);
MutexLocker sd(SystemDictionary_lock);
- // First, count the classes in the system dictionary which have this loader recorded
+ // First, count the classes in the class loader data dictionaries which have this loader recorded
// as an initiating loader. For basic type arrays this information is not recorded
// so GetClassLoaderClasses will return all of the basic type arrays. This is okay
// because the defining loader for basic type arrays is always the boot class loader
// and these classes are "visible" to all loaders.
- SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
+ ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::increment_with_loader);
Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::increment_for_basic_type_arrays);
// Next, fill in the classes
closure.allocate();
- SystemDictionary::classes_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
+ ClassLoaderDataGraph::dictionary_all_entries_do(&JvmtiGetLoadedClassesClosure::add_with_loader);
Universe::basic_type_classes_do(&JvmtiGetLoadedClassesClosure::add_for_basic_type_arrays);
// Drop the SystemDictionary_lock, so the results could be wrong from here,
// but we still have a snapshot.
--- a/hotspot/src/share/vm/runtime/biasedLocking.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -42,7 +42,7 @@
static GrowableArray<Handle>* _preserved_oop_stack = NULL;
static GrowableArray<markOop>* _preserved_mark_stack = NULL;
-static void enable_biased_locking(Klass* k) {
+static void enable_biased_locking(InstanceKlass* k) {
k->set_prototype_header(markOopDesc::biased_locking_prototype());
}
@@ -56,9 +56,9 @@
bool is_cheap_allocated() const { return _is_cheap_allocated; }
void doit() {
- // Iterate the system dictionary enabling biased locking for all
- // currently loaded classes
- SystemDictionary::classes_do(enable_biased_locking);
+ // Iterate the class loader data dictionaries enabling biased locking for all
+ // currently loaded classes.
+ ClassLoaderDataGraph::dictionary_classes_do(enable_biased_locking);
// Indicate that future instances should enable it as well
_biased_locking_enabled = true;
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -312,13 +312,13 @@
// and hence GC's will not be going on, all Java mutators are suspended
// at this point and hence SystemDictionary_lock is also not needed.
assert(SafepointSynchronize::is_at_safepoint(), "can only be executed at a safepoint");
- int nclasses = SystemDictionary::number_of_classes();
+ int nclasses = InstanceKlass::number_of_instance_classes();
double classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 /
CounterHalfLifeTime);
for (int i = 0; i < classes_per_tick; i++) {
- Klass* k = SystemDictionary::try_get_next_class();
- if (k != NULL && k->is_instance_klass()) {
- InstanceKlass::cast(k)->methods_do(do_method);
+ InstanceKlass* k = ClassLoaderDataGraph::try_get_next_class();
+ if (k != NULL) {
+ k->methods_do(do_method);
}
}
}
--- a/hotspot/src/share/vm/runtime/memprofiler.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/runtime/memprofiler.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -120,7 +120,7 @@
fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",",
os::elapsedTime(),
Threads::number_of_threads(),
- SystemDictionary::number_of_classes(),
+ InstanceKlass::number_of_instance_classes(),
Universe::heap()->used() / K,
Universe::heap()->capacity() / K);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -31,8 +31,6 @@
#include "classfile/compactHashtable.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
-#include "classfile/loaderConstraints.hpp"
-#include "classfile/placeholders.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeBlob.hpp"
@@ -193,10 +191,8 @@
typedef Hashtable<Symbol*, mtSymbol> SymbolHashtable;
typedef HashtableEntry<Symbol*, mtClass> SymbolHashtableEntry;
typedef Hashtable<oop, mtSymbol> StringHashtable;
-typedef TwoOopHashtable<InstanceKlass*, mtClass> KlassTwoOopHashtable;
typedef Hashtable<InstanceKlass*, mtClass> KlassHashtable;
typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
-typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
@@ -250,7 +246,6 @@
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
nonstatic_field(InstanceKlass, _java_fields_count, u2) \
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
- nonstatic_field(InstanceKlass, _class_loader_data, ClassLoaderData*) \
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
nonstatic_field(InstanceKlass, _source_debug_extension, const char*) \
nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
@@ -291,6 +286,7 @@
nonstatic_field(Klass, _next_sibling, Klass*) \
nonstatic_field(Klass, _next_link, Klass*) \
nonstatic_field(Klass, _vtable_len, int) \
+ nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \
nonstatic_field(vtableEntry, _method, Method*) \
nonstatic_field(MethodData, _size, int) \
nonstatic_field(MethodData, _method, Method*) \
@@ -607,46 +603,16 @@
/* SystemDictionary */ \
/********************/ \
\
- static_field(SystemDictionary, _dictionary, Dictionary*) \
- static_field(SystemDictionary, _placeholders, PlaceholderTable*) \
static_field(SystemDictionary, _shared_dictionary, Dictionary*) \
static_field(SystemDictionary, _system_loader_lock_obj, oop) \
- static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \
static_field(SystemDictionary, WK_KLASS(Object_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(String_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(Class_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Cloneable_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(ClassLoader_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Serializable_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(System_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Throwable_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(ThreadDeath_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Error_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Exception_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(RuntimeException_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(ClassNotFoundException_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(NoClassDefFoundError_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(LinkageError_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(VirtualMachineError_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Reference_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(SoftReference_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(WeakReference_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(FinalReference_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(PhantomReference_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Finalizer_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(Thread_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(Properties_klass), InstanceKlass*) \
- static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), InstanceKlass*) \
static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), InstanceKlass*) \
- static_field(SystemDictionary, _box_klasses[0], InstanceKlass*) \
static_field(SystemDictionary, _java_system_loader, oop) \
\
/*************/ \
@@ -681,42 +647,13 @@
nonstatic_field(BasicHashtable<mtInternal>, _entry_size, int) \
\
/*******************/ \
- /* DictionaryEntry */ \
+ /* ClassLoaderData */ \
/*******************/ \
- \
- nonstatic_field(DictionaryEntry, _loader_data, ClassLoaderData*) \
- nonstatic_field(DictionaryEntry, _pd_set, ProtectionDomainEntry*) \
- \
- /********************/ \
- \
- nonstatic_field(PlaceholderEntry, _loader_data, ClassLoaderData*) \
- \
- /**************************/ \
- /* ProtectionDomainEntry */ \
- /**************************/ \
- \
- nonstatic_field(ProtectionDomainEntry, _next, ProtectionDomainEntry*) \
- nonstatic_field(ProtectionDomainEntry, _pd_cache, ProtectionDomainCacheEntry*) \
- \
- /*******************************/ \
- /* ProtectionDomainCacheEntry */ \
- /*******************************/ \
- \
- nonstatic_field(ProtectionDomainCacheEntry, _literal, oop) \
- \
- /*************************/ \
- /* LoaderConstraintEntry */ \
- /*************************/ \
- \
- nonstatic_field(LoaderConstraintEntry, _name, Symbol*) \
- nonstatic_field(LoaderConstraintEntry, _num_loaders, int) \
- nonstatic_field(LoaderConstraintEntry, _max_loaders, int) \
- nonstatic_field(LoaderConstraintEntry, _loaders, ClassLoaderData**) \
- \
nonstatic_field(ClassLoaderData, _class_loader, oop) \
nonstatic_field(ClassLoaderData, _next, ClassLoaderData*) \
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
nonstatic_field(ClassLoaderData, _is_anonymous, bool) \
+ volatile_nonstatic_field(ClassLoaderData, _dictionary, Dictionary*) \
\
static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
\
@@ -1610,20 +1547,13 @@
declare_type(RehashableSymbolHashtable, BasicHashtable<mtSymbol>) \
declare_type(SymbolTable, SymbolHashtable) \
declare_type(StringTable, StringHashtable) \
- declare_type(LoaderConstraintTable, KlassHashtable) \
- declare_type(KlassTwoOopHashtable, KlassHashtable) \
- declare_type(Dictionary, KlassTwoOopHashtable) \
- declare_type(PlaceholderTable, SymbolTwoOopHashtable) \
+ declare_type(Dictionary, KlassHashtable) \
declare_toplevel_type(BasicHashtableEntry<mtInternal>) \
declare_type(IntptrHashtableEntry, BasicHashtableEntry<mtInternal>) \
declare_type(DictionaryEntry, KlassHashtableEntry) \
- declare_type(PlaceholderEntry, SymbolHashtableEntry) \
- declare_type(LoaderConstraintEntry, KlassHashtableEntry) \
declare_toplevel_type(HashtableBucket<mtInternal>) \
declare_toplevel_type(SystemDictionary) \
declare_toplevel_type(vmSymbols) \
- declare_toplevel_type(ProtectionDomainEntry) \
- declare_toplevel_type(ProtectionDomainCacheEntry) \
\
declare_toplevel_type(GenericGrowableArray) \
declare_toplevel_type(GrowableArray<int>) \
@@ -2355,12 +2285,6 @@
declare_preprocessor_constant("PERFDATA_BIG_ENDIAN", PERFDATA_BIG_ENDIAN) \
declare_preprocessor_constant("PERFDATA_LITTLE_ENDIAN", PERFDATA_LITTLE_ENDIAN) \
\
- /***********************************/ \
- /* LoaderConstraintTable constants */ \
- /***********************************/ \
- \
- declare_constant(LoaderConstraintTable::_loader_constraint_size) \
- declare_constant(LoaderConstraintTable::_nof_buckets) \
\
/************************************************************/ \
/* HotSpot specific JVM_ACC constants from global anon enum */ \
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -417,10 +417,6 @@
const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 (p.134)
-// Default ProtectionDomainCacheSize values
-
-const int defaultProtectionDomainCacheSize = NOT_LP64(137) LP64_ONLY(2017);
-
//----------------------------------------------------------------------------------------------------
// Default and minimum StringTableSize values
--- a/hotspot/src/share/vm/utilities/hashtable.cpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp Fri Jul 28 10:48:35 2017 -0400
@@ -84,6 +84,17 @@
return entry;
}
+// Version of hashtable entry allocation that allocates in the C heap directly.
+// The allocator in blocks is preferable but doesn't have free semantics.
+template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::allocate_new_entry(unsigned int hashValue, T obj) {
+ HashtableEntry<T, F>* entry = (HashtableEntry<T, F>*) NEW_C_HEAP_ARRAY(char, this->entry_size(), F);
+
+ entry->set_hash(hashValue);
+ entry->set_literal(obj);
+ entry->set_next(NULL);
+ return entry;
+}
+
// Check to see if the hashtable is unbalanced. The caller set a flag to
// rehash at the next safepoint. If this bucket is 60 times greater than the
// expected average bucket length, it's an unbalanced hashtable.
@@ -357,6 +368,7 @@
template class Hashtable<Klass*, mtClass>;
template class Hashtable<InstanceKlass*, mtClass>;
template class Hashtable<oop, mtClass>;
+template class Hashtable<Symbol*, mtModule>;
#if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
template class Hashtable<oop, mtSymbol>;
template class RehashableHashtable<oop, mtSymbol>;
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.hpp Fri Jul 28 10:48:35 2017 -0400
@@ -253,18 +253,20 @@
// Debugging
void print() PRODUCT_RETURN;
-protected:
-
- unsigned int compute_hash(Symbol* name) {
+ unsigned int compute_hash(const Symbol* name) const {
return (unsigned int) name->identity_hash();
}
- int index_for(Symbol* name) {
+ int index_for(const Symbol* name) const {
return this->hash_to_index(compute_hash(name));
}
+protected:
+
// Table entry management
HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);
+ // Don't create and use freelist of HashtableEntry.
+ HashtableEntry<T, F>* allocate_new_entry(unsigned int hashValue, T obj);
// The following method is MT-safe and may be used with caution.
HashtableEntry<T, F>* bucket(int i) const {
@@ -324,31 +326,4 @@
template <class T, MEMFLAGS F> juint RehashableHashtable<T, F>::seed() { return _seed; };
template <class T, MEMFLAGS F> bool RehashableHashtable<T, F>::use_alternate_hashcode() { return _seed != 0; };
-// Versions of hashtable where two handles are used to compute the index.
-
-template <class T, MEMFLAGS F> class TwoOopHashtable : public Hashtable<T, F> {
- friend class VMStructs;
-protected:
- TwoOopHashtable(int table_size, int entry_size)
- : Hashtable<T, F>(table_size, entry_size) {}
-
- TwoOopHashtable(int table_size, int entry_size, HashtableBucket<F>* t,
- int number_of_entries)
- : Hashtable<T, F>(table_size, entry_size, t, number_of_entries) {}
-
-public:
- unsigned int compute_hash(const Symbol* name, const ClassLoaderData* loader_data) const {
- unsigned int name_hash = name->identity_hash();
- // loader is null with CDS
- assert(loader_data != NULL || UseSharedSpaces || DumpSharedSpaces,
- "only allowed with shared spaces");
- unsigned int loader_hash = loader_data == NULL ? 0 : loader_data->identity_hash();
- return name_hash ^ loader_hash;
- }
-
- int index_for(Symbol* name, ClassLoaderData* loader_data) {
- return this->hash_to_index(compute_hash(name, loader_data));
- }
-};
-
#endif // SHARE_VM_UTILITIES_HASHTABLE_HPP
--- a/hotspot/test/runtime/NMT/CheckForProperDetailStackTrace.java Thu Jul 27 17:47:57 2017 -0700
+++ b/hotspot/test/runtime/NMT/CheckForProperDetailStackTrace.java Fri Jul 28 10:48:35 2017 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -40,10 +40,10 @@
/* The stack trace we look for by default. Note that :: has been replaced by .*
to make sure it maches even if the symbol is not unmangled. */
public static String stackTraceDefault =
+ ".*Hashtable.*allocate_new_entry.*\n" +
".*ModuleEntryTable.*new_entry.*\n" +
".*ModuleEntryTable.*locked_create_entry_or_null.*\n" +
- ".*Modules.*define_module.*\n" +
- ".*JVM_DefineModule.*\n";
+ ".*Modules.*define_module.*\n";
/* The stack trace we look for on Solaris and Windows slowdebug builds. For some
reason ALWAYSINLINE for AllocateHeap is ignored, so it appears in the stack strace. */