Java/ Xshareclasses

Xshareclasses

■ってかそもそも(スキップして構へん)
Javaってprogramming once running anywhereを目的に始まった言語
なんで
その性能はCに激しく劣るものだった

javaのrunning anywhereを叶えているのは人間のjava語から電脳の機会語に訳すコンパイル
Cとかは静的なコンパイルなのに対しJavaは動的なコンパイル
当初は酷かった性能は今やCに十分匹敵するもの

ただ
経験値から依然Javaが劣るという技術者も少なくなく
Javaも静的コンパイラを採用すべきと提唱している

そんな背景からJavaには
動的コンパイル=JITJust-In-Time
静的コンパイル=AOTAhead-Of-Time
がある
両者は一長一短で排他なものでない

■そして本題の前提(スキップして構へん)
Javaアプリを分離させるにはJVMを分離させれば良い
ただ
JVMの分離となると初期コストやメモリ面は無駄が発生しうる
そこで
JVM間でリソースを共有できないか?
という発想に至る
それを叶えるのがIBMであればXshareclasses

■本題
共有クラス:
複数JVM環境下でシステムクラスを共有メモリにロードして
システムクラスのコア・セットを共有する仕組みで
JVM呼び出しの度にロードするのを避ける
・各JVMでのメモリ容量のコストを削減する
のが狙い

# 共有メモリ=全てのJVMに共有のメモリ領域

■ヒープ(余談)
メモリ=システム・ヒープ(共有ヒープ)+Javaヒープ

システム・ヒープ
Master JVM(Primary JVM)が共有メモリに割り当てるところでシステム・クラスが置かれる
Master JVMの息の限り存在するためGCの対象にならない
# Mater JVMに続く各Worker JVMが共有地としてシステム・ヒープ、非共有の私有地としてそれぞれのJavaヒープを使う
# Javaヒープは常にGCの対象になる

各Worker JVMがシステム・ヒープ(共有ヒープ)にクラスをロードさせるためには
共有可能クラスローダー のクラスパスに対象のクラスを置いとけば良い
# 共有クラスは通常のクラスと同様にparent-delegationモデルでロードされる


ref:
Real-time Java, Part 2: Comparing compilation techniques, 2007/4/17
http://www.ibm.com/developerworks/java/library/j-rtj2/
 in jp
  リアルタイム Java、第 2 回: コンパイル技術を比較する, 2007/4/17
  http://www.ibm.com/developerworks/jp/java/library/j-rtj2/
 in cn
  实时 Java,第 2 部分: 比较编译技术, 2007/5/16
  http://www.ibm.com/developerworks/cn/java/j-rtj2/
 # kr @2007/6/5, br @2011/9/16

Java technology, IBM style: Class sharing, 2006/5/30
http://www.ibm.com/developerworks/java/library/j-ibmjava4/
 in jp
  Java共有クラス, 2004/5/8
  http://www.ibm.com/developerworks/jp/java/library/j-shared/

クラスの共有によるパフォーマンスの向上, 2008/9/30
http://www.ibm.com/developerworks/jp/java/library/j-sharedclasses/

tags:
Xshareclasses JIT AOT Just-In-Time Ahead-Of-Time JVM

tag : Xshareclasses JIT AOT Just-In-Time Ahead-Of-Time JVM

2012-12-28 22:41 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ xml

大きく3種類
DOM ドム
StAX スタックス
SAX サックス

DOM
―Xpathを使う
―全データをメモリに展開する
―任意の処理始めるまでにロード時間がかかる
―出力も可能

StAX
―ストリーム型
―pullタイプ(呼び出し側がスレッド握ってる感じ)
―出力も可能

SAX
―ストリーム型
―pushタイプ(パーサ側がスレッド握ってる感じ)
―出力は不可

DOMはgetElementByTagNameとか柔軟な編集ができる
StAXSAXはストリーム型なのでメモリを節約できる
SAXはAPI側にスレッドを握られるため出力ができない

tag : Java XML DOM StAX SAX

2012-12-27 06:35 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ コマンドからの実行

■前提
C:\tmp\javabattest
│ exe.bat

├─lib
│ hoge1.jar
│ hoge2.jar

└─prop
piyoyo.properties
piyoyoyo.xml

bat
exe.bat//-----------------------------------------
@echo off

REM == バッチファイル起動ディレクトリ取得 ==
SET BAT_PASS=%~dp0

REM == 実行するJavaClass指定 ==
SET EXECUTE_CLASS=sample.JavaMainTest
SET ARGS="param1 maram2"

REM == クラスパス指定 ==
set LIBS=
rem ↑同じ窓でbatを連打する度に追記されぬよう初期化しとく
set LIBS=%LIBS%;%BAT_PASS%lib\hoge1.jar
set LIBS=%LIBS%;%BAT_PASS%lib\hoge2.jar
rem ↑は「set LIBS=%LIBS%;%BAT_PASS%lib\*」と書いてもOK
set CLASS_PASS=
set CLASS_PASS=%LIBS%;%BAT_PASS%prop\.

REM == 設定値の出力 ==
echo BAT_PASS=%BAT_PASS%
echo EXECUTE_CLASS=%EXECUTE_CLASS%
echo -----
echo CLASS_PASS=%CLASS_PASS%
echo -----

echo java -cp %CLASS_PASS% %EXECUTE_CLASS% %ARGS%
java -cp %CLASS_PASS% %EXECUTE_CLASS% %ARGS%

exit /b %errorlevel%
-----------------------------------------//exe.bat

ref:
Java起動バッチファイル(bat)
http://itdata.blog.shinobi.jp/Entry/77/
コマンドからの実行で入力行が長すぎます
http://8318.blog100.fc2.com/blog-entry-769.html

tag:
java cmd cp classpass bat

tag : java cmd cp classpass bat

2012-08-18 00:57 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ コマンドからの実行で入力行が長すぎます

Windows/ 入力行が長すぎます

現象
コマンドプロンプトからbat叩くと「入力行が長すぎます」で怒られる

背景
1このコマンドプロンプトから
classpassが定義された同じbatをファイルを繰り返し叩いてるとなる

原因
その定義されたclasspassは呼ばれる度にappendされてくらしいため

対策
同じコマンドプロンプトで叩くならば
2度目以降は1度目の設定が残っているのでclasspass叩かんで良い

tag:
入力行が長すぎます java windows bat cmd cp classpass

tag : 入力行が長すぎます java windows bat cmd cp classpass

2012-08-18 00:56 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ カレントディレクトリを知る方法

File file = new File(".");
System.out.println(file.getAbsolutePath());


ref:
http://tk-factory.net/wordpress/?p=1980

tag : java file getAbsolutePath

2012-05-29 22:34 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ マルチスレッド・プログラミング

プロセス
OSにおける処理の単位のようなもの
スレッド
プロセス内で実行される一連の処理の流れのこと

プロセス内では 処理の流れを平行して複数実行することも出来る
複数のスレッドを同時実行した状態をマルチスレッドと呼ぶ
1つのスレッドで処理を進める状態をシングルスレッドと呼ぶ


マルチスレッドでは
基本的に各スレッドがほかのスレッドと同期をとらず別々に処理を実行する
マルチスレッドを実現するには新たなスレッドを生成/実行する処理をプログラム内に実装する
実装方法は2つ

実装方法1
Threadのサブクラスを作成する方法
Threadを継承してrunメソッドをoverrideする
runが生成されたスレッド上で実行される処理になる
runを新たなスレッドとして実行するには
まずThreadのサブクラスをインスタンス化する
次にその結果生成されたオブジェクトのstartメソッドを呼ぶ
startを呼ぶことでJVMが新しいスレッドを生成して実行する

実装方法2
Runnableをimplementsする方法
Runnableをimplementsしてrunメソッドを実装する
実行するには
まずRunnableをimplementsしたクラスをインスタンス化する
次にインスタンスをThreadのコンストラクタの引数に渡してThreadオブジェクトを生成する
最後に同オブジェクトのstartメソッドを呼ぶ

使い分けの指針
以下を確認する
・runメソッドを実装するクラスが既にほかのクラスのサブクラスになっている
・runメソッドを実装するクラスが「スレッドの実行」以外の役割を持っている

Javaでは多重継承できない
runメソッドを実装するクラスが既にほかのクラスのサブクラスになっている場合そのクラスをThreadのサブクラスにできない
→Runnableをimplementsしてマルチスレッドを実現する他ない

runメソッドを実装しようとしているクラスが何かの役割を持ったクラスで
かつその役割がスレッドの実行とは関連がない場合は
Threadのサブクラスにすると同クラスのメソッドを全て継承することになり
本来の役割とは関係のない機能を持たせることになってしまう

上記2点に当てはまらない場合はThreadのサブクラスとして定義する方が良い


マルチスレッドの落とし穴
バグを発生させないためには

隠すレッドで実行される更新系のメソッドにsynchronizedを指定すること
synchronizedされたメソッドは複数のスレッドから同時に実行されることがなくなる
ただし
並行して処理を進められないため性能に悪影響を及ぼす

スレッドごとに別々の変数を用意すること
各スレッドが別々に参照/更新する変数をスレッドローカル変数と呼ぶ
Javaではスレッドローカル変数をjava.lang.ThreadLocalで実現する

ref:
ITアーキテクト, マルチスレッド・プログラミング 並行処理によるバグのぱっせいを防ぐ実装方法, 2006/12/25
http://www.itarchitect.jp/beginners/-/51389.html

tag : マルチスレッド

2011-10-02 10:29 : __lang__java : コメント : 0 : トラックバック : 0 :

intro to Java

■変数と初期化
Javaがサポートする変数は2種類
クラスのメンバ変数 と メソッドのローカル変数

□メンバ変数
オブジェクトの生成時に作成されオブジェクトの破棄時に削除される
自動的に初期化される
staticでないインスタンス変数は クラスのコンストラクタが実行される直前に初期化される
staticで宣言された変数は クラスの読み込み時に初期化される

□ローカル変数(メソッドローカル/自動変数)
メソッドへの進入時に作成されメソッドの実行終了まで存続する(インナークラスは例外)
自動的に初期化されない=自分で初期化かしないとコンパイルエラー

■引数の引渡し
メソッドの呼び出しに渡されるのは引数のコピーである
void test() {
 int xx = 12345;
 bumper(xx);
 syso("Now xx is " + xx);
}
--
void bumper(int bumMe) {
 bumpMe += 15;
}
testメソッドからsysoutされるxxは12345のままである

基本データのみならずオブジェクトでも値が直に渡されないのは同じだが
オブジェクト参照object referenceになるため結果は異なる

JavaではObjectをdirectに扱わずにobjectを一意に識別する値bit pattern=参照を代わりに扱う
メソッドの引数に渡されるのもこの参照である
# JVMの実装によっては参照としてobjectのアドレスが使われたりする
# 実際にはアドレスのアドレスが参照の値となる
 この2面目のアドレスは実際のデータを指す
 この二重間接参照double indirectionでガーベッジコレクションの際に
 objectの割り当てを変更することでメモリの断片化fragmentationを減らせる

void test() {
 String color = "white";
 change(xx);
 syso("Now color is " + color);
}
--
void change(String color) {
 color = "blue";
}
testメソッドからsysoutされるcolorはblueになる

□基本データを参照渡しにする方法
void test() {
 int[] xx = {1};
 bumper(xx);
 syso("Now xx is " + xx[0]);
}
--
void bumper(int bumMe) {
 bumpMe[0]++;
}
testメソッドからsysoutされるxxは2となる

■garbage collection
Javaではプログラムの実行中に
スタック領域 と ヒープ領域 にメモリを割り当てる
メソッドのローカル変数や引数 は スタック 上に割り当てられ メソッドの終了で破棄される
newで生成されたobject は ヒープ 上に割り当てられ より長い寿命を持つ

public void aMethod() {
 MyClass mc = new MyClass();
}
ローカル変数mc(objectへの参照)は スタック上に割り当てられるが
MyClassのインスタンスはヒープ上に割り当てられる

割り当てられた領域の解放をするのがgarbage collector
garbage collectorは優先度の低いthreadから
どのactive threadからもアクセスできなくなったメモリを検出して
解放しヒープに戻して再利用できるようにする

System.gc();
Runtime.gc();
でgarbage collectorを実行するが
すぐに実行されるとは限らないし必ず実行されるとも限らない

メモリリーク回避のためnullを明示的代入するのが大切

■other
符号付の整数データ型: byte, short, int, long (いずれも2の補数)
浮動小数点型: float, double
char型: unicode文字


tag:
Java SJC-P

tag : Java SJC-P

2011-08-24 04:55 : __lang__java : コメント : 0 : トラックバック : 0 :

Java基本クラス解析

注:JDKは1.4.2の話。

■String
□文字列格納フィールド
private char value[];
char型はプリミティブ型で常にUnicode形式。
◎文字コードを意識せんでも良い。
×文字以外の情報は扱えない。
 ∵char型のバイナリ値の格納は不可。
 →Stringのインスタンスもバイナリ値の格納不可。
□equalsメソッド
文字数の多い文字列の比較は高コスト。
∵equalsメソッドはHash系クラス等で頻繁に使われる。
 →マップに使うキー文字列は短くしてが効率UP。

■Date/Calendar
□違い
Dateのフィールドにはlong型が一つ。
○生成が低コスト。
 ※シリアライズしても容量たった4byte。
CalendarはDateの機能を網羅してる。
×Dateより重い。
 ※シリアライズすると消費する容量は1000byte以上。
□Date#getHoursがdeprecatedな訳
∵同期(synchronized)メソッドだから。


XXX

ref:
Program Island Java基本クラス解析
http://www.limy.org/program/java/java_basic1.html

tag : XXX

2011-08-08 20:45 : __lang__java : コメント : 0 : トラックバック : 0 :

マルチスレッド@Java

Javaではローカル変数のみ安心

マルチスレッドで動作するアプリでは
1つのプロセスで複数の利用者からのリクエストを同時に受け付けて処理する
いちいちプロセスを起動しない分
性能向上や効率的なCPU/メモリの使用に繋がる
マルチコアCPUであれば
複数のコアで各スレッドを同時実行できちゃう

JavaのServletやJSP(JavaServer Pages)がマルチスレッド動作を前提としている

Servletでは以下の3種類の変数を利用できる
・クラスで共用される「クラス変数」
・クラスから生成された個々のインスタンス(オブジェクト)で使用される「インスタンス変数」
・メソッド内やブロック内で使われる「ローカル変数」

3種類の変数のうち
スレッドセーフなのはローカル変数だけである
ローカル変数は
スレッド固有のメモリ領域である「Javaスタック」に保持されるため
1つのスレッドからしかアクセスされない
スレッド毎に固有の変数格納庫があることになり
他のスレッドに情報を書き換えられたり
他のスレッドが情報を取り違えて参照したりすることはない


ローカル変数以外は複数のスレッドから共有され得る
インスタンス変数やクラス変数は
共有メモリである「ヒープ領域」に格納されるため
複数のsレッドが共有する可能性がある
そのため参照/更新する時はロック(更新メソッドにsynchronized宣言する等)しない限り
スレッドセーフではない

JSPの場合
変数やメソッドの宣言に使われる<'%! %>タグが
Servletへのコンパイル字にインスタンス変数に展開される
そのため
Servletと同様にマルチスレッドの考慮が必要になる


ref:
[実装編]スレッドセーフにすることを忘れてはいけない
★★★★☆+α
http://itpro.nikkeibp.co.jp/article/COLUMN/20070820/279950/

tag : Java Multi Thread

2010-04-08 01:01 : __lang__java : コメント : 0 : トラックバック : 0 :

Introduction to Java programming

■エスケープシーケンス
the escape sequences start with "\."

\t 水平タブ
\n 改行
\" 二重引用符(")
\' 一重引用符(')
\\ 円マーク
\uXXXX XXXX部分に16進数4桁でUnicodeの値で その文字コードを持つ文字として扱われる

■基本型

□整数型
デフォルトは int型
long型として利用したい場合は 数値の後にlかLを指定する
"0"で始まる数値は8進数値
"0x"で始まる数値は16進数と見なされる

□浮動小数
デフォルトはdouble
floatとして利用したい場合は 数値の後にfかFを指定する

□文字
1文字を表現するときはchar型になる
シングルクオテーションで囲んで表記する

□論理
真偽値は trueとfalse

■演算子

□数術演算子
和 +
差 -
積 *
商 /
剰余 %

□比較演算子
小なり <
大なり >
小なりイコール <=
大なりイコール >=
等しい ==
等しくない !=

□ブール演算子
論理積(且つ) &&
論理和(または) ||

□インクリメント/デクリメント演算子
x++ xを評価した後にxをx+1に更新
++x xをx+1に更新した後にxを評価
x-- xを評価した後にxをx-1に更新
--x xをx-1に更新した後にxを評価

□再帰代入演算子
y+=10 → y=y+10
y-=10 → y=y-10
y*=10 → y=y*10
y/=10 → y=y/10
y%=10 → y=y%10

■条件分岐

□分岐文
・if-else文
・switch文

■繰り返し処理

□ループ文
・forループ
・whileループ
・do-whileループ

□ループ制御
break
continue
return
ラベル
ラベル付break文
ラベル付continue文

■配列

□多次元配列
int twoDim[][] = neew int[3][];
twoDim[0] = new int[5];
twoDim[1] = new int[3];
twoDim[2] = new int[7];
2010-04-07 23:56 : __lang__java : コメント : 0 : トラックバック : 0 :

intro to java programming/ 変数

|public class HelloWorld {
| public static void main( String args[] ) {
|  System.out.println("Hello!");
|  System.out.println(12345);
| }
|}

ダブルクオテーション
コンパイラが解釈しないよう
で括って文字列であることを明示する際に使用する
ただし 数字は括る必要ない

セミコロン
文を区切るのに使用する

|public class Calculation {
| public static void main( String args[] ) {
|  System.out.println(3*6+4/2);
| }
|}

実行すると計算結果が表示される

|C:\DOCUME~1\MYDOCU~1\MYJAVA~1>java Calculation
|20

「*」,「+」,「/」を演算子という

