java - 如何使用 Eclipse 在 JDK 的特定次要版本上构建 java 文件?

标签 java eclipse

如果我们看到 .class 文件结构,它会显示: 偏移量 0x04-0x05 用于 JDK 的次要版本,并且 偏移量0x06-0x07用于JDK的主要版本

我使用 eclipse 进行 java 项目开发,并为 JRE 系统库配置了 JDK1.5.0_7/JRE,类文件显示偏移量为 0x00 0x00 0x00 0x31。

如何将编译器更改为JDK1.5.0_7,以便偏移量变为0x00 0x07 0x00 0x31?

最佳答案

您无法在编译过程中自行指定次编号。

主次编号并不表示编译时使用的JDK版本。它们指示类文件格式的版本。看看这个SO answer .

类文件版本还指定能够执行该类文件的 JRE 版本。例如:如果major.minor版本是0x30.0x00,则至少需要JRE 1.4才能执行此类文件。这并非在所有情况下都意味着以前的 JRE 无法理解字节码。一旦您使用以前的 Java 版本中不存在的 Java 语言功能/运行时类,情况就不再是这样了。

一个简单的例子

public class Scratch {
    public static void main(String[] args) {
        System.out.println("foobar");
    }
}

这个简单的类可以使用与 JDK 的默认类文件版本不同的版本进行编译

下面将编译它的版本 1.4

javac -source 1.4 -target 1.4 Scratch

在这个简单的示例中,生成的字节码仍然是相同的。这个简单示例的最低可能的类文件版本是 2D.E(使用 javac -target 1.1 -source 1.2 Scratch.java 进行编译)。然后 JRE 1.1(使用 JRE 1.1.8 验证)可以运行它。

要检查版本,您可以使用此代码段

import java.io.DataInputStream;
import java.io.FileInputStream;
public class ClassFileVersion {
    // add exception handling, left out only for the example
    public static void main(String[] args) throws Exception {
        String filename = args[0];
        try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
            int magic = in.readInt();
            if (magic != 0xcafebabe) {
                System.out.println(filename + " looks not like a Java class file.");
            }
            int minor = in.readUnsignedShort();
            int major = in.readUnsignedShort();
            System.out.printf("majaor.minor: %X.%X hex  %d.%d dec%n", major, minor, major, minor);
        }
    }
}

编辑

这里有一个小片段来演示其影响。

  1. 使用当前的 JDK 编译上述 Scratch.java
  2. 运行 Scratch.class 的类文件次要版本

    Path path = Paths.get("Scratch.class");
    byte[] bytes = Files.readAllBytes(path);
    bytes[5] = 1; // it was zero before
    Files.write(path, bytes, StandardOpenOption.TRUNCATE_EXISTING)
  3. 运行更改后的类文件java Scratch执行将失败(错误消息的措辞可能有所不同,具体取决于您使用的JRE)

    java.lang.UnsupportedClassVersionError: Scratch has been compiled by a more recent
    version of the Java Runtime (class file version 52.1), this version of the Java Runtime
    only recognizes class file versions up to 52.0

如果您编译较低主要版本的源代码(-target 选项),以前的 JRE 可以执行字节码(请参阅前面提到的限制)。

假设您使用 JDK 8 javac -target 1.4 -source 1.4 Scratch.java 运行此程序。 javac 会发生不同的事情。首先,它检查 Scratch.java 是否仅使用 Java 1.4 中可用的语言功能。其次,生成的 Scratch.class 获得 Java 1.4 中使用的 Major.minor 类文件版本(30.0 十六进制)。然后您可以使用 JRE 1.4 作为 java Scratch 运行此类。

关于java - 如何使用 Eclipse 在 JDK 的特定次要版本上构建 java 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33820186/

相关文章:

java - Android 高度映射 在 OpenGL ES 2.0 中导入 OBJ 文件?

ruby-on-rails - Eclipse(Aptana插件)源代码行边框

visual-studio - Eclipse:改进调试并在mouseOver上显示变量值

java - 对于下面提到的情况,接口(interface)或枚举哪一个是更好的选择?

java.lang.UnsupportedClassVersionError : com/dicoding/javafundamental/basic/Main has been compiled by a more recent version of the Java Runtime

eclipse(设置scala环境): object apache is not a member of package org

每次启动程序时 Eclipse 索引器都会运行

java - 使用构建的存储库输出 SDK 从 Eclipse 启动 GWT 项目会响应 404

java - 为什么在这个java类中使用两个记录器实例?

java - Gradle 依赖排除不适用于传递依赖