Java .class文件的最大大小是多少?

Oli*_*ire 24 java jvm specifications .class-file

.class文件是一个相当有据可查的格式定义部分和大小,因此,最大尺寸为好.

例如,一个.class文件包含一个幻数(4个字节),一个版本(4个字节),一个常量池(可变大小)等.但是可以在几个级别定义大小:你可以有65535个方法,每个方法仅限于65535个字节.

其他限制是什么?并且,如果你想使最大的.class文件成为可能,它的大小是多少?

如果需要,限制Java的答案.这意味着如果Scala或Clojure(或......)改变了某些限制,则忽略这些值.

Hol*_*ger 19

JVM规范没有强制限制类文件,因为类文件是可扩展容器,支持任意自定义属性,您甚至可以根据需要最大化它.

每个属性具有大小字段的的u4类型,因此,可以指定一个数可达2³²-1(4GiB).实际上,由于JRE API(ClassLoader方法,Instrumentation API和Unsafe)都一直使用byte[]ByteBuffer描述类文件,因此无法创建具有多于2³¹-1bytes(2GiB)的类文件的运行时类.

换句话说,即使单个自定义属性的大小也可能超过实际可加载类的大小.但是一个类可以有65535个属性,加上65535个字段,每个属性都有65535个属性,加上65535个方法,每个属性也有多达65535个属性.

如果进行数学运算,您将得出结论:仍然良好形成的类文件的理论最大值可能超过任何实际存储空间(超过2⁶⁵字节).

  • 结论是绝对正确的,我已经设法编写了一个 [程序](https://gist.github.com/apangin/7c8cfb671c8683a751fa3fdae0bbb38f),它创建了一个有效的 2,147,483,647 字节的类文件,可以成功加载到 HotSpot JVM 中,但没有一个字节多。然而,原因不是 JRE API,因为引导类加载器不使用 `byte[]` 或 `ByteBuffer` 或 `Unsafe`。但是,HotSpot `classFileParser` 也依赖 `int` 变量来处理类文件流。 (2认同)

Tag*_*eev 14

使用嵌套的finally块来制作巨大的StackMapTable非常容易,因为javac不明智地为每个嵌套级别生成单独的变量.这允许从非常简单的方法产生几兆字节,如下所示:

class A {{
  int a;
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  a=0;
  }}}}}}}}}}}}
}}
Run Code Online (Sandbox Code Playgroud)

无法添加更多嵌套级别,因为您将超出单个方法的代码大小.您还可以使用将实例初始化程序复制到每个构造函数的事实来复制它:

class A {{
  int a;
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  try {a=0;} finally {
  a=0;
  }}}}}}}}}}}}
}
A() { }
A(int a) { }
A(char a) { }
A(double a) { }
A(float a) { }
A(long a) { }
A(short a) { }
A(boolean a) { }
A(String a) { }
A(Integer a) { }
A(Float a) { }
A(Short a) { }
A(Long a) { }
A(Double a) { }
A(Boolean a) { }
A(Character a) { }

}
Run Code Online (Sandbox Code Playgroud)

使用Java 8 javac编译时,这个简单的java文件生成105,236,439字节.class-file.您还可以添加更多构造函数,但javac可能会失败OutOfMemoryError(用于javac -J-Xmx4G克服此问题).

  • 这真太了不起了。:) (2认同)