Javaの演算子
優先度高
[], ()
++, --
!, ~, instanceof
*, /, %
+, -
<<, >>, >>>
<, >, <=, ==, !=
&, ^, |, >=
&&, ||
?:
=, op=(*=, /=, %=, +=, -=
優先度低

Javaの変数

|public class CalcWithParams {
| public static void main( String args[] ) {
|  int x;
|  int y;
|  x = 2;
|  y = 2*x + 3;
|  System.out.println(y);
| }
|}

変数という概念は数学に由来するもの
上記であれば
xが2だった時の2x+3の結果をyに代入しているように
数学の変数と同じ役割を果たしている

変数の宣言

Javaでは変数を使う前に宣言する
|int a;
"int"はinteger(整数)の略
"int a;"でこれから整数型の変数aを使う意味を示す
この文が実行されると
コンピュータのメモリのうち4bytes分が確保される
確保した領域をソースコード中で"a"と呼ぶことがコンパイラに宣言される
ただし
メモリ領域の内容は初期化されるまで読み出されない

Javaで扱う全てのデータには型がある
文字列も実際はString型のデータである
データの型とは
データを格納するのに必要なメモリのサイズのこと
int型は4bytes分のメモリを使って表す整数

Javaで使える型とサイズ
整数
byte 1bytes -128~+127
short 2bytes -32768~+32767
int 4bytes -2147483648~+2147483647
long 8bytes -9223372036854775808~+9223372036854775807
浮動小数
float 4bytes ±3.40282347E+38~±1.40239846E- 45
double 8bytes ±1.79769313486231570E+380~±4.94065645841246544E- 324
文字
char 2bytes 0~65535(Unicode 表現)
理論
boolean 1bytes true/false

変数の初期化と代入

変数の宣言はメモリを必要なサイズ分確保すること
ただし
メモリを確保した段階では
メモリにどんな値が書き込まれているかは分からない
変数から値を読み出す前に何かしらの値を書き込んで変数を初期化する必要がある
初期化せずに変数を使おうとするとコンパイルエラーになる

|public class NoInitParam {
| public static void main( String args[] ) {
|  int a;
|  System.out.println(a);
| }
|}
コンパイルすると
|C:\DOCUME~1\MYDOCU~1 \MYJAVA~1>javac NoInitParam.javaNoInitParam.java:4: 変数 a は初期化されていない可能性があります。
| System.out.println(a);
| ^
|エラー 1 個
|C:\DOCUME~1\MYDOCU~1\MYJAVA~1>

変数を初期化するには
読み出す前に何かの値を代入すればよい

|public class InitParam {
| public static void main( String args[] ) {
|  int a;
|  a = 1;
|  System.out.println(a);
| }
|}
コンパイル/実行すると
|C:\DOCUME~1\\MYDOCU~1\MYJAVA~1>javac InitParam.java
|C:\DOCUME~1\MYDOCU~1\MYJAVA~1>java InitParam
|1

"a = 1;"という文で
"a"と呼ばれることになった4bytes分のメモリ領域に対して
"00000001"が書き込まれる
変数のへ初めての代入が終わると初期化されたことになり
以後読み出せるようになる

Javaでは
変数だけでなく数値を含む全てのデータに型がある
int型の変数aに代入される数値"1"は
同じくint型で扱われるので
メモリに書き込まれるデータは"00000001"になる

変数aが
1byte分のメモリを使う整数を表すbyte型で宣言あれば
"a = 1;"で"01"という1byte分のデータが書き込まれる

ref:
中野克平, 第2回 Javaの変数の本質を知る, 2002/11/29
★★★★☆
http://www.atmarkit.co.jp/fjava/rensai2/javaent02/javaent02.html

tag : Java

2010-03-23 04:11 : __lang__java : コメント : 0 : トラックバック : 0 :

intro to java programming

Java開発環境
人間が読めるテキストファイルを
コンパイラやインタプリタなどで
機械が読めるバイナリファイルに変換する

ソースファイル
|if ( hostname.equals("localhost") )
|  accept();
|else
|  reject();

バイナリファイル
|C0 74 0D 83 7B 04 0D 75 07 B2 01 E8 94 69 FE FF
|8D 55 F8 8B C7 8B 08 FF 91 B8 00 00 00 8B 45 F8
|50 8B C7 E8 2C F8 FF FF 5A 8B 08 FF 51 78 1C 57

バイナリファイル
CPUが解釈して実行するためのもの
人間が直接書くのは困難
なのでコンパイラやインタプリタで変換する

コンパイラ
個々のソースファイルを
実行可能な形式のファイルに
変換するためのプログラムのこと
C/C++等のコンピュータ言語がコンパイラ方式
実行可能な形式はCPUやOSによって異なるため
実行環境が変わる場合は再コンパイルが必要

インタプリタ
実行時のソースファイルを逐一解釈してCPUに処理させること
JavaScript等のスクリプト言語の多くがインタプリタ方式
インタプリタさえあれば
CPUやOSの種類に依存せず実行可能だが
実行時に解釈するため実行速度はコンパイラ方式に劣る

Javaはコンパイラ型のコンピュータ言語
だが
Javaのコンパイラは
ソースファイルをCPUが実行可能な形式のファイルには変換しない
代わりに
中間コードに変換する

中間コード
機械が理解し易いように
ソースファイルのある文法エラーを取り除いたもの
|01 02 03 "localhost" 04 05
01 = if
02 = 変数hostname
03 = 関数equals()
04 = 関数accept()
05 = 関数reject()

バーチャルマシン
CPUは理解出来ない中間コードを解釈して
CPUに実行させる仕組み

Javaのバーチャルマシン
Javaのコンパイラが生成した中間コードを理解できる仮想的なマシンのこと
CPUやOSの種類毎にバーチャルマシンを用意すれば
CPUの違いはJavaバーチャルマシンが吸収するため
WindowsでもMacintoshでも同じコードでプログラムを実行できる

開発環境
ソースファイルをCPUが実行可能なファイルにするまでのプログラム

Java 2 SDK
Javaの開発環境
Software Development Kit
Javaのコンパイラと
コンパイラが生成するコードを解釈して実行するJava VM(Virtual Machine)
等が含まれる

Javaのコンパイラ
インストール先フォルダのbinにあるjavac.exeで
DOSプログラムなのでコマンドプロンプトから実行できる

Javaのコンパイル
>javac.exe Hoge.java
拡張子が.classの同ファイルがコンパイルされたファイル

Javaのアプリ実行
>java Hoge
".class"は書かんでOK

ref:
中野克平, 第1回 Java2 SDKで学習の準備, 2002/10/29
★★★★☆
http://www.atmarkit.co.jp/fjava/rensai2/javaent01/javaent01.html

tag : Java SDK

2010-03-23 02:45 : __lang__java : コメント : 0 : トラックバック : 0 :

Object Pooling

オブジェクトのプーリングは
パフォーマンス向上が目的
プーリングとは
生成したオブジェクトをプール(pool)に蓄積しておき 必要になった際にプールからオブジェクトを取り出して利用し 不要になった際にはオブジェクトをプールに戻すこと
利用する度にオブジェクトを生成する方法に比べ 速度が速いのが利点
サーバサイドプログラミングであれば
スレッドオブジェクトやデータベースコネクションオブジェクトなどの生成にオーバーヘッドがかかるオブジェクトをプールして再利用するが一般的


Jakarta CommonsのPoolコンポーネントは
オブジェクトをプールするためのメカニズムを提供するもの

org.apache.commons.pool.ObjectPoolインターフェイス
オブジェクトプールインスタンスを利用するためのインターフェイス
org.apache.commons.pool.PoolableObjectFactoryインターフェイス
オブジェクトプールに蓄積するオブジェクトのライフサイクルを管理するためのインターフェイス

Poolでオブジェクトプールを実現するには
通常まずプールするオブジェクトのライフサイクルを管理する PoolableObjectFactoryインターフェイスの実装クラスを準備する
次にPoolableObjectFactoryインターフェイスの実装クラスをコンストラクタに与えてObjectPoolインターフェイスの実装クラスのインスタンスを生成する
後は生成したObjectPoolインスタンスからオブジェクトを取り出して利用し、不要になった時点でObjectPoolインスタンスにオブジェクトを返す要領

ObjectPoolのメソッドのうち必須なのが
borrowObject(プールからオブジェクトを取り出す)
returnObject(プールから取り出したオブジェクトを返却する)
close(プールをクローズする)
の3つ

ObjectPool#borrowObject()メソッドは
引数なしでオブジェクトをプールから取り出す
単にプーリングするのではなく
あるキーとオブジェクトを結び付けて管理したい場合は
ObjectPoolの代わりにKeyedObjectPoolインターフェイス(org.apache.commons.pool.KeyedObjectPool)の実装クラスを用いる
KeyedObjectPoolインターフェイスのjava.lang.Objectクラスのオブジェクトを引数に持つ borrowObject()メソッドでキーを指定してオブジェクトをプールから取り出せる

Poolには
ObjectPoolの実装クラスとして
org.apache.commons.pool.impl.GenericObjectPool
org.apache.commons.pool.impl.StackObjectPool
org.apache.commons.pool.impl.SoftReferenceObjectPool
の3つが用意されている
※これらに対応するKeyedObjectPoolの実装クラスもある
※ObjectPoolの実装クラスを独自に作成する場合はorg.apache.commons.pool.BaseObjectPool.BaseObjectPoolクラスのサブクラスとして作成することが推奨されている

GenericObjectPool
汎用的なオブジェクトプール
StackObjectPool
限定された個数のオブジェクトをプールするようなオブジェクトプール
ただしアイドル状態のオブジェクトがないときにオブジェクトの取り出し要求がきた場合には新規にオブジェクトを生成する
SoftReferenceObjectPool
アイドル状態のインスタンスが適宜ガベージコレクタによって除去されるようなオブジェクトプール

PoolableObjectFactory
オブジェクトプールがオブジェクトのライフサイクルを管理するためのインタフェース
ObjectPoolの実装クラスのPoolableObjectFactoryオブジェクトを引数に取るコンストラクタに渡すPoolableObjectFactoryでオブジェクトを管理する
※KeyedObjectPoolの実装クラスのコンストラクタにはorg.apache.commons.pool.KeyedPoolableObjectFactoryのオブジェクトを指定する

PoolableObjectFactoryインターフェイスのメソッド
makeObject
オブジェクトを新規に生成する
activateObject
オブジェクトがプールから取り出される前に呼ばれる
passivateObject
オブジェクトがプールに返却されたときに呼ばれる
validateObject
プールから取り出されるオブジェクトが正当であるかどうかを判定する
destroyObject
プールからオブジェクトが破棄されるときに呼ばれる

PoolableObjectFactoryの実装クラスの作成を簡便化するための基底クラスとして
org.apache.commons.pool.BasePoolableObjectFactoryがある



DBアクセス用のJDBCドライバが生成するjava.sql.Connectionをプーリングして再利用する

1. Connectionオブジェクトの取得
2. SQL文の発行(SELECT 1)
3. Connectionオブジェクトの解放

1.
. try {
.  // MySQLのためのJDBCドライバのロード
.  Class.forName("com.mysql.jdbc.Driver");
.  // オブジェクトプールの管理クラスのインスタンス生成
.  PoolableObjectFactory factory = new SimpleConnectionFactory(url_, user_, password_);
.  // オブジェクトプールのインスタンス生成
.  pool_ = new StackObjectPool(factory);
. } catch (Throwable t) {
.  throw new RuntimeException(t);
. }

オブジェクトプールを利用するための
プーリングするオブジェクトのライフサイクルを管理するPoolableObjectFactoryの実装クラスを用意する

SimpleConnectionFactory.java(抜粋)
.public class SimpleConnectionFactory extends BasePoolableObjectFactory{
... (略) ...
. /**
.  * このクラスのインスタンスを生成する。
.  *
.  * @param url データベース接続のためのURL。
.  * @param user データベース接続のためのユーザ名。
.  * @param password データベース接続のためのパスワード。
.  */
. public SimpleConnectionFactory(String url, String user, String password) {
.  url_ = url;
.  user_ = user;
.  password_ = password;
. }
.
. /**
.  * java.sql.Connectionオブジェクトを生成する。
.  *
.  * @return 生成したオブジェクト。
.  */
. public Object makeObject() throws Exception {
.  return DriverManager.getConnection(url_, user_, password_);
. }
.}

生成したConnectionFactoryインスタンスをコンストラクタ引数にObjectPoolのインスタンスを生成する

※ファクトリクラスを用いてオブジェクトプールのインスタンス生成するも可
StackObjectPoolであればorg.apache.commons.pool.impl.StackObjectPoolFactory で生成する具合


プールしてるオブジェクトの取得
. Connection con = null;
. for (int i = 0; i < count; i++) {
.  try {
.   // Connectionオブジェクトの取得
.   con = getConnection(usePool);
.   // SQL文の実行
.   Statement stmt = con.createStatement();
.   ResultSet rs = stmt.executeQuery("SELECT 1");
.   rs.close();
.   stmt.close();
.  } finally {
.   // Connectionオブジェクトの返却
.   returnConnection(con, usePool);
.  }
. }

getConnection()とreturnConnection()
. /**
.  * java.sql.Connectionオブジェクトを返す。
.  *
.  * @param usePool trueの時プールからオブジェクトを取得して返す。
.  * falseの時オブジェクトを毎回生成して返す。
.  * @return java.sql.Connectionオブジェクト。
.  */
. private Connection getConnection(boolean usePool) throws Exception {
.  if (usePool) {
.   // オブジェクトプールからオブジェクトを取り出す
.   return (Connection)pool_.borrowObject();
.  }
.  return DriverManager.getConnection(url_, user_, password_);
. }

. /**
.  * java.sql.Connectionオブジェクトの使用を終了する。
.  *
.  * @param con java.sql.Connectionオブジェクト。
.  * @param usePool trueの時オブジェクトをプールに返却する。
.  * falseの時オブジェクトをクローズする。
.  */
. private void returnConnection(Connection con, boolean usePool) throws Exception {
.  if (con != null) {
.   if (usePool) {
.    // オブジェクトプールにオブジェクトを返却する
.    pool_.returnObject(con);
.   } else {
.    con.close();
.   }
.  }
. }

必要な初期化処理や終了処理は通常PoolableObjectFactoryクラスが行うので
プールから取り出したオブジェクトに対するConnectionオブジェクトの初期化や
プールに返却するオブジェクトに対するConnectionオブジェクトのクローズ処理は不要

ref:
横田健彦, 第5回Commonsでオブジェクトプーリングを実現, 2003/4/12
http://www.atmarkit.co.jp/fjava/rensai2/jakarta05/jakarta05.html

tag : PoolableObjectFactory

2010-03-04 01:06 : __lang__java : コメント : 0 : トラックバック : 0 :

Shallow Copy & Deep Copy

■Overview
Javaには、オブジェクトのクローンと呼ばれる、オブジェクトのコピーメカニズムがある。
オブジェクトのコピーは、Shallow CopyとDeep Copyの2通りある。

■Shallow Copy
オブジェクトのbit-wiseなコピー。
newOject(コピー生成された新しいオブジェクト)は、originalObject(コピー元のオブジェクト)と同じ値を保持する。
originalObjectに、他のオブジェクトを参照するフィールドがあった場合、その参照値だけがnewObjectにコピーされる。
つまり、
originalObjetのそのフィールドと、newObjectのそのフィールドは、同じオブジェクトを参照する。

■Deep Copy
オブジェクトの完全なコピー。
originalObjetが、他のオブジェクトを参照する場合、参照先のオブジェクトもクローンが生成される。
つまり、
Deep Copyはプリミティブ値のコピーのみならず、サブオブジェクト(originalObjetが参照するオブジェクト)をも同様にコピーする。

■Tips For Deep Copy
Objectが提供するclone()は、ただのシャローコピー。
ディープコピーしたい場合は、自分で小細工する必要がある。
小細工しても、それを継承したクラスがきちんとオーバーライドせんことには、ディープコピーにならんことも。
と、まぁ、いろいろディープコピーはメンドウ。
ゆう時は、シリアライズが便利。
シリアライザブルをimplementsすれば、万事解決。
ただ、パフォーマンスクリティカルなケースは、きちんと考慮して選択すべし。

詳細は、記事参照。


ref:
What is shallow copy and deep copy in Java?
http://www.coders2020.com/what-is-shallow-copy-and-deep-copy-in-java
Java Tip 76: An alternative to the deep copy technique
http://www.javaworld.com/javaworld/javatips/jw-javatip76.html

続きを読む

2009-06-22 05:43 : __lang__java : コメント : 0 : トラックバック : 0 :

generic interface

--Main--------------------------------------------
package pkg.y2009.m06.test002;

public class Main {

/**
* generic interface
* @param args
*/
public static void main(String[] args) {
Integer[] integers = {8, 7, 6, 5, 12, 11, 10};
Character[] characters = {'a', 's', 'd', 'f', 'g'};
MinMaxImpl i = new MinMaxImpl(integers);
MinMaxImpl c = new MinMaxImpl(characters);

System.out.println("integers.min: " + i.min());
System.out.println("integers.max: " + i.max());
System.out.println("characters.min: " + c.min());
System.out.println("characters.max: " + c.max());
}
}
--/Main-------------------------------------------
--MinMax------------------------------------------
package pkg.y2009.m06.test002;

public interface MinMax <'T extends Comparable<'T>> {
  T min();
  T max();
}
--/MinMax-----------------------------------------
--MinMaxImpl--------------------------------------
package pkg.y2009.m06.test002;

public class MinMaxImpl<'T extends Comparable<'T>> implements MinMax<'T> {
  T[] vals;
  MinMaxImpl(T[] ts) { vals = ts; }
  public T min() {
    T min = vals[0];
    for (T t : vals)
      if (t.compareTo(min) < 0) min = t;
    return min;
  }
  public T max() {
    T max = vals[0];
    for (T t : vals)
      if (t.compareTo(max) > 0) max = t;
    return max;
  }
}
--/MinMaxImpl-------------------------------------
--console log-------------------------------------
integers.min: 5
integers.max: 12
characters.min: a
characters.max: s
--/console log------------------------------------

ref:
http://www.java2s.com/Code/Java/Language-Basics/Agenericinterfaceexample.htm
2009-06-22 02:13 : __lang__java : コメント : 0 : トラックバック : 0 :

how to get a seq No among several threads.

--Main.jave---------------------------------------
package pkg.y2009.m06.test001;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import pkg.test001.Runnablee;
import pkg.test001.Runnablee2;

public class Main {

  /**
   * @param args
   */
  public static void main(String[] args) {
    try {
      test001();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

  }

  /**
   * how to get a seq no among several threads.
   * @throws InterruptedException
   *
   */
  private static void test001() throws InterruptedException {
    int hangingTime = 2000;
    int runnerListSize = 10;
    
    ////////////////////Runnablee
    int subId = 1;
    Thread.currentThread().getThreadGroup().list();
    List list = Runnablee.getInstanceList(runnerListSize, subId);
    for (Runnablee t : list) t.run();//1st execution
    Thread.sleep(hangingTime);
    
    subId = 2;
    Thread.currentThread().getThreadGroup().list();
    list = Runnablee.getInstanceList(runnerListSize, subId);
    for (Runnablee t : list) t.run();//renew and execute again
    Thread.sleep(hangingTime);
    
    subId = 3;
    Thread.currentThread().getThreadGroup().list();
    list = Runnablee.getInstanceList(runnerListSize, subId);
    ExecutorService es = Executors.newFixedThreadPool(2);
    for (Runnablee t : list) es.execute(t);
    es.shutdown();
    Thread.sleep(hangingTime);
    
    subId = 4;
    Thread.currentThread().getThreadGroup().list();
    list = Runnablee.getInstanceList(runnerListSize, subId);
    es = Executors.newCachedThreadPool();
    for (Runnablee t : list) es.execute(t);
    es.shutdown();
    Thread.sleep(hangingTime);
    
    Thread.currentThread().getThreadGroup().list();
    
    ////////////////////Runnablee2
    subId = 1;
    Thread.currentThread().getThreadGroup().list();
    List list2 = Runnablee2.getInstanceList(runnerListSize, subId);
    for (Runnablee2 t : list2) t.run();//1st execution
    Thread.sleep(hangingTime);
    
    subId = 2;
    Thread.currentThread().getThreadGroup().list();
    list2 = Runnablee2.getInstanceList(runnerListSize, subId);
    for (Runnablee2 t : list2) t.run();//renew and execute again
    Thread.sleep(hangingTime);
    
    subId = 3;
    Thread.currentThread().getThreadGroup().list();
    list2 = Runnablee2.getInstanceList(runnerListSize, subId);
    ExecutorService es2 = Executors.newFixedThreadPool(2);
    for (Runnablee2 t : list2) es2.execute(t);
    es2.shutdown();
    Thread.sleep(hangingTime);
    
    subId = 4;
    Thread.currentThread().getThreadGroup().list();
    list2 = Runnablee2.getInstanceList(runnerListSize, subId);
    es2 = Executors.newCachedThreadPool();
    for (Runnablee2 t : list2) es2.execute(t);
    es2.shutdown();
    Thread.sleep(hangingTime);

    Thread.currentThread().getThreadGroup().list();
  }

}
--/Main.jave--------------------------------------
--Runnablee.jave----------------------------------
package pkg.y2009.m06.test001;

import java.util.ArrayList;
import java.util.List;

public class Runnablee implements Runnable {

  static final String SYSOUT_PREFIX = "【TEST001】";

  static {
    System.out.println("Runnablee.threadId has the overrided get-method which returns next value.");
  }

  public static int SEQ = 0;

  public static synchronized int next() {
    return ++SEQ;
  }

  public static ThreadLocal threadId = new ThreadLocal() {

    @Override
    public Integer get() {
      return next();
    }

    @Override
    protected Integer initialValue() {
      return next();
    }

  };

  int subId = -1;

  public Runnablee(int subId) {
    this.subId = subId; 
  }


//  @Override
  public void run() {

    sysout(subId, this.hashCode(), threadId.get(), Thread.currentThread().getId(), this.getClass().getName());

  }

  static void sysout(int subId, int hashCode, Integer seq, long threadId, String className) {
    System.out.println(SYSOUT_PREFIX + className + "(" + subId + "): " + seq
        + "\t (threadId: " + threadId + ")" + " [ " + hashCode + " ]");
  }

  public static List getInstanceList(int listSize, int subId) {
    List list = new ArrayList();
    for (int i = 1; i <= listSize; i++) {
      list.add(new Runnablee(subId));
    }
    return list;
  }

}
--/Runnablee.jave---------------------------------
--Runnablee2.jave---------------------------------
package pkg.y2009.m06.test001;

import java.util.ArrayList;
import java.util.List;

public class Runnablee2 implements Runnable {

  static {
    System.out.println("Runnablee2.threadId2 doesnt have the overrided get-method.");
  }

  public static int SEQ2 = 0;

  public static synchronized int next2() {
    return ++SEQ2;
  }

  /**
   * no get overriding.
   */
  public static ThreadLocal threadId2 = new ThreadLocal() {

    @Override
    protected Integer initialValue() {
      return next2();
    }

  };

  public Runnablee2(int subId) {
    this.subId = subId; 
  }
  
  int subId = -1;
  
//  @Override
  public void run() {

    Runnablee.sysout(subId, this.hashCode(), threadId2.get(), Thread.currentThread().getId(), this.getClass().getName());

  }

