Странный путь к классам, ошибки .NoClassDefFoundError

Отредактировано: РЕШЕНИЕ НАЙДЕНО. Это странное и не лучшее решение, но я просто пошел дальше и поместил МОЙ JAVA CODE (com. *) Классы в swt.jar, чтобы swt.jar и мои классы загружались в один и тот же момент и одним и тем же загрузчик классов. Не лучшее решение, но временное решение.

Отредактировано: я добавил сюда большую часть кода: http://groups.google.com/group/clojure/browse_thread/thread/1d7dd4913b2f9aa7 http://groups.google.com/group/clojure/web/NoClassDefIssue.zip http://groups.google.com/group/clojure/web/MostCodeIssue.java

Это странная ошибка no classdef not found. Вот сценарий, который немного отличается от работы 90% моего кода. Не обращайте внимания на то, что я использую Clojure, я также сделал это с помощью обычного java-кода и по-прежнему получаю ту же ошибку.

В идеале я надеялся на некоторую помощь с пользовательским загрузчиком классов. Моя первоначальная мысль заключалась в том, что я могу создать загрузчик классов, добавить путь к файлу / URL-адрес jar-файлов в загрузчик классов и запустить свой код. Но, видимо, здесь происходят какие-то странности.

  1. У меня есть ОДИН файл jar, который динамически загружает 4-5 вспомогательных файлов jar. Он построен на простом URLClassLoader. Я хочу сделать это, потому что могу заставить пользователя щелкнуть один файл jar и запустить приложение. Итак, есть одна вещь, о которой пользователь должен беспокоиться.

  2. При нажатии на этот файл jar приложение загружает файлы jar из файловой системы. Например. приложение загружает swt.jar (набор инструментов Eclipse для виджетов) и некоторые другие jar-файлы.

3 (но не беспокойтесь об этом), мое приложение построено на Clojure (языке динамического программирования), первое приложение, которое запускается, - это этот скрипт Clojure. Большая часть моего приложения находится в сценарии clojure.

4. Все до 1-3 работает нормально. Приложение загружается и запускается скрипт закрытия, запускается приложение SWT GUI и т. Д.

  1. Вот часть, которая не работает.

  2. У меня есть библиотека Java, назовите ее my-swt-gui.jar. Это тоже приложение SWT. По сути, это еще одно приложение с графическим интерфейсом, которое уже создано. Я пытаюсь загрузить окно из моего текущего приложения clojure / swt. По какой-то причине библиотека, ориентированная на JAVA, не распознает SWT, и я получаю ошибки noclassdef.

Вот в чем странность. И я определю, где, по моему мнению, могут быть странности.

Entitis: A. Java-ориентированный загрузчик классов. В загрузчике классов java я запускаю приложение clojure. SWT и другие файлы jar загружаются этим загрузчиком классов. B. Код, ориентированный на Clojure, который вызывается сущностью раздела a. Код clojure - это приложение с графическим интерфейсом на основе SWT. B работает нормально. C. Код Java, содержащий другое окно графического интерфейса. По какой-то причине эта библиотека не загружается, и я получаю сообщение об ошибке noclassdef.

ПРИМЕЧАНИЕ. Я ЗНАЮ ПО ФАКТУ, ЧТО класс SWT действительно находится в пути к классам, иначе я получу исключение NoClassFound. Я не получаю этого исключения. Что-то еще происходит.

Примечание: может ли это быть проблемой из-за того, что SWT включает библиотеки DLL win32? Может быть, доступ к jar-библиотеке win32 dll в первый раз работает, но с java-кодом это не работает? Но это странно. Почему SWT работал, а затем не работал?

Я не могу показать вам весь код, я надеюсь, что смогу показать вам соответствующие части.

Вот основной код загрузчика классов:

 public static final String [] JAVA_LIBRARIES = {
        "lib\\log4j-1.2.15.jar",
        "lib\\octane_commons.jar",
        "lib\\clojure.jar",
        "lib\\swt\\win32\\swt.jar",
        "lib\\jfreechart\\jcommon-1.0.15.jar",
        "lib\\jfreechart\\jfreechart-1.0.12.jar",
        "lib\\jfreechart\\jfreechart-1.0.12-swt.jar",
        "lib\\pdf\\minium.jar",
        "lib\\pdf\\tagsoup-1.2.jar",
        "lib\\pdf\\core-renderer.jar",
        "lib",
        "conf",
        "src"
    };

My classloader code is based on jetty's classloader and it works OK
but I keep get ting classnotdef errors.  Strange ones.  I can see a
clear distinction between classnotfound errors.  If the file path to
the jar is invalid then I get classnotfound, easy to detect and fix.

Here is essentially the classloader code for future reference.

Classpath classpath = new Classpath();

boolean res = classpath.addComponent(libFilePath);

/// Classloader

private class Loader extends URLClassLoader {
        String name;
        Loader(URL[] urls, ClassLoader parent) {
            super(urls, parent);
            name = "StartLoader" + Arrays.asList(urls);
        }

        public String toString() {
            return name;
        }
    }

//// Then set the classloader
//// where the URLs are the JAR libraries:
   URL [] urls = new URL[NUMBER_OF_JARS];
   for (x in urls) {
      urls[i] = new URL("THE JAR PATH");
   }

    ClassLoader parent = Thread.currentThread().getContextClassLoader();
        if (parent == null) {
            parent = Classpath.class.getClassLoader();
        }
        if (parent == null) {

            parent = ClassLoader.getSystemClassLoader();
        }
        return new Loader(urls, parent);

///////////// 

И вот так я пытался загрузить окно java swt. Я попытался распечатать как можно больше о загрузчике классов и перейти на другой загрузчик классов.

public static final void createPDFWindowShell (IStartService service, final Object shell, final Object globalClassLoader) выдает исключение {

if ((service != null) && (shell != null)) {
    synchronized(service) {
        service.runService();
        Thread.sleep(80);
    }
} else {
    System.err.println("Invalid arguments : service => " + service + " shell =>" + shell);
    return;
} // End of the if //    

final ClassLoader cl = globalClassLoader == null ? service.getClass().getClassLoader() : (ClassLoader) globalClassLoader;
System.out.println("Service Class Loader.1: " +  service.getClass().getClassLoader());  
System.out.println("Service Class Loader.2 : " +  cl);
System.out.println("-----------------");
System.out.println("[From DynaClass.1] : " + cl.loadClass("com.octane.start.services.IStartService"));
System.out.println("[From DynaClass.2] : " + cl.loadClass("org.eclipse.swt.SWT"));                      
System.out.println("[From DynaClass.3] : " + cl.loadClass("org.eclipse.swt.events.SelectionListener"));
System.out.println("-----------------");        

final Class listenerTargetClass = cl.loadClass("org.eclipse.swt.events.SelectionListener");
final ClassLoader newCl = globalClassLoader == null ? service.getClass().getClassLoader() : (ClassLoader) globalClassLoader;

// Now launch the shell //        
//final Class winClass = Class.forName("com.ca.util.gui.SimplePFSXHtmlPDFWin");
final Class winClass = cl.loadClass("com.ca.util.gui.SimplePFSXHtmlPDFWin");
final Method methodCreate = winClass.getMethod("createPDFWindowShell", new Class [] { Object.class });
methodCreate.invoke(null, shell);

}


Вот ошибка:

 [java] [INFO : Classpath Loader Check] : valid files=17 / total=17
 [java] [Classpath Loader] - thread class loader parent == false
 [java] [INFO : Classpath Loader Check] : classpath=StartLoader[file:/C%3a/Program%20Files/Java/jdk1.5.0_11/lib/tools.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/log4j-1.2.15.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/octane_commons.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/clojure.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/swt/win32/swt.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jcommon-1.0.15.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12-swt.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/gnujaxp.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/swtgraphics2d.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12-experimental.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/xercesImpl.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/minium.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/tagsoup-1.2.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/core-renderer.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/, file:/C%3a/usr/local/pfs/projects/octane/conf/, file:/C%3a/usr/local/pfs/projects/octane/src/]
 [java] Active threads : 3
 [java] class clojure.lang.Script
 [java] class org.eclipse.swt.SWT
 [java] interface org.eclipse.swt.events.SelectionListener
 [java] class org.apache.log4j.Logger
 [java] class org.xhtmlrenderer.util.XRLog
 [java] [INFO] Thread ID : Thread[Thread-3,5,main]
 [java] Service Class Loader.1: sun.misc.Launcher$AppClassLoader@92e78c
 [java] Service Class Loader.2 : StartLoader[file:/C%3a/Program%20Files/Java/jdk1.5.0_11/lib/tools.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/log4j-1.2.15.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/octane_commons.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/clojure.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/swt/win32/swt.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jcommon-1.0.15.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12-swt.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/gnujaxp.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/swtgraphics2d.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/jfreechart/jfreechart-1.0.12-experimental.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/xercesImpl.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/minium.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/tagsoup-1.2.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/pdf/core-renderer.jar, file:/C%3a/usr/local/pfs/projects/octane/lib/, file:/C%3a/usr/local/pfs/projects/octane/conf/, file:/C%3a/usr/local/pfs/projects/octane/src/]
 [java] -----------------
 [java] [From DynaClass.1] : interface com.octane.start.services.IStartService
 [java] [From DynaClass.2] : class org.eclipse.swt.SWT
 [java] [From DynaClass.3] : interface org.eclipse.swt.events.SelectionListener
 [java] -----------------
 [java] java.lang.reflect.InvocationTargetException
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 [java]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 [java]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 [java]     at java.lang.reflect.Method.invoke(Method.java:585)
 [java]     at com.octane.start.OctaneClojureScript.invokeVarInvoke(OctaneClojureScript.java:89)
 [java]     at com.octane.start.OctaneClojureScript.invokeContract(OctaneClojureScript.java:118)
 [java]     at com.octane.start.OctaneClojureScript.main(OctaneClojureScript.java:129)
 [java]     at com.octane.start.services.ClassPathLoaderService.runService(ClassPathLoaderService.java:225)
 [java]     at com.octane.start.OctaneLauncherMain.runClasspathService(OctaneLauncherMain.java:73)
 [java]     at com.octane.start.OctaneLauncherMain.main(OctaneLauncherMain.java:97)
 [java] Caused by: java.lang.NoClassDefFoundError: org/eclipse/swt/events/SelectionListener (octane_main_window.clj:0)
 [java]     at clojure.lang.Compiler.eval(Compiler.java:4543)
 [java]     at clojure.lang.Compiler.load(Compiler.java:4857)
 [java]     at clojure.lang.RT.loadResourceScript(RT.java:326)
 [java]     at clojure.lang.RT.loadResourceScript(RT.java:317)
 [java]     at clojure.lang.RT.load(RT.java:395)
 [java]     at clojure.lang.RT.load(RT.java:367)
 [java]     at clojure.core$load__5058$fn__5061.invoke(core.clj:3734)
 [java]     at clojure.core$load__5058.doInvoke(core.clj:3733)
 [java]     at clojure.lang.RestFn.invoke(RestFn.java:413)
 [java]     at clojure.core$load_one__5010.invoke(core.clj:3578)
 [java]     at clojure.core$load_lib__5031.doInvoke(core.clj:3615)
 [java]     at clojure.lang.RestFn.applyTo(RestFn.java:147)
 [java]     at clojure.core$apply__3243.doInvoke(core.clj:390)
 [java]     at clojure.lang.RestFn.invoke(RestFn.java:443)
 [java]     at clojure.core$load_libs__5043.doInvoke(core.clj:3641)
 [java]     at clojure.lang.RestFn.applyTo(RestFn.java:142)
 [java]     at clojure.core$apply__3243.doInvoke(core.clj:390)
 [java]     at clojure.lang.RestFn.invoke(RestFn.java:443)
 [java]     at clojure.core$require__5049.doInvoke(core.clj:3701)
 [java]     at clojure.lang.RestFn.invoke(RestFn.java:413)
 [java]     at clojure.lang.Var.invoke(Var.java:346)
 [java]     ... 10 more
 [java] Caused by: java.lang.NoClassDefFoundError: org/eclipse/swt/events/SelectionListener
 [java]     at java.lang.Class.getDeclaredMethods0(Native Method)
 [java]     at java.lang.Class.privateGetDeclaredMethods(Class.java:2395)
 [java]     at java.lang.Class.getMethod0(Class.java:2642)
 [java]     at java.lang.Class.getMethod(Class.java:1579)
 [java]     at com.octane.start.PDFDynamicStartWin.createPDFWindowShell(PDFDynamicStartWin.java:39)
 [java]     at octane.toolkit.octane_core_widgets$pdf_handler__2659.invoke(octane_core_widgets.clj:81)
 [java]     at octane.toolkit.octane_core_widgets$fn__2662$fn__2664.invoke(octane_core_widgets.clj:87)
 [java]     at clojure.proxy.org.eclipse.swt.events.SelectionAdapter.widgetSelected(Unknown Source)
 [java]     at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
 [java]     at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
 [java]     at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
 [java]     at org.eclipse.swt.widgets.Display.runDeferredEvents(Unknown Source)
 [java]     at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
 [java]     at octane.toolkit.octane_main_window$create_gui_window__2990.invoke(octane_main_window.clj:234)
 [java]     at octane.toolkit.octane_main_window$main_1__2994.invoke(octane_main_window.clj:246)
 [java] Processing Time : 6235
 [java]     at octane.toolkit.octane_main_window$_main__2998.doInvoke(octane_main_window.clj:250)
 [java]     at clojure.lang.RestFn.invoke(RestFn.java:402)
 [java]     at octane.toolkit.octane_main_window$eval__3001.invoke(octane_main_window.clj:259)
 [java]     at clojure.lang.Compiler.eval(Compiler.java:4532)
 [java]     ... 30 more

-


person Berlin Brown    schedule 29.06.2009    source источник


Ответы (2)


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

Без всего кода я не могу быть уверен, но подозреваю, что происходит что-то вроде следующего:

  1. "Глобальный" загрузчик классов делегирует загрузчику классов A для загрузки классов SWT.
  2. «Глобальный» загрузчик классов делегирует загрузчику классов B для загрузки кода Clojure
  3. Код Clojure пытается динамически загружать классы SWT через единственный известный ему загрузчик классов, то есть загрузчик классов B.
  4. Загрузчик классов B не знает, где их найти, и взрывается.

Это помогает?

person David Moles    schedule 30.06.2009
comment
Это вроде как, но я подозреваю, что с вашим сценарием я получу исключение ClassNotFound. Я думаю, что происходит еще кое-что. Например, мне интересно, вызывает ли проблемы использование SWT, который включает в себя DLL. Интересно, может ли DLL win32, которая включена в банку, вызвать ошибку ClassDef. - person Berlin Brown; 30.06.2009
comment
@Berlin Brown - исключение ClassNotFound возникает, когда приложение пытается загрузить класс, обычно через class.forName (). Ошибка возникает, когда виртуальная машина или загрузчик классов не может найти класс. Ответ @David Moles, скорее всего, ваша проблема, и ее нетрудно вызвать при использовании фреймворков в среде с несколькими загрузчиками классов. - person Robin; 30.06.2009
comment
Да, если посмотреть на трассировку стека, это очень похоже на описанный здесь сценарий: jroller.com/sjivan / entry / - person David Moles; 30.06.2009
comment
Я бы удостоверился, что вы исключили более простой сценарий, прежде чем переходить к рассмотрению DLL - попробуйте вручную скатать тестовый пример, который имеет те же отношения классов и разделение JAR, и посмотрите, получите ли вы ту же ошибку. - person David Moles; 30.06.2009
comment
Хорошо, я добавил код, если вам действительно интересно. (без библиотек jar). Конечно, код может быть не идеальным, но я все еще пытался использовать тот же подход. Например. Не хочу все складывать в одну банку. - person Berlin Brown; 01.07.2009
comment
Если это проблема с DLL, вы должны получить другую ошибку (я думаю, UnsatisifiedLinkError) - person John Meagher; 01.07.2009