При создании ссылки на объект, откуда загружается этот класс? - PullRequest
1 голос
/ 31 декабря 2010

При выполнении некоторого примера кодирования с Java я наткнулся на ClassCastException, откуда я приводил объект к StaticClass.Может ли кто-нибудь объяснить, что здесь произошло?

public void test5() throws Exception {

   System.out.println(StaticClass.obj);
   Object newInstance = ClassLoader.getSystemClassLoader().loadClass("com.StaticClass").newInstance();
   System.out.println(newInstance.getClass().getDeclaredField("obj").get(newInstance));

   Object newInstance2 = new ILoader().loadClass("com//StaticClass.class").newInstance();
   System.out.println(newInstance2.getClass().getDeclaredField("obj").get(newInstance2));

   StaticClass s = (StaticClass)newInstance2;
   System.out.println(s.obj);

   System.out.println(newInstance.getClass().getClassLoader());
   System.out.println(newInstance2.getClass().getClassLoader());

}

package com;

public class StaticClass {

   public static final Object obj = new Object();
}

package com;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ILoader extends ClassLoader {

 public ILoader() {
  super(null);
 }

 @Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {

   File file = new File(name);

   byte[] bytes = new byte[(int)file.length()];

   try {
     new FileInputStream(file).read(bytes);
   } catch (FileNotFoundException e) {
    e.printStackTrace();
   } catch (IOException e) {
    e.printStackTrace();
   }

   return super.defineClass("com.StaticClass",bytes, 0, bytes.length);
 }
}

вывод, который был предоставлен последним System.out, когда не существовала часть кода, используемая для преобразования.как показано ниже.

sun.misc.Launcher$AppClassLoader@133056f
com.ILoader@1ac3c08

Ответы [ 2 ]

2 голосов
/ 31 декабря 2010

Когда два загрузчика классов загружают класс, у вас фактически есть две копии класса. В вашем сценарии, когда вы делаете что-то вроде этого

StaticClass s = (StaticClass)newInstance2;

Тогда по умолчанию ваш системный загрузчик классов по умолчанию входит в картинку для приведения. Так как newInstance2 загружается из другого загрузчика классов, следовательно, он даст ClassCastException. Это не будет работать - они представлены двумя различными объектами Class внутри JVM, и приведение не будет выполнено.

Подробнее см. В следующих статьях и записях на форуме:

  1. http://onjava.com/pub/a/onjava/2003/11/12/classloader.html

  2. http://java.sun.com/developer/technicalArticles/Networking/classloaders/index.html

  3. http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html

  4. http://www.coderanch.com/t/380416/java/java/Loading-same-class-two-different

  5. Различные загрузчики классов вызывают ClassCastException при сохранении данных через Spring

0 голосов
/ 31 декабря 2010

Класс определяется как его полностью определенным именем, так и загрузчиком классов, который его загрузил.

Это необходимо, потому что два класса одинаковы, только если они имеют одно и то же полное имя и были найдены вто же место (тот же загрузчик классов).

Если два класса имеют одинаковые имена и , они были загружены из разных загрузчиков классов, то нет гарантии, что они представляют один и тот же файл классов.

Если бы это было не так, это также представляло бы угрозу безопасности, поскольку вы могли бы подделать классы Java API.Вы можете создать свою собственную версию java.lang.String, загрузить ее с помощью другого загрузчика классов и получить привилегии других классов в java.lang (например, увидеть частные поля пакета).

ТамЕсть множество других преимуществ, связанных с уникальным идентификатором класса по имени и загрузчику классов.Хотя это выглядит немного странно, когда код генерирует исключение ClassCastException и классы имеют одинаковые имена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...