Does Java guarantee that Object.getClass() == Object.getClass()?

前端 未结 4 2146
礼貌的吻别
礼貌的吻别 2020-11-27 06:41

I really do mean identity-equality here.

For example, will the following always print true?

System.out.println(\"foo\".getClass() ==         


        
4条回答
  •  野性不改
    2020-11-27 06:53

    It is guaranteed per classloader, as stated in the JVM specification:

    First, the Java Virtual Machine determines whether it has already recorded that L is an initiating loader of a class or interface denoted by N. If so, this creation attempt is invalid and loading throws a LinkageError.

    That is, if a class loader (L) tries to bypass default Class instances caching, and make the JVM load the byte[] definition more than once for the same class name (N), a LinkageError will be thrown by the JVM.

    For example, implement a class loader that calls defineClass(...) each time loadClass(...) is invoked (bypassing default 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);
        }
    }
    

    and this is what happens:

    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)
    

    Cheers

提交回复
热议问题