PowerPoint プレゼンテーション

Similar documents
Microsoft PowerPoint ppt

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

Exam : 1z1-809-JPN Title : Java SE 8 Programmer II Vendor : Oracle Version : DEMO Get Latest & Valid 1z1-809-JPN Exam's Question and Answers 1 from Ac

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

新・明解Java入門

Java知識テスト問題

開発・運用時のガイド JDK8への移行に伴う留意点 [UNIX]

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版   None

Javaの作成の前に

(Microsoft PowerPoint - \223\306\217KJAVA\221\346\202R\224\ ppt)

開発・運用時のガイド JDK11への移行に伴う留意点

V8.1新規機能紹介記事

メディプロ1 Javaプログラミング補足資料.ppt

Microsoft PowerPoint - prog09.ppt

Microsoft PowerPoint - prog09.ppt

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版  

10/ / /30 3. ( ) 11/ 6 4. UNIX + C socket 11/13 5. ( ) C 11/20 6. http, CGI Perl 11/27 7. ( ) Perl 12/ 4 8. Windows Winsock 12/11 9. JAV

PowerPoint プレゼンテーション

SpringSecurity

PowerPoint プレゼンテーション

2

JAVA入門

JAVA とテンプレート

Prog1_10th

PowerPoint Presentation


.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

GEC-Java

intra-mart Accel Platform — 外部ソフトウェア接続モジュール 仕様書   第3版  

Java プログラミング Ⅰ 3 回目変 数 今日の講義講義で学ぶ内容 変数とは 変数の使い方 キーボード入力の仕方 変 数 変 数 一時的に値を記憶させておく機能 変数は 型 ( データ型 ) と識別子をもちます 2 型 ( データ型 ) 変数に記憶する値の種類変数の型は 記憶できる値の種類と範囲

Brekeke PBX - Version 2.1 ARSプラグイン開発ガイド

リファレンス,配列 例外処理

Javaセキュアコーディングセミナー東京 第2回 数値データの取扱いと入力値の検証 演習解説

Prog2_9th

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

Javaセキュアコーディングセミナー東京 第3回 入出力(File, Stream)と例外時の動作 演習解説

Java演習(4) -- 変数と型 --

やさしいJavaプログラミング -Great Ideas for Java Programming サンプルPDF

JavaプログラミングⅠ

JavaプログラミングⅠ

問 次の Fortran プログラムの説明及びプログラムを読んで、設問に答えよ。

JEB Plugin 開発チュートリアル 第4回

C/C++からJVMを起動します

** 平成 16 年度 FE 午後問題 Java** 示現塾プロジェクトマネージャ テクニカルエンジニア ( ネットワーク ) など各種セミナーを開催中!! 開催日 受講料 カリキュラム等 詳しくは 今すぐアクセス!! 平成 16

スライド 1

Make the Future Java FY13 PPT Template

JavaプログラミングⅠ

K227 Java 2

ただし 無作為にスレッドを複数実行すると 結果不正やデッドロックが起きる可能性がある 複数のスレッド ( マルチスレッド ) を安全に実行する ( スレッドセーフにする ) ためには 同期処理を用いるこ とが必要になる 同期処理は 予約語 synchronized で行うことができる ここでは sy

Java言語 第1回

Prog1_15th

実行時のメモリ構造\(2\) Javaスタック内のフレーム間動作

ファイナライザを理解する ~ ファイナライザに起因するトラブルを避けるために ~ 2013 年 11 月 25 日 橋口雅史 Java アプリケーションでファイナライザ (finalize() メソッド ) を使用したことがあるプログラマーは多いと思います しかし ファイナライザの仕組みや注意点につ

目的 泡立ち法を例に Comparableインターフェイスの実装 抽象クラスの利用 型パラメタの利用 比較 入替 の回数を計測

プログラミング基礎I(再)

JavaプログラミングⅠ

JavaプログラミングⅠ

JDK のインストール (2012 年 8 月時点でのバージョン ) Java の実行環境 開発環境は さまざまな企業 団体が開発 配布を行っているが 当テキストでは Java の生みの親である Sun MicroSystems 社 ( 現 Oracle 社 ) の実行環境 開発環境を使用する Ja

Prog2_9th

intra-mart Accel Platform

Microsoft PowerPoint - ●SWIM_ _INET掲載用.pptx

基本情報STEP UP演習Java対策

HCI プログラミング 8 回目ボタン チェックボックス ラジオボタン 今日の講義で学ぶ内容 ボタンとアクションイベント ボタンのカスタマイズ チェックボックスとラジオボタン ボタンとアクションイベント 1 ボタンを配置してみましょう ボタンは ラベルと同じようにフォントやその色 画像の貼り付けなど

オブジェクト指向プログラミング・同演習 5月21日演習課題

Prog2_10th

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

Microsoft Word - Android_SQLite講座_画面800×1280

ALG ppt

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

WebOTXマニュアル

Android Layout SDK プログラミング マニュアル

JavaプログラミングⅠ

untitled

JUnit 概要 2015/4/16 版今泉俊幸 2015 bbreak Systems 1

Javaプログラムの実行手順

JavaプログラミングⅠ

WebReportCafe

Javaと マルチスレッド

2 1 Web Java Android Java 1.2 6) Java Java 7) 6) Java Java (Swing, JavaFX) (JDBC) 7) OS 1.3 Java Java

デジタル表現論・第4回

2

Make the Future Java FY13 PPT Template

Javaプログラマー早期育成ドリル ~コードリーディング編~ 解答

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

Java講座

できるプログラマーを本気で育てる Java 超 Webプログラマーへの第 歩 第 2 回オブジェクト指向 テクノロジックアート 瀬 嘉秀

MISAO with WPF

Prog2_12th

Microsoft PowerPoint - chap10_OOP.ppt

Prog2_10th

PowerPoint プレゼンテーション

WTM2019SingleSignOn

