如何在Java中编写大型静态字节数组?

时间:2012-11-22 10:21:17

标签: java arrays static jvm

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

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字节限制”。

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

我该怎么办?我可以在类外面声明数组吗?或者我应该使用带有unicode的字符串作为值128-255(例如\ 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” - which breaks the compilation of your source code。因此,您的字符串可能会出现Unicode转义符,但您必须分别使用“\ n”和“\ r”而不是\ u000a和\ u000d。将可打印字符放在字符串中而不是6字符Unicode转义表示中并没有什么坏处。

3 个答案:

答案 0 :(得分: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,这不是太糟糕且标准化很好。

答案 1 :(得分:0)

声明一个arraylist并使用静态构造函数

答案 2 :(得分:-1)

您可以使用嵌套类来存储静态数组。 这个步骤并不是最好的表现方式,但我认为你可以通过最少的代码更改来获得它。