2

我正在编写一个代码生成器,它正在重放数据包捕获期间记录的事件。

JVM 非常有限——事实证明。方法的大小不能大于 64KB。所以我添加了各种诡计来让我的代码生成器拆分 Java 方法。

但现在我有一个新问题。我正在使用一些 byte[] 数组并在我的类中将它们设为静态变量,例如:

public class myclass {
    private static byte[] byteArray = { 0x3c, 0x3f, ...
        ...
    };
    private static byte[] byteArray2 = { 0x1a, 0x20, ...
        ...
    };

    ...

    private static byte[] byteArray_n = { 0x0a, 0x0d, ...
        ...
    };        
}

现在我收到错误消息:“静态初始化程序的代码超出了 65535 字节的限制”。

我不想拥有外部文件并从那里读取数据。我想使用在单个文件中生成的代码。

我能做些什么?我可以在类外声明数组吗?或者我应该对值 128-255 使用带有 unicode 的字符串(例如 \u009c 而不是 (byte)0x9c)?还是我现在是世界上唯一一个想要使用静态初始化数据的人?

更新

我现在使用的技术是自动创建如下函数:

private byte[] byteArray_6() {
  String localString = "\u00ff\u00d8\u00ff\u00e0\u0000\u0010JFIF\u0000" +
    "(0%()(\u00ff\u00db\u0000C\u0001\u0007\u0007\u0007\n\u0008\n\u0013\n" +
    "\u0000\u00b5\u0010\u0000\u0002\u0001\u0003\u0003\u0002\u0004\u0003";
  byte[] localBuff = new byte[ localString.length() ];
  for ( int localInt = 0; localInt < localString.length(); localInt++ ) {
    localBuff[localInt] = (byte)localString.charAt(localInt);
  }
  return localBuff;
}

注意:Java 总是令人惊讶。您可能认为您可以将 0-255 范围内的每个值编码为 \u00XX(其中 XX 是 2 个字符的十六进制表示)。但你错了。Java 编译器实际上认为 \u000A 是代码中的文字“\n” -这会破坏源代码的编译。因此,您的字符串可能会被 Unicode 转义符乱扔,但您必须分别使用 "\n" 和 "\r" 而不是 \u000a 和 \u000d。并且将可打印字符原样放在字符串中而不是 6 个字符的 Unicode 转义表示中并没有什么坏处。

4

3 回答 3

4

通常,您会将数据放在文字中String,然后使用一种方法将其解码为byte[]. toByteArray()使用有限,因为 UTF-8 不会产生所有可能的字节序列,并且某些值根本不会出现。

这种技术在尝试生成小目标代码时非常流行。删除大量数组初始化代码也将有助于启动时间。

在我的头顶上:

public static byte[] toBytes(String str) {
    char[] src = str.toCharArray();
    int len = src.length;
    byte[] buff = new byte[len];
    for (int i=0; i<len; ++i) {
        buff[i] = (byte)src[i];
    }
    return buff;
}

可以使用更紧凑的方案。例如,您可以将字符串字符内容限制为 [1, 127] (出于非常糟糕的原因,0 以非规范化形式编码)。或者更复杂的东西。我相信 JDK8 将有一个用于 Base64 解码的公共 API,它还不错,而且标准化得很好。

于 2012-11-22T10:23:24.097 回答
0

声明一个数组列表并使用静态构造函数

于 2012-11-22T10:47:17.277 回答
0

您可以使用嵌套类来存储静态数组。这一步并不是执行的最佳方式,但我认为您可以通过对代码的最小更改来获得它。

于 2013-12-19T10:41:08.460 回答