JavaでGC(Garbage Collection)のログのオプションでハマる

f:id:ts0818:20210102181706j:plain

www.maff.go.jp

FAO(国際連合食糧農業機関)の報告書によると、世界では食料生産量の3分の1に当たる約13億トンの食料が毎年廃棄されています。

日本でも1年間に約612万トン(2017年度推計値)もの食料が捨てられており、これは東京ドーム5杯分とほぼ同じ量。日本人1人当たり、お茶碗1杯分のごはんの量が毎日捨てられている計算になります。

https://www.maff.go.jp/j/pr/aff/2010/spe1_01.html

⇧ ちょっと旧い情報だけども、日本の「食品ロス」の量が想像以上に多いことに驚きを隠せない、どうもボクです。

というわけで、今回もJavaの話です。

レッツトライ~。

 

JavaGC(Garbage Collector)は改良がされてるらしい

Javaもバージョンによっては、破壊的な変更が起こってるらしいですね。

ちなみに、 

blogs.oracle.com

本記事では、アプリケーションでのGCによる一時停止時間についての悩みを解消できるいくつかの方法を紹介しました。G1の改善は続くものの、ヒープ・サイズが増加し、一時停止時間が許容されにくくなるにつれて、ShenandoahやZGCなどの新しいGCによって、スケーラブルで一時停止時間の短い未来が実現することを覚えておいて損はありません。

https://blogs.oracle.com/otnjp/understanding-the-jdks-new-superfast-garbage-collectors-ja

⇧ってな感じで、将来的に「GC(Garbage Collector)」が刷新されることもあるんですかね?

他にも、 

matsumana.info

⇧ 注意事項は上記サイト様が詳しいです。 

  

JavaGC(Garbage Collector)って何?

そもそも、Javaの「GC(Garbage Collector)」って何?

Oracleさんの説明によると、

www.oracle.com

Java is a programming language and computing platform first released by Sun Microsystems in 1995.

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

Javaってのが1995年にリリースされたわけなんですが、どうも「JVMJava Virtual Machine)」の一機能ってことになるみたいですと。

Javaの構成については、

⇧ 上記サイト様が詳しいです。

JDKJava Developmet Kit)

Java Development Kit (JDK) is the software for programmers who want to write Java programs.
The JDK consists of a set of separate programs for compiling, running, and testing Java programs. So as you can see on the diagram down, JDK contains JRE and Development Tools (e.g. javac, java, etc.)

JDK = JRE + Development Tools

https://www.dev-guide.org/the-java-language-specification-api-ide-jdk-jre-and-jvm/

JREJava Runtime Enviroment)

Java Runtime Environment (JRE) is the software for consumers who want to run Java programs. It contains the API (Java libraries), Java Virtual Machine (JVM) and other files.

JRE = API + JVM + other files

https://www.dev-guide.org/the-java-language-specification-api-ide-jdk-jre-and-jvm/

 

で、「JVMJava Virtual Machine)」がどんな構成かと言うと、

⇧ ってな感じですと。「HotSpot」以外の「JVMJava Virtual Machine)」はちょっと分からんけども。

で、「GC(Garbage Collector)」ってのは、

There are three components of the JVM that are focused on when tuning performance. The heap is where your object data is stored. This area is then managed by the garbage collector selected at startup. Most tuning options relate to sizing the heap and choosing the most appropriate garbage collector for your situation. The JIT compiler a

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

Javaアプリケーションのパフォーマンスに関わってくる「JVMJava Virtual Machine)」の3つのコンポーネントの内の1つということらしい。

GC(Garbage Collector)」の超ザックリとした概要は、

⇧ 上図のような「Heap」っていうメモリ領域に配置されるオブジェクトを管理するってことかと。

オブジェクトは、

www.oracle.com

HotSpotの専門用語である"OOP"("Ordinary Object Pointer")は、オブジェクトに対する管理ポインタを表します。 

https://www.oracle.com/technetwork/jp/articles/java/compressedoops-427542-ja.html

OOP(Ordinary Object Pointer)って仕組みで「JVMJava Virtual Machine)」が管理してるってことだとは思うんだけど、「GC(Garbage Collectors)」との関係がいまいちよく分からんかったです。

 

GC(Garbage Collection)のログのオプションでハマる

JVMJava Virtual Machine)にGC(Garbage Collectors)って機能があることが分かったんだけど、 

  • GCs(Garbage Collectors)
  • GC(Garbage Collector)
  • GC(Garbage Collection)

って、GCのって略称だけだと、どっちのこと言ってるのか分からんくなるよね...

文章にするときは、略称だけじゃなく正式名称も記載するようにしたいですね。

で、「GC(Garbage Collector)」によって「GC(Garbage Collection)」が行われる際にログが取れるらしいんですが、

docs.oracle.com

Convert GC Logging Flags to Xlog

Table 2-1 Mapping Legacy Garbage Collection Logging Flags to the Xlog Configuration

https://docs.oracle.com/javase/9/tools/java.htm#GUID-BE93ABDC-999C-4CB5-A88B-1994AAAC74D5__CONVERTGCLOGGINGFLAGSTOXLOG-A5046BD1

