アクセスカウンタ

プロフィール

ブログ名
Java etc...
ブログ紹介
Java ネタを中心にしたブログです。
help RSS

JDK8u11-b20 とか

2014/07/23 08:42
JDK8 update11 がでた時、
for Windows は build 19 だった記憶があるのだけど、
昨日みたら、build 20 になってた。
記事へブログ気持玉 / トラックバック / コメント


JDK 7u55-b14

2014/04/22 23:59
また、なんの前触れもなく 7u55-b14 が出ていますね。

Java SE Development Kit 7, Update 55(JDK 7u55-b14)

こんな文言が追加されてました。
online 32bit JRE installers and Auto Update mechanisms for the Windows, where the version string is 1.7.0_55-b14
記事へブログ気持玉 / トラックバック / コメント


Java SE 8u5, 7u55

2014/04/16 23:21
予定通り、Java SE 8u5 が出ました。さらに、Java SE 7u55 も。

リリースメモはこちら。

Java SE Development Kit 8, Update 5(JDK 8u5-b13)
Java SE Development Kit 7, Update 55(JDK 7u55-b13)

Java Plugin が Windows 8.1/IE11 拡張保護モードで動作するようになったみたいです。ただ、64bit Windows OS での拡張保護モードでは、32bit と 64bit の JRE をインストールする必要があるようです。

そして、有償の Java SE Advanced and Java SE Support の情報はこちら。

Java SE Advanced/Java SE Support 7u55(-b31)
Java SE Advanced/Java SE Support 6u75(-b13)
Java SE Advanced/Java SE Support 5.0u65(-b10)
記事へブログ気持玉 / トラックバック / コメント


Java SE 8 リリース !!

2014/03/21 22:28
JDK8 がリリースされた。build は b132 らしい。
http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html

そして、すでに 8u20 Build b05 も Early Access 版として公開されている。
https://jdk8.java.net/download.html

8u20 は 8 月にリリースとなるらしい。
http://openjdk.java.net/projects/jdk8u/releases/8u20.html

さらに、7u60 も Early Access で b11 が公開されていた(3/19 なので、8 が出てすぐか)。
https://jdk7.java.net/download.html
記事へブログ気持玉 / トラックバック / コメント


Lambda 式をデバックしたら(2)

2014/03/18 00:30
Lambda 式 を jdb でデバッグしたら、どうなるか ... やってみた。

ソースコードは、JavaOne 2013 San Francisco のセッション CON2055] Programming with Lambda Expressions in Java で使われていたコードを使っています。

1. import java.util.*;
2.
3. public class LambdaTest2 {
4.   static public void main(String args[]) {
5.     List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
6.
7.     System.out.println(
8.      numbers.stream()
9.       .filter(number -> {
10.          System.out.println("isGreaterThan3 " + number);
11.          return number > 3;
12.       })
13.       .filter(number -> {
14.          System.out.println("isEven " + number);
15.          return number % 2 == 0;
16.       })
17.       .map(number -> {
18.          System.out.println("doubleIt " + number);
19.          return number * 2;
20.       })
21.       .findFirst()
22.     );
23.   }
24.
}


とりあえず、これを実行した時の結果は、こうなる。

isGreaterThan3 1
isGreaterThan3 2
isGreaterThan3 3
isGreaterThan3 4
isEven 4
doubleIt 4
Optional[8]


いまどき、jdb でデバッグしてみる。main メソッドの入口で、いったん止める。

jdb LambdaTest2
jdbの初期化中...
> stop in LambdaTest2.main
遅延したブレークポイントLambdaTest2.main。
クラスがロードされた後に設定されます。
> run
LambdaTest2の実行
捕捉されないjava.lang.Throwableの設定
遅延した捕捉されないjava.lang.Throwableの設定
>
VMが開始されました: 遅延したブレークポイントLambdaTest2.mainの設定

ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=5 bci=0
5 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);


そして、7 行目の System.out.println 呼び出し、そして、stream API を呼び出している箇所と、さらに各ラムダ式の最初の行(System.out.println呼び出し)にブレークポイントを設定する。

main[1] stop at LambdaTest2:7
ブレークポイントLambdaTest1:7の設定
main[1] stop at LambdaTest1:9
ブレークポイントLambdaTest1:9の設定
main[1] stop at LambdaTest1:10
ブレークポイントLambdaTest1:10の設定
main[1] stop at LambdaTest1:13
ブレークポイントLambdaTest1:13の設定
main[1] stop at LambdaTest1:14
ブレークポイントLambdaTest1:14の設定
main[1] stop at LambdaTest1:17
ブレークポイントLambdaTest1:17の設定
main[1] stop at LambdaTest1:18
ブレークポイントLambdaTest1:18の設定
main[1] stop at LambdaTest1:21
ブレークポイントLambdaTest1:21の設定


cont の繰り返しを行うと、次のようになる。

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=7 bci=52
7 System.out.println(

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=9 bci=66
9 .filter(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=13 bci=76
13 .filter(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=17 bci=86
17 .map(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=21 bci=91
21 .findFirst()

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$0()、行=10
bci=0
10 System.out.println("isGreaterThan3 " + number);

main[1] cont
> isGreaterThan3 1
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

main[1]
cont
> isGreaterThan3 2
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

main[1] cont
> isGreaterThan3 3

ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

main[1] cont
> isGreaterThan 4
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$1()、行=14 bci=0
14 System.out.println("isEven " + number);

main[1] cont
> isEven 4

ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$2()、行=18 bci=0
18 System.out.println("doubleIt " + number);

main[1] cont
> doubleIt 4
Optional[8]

アプリケーションが終了しました


出力を見てもらうとわかるが、最後の doubleIt の呼び出しがあってから、isGreaterThan3 が何度か出力され、isEven が出力される。いわゆる、遅延評価っていうのが行われていることがわかる。

次に、このコードの 6 行目を stream() から parallelStream() に変えてみる。

7.     System.out.println(
8.      numbers.parallelStream()
9.       .filter(number -> {
10.          System.out.println("isGreaterThan3 " + number);
11.          return number > 3;
12.       })
13.       .filter(number -> {
14.          System.out.println("isEven " + number);
15.          return number % 2 == 0;
16.       })
17.       .map(number -> {
18.          System.out.println("doubleIt " + number);
19.          return number * 2;
20.       })
21.       .findFirst()
22.     );


単純に実行すると、次のようになる。

isGreaterThan3 4
isGreaterThan3 1
isGreaterThan3 5
isGreaterThan3 3
isGreaterThan3 2
isGreaterThan3 6
isEven 5
isEven 4
isEven 6
doubleIt 4
doubleIt 6
Optional[8]


そして、同じように jdb でデバッグ実行してみる。パラレル実行されるので、デバッガで実行した時の出力の順序と通常実行時の結果(上の)順序と同じになるとは限らない。

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=7 bci=52
7 System.out.println(

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=9 bci=66
9 .filter(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=13 bci=76
13 .filter(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=17 bci=86
17 .map(number -> {

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.main()、行=21 bci=91
21 .findFirst()

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$0()、行=10
bci=0
10 System.out.println("isGreaterThan3 " + number);

main[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

ForkJoinPool.commonPool-worker-2[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-1", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

ForkJoinPool.commonPool-worker-1[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-3", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

ForkJoinPool.commonPool-worker-3[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-5", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

ForkJoinPool.commonPool-worker-5[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-4", LambdaTest2.lambda$main$0()、行=10 bci=0
10 System.out.println("isGreaterThan3 " + number);

ForkJoinPool.commonPool-worker-4[1] cont
> isGreaterThan3 4
isGreaterThan3 5
isGreaterThan3 3
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$1()、行=14 bci=0
14 System.out.println("isEven " + number);

main[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-4", LambdaTest2.lambda$main$1()、行=14 bci=0
14 System.out.println("isEven " + number);

ForkJoinPool.commonPool-worker-4[1] cont
> isGreaterThan3 1
isGreaterThan3 2
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest2.lambda$main$1()、行=14 bci=0
isGreaterThan3 6
isEven 5
14 System.out.println("isEven " + number);

ForkJoinPool.commonPool-worker-2[1] cont
> isEven 4
isEven 6
ヒットしたブレークポイント: "スレッド=main", LambdaTest2.lambda$main$2()、行=18 bci=0
18 System.out.println("doubleIt " + number);

main[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest2.lambda$main$2()、行=18 bci=0
18 System.out.println("doubleIt " + number);

ForkJoinPool.commonPool-worker-2[1] cont
> doubleIt 6
doubleIt 4
Optional[8]

アプリケーションが終了しました


先の例のように、stream() を利用した場合は main スレッド上でブレークポイントにヒットするが、parallelStream() を使うと、ForkJoinPool の wroker スレッド上でブレークポイントにヒットしている。

いくつ worker スレッドが使われるかは、worker スレッド上で停止している時に threads を実行してみるとよい。

main[1] threads
グループsystem:
(java.lang.ref.Reference$ReferenceHandler)0x169 Reference Handler は条件を待機中です
(java.lang.ref.Finalizer$FinalizerThread)0x168 Finalizer は条件を待機中です
(java.lang.Thread)0x167 Signal Dispatcher は実行中です
(java.lang.Thread)0x166 Attach Listener は実行中です
グループmain:
(java.lang.Thread)0x1 main は実行中です(ブレークポイント)
(java.util.concurrent.ForkJoinWorkerThread)0x274 ForkJoinPool.commonPool-worker-1はモニター内で待機中です
(java.util.concurrent.ForkJoinWorkerThread)0x275 ForkJoinPool.commonPool-worker-2はモニター内で待機中です
(java.util.concurrent.ForkJoinWorkerThread)0x279 ForkJoinPool.commonPool-worker-3はモニター内で待機中です
(java.util.concurrent.ForkJoinWorkerThread)0x27b ForkJoinPool.commonPool-worker-4は実行中です
(java.util.concurrent.ForkJoinWorkerThread)0x27a ForkJoinPool.commonPool-worker-5は実行中です
(java.util.concurrent.ForkJoinWorkerThread)0x27c ForkJoinPool.commonPool-worker-6は条件を待機中です
(java.util.concurrent.ForkJoinWorkerThread)0x27f ForkJoinPool.commonPool-worker-7は実行中です


ということで、遅延評価されていることと、ForkJoin が使われていることがわかった。

最後に、ロードされているクラスを見てみる。classes の出力の先頭を見ると、LambdaTest2 のネストクラスがいくつか見られる。

main[1] classes
** クラス・リスト **
LambdaTest2
LambdaTest2$$Lambda$1.606548741
LambdaTest2$$Lambda$2.1389647288
LambdaTest2$$Lambda$3.1634198
:
:


これらのクラスは Lambda 式が内部クラスになる時のクラス名であり、これらのクラスは実行時に生成される。コンパイル時に .class というクラスファイルは生成されない。

たとえば、内部クラスの LambdaTest2$$Lambda$3.1634198 の情報を見てみると、java.util.funciton.Function を実装したクラスであり、いくつかのメソッドが定義されていることがわかる。

main[1] class LambdaTest2$$Lambda$3.1634198
クラス: LambdaTest2$$Lambda$3.1634198
拡張します: java.lang.Object
実装します: java.util.function.Function

main[1] methods LambdaTest2$$Lambda$3.1634198
** メソッド・リスト **
LambdaTest2$$Lambda$3.1634198 <init>()
LambdaTest2$$Lambda$3.1634198 apply(java.lang.Object)
java.lang.Object <init>()
java.lang.Object registerNatives()
java.lang.Object getClass()
java.lang.Object hashCode()
java.lang.Object equals(java.lang.Object)
java.lang.Object clone()
java.lang.Object toString()
java.lang.Object notify()
java.lang.Object notifyAll()
java.lang.Object wait(long)
java.lang.Object wait(long, int)
java.lang.Object wait()
java.lang.Object finalize()
java.lang.Object <clinit>()
java.util.function.Function apply(java.lang.Object)
java.util.function.Function compose(java.util.function.Function)
java.util.function.Function andThen(java.util.function.Function)
java.util.function.Function identity()
java.util.function.Function lambda$identity$7(java.lang.Object)
java.util.function.Function lambda$andThen$6(java.util.function.Function, java.lang.Object)
java.util.function.Function lambda$compose$5(java.util.function.Function, java.lang.Object)

記事へブログ気持玉 / トラックバック / コメント


Lambda/Stream API をデバッグしたら ...

2014/03/13 00:42
Lambda 式や stream API のソースコードを jdb でデバッグしたら、どうなるか ... やってみた。

ソースコードは、JavaOne 2013 San Francisco のセッション CON2055] Programming with Lambda Expressions in Java で使われていたコード。

1. import java.util.*:
2.
3. public class LambdaTest1 {
4.   static public void main(String args[]) {
5.     List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
6.
7.     System.out.println(
8.      numbers.stream()
9.       .filter(LambdaTest1::isGreaterThan3)
10.       .filter(LambdaTest1::isEven)
11.       .map(LambdaTest1::doubleIt)
12.       .findFirst()
13.     );
14.   }
15.
16.   public static boolean isGreaterThan3(int number) {
17.     System.out.println("isGreaterThan3 " + number);
18.     return number > 3;
19.   }
20.
21.   public static boolean isEven(int number) {
22.     System.out.println("isEven " + number);
23.     return number % 2 == 0;
24.   }
25.
26.   public static int doubleIt(int number) {
27.     System.out.println("doubleIt " + number);
28.     return number * 2;
29.   }
30. }


とりあえず、これを実行した時の結果は、こうなる。

isGreaterThan3 1
isGreaterThan3 2
isGreaterThan3 3
isGreaterThan3 4
isEven 4
doubleIt 4
Optional[8]


いまどき、jdb でデバッグしてみる ...
main メソッドの入口で、いったん止める。

jdb LambdaTest1
jdbの初期化中...
> stop in LambdaTest1.main
遅延したブレークポイントLambdaTest1.main。
クラスがロードされた後に設定されます。
> run
LambdaTest1の実行
捕捉されないjava.lang.Throwableの設定
遅延した捕捉されないjava.lang.Throwableの設定
>
VMが開始されました: 遅延したブレークポイントLambdaTest1.mainの設定

ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=5 bci=0
5        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);


そして、System.out.println 呼び出し、
そして、stream API を呼び出している 8 〜 12 行目 にブレークポイントを設定します。
さらに、メソッド参照で参照しているそれぞれの static メソッドの最初の行にもブレークポイントを設定する。

main[1] stop at LambdaTest1:7
ブレークポイントLambdaTest1:7の設定
main[1] stop at LambdaTest1:8
ブレークポイントLambdaTest1:8の設定
main[1] stop at LambdaTest1:9
ブレークポイントLambdaTest1:9の設定
main[1] stop at LambdaTest1:10
ブレークポイントLambdaTest1:10の設定
main[1] stop at LambdaTest1:11
ブレークポイントLambdaTest1:11の設定
main[1] stop at LambdaTest1:12
ブレークポイントLambdaTest1:12の設定
main[1] stop at LambdaTest1:17
ブレークポイントLambdaTest1:17の設定
main[1] stop at LambdaTest1:22
ブレークポイントLambdaTest1:22の設定
main[1] stop at LambdaTest1:27
ブレークポイントLambdaTest1:27の設定


cont の繰り返しを行うと、次のようになる。

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=7 bci=52
7        System.out.println(
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=8 bci=56
8         numbers.stream()
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=9 bci=66
9          .filter(LambdaTest1::isGreaterThan3)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=10 bci=76
10          .filter(LambdaTest1::isEven)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=11 bci=86
11          .map(LambdaTest1::doubleIt)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=12 bci=91
12          .findFirst()
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
main[1] cont
> isGreaterThan3 1
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
main[1] cont
> isGreaterThan3 2
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
main[1] cont
> isGreaterThan3 3
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
main[1] cont
> isGreaterThan3 4
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isEven()、行=22 bci=0
22        System.out.println("isEven " + number);
main[1] cont
> isEven 4
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.doubleIt()、行=27 bci=0
27        System.out.println("doubleIt " + number);
main[1] cont
> doubleIt 4
Optional[8]
アプリケーションが終了しました


出力を見てもらうとわかるが、最後の findFirst の呼び出しがあってから、
isGreaterThan3 が何度か出力され、isEven が出力される。
いわゆる、遅延評価っていうのが行われていることがわかる。

次に、このコードの 6 行目を stream() から parallelStream() に変えてみる。

7.     System.out.println(
8.       numbers.parallelStream()
9.        filter(LambdaTest1::isGreaterThan3)
10.       .filter(LambdaTest1::isEven)
11.       .map(LambdaTest1::doubleIt)
12.       .findFirst()
13.     );
14.  }


単純に実行すると、次のようになる。

isGreaterThan3 4
isGreaterThan3 3
isGreaterThan3 5
isGreaterThan3 1
isGreaterThan3 2
isGreaterThan3 6
isEven 5
isEven 4
isEven 6
doubleIt 4
doubleIt 6
Optional[8]


そして、同じように jdb でデバッグ実行してみる。
パラレル実行されるので、デバッガで実行した時の出力の順序と通常実行時の結果(上の)順序と同じになるとは限らない。

main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=7 bci=52
7        System.out.println(
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=8 bci=56
8         numbers.parallelStream()
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=9 bci=66
9          .filter(LambdaTest1::isGreaterThan3)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=10 bci=76
10          .filter(LambdaTest1::isEven)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=11 bci=86
11          .map(LambdaTest1::doubleIt)
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.main()、行=12 bci=91
12          .findFirst()
main[1] cont
>
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
main[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-3", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
ForkJoinPool.commonPool-worker-3[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
ForkJoinPool.commonPool-worker-2[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-4", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
ForkJoinPool.commonPool-worker-4[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-1", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
ForkJoinPool.commonPool-worker-1[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-5", LambdaTest1.isGreaterThan3()、行=17 bci=0
17        System.out.println("isGreaterThan3 " + number);
ForkJoinPool.commonPool-worker-5[1] cont
> isGreaterThan3 2
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.isEven()、行=22 bci=0
22        System.out.println("isEven " + number);
isGreaterThan3 4
isGreaterThan3 1
main[1] cont
> isGreaterThan3 6
isGreaterThan3 5
isGreaterThan3 3
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest1.isEven()、行=22 bci=0
22        System.out.println("isEven " + number);
ForkJoinPool.commonPool-worker-2[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-4", LambdaTest1.isEven()、行=22 bci=0
22        System.out.println("isEven " + number);
ForkJoinPool.commonPool-worker-4[1] cont
>isEven 5
isEven 4
ヒットしたブレークポイント: "スレッド=main", LambdaTest1.doubleIt()、行=27 bci=0
27        System.out.println("doubleIt " + number);
isEven 6
main[1] cont
>
ヒットしたブレークポイント: "スレッド=ForkJoinPool.commonPool-worker-2", LambdaTest1.doubleIt()、行=27 bci=0
27        System.out.println("doubleIt " + number);
ForkJoinPool.commonPool-worker-2[1] cont
> doubleIt 4
doubleIt 6
Optional[8]
アプリケーションが終了しました


最初の stream() を利用した場合は main スレッド上でブレークポイントにヒットするが
parallelStream() を使うと、ForkJoinPool の wroker スレッド上でブレークポイントにヒットしている。

いくつ worker スレッドが使われるかは、worker スレッド上で停止している時に threads を実行してみるとよい。

ForkJoinPool.commonPool-worker-2[1] threads
グループsystem:
 (java.lang.ref.Reference$ReferenceHandler)0x169 Reference Handler は条件を待機中です
 (java.lang.ref.Finalizer$FinalizerThread)0x168 Finalizer は条件を待機中です
 (java.lang.Thread)0x167 Signal Dispatcher は実行中です
 (java.lang.Thread)0x166 Attach Listener は実行中です
グループmain:
 (java.lang.Thread)0x1 main は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x312 ForkJoinPool.commonPool-worker-1 は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x313 ForkJoinPool.commonPool-worker-2 は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x316 ForkJoinPool.commonPool-worker-3 は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x319 ForkJoinPool.commonPool-worker-4 は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x317 ForkJoinPool.commonPool-worker-5 は実行中です(ブレークポイント)
 (java.util.concurrent.ForkJoinWorkerThread)0x31a ForkJoinPool.commonPool-worker-6 は条件を待機中です
 (java.util.concurrent.ForkJoinWorkerThread)0x31b ForkJoinPool.commonPool-worker-7 は実行中です
ForkJoinPool.commonPool-worker-2[1]


ということで、遅延評価されていることと、ForkJoin が使われていることがわかった。
記事へブログ気持玉 / トラックバック / コメント


Java SE 7u51

2014/01/15 23:09
予定通り、Java SE 7u51 が出ました。36 の脆弱性を Fix したとのことです。

リリースメモはこちら。

Java SE Development Kit 7, Update 51(JDK 7u51-b13)

"Changes" がいくつかありますね。

■ Jarsigner updated to encourage timestamping
■ Changes to Security Slider:
■ Prompt users to clear previously remembered decisions:
■ Exception Site List:
■ Change in Default Socket Permissions
■ Change in JAXP Xalan Extension Functions


そして、有償の Java SE Advanced and Java SE Support の情報はこちら。

Java SE Advanced/Java SE Support 7u51(-b13)
Java SE Advanced/Java SE Support 6u71(-b12)
Java SE Advanced/Java SE Support 5.0u61(-b11)
記事へブログ気持玉 / トラックバック / コメント


JDK 7u60 build 01, Early Access

2013/12/07 19:14
いつの間にか、7u60 の EA 版がリリースされていた。

JDK 7 Update 60 Early Access Release, 7u60 Build b01

記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 の IBM セッション資料

2013/11/12 23:30
スピーカが IBM のセッションは、このサイトから Slideshare にある資料を閲覧、ダウンロードできるようです。
Oracle のセッションカタログでは公開されていない資料も、こちらにはあるみたいです。

 ● Slides and Reviews of the IBM Sessions

一応、Oracle のサイトのリンクも。

 ◎ キーノート動画
 ◎ セッションカタログ
 ◎ セッション動画


記事へブログ気持玉 / トラックバック / コメント


Java SE 7u45 などなど...

2013/10/17 00:45
予定通り、Java SE 7u45 が出ました。51の脆弱性を Fix したとのことです。

リリースメモはこちら。

Java SE Development Kit 7, Update 45(JDK 7u45-b18)

JAXP とか TimeZone.setDefault の挙動が変更されたとか。いずれも、セキュリティ強化によるものらしい。


そして、有償の Java SE Advanced and Java SE Support の情報はこちら。

Java SE Advanced/Java SE Support 7u45(-b18/-b31)
Java SE Advanced/Java SE Support 6u65(-b14/-b32)
Java SE Advanced/Java SE Support 5.0u55(-b10)
記事へブログ気持玉 0 / トラックバック 0 / コメント 1


JavaOne 2013 SFO 4日目(最終日)

2013/09/28 08:44
JavaOne 2013 SFO 4日目で Schedule していたセッションは、次の通りです。

◉ [KEY11027] Java Community Keynote
[CON2079] Designing with Lambda Expressions in Java
[CON7852] Moving from Swing to JavaFX
[CON5876] How to Write Memory-Efficient Java Code

 
■ [CON5876] How to Write Memory-Efficient Java Code

もしかしたら、IBM の JavaVM で、hotspot とは異なるかもしれなせん ...

オブジェクトサイズってご存知ですか ?
たとえば、new Iteger(10) は何バイトでしょうか ?

32bit VM では 128bit, 64bit VM では 224bit だそうです。64bit では多くのメモリが必要になるので、数が増えれば、なおさら。そこで、CompreaaedOOP/Refs を使ってみる。すると 128bit になります。これで 32bit VM 相当まで低減できますね。

では、new String("MyString") は ? 答えは 480bit。

文字列連結でリテラル同士の連結できるなら、そして、それで十分なら、そういうコードを書きましょう。
リテラル文字列の "+" は、コンパイル時に連結されるので、オブジェクトが余分に生成されません。

次に GC について。GC の実行時間率は AP全体の実行時間の 10% 程度までとなるのが目安。
つまり、余分なオブジェクトを作りすぎないことがポイント。

コレクションを使うと多くのメモリが必要になります。そして、
 - ArrayList
 - LinkedList
 - HashTable
 - HashMap
 - HashSet
この順番で、機能も豊富になる。データサイズも大きくなります。

HashMap の場合、空での128 byte 取られる。HashMap$Entry の 16 個の配列。10000 Entry で 360K のオーバヘッドになります。
LinkedList の場合、空でも48Bytes。LinkedList$Entry が 1個10000 個で 240Kのオーバヘッド
ArrayList の場合、空でも 88byte。デフォルトキャパシティは 10。10000 で 40K のオーバヘッド
StringBuffer の場合、空でも72bytes。デフォルトで16文字。24byteのオーバヘッド
Hash* は ArrayList の 9 倍大きい。Hash* の検索などは一定。AttayList は線形。

空でも、それなりのオーバヘッドがあることに注意が必要。そして、Collection は自動拡張するが、自動縮退はしないことにも留意すべき。

自動拡張といえば、StringBuffer/Buikder。たとえば、StringBuffer はサイズ拡張を 2 倍で行うので、16M に 1 文字でも追加しようとすると、32M が取られる。15M は予約されている状態であるが、使われていないという意味では無駄かもしれない。

実際のアプリケーション(WebSphere で 5ユーザでテスト)を分析したら、実際に利用していた 206MB のメモリ使用量の中で、Collection で 43MB 使っている(16%)。これは、ほぼ、そのくらいの管理領域がある !! ということを意味しています。MAT で調べたら空のCollectionが多くある(50%+) !!

メモリを最小化するための工夫の観点
 - Lazy Allocation を使うとよい。 WeakHashMap を使うなど ... 言うほど簡単ではない ...
 - 一つのオブジェクトのコレクションを使うな
 - コレクションに入れるな ...
 - Size を適切に指定する - デフォルトのサイズが大きいことがある 
 - 拡張の機会をなくせ - 2倍サイズ拡張の弊害を避けるため
 - 再割り当て、コピーすることも考えよ - Collection は自動拡張しても、そこから自動縮退しないので
記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 サンフランシスコ 3日目

2013/09/27 08:15
JavaOne 2013 SFO 3日目で Schedule していたセッションは、次の通りです。

[CON2055] Programming with Lambda Expressions in Java
[CON7942] Java 8 Streams: Lambda in Top Gear
◉ [CON7624] Understanding Java Garbage Collection and What You Can Do About It
[CON2214] One JVM to Monitor Them All
◉ [CON4044] The Chuck Norris Experiment: Running Java in Any Browser Without a Plug-in
[CON2417] I Bet You Have a Memory Leak in Your Application

前日までの諸般の事情は、一通り済んだので、ここからセッションに集中できることになりました。
1つを除いて、予定していたセッションを受けることができました。

 
■ [CON2055] Programming with Lambda Expressions in Java

配列データを繰り返し処理するコードをラムダ式で表してみましょう...

List<Integer> numbers = new Arrays.asList(1, 2, 3, 4, 5, 6);

このデータを一要素づつデータを印字する場合、単純な for 文で書くとこうなります。

for(int i = 0; i < number.size(); i++) {
  System.out.println(numbers.get(i));
}


さらに、拡張 for 文にすると、少し短く書ける。

for(int e : numbers) { System.out.println(e); }

そして forEach メソッドを使うと、自分でループを書く必要がなくなる。
でも、記述量が増えます !! 多くが、決まり文句なのですが、書かないといけません。

numbers.forEach(new java.util.Consumer<Integer>() {
  public void accept(Integer value) {
    System.out.printl(value);
  }
});


これをラムダ式を使うと、記述量が拡張 for 文くらいに減りますね。

numbers.forEach((Integer vaue) -> System.out.println(value));

まだ、コンパイラに頑張ってもらって、変数の型を推論してもらいましょう。

numbers.forEach(valuus -> System.out.println(value));

さらに、引数を単に渡して利用されるだけなら、メソッド参照が使えます。

numbers.forEach(System.out::println); // method references

次に、配列のそれぞれの要素を 2 倍して、それらの和を求める場合を考えてみる。

int total = 0;
for(int e : numbers) {
  total = e * 2;
}
System.out.println(total);


これも、ループを明示的に書かずにすますことができる。もちろん、ラムダ式を使て。

System.out.println(numbers.stream().mapToInt(value -> value * 2).sum());

もっと、複雑な計算も繰り返しを記述せずに、Lambda 式とライブラリを使って書くこともできる。

// 3 以上の最初の偶数の 2 倍を求める。
int total = 0;
for(int e : numbers) {
  if(e > 3 && e % 2 == 0) {
    total = e * 2;
    break;
  }
}
Systemout.println(total);


これも、プールを使わずに次のように書ける。

Sysyte.our.println(
  numbers.stream().filter(value -> value > 3)
                  .filter(value -> aule % 2 == 0)
                  .map(calue -> calue * 2)
                  .findFirst());


ここで、"3 より大きい" は "偶数" のそれぞれの判定と、"2倍する"をメソッドにして、メソッド参照を使いように変更する。これは、これから性能の話をするための準備として ...

Sysyte.our.println(
  numbers.stream().filter(Sample::isGreaterThan3)
                  .filter(Sample::isEven)
                  .map(Sample::doubleIt)
                  .findFirst());

  public static boolean isGreaterThar3(int number) {
    System.out.println("isGreaterThae3" + number);
    return number > 3;
  }

  public static boolean isEven(int number) {
    System.out.println("isEven" + number);
    return number % 2 == 0;
  }

  public static boolean duobleIt(int number) {
    System.out.println("doubleIt" + number);
    return number * 2;
  }


Performance/Lazy の評価のため、それぞれの static メソッドに、SYstem.out.println("Function名" + number) を差し込んでいる。で、実行すると、次のようになる。

isGreaterThan3 1
isGreaterThan3 2
isGreaterThan3 3
isGreaterThan3 4
isEven 4
doubleIt 4


これは、"3より大きい"判定, "偶数"判定, "2倍する" のそれぞれの処理が 4 回づつ繰り返し実行されるわけではないことを示しています。
つまり、自分で繰り返し処理を記述するよりも、効率的に実行されることが期待できることを示しています。

いくつかの銘柄お株価を取ってきて 500$ 以下のものを表示するプログラム !? の速度比較をしてみた。

normal iteration  77s
stream            49s
ParallelStream    12s


だったそうです。

Effectievly Final の扱いに注意が必要。ラムダ式で、その外側で宣言された変数を利用すると、その変数は effectively final(実質的 final) として扱われます。
つまり、その変数は変更できません。

int factor = 3;
System.out.println(numbers.stream().mapToInt(value -> value * factor).sum());
factor = 4 // factor が effectivly final なので、コンパイルエラーになります。


 
■ [CON7942] Java 8 Streams: Lambda in Top Gear

Lambda のライブラリサポートの話です。

Lambda 機能は、言語構文のサポートだけでなく、ライブラリのサポートもある。
ここでは、コアライブラリにLambdaを統合した方法についての話です。

aggregate Operation の Java SE 8 の答えが Stream です。Stream はデータ構造ではないし、有限ではない。

Stream パイプラインは filter/map/sum がある。filter/map は、実際に仕事をするとは限らない。sum をした時に、そおすべてのお作業を行う。

Stream パイプラインはソースをもつ。stream を生成する方法がいくつかある(ソースに応じて?)
 - Collection.strream
 - Arrays.stream
 - Generator Function - InStream.range
 - Splitaratorを使って自分で ...

パイプライン操作には、中間処理(Immtermidiate Operations)と最終処理(Terminal Operations)とがある。中間操作には、stateless, stateful がある。stateless は filter/map などで、stateful は sort/limit などです。最終処理は toArray, reduce, collect, sum, forEach などがある。

Stream Pipeline は builder のようなもの。ソースを変更しないこと。Stateful を避けるには、forEach を collect に置き換えるなどせよ。

Reduce 処理 : sum は reduce(0, (s, e) -> s + e), count は map(e->1).sum() と書ける。

いくつかの操作を組み合わせる処理が結合規則が成立するなら、並行化ができる。
ただし、Parallel は決定的でない可能性がある。つまり、steam(). ,,, と parallelStream() ... とでが同じ結果とならないことがある。

 
■ [CON2417] I Bet You Have a Memory Leak in Your Application

自分のコードに問題がなくても、あるいは、問題ないと思って書いても、メモリリークするケースが多いという話。
厄介なのは、ClassLoader Leak。たいていはは、あなたの問題では発生しない。これは、PermGen が MetaSpace になったからといって問題がなくなるわけではない。
再デプロイさえしなければ、問題は起きないが... モジュールの再利用はもろ刃の剣だとうことです。

自分のコードの問題ではなく、利用しているライブラリ内で問題があることがある。

たとえば、MySQL JDBC Driver 内で Thread をキックしている。このスレッドが終わらせないと、undeploy ができない。re-deploy しても、古いバージョンが残ってしまう。これに対応するための奇妙なトリックを使うことになる。また、別のケースとして(自分のコードではなく、ライブラリの)Fainalizer が悪さすることがある。そんなトリックを知っていたとしても、実装が悪いと、問題が起きる。finalizer に頼っている場合などは、ライブラリ利用者から見えなければ、わかるわけがない。

もちろん、原則は、自分で何かを始めたら自分で後始末することである。open したら close する。これは忘れずに。JNDI もそう。ThreadLocal を Web AP で使う時は、自分で登録したデータは、いずれ、どっかで取り出すこと。AP がシャットダウンした時には、削除することが必要になる。contextDestory() で、後始末コードを書くこと。

sun.awt.AppContext でも clssloader leak がある。JDK 6 以前。JDK7 update の初期もあるかもしれない。

JDBC Driver の仕様では、どの実装も、java.sql.Driver に登録することになっている。よって、JDBC Driver の実装クラスは、かならず、紐ついていることになる。setDeregisterDriver(true)をしないといけない。

java.util.logging ... にも leak につながるネタ(バグ)あり。

HttpConnection を使うと、sun.net.www.http.KeepAliveCache が使われ ...(聞き逃した)

このセッションの資料は公開されているみたいですが、その資料には詳細まで書かれていないようです。

セッションの後は、Oracle Appreciation Event が予定されており、BOF はなし。
その Appreciation Event の様子は、こんな感じでした。

Oracle Appreciation Event at Treasure Island
Oracle Appreciation Event at Treasure Island

記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 サンフランシスコ 2日目

2013/09/26 08:36
JavaOne 2013 SFO 2日目で、Schedule していたセッション。

◉ [CON2076] Demystifying invokedynamic : 後半参加
◉ [CON7941] Lambda: A Peek Under the Hood
[CON6727] The invokedynamic Instruction in 45 Minutes
◉ [BOF9784] The Modular Java Platform and Project Jigsaw BOF : 資料なしの BOF
[BOF2913] Evolutionary Algorithms: The Key to Solving Complex Java Puzzles : 前半参加
[TUT7610] JVM Bytecode Engineering 101

もともと聞こうと思ったセッションですが、午前中にミーティングがあったり、晩は晩でお呼ばれしたりで、セッションを途中抜けすることが多かったです。
また、前日の晩餐で、少し調子にのってしまったようで、朝、起きたら頭が痛くて、このまま朝一のセッションから馬力を使いすぎてバテるのを避けたいので、最初のセッションも途中からの参加としました。

とうことで、細かな情報は書きません。
その上、まだまだ、セッション資料が公開されていません。

 
■ [BOF2913] Evolutionary Algorithms: The Key to Solving Complex Java Puzzles

真正直に計算をするととんでもない計算量になってしまうような問題に対すする考え方を見直そう、すると、より効果的に答えを導き出せるというような内容だったと思います。
ここでは、セールスマン巡回問題を解くことを例示してました。

途中で抜けたセッションなので、最後のサマリを聞いていないので、本当のゴールがそうだったのかはわかりません。いずれにしても、柔軟に、あらゆる角度から解決策を見出すことが大事かと ...

記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 サンフランシスコ 1日目

2013/09/25 14:50
JavaOne 2913 SFO 1日目で、Schedule していたセッション。

このうち、諸般の事情により、取り消し線は参加しませんでした。

[CON5323] Don't Code It !! Unicode It !!
[CON3675] Garbage Collection: The Useful Parts (Practical), Part 2
[CON1861] Enhanced Metadata in Java SE 8
[CON6064] Introducing the Java Time API in JDK 8
[CON8165] Type Inference in Java SE 8
[BOF3663] Debugging Native Heap OOM: Tools and Techniques
[BOF5621] Bytecode Instrumentation for Beginners
[BOF7937] Collections Gathering
◉ [BOF4020] Garbage Collection Tuning Q&A
[BOF4471] JVM Performance


[CON5323] Don't code it!! Unicode it!!

今年の JavaOne の最初のセッションは、Java EE のメイン会場 Parc 55 で、しかし、テーマは Unicode。Unicode に関するセッションは、今までの JavaOne で初めて聞きました。もっと言えば、今まで参加した JavaOne で Unicode に関するセッションは見かけたのも初めてでした。

自己紹介のスライドで多くの人が "Who am I" としているところを "私は誰だ" と日本語(漢字とひらがな)で書かれていました。スピーカーは、日本人ではありません。でも、さすが、Unicode のセッションっという掴みは OK でした(自分が日本人だからか ?!)。

内容は、まず、ASCII, ISO 8859-*、さらに Code pages の説明をしてから、Unicode の話になりました。なお、現時点での Unicode の最新バージョンは 6.2.0 だそうです。

さらに、Encoding の話が続きます。CpXXX, IBMXXX, MS-DOC Latin-1、そして、もちろん UTF-8, UTF-16, UTF-32 の話もありました。記憶スペースのサイズの話も。

国際化の原則は UTF-8 だとすると、Web UI では Content-Type の charset を utf-8 にします。HTML での meta タグの charset や JSP の page タグの pageEncoding="UTF-8" にする。Tomcat のデフォルトは ISO-8859-1 なので、server.xml で URLEncoding="UTF-8" とします。Tomcat に限らず、通常 App Server では、これらの設定ができるようになっています。 Java VM にも file.encoding プロパティがあります。

電子メールの Subject は UTF-8 で符号化された文字列は表示できない場合が多いです。ファイルダウンロードも、ファイル名を UTF-8 を使うと、いわゆる文字化けが発生することが多々あります。

文字列長にも注意が必要です。

JDBC 関連では、oracle.jdbc.defaultNChar と oracle.jdb.defaultNchar とに注意が必要です。前者は挿入(insertion)に作用し、後者は取得(retrieval)に作用するようです。Char と cahr の差はわずかですが、重要な差です。

ついでにローカライズ(L10N : Localization)。"03.04.05" は、いったい何年何月何日でしょうか ? ヨーロッパなら、April 3rd 2005, フロリダは March 4th, 2005, 日本では April 5th, 2005 です。小数点の表記("." と ",")や、Collation(ソート順序) の話がありました。


[CON3675] Garbage Collection: The Useful Parts (Practical), Part 2

10:00 〜 11:00 のセッションなのだけど、11:00 から別件の打合せが予定されていたので、10:45 には抜け出さざるをえず。そのため、一番後ろに陣取る。

このセッションは Hotspot の JVM が対象で、でも、G1GC は対象にしないらしい。

まずはヒープの構造の絵(良く見る絵)と、Copy GC, Mark and Sweep GC の紹介。Copy GC は Young 領域で、Mark and Sweep GC は Old 領域で採用されています。

ヒープ構造


そして、こんなに沢山のオプションがある ...

GC関連オプション


Mandatory なオプションは、次の3つとのこと。
 ◉ -Xloggc;<pathtofile>
 ◉ -XX:+PrintGCDetail
 ◉ -XX:+PrintTenuringDistribution

ツール紹介。
 ◉ HPJMeter
 ◉ GCViewer
 ◉ GarbageCat
 ◉ IBM GCMV
 ◉ JClarity Censum

チューニングする前に、どうしたいかを決めよ。Latency vs. Throughput vs. Footprint ... これらはトレードオフ。Latency を求めると Throughput が悪くなる。Footprint を求めると Throughput が悪くなる。Throughput を求めると Latency と Footprint が悪くなる。

チューニングは繰り返し行う作業である。ある問題を解決すると、次の問題が顕在化してくる。それを解決すると、また別の問題が出てくる。これを繰り返して落としどころに持ち込む。

一度に一つの点だけを修正すること。

GCログからメモリリークを調べることはできない。メモリリークが疑うなら、まずヒープサイズを増やせ。その次に、メモリプロファイルをしてみよ。例えば、Visual VM や jmap -histo を使う。

一時定時間が長い場合、-XX:ParallelGCThreads=N の N を実際のコア数の 3/4 にする。あるいは、ParNew/CMS, PSScavenge/ParOld, iCMS, G1 など別の GC アルゴリズムを試す。ちなみに、G1GC は一時停止時間の目標を設定できる。ただし、100ms 未満の値は、うまくいかないかも。

ここまで聞いて退席。


[CON6064] Introducing the Java Time API in JDK 8

JDK8 で導入される新しい date/time API の話です。

スクラッチで作ったとのことで、既存のクラスは参照しない。グローバルカレンダをサポートし、型安全で既存クラスとも協調して動くらしい。スレッドセーフなのでキャッシュできるし、可読性も高いよとのことです。

"date" と "time" には多くの意味がある。ということで、それぞれに対応するクラスがある。多くの意味があるのは確かだけど、それらの多くのクラスを使いこなすのは大変そうです。

 ◉ java.time.LocalDate
 ◉ java.time.LocalTime
 ◉ java.time.LocalDateTime
 ◉ java.time.OffsetTime
 ◉ java.time.OffsetDataTime
 ◉ java.time.ZonedDateTime
 ◉ java.time.Instant

[LocalDateTime のコード例]
  dt1 = LocalDateTime.now();
  dt2 = LocalDateTime.of(2013, Month.SEPTEMBER, 12, 13, 30);
  dt1 = dt1.plusDays(2).minusHours(1);
  dt1 = dt1.with(next(TUESDAY));
  dt2.toString(); // 2013-09-12T13:30

[ZonedDateTime のコード例]
  zone = ZoneId.of("Europe/London");
  dt2 = ZonedDateTime.of(2013, Month.SEPTEMBER, 12, 13, 30, 0, 0, zone);
  dt1 = dt1.plusDays(2).minusHours(1);
  dt1 = dt1.with(next(TUESDAY));
  dt2.toString(); // 2013-09-12T13:30+1:00[Europe/London]

ちなみに、ZonedDateTime を使った時、その Zone で夏時間(Daylight Saving Time)採用していると、夏時間へ/からの切り替えの際に、時間のギャップとオーバラップがある。

[オーバラップの例]
  // 夏時間最終日1日前
  zone = ZoneId.of("Europe/London");
  dt = ZonedDateTime.of(2010, OCTOBER, 27, 1, 30, 0, 0, zone);

  //dt = 2010-10-27 01:30 +01:00
  dt = dt.plusDays(1);
  //dt = 2010-10-28 01:30 +01:00 ... 夏時間最終日(切替時間前) - オフセットを維持
  dt = dt.plusHours(1);
  //dt = 2010-10-28 01:30 +00:00 ... オフセット変更 - (1時間後でも)同じ時間

量としての時間を表すクラスもある。期間ともいえるかな。日数単位と時間単位とのクラスがそれぞれある。

 ◉ java.time.Period : 日単位の期間
 ◉ java.time.Duration : 時間単位の期間

[Period のコード例]
  period = Period.ofMonths(9); // 9ヶ月
  period = Period.plusDays(6); // 9ヶ月と6日
  dt = LocalDateTime.now();
  dt = dt.plus(period); // 9ヶ月6日後

[Duration のコード例]
  duration = Duration.ofHour(6); // 6時間
  duration = duration.multiplieBy(3); // 18時間
  duration = duration.plusMinutes(30); // 18時間30分
  dt = LocalDateTime.now();
  dt = dt.plus(duration); // 18時間30分後

いずれにしても、多くのクラスがあるので、どのクラスを使ったらよいかは、少し勉強しておいたほうがよさそう。


[BOF3663] Debugging Native Heap OOM: Tools and Techniques

ネイティブヒープの OutOfMemory Error の原因調査についてのセッション。

まず、理解しておくべきことは、プラットフォームの限界を知ること。
例えば、アプリケーションのプロセスは当然ながら OS がサポートする範囲で動作する。これは、Java プロセスも同じ。アドレッシングしかり、メモリモデルしかり ,,,

アドレッシングは、理論値として 32bit であれば 4G(2^32) だし、64bit なら 16EiB(2^64)である。が、実際には、諸事情により、それらの空間のすべてが利用できるわけではない。Windows 32bit はカーネル空間 2G, ユーザ空間2Gだし、Linux 32bit ならカーネル空間 1G, ユーザ空間 3G だったりする。

ユーザ空間は、Java Heap, JIT Data(Code Cache), VM Reource, Native & JNI Allocations(ネイティブメソッドで割り当てるメモリなど), Java Object の下で使われるネイティブリソース(Thread, ByteBuffer, Socket など)で使われる。

ネイティブヒープは、このユーザ空間から Java Heap の最大サイズを除いた部分である。

ネイティブヒープの問題の症状は、どのリソースが足りなくなったかによって様々。OutOfMemoryError はその一つ。それ以外、あるいは、それによって、アプリケーションがクラッシュしたり、応答しなかったりすることもある。

これらを理解したうえで、メモリの使用状況をモニタリングする。

プロセスのサイズのモニタリングにより早期に問題を検出でき、またネイティブメモリの問題を理解するために重要な部分である。

プロセスサイズのモニタリングは、Resident Size と Virtual Size。Windows なら Performance Monitor を, Linux なら ps を使う。そして、IBM GCMV(Garbage Collection & Memory Visualizer)もある - スピーカが IBM の方なので ...。

ネイティブメモリの OOME の原因を調査する基本的なアプローチは、ネイティブメモリの利用増加率調査することから。何度かスナップショットを取り、それぞれを比較することで成長率が求まる。

Windows では UMDH, DebugDiag, VMMAP などが利用できる。

次の作業は、原因となったスタックの状況によって変わる。
自分自身のネイティブコードであれば、自分でのメモリ割り当てに関係している。Java クラスに関連したネイティブコードであれば、関連するオブジェクトがヒープ上でリークしていないかを確認する。また、既存の問題がないかを確認する。最後には、JVM ベンダにコンタクトする。3rd party のライブラリのネイティブコードなら、既存の問題がないかを確認し、提供ベンダにコンタクトする。


[BOF7937] Collections Gathering

Java 7 では、7u6 や 7u40 で HashMap/ArrayList 辺りを少し改善している。

Java 8 では、Stream や Lambda でコレクションの集合演算が行えるようになる。また、デフォルトメソッドが追加される。java.util.concurrrent の機能と性能が向上する。HashMap も...

そして、Java 9 以降では、特に 10 以降になるみたいですが、こんな項目が挙げられています。
 ◉ Refication, Value Type, Packed Object
◉ Primitives
◉ Large/Segmantaed/Sparse Arrays
◉ Immutable Clojure/Bagwell style
◉ Focus on Streams API

最後は、本日の晩餐。遅めの豪華な晩飯。

IMG_4351 IMG_4380 IMG_4393 IMG_4361


ワインとステーキは、あまり相性が良くないのか、翌日二日酔いで頭がガンガンになってしまった。

記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 SFO 基調講演の巻

2013/09/25 06:56
JavaOne 2013 San Francisco の基調講演。

今年は Moscone Center North に戻ってきました ... それも、日曜日の昼から。その後、15:00 〜、OOW の基調講演があるらしいので、前座的な扱いか !? 本当かどうかは、さておき、Moscone North の Hall D の前に入れるのは 11:00 から。その 11:00 になると、こんな感じでした。

最初は、パラパラ。

IMG_3705


徐々に、並ぶ人が増えてきて、

IMG_3706


そして、South まで伸びる列。

IMG_3717


で、並び過ぎたらしく、列の幅を広くとるように誘導されてたため、ほとんど、並んだ意味がない状態に。

Hall D の入り口には、赤くない(珍しい)

IMG_3923


基調講演では、特に大きなサプライズはありませんでした。あえて、強調していたと言えば、Project Avator が Open Soure になったことぐらいでしょうか ?

ちなみに、Java SE(+Embedded)のロードマップも出てましたが、来年の前半に Java SE 8 が出ることになっていることは既出の通りのままです。一方で、今回のロードマップの絵には 8.1 とか 8.2 とかは出ていません。そして、Java SE 8 のタイミングで、Java SE Embedded 8. Java ME Embedded 8 が、同期を取ってのリリースになりそうです。

2016年には Java SE 9 が出るというロードマップですが、その時期に Java Embedded 9 というものが出るようです。Java Embedded です。Java SE Embedded でも、Java ME Embedded でもなく ...

ちなみに、Java ME(Embedded ?) 8 は、Java SE 8 の言語仕様のサブセットが採用され、また、その API の一部が Java SE 8 の API になる見込で、ベン図での重なりの範囲が、少し広くなるイメージです。

さらに、Java 8 以降で(Java 9 かどうかは不明)、Java ME というキーワードではなく、Small Device というキーワードで表現されています。それで、Java Embedded という表現になっているのかもしれません。いずれにしても、SE の言語仕様の多くが利用でき、また、API の重なりも広くなるようです。

そして DukePad

最後に、Java 9 ... and Beyond。

どれが Java 9 に入るかどうかは未確定だと思いますが、こんなキーワードが上がっていました。
 - Java on GPUs(Smatra)
 - Modular Platform(Jigsaw)
 - Relfication(Unified Type System)
 - JNI 2.0
 - Memory-Efficient Data Structure

最後の Memory-Efficient Data Structure 関連の話は、Java ME の CDC レベルの JVM を SE の JVM に統合する話の中で出てきています。IBM のキーノードでも @Packed アノテーションとして、そのアイディアを説明していました。Java 9 の頃には形になっているかもしれませんね。

登壇者は、こちらの方々。


IMG_3744IMG_3773IMG_3794IMG_3816IMG_3841IMG_3858IMG_3867IMG_3898IMG_3916IMG_3881

記事へブログ気持玉 / トラックバック / コメント


JavaOne 2013 に来ました。

2013/09/23 03:30
一年ぶりの San Francisco です。

今年も、JavaOne 2013 に来ました。


羽田 搭乗ゲート112 
JL002, B787-8 
サンフランシスコ国際空港


直前まで、来ないつもりだったので、航空券やらホテルやらでバタバタでしたが、なんとか、無事に来れました。

今年は、昨年と違って、到着便が重ならなかったかもしれないが、イミグレーションにはさほぼ時間がかからず。とっとと、税関も抜けて、BART でダウンタウンに移動。

BART に乗る前に Clipper Card を購入。便利になるはず、を信じて。

... で、日は変わって ...

まもなく、JavaOne のキーノートです。
Moscone Center North に戻ってきました。が、まわりは真っ赤っかです。


IMG_3651 
IMG_3670


そして、今日は日曜日。その真昼間からです。そして、たしか、JavaOne のキーノートのあと、OOW のキーノートのようです。
記事へブログ気持玉 / トラックバック / コメント


Java SE 7 update 40 出ました。Advanced 6u60 も。

2013/09/12 00:55
昨日の JJUG Night セミナーでの、オフレコでの予告の通り、Java SE 7 update 40 が出ました。build 番号は 43。update 番号は、25 から、次の 20 の倍数である 40 になり 7u26 〜 7u39 は欠番です。

それ以外に、Java SE advanced 6 update 60(build 31) も出てます。ここでも、欠番が出ています。いずれも u52 〜 u59 が欠番。51 の次の 20 の倍数である 60 です。

リリースメモはこちら。

Java SE Development Kit 7, Update 40(JDK 7u40-b43)

目玉は、JRockit との統合によって、hotspot 系で Mission Control やFlight Recorder が使えるようになったこと。これらは、商用利用では、別途(BCLではなく)有償ライセンスが必要。

でも、一時的な評価などのために利用できるように、次のようなオプションを指定すると使えるらしい。FlightRecorder の場合、

-XX:+UnlockedCommercialFeatures -XX:+FlightRecorder

と指定する。
なお、この情報は、JJUG Night セミナーで聞いた話であって、自分ではまだ、試してない。

そして、有償の Java SE Advanced and Java SE Support の情報はこちら。

Java SE Advanced/Java SE Support 7u40(-b43)
Java SE Advanced/Java SE Support 6u60(-b07/-b31)
記事へブログ気持玉 / トラックバック / コメント


JavaOne に行けるみたいだ。

2013/09/06 23:40
今年の JavaOne SFは、行けないつもりでいたので、全く下調べもなにもしてなかったのでけど。

ひょんなことから、行くことになるかも、となり、昨日慌てて ESTA 申請したりして。

したら、行くことになり。

これから、飛行機とホテルの探し。

果たして、この時期に、まだ、空いてるところがあんのか ?
記事へブログ気持玉 / トラックバック / コメント


JDK7 update 25 build 17 for Windows ...

2013/06/25 23:45
JDK7u25 build 17 for windows ってのが出てますね。

build 16 だったのが、build 17 になったのは、どこがかわったのか...

よくわからんです。

Java SE Development Kit 7, Update 25(JDK 7u25-b15/b17 for Windows)

たまに、あるんだよな。

突然、Release Note での build 番号の記載が知らぬ間に更新されてるのが。
記事へブログ気持玉 0 / トラックバック 0 / コメント 2


JavaSE 7 update 25 出た。Advanced 6u51, 5.0u51 も

2013/06/21 00:47
定期のアップデート(CPU:Critical Patch Updates)でました。

Java SE 7 update 25。build 番号は 15(16 for Windows)。なお、7u22 〜 7u24 は欠番です。新しい番号付与ルールの 5 の倍数の方が適用されているようです。

それ以外に、Java SE advanced 6 update 51(build 11), Java SE advanced 5.0 update 51(build 10) も出てます。ここでも、欠番が出ています。いずれも u46 〜 u50 が欠番。こちらも、5の倍数ルール。5の倍数が偶数なら +1 ってのも適用。

今回は 40 の Security Fix が入っている。
詳細は、Oracle Java SE Critical Patch Update Advisory - June 2013 にあります。

リリースメモはこちら。

Java SE Development Kit 7, Update 25(JDK 7u25-b15/b16)

興味深いのは、Java API Documentation Updater Tool というもの。

また、JDK 7u21 のリリースメモから書かれている "JRE Expiration Date" は Java Control Panel の設定が "高"(デファルト)の時に、この期限をすぎていると、LiveConnect を利用して JavaScript から Java の呼び出しをブロックするといったところに影響があるみたい。他のセキュリティー機構にも関係するとは思うけど。一応、どういう時に効き目があるのかが分かった。

ちなみに、7u25 の "JRE Expiration Date" は、2013/11/15 とのこと。これは、次の CPU の 1ヶ月後。

そして、有償の Java SE Advanced and Java SE Support の情報はこちら。

Java SE Advanced/Java SE Support 7u25(-b15/b16)
Java SE Advanced/Java SE Support 6u51(-b11)
Java SE Advanced/Java SE Support 5.0u51(-b10)
記事へブログ気持玉 0 / トラックバック 1 / コメント 0


続きを見る

トップへ

月別リンク

Java etc.../BIGLOBEウェブリブログ