Tech

Java Exception: java.lang.ClassFormatError: 「Illegal UTF8 string …」「Unknown constant tag …」

java ClassFormatError
*記事内に商品プロモーションを含む場合があります

javaで謎のエラーが発生するので調査しました。

Java Exception
java.lang.ClassFormatError: Illegal UTF8 string in constant pool in class file
java.lang.ClassFormatError: Unknown constant tag 31 in class file

調査・対応方法

1. エラー内容
2. コンパイル・実行環境で問題発生
3. JDKのバージョン
4. openJDKに切り替える方法

実行時に以下のエラーが発生

謎の ClassFormatError

java.lang.ClassFormatError: Illegal UTF8 string in constant pool in class file
java.lang.ClassFormatError: Unknown constant tag 31 in class file

1つ目のエラー

#
#
Exception in thread "main" java.lang.ClassFormatError: Illegal UTF8 string in constant pool in class file TestCase2Thread
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at TestCase2.main(TestCase2.java:38)

2つ目のエラー

#
#
Exception in thread "main" java.lang.ClassFormatError: Unknown constant tag 31 in class file TestCase4Thread
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    at TestCase4.main(TestCase4.java:39)

発生パターン

openJDKでコンパイル(ビルド)するとエラーになるようです。

コンパイル 実行 実行結果
パターン1 openJDK 1.8 openJDK 1.8 × error
パターン2 openJDK 1.8 Oracle JDK 1.8 × error
パターン3 Oracle JDK 1.8 Oracle JDK 1.8 〇 OK

Oracle JDKでコンパイルする必要がありました。

原因まで調査できていません。
もしかしたら最新のopenJdkでは修正されている可能性もあります。
openJDKをレビジョンアップ、バージョンアップで回避できるかもしれません。

確認したJDKのバージョン

openjdk

$ java -version

openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

Oracle JDK

$ java -version

java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

Oracle JDKに切り替える方法

openJDK と Oracle JDKを同時にインストール可能です。

環境変数で切り替え可能です。

export JAVA_HOME=/usr/java/latest

export PATH=${JAVA_HOME}/bin:$PATH: