Странное поведение Java Class-Path / Class-Loader - PullRequest
0 голосов
/ 29 февраля 2012

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

Загрузка класса, который имеет (во время выполнения нетронутый метод), который вызывает конструктор другого класса с параметром, который приводится к классу, который наследует класс параметра, вызывает исключение класса not found класса paramter, если класс для загрузки, но нет других классов, на которые есть ссылки в методах этого класса, находится в пути к классу.

Я использую следующую Java:

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)
(Windows Server 2008 R2)

Вот пример:

public class A
{
  public static void main(String[] args)
  {
    System.out.println("it works");
  }

  public void foo()
  {
    new B((D)null);
  }
}

public class B
{
  public B(C c) {
  }
}

public class C
{
}


public class D extends C
{
}

Теперь я скомпилирую классы, и если я выполню класс A со всеми файлами классов в пути к классам, он выдаст «все работает».

Если я удаляю все классы, кроме класса A из пути к классам, возникает следующая ошибка:

Exception in thread "main" java.lang.NoClassDefFoundError: C
Caused by: java.lang.ClassNotFoundException: C
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: A.  Program will exit.

хотя класс C никогда не нужен во время выполнения.

Следующие работы созвездия (заменил «новый B ((D) ноль)» в классе A):

public class A
{
  public static void main(String[] args)
  {
    System.out.println("it works");
  }

  public void foo()
  {
    D d = (D)null;
    d.toString();
    B b = (B)null;
    b.toString();
    new B(null);
  }
}

public class B
{
  public B(C c) {
  }
}

public class C
{
}


public class D extends C
{
}

Следующее созвездие также работает (приведение к C вместо D; C не наследует ни один класс)

public class A
{
  public static void main(String[] args)
  {
    System.out.println("it works");
  }

  public void foo()
  {
    new B((C)null);
  }
}

public class B
{
  public B(C c) {
  }
}

public class C
{
}


public class D extends C
{
}

Это ожидаемое поведение или ошибка Java?

Ответы [ 2 ]

1 голос
/ 29 февраля 2012

см. Раздел 5.5 , если «Если значение во время выполнения равно нулю, то приведение разрешено», поэтому работает приведение к нулю.

0 голосов
/ 29 февраля 2012

Я не прошел через JSR, но я думаю, что когда интерпретатор интерпретирует файл класса, он не будет выполнять только необходимые методы, он будет делать все. В этом случае необходимо A, а если foo() также интерпретируется, то потребуется C. Все это должно происходить в момент загрузки A. Так что ошибка ..

...