Java是否保证Object.getClass()== Object.getClass()?
我在这里确实是指身份平等。
例如,以下总是会打印真实的 ?
System.out.println("foo".getClass() == "fum".getClass());
是的,类令牌是唯一的(对于任何给定的类加载器,就是这样)。
也就是说,您将始终在相同的类加载器领域中获取同一物理对象的引用。 然而,不同的类加载器会加载一个不同的类标记,以及由两个不同的类加载器加载时相同的类定义被认为是不同的。
看到我以前的回答这个示范。
对于X
类的两个实例,
x1.getClass() == x2.getClass()
除非
x1.getClass().getClassLoader() == x2.getClass().getClassLoader()
注意: Class.getClassLoader()
可能返回null,这意味着引导类加载器。
是。
返回的Class对象是被表示类的静态同步方法locking的对象。
如果有可能返回多个实例,那么
public static synchronized void doSomething() {..}
不会是线程安全的。
正如JVM规范中所述,它是按类加载器保证的:
首先,Java虚拟机确定是否已经logging了L是由N表示的类或接口的启动加载器。如果是,则该创build尝试是无效的,并且加载会引发LinkageError。
也就是说,如果一个类加载器(L)试图绕过默认的Class
实例caching,并且让JVM不止一次地为相同的类名(N)加载byte[]
定义,那么JVM就会抛出LinkageError
。
例如,每次调用loadClass(...)
时defineClass(...)
实现一个调用defineClass(...)
的类加载器(绕过默认caching):
public class ClassloaderTest { private static final byte[] CLASS_DEF = readClassBytes(); private static byte[] readClassBytes() { try { InputStream is = ClassloaderTest.class.getResourceAsStream("ClassloaderTest.class"); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[16384]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); return buffer.toByteArray(); } catch (IOException ex) { throw new AssertionError(); } } private static ClassLoader createNonCachingClassloader() { return new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name.equals("classloader.ClassloaderTest")) { return defineClass(name, CLASS_DEF, 0, CLASS_DEF.length); } else { return getParent().loadClass(name); } } }; } public static void main(String[] args) throws Exception { ClassLoader cl = createNonCachingClassloader(); Class<?> cl1 = cl.loadClass("classloader.ClassloaderTest"); Class<?> cl2 = cl.loadClass("classloader.ClassloaderTest"); System.out.println(cl1==cl2); } }
这是发生了什么事情:
Exception in thread "main" java.lang.LinkageError: loader (instance of classloader/ClassloaderTest$1): attempted duplicate class definition for name: "classloader/ClassloaderTest" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760) at java.lang.ClassLoader.defineClass(ClassLoader.java:642) at classloader.ClassloaderTest$1.loadClass(ClassloaderTest.java:53) at classloader.ClassloaderTest.main(ClassloaderTest.java:64)
干杯