[Java] Understanding the Server JRE

原文はこちら。
https://blogs.oracle.com/java-platform-group/understanding-the-server-jre

Java SEダウンロードページには、Java Server Runtime Environment (JRE) 、Server JRE、Java Development Kit (JDK) のダウンロードリンクがあります。
Java SE download Page
http://www.oracle.com/technetwork/java/javase/downloads/index.html
[Glossary]
Java Runtime Environment (JRE)
http://www.oracle.com/technetwork/java/glossary-135216.html#jre
JDK
http://www.oracle.com/technetwork/java/glossary-135216.html#jdk
JREは、デスクトップのJavaアプリケーションを含んだ幅広いJavaプログラムを実行するために使われます。JDKはJava開発者のためのもので、これには先ほど述べたJREと、Javaプログラムの開発、コードの署名、ドキュメントの生成などのために必要なツールが含まれています。JDKはプログラムの監視やデバッグのためのツールも同梱しています。

では、Server JREはどこに収まるのでしょう。一般的なサーバーサイド・アプリケーションの観点から、JREには監視ツールや、実行時にJavaソースコードをコンパイルするアプリケーションの場合、javacはありません。一方、JDKには、システム管理者にとっては、本番環境上では必要としないようなWebブラウザ用のJavaプラグイン、自動更新エージェント、javadocなどの開発ツールといった、追加の機能が含まれています。

Server JREについて:Server JREはサーバーサイド・アプリケーション用に設計されていて、JREおよびJDKから一般的に必要な機能だけを含んでいます。Server JREには専用のインストーラがなく、簡単に使用できるように単純に圧縮されたディレクトリとして提供しています。

Server JREは全てのサーバーアプリケーションで利用できるの?
いいえ、アプリケーションがServer JREで提供しているもの以外の機能を必要としている場合、例えば追加の開発ツールやJavaFXなどが必要であれば、Server JREは当該アプリケーションにとって適切な選択ではないでしょう。

JDKがServer JREのスーパーセットなら、単純にJDKを使えばいいんじゃないの?
不要なコンポーネントを削除することで、潜在的な攻撃対象を減らし、より小さいサイズにすることでストレージやデプロイメントをより速く、より簡単にしています。Linux x64システムでは、Server JRE 8はJDK 8のフルサイズの40%程度のサイズです。

利用しているソフトウェアのベンダーがアプリケーションにJDKが必要と言っているのだけど、そのかわりにServer JREを使うことができるの?
ソフトウェアベンダーに問い合わせてJDKではなくServer JREを利用できるかどうか尋ねてください。実験できるなら、試してみるべきでしょう。アプリケーションを実行するだけであれば、JDKよりもServer JREを常にお奨めします。

Server JREに含まれているものに対して変更を提案できるの?
はい。Server JREの目的は、大部分のサーバー・アプリケーションに必要なツールを提供することですが、全てのサーバー・アプリケーション向けでないのは確かにそうです。常に含めるべきコンポーネントを再評価しています。

通常のOracle Communityチャネルを通じて、是非フィードバックをお寄せください。
Java Runtime Environment (JRE)
https://community.oracle.com/community/java/java_desktop/java_runtime_environment

[misc.] Announcing Oracle Developers on Medium

原文はこちら。
https://blogs.oracle.com/developers/announcing-oracle-developers-on-medium

技術コンテンツを熱心に読んでらっしゃるなら、Mediumに詳細な技術記事を出していることをご存知かと思います。
OracleDevs - Medium
https://medium.com/oracledevs
Oracle Cloudやその他Oracleテクノロジーに関して共有できる優れたコンテンツを有する、文字通り全ての人が、そのすばらしいコンテンツをホストするための専用の場所としてこのMediumを利用できるようにしています。medium.com/oracledevsのコンテンツは、Oracleのエンジニアやプロダクトマネージャ、コンサルタントだけでなく、Oracleテクノロジーを使ってくださる多くの外部開発者からのコンテンツを纏めたものです。

Oracle ACEエキスパート、Java Champion、先日立ち上がったDeveloper Championは自由に参加できます。

Related Content

コンテンツを見逃さないよう、是非すぐにOracleDevsをフォローしてください。先日公開されたAbhisek GuptaAbhinav ShroffDan McGhanらによる興味深い記事が見つかることでしょう。

JFrogのArtifactoryでDeveloper Cloud Serviceを使用する上での洞察、WildFly SwarmでMicroProfileアプリケーションをデプロイする方法、Node.jsアプリケーション用のデータベースサンドボックスを作成する方法、Javaアプリケーション用にRedisをデプロイする方法、Artilleryを使う方法など、手始めに5つの記事が公開されています。是非チェックしてください。

このmedium/OracleDevsに記事を出してコンテンツを広く展開したいと思っている方は、筆者(bruno dot borges at oracle dot com)までメールを送ってください。そのとき、タイトルは [Medium] Story Proposalとしておいてください。なお、公開するためには、Mediumでのユーザー名を忘れずにお知らせください。

[Database] Python cx_Oracle 6.0 RC 2 is on PyPI

原文はこちら。
https://blogs.oracle.com/opal/python-cx_oracle-60-rc-2-is-on-pypi

Python cx_Oracle は、Oracle DatabaseのPythonインターフェースです。
Anthony Tuininga がPython cx_Oracle 6.0のRelease Candidate 2(おそらく最終版)をリリースしました。PyPIからご利用いただけます。
cx_Oracle 6.0rc2
https://pypi.python.org/pypi/cx_Oracle/ 
現在プロダクションリリースに向けて全力を尽くしているので、テストを続けてください。 Issueは、GitHubやメーリングリストで報告することができます。
python-cx_Oracle Issue Tracker
https://github.com/oracle/python-cx_Oracle/issues
Mailing List: cx-oracle-users
https://sourceforge.net/projects/cx-oracle/lists/cx-oracle-users
このプレリリース版をインストールするためには、 '--pre' オプションを使ってください。
python -m pip install cx_Oracle --upgrade --pre
Oracleクライアントライブラリも必要ですが、無償のOracle Instant Clientを使うことができます。
Oracle Instant Client
http://www.oracle.com/technetwork/database/features/instant-client/
ブログの読者の方々がユーザビリティの面で筆者が気に入った部分を知ってもらえるよう、いくつかの変更点を強調したいと思います。
  • 今回のリリースでは、最新のODPI-C Oracle DB抽象化レイヤを採用しています。特に、cx_Oracleのインポート時に'UnicodeDecodeError' という混乱させるWindowsシステムメッセージが出ていた問題が解決しました。これで実際のWindowsエラーメッセージが表示され、根本的な問題点を確認することができます。
  • インストールに関する注意事項は整理されており、ドキュメントの新しいインストールの章に、トラブルシューティングのヒントとともに記載されています。
    cx_Oracle 6 Installation
    http://cx-oracle.readthedocs.io/en/latest/installation.html
  • いくつかの導入サンプルが追加され、サンプルやテストスキーマ作成スクリプトが改善されています。これらのスクリプトは、共通のファイルを参照して資格情報を設定するため、すべてのファイルを編集することなく簡単に試すことができます。
    python-cx_Oracleのsample
    https://github.com/oracle/python-cx_Oracle/tree/master/samples
cx_Oracleのリリースノートは以下からご覧いただけます。フィードバックをお待ちしています。
cx_Oracle Release Notes
http://cx-oracle.readthedocs.io/en/latest/releasenotes.html

[Database] ODPI-C 2.0.0 RC2 is released on GitHub

原文はこちら。
https://blogs.oracle.com/opal/odpi-c-200-rc2-is-released-on-github

ODPI-C 2.0.0 Release Candidate 2がGitHubからご利用頂けるようになりました。
Oracle Database Programming Interface for Drivers and Applications
https://github.com/oracle/odpi
ODPI-Cとは、Oracle Databaseドライバやユーザーアプリケーション向けに、よく使われるOracle Call Interface (OCI) の機能を簡単に利用できるようにするためのCで書かれたオープンソース・ライブラリです。
2.0.0 RC2のリリースノートは以下にあります。
ODPI-C Release notes
https://oracle.github.io/odpi/doc/releasenotes.html
バグ修正とともに、防御的なコーディングの改善やユーザー体験改善に役立つようエラーメッセージの調整を確認できます。これらは小さい修正・改善にみえるかもしれませんが、回復力 (resilience) を追加し、状況が悪化したときにユーザーに対し多くの情報を提供することで、ユーザーの利便性が向上し、問題をより迅速に解決できるようになります。
すべてのテスト担当者に多大なる感謝を申し上げたいます。もちろん、テストは終わりのない仕事です!RC2の新しいODPI-Cの機能テストに加え、Node.jsのnode-oracledbとPython cx_Oracleのテスト担当者は、機能テストとストレステストの作成と実行に忙しく取り組んできました(node-oracledbとcx_Oracleの最新バージョンではODPI-Cを使用しています!)が、いい感じです。
ODPI-Cは最初のProductionリリースに向けて進んでいますので、我々のペースにあわせ、皆さんはアプリケーションをテストしまくってください。

