Open Libertyのjvm.optionsに設定する汎用JVM引数


## はじめに
従来のWebSphere Application Serverでは汎用JVM引数の設定で、コマンドに引数をとる場合など、つまりスペースが入る場合は、""で囲んで記述していました。

参考：https://www.ibm.com/developerworks/jp/websphere/library/was/was_tips/31.html

> 汎用JVM引数の設定を下記のように行います。
>（ア）UNIX/Linuxの場合
> -Xdump:tool:events=systhrow,filter=java/lang/OutOfMemoryError,exec="kill -9 %pid"

Libertyでも同じように設定するのだろうと思い込み、jvm.optionsに上記と同じ記述を行ったところ、OutOfMemoryErrorを起こしてもJVMがkillされませんでした。。

ので調査してみたところ、以下の情報が見つかりました。
https://www-01.ibm.com/support/docview.wss?uid=swg1PI74586

>The fix for this APAR adds the quotes back in when processing
the jvm.options file.

Libertyの場合、jvm.optionsを処理するときには単引用符を内部的に付加しているようです。そのため二重引用符をユーザーが記述すると、'"xxx"'となってしまうようです。
上記の設定の場合、「killコマンド」＆引数と認識されず、「kill -9 %pid」というコマンドとして認識されてしまい、command not foundなエラーが発生します。

## 試してみる
### 前提条件
* CentOS 7.1
* Open Liberty： 18.0.0.3
* Eclipse OpenJ9： 1.8.0_162
* OutOfMemoryErrorを起こすアプリ：[こちら](https://qiita.com/rinaxsumomo/items/d871534208e4fe5975bd)で入れた問題判別ハンズオン用アプリを使用

### ""付きの場合

１. jvm.optionsを設定する

```jvm.options
# Kill JVM when OutOfMemoryError occured.
-Xdump:tool:events=systhrow,filter=java/lang/OutOfMemoryError,exec="kill -9 %pid"
```

２. server start server1でJVMを起動し、OOMEアプリを実行しOOEM発生を確認

```server
server start server1
```

```console.log
[ERROR   ] SRVE0777E: アプリケーション・クラス 'pdpro.oome.MyOutOfMemoryErrorServlet.doTask:83' によって例外がスローされました
java.lang.OutOfMemoryError: Java ヒープ・スペース
	at pdpro.oome.MyOutOfMemoryErrorServlet.doTask(MyOutOfMemoryErrorServlet.java:83)
	at pdpro.oome.MyOutOfMemoryErrorServlet.doPost(MyOutOfMemoryErrorServlet.java:34)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1255)
	at [internal classes]

```


３. 生成されたjavacoreから、上記汎用JVM引数は読み込まれていることを確認

```javacore
0SECTION       TITLE subcomponent dump routine
NULL           ===============================
1TICHARSET     UTF-8
1TISIGINFO     Dump Event "systhrow" (00040000) Detail "java/lang/OutOfMemoryError" "Java ヒープ・スペース" received 
1TIDATETIME    Date: 2018/10/09 at 08:40:09:587
1TINANOTIME    System nanotime: 1698026317031
1TIFILENAME    Javacore filename:    /opt/IBM/OpenLiberty/wlp/usr/servers/server1/javacore.20181009.084006.4819.0005.txt
1TIREQFLAGS    Request Flags: 0x81 (exclusive+preempt)
1TIPREPSTATE   Prep State: 0x104 (exclusive_vm_access+trace_disabled)
(略)
2CIUSERARG               -Xdump:tool:events=systhrow,filter=java/lang/OutOfMemoryError,exec="kill -9 %pid"

```

４. console.logを確認すると、上記で設定したkill -9 %PIDは、コマンドが見つからずエラーになっていることがわかる

```console.log
(略)
JVMDUMP039I ダンプ・イベント "systhrow"、詳細 "java/lang/OutOfMemoryError" (場所: 2018/10/09 08:40:06) を処理しています - お待ちください。
(略)
JVMDUMP007I JVM は Tool ダンプ ('"kill -9 4819"' を使用する) を要求しています
JVMDUMP011I Tool ダンプはプロセス 5036 を作成しました
/bin/sh: kill -9 4819: コマンドが見つかりません
JVMDUMP013I ダンプ・イベント "systhrow"、詳細 "java/lang/OutOfMemoryError" を処理しました。

```

５. server statusで確認しても稼働中であることがわかる

```server
./server status server1
サーバー server1 はプロセス ID 4819 で稼働中です。
```

### ""無しの場合
１. jvm.optionsを設定する

```jvm.options
# Kill JVM when OutOfMemoryError occured.
-Xdump:tool:events=systhrow,filter=java/lang/OutOfMemoryError,exec=kill -9 %pid

```

２. 上記同様に、OOMEアプリを実行しOOEM発生

３. 生成されたjavacoreから、上記汎用JVM引数は読み込まれていることを確認

```javacore
0SECTION       TITLE subcomponent dump routine
NULL           ===============================
1TICHARSET     UTF-8
1TISIGINFO     Dump Event "systhrow" (00040000) Detail "java/lang/OutOfMemoryError" "Java ヒープ・スペース" received 
1TIDATETIME    Date: 2018/10/09 at 08:58:15:455
1TINANOTIME    System nanotime: 2783894610353
1TIFILENAME    Javacore filename:    /opt/IBM/OpenLiberty/wlp/usr/servers/server1/javacore.20181009.085808.5733.0003.txt
1TIREQFLAGS    Request Flags: 0x81 (exclusive+preempt)
1TIPREPSTATE   Prep State: 0x104 (exclusive_vm_access+trace_disabled)
(略)
2CIUSERARG               -Xdump:tool:events=systhrow,filter=java/lang/OutOfMemoryError,exec=kill -9 %pid
```

４. console.logを確認すると、上記で設定したkill -9 %PIDはエラーなく実行されていることがわかる

```console.log
(略)
JVMDUMP039I ダンプ・イベント "systhrow"、詳細 "java/lang/OutOfMemoryError" (場所: 2018/10/09 08:58:08) を処理しています - お待ちください。
(略)
JVMDUMP007I JVM は Tool ダンプ ('kill -9 5733' を使用する) を要求しています
JVMDUMP011I Tool ダンプはプロセス 5860 を作成しました
JVMDUMP039I ダンプ・イベント "systhrow"、詳細 "java/lang/OutOfMemoryError" (場所: 2018/10/09 08:58:15) を処理しています - お待ちください。

```

５. server statusで確認しても停止中であることがわかる

```server
./server status server1
サーバー server1 は稼働していません。
```


## まとめ
というわけでLibertyでは汎用JVM引数をjvm.optionsに記述するときは、コマンドの引数などでスペースがある場合でも""で囲む必要は無くなりました。
なお、WebSphere LibertyでもOpen Libertyでも上記内容は同じのようです。

## 追記
マニュアルにもいつの間にか追記されてました。。
https://www.ibm.com/support/knowledgecenter/ja/SSD28V_9.0.0/com.ibm.websphere.wlp.core.doc/ae/twlp_admin_customvars.html

>プロパティー値を引用符で囲まないでください。


## 参考
* https://www-01.ibm.com/support/docview.wss?uid=swg1PI74586
* https://www.ibm.com/developerworks/jp/websphere/library/was/was_tips/31.html