OpenJDK10无法编译代码,同Ubuntu环境下其他JDK版本正常工作
本地Ubuntu 22.04环境下JDK10编译失败问题
问题描述
需使用已停止维护的JDK10编译遗留项目,项目在CI流水线和生产环境可正常构建,但本地Ubuntu 22.04机器上JDK10无法编译任何Java代码,触发ClassFormatError错误,而JDK8、9、11、12、17等版本均可正常工作。
复现步骤
- 编写测试用Hello World程序
Test.java:
public class Test { public static void main(String[] args) { System.out.println("Hello, world!"); } }
- 下载并解压OpenJDK10官方版本:
$ wget https://download.java.net/java/GA/jdk10/10.0.2/19aef61b38124481863b1413dce1855f/13/openjdk-10.0.2_linux-x64_bin.tar.gz $ tar -xzf openjdk-10.0.2_linux-x64_bin.tar.gz
- 验证JDK版本有效性:
$ jdk-10.0.2/bin/java -version openjdk version "10.0.2" 2018-07-17 OpenJDK Runtime Environment 18.3 (build 10.0.2+13) OpenJDK 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode) $ jdk-10.0.2/bin/javac -version javac 10.0.2
- 编译代码触发错误:
$ jdk-10.0.2/bin/javac Test.java Exception in thread "main" java.lang.ClassFormatError: Ille in class file <Unknown> at java.base/jdk.internal.misc.Unsafe.defineAnonymousClass0(Native Method) at java.base/jdk.internal.misc.Unsafe.defineAnonymousClass(Unsafe.java:1223) at java.base/java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:320) at java.base/java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:188) at java.base/java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:317) at java.base/java.lang.invoke.CallSite.makeSite(CallSite.java:330) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:250) at java.base/java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:240) at jdk.compiler/com.sun.tools.javac.code.Symtab.doEnterClass(Symtab.java:700) at jdk.compiler/com.sun.tools.javac.code.Symtab.enterClass(Symtab.java:714) at jdk.compiler/com.sun.tools.javac.code.Symtab.enterClass(Symtab.java:275) at jdk.compiler/com.sun.tools.javac.code.Symtab.<init>(Symtab.java:485) at jdk.compiler/com.sun.tools.javac.code.Symtab.instance(Symtab.java:89) at jdk.compiler/com.sun.tools.javac.comp.Attr.<init>(Attr.java:128) at jdk.compiler/com.sun.tools.javac.comp.Attr.instance(Attr.java:119) at jdk.compiler/com.sun.tools.javac.comp.Annotate.<init>(Annotate.java:109) at jdk.compiler/com.sun.tools.javac.comp.Annotate.instance(Annotate.java:84) at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.<init>(ClassReader.java:235) at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.instance(ClassReader.java:228) at jdk.compiler/com.sun.tools.javac.code.ClassFinder.<init>(ClassFinder.java:180) at jdk.compiler/com.sun.tools.javac.code.ClassFinder.instance(ClassFinder.java:173) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.<init>(JavaCompiler.java:386) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.instance(JavaCompiler.java:115) at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:291) at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:165) at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:57) at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:43)
已完成排查
- 多JDK版本验证:JDK8、9、11、12、17均能正常编译运行测试程序;同时测试Zulu发行版JDK10,问题复现,排除JDK发行版本身问题。
- 全新系统对比:在VirtualBox的全新Ubuntu22.04镜像中,JDK10可正常编译代码,排除系统版本兼容性问题,确定为本地机器配置异常。
本地系统信息
$ cat /etc/os-release PRETTY_NAME="Ubuntu 22.04.1 LTS" NAME="Ubuntu" VERSION_ID="22.04" VERSION="22.04.1 LTS (Jammy Jellyfish)" VERSION_CODENAME=jammy ID=ubuntu ID_LIKE=debian HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" UBUNTU_CODENAME=jammy $ uname --all Linux Work-Miguel 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
解决建议
1. 排查环境变量干扰
- 查看是否存在影响JDK编译的全局环境变量:
env | grep -E "(JAVA|JAVAC|TOOL_OPTIONS)" - 临时清空相关变量后重新测试:
unset JAVA_TOOL_OPTIONS JAVAC_OPTS jdk-10.0.2/bin/javac Test.java
2. 检查权限与目录问题
- 确认JDK解压目录的权限,确保当前用户拥有执行权限:
ls -ld jdk-10.0.2/ ls -l jdk-10.0.2/bin/javac - 尝试将JDK解压到临时目录(如
/tmp/jdk10),避免原目录存在隐藏的挂载或权限问题:mkdir /tmp/jdk10 tar -xzf openjdk-10.0.2_linux-x64_bin.tar.gz -C /tmp/jdk10/ /tmp/jdk10/jdk-10.0.2/bin/javac Test.java
3. 清理用户级/系统级Java配置
- 临时重命名用户目录下的Java配置文件夹:
mv ~/.java ~/.java.bak mv ~/.javac ~/.javac.bak - 检查系统级配置目录
/etc/java-*,若存在非默认配置,可临时重命名后测试。
4. 排查动态链接库冲突
- 查看javac依赖的动态库,对比正常环境的输出:
ldd jdk-10.0.2/bin/javac - 检查是否存在全局预加载的动态库:
若有内容,临时清空后测试:echo $LD_PRELOADunset LD_PRELOAD jdk-10.0.2/bin/javac Test.java
5. 使用容器隔离环境
如果以上方法均无效,可通过Docker创建隔离环境编译代码:
docker run -it --rm -v $(pwd):/work ubuntu:22.04 /bin/bash # 容器内执行以下命令: apt update && apt install -y wget wget https://download.java.net/java/GA/jdk10/10.0.2/19aef61b38124481863b1413dce1855f/13/openjdk-10.0.2_linux-x64_bin.tar.gz tar -xzf openjdk-10.0.2_linux-x64_bin.tar.gz cd /work ../jdk-10.0.2/bin/javac Test.java ../jdk-10.0.2/bin/java Test
内容的提问来源于stack exchange,提问作者Miguel Alorda
相关产品推荐
相关产品推荐

