2014-02-13 3 views
1

код выглядит следующим образомХотя был загружен мой класс, Class.forName бросает ClassNotFoundException

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

import java.io.File; 
import java.util.jar.JarFile; 
import java.util.jar.JarEntry; 
import java.net.URLClassLoader; 
import java.net.URL; 
import java.util.Enumeration; 
import java.lang.ClassLoader; 
public class Plugin extends ClassLoader { 
public static void main(String[] args) throws Exception { 

    File file = new File(System.getProperty("user.home") + "/HelloWorld.jar"); 

    URLClassLoader clazzLoader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()}); 

    JarFile jarFile = new JarFile(file); 
    Enumeration<JarEntry> entries = jarFile.entries(); 

    while (entries.hasMoreElements()) { 
     JarEntry element = entries.nextElement(); 
     if (element.getName().endsWith(".class")) { 
      try { 
       Class c = clazzLoader.loadClass(element.getName().replaceAll(".class", "").replaceAll("/", ".")); 
       c.newInstance(); // this proves that class is loaded 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    Class cls = Class.forName("HelloWorld"); 
    cls.newInstance(); 
    Plugin p = new Plugin(); 
    p.checkIfLoaded(); 

} 

public void checkIfLoaded() { 
System.out.println("coming in"); 
if (findLoadedClass("HelloWorld") != null){ 
     System.out.println("Yepee, HelloWorld class is loaded !"); 
} 
} 

} 

Мои HelloWorld как в https://github.com/HarishAtGitHub/doc/blob/master/makeExecutableJar/HelloWorld.java

и банка заводится с инструкциями в моем GitHub счета, упомянутых выше.

c.newInstance() работает.

Как я могу подтвердить?

статический блок был выполнен ...

но Class.forName("HelloWorld") бросает ClassNotFoundException

также findLoadedClass("HelloWorld") является пустой ..

Я не могу понять, почему это странное поведение?

Пожалуйста, руководство ...

+2

Класс HelloWorld в пакете по умолчанию? – Kick

+0

нет. Он находится на том же уровне, что и папка META-INF .... –

ответ

2

Это вопрос Загрузчик классов.

В соответствии с Javadocs to Class.forName вы изучаете класс, используя загрузчик классов текущего класса. В качестве основного класса это будет загрузчик классов bootstrap JVM (и более или менее просто включите стандартную библиотеку плюс все, что вы указали в качестве аргумента командной строки -cp). Он не собирается делегировать загрузчику классов, который вы создавали как локальную переменную, и поэтому не будет возвращать классы, которые , что может найти classloader.

Если вы должны были указать загрузчик классов в явном виде, и вызвать

Class.forName("HelloWorld", true, clazzloader) 

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

+0

ya. так что невозможно проверить из любого места, если мой класс был загружен? должен ли мой clazzLoader всегда проходить мимо? являются загруженной информацией о классе, хранящейся в общем месте? –

+0

Самый простой способ справиться с этой конкретной ситуацией - загрузить ваши классы загрузочным загрузчиком (то есть основным). Если вы передадите 'Hello_World.jar' в качестве аргумента' -cp' для вашего вызова Java, классы в нем будут автоматически загружаться главным загрузчиком классов, вам больше не нужно ничего делать. (Или, если приложение само является JAR, вы можете установить свойство Class-Path своего манифеста.) –

+0

Да, я понимаю. Я делаю это упражнение только для отклонения цели ..... –

1

Поскольку Class.forName (String) использует currentClassLoader и вы должны загрузить класс в разных ClassLoader.

Согласно с javadoc, вызывая Class.forName (String) эквивалентно:

Class.forName(className, true, currentLoader) 
Смежные вопросы