Java 非法类修饰符异常代码 0x209

标签 java eclipse

我对遗留代码库有疑问。我想用 1.6 类格式开始编译它,但是只有当我尝试运行编译后的代码时才会出现一个问题。我得到以下异常:

java.lang.ClassFormatError: 类 FooBar 0x209 中的非法类修饰符

用谷歌搜索并没有透露很多细节。根据this该问题可能与接口(interface)和实现修饰符之间的不匹配有关。当然,这一定是 1.5 中没有的一些新限制。

有问题的是类很大,并且有很多内部类和内部内部类,所以问题很难找到(我敢肯定这是内部类之一)。不用说,该类也没有任何测试,因此更改它需要格外小心并且很费力。

那么,有没有人知道关于 0x209 的任何确切信息 - 该代码的具体含义是什么?

编辑:

感谢 Arne 将我们引向了正确的方向,我们得以追踪问题并制定解决方法。根本原因尚不清楚,但现在我们可以避免它。

我们正在使用 Doug Lea 的古老 util.concurrent package在某些领域,因为某些组件在仅提供 Java 1.1 的环境中运行(是的,它 笑是没问题的,我不介意)。

同样的代码(使用并发实用程序)也被用作另一个相关软件的小组件。由于 Doug 的代码使用了一些 1.2 功能,我们还被迫修改 util.concurrent 的某些部分,使其 1.1 与 Sun 的 1.1 向后移植的集合包兼容(再也找不到这些链接了)。当我们将类格式更改为 Java 1.6 时,它以某种方式导致了这种特殊的 Eclipse 编译行为。这是导致问题的最少代码:

EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
import com.sun.java.util.collections.Map;

public class FooBar
{
    public static void main(String[] args) {
        Map.Entry e = (Map.Entry)(new ConcurrentHashMap().entrySet().iterator().next());
    }
}

用 Eclipse 编译它(编译设置为 1.6,1.5 工作正常)并尝试从 Sun 的 1.6 JRE 加载类后,问题出现了。解决方法:我们不遍历条目,而是遍历键并使用键在循环内获取值。

我们这里的设置非常奇特,难怪没有其他人碰到过这个。我终于检查了我们的构建脚本,你瞧,ant 脚本有 1.6 源和目标设置。很显然,这是特定于 Eclipse 的。

编辑 2:

我更仔细地查看了我在此处链接的 Sun 错误报告。那里的问题也与 com.sun.java.util.collections.Map.Entry 有关。这发生在 Sun 的 Javac 上。有趣。

最佳答案

代码不是代码,而是类文件字节码中类修饰符的内部表示。

可以设置八个不同的标志。

ACC_PUBLIC (0x0001)
ACC_FINAL (0x0010)
ACC_SUPER (0x0020)
ACC_INTERFACE (0x0200)
ACC_ABSTRACT (0x0400)
ACC_SYNTHETIC (0x1000)
ACC_ANNOTATION (0x2000)
ACC_ENUM (0x4000)

例如,公共(public)最终类的修饰符字节为 0x0011,公共(public)抽象类为 0x0401。

您的案例 0x209(或更好:0x0209)是非法修改器。它看起来像一个接口(interface) (0x0200),但 0x0009 部分不是规范的一部分。我猜这是一个编译器错误。

也许以下代码有助于隔离问题。它从类文件中读取类修饰符并验证修饰符是否正确。如果不是,它会打印文件名和 INVALID!!!也许您可以在您的类文件上使用此工具来隔离导致错误的类。

import java.io.*;

public class Main {

 public static void main(String[] args) throws Exception {
  String path = "D:/Arne/workspaces/IDEDeluxe/TestBytecode/bin/";
  String[] fileNames = { "Main.class" };
  for(String fileName : fileNames)
   traceFile(path, fileName);
 }

 private static void traceFile(String path, String fileName) throws FileNotFoundException, IOException {
  DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(path + fileName)));
  trace(fileName, readClassAccessFlags(stream));
  stream.close();
 }

 private static int readClassAccessFlags(DataInputStream stream) throws IOException {
  skipHeader(stream);
  skipConstantPool(stream);
  return stream.readUnsignedShort();
 }

 private static void skipHeader(DataInputStream stream) throws IOException {
  stream.readInt();
  stream.readUnsignedShort();
  stream.readUnsignedShort();
 }

 private static void skipConstantPool(DataInputStream stream) throws IOException {
  int constantPoolCount = stream.readUnsignedShort();
  for(int n = 1; n < constantPoolCount; n++) {
   int tag = stream.readUnsignedByte();
   switch(tag) {
   case 7:
    stream.readUnsignedShort();
    break;
   case 9:
   case 10:
   case 11:
    stream.readUnsignedShort();
    stream.readUnsignedShort();
    break;
   case 8:
    stream.readUnsignedShort();
    break;
   case 3:
   case 4:
    stream.readInt();
    break;
   case 5:
   case 6:
    stream.readInt();
    stream.readInt();
    break;
   case 12:
    stream.readUnsignedShort();
    stream.readUnsignedShort();
    break;
   case 1:
    stream.readUTF();
    break;
   }
  }
 }

 private static void trace(String fileName, int flags) {
  System.out.print(fileName + ": " + Integer.toHexString(flags) + " - ");
  if((flags & 0x0001) != 0)
   flags -= 0x0001;
  if((flags & 0x0010) != 0)
   flags -= 0x0010;
  if((flags & 0x0020) != 0)
   flags -= 0x0020;
  if((flags & 0x0200) != 0)
   flags -= 0x0200;
  if((flags & 0x0400) != 0)
   flags -= 0x0400;
  if((flags & 0x1000) != 0)
   flags -= 0x1000;
  if((flags & 0x2000) != 0)
   flags -= 0x2000;
  if((flags & 0x4000) != 0)
   flags -= 0x4000;
  if(flags == 0)
   System.out.println("OK!");
  else
   System.out.println("INVALID!!!");
 }

}

关于Java 非法类修饰符异常代码 0x209,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1832241/

相关文章:

java - 程序占用了我的所有资源并且未完成(可能是无限循环?)

eclipse中的JavaFX找不到外部jar

android - 此 Android SDK 需要 ADT 版本 23.0.0 或更高版本。当前版本是 22.6。请更新 ADT 到最新版本?

java - 需要提高Android的HttpClient性能

使用 Swing 和 RXTX 进行 Java RS232 通信

java - 上下文初始化失败 - Alfresco

java - 检测 TableView JavaFX 行上的双击

Java从列表中查找部分匹配的字符串

java - Glassfish 服务器在启动时显示错误

java - 线程 "main"java.lang.NoSuchMethodError : com. google.common.base.Preconditions.checkArgument 中的 Cloud Vision API 异常