ODPI-Cのissueは以下から報告できます。
ODPI-C Issue Tracker
https://github.com/oracle/odpi/issues

[Database] An Easy Way to Get Graph Config in JSON for Oracle Database

原文はこちら。
https://blogs.oracle.com/bigdataspatialgraph/an-easy-way-to-get-graph-config-in-json-for-oracle-database

プロパティグラフ機能を使うにあたり、グラフの設定を正しく実施しておくことが重要です。通常のグラフ設定には、重要な情報(データベース接続情報、グラフ名、読み取り/利用対象のプロパティなど)が含まれています。
簡単なのは、グラフ設定Javaオブジェクトを提供されているJava APIを使って構築することですが、ユーザーがグラフ設定をJSON形式で生成し、Webアプリケーションを使いたいと思うことがあるかもしれません。以下はOracle Databaseのグラフ設定をJSON形式で取得する簡単な方法です。
まず、組み込みのgroovyを起動します。
[oracle@groovy/]$ sh ./gremlin-opg-rdbms.sh 
続いて、Java APIを使ってgraph configを構築します。
opg-oracledb> cfg =  GraphConfigBuilder.forPropertyGraphRdbms().setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521:orcl").setUsername("scott").setPassword("<your_password>").setName("my_graph").setMaxNumConnections(2).setLoadEdgeLabel(false).addVertexProperty("name", PropertyType.STRING, "default_name").addEdgeProperty("cost", PropertyType.DOUBLE, "1000000").build();

==>{"max_num_connections":2,"username":"scott","db_engine":"RDBMS","loading":{"load_edge_label":false},"error_handling":{},"edge_props":[{"name":"cost","default":"1000000","type":"double"}],"vertex_props":[{"name":"name","default":"default_name","type":"string"}],"name":"my_graph","jdbc_url":"jdbc:oracle:thin:@127.0.0.1:1521:orcl","attributes":{},"format":"pg","password":"<your_password>"}
これで、JSONベースのgraph configができあがりです。

[Java] How do I find what's getting promoted to my old generation?

原文はこちら。
https://blogs.oracle.com/poonam/how-do-i-find-whats-getting-promoted-to-my-old-generation

「minor/young GCでold generationに昇格しているものを見つける方法は?」という質問はたびたびいただきます。先頃、アプリケーションに対する様々な入力負荷で、old generationへ昇格されるオブジェクトの種類を知りたいというケースがありました。

少し時間がかかり、かつ面倒なやり方は、-XX:+TraceScavengeオプションを使うことです。これはデバッグバージョンにのみ含まれるオプションなので、このオプションを使用するには、HotSpot JVMのデバッグバージョンをビルドする必要があります。このオプションでは冗長な出力が生成され、young generationコレクションで処理されているすべてのオブジェクトをすべてログに記録します。

別の方法もあります。ヒープダンプからこの情報を抽出することができます。-XX:+PrintHeapAtGCオプションを付けて、収集されたヒープ境界情報とペアのminor GCの後に収集されたヒープダンプを使うと、old generationで重なっているオブジェクトを見つけることができます。

では、簡単な例を使ってどうやって実現するのかを見ていきましょう。ちょっとしたJavaプログラムを以下のオプションを付けて実行しました。
java -Xmx100m -XX:NewSize=10m -XX:+PrintGCDetails -XX:+HeapDumpBeforeFullGC -XX:+PrintHeapAtGC MemoryEater
4回のyoung generationのGCの後、old generationが一杯になって、Full GCが呼び出されました。この時点で、ヒープダンプが生成されたので、このヒープダンプを分析し、4回目のminor GCで何がold generationに昇格したのかを分析しましょう。

