Гарантируется для каждого загрузчика классов, как указано в спецификации JVM :
Сначала виртуальная машина Java определяет, записала ли она уже, что L является инициирующим загрузчиком класса или интерфейса, обозначенного N. Если это так, эта попытка создания недопустима, и при загрузке возникает ошибка LinkageError.
То есть, если загрузчик классов (L) пытается обойти кэширование Class
экземпляров по умолчанию и заставить JVM загрузить определение byte[]
более одного раза для того же имени класса (N), LinkageError
будет быть брошенным JVM.
Например, реализовать загрузчик классов, который вызывает defineClass(...)
каждый раз, когда вызывается loadClass(...)
(в обход кэширования по умолчанию):
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)
Приветствия