Java 9 から結構変更があるらしい。

なので、もし、GC(Garbage Collection)のログに関するオプションとかを設定してJavaアプリケーションを実行してる場合で、Javaのバージョンアップをする場合は何かと注意が必要ですかね。

ちなみに、

github.com

⇧ 上記サイト様の「061:複合(1)」ってのを試して、GC(Garbage Collection)のログに関するオプションが変わってることに気づきました。

自分は、以下のようにEclipseJavaプロジェクトを作成して実施しました。Java 11を使ってます。

f:id:ts0818:20201229120322p:plain

Windowsのバッチだけ修正してます。

変更前

@ECHO OFF
@REM ------------------------------------
@REM java-100practices
@REM answer061.bat
@REM author: ts0818
@REM ------------------------------------

@REM 変数設定
SET CLASSPATH="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\java_one_hundred_nock\bin"
SET SOURCEPATH="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\java_one_hundred_nock\src"
SET JAVAC="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\bin\javac.exe"
SET JAVAE="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\bin\java.exe"
SET TARGET=Answer061
SET JAVA=.java
SET PACKAGE=java_one_hundred_nock.sixtyone.
SET LOG=log.txt

@REM 変数連結
SET TARGET_JAVA_STR=%TARGET%%JAVA%
SET TARGET_JAVA="%TARGET_JAVA_STR%"

SET TARGET_CLASS_STR=%PACKAGE%%TARGET%
SET TARGET_CLASS="%TARGET_CLASS_STR%"

@REM Javaのコンパイル
%JAVAC% -sourcepath %SOURCEPATH% -d %CLASSPATH% -encoding UTF-8 %TARGET_JAVA% >> %LOG% 2>&1
IF ERRORLEVEL 1 GOTO FAILURE

@REM Javaの実行
%JAVAE% -cp %CLASSPATH% -Xms8m -Xmx8m -XX:NewSize=1536k -XX:MaxNewSize=1536k -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails %TARGET_CLASS% >> %LOG% 2>&1
IF ERRORLEVEL 1 GOTO FAILURE

GOTO SUCCESS

:FAILURE
EXIT /B %ERRORLEVEL%

:SUCCESS   

⇧ 実行すると、エラーが出るんですが、

github.com

the flag PrintGCTimeStamps has been removed together with others via bug https://bugs.openjdk.java.net/browse/JDK-8145092 in JDK9. It is the implementation of JEP 271: "Unified GC Logging" (https://openjdk.java.net/jeps/271). So for JDK11 you should read the JEP and adjust your gc logging settings accordingly.

https://github.com/SAP/SapMachine/issues/554

⇧ ってことで、Java 9 でJava実行時に設定できるGC(Garbage Collection)のログのオプションが刷新されたってことみたいね。

今回は、Java 11を使ってるので、オプションを変更で。 

■変更後

@ECHO OFF
@REM ------------------------------------
@REM java-100practices
@REM answer061.bat
@REM author: ts0818
@REM ------------------------------------

@REM 変数設定
SET CLASSPATH="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\java_one_hundred_nock\bin"
SET SOURCEPATH="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\workspace\java_one_hundred_nock\src"
SET JAVAC="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\bin\javac.exe"
SET JAVAE="C:\Eclipse-2020-06\pleiades-2020-06-java-win-64bit-jre_20200702\pleiades\java\11\bin\java.exe"
SET TARGET=Answer061
SET JAVA=.java
SET PACKAGE=java_one_hundred_nock.sixtyone.
SET LOG=log.txt

@REM 変数連結
SET TARGET_JAVA_STR=%TARGET%%JAVA%
SET TARGET_JAVA="%TARGET_JAVA_STR%"

SET TARGET_CLASS_STR=%PACKAGE%%TARGET%
SET TARGET_CLASS="%TARGET_CLASS_STR%"

@REM Javaのコンパイル
%JAVAC% -sourcepath %SOURCEPATH% -d %CLASSPATH% -encoding UTF-8 %TARGET_JAVA% >> %LOG% 2>&1
IF ERRORLEVEL 1 GOTO FAILURE

@REM Javaの実行
%JAVAE% -cp %CLASSPATH% -Xms8m -Xmx8m -XX:NewSize=1536k -XX:MaxNewSize=1536k -verbose:gc -Xlog:gc* %TARGET_CLASS% >> %LOG% 2>&1
IF ERRORLEVEL 1 GOTO FAILURE

GOTO SUCCESS

:FAILURE
EXIT /B %ERRORLEVEL%

:SUCCESS   

⇧ ってな感じで、今回はJava 11を使っているので、Java実行時のGC(Garbage Collection)のログのオプションを修正する必要がありますかね。(Java 8とかであれば修正前ので動くかと)

で結果として、「java.lang.OutOfMemoryError」が起これば良いらしい。

f:id:ts0818:20210102184826p:plain

 

Javaのバージョンアップ、フレームワークのバージョンアップ、ミドルウェアのバージョンアップ、考えなければいけないことが多くて疲れますね...

今回はこのへんで。