#環境
###実行環境
AWS EC2 t2.micro
Amazon Linux 2
Apache Tomcat/9.0.34
# java -version
openjdk version "1.8.0_252-debug"
OpenJDK Runtime Environment (build 1.8.0_252-debug-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09-debug, mixed mode)
# javac -version
javac 1.8.0_252-debug
###ビルド環境(ローカル環境)
Windows10
Eclipse 2020-03
Windowsコマンドプロンプトで確認したJavaのバージョン
> java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
> javac -version
javac 1.8.0_231
#経緯
Webアプリ開発の勉強のため、Eclipse上で動的Webプロジェクト「example」を作成し、
サーブレット&JSPでサンプルアプリケーション「HealthCheck」を作成した。
ブラウザから「http://localhost:8080/example/HealthCheck
」で正常動作を確認。
ローカルではちゃんと動く。
EC2にデプロイして動くか確認したかったため、Eclipse上でプロジェクトごと
.warファイルにエクスポートしEC2上へ配置。
[root@ip-10-0-0-50 webapps]# ls -l /opt/apache-tomcat/webapps
total 24
drwxr-x--- 16 tomcat tomcat 4096 Apr 24 15:28 docs
drwxr-x--- 5 tomcat tomcat 123 Jun 3 12:55 example
drwxr-x--- 6 tomcat tomcat 83 Apr 24 15:28 examples
-rwxr-xr-x 1 tomcat tomcat 18910 Jun 3 12:55 example.war ←★
drwxr-x--- 5 tomcat tomcat 87 Apr 24 15:28 host-manager
drwxr-x--- 5 tomcat tomcat 103 Apr 24 15:28 manager
drwxr-x--- 3 tomcat tomcat 283 Apr 24 15:28 ROOT
[root@ip-10-0-0-50 webapps]# ls -l /opt/apache-tomcat/webapps/example
total 16
drwxr-x--- 2 tomcat tomcat 31 Jun 3 12:55 css
-rw-r----- 1 tomcat tomcat 761 May 27 00:08 Ex5_2.jsp
-rw-r----- 1 tomcat tomcat 493 May 26 23:31 formSample.jsp
-rw-r----- 1 tomcat tomcat 140 May 25 21:06 hello.html
drwxr-x--- 2 tomcat tomcat 44 Jun 3 12:55 META-INF
-rw-r----- 1 tomcat tomcat 670 May 26 18:38 sample.jsp
drwxr-x--- 5 tomcat tomcat 43 Jun 3 12:55 WEB-INF
tomcat.serviceのリスタートを行い、ステータスチェック
[root@ip-10-0-0-50 webapps]# systemctl status tomcat.service
● tomcat.service - Apache Tomcat Web Application Container
Loaded: loaded (/usr/lib/systemd/system/tomcat.service; enabled; vendor preset: disabled)
Active: active (exited) since Wed 2020-06-03 13:12:27 UTC; 1h 4min ago
Process: 4100 ExecStop=/opt/apache-tomcat/bin/shutdown.sh (code=exited, status=0/SUCCESS)
Process: 4129 ExecStart=/opt/apache-tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
Main PID: 4129 (code=exited, status=0/SUCCESS)
CGroup: /system.slice/tomcat.service
mq4144 /usr/bin/java -Djava.util.logging.config.file=/opt/apache-tomcat/conf/loggin...
Jun 03 13:12:27 ip-10-0-0-50.ap-northeast-1.compute.internal systemd[1]: Starting Apache Tomca...
Jun 03 13:12:27 ip-10-0-0-50.ap-northeast-1.compute.internal systemd[1]: Started Apache Tomcat...
Hint: Some lines were ellipsized, use -l to show in full.
#発生事象
EC2にアタッチしたEIP宛てにブラウザから接続したところ「500 – Internal Server Error」が発生
http://[EIP]:8080/example/HealthCheck
HTTPステータス 500 – Internal Server Error
タイプ: 例外報告
メッセージ: Error instantiating servlet class [servlet.HealthCheck]
説明:サーバーは予期しない条件に遭遇しました。それはリクエストの実行を妨げます。
例外:
javax.servlet.ServletException: Error instantiating servlet class [servlet.HealthCheck]
(中略)
根本原因:
java.lang.UnsupportedClassVersionError: servlet/HealthCheck has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 (unable to load class [servlet.HealthCheck])
(中略)
注意: 原因のすべてのスタックトレースは、サーバのログに記録されていますApache Tomcat/9.0.34
#調査
####Javaのバージョン差異によるもの?
この「UnsupportedClassVersionError」は、
Java仮想マシンが、クラス・ファイルの読込み中に、そのファイルのメジャー・バージョン番号と
マイナー・バージョン番号がサポートされていないと判定した場合にスローされます。
というもの。
つまり、ビルド環境と実行環境のJavaのバージョン差異が原因と考えられる。
冒頭の「環境」に記載した通りビルド環境のjavacのバージョンはjavac 1.8.0_231
実行環境のjavaのバージョンはopenjdk version "1.8.0_252-debug"
となっているため、問題無さそう・・・
コンパイルされたclassファイルのバージョンを調べてみる
[root@ip-10-0-0-50 webapps]# javap -v ./example/WEB-INF/classes/servlet/HealthCheck.class
Classfile /opt/apache-tomcat-9.0.34/webapps/example/WEB-INF/classes/servlet/HealthCheck.class
Last modified Jun 4, 2020; size 1988 bytes
MD5 checksum 83f908e6070439cc6281b73baae5306d
Compiled from "HealthCheck.java"
public class servlet.HealthCheck extends javax.servlet.http.HttpServlet
minor version: 0
major version: 55 ←★
flags: ACC_PUBLIC, ACC_SUPER
メジャーバージョンが" 55 "になってる!!
一方で、実行環境のJREバージョンは1.8。こちらのサイト様によると、
JREバージョン1.8がサポートするクラスファイルバージョンは"52"とのこと。
エラーの内容が把握できました。
で、冒頭の「ビルド環境」のところで確認したJavacのバージョンは、Windows全体として確認した
(スタートメニューから開いたcmdで確認した)結果であって、Eclipse上でプロジェクトの
右クリックメニューに出てくる「コマンドプロンプト」で確認できる内容とは異なることが分かった。
>javac -version
javac 11.0.5
D:\31_Pleiades\workspace\example>java -version
openjdk version "11.0.5" 2019-10-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.5+10, mixed mode)
これを見ると、javacのバージョンは"11.0.5"となっている。
今使っているEclipseは「Pleiades All in One Eclipse」であり、このプラグインの中には複数バージョンのJDKが入っている。
Windowsには別口で導入したJDK1.8が存在し、パスはそちらに通っているため冒頭の確認では気づけなかった。
Eclipseでビルドする際に使用されるjavacは"11.0.5"だったために、今回の問題が発生したというわけ。
ビルドする際に使用するjavacのバージョンを"1.8"に下げることができれば今回の問題はクリアできそう。
#対処
####ビルド時のJDKバージョンを下げてみる
まずはEclipse全体の設定を確認
リビルドしてクラスファイルのバージョンを確認する
>javap -v HealthCheck.class
Classfile /D:/31_Pleiades/workspace/example/build/classes/servlet/HealthCheck.class
Last modified 2020/06/04; size 1988 bytes
MD5 checksum 5deb7a7fe4b855e66be9d06261116bd6
Compiled from "HealthCheck.java"
public class servlet.HealthCheck extends javax.servlet.http.HttpServlet
minor version: 0
major version: 52 ←★成功
flags: ACC_PUBLIC, ACC_SUPER
改めて.warファイルにエクスポート→サーバ配置→アクセスしてみる
・・・
・・・
・・・
###成功!!
というわけで、Javaのバージョンはしっかり確認しましょう!というお話でした。。。