.class文件中的错误版本号 - 如何查找它是哪个类 [英] Bad version number in .class file - how to find which class it is

查看:218
本文介绍了.class文件中的错误版本号 - 如何查找它是哪个类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我相信我已经看过这个问题上的所有其他帖子。我认为这是一个不同的问题,因为我正在寻找一种方法来确定导致问题的类。

I believe I've seen all of the other posts on this issue. I think this is a different question because I am looking for a way to determine which class is causing the problem.

我使用Maven构建我的jar。

I build my jar using Maven.

如果我要求它为Java 5构建并且我在Java 6下运行它可以正常工作。

If I ask it to build for Java 5 and I run it under Java 6 it works fine.

如果我要求它为Java 6构建并且我在Java 6下运行它可以正常工作。

If I ask it to build for Java 6 and I run it under Java 6 it works fine.

如果我要求它为Java 5构建并且我在Java下运行它5它失败了:

If I ask it to build for Java 5 and I run it under Java 5 it fails:

java.lang.RuntimeException: public static void ....main(java.lang.String[]) failed for arguments (String[]{...})
Caused by: java.lang.reflect.InvocationTargetException: 
...
Caused by: java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
    ...

我使用 Java Version Check 检查了jar并报告了它jar中为Java 5构建的所有类。

I have inspected the jar using Java Version Check and it reports all classes in the jar as built for Java 5.

我只能得出结论,它正在攻击自己的类路径,并与我的机器上的其他库/ jar连接起来不是Jav a 5.这很有可能,但是我无法访问该进程的源代码,据我所知,我无法单步进入类加载器以找出它正在加载的类。

I can only conclude that it is hacking its own classpath and linking up with some other library/jar on my machine that is not Java 5. This is quite possible but I do not have access to the source of that process and as far as I am aware I cannot single-step into the class loader to find out which class it is loading.

我可以使用哪些技巧来帮助我找出哪个类导致异常?

Are there any techniques I can use that will help me work out which class is causing the exception?

推荐答案

捕获几乎所有类定义的一种方法是使用Instrumentation API使用 Java代理。此API允许在使用之前转换所有字节代码(某些核心类除外),但是,当然,您可以使用它来提取版本号并生成报告而不更改字节代码。

One way to catch almost all class definitions is to use a Java Agent using the Instrumentation API. This API allows to transform all byte codes before they are used (with the exception of some of the core classes) but, of course, you can use it to just extract the version number and generate a report without changing the byte code.

类文件转换的一个不错的属性是,JVM将在拒绝格式错误/不支持的字节代码之前调用转换器,以便为它们提供转换的机会代码可用的东西。因此,我们将在抛出 UnsupportedClassVersionError 之前看到负责的字节代码。

One nice property of the class file transformation is that the JVM will call the transformers before rejecting malformed/ unsupported byte code to give them a chance to transform the code to something usable. So we will see the responsible byte code before the UnsupportedClassVersionError is thrown.

这是Java代理的代码完成这项工作:

Here is the code of the Java Agent which does the job:

package versioncheck;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class CheckAgent implements ClassFileTransformer
{
  public static void premain(String agentArgs, Instrumentation inst)
  {
    inst.addTransformer(new CheckAgent(), inst.isRetransformClassesSupported());
  }
  public static void agentmain(String agentArgs, Instrumentation inst)
  {
    inst.addTransformer(new CheckAgent(), inst.isRetransformClassesSupported());
  }
  private int supported;
  CheckAgent()
  {
    supported=(int)Double.parseDouble(System.getProperty("java.class.version"));
  }
  public byte[] transform(ClassLoader loader, String className,
      Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
      byte[] classfileBuffer) throws IllegalClassFormatException
  {
    int version=(classfileBuffer[6]&0xff)<<8 | (classfileBuffer[7]&0xff);
    if(version>supported)
      System.out.println(className+" v"+version+" from "
      +protectionDomain.getCodeSource());
    return null;
  }
}

然后你需要将这个类放在一个罐子里使用包含以下行的清单:

Then you need to put this class in a jar together with a manifest containing the following lines:

Premain-Class: versioncheck.CheckAgent
Agent-Class: versioncheck.CheckAgent
Can-Redefine-Classes: true

最后要做的就是添加以下参数指向启动Java应用程序的命令行: -javaagent:pathtothe.jar

And the last thing to do is to add the following parameter to command line which starts your Java application: -javaagent:pathtothe.jar

另请参阅 http://docs.oracle.com/javase/ 7 / docs / api / java / lang / instrument / package-summary.html

作为旁注,这样的Java代理也可以解决问题通过将字节代码转换(向下移植)到较低版本。但这远远超出原来的问题......

As a side note, such a Java Agent could also fix the problem by transforming (down-porting) the byte code to a lower version. But that’s far beyond the original question…

这篇关于.class文件中的错误版本号 - 如何查找它是哪个类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