GCログによると、4回目のGC前後でのヒープの利用状況の詳細は以下の通りです。
{Heap before GC invocations=4 (full 0):
 PSYoungGen      total 17408K, used 17392K [0x00000000fdf00000, 0x0000000100000000, 0x0000000100000000)
  eden space 16384K, 100% used [0x00000000fdf00000,0x00000000fef00000,0x00000000fef00000)
  from space 1024K, 98% used [0x00000000fef00000,0x00000000feffc010,0x00000000ff000000)
  to   space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
 ParOldGen       total 68608K, used 34096K [0x00000000f9c00000, 0x00000000fdf00000, 0x00000000fdf00000)
  object space 68608K, 49% used [0x00000000f9c00000,0x00000000fbd4c000,0x00000000fdf00000)
 Metaspace       used 2612K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 285K, capacity 386K, committed 512K, reserved 1048576K

[GC (Allocation Failure) [PSYoungGen: 17392K->1024K(32768K)] 51488K->52816K(101376K), 0.0101398 secs] [Times: user=0.00 sys=0.00, real=0.00

Heap after GC invocations=4 (full 0):
 PSYoungGen      total 32768K, used 1024K [0x00000000fdf00000, 0x0000000100000000, 0x0000000100000000)
  eden space 31744K, 0% used [0x00000000fdf00000,0x00000000fdf00000,0x00000000ffe00000)
  from space 1024K, 100% used [0x00000000fff00000,0x0000000100000000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 68608K, used 51792K [0x00000000f9c00000, 0x00000000fdf00000, 0x00000000fdf00000)
  object space 68608K, 75% used [0x00000000f9c00000,0x00000000fce94050,0x00000000fdf00000)
 Metaspace       used 2612K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 285K, capacity 386K, committed 512K, reserved 1048576K
}

Heap Dump (before full gc): Dumping heap to java_pid31684.hprof ...
ParOldGenの'object space'の使用量の変化に着目してください。

では、Eclipse Memory Analyzer(MAT)でヒープ・ダンプ(java_pid31684.hprof)を開きましょう。でもその前に、MATがヒープダンプをロードする際に 'Keep unreachable objects' (到達不能なオブジェクトを保持)するようにMATを設定する必要があります。こうすることで、現在到達不能になっている可能性があるがJavaヒープに存在するオブジェクトも、ツールで説明および表示します。この設定を有効にするには、Window-> Preferences-> Memory Analyzerを選択します。


MATでヒープダンプを開いた後、ヒープのヒストグラムを確認しましょう。

このヒストグラムから、Javaヒープの中で最も多くの領域をbyte[]が占めていることがわかりますが、これらのbyte[]が存在する世代については何もわかりません。

上記のGCログから、old generationの開始アドレスが 0x00000000f9c00000 だったことがわかります。4回目のminor GCの前に、old generationは 0x00000000fbd4c000 まで使われ、GCの後、old generationは 0x00000000fce94050 に達しています。これはつまり、GC #4で昇格したオブジェクトが0x00000000fbd4c000 から 0x00000000fce94050 のアドレス範囲にコピーされた、ということです。以下のクエリのような式を使って、アドレス幅0x00000000fbd4c000 から 0x00000000fce94050 の範囲でold generationに存在するオブジェクトを確認することができます。
SELECT * FROM INSTANCEOF java.lang.Object t WHERE (toHex(t.@objectAddress) >= "0xfbd4c000" AND toHex(t.@objectAddress) <= "0xfce94050")

フィルタを追加して、特定のタイプのインスタンスの昇格した個数も確認できます。例えば、byte[] のフィルタを付けると、15,407個のbyte[]インスタンスが4回目のminor GCで昇格したことがわかります。

こうした簡単な手順で、old generationに何が存在するのか、young generationのサイズもしくはそれともsurvivor領域を調整し、昇格を避ける、もしくは最小限にする必要があるかどうかという点について、公正な考えを得ることができます。

[Java] HotSpot JVM throwing OOM even when there is memory available

https://blogs.oracle.com/poonam/hotspot-jvm-throwing-oom-even-when-there-is-memory-available-v2

「まだ利用可能なメモリはたんまりあるのに、「Javaアプリケーションでヒープを使い果たすのだけど。」という質問を最近もらいました。質問の詳細は、 「-Xmx1600m を指定してアプリケーションを実行しているんだけれども、ログには1600mbを完全に使っていないのにメモリを使い果たしている、と出ている」というものです。
2017-03-21T13:15:39.478+0000: 289274.599: [Full GC [PSYoungGen: 338944K->0K(425472K)] [ParOldGen: 1092073K->1055276K(1092096K)] 1431017K->1055276K(1517568K) [PSPermGen: 493920K->493889K(494592K)], 1.1709840 secs] [Times: user=5.06 sys=0.00, real=1.18 secs]
...
2017-03-21T13:19:50.517+0000: 289525.638: [Full GC [PSYoungGen: 322035K->0K(364544K)] [ParOldGen: 1092088K->1091814K(1092096K)] 1414124K->1091814K(1456640K) [PSPermGen: 494764K->494163K(495104K)], 2.5423990 secs] [Times: user=15.30 sys=0.00, real=2.54 secs]
ヒープは最大で1517568Kにまで達することがあったり、1456640Kでとどまる時もあります。なぜ`1600mb全てを使わないのでしょうか。
そうですね、端的に言うと、説明されていない領域がSurvivor領域の一つにあるということです。
説明を加えた答えは、Young世代はEdenと2個のSurvivor領域、FromとToから構成されています。これらのうち、EdenとFrom領域からのみメモリ割り当てが可能です。Toは生存オブジェクトをコピーするために使えるよう余裕を残してあって、Young世代のキャパシティをレポートする場合に省略されます。

では別の例を見てみましょう。ここでは、たくさんの領域を割当て、Javaのヒープを使い果たすようなシンプルなプログラムを実行します。以下のオプションを付けてこのプログラムを実行します。
java -XX:+PrintGCDetails -Xmx60m -XX:MaxNewSize=20m TestProgram
......
[Full GC (Ergonomics) [PSYoungGen: 15360K->15360K(17920K)] [ParOldGen: 40464K->40464K(40960K)] 55824K->55824K(58880K), [Metaspace: 2723K->2723K(1056768K)], 0.1519409 secs] [Times: user=0.50 sys=0.00, real=0.15 secs]
[Full GC (Ergonomics) [PSYoungGen: 15360K->15360K(17920K)] [ParOldGen: 40465K->40465K(40960K)] 55825K->55825K(58880K), [Metaspace: 2723K->2723K(1056768K)], 0.1196922 secs] [Times: user=0.41 sys=0.00, real=0.12 secs]
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
        at TestProgram.main(TestProgram.java:15)[Full GC (Ergonomics) [PSYoungGen: 15360K->0K(17920K)] [ParOldGen: 40468K->324K(30720K)] 55828K->324K(48640K), [Metaspace: 2748K->2748K(1056768K)], 0.0072977 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
ヒープサイズを60MBとして構成しましたが、トータルのJavaヒープのキャパシティは、上記ログを見ると58880Kしかありません(YoungGen:17920K + OldGen:40960K = Total:58880K)。60*1024K-58880K = 2560K分はどこにいったのでしょう。

では、ヒープ利用の詳細を見てみましょう。
Heap
 PSYoungGen      total 17920K, used 307K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)
  eden space 15360K, 2% used [0x00000000fec00000,0x00000000fec4ce70,0x00000000ffb00000)
  from space 2560K, 0% used [0x00000000ffb00000,0x00000000ffb00000,0x00000000ffd80000)
  to   space 2560K, 0% used [0x00000000ffd80000,0x00000000ffd80000,0x0000000100000000)
 ParOldGen       total 30720K, used 324K [0x00000000fc400000, 0x00000000fe200000, 0x00000000fec00000)
  object space 30720K, 1% used [0x00000000fc400000,0x00000000fc4511e0,0x00000000fe200000)
 Metaspace       used 2755K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 301K, capacity 386K, committed 512K, reserved 1048576K 
Capacity of PSYoungGen:17920K = eden:15360K + from:2560K
ToのSurvivor領域が含まれていないことがわかりますね。