簡體   English   中英

Java是否保證Object.getClass()== Object.getClass()?

[英]Does Java guarantee that Object.getClass() == Object.getClass()?

我真的是在這里指身份平等。

例如,以下內容將始終打印true嗎?

System.out.println("foo".getClass() == "fum".getClass());

是的,類令牌是唯一的(對於任何給定的類加載器而言)。

即,您將始終在相同的類加載器領域中獲得對相同物理對象的引用。 但是,不同的類加載器將加載不同的類令牌,同時,當兩個不同的類加載器加載相同的類定義時,該類定義也被視為不同。

有關示例,請參見我的較早答案

對於X類的兩個實例,

x1.getClass() == x2.getClass()

除非

x1.getClass().getClassLoader() == x2.getClass().getClassLoader()

注意: Class.getClassLoader()可能返回null,這意味着引導ClassLoader。

是。

返回的Class對象是被表示的類的靜態同步方法鎖定的對象。

如果可以返回多個實例,則

public static synchronized void doSomething() {..}

將不是線程安全的。

JVM規范中所述,每個類加載器都可以保證它:

首先,Java虛擬機確定是否已記錄L是由N表示的類或接口的啟動加載器。如果是,則此創建嘗試無效,並且加載會引發LinkageError。

也就是說,如果類加載器(L)試圖繞過默認的Class實例緩存,並且使JVM對於同一個類名(N)多次加載byte[]定義,則JVM將引發LinkageError

例如,實現一個每次調用loadClass(...)都會調用defineClass(...)的類加載器(繞過默認緩存):

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)

干杯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM