Eclipseでビルドした.warファイルをEC2上に配置して実行してみるとUnsupportedClassVersionErrorが出力された

#環境
###実行環境
AWS EC2 t2.micro
Amazon Linux 2
Apache Tomcat/9.0.34
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/87579f9f-7a73-aa68-6af3-dc7fee562b81.png" width=400>

```shell
# 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
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/e5848a33-8def-24b0-c501-6f2522c8d06c.png" width=550>

Windowsコマンドプロンプトで確認したJavaのバージョン

```powershell
> 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上へ配置。

```shell
[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のリスタートを行い、ステータスチェック

```shell
[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ファイルのバージョンを調べてみる

```shell
[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。[こちら](http://www.ne.jp/asahi/hishidama/home/tech/java/version.html)のサイト様によると、
JREバージョン1.8がサポートするクラスファイルバージョンは"52"とのこと。

エラーの内容が把握できました。


で、冒頭の「ビルド環境」のところで確認したJavacのバージョンは、Windows全体として確認した
（スタートメニューから開いたcmdで確認した）結果であって、Eclipse上でプロジェクトの
右クリックメニューに出てくる「コマンドプロンプト」で確認できる内容とは異なることが分かった。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/1df67507-cf9f-b69c-bd15-a35ae937b653.png" width=250>

```powershell
>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](https://mergedoc.osdn.jp/)」であり、このプラグインの中には複数バージョンのJDKが入っている。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/e9991c8e-74a2-ed69-f6fa-e8784e059e48.png" width=400>

Windowsには別口で導入したJDK1.8が存在し、パスはそちらに通っているため冒頭の確認では気づけなかった。

Eclipseでビルドする際に使用されるjavacは"11.0.5"だったために、今回の問題が発生したというわけ。
ビルドする際に使用するjavacのバージョンを"1.8"に下げることができれば今回の問題はクリアできそう。


#対処
####ビルド時のJDKバージョンを下げてみる
まずはEclipse全体の設定を確認
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/e3e54b96-eb39-06c2-ae37-5eb4969b608a.png" width=400>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/aae1eec5-a4dd-eb55-a7a5-295222ba981a.png" width=400>


プロジェクト固有設定としてバージョンを下げてみる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/5098c56e-e448-264b-360c-4d5087a42cc7.png" width=400)>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613975/e43e5ebc-4c17-c992-027c-03f6a27716af.png" width=400>

リビルドしてクラスファイルのバージョンを確認する

```powershell
>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のバージョンはしっかり確認しましょう！というお話でした。。。