[JAVA] UnsupportedClassVersionError was output when I placed the .war file built with Eclipse on EC2 and executed it.

environment

Execution environment

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

Build environment (local environment)

Windows10 Eclipse 2020-03

Java version confirmed at Windows command prompt

> 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

Background

Create a dynamic web project "example" on Eclipse to study web application development, I created a sample application "HealthCheck" with Servlet & JSP. Confirm normal operation with " http: // localhost: 8080 / example / HealthCheck "from the browser. It works locally.

I wanted to deploy it on EC2 and see if it works, so for each project on Eclipse Export to .war file and place on 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

Restart tomcat.service and check status

[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.

Occurrence event

"500 – Internal Server Error" occurs when connecting from a browser to the EIP attached to EC2 http://[EIP]:8080/example/HealthCheck


HTTP Status 500 – Internal Server Error

Type: Exception report Message: Error instantiating servlet class [servlet.HealthCheck] Description: The server has encountered an unexpected condition. It prevents the request from being executed. Exception:  javax.servlet.ServletException: Error instantiating servlet class [servlet.HealthCheck] (Omitted) Root cause:  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]) (Omitted) Note: All stack traces of the cause are logged on the server

Apache Tomcat/9.0.34

Investigation

Is it due to Java version difference?

This "UnsupportedClassVersionError" is

While the Java virtual machine is reading a class file, the major version number of that file Thrown if it determines that the minor version number is not supported.

something like.

In other words, it is thought that the cause is the Java version difference between the build environment and the execution environment.

As mentioned in "Environment" at the beginning, the javac version of the build environment is `javac 1.8.0_231``` The java version of the execution environment is ```openjdk version "1.8.0_252-debug" ` Because it is, there seems to be no problem ...

Check the version of the compiled class file

[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

The major version is "55"! !!

On the other hand, the JRE version of the execution environment is 1.8. According to the site of here The class file version supported by JRE version 1.8 is "52".

I was able to understand the details of the error.

So, the version of Javac confirmed in the "Build environment" at the beginning was confirmed for Windows as a whole. It is the result (confirmed by cmd opened from the start menu), and it is the result of the project on Eclipse. It turned out that the contents are different from what can be confirmed at the "command prompt" that appears in the right-click menu.

>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)

Looking at this, the version of javac is "11.0.5". The Eclipse I'm using now is "Pleiades All in One Eclipse", and this plugin contains multiple versions of the JDK.

There is JDK1.8 which was introduced by another mouth in Windows, and since the path goes there, I did not notice it in the confirmation at the beginning.

The javac used when building with Eclipse was "11.0.5", so this problem occurred. If you can reduce the version of javac used when building to "1.8", this problem seems to be cleared.

Coping

Try lowering the JDK version at build time

First, check the settings of the entire Eclipse

Try lowering the version as a project-specific setting

Rebuild and check the class file version

>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 ← ★ Success
  flags: ACC_PUBLIC, ACC_SUPER

Export to .war file again → Server deployment → Try to access

・ ・ ・ ・ ・ ・ ・ ・ ・

success! !!

So be sure to check your Java version! It was a story. .. ..

Recommended Posts

UnsupportedClassVersionError was output when I placed the .war file built with Eclipse on EC2 and executed it.
I want to download a file on the Internet using Ruby and save it locally (with caution)
I installed Docker on EC2 and started it
When I call the file with Class # getResource from the jar file, it becomes Not Found and it is a crappy memorandum
When I used Slick on Rails, it competed with Turbolinks.
I opened the menu bar (option menu) on Android and saw it.
I checked because the response was strange when debugging with Tomcat 8
When I edit the properties file, it looks like garbled characters
What I did when I was addicted to the error "Could not find XXX in any of the sources" when I added a Gem and built it
Problems I was addicted to when building the digdag environment with docker
I was stuck with the handling of the time zone when formatting with SimpleDateFormat