  public static List getInstanceList(int listSize, int subId) {
    List list = new ArrayList();
    for (int i = 1; i <= listSize; i++) {
      list.add(new Runnablee2(subId));
    }
    return list;
  }

}
--/Runnablee2.jave--------------------------------
--console log-------------------------------------
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
Runnablee.threadId has the overrided get-method which returns next value.
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 1  (threadId: 1) [ 11394033 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 2  (threadId: 1) [ 4384790 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 3  (threadId: 1) [ 9634993 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 4  (threadId: 1) [ 1641745 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 5  (threadId: 1) [ 11077203 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 6  (threadId: 1) [ 14576877 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 7  (threadId: 1) [ 12677476 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 8  (threadId: 1) [ 33263331 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 9  (threadId: 1) [ 6413875 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(1): 10  (threadId: 1) [ 21174459 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 11  (threadId: 1) [ 827574 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 12  (threadId: 1) [ 17510567 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 13  (threadId: 1) [ 27744459 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 14  (threadId: 1) [ 6927154 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 15  (threadId: 1) [ 24355087 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 16  (threadId: 1) [ 5442986 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 17  (threadId: 1) [ 10891203 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 18  (threadId: 1) [ 9023134 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 19  (threadId: 1) [ 19336051 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(2): 20  (threadId: 1) [ 6336176 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 21  (threadId: 7) [ 21091971 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 22  (threadId: 7) [ 23746042 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 23  (threadId: 7) [ 3327002 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 24  (threadId: 7) [ 15244180 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 25  (threadId: 7) [ 20848735 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 26  (threadId: 7) [ 29324282 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 27  (threadId: 7) [ 5718203 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 28  (threadId: 8) [ 5947506 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 29  (threadId: 7) [ 1088076 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(3): 30  (threadId: 8) [ 131577 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 31  (threadId: 9) [ 12848256 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 32  (threadId: 10) [ 14410104 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 33  (threadId: 11) [ 28286498 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 34  (threadId: 12) [ 11988197 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 35  (threadId: 13) [ 24825485 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 36  (threadId: 13) [ 26130918 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 37  (threadId: 13) [ 21944831 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 38  (threadId: 12) [ 30028170 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 39  (threadId: 14) [ 24807699 ]
【TEST001】pkg.y2009.m06.test001.Runnablee(4): 40  (threadId: 13) [ 29193342 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
Runnablee2.threadId2 doesnt have the overrided get-method.
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 22485126 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 17514905 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 33536220 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 29459700 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 33537384 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 15472292 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 29530802 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 20591247 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 30246505 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(1): 1  (threadId: 1) [ 3373112 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 18468004 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 13249998 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 25516242 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 25839584 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 24431647 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 17108511 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 14831146 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 24756869 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 13755908 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(2): 1  (threadId: 1) [ 5510959 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 32320232 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 27010805 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 12694833 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 22982825 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 27284232 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 11227341 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 21352552 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 3  (threadId: 16) [ 7704521 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 2  (threadId: 15) [ 3341135 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(3): 3  (threadId: 16) [ 17905416 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 4  (threadId: 17) [ 23105029 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 5  (threadId: 18) [ 783148 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 6  (threadId: 19) [ 9042915 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 6  (threadId: 19) [ 16259139 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 5  (threadId: 18) [ 56667 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 4  (threadId: 17) [ 12893404 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 7  (threadId: 20) [ 4932403 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 6  (threadId: 19) [ 19456522 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 5  (threadId: 18) [ 17829242 ]
【TEST001】pkg.y2009.m06.test001.Runnablee2(4): 4  (threadId: 17) [ 15006066 ]
java.lang.ThreadGroup[name=main,maxpri=10]
  Thread[main,5,main]
--/console log------------------------------------
2009-06-22 01:37 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ XML

■XML@JAVA
↓4種類のパーサを使うことでJavaでXMLが扱える。
DOM:オブジェクトモデル
SAX:プッシュモデル
StAX(Streaming API for XML):プルモデル
JAXB

■プッシュ&プル
*プッシュモデル
 一方的にパーサがパースをしているAPを呼び出すイメージ。
 要するにイベント。
 SAXパーサは、
 XMLドキュメントを頭から読んでいき、
 タグの開始や終了に当たると、
 決められたアプリ側のコールバックルーチンをコールする仕組み。
 アプリ側は、
 XMLドキュメントの読み込みを制御は出来ず、
 コールバックルーチンをひたすら待つ。
*プッシュモデル
 アプリ側は、
 XMLドキュメントの読み込みを制御でき、
 必要に応じて、StAXパーサから情報を取得する構成。


XXX

ref:
http://www.javainthebox.net/laboratory/JavaSE6/stax/stax.html

tag : DOM SAX StAX JAXB

2009-06-15 23:18 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ データ構造

Javaが提供するデータ構造のIFは10以上

Collection(値の集合)
 |
 |―List(順序の保存)
 |  |
 |  |―Vector(JDK1.0)
 |  |
 |  |―ArrayList(JDK1.2)
 |  |
 |  |―LinkedList(JDK1.2)
 |
 |―Set(重複データ不可)
 |  |
 |  |―HashSet(JDK1.2)
 |  |
 |  |―SortedSet(並べ替え)
 |  |  |
 |  |  |―TreeSet(JDK1.2)
 |  |
 |  |―LinkedHashSet(JDK1.2)
 |
 |―Map(キーと値の集合)
 |  |
 |  |―HashTable(JDK1.0)
 |  |
 |  |―HashMap(JDK1.2)
 |  |
 |  |―SortedMap(並べ替え)
 |  |  |
 |  |  |―TreeMap(JDK1.2)
 |  |
 |  |―LinkedHashMap(JDK1.4)
 //

機能的には3種類
List
Set
Map

ListとSetが値の集合
Listは順序を保障し重複を許す
Setは重複は許さず追加順序は保障しない

TreeSetの場合 必ず並べ替えられた順序になり
LinkedHashSetは順序を保障する

Mapもキー重複を許さず追加順序を保障しない
※TreeMapの場合はキーで並べ替えられる


List/Set/Mapの使い分け基準
―Vector
  ○ X番目の値へのアクセス
  × 値の検索
  △ 末尾への追加
  × 挿入
  × 削除
―ArrayList
  ○ X番目の値へのアクセス
  × 値の検索
  △ 末尾への追加
  × 挿入
  × 削除
―LinkedList
  × X番目の値へのアクセス
  × 値の検索
  ○ 末尾への追加
  ○ 挿入
  ○ 削除
―HashSet
  × X番目の値へのアクセス
  ○ 値の検索
  - 末尾への追加
  ○ 挿入
  ○ 削除
―TreeSet
  × X番目の値へのアクセス
  △ 値の検索
  - 末尾への追加
  △ 挿入
  △ 削除

検索主体の場合はSetが有効
その中でも
値の並べ替えが必要な場合はTreeSetが有効

検索が少なく データの追加/削除が少ない場合はVector/ArrayList
検索が少なく データの追加/削除が多い場合はLinkedListが有効


ref:
http://www.fk.urban.ne.jp/home/kishida/kouza/kishou/10cont.html
2009-06-14 00:48 : __lang__java : コメント : 0 : トラックバック : 0 :

LINKS/ JAVA/ API

■Java EE APIs & Docs
http://java.sun.com/javaee/reference/

tag : LINKS JAVA API

2009-06-13 01:13 : __lang__java : コメント : 0 : トラックバック : 0 :

TIPS/ Java/ ログ出力

sysoutをコンソールに出せん時など、
とっさにログをファイルに残したい時の策。

JLoggerでのログ出力が本筋だが、
sysoutしてる箇所を全部JLoggerに書き換えるのは大変。
デバッグ目的なら、sysoutで十分だし。

⇒sysout先をコンソールからファイルに変えてしまう!

// これを一度どこかで呼んでおく。
System.setOut(new PrintStream(new FileOutputStream("data.txt")));

// 以降はprintするだけでファイルに書き出される
Sysatem.out.println("出力文字列");

ref:
http://www.sdls.jp/~barista/tech/java/maximT2.html

tag : TIPS

2009-06-13 01:12 : __lang__java : コメント : 0 : トラックバック : 0 :

正規表現

■env
@env J2SE1.3 or lower: jakarta ORO が必要
@env J2SE1.4 or higher: java.util.regexパッケージが必要
*jakarta ORO
 正規表現・glob表現・置き換え・分割・ファイル名のフィルタリング
 等のutilityを提供するテキスト処理ライブラリ
 http://jakarta.apache.org/oro/
 

ref:
http://programnet.hp.infoseek.co.jp/practical/regex.html


tag : regex

2009-06-11 22:43 : __lang__java : コメント : 0 : トラックバック : 0 :

JavaCommand

javaコマンド
Javaアプリを実行させるコマンド。
一般的には、
JVM起動→クラスのロード→処理実行
の順。
javaコマンドで実行されるクラスは、
以下シグニチャを持つmainメソッドがあること。
+アクセス修飾子がpublicである。
+staticメソッドである。
+voidである。
+メソッド名が[main]である。
+複数文字列を引数に受け取れる。
ex
java hogepackage.HogeMain
※実行するクラス名の指定は、
 FQCN(パッケージ名/クラス名を含む完全修飾名)形式であること。

■クラスローダ&クラスパス
クラスローダによるクラスファイルの検索パス
bootstrapに指定されたパス→拡張(extension)クラスパス→ユーザ定義クラスパス

□bootstrapクラスパス
javaの基本的なシステムクラス郡。
java.lang.Objectとか、java.lang.Exceptionとか。
デフォルトでは、JREインストールディレクトリ/lib/rt.jarファイルがそう。

□拡張クラスパス
Extension Frameworkに基づく拡張フォルダ。
デフォルトでは、JREインストールディレクトリ/lib/extフォルダがそう。

□ユーザクラスパス
ユーザが新規に作成したクラスファイルたち。
環境変数CLASSPATHで指定。

■インタプリタと動的コンパイラ(適応型コンパイラ)
インタプリタによるjavaバイトコードの実行よりネイティブコードの実行の方が高速。
が、一回しか実行しないプログラムの場合、ネイティブコードへの変換がコストになる。
→javaHotSpotVM使えば、
 一定回数実行された処理のみネイティブコードに変化
 →処理速度の向上。

■javaメモリ構造
□ヒープ
JVM毎に1つだけ割り当てられ、生成された全てのスレッドから共有される可変長のメモリ領域。
ヒープ内には、
クラスローダがロードしたクラス情報、クラスから生成されたインスタンス等が格納される。
ヒープ領域の管理は、
ガベッジコレクタが担当し、未使用の領域を開放する。
領域の断片化、絶対的の不足などで、
このヒープ領域が不足した場合に、java.lang.OutOfMemoryErrorが発生する。
この例外は、
-Xmxオプションで最大ヒープサイズを拡張して対処できる。
が、
一般的に、ヒープサイズが大きくなるほど、
ガベッジコレクションによるプログラムの中断時間が長くなる。
また、
ヒープサイズを小さくした場合、
ガベッジコレクションによるプログラム中断時間は短くなるが、実行頻度が増える。

□スタック
スレッドごとに保持される固定長のメモリ領域。
メソッド・変数に関する情報がここに格納される。
スタック領域は、LIFOのスタックから構成される。
スタック領域がふそくすると、
java.lang.StackOverflowErrorが発生する。
この例外は、
-Xssオプションでのスタックサイズの調整で対処できる。


ref:
http://www.stackasterisk.jp/tech/java/javaCommand01_01.jsp

tag : java

2009-06-10 00:20 : __lang__java : コメント : 0 : トラックバック : 0 :

Java/ Chap. 1

■souce file
there are 3 top level called compilation unit.
-package definition
-import definition
-class definition
you have to define these as the order above.

■キーワードと識別子
java has 52 keywords and reserved words.
識別子(identifier):
 プログラマが変数、メソッド、クラス、ラベルに名前を付ける為の単語
 1文字目は、英字、ドル記号($)、アンダーバー(_)であること

--keywords & reserved words--
abstract class false import package super try assert const final instanceof private switch void boolean continue finally int protected synchronized volatile break default float interface public this while byte do for long return throw case double goto native short throws catch else if new static transient char extends implements null strictfp true
--/keywords & reserved words--
※goto, const: ただの予約語で意味持たない。

■基本データ型
Javaの基本データ型(primitive data type)たち↓
boolean(1) char(16)
byte(8) short(16)
int(32) long(64)
float(32) double(64)
(有効表現サイズ/bit)


□符号付整数データ型
うち符号付の整数データ型が↓たち
byte 8bit min: -2^7 max: 2^7-1
short 16bit min: -2^15 max: 2^15-1
int 32bit min: -2~31 max: 2^31-1
long 64bit min: -2^63 max: 2^63-1
※いずれも2の補数

□char
符号なし整数
範囲: 0 ~ 2^16-1
上位9ビットが全て0の場合 エンコーディングは7ビットのASCIIに等しい

□Unicode
Javaの文字コード
広い範囲の国際的な文字の表記が可能
16bitのエンコーディング方式

□浮動小数点型
うち浮動小数点型が↓たち
float
double
数値で表せない値を表現するための型
↓が定義されている
-Float.NaN (Not a Number)
-Float.NEGATIVE_INFINITY
-Float.POSITIVE_INFINITY
-Double.NaN
-Double.NEGATIVE_INFINITY
-Double.POSITIVE_INFINITY

※数値の基本データ型(booleanとchar以外)は、全て符号付きである。

■リテラル (literal)
実行時に決定される値とは対照的に、プログラムソースで指定される値。

□boolean型のリテラル
boolean型のリテラルとして有効なのは、trueとfalseだけ。

□char型のリテラル
char型のリテラルを定義するには、
必要な文字を単一引用符で囲む。
もしくは、
Unicode値で定義する。
4桁の16進数を使用し、先頭に\uを付け、全体を単一引用符で囲む。
※先頭文字は、バックスラッシュか円符号。
※Javaがサポートする特殊文字のエスケープシーケンス
 -'\n' 改行
 -'\f' 改ページ
 -'\r' 復帰
 -'\'' 単一引用符
 -'\"' 二重引用符
 -'\t' タブ
 -'\b' バックスペース
 -'\\' バックスラッシュ

□整数型のリテラル
整数型のリテラルは、10進数、8進数、6進数で表される。
デフォルトは、10進数。
8進数であることを示すには、リテラルの先頭に0(ゼロ)を付ける。
16進数であることを示すには、リテラルの先頭に0xまたは0Xを付ける。

'28'であれば、'28', '034', '0x1c', 0x1C', '0X1c', '0X1C'で示せられる。

整数型のリテラルは32ビットん「値。
リテラルがlong(64ビット)であることを示すには、末尾にLを付ける。

□浮動小数点数型のリテラル
↓で浮動小数点数の数値を表す。
-小数点: 1.414
-科学表記のE(またはe): 4.23E+21
-float型のリテラルの接尾語F(またはf): 1.828f
-double型のリテラルを表す接尾語D(またはd): 1234d
※接尾語F/Dのない浮動小数点数型のリテラルは、デフォルトdouble型になる。

※オーバーフロー
 byte, short, char型の変数への代入は、
 代入値がその型で表現可能な範囲であれば、int型のリテラルの値を記述できる。
 ∵コンパイル時にオーバーフローを起こさないことが明白だから。
 ex
 short s = 8; →有効
 short s2 = 10 + s; →コンパイルエラー
  ∵10 + s のサイズはコンパイル時でなく実行時にjintで処理される。
    →精度が落ちている可能性有り

□文字列のリテラル
二重引用符(")で囲まれた文字の連なり。


■配列
Javaの配列は、
基本データ型、参照型、または他の配列からなる順序付きのコレクションである。
Javaの配列は「同種(homogeneous)」である。
つまり、
ポリモーフィズム許可されたものを除き、配列の全ての要素が同じ型でないといけん。
→配列を生成する際には、要素の型(クラス)を指定しないとダメ。

生成された配列を構成する要素は、
そのクラスのインスタンスか、そのサブクラスのインスタンスに限る。

配列生成手順
①宣言 declaration
②生成 construction
③初期化 initialization

二次元配列なら↓こんな感じ。
float[][] twoDee;

メソッド引数に指定するなら↓こんな感じ。
myMethod(double dubs[]) か myMethod(double[] dubs)

メソッド戻り値に指定するなら↓こんな感じ。
double[] anotherMethod() か anotherMethod() []

配列のサイズは、newする時に割り当てる。
int size = 10 * 8;
int[] intArray;
intArray = new int[size];
int[] intArray2 = new int[12];

要素は、自動的にデフォルト値で初期化される。
byte: 0
short: 0
int: 0
long: 0L
float: 0.0f
double 0.0d
char: '\u0000'
boolean: false
参照値: null



XXX


2009-06-04 00:36 : __lang__java : コメント : 0 : トラックバック : 0 :

java/ null check

□NULLでないことが確認されている変数のNULLチェックをしない
NULLを返さない仕様のメソッドの戻り値のNULLチェックはムダ。
ex
 Class.forNameは NULLを返さない(ref: org.w3c)
 dom.Element#getChildNodesはNULLを返さない
 StringBuffer#toStringはNULLを返さない


ref:
http://d.hatena.ne.jp/sawat/20070117/1169052896

tag : java

2009-04-23 23:44 : __lang__java : コメント : 0 : トラックバック : 0 :

Instance Initializer Block & Static Initializer Block

■コレクションの初期化
Static Initializer でなく Instance Initializer を使用すべし。
Javaでstatic finalな配列をpublicで公開すると要素が書き換えられてまう。

×public static final String VALUES = {"val1", "val2"};

コピーを返せないようにすべきで、不変(イミュータブル)でないオブジェクトをstatic finalで公開するのは、多くの場合NG!

○private static final String VALUES = {"val1", "val2"};
 public static String[] getValues() {
  return VALUES.clone();
 }


Javaの言語仕様上、配列要素の参照を不変に出来ないため、仕方なくコピーを返す
というイディオム。

目的がコピー編集再利用ならヨイが
コピーして返すのでヨイんなら↓みたくStatic Initializerで不変化すべし。

※Static Initializer
 Staticブロックでクラスロード時にクラスがロックされるためスレッドセーフなもの。

public static final List LIST;
static {
List tmp = new LinkedList();
tmp.add("要素1");
tmp.add("要素2");
LIST = Collections.unmodifiableList(tmp);
}

↑finalの場合、1度しか代入できないため、
tmpを使用してる分、なんか冗長なので、
あまり使われん手だけど
匿名クラスとインスタンスイニシャライザを使うべし↓。

public static final List LIST = Collections.unmodifiableList(new LinkedList(){{
add("要素1");
add("要素2");
}});

通常、
Static Initializerはクラスを初期化する唯一の方法なのに対し、
インスタンスの初期化は、Instance Initializer使わんでも、
コンストラクタで事足りる。
が、
匿名クラスではコンストラクタを記述できないため、
インスタンスイニシャライザを使う。

システム共通の定数リストや定数マップの実装に有効な手。


■インスタンス初期化子
クラスのインスタンス生成時に特定の処理を実装に使うもの。

*クラスの直下( class Hoge { /*ここ*/ } )に「{<処理>;...}」の形式で書く。
*インスタンス生成時「コンストラクタの前」に実行される。
 親クラスのインスタンスイニシャライザ
 →親クラスのコンストラクタ
 →クラスのインスタンスイニシャライザ
 →クラスのコンストラクタ
 の順。
*"this"が利用できる。
 ※Static Initializerでは、使用不可。


■無効なInstance Initializer Block
こんな記述も。。

↓実は無効なコード
------------------------------
HashMap map = new HashMap()
{
 {
  put("item1", "This is item1");
  put("item2", "This is item2");
 }
}
------------------------------
一見Mapオブジェクトのnewで実行されそうなものだけど
ゆわゆるオブジェクト生成時に実行されるイニシャライザブロックではないのだ。
やるなら匿名クラスか普通の別クラスですべし↓
------------------------------
public class Test extends HashMap
{
 {
  put("item1", "This is item1");
  put("item2", "This is item2");
 }
}
------------------------------
↑としとけば きちんとコンストラクタが呼ばれる前に実行される。


ref:
http://d.hatena.ne.jp/cypher256/20080114/p1
http://d.hatena.ne.jp/unageanu/20080118
http://www.xs4all.nl/~kzeil/en/project/java/initializer-block.html
2009-04-17 06:50 : __lang__java : コメント : 0 : トラックバック : 0 :

検査例外と実行時例外

■Javaの例外種類
-検査例外
-実行時例外
ざっくりコンパイルエラーなるか、ならないか、の違い。

■検査例外
Checked Exception
親:java.lang.Exception
throws:必須
try-catch:必須
例外の発生と捕捉が必ずチェックされる例外。
投げる側は、throwsし、呼び出す側は、try-catchする。
反すれば、コンパイルエラー。
例:
-SQLException
-RemoteException
-ParseException
-IOException

■実行時例外
Runtime Exception
親:java.lang.RuntimeException
throws:任意
try-catch:任意
実行ランタイム(=JVM)で発生する例外。
通常は発生してはいけないような実行ランタイムの異常状態を表現するための例外。
投げる側も、呼び出す側も、throws/try-catchの必要はない。
例:
-IllegalArgumentException
-IndexOutOfBoundsException
-NullPointerException
-ClassCastException
-BufferOverflowException
-MissingResourceException

ref:
http://blogs.msdn.com/nakama/archive/2009/01/09/net-java.aspx
2009-04-16 22:29 : __lang__java : コメント : 0 : トラックバック : 0 :

JAX-RPC & JAX-WS

Java API for XML Web Services
JavaEE5/JavaSE6の新機能
主にSOAPを使ったWebサービスを扱うためのAPI

JAX-RPC (Java API for XML-based RPC 1.1)の追加リリース分
JAX-RPCは リモートプロシージャに焦点当てたもの

JAX-WS
JAX-RPC+RPC以外のメッセージングでやり取りするWebサービス

Javaテクノロジを使用したWebサービスの開発作業を簡素化する

@WebService
@WebMethod
やらアノテーションWebサービスを公開できちゃう

WSDLの生成はwsgenコマンドを使用

SOAP1.1、SOAP1.2、XMLに加え、HTTP等のプロトコールを追加サポートで
JAX-RPC1.1の問題を解決

データバインディングにはJAXB2.0を使用
生成されたサービスエンドポイントインタフェースを
制御するためのカスタマイズをサポート
同時に開発の簡素化でJARファイルのサイズを削減


ref:
http://itpro.nikkeibp.co.jp/article/COLUMN/20080801/311972/?ST=develop
http://www.netbeans.org/kb/55/websvc-jax-ws_ja.html
http://www.ibm.com/developerworks/jp/webservices/library/ws-tip-jaxwsrpc.html

tag : JAX-WS JAX-RPC WebService

2009-02-13 00:36 : __lang__java : コメント : 0 : トラックバック : 0 :

Sizeof for Java

オブジェクトのサイズが知りたい!
ゆう時 Cやったら Sizeof なんゆう便利なやつがいてるらしい
が…ってゆう話。

【Q】Javaには Cのsizeof()的なやつはいるん?
【A】いない。
  ってか、なして欲しいん?
  Cプログラマは 自分でデータ構造や割り当てられたメモリをsizeofで知らにゃならんけど
  Javaは 必要ないやろ
  勝手にガーベッジコレクションが動いてくれるけ
  開発者はメモリうんぬんぬんを気にせんでもいいんやから
  確かに C/C++に比べたら Javaは物理メモリを占領しがちになってまうけど
  最近は32-bit JVMが普通やし
  やけ Java開発者は いくらメモリ占有してるかとか膨れすぎてないかとかを
  sizeof とかでチェックするなんゆう必要ないねん

【+】Javaのbasic typeのサイズは決まってるんやからsizeofは必要なか
 どんなJVMやろうがプラットホームやろうがJavaのintは32bit
 ゆうのがjavaの仕様であって開発者が知れる全て
 やけど64-bitのマシンやったら64-bitの物理メモリ使うまうことも
 プリミティブに限らず 参照型も同じこと
 Javaは 物理メモリの制限なんてしとらんねん。配列にしても同じこと

【+】オブジェクトとバイトストリームにシリアライズして その文字列長で オブジェクトのサイズが知れる
 シリアライズは 実際のメモリにあるものを反映したもの
 Stringがどれくらい2バイト文字列でメモリに保持されてるか
 がシリアライズすることで分かるゆうわけ
 シリアライズされた文字列のエンコードがUTF-8かASCII系だった場合は その半分のサイズ

ちなみに
Java Tip 130: Do You Know Your Data Size?: http://www.javaworld.com/javaworld/javatips/jw-javatip130.html

全く同じクラスインスタンスの大量生成での JVMの使用ヒープサイズの増加を測定中
この記事で紹介する方法に 代わる有効な手段よ
注意
静止しているJVMで同一クラスインスタンスを大量生成する方法だから
特定のオブジェクトのサイズを知りたい場合や
そのオブジェクトが実際にどれくらいのサイズかを測りたい場合は 他当たって。


【Q】オブジェクトのサイズって何よ?
【A】オブジェクトグラフやらオブジェクトのサイズやらは哲学的観点
  それらグラフデータが示すサイズゆうのは 知りたいオブジェクトインスタンスそのものサイズとちゃうのだ
  ビギナー向けにざっくり言うなら オブジェクトのサイズとは
  -オブジェクトに定義されたstaticでない全フィールドの合計サイズ(親クラスのフィールドも含む)
  -クラスメソッドは オブジェクトのサイズに影響しない(コレ、C++と違う点。)
  -インタフェースもオブジェクトサイズに影響なし(※)
  -結局 オブジェクト生成時状態である 全オブジェクトを終了させた時のサイズ
  ※インタフェースの実装は 単にそのクラスにマークを付けるだけで
   クラス定義にデータを追加するものでない
   実際にJVMも
   実装クラスの全メソッドがインタフェースに定義されてるかどうかのチェックをするだけ
   (最近コンパイラ仕様で厳しくなったとか)

【*】本題
  プリミティブ型を検証に使用↓な感じ
  (一般的な32-bit JVMなら java.lang.Objectで8バイト 基本データ(boolean以外)で定義分のメモリを要する)
  // java.lang.Object shell size in bytes:
  public static final int OBJECT_SHELL_SIZE = 8;
  public static final int OBJREF_SIZE = 4;
  public static final int LONG_FIELD_SIZE = 8;
  public static final int INT_FIELD_SIZE = 4;
  public static final int SHORT_FIELD_SIZE = 2;
  public static final int CHAR_FIELD_SIZE = 2;
  public static final int BYTE_FIELD_SIZE = 1;
  public static final int BOOLEAN_FIELD_SIZE = 1;
  public static final int DOUBLE_FIELD_SIZE = 8;
  public static final int FLOAT_FIELD_SIZE = 4;
  
  便宜上 オブジェクトインスタンスのサイズ以外に
  IObjectProfileNodesでデータ構造も出すっぺ

  interface IObjectProfileNode {
   Object object ();
   String name ();
  
   int size ();
   int refcount ();
  
   IObjectProfileNode parent ();
   IObjectProfileNode [] children ();
   IObjectProfileNode shell ();
  
   IObjectProfileNode [] path ();
   IObjectProfileNode root ();
   int pathlength ();
  
   boolean traverse (INodeFilter filter, INodeVisitor visitor);
   String dump ();
  } // End of interface

 

XXX



なんかUtilToolぽい
試しとらんが使えそう
http://sourceforge.net/projects/sizeof

ref:
Vladimir Roubtsov, Sizeof for Java, JavaWorld, 12/26/03
http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html

tag : DL sizeof java

2009-02-09 06:58 : __lang__java : コメント : 0 : トラックバック : 0 :

java.util.concurrent

Executors

非同期での処理実行
全ての処理(タスク)を処理するには
一つ一つのタスクのためのスレッドを容易するのではリソースの浪費に
→起動済みスレッドの再利用
java.util.concurrent.Executor(JDK5.0~)で
 スレッドの再利用、スケジューリング、並列処理を実現

IF Executor.execute(Runnable)

ex
// 1つのスレッドで複数タスクを処理するExecutorの取得
Executor e = Executors.newSingleThreadExecutor();
Runnable r1 = ...
Runnable r2 = ...
e.execute(r1);// タスクの実行
e.execute(r2);

methods;
Executors.newSingleThreadExecutor()
→1つのスレッドで複数タスクを処理するExecutorの取得
newFixedThreadPool()
→指定した数のスレッドを作成+タスクの実行
newCachedThreadPool()
→必要に応じてスレッドを自動生成+タスク実行


ExecutorService
ExecutorのサブIF
状態追跡やタスク中断を担当

methods;
execute()
→Executor.execute()
submit() return Future
→タスクの実行結果/処理状態の取得
shutdown()
→実行済みのタスクの継続実行+新規タスクの受付拒否
shutdownNow()
→実行中タスクの処理中断+待機タスクの処理停止


■ThreadPool
プールしておいたスレッドで
キューに追加されたタスクを順次実行
するマルチスレッドの1形式
必要以上にスレッドを作成しないことで リソースの浪費を避ける

Executor.newSingleThreadExecutor()
担当タスクがある限り 順次タスクを処理する1スレッドを生成する。

ex: newSingleThreadExecutor()
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyTask implents Runnable {
 private String tab = "";

 public MyTask (int tab) {
  for (int i = 0; i <= tab; i++) {
   this.tab += " ";
  }
 }

 public void run() {
  for (int i = 0; i < 3; i++) {
   syso(tab + i);
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {}
  }
 }

 public static void main(String[] args) {
  ExecutorService es = Executors.newSingleThreadExecutor();
  syso("[Sending Tasks...]");
  for (int i = 0; i < 3; i++) {
   es.execute( new MyTask( i*3 ) );
  }
  syso("[Finish Sending!]");
  ex.shutdown();
  syso("[ShutDown]");
 }
}


ex: newFixedThreadPool
public class MyTask ex PreviousMyTask impl Runnable {
 ...
 public static void main(String[] args) {
  ExecutorService es = Executors.newFixedThreadPool(2);// 使用するスレッドの数を指定
  syso("[Sending Tasks...]");
  for (int i = 0; i < 3; i++)
   es.execute( new MyTask( i*3 ) );// 指定数のスレッドを使いまわして複数タスクを処理
  syso("[Finish Sending!]");
  es.shutdown();
  syso("[ShutDown]");
 }
}


ex: newCachedThreadPool
public class MyTask ex PreviousMyTask impl Runnable {
 private int n;
 public MyTask(int n) {
  this.n = n;
 }

 public static void main(String[] args) {
  syso("Task" + n + " Start");
  try {
   Thread.sleep(1000);// 1秒休み
  } catch (Exception e){}
  syso("Task" + n + " End");
 }

 public static void main(String[] args) {
  ExecutorService es = Executors.newCachedThreadPool();
  Thread.currentThread().getThreadGroup().list();
  syso("Sending Tasks...");
  for (int i = 0; i < 3; i++) {
   ex.execute(new MyTask(i));
   Thread.currentThread().getThreadGroup().list();
   try {
    Thread.sleep(600);
   } catch (Exception e) {}
  }
  es.shutdown();
 }
}
→実行可能スレッド(全担当タスク完了状態)がなければ新規スレッドを生成
 実行可能スレッドがあれば そいつが新規タスクを受理
 実行可能スレッドは 一定時間内に新規タスクを受けなかった場合 削除される

ref:
http://www.techscore.com/tech/J2SE/Thread/7.html

tag : java.util.concurrent Executor Executors ExecutorService newSingleThreadExecutor newFixedThreadPool newCachedThreadPool

2009-02-09 05:25 : __lang__java : コメント : 0 : トラックバック : 0 :

Equals and Hash Code

イントロ

JavaのObjectが持つ下記メソッドについての話。
 * public boolean equals(Object obj)
 * public int hashCode()
あるクラスと別のクラスを比較する時や コレクションにオブジェクトを足す時に こやつらが重要になってくる。
SCJP 1.4対策にもヨイけど こやつらのメカニズムやお決まりごとを理解すれば何かと役立つはず。

【public boolean equals(Object obj)】

あるオブジェクト自身とそのequalsメソッドの引数で渡されるオブジェクトが同じかをチェックするメソッド。
Objectクラスに実装されているこのメソッドは 単純に 2つのオブジェクト参照が 同一オブジェクトを参照してるかチェックしてる。例えば、x == y みたいな。ゆわゆる"shallow comparison"(狭域比較?)で知られる比較。
が、equalsメソッドを独自実装すれば、"deep comparison"(広域比較?)での比較も可能。実際の関連データメンバも比較するやつ。そのオブジェクトが何のデータも持ってなければshallow comarisonと同じことやけど。

JDK 1.4 API によれば、Objectのequalsメソッドは、↓なもの。

なんか他のオブジェクトが指定のオブジェクトと等しいかを示す。

  * 参照値が同じであればtrueを返す。
  * x.equals(y)がtrueなら、y.equals(x)もtrueを返す。
  * x.equals(y)がtrueで、y.equals(z)もtrueなら、x.equals(z)もtrueを返す。
* It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
* For any non-null reference value x, x.equals(null) should return false.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values x and y, this method returns true if and only if x and y refer to the same object (x==y has the value true).

注意!基本的にオーバーライドされていてもハッシュコードメソッドをオーバーライドすること。オーバーライドで、オブジェクトの等価がハッシュコードの等価と同等になる。

The contract of the equals method precisely states what it requires. Once you understand it completely, implementation becomes relatively easy, moreover it would be correct. Let's understand what each of this really means.

1. Reflexive - It simply means that the object must be equal to itself, which it would be at any given instance; unless you intentionally override the equals method to behave otherwise.
2. Symmetric - It means that if object of one class is equal to another class object, the other class object must be equal to this class object. In other words, one object can not unilaterally decide whether it is equal to another object; two objects, and consequently the classes to which they belong, must bilaterally decide if they are equal or not. They BOTH must agree.
Hence, it is improper and incorrect to have your own class with equals method that has comparison with an object of java.lang.String class, or with any other built-in Java class for that matter. It is very important to understand this requirement properly, because it is quite likely that a naive implementation of equals method may violate this requirement which would result in undesired consequences.
3. Transitive - It means that if the first object is equal to the second object and the second object is equal to the third object; then the first object is equal to the third object. In other words, if two objects agree that they are equal, and follow the symmetry principle, one of them can not decide to have a similar contract with another object of different class. All three must agree and follow symmetry principle for various permutations of these three classes.
Consider this example - A, B and C are three classes. A and B both implement the equals method in such a way that it provides comparison for objects of class A and class B. Now, if author of class B decides to modify its equals method such that it would also provide equality comparison with class C; he would be violating the transitivity principle. Because, no proper equals comparison mechanism would exist for class A and class C objects.
4. Consistent - It means that if two objects are equal, they must remain equal as long as they are not modified. Likewise, if they are not equal, they must remain non-equal as long as they are not modified. The modification may take place in any one of them or in both of them.
5. null comparison - It means that any instantiable class object is not equal to null, hence the equals method must return false if a null is passed to it as an argument. You have to ensure that your implementation of the equals method returns false if a null is passed to it as an argument.
6. EqualsHash Code の関係 - The last note from the API documentation is very important, it states the relationship requirement between these two methods. It simply means that if two objects are equal, then they must have the same hash code, however the opposite is NOT true. This is discussed in details later in this article.

The details about these two methods are interrelated and how they should be overridden correctly is discussed later in this article.

【public int hashCode()】

オブジェクトのハッシュコードを、Hashtable, HashMap, HashSetとかハッシュベースのコレクションに有効なIntegerで返すメソッド。This method must be overridden in every class that overrides the equals method.

This is what the JDK 1.4 API documentation says about the hashCode method of Object class-

Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

* The general contract of hashCode is: Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
* If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
* It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

As compared to the general contract specified by the equals method, the contract specified by the hashCode method is relatively simple and easy to understand. It simply states two important requirements that must be met while implementing the hashCode method. The third point of the contract, in fact is the elaboration of the second point. Let's understand what this contract really means.

1. Consistency during same execution - Firstly, it states that the hash code returned by the hashCode method must be consistently the same for multiple invocations during the same execution of the application as long as the object is not modified to affect the equals method.
2. Hash Code & Equals relationship - The second requirement of the contract is the hashCode counterpart of the requirement specified by the equals method. It simply emphasizes the same relationship - equal objects must produce the same hash code. However, the third point elaborates that unequal objects need not produce distinct hash codes.

After reviewing the general contracts of these two methods, it is clear that the relationship between these two methods can be summed up in the following statement -

Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.

The rest of the requirements specified in the contracts of these two methods are specific to those methods and are not directly related to the relationship between these two methods. Those specific requirements are discussed earlier. This relationship also enforces that whenever you override the equals method, you must override the hashCode method as well. Failing to comply with this requirement usually results in undetermined, undesired behavior of the class when confronted with Java collection classes or any other Java classes.

Correct Implementation Example

The following code exemplifies how all the requirements of equals and hashCode methods should be fulfilled so that the class behaves correctly and consistently with other Java classes. This class implements the equals method in such a way that it only provides equality comparison for the objects of the same class, similar to built-in Java classes like String and other wrapper classes.

1. public class Test
2. {
3. private int num;
4. private String data;
5.
6. public boolean equals(Object obj)
7. {
8. if(this == obj)
9. return true;
10. if((obj == null) || (obj.getClass() != this.getClass()))
11. return false;
12. // object must be Test at this point
13. Test test = (Test)obj;
14. return num == test.num &&
15. (data == test.data || (data != null && data.equals(test.data)));
16. }
17.
18. public int hashCode()
19. {
20. int hash = 7;
21. hash = 31 * hash + num;
22. hash = 31 * hash + (null == data ? 0 : data.hashCode());
23. return hash;
24. }
25.
26. // other methods
27. }


Now, let's examine why this implementation is the correct implementation. The class Test has two member variables - num and data. These two variables define state of the object and they also participate in the equals comparison for the objects of this class. Hence, they should also be involved in calculating the hash codes of this class objects.

Consider the equals method first. We can see that at line 8, the passed object reference is compared with this object itself, this approach usually saves time if both the object references are referring to the same object on the heap and if the equals comparison is expensive. Next, the if condition at line 10 first checks if the argument is null, if not, then (due to the short-circuit nature of the OR || operator) it checks if the argument is of type Test by comparing the classes of the argument and this object. This is done by invoking the getClass() method on both the references. If either of these conditions fails, then false is returned. This is done by the following code -
if((obj == null) || (obj.getClass() != this.getClass())) return false; // prefer
This conditional check should be preferred instead of the conditional check given by -
if(!(obj instanceof Test)) return false; // avoid
This is because, the first condition (code in blue) ensures that it will return false if the argument is a subclass of the class Test. However, in case of the second condition (code in red) it fails. The instanceof operator condition fails to return false if the argument is a subclass of the class Test. Thus, it might violate the symmetry requirement of the contract. The instanceof check is correct only if the class is final, so that no subclass would exist. The first condition will work for both, final and non-final classes. Note that, both these conditions will return false if the argument is null. The instanceof operator returns false if the left hand side (LHS) operand is null, irrespective of the operand on the right hand side (RHS) as specified by JLS 15.20.2. However, the first condition should be preferred for better type checking.

This class implements the equals method in such a way that it provides equals comparison only for the objects of the same class. Note that, this is not mandatory. But, if a class decides to provide equals comparison for other class objects, then the other class (or classes) must also agree to provide the same for this class so as to fulfill the symmetry and reflexivity requirements of the contract. This particular equals method implementation does not violate both these requirements. The lines 14 and 15 actually perform the equality comparison for the data members, and return true if they are equal. Line 15 also ensures that invoking the equals method on String variable data will not result in a NullPointerException.
While implementing the equals method, primitives can be compared directly with an equality operator (==) after performing any necessary conversions (Such as float to Float.floatToIntBits or double to Double.doubleToLongBits). Whereas, object references can be compared by invoking their equals method recursively. You also need to ensure that invoking the equals method on these object references does not result in a NullPointerException.

Here are some useful guidelines for implementing the equals method correctly.

1. Use the equality == operator to check if the argument is the reference to this object, if yes. return true. This saves time when actual comparison is costly.
2. Use the following condition to check that the argument is not null and it is of the correct type, if not then return false.
if((obj == null) || (obj.getClass() != this.getClass())) return false;
Note that, correct type does not mean the same type or class as shown in the example above. It could be any class or interface that one or more classes agree to implement for providing the comparison.
3. Cast the method argument to the correct type. Again, the correct type may not be the same class. Also, since this step is done after the above type-check condition, it will not result in a ClassCastException.
4. Compare significant variables of both, the argument object and this object and check if they are equal. If *all* of them are equal then return true, otherwise return false. Again, as mentioned earlier, while comparing these class members/variables; primitive variables can be compared directly with an equality operator (==) after performing any necessary conversions (Such as float to Float.floatToIntBits or double to Double.doubleToLongBits). Whereas, object references can be compared by invoking their equals method recursively. You also need to ensure that invoking equals method on these object references does not result in a NullPointerException, as shown in the example above (Line 15).
It is neither necessary, nor advisable to include those class members in this comparison which can be calculated from other variables, hence the word "significant variables". This certainly improves the performance of the equals method. Only you can decide which class members are significant and which are not.
5. Do not change the type of the argument of the equals method. It takes a java.lang.Object as an argument, do not use your own class instead. If you do that, you will not be overriding the equals method, but you will be overloading it instead; which would cause problems. It is a very common mistake, and since it does not result in a compile time error, it becomes quite difficult to figure out why the code is not working properly.
6. Review your equals method to verify that it fulfills all the requirements stated by the general contract of the equals method.
7. Lastly, do not forget to override the hashCode method whenever you override the equals method, that's unpardonable. ;)

Now, let's examine the hashCode method of this example. At line 20, a non-zero constant value 7 (arbitrary) is assigned to an int variable hash. Since the class members/variables num and data do participate in the equals method comparison, they should also be involved in the calculation of the hash code. Though, this is not mandatory. You can use subset of the variables that participate in the equals method comparison to improve performance of the hashCode method. Performance of the hashCode method indeed is very important. But, you have to be very careful while selecting the subset. The subset should include those variables which are most likely to have the greatest diversity of the values. Sometimes, using all the variables that participate in the equals method comparison for calculating the hash code makes more sense.
This class uses both the variables for computing the hash code. Lines 21 and 22 calculate the hash code values based on these two variables. Line 22 also ensures that invoking hashCode method on the variable data does not result in a NullPointerException if data is null. This implementation ensures that the general contract of the hashCode method is not violated. This implementation will return consistent hash code values for different invocations and will also ensure that equal objects will have equal hash codes.
While implementing the hashCode method, primitives can be used directly in the calculation of the hash code value after performing any necessary conversions, such as float to Float.floatToIntBits or double to Double.doubleToLongBits. Since return type of the hashCode method is int, long values must to be converted to the integer values. As for hash codes of the object references, they should be calculated by invoking their hashCode method recursively. You also need to ensure that invoking the hashCode method on these object references does not result in a NullPointerException.

Writing a very good implementation of the hashCode method which calculates hash code values such that the distribution is uniform is not a trivial task and may require inputs from mathematicians and theoretical computer scientist. Nevertheless, it is possible to write a decent and correct implementation by following few simple rules.

Here are some useful guidelines for implementing the hashCode method correctly.

1. Store an arbitrary non-zero constant integer value (say 7) in an int variable, called hash.
2. Involve significant variables of your object in the calculation of the hash code, all the variables that are part of equals comparison should be considered for this. Compute an individual hash code int var_code for each variable var as follows -
1. If the variable(var) is byte, char, short or int, then var_code = (int)var;
2. If the variable(var) is long, then var_code = (int)(var ^ (var >>> 32));
3. If the variable(var) is float, then var_code = Float.floatToIntBits(var);
4. If the variable(var) is double, then -
long bits = Double.doubleToLongBits(var);
var_code = (int)(bits ^ (bits >>> 32));
5. If the variable(var) is boolean, then var_code = var ? 1 : 0;
6. If the variable(var) is an object reference, then check if it is null, if yes then var_code = 0; otherwise invoke the hashCode method recursively on this object reference to get the hash code. This can be simplified and given as -
var_code = (null == var ? 0 : var.hashCode());
3. Combine this individual variable hash code var_code in the original hash code hash as follows -
hash = 31 * hash + var_code;
4. Follow these steps for all the significant variables and in the end return the resulting integer hash.
5. Lastly, review your hashCode method and check if it is returning equal hash codes for equal objects. Also, verify that the hash codes returned for the object are consistently the same for multiple invocations during the same execution.

The guidelines provided here for implementing equals and hashCode methods are merely useful as guidelines, these are not absolute laws or rules. Nevertheless, following them while implementing these two methods will certainly give you correct and consistent results.

Summary & Miscellaneous Tips

* Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.
* The equals method provides "deep comparison" by checking if two objects are logically equal as opposed to the "shallow comparison" provided by the equality operator ==.
* However, the equals method in java.lang.Object class only provides "shallow comparison", same as provided by the equality operator ==.
* The equals method only takes Java objects as an argument, and not primitives; passing primitives will result in a compile time error.
* Passing objects of different types to the equals method will never result in a compile time error or runtime error.
* For standard Java wrapper classes and for java.lang.String, if the equals argument type (class) is different from the type of the object on which the equals method is invoked, it will return false.
* The class java.lang.StringBuffer does not override the equals method, and hence it inherits the implementation from java.lang.Object class.
* The equals method must not provide equality comparison with any built in Java class, as it would result in the violation of the symmetry requirement stated in the general contract of the equals method.
* If null is passed as an argument to the equals method, it will return false.
* Equal hash codes do not imply that the objects are equal.
* return 1; is a legal implementation of the hashCode method, however it is a very bad implementation. It is legal because it ensures that equal objects will have equal hash codes, it also ensures that the hash code returned will be consistent for multiple invocations during the same execution. Thus, it does not violate the general contract of the hashCode method. It is a bad implementation because it returns same hash code for all the objects. This explanation applies to all implementations of the hashCode method which return same constant integer value for all the objects.
* In standard JDK 1.4, the wrapper classes java.lang.Short, java.lang.Byte, java.lang.Character and java.lang.Integer simply return the value they represent as the hash code by typecasting it to an int.
* Since JDK version 1.3, the class java.lang.String caches its hash code, i.e. it calculates the hash code only once and stores it in an instance variable and returns this value whenever the hashCode method is called. It is legal because java.lang.String represents an immutable string.
* It is incorrect to involve a random number directly while computing the hash code of the class object, as it would not consistently return the same hash code for multiple invocations during the same execution.

Review Questions

The review questions are available separately - here.


ref:
http://www.geocities.com/technofundo/tech/java/equalhash.html

続きを読む

tag : Equals Hash Code TODO

2009-01-25 01:00 : __lang__java : コメント : 0 : トラックバック : 0 :
ホーム  次のページ »

search

ad



counter


tag cloud

category cloud