3 Java 3.1 Hello World! Hello World public class HelloWorld { public static void main(string[] args) { System.out.println("Hello World");

Microsoft Word - CombB-Ex

機能紹介 : Java ゲートウェイとインターシステムズ製品

メソッドのまとめ

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

お知らせ

プレポスト【問題】


Transcription:

JDK 7 から JDK 8 に移行する際の注意点 2015 年 6 月 1 日第 1.1 版 日本電気株式会社 クラウドプラットフォーム事業部

目次 1. はじめに 2. JDK 7とJDK 8の非互換項目 3. JDK 8のチューニング 4. 参照 URL

はじめに

はじめに 背景 2015 年 4 月に Oracle Java SE Development Kit 7 (JDK 7) が EOL (End Of Life) を迎えたことを機に これからは JDK 8 を適用したシステムが増加すると過去の経験から想定しています それに合わせて弊社では 翌 5 月に JDK 8 に対応した WebOTX Application Server V9.3 をリリースしました 有償サポート版の Java SE Advanced は 今後も JDK 7 自体のメンテナンスは継続します しかし 無償で入手できるパブリック アップデート版は EOL 時点のもので強化が終了します そのため 今後 JDK に不具合が検出されたとしても それを改修した無償版が公開されることはありません このことから JDK 7 で動作するシステムには速やかに JDK 8 に移行することが求められます とは言え JDK 7 と 8 の間では完全に互換性が保たれてない場合があり このことが移行を躊躇する要因の 1 つとなっています 目的と対象読者 本資料では 新たに JDK 8 の使用を試みる利用者に対して アプリケーションの移行や運用管理における注意点について記載しています 特に JDK 8 をサポートした WebOTX Application Server V9.3 以降を導入される方にとって JDK 7 環境で動作していたアプリケーションを JDK 8 に移行させる際に有用です 前提条件 本資料は作成した 2015 年 6 月時点で最新の JDK アップデートバージョン JDK 8 Update 45 を対象としています その後にリリースされたアップデートバージョンで動作が変わる可能性がありますがご了承ください 4 NEC Corporation 2016

用語定義 パスの定義 本資料では パスの表記を としています UNIX 系の場合は を / に読み替えてください インストールディレクトリの表記 プレースホルダ ${AS_INSTALL ${domain ${JAVA_HOME 説明 WebOTXのインストールディレクトリ WebOTXのドメインディレクトリ JDKのインストールディレクトリ 5 NEC Corporation 2016

JDK 7 と JDK 8 の非互換項目

非互換項目 JDK 7 と JDK 8 の非互換項目は以下のように大きく 3 パターンに分類できます コンパイルできない DatagramPacket コンストラクタの仕様変更 (P.8) Java 言語仕様 15.21 項の厳格化 (P.9) ジェネリクスが指定された型と RAW 型の型チェックの強化 (P.11) 実行時に例外が発生 Proxy クラスの仕様変更 ~ 1 ~ (P.13) Proxy クラスの仕様変更 ~ 2 ~ (P.17) Collection インタフェースの仕様厳格化 (P.19) ソケットに割り当てるポート番号の範囲に関する仕様変更 (P.20) 制限付きパッケージの追加 (P.22) 実行結果が異なる MBean および MXBean インタフェースに関する仕様厳格化 (P.24) NumberFormat および DecimalFormat の丸め動作の修正 (P.26) WWW-Authenticate レスポンス ヘッダの仕様厳格化 (P.27) アノテーションに関する動作変更 (P.28) BigDecimal#stripTrailingZeros() の戻り値の変更 (P.30) LocaleServiceProvider#isSupportedLocale() の追加 (P.32) Windows における user.home システムプロパティ取得方法の変更 (P.34) 7 NEC Corporation 2016

DatagramPacket コンストラクタの仕様変更 コンパイルできない 条件 アプリケーション内で java.net.datagrampacket クラスを使用している場合 現象 JDK 7 では コンストラクタの一部で java.net.socketexception 例外がスローされますが JDK 8 ではスローされなくなりました 移行後の再コンパイル時に この例外を catch している箇所でコンパイルに失敗します try { DatagramPacket a = new DatagramPacket(buf, length, address); catch (SocketException e) { 対処 java.net.socketexception 例外 またはそのスーパークラスの java.io.ioexception 例外の catch 節を削除した後にコンパイルしてください 8 NEC Corporation 2016

Java 言語仕様 15.21 項の厳格化 (1/2) コンパイルできない 条件 アプリケーション内で型が異なるオブジェクトに対して == または!= を使用している場合 現象 具体的には以下の比較以外を行っている場合 数値の型 (Integer と int など ) Boolean と boolean 参照型と null JDK 7 では 下記のような異なるオブジェクトに対して == または!= を使用すると false が返却されましたが JDK 8 ではこのような比較を許容しなくなりました そのため 移行後の再コンパイル時に比較箇所でコンパイルに失敗します boolean bt = true; Object obj = new Integer(1); System.out.println(bt == obj); 9 NEC Corporation 2016

Java 言語仕様 15.21 項の厳格化 (2/2) コンパイルできない 対処 正しい型で比較するよう アプリケーションを改修してください または 下記のようにキャストにより java.lang.classcastexception 例外をスローさせ この例外を捕獲する catch 節の中で false を返すようにアプリケーションを改修してください boolean bt = true; Object obj = new Integer(1); try { System.out.println(bt == (Boolean)obj); catch (ClassCastException cce){ boolean bf = false; System.out.println(bf); 10 NEC Corporation 2016

ジェネリクスが指定された型と RAW 型の型チェックの強化 (1/2) コンパイルできない 条件 アプリケーション内で下記のようにジェネリクスを使用しており JDK 7 では警告付きでコンパイルされていた場合 現象 JDK 7 では警告付きでコンパイルされていましたが JDK 8 ではコンパイルに失敗します public static void main(string[] args) { Baz baz = new Baz(); bar(baz); static class Baz<T> { public static List<Baz<Object>> samplemethod(baz<object> param) { List<Baz<Object>> c = new ArrayList<Baz<Object>>(); c.add(param); return c; private static void bar(baz arg) { Baz element = Baz.sampleMethod(arg).get(0); 11 NEC Corporation 2016 コンパイル結果 ( 例 ) エラー : 不適合な型 : Object を Baz に変換できません : Baz element = Baz.sampleMethod(arg).get(0);

ジェネリクスが指定された型と RAW 型の型チェックの強化 (2/2) コンパイルできない 対処 下記のように RAW 型の部分に型を指定してください public static void main(string[] args) { Baz baz = new Baz(); bar(baz); static class Baz<T> { public static List<Baz<Object>> samplemethod(baz<object> param) { List<Baz<Object>> c = new ArrayList<Baz<Object>>(); c.add(param); return c; private static void bar(baz<object> arg) { Baz element = Baz.sampleMethod(arg).get(0); 12 NEC Corporation 2016

Proxy クラスの仕様変更 ~1~ (1/4) 実行時に例外が発生 条件 java.lang.reflect.proxy をスーパークラスとする動的プロキシクラスが public でないインタフェースを実装する場合 さらに そのインタフェースと同じパッケージ内に呼び出しもとが存在しない場合 現象 JDK 7 では この動的プロキシクラスの可視性は public でしたが JDK 8 では public ではなくなります そのため インタフェースと呼び出し元が同じパッケージ内に配置されていない場合に java.lang.illegalaccessexception 例外が発生します Exception in thread "main" java.lang.runtimeexception: java.lang.illegalaccessexception: Class sample2.myproxy can not access a member of class sample1.$proxy0with modifiers "public" at sample2.myproxy.createproxy(myproxy.java:36) at sample2.myproxy.<init>(myproxy.java:13) at sample1.myclass.main(myclass.java:14) 13 NEC Corporation 2016

Proxy クラスの仕様変更 ~1~ (2/4) 実行時に例外が発生 package sample1; パッケージ構成 interface MyInterface { String sayhello(string name); package sample1; class MyClass implements MyInterface{ public String sayhello( String name ) { System.out.println("hello! "+name); return "hello!"; public static void main(string[] args) throws Exception{ MyProxy p = new MyProxy(MyInterface.class); p.getproxyobject(); 14 NEC Corporation 2016

Proxy クラスの仕様変更 ~1~ (3/4) 実行時に例外が発生 package sample2; public class MyProxy implements InvocationHandler{ private Object proxy; private Class<?> targetclass = null; public MyProxy(Class<?> target) { createproxy(target); public Object getproxyobject(){ return proxy; private void createproxy(class<?> target) { targetclass = target try { Class<?> proxyclass = Proxy.getProxyClass(target.getClassLoader(), new Class[] { target ); Class h = InvocationHandler.class; Constructor constructor = proxyclass.getconstructor(h); proxy = constructor.newinstance(new Object[] { this ); catch (Exception e) { throw new RuntimeException(e); 15 NEC Corporation 2016

Proxy クラスの仕様変更 ~1~ (4/4) 実行時に例外が発生 対処 Constructor.setAccessible(true) により accessible フラグを true にしてください (a) または Proxy#newProxyInstance() を使用してインスタンスを生成してください (b) private void createproxy(class<?> target) { targetclass = target try { Class<?> proxyclass = Proxy.getProxyClass(target.getClassLoader(), new Class[] { target ); Class h = InvocationHandler.class; Constructor constructor = proxyclass.getconstructor(h); constructor.setaccessible(true); (a) // proxy = constructor.newinstance(new Object[] { this ); proxy = Proxy.newProxyInstance(target.getClassLoader(),new Class[] { target, this); (b) catch (Exception e) { throw new RuntimeException(e); 16 NEC Corporation 2016

Proxy クラスの仕様変更 ~2~ (1/2) 実行時に例外が発生 条件 アプリケーション内でコンストラクタ java.lang.reflect.proxy(invocationhandler h) を呼び出しており その引数 h が null となる可能性がある場合 現象 JDK 7 では コンストラクタ java.lang.reflect.proxy(invocationhandler h) 呼び出し時に h が null の場合でも例外は発生しませんでしたが JDK 8 では java.lang.nullpointerexception 例外がスローされます public class ProxyTest2 extends Proxy{ protected ProxyTest2(InvocationHandler h) { super(h); public static void main(string[] args) { InvocationHandler a = null; ProxyTest2 b = new ProxyTest2(a); 17 NEC Corporation 2016

Proxy クラスの仕様変更 ~2~ (2/2) 実行時に例外が発生 対処 null チェックを行ってください public class ProxyTest2 extends Proxy{ protected ProxyTest2(InvocationHandler h) { super(h); public static void main(string[] args) { InvocationHandler a = b; if ( b!= null ) { ProxyTest2 c = new ProxyTest2(b); 18 NEC Corporation 2016

Collection インタフェースの仕様厳格化 実行時に例外が発生 条件 アプリケーション内で Collection#removeAll(Collection<?> c) または Collection#retainAll(Collection<?> c) を使用し 引数に null が指定される可能性がある場合 現象 JDK 7 ではコレクション自体が空の場合は処理が続行されていましたが JDK 8 では java.lang.nullpointerexception 例外がスローされます List<String> list = new ArrayList<String>(); list.removeall(null); 対処 null チェックを行ってください List<String> list = new ArrayList<String>(); If (e!= null) { list.removeall(e); 19 NEC Corporation 2016

ソケットに割り当てるポート番号の範囲に関する仕様変更 (1/2) 実行時に例外が発生 条件 セキュリティマネージャを利用するアプリケーション内でエフェメラル範囲外のポートをソケットに割り当てている場合 (Windows の場合 エフェメラルポートは規定では 49152 番から 65535 番 ) 現象 JDK 7 では処理が続行されていましたが JDK 8 では java.security.accesscontrolexception 例外が発生します Exception in thread "main" java.security.accesscontrolexception: access denied ("java.net.socketpermission" "localhost:80" "listen,resolve") JDK 7 Update 51 以降でも同様の問題が発生します 20 NEC Corporation 2016 at java.security.accesscontrolcontext.checkpermission(accesscontrolcontext.java:457) at java.security.accesscontroller.checkpermission(accesscontroller.java:884) at java.lang.securitymanager.checkpermission(securitymanager.java:549) at java.lang.securitymanager.checklisten(securitymanager.java:1131) at java.net.serversocket.bind(serversocket.java:374)

ソケットに割り当てるポート番号の範囲に関する仕様変更 (2/2) 実行時に例外が発生 対処 ${AS_INSTALL domains WebOTXAdmin config の server.policy ファイルに以下を追加 permission java.net.socketpermission localhost:80, listen,resolve ; 参考 Derby 起動時にこの現象が発生する場合は セキュリティマネージャなしで起動するオプション -nosecuritymanager を付けることにより回避できます 21 NEC Corporation 2016

制限付きパッケージの追加 (1/2) 実行時に例外が発生 条件 セキュリティマネージャを利用するアプリケーション内で以下のパッケージを使用している場合 現象 com.sun.media.sound com.sun.corba.se JDK 7 では セキュリティマネージャを利用するアプリケーション内でこれらのパッケージを使用できていましたが JDK 8 では これらのパッケージが制限付きパッケージに追加されたため 実行時に java.security.accesscontrolexception 例外が発生します そのため JDK 8 では java.security.accesscontrolexception が発生します Exception in thread "main" java.security.accesscontrolexception: access denied ("java.lang.runtimepermission" "accessclassinpackage.com.sun.media.sound") at java.security.accesscontrolcontext.checkpermission(accesscontrolcontext.java:457) at java.security.accesscontroller.checkpermission(accesscontroller.java:884) at java.lang.securitymanager.checkpermission(securitymanager.java:549) at java.lang.securitymanager.checkpackageaccess(securitymanager.java:1564) 22 NEC Corporation 2016

制限付きパッケージの追加 (2/2) 実行時に例外が発生 対処 ${AS_INSTALL domains WebOTXAdmin config の server.policy ファイルに以下を追加 permission java.lang.runtimepermission accessclassinpackage.< パッケージ名 > ; 参考 制限付きパッケージとは java.lang.securitymanager#checkpackageaccess(string pkg) によりアクセス制御を受けるパッケージで その一覧は ${JAVA_HOME jre lib security java.security で package.access というキーに対して列挙されています アプリケーションが 制限パッケージに含まれる API を使用しているかどうかは JDK 8 以降 jdeps というコマンドを利用して調べることができます ( 使用例 ) >jdeps sample.jar sample.jar -> C: Program Files Java jdk1.8.0_45 jre lib rt.jar sample (sample.jar) -> java.io -> java.lang -> javax.ejb 23 NEC Corporation 2016

MBean および MXBean インタフェースに関する仕様厳格化 (1/2) 実行結果が異なる 条件 アプリケーション内で独自に作成した MBean または MXBean を使用している場合 現象 JDK 7 では public ではないインタフェースの公開が許容されていましたが JDK 8 では仕様に厳密に従い public でないインタフェースを公開しようとすると javax.management.notcompliantmbeanexception が発生します private static interface PrivateMBean { public int[] getints(); private static interface PrivateMXBean { public int[] getints(); public static class Private implements PrivateMXBean, PrivateMBean { public int[] getints() { return new int[]{1,2,3; 24 NEC Corporation 2016

MBean および MXBean インタフェースに関する仕様厳格化 (2/2) 実行結果が異なる 対処 public ではない MBean を公開しないよう アプリケーションを改修してください システムプロパティ jdk.jmx.mbeans.allownonpublic を指定して旧互換動作をさせることも可能です ただし 本システムプロパティは将来的に廃止されます public static interface PublicMBean { public int[] getints(); public static interface PublicMXBean { public int[] getints(); public static class Public implements PublicMXBean, PublicMBean { public int[] getints() { return new int[]{1,2,3; 25 NEC Corporation 2016

NumberFormat および DecimalFormat の丸め動作の修正 実行結果が異なる 条件 アプリケーション内で java.text.numberformat#format() あるいは java.text.decimalformat#format() を使用している場合 現象 0.8055d という値は 以下を実行することにより JDK 7 では 0.806 となりますが JDK 8 では 0.805 となります NumberFormat nf = java.text.numberformat.getinstance(); System.out.println(nf.format(0.8055d)); 対処 double 型ではなく BigDecimal 型を使用するようアプリケーションを改修してください BigDecimal bd = new java.math.bigdecimal( 0.8055 ); NumberFormat nf = java.text.numberformat.getinstance(); System.out.println(nf.format(bd)); 26 NEC Corporation 2016

WWW-Authenticate レスポンス ヘッダの仕様厳格化 実行結果が異なる 条件 アプリケーション内で Digest 認証を行っている場合 現象 JDK 7 では 下記の algorithm および qop の値が誤って引用符で囲まれていました JDK 8 では仕様に厳密に従い 引用符で囲まれなくなります そのため 認証先のサーバの実装が 引用符で囲まれることを想定している場合 Digest 認証に失敗します Digest username= " foo ", realm= " ****** ", nonce= " 1359097999996:13ed87b1b78c157232d609a099bcdb6e ", nc=00000001, uri= " /****** ", response= " b6f80b049b4b39000da79c96442e0740 ", algorithm= " MD5 ", opaque= " 3E8794E4CE80B19E5DF888D615FFBBA5 ", cnonce= " DGKKOPAFPJKCKKBDLFECINONACKFJIFNDOGKGLIO ", qop= " auth " 対処 Digest 認証に失敗する場合は 認証先のサーバを変更するか 認証先のサーバ運用者に対処を依頼してください 27 NEC Corporation 2016

アノテーションに関する動作変更 (1/2) 実行結果が異なる 条件 アプリケーションのコンパイル時にコンパイラによって合成ブリッジ メソッドが生成される場合 さらに 合成ブリッジ メソッドの生成対象となるメソッド またはメソッド内のパラメータにアノテーションを使用している場合 現象 JDK 7 では 自動生成される合成ブリッジ メソッドにアノテーションは付加されませんが JDK 8 では付加されます そのため 付加されるアノテーションによっては 実行結果に差が出る可能性があります 参考 共変戻り値 メソッドをオーバーライドした場合に 子クラスのメソッドの戻り値型に 親クラスで定義された戻り値型のサブクラスを定義すること 合成ブリッジ メソッド 共変戻り値を使った場合に コンパイラにより自動生成される 親クラスと同じ戻り値型のメソッドのこと 28 NEC Corporation 2016

アノテーションに関する動作変更 (2/2) 実行結果が異なる abstract class T<A, B> { B m(a a) { return null; class AnnotationTest extends T<Integer, Integer> { @MethodAnnotation Integer m(@paramannotation Integer i) { return i; public class VisibilityChange extends AnnotationTest { クラスファイル ( 抜粋 ) java.lang.object m(java.lang.object); descriptor: (Ljava/lang/Object;)Ljava/lang/Object; flags: ACC_BRIDGE, ACC_SYNTHETIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: checkcast #2 // class java/lang/integer 5: invokevirtual #3 // Method m:(ljava/lang/integer;)ljava/lang/integer; 8: areturn LineNumberTable: line 22: 0 RuntimeVisibleAnnotations: 0: #16() RuntimeVisibleParameterAnnotations: parameter 0: 0: #18() jdk1.8.0_45 でコンパイル #16 : MethodAnnotation に対応 #18 : ParamAnnotation に対応 JDK 8 で追加された箇所 対処 実行結果に差があり アプリケーションの動作に影響を及ぼす場合は アノテーションを使用しないなど アプリケーションの改修を行ってください 29 NEC Corporation 2016

BigDecimal#stripTrailingZeros() の戻り値の変更 実行結果が異なる 条件 アプリケーション内で 0 に相当する値に対して BigDecimal#stripTrailingZeros() を使用している場合 現象 JDK 7 では元の値がそのまま返されましたが JDK 8 では BigDecimal.ZERO が返されます 以下のコードを実行すると JDK 7 では 0.0000 が出力されますが JDK 8 では 0 が出力されます BigDecimal dec = new BigDecimal("0.0000"); System.out.println(dec.stripTrailingZeros()); 30 NEC Corporation 2016

BigDecimal#stripTrailingZeros() の戻り値の変更 実行結果が異なる 対処 結果の違いがアプリケーション全体に影響する場合 以下のような処理を追加してください BigDecimal dec = new BigDecimal("0.0000"); BigDecimal _dec = dec.striptrailingzeros(); if (_dec.equals(bigdecimal.zero)){ System.out.println(dec.toPlainString()); else { System.out.println(_dec); 31 NEC Corporation 2016

LocaleServiceProvider#isSupportedLocale() の追加 (1/2) 実行結果が異なる 条件 アプリケーション内で java.util.spi.localeserviceprovider を拡張したクラスを使用し その中で JDK でサポートされていない独自のロケールを定義している場合 private final static Locale YEN = new Locale("ja", "JP", "YEN"); 現象 JDK 8 では issupportedlocale(locale locale) が追加されました このメソッドの引数に独自のロケールを指定した場合 サポートされているにもかかわらず false が返されます 32 NEC Corporation 2016

LocaleServiceProvider#isSupportedLocale() の追加 (2/2) 実行結果が異なる 対処 issupportedlocale(locale locale) を下記のようにオーバーライドすることで 独自ロケールが引数に指定された場合に true を返すようにしてください public boolean issupportedlocale(locale locale) { boolean sb = super.issupportedlocale(locale); if (!sb && locale.equals(yen)){ return true; else { return false; 33 NEC Corporation 2016

Windows における user.home 取得方法の変更 実行結果が異なる 条件 Windows Server 2008 以降において アプリケーション内で System.getProperty( user.home ) を使用している さらに 以下の値が異なる場合 現象 環境変数 %USERPROFILE% の値 (a) レジストリの以下の値 (b) (HKEY_CURRENT_USER Software Microsoft Windows CurrentVersion Explor er Shell Folders Desktop) に設定されている値の一つ上のディレクトリ JDK 7 では (b) の値を取得していましたが JDK 8 では (a) の値が取得されます 対処 (b) の値を取得するには 下記のようにシステムプロパティに (b) の値を指定してください -Duser.home=<pathname> 34 NEC Corporation 2016

JDK 8 のチューニング

Permanent 領域から Metaspace 領域へ JDK 7 で Java Heap にあった Permanent 領域は JDK 8 で廃止されました JDK 7 で Permanent 領域に格納されていたデータのうち クラスに関するメタデータは JDK 8 では 新たに設けられた Metaspace と呼ばれる領域に格納されます Java Heap Native Memory JDK 7 Eden From To Old Permanent C Heap Thread Stack Java Heap Native Memory JDK 8 Eden From To Old Metaspace C Heap Thread Stack 36 NEC Corporation 2016

Metaspace 領域のチューニング パラメータ この変更に伴い メモリ領域のチューニング パラメータも変更になります 主要なチューニング パラメータは下記のとおりです -XX:MaxMetaspaceSize=<NNN> (default: 無制限 ) -XX:MetaspaceSize=<NNN> (default:12mb ~ 22MB 程度 ) これらのパラメータは 通常 指定する必要はありません ただし アプリケーション内で メモリ リークが発生した場合 ( 例えば ThreadLocal にクラスを格納していた場合 アプリケーションが配備解除されても スレッドは破棄されず クラスの情報が GC 対象にならない ) Metaspace は際限なく消費され サーバのメモリ不足を引き起こす可能性があります このような状況を未然に防ぐためには MaxMetaspaceSize を指定しておくことが有効です 37 NEC Corporation 2016

階層型コンパイルの有効化 JDK 7 では -XX:+TieredCompilation を付けることで有効化 ( 既定では無効 ) が可能な階層型コンパイルが JDK 8 では既定で有効になりました 階層型コンパイルにより サーバの起動性能が大幅に向上 階層型コンパイルとは JIT コンパイラによって行われるコンパイルにおいて サーバコンパイラとクライアントコンパイラを組み合わせて最適化を図ったコンパイル手法のことです JIT コンパイラ (Just-In-Time compiler) バイトコードをネイティブコードに書き換えるコンパイラ クライアントコンパイラ (C1) JVM の起動後 早期にコンパイルを開始 コンパイル時間が短く コンパイル時のメモリ消費量もそれほど多くない サーバコンパイラ (C2) コンパイル時間が C1 より長く メモリ消費量も多い しかし C1 より高速に動作するコードを生成する 38 NEC Corporation 2016

階層型コンパイルに関連したチューニング JIT コンパイラにより生成されたネイティブコードは コード キャッシュというメモリ領域に配置されます そのため 階層型コンパイルを行う場合 コード キャッシュサイズの既定値では すぐにキャッシュサイズがいっぱいになる可能性があります いっぱいになると JIT コンパイルが行われないため 性能が低下します コード キャッシュサイズがいっぱいになると ${AS_INSTALL domains ${domain logs server.log に以下のような警告が出力されます Java HotSpot(TM) Server VM warning: CodeCache is full. Compiler has been disabled. Java HotSpot(TM) Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize= チューニングの指針 1. -XX:+PrintCompilation を使用して 実際にコンパイルされているメソッドを出力 2. この出力が安定状態になるまで待つ 3. -XX:ReservedCodeCacheSize を使用して コード キャッシュサイズを 試しに 2 倍に増やす 4. コンパイルされたメソッド数が増加した場合 元のコード キャッシュサイズが小さすぎたと見なせる 5. 全体的なパフォーマンスの再テストを行い コード キャッシュサイズの変更が他の側面に悪影響を及ぼしていないかどうかを確認する 39 NEC Corporation 2016

コード キャッシュサイズの監視 jconsole を使用してコード キャッシュサイズを監視することができます jconsole を起動し メモリー パネルで メモリー プール Code Cache を選択してください 40 NEC Corporation 2016

参考 URL JDK 8 の互換性ガイド http://www.oracle.com/technetwork/jp/java/javase/overview/8-compatibility-guide-2156366- ja.html JDK 8 リリース ノート http://www.oracle.com/technetwork/jp/java/javase/overview/8train-relnotes-latest-2153846- ja.html Java HotSpot VM コード キャッシュについて http://www.oracle.com/webfolder/technetwork/jp/javamagazine/java-ja13-architect-evans.pdf Java Day Tokyo 2015 講演資料 Java EE アプリケーションサーバの開発現場で見た Java SE の実際 http://www.oracle.co.jp/jdt2015/pdf/3-2.pdf 41 NEC Corporation 2016