Нахождение какого файла .class имеет плохую версию - PullRequest
3 голосов
/ 15 июня 2009

Какой самый простой способ определить, какой класс Java компилируется с «неправильным» номером версии?

У меня есть проект с большим количеством зависимостей, и где-то у меня есть класс, скомпилированный с использованием Java 1.6, где требуется Java 1.5. Во время выполнения я получаю неинформативное исключение:

[WARN] StandardWrapperValve[shell]: Servlet.service() for servlet shell threw exception
java.lang.UnsupportedClassVersionError: Bad version number in .class file
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
    at foo.Listener.(Listener.java:30)
    at foo.rpc.service.MapServiceImpl.(MapServiceImpl.java:58)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
    at java.lang.Class.newInstance0(Class.java:350)
    at java.lang.Class.newInstance(Class.java:303)
    at com.google.gwt.dev.shell.GWTShellServlet.tryGetOrLoadServlet(GWTShellServlet.java:934)
    at com.google.gwt.dev.shell.GWTShellServlet.service(GWTShellServlet.java:276)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
    at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:613)

Единственное, что я замечаю, это класс foo.Listener, для которого требуются все мои зависимости (Camel, ActiveMQ, различные в домашних библиотеках).

Лучшее, о чем я думал до сих пор, это слишком использовать opensnoop и вручную копаться в банках и классах, используя идеи из "how-can-i-find-the-target-java-version-for -a скомпилированный класс ". Есть ли лучший способ?

Ответы [ 4 ]

4 голосов
/ 15 июня 2009

Вы можете попробовать подключить отладчик с точкой останова, установленной в UnsupportedClassVersionError. (Выполнить -> Добавить точку останова исключения Java в Eclipse)

Затем можно проверить имя класса, переданное во фрейм defineClass или loadClass, когда точка останова останавливает виртуальную машину.

1 голос
/ 15 июня 2009

Попробуйте запустить с флагом -verbose в командной строке.

0 голосов
/ 30 сентября 2016

В дополнение к тому, что сказал @gibbss, вы можете использовать эту команду в командной строке.

javap -v path-to-your-class-file > output.txt

После этого откройте файл output.txt в любом редакторе. В начале файла будет информация о версии Java, используемой для компиляции этого класса. Информация, которую вы должны искать, это "java major version".
Воспользуйтесь приведенной ниже информацией, чтобы узнать версию Java, если вы знаете основную информацию.

Java 1.2 uses major version 46
Java 1.3 uses major version 47
Java 1.4 uses major version 48
Java 5 uses major version 49
Java 6 uses major version 50
Java 7 uses major version 51
Java 8 uses major version 52
0 голосов
/ 15 июня 2009

Если вы хотите обнаружить все файлы (в .jar или каталоге), которые имеют неверную версию, вы можете загрузить каждый из файлов через библиотеку байт-кода (BCEL или ASM) и проверить их номер версии

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