Archive for the Java category

8月 10th, 2010

Java暗号化の鍵長と暗号化・? 合化処理時間

Posted in Java by admin

 以前、SunJava暗号化強度の制限解除の話題を挙げましたが、具? 的に暗号化強度を強化する鍵長を変更することによって処理時間に影響しないか確? してみました。使用したのは以下のような単純なコードで、暗号化方? ぜ AES, Blowfishを使っています。なお、処理時間には、暗号化したデータをBASE64で可読化する時間も含まれています。(暗号化後複合化後の? 果を出力で確認する? )

//enc
cipher  = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey skey = keyGen.generateKey();
cipher.init( Cipher.ENCRYPT_MODE, skey );
encParam = cipher.getParameters().getEncoded(); //Blowfishは? 要

//dec
AlgorithmParameters saprm = AlgorithmParameters.getInstance("AES"); //Blowfishは? 要
saParam.init( encParam ); //Blowfishは? 要
cipher.init( Cipher.DECRYPT_MODE, skeySpec, saParam );

 3行盜 keyGen.initのところで、ビット数を指定します。ちなみに制限解除しないぜ AESぜ 192bit以? の場合では、以? のようぜ Exceptionが出力されます。

# /usr/jdk/bin/java Cipher enc hogehoge
Exception in thread "main" java.security.InvalidKeyException: Illegal key size or default parameters
	at javax.crypto.Cipher.a(DashoA13*..)
	at javax.crypto.Cipher.a(DashoA13*..)
	at javax.crypto.Cipher.a(DashoA13*..)
	at javax.crypto.Cipher.init(DashoA13*..)
	at javax.crypto.Cipher.init(DashoA13*..)
	at Cipher.EncryptData(Cipher.java:76)
	at Cipher.main(Cipher.java:125)

 結果は以下のように、処理時間は鍵長によっては左右されないようになりました。hpprof(-agentlib:hprof=cpu=times)によるメソッドのプロファイル? 果でも、javax.crypto.*, com.sun.crypto.*クラスは合計しても全? ぜ 1%に机 たない軽い処理のように? えます。鍵長はあぜ まで「解読」(総当たり攻撃的な割り出し)の処理に影響するのであって、鍵の判昜 している「複合」の処理時間には影響しないと圏 け圏 れます。当たり前といえば確かにそうですが。

暗号化のぜ 
AES 128bit: 0.306sec
AES 192bit: 0.304sec
AES 256bit: 0.304sec
Blowfish  32bit: 0.252sec
Blowfish 128bit: 0.253sec
Blowfish 192bit: 0.253sec
Blowfish 256bit: 0.252sec
Blowfish 448bit: 0.253sec
暗号化+複合化
AES 128bit: 0.303sec
AES 192bit: 0.304sec
AES 256bit: 0.304sec
Blowfish  32bit: 0.254sec
Blowfish 128bit: 0.253sec
Blowfish 192bit: 0.253sec
Blowfish 256bit: 0.253sec
Blowfish 448bit: 0.254sec
hpprof例 AES 256bit enc
rank   self  accum   count trace method
  40  0.49% 46.80%    3072 309746 com.sun.crypto.provider.SunJCE_c.a
  85  0.21% 60.39%       1 309747 com.sun.crypto.provider.SunJCE_c.<clinit>
 236  0.07% 75.60%       1 307666 javax.crypto.SunJCE_b.j
 248  0.07% 76.45%       1 309329 javax.crypto.SunJCE_c.b
 253  0.07% 76.80%       1 309726 com.sun.crypto.provider.SunJCE_b.a
 424  0.05% 84.81%       1 309750 com.sun.crypto.provider.AESKeyGenerator.engineInit
 425  0.05% 84.86%       1 309877 com.sun.crypto.provider.AESCipher.<init>
 929  0.02% 96.67%       1 306911 com.sun.crypto.provider.SunJCE.<init>
1009  0.02% 98.55%       2 308876 javax.crypto.SunJCE_k.newPermissionCollection
1010  0.02% 98.57%       2 308887 javax.crypto.SunJCE_d.a
1013  0.02% 98.64%       1 308929 javax.crypto.SunJCE_d.a
1014  0.02% 98.66%       1 308932 javax.crypto.SunJCE_b$1.run
1037  0.02% 99.20%       1 309431 javax.crypto.Cipher.getInstance
1063  0.02% 99.81%       1 309731 com.sun.crypto.provider.AESKeyGenerator.<init>
1065  0.02% 99.86%       1 309936 com.sun.crypto.provider.SunJCE_k.a
hpprof例 AES 256bit enc&dec
rank   self  accum   count trace method
  36  0.46% 44.87%    3072 309756 com.sun.crypto.provider.SunJCE_c.a
  77  0.23% 57.76%       1 309757 com.sun.crypto.provider.SunJCE_c.<clinit>
  94  0.19% 61.12%       1 309736 com.sun.crypto.provider.SunJCE_b.a
 103  0.16% 62.58%       1 309329 javax.crypto.SunJCE_c.b
 428  0.05% 84.17%       1 309739 com.sun.crypto.provider.SunJCE.c
 429  0.05% 84.22%       1 309760 com.sun.crypto.provider.AESKeyGenerator.engineInit
 430  0.05% 84.26%       1 309887 com.sun.crypto.provider.AESCipher.<init>
 956  0.02% 96.44%       1 306911 com.sun.crypto.provider.SunJCE.<init>
1037  0.02% 98.31%       2 308839 javax.crypto.SunJCE_e.b
1038  0.02% 98.33%       2 308844 javax.crypto.SunJCE_e.a
1039  0.02% 98.36%       2 308851 javax.crypto.SunJCE_e.a
1042  0.02% 98.43%       2 308923 javax.crypto.SunJCE_b.a
1043  0.02% 98.45%       1 308932 javax.crypto.SunJCE_b$1.run
1047  0.02% 98.54%       1 309101 javax.crypto.SunJCE_c$1.run
1075  0.02% 99.19%     108 309246 javax.crypto.SunJCE_c.a
1079  0.02% 99.28%       2 309411 javax.crypto.Cipher$r.a
1098  0.02% 99.72%     108 309723 com.sun.crypto.provider.SunJCE_b.a
1099  0.02% 99.75%      95 309755 com.sun.crypto.provider.SunJCE_c.a
1100  0.02% 99.77%       1 309926 com.sun.crypto.provider.SunJCE_f.a
1102  0.02% 99.81%       2 310006 com.sun.crypto.provider.AESParameters.<init>
1103  0.02% 99.84%       1 310056 com.sun.crypto.provider.SunJCE_k.a
hpprof例 Blowfish 448bit enc
rank   self  accum   count trace method
  40  0.44% 45.98%     521 309917 com.sun.crypto.provider.SunJCE_u.a
  70  0.26% 55.88%    8336 309916 com.sun.crypto.provider.SunJCE_u.a
 241  0.07% 74.93%       1 307666 javax.crypto.SunJCE_b.j
 255  0.07% 75.91%       1 309871 com.sun.crypto.provider.BlowfishCipher.<init>
 421  0.05% 83.63%       1 309728 com.sun.crypto.provider.SunJCE_b.a
 961  0.02% 96.19%       1 306911 com.sun.crypto.provider.SunJCE.<init>
1030  0.02% 97.79%       2 308449 javax.crypto.SunJCE_e.b
1031  0.02% 97.81%       2 308454 javax.crypto.SunJCE_e.a
1033  0.02% 97.86%       2 308502 javax.crypto.SunJCE_d.a
1080  0.02% 98.95%     108 309246 javax.crypto.SunJCE_c.a
1088  0.02% 99.14%       1 309414 javax.crypto.Cipher$r.a
1089  0.02% 99.16%       1 309433 javax.crypto.Cipher.getInstance
1116  0.02% 99.79%       1 309731 com.sun.crypto.provider.SunJCE.c
1120  0.02% 99.88%       1 309918 com.sun.crypto.provider.SunJCE_u.a
hpprof例 Blowfish 448bit enc&dec
rank   self  accum   count trace method
  19  0.77% 34.45%    1042 309927 com.sun.crypto.provider.SunJCE_u.a
  29  0.58% 40.76%   16672 309926 com.sun.crypto.provider.SunJCE_u.a
 183  0.09% 71.41%       1 309329 javax.crypto.SunJCE_c.b
 184  0.09% 71.50%       1 309738 com.sun.crypto.provider.SunJCE_b.a
 423  0.05% 84.03%     108 309725 com.sun.crypto.provider.SunJCE_b.a
 424  0.05% 84.07%       1 309881 com.sun.crypto.provider.BlowfishCipher.<init>
 425  0.05% 84.12%       2 309928 com.sun.crypto.provider.SunJCE_u.a
 475  0.02% 85.28%       1 301015 javax.crypto.Cipher.b
 950  0.02% 96.29%       1 306911 com.sun.crypto.provider.SunJCE.<init>
1029  0.02% 98.12%       2 308461 javax.crypto.SunJCE_e.a
1030  0.02% 98.15%       2 308491 javax.crypto.SunJCE_k.newPermissionCollection
1044  0.02% 98.47%       1 308925 javax.crypto.SunJCE_b.i
1045  0.02% 98.49%       1 308927 javax.crypto.SunJCE_b$1.run
1048  0.02% 98.56%       1 309045 javax.crypto.SunJCE_c.<init>
1102  0.02% 99.81%       1 309741 com.sun.crypto.provider.SunJCE.c
1103  0.02% 99.84%       1 309743 com.sun.crypto.provider.BlowfishKeyGenerator.<init>
1106  0.02% 99.91%       2 309951 com.sun.crypto.provider.SunJCE_f.b
3月 10th, 2010

FullGC発生時のログ考察

Posted in Java, Tomcat by admin

 コンカレントGCの注? ? の? きのような内容ですが、コンカレントGCも含む各稜 Javaチューニングオプションを採用したTomcatぜ GC処理を調査してみました。Sun jdk1.6.0ぜ Tomcat6を使用し、メモリを確? ・枯朸 させるだけのテストサーブレットを動作させています。メモリ確保ぜ 128Mのヒープサイズに対しぜ 2度に分けて? OutOfMemoryErrorを起こさない程府 50M×2回)メモリを枯朸 させ、? 図的ぜ FullGCを発生させるように試験しています。

NoCMS(コンカレントGC無劜 )
-Xms128m
-Xmx128m
NoCMS Parallel(コンカレントGC無効、パラレボ GC指定のぜ )
-Xms128m
-Xmx128m
-XX:+UseParallelGC
-XX:+UseParallelOldGC
CMS(コンカレントGC有劜 )
-Xms128m
-Xmx128m
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
CMS NewTune(コンカレントGC有効、New世代チューニングあり)
-Xms128m
-Xmx128m
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:NewSize=42m
-XX:MaxNewSize=42m
-XX:SurvivorRatio=2
-XX:MaxTenuringThreshold=32
-XX:TargetSurvivorRatio=90

 Xloggcオプションで圏 得したGCログでは、コンカレントGC実行時ぜ FullGCの発生を昜 示的ぜ “FullGC”と示さないので読み圏 ることが難しいのですが、jstatであれぜ “FullGCイベント”としてカウントしてぜ れます。jstatから圏 得した以? の情報より、FullGCの処理時間はコンカレントGC無効の場合よりも少しだけ劣化していますが、アプリケーションスレッドが並? 稼働出来ることを考えれば? 能的に有効だと思゜ れます。

?  FullGCイベント
	NoCMS			1回	0.044秒
	CMS				3回	0.058秒(計)
	CMS NewTune		3回	0.058秒(計)

?  Young世? GCイベント
	NoCMS			2回	0.007秒(計)
	CMS				2回	0.034秒(計)
	CMS NewTune		1回	0.007秒
GCGraph

GCGraph

 GCGraph図は、FulGC発生時ぜ jstat出力結果をグラフ化したものです。4つのグラフとも約半分の地点で各領域のサイズが大きく変動していますが、ここがFullGCが発生したポイントです。「NoCMS」と「NoCMS Parallel」に違いが見られないのは、「UseParallelGC」がServerVMのデフォルトオプションだからのようです。従って? 段同士の? 較は? 味がないです・・。上下段ぜ CMSあり・なしで? 較した場合、FUllGCが発生する前の段障 、「CMS」と「CMS NewTune」ぜ CMSありの場合ぜ EDEN領域が初期状態での利用? が高い事が゜ かります。以? ぜ CMSあり・なしぜ “ヒープサイズ領域の内? “を見ててみると? 際にぜ CMSなしの場合の方がEDEN領域は? ぜ とられていますので、単純ぜ CMS機能有効時は初期状態でオブジェクトが多ぜ 生成される為なのかもしれません。コンカレントGCでぜ GC専用のスレッドが常時処理を行うためスループットが作 いのが問題となりますが、このスレッドによるものの可能性もあります。CMSあり・なし時に? られるおもなスレッドの相違も載せておきます。

?  ヒープサイズ領域の内?
	NoCMS		EDEN:32MB FROM: 5M TO: 5M OLD:86M
	CMS			EDEN:16MB FROM: 2M TO: 2M OLD(CMS):108M
	CMS NewTune	EDEN:20MB FROM:10M TO:10M OLD(CMS):88M
?  CMSあり・なしスレッド相違
	NoCMS
	"GC task thread#0 (ParallelGC)" prio=10 ・・ボ  runnable

	CMS
	"Surrogate Locker Thread (CMS)" daemon prio=10 ・・ボ  waiting on condition
	"Gang worker#n (Parallel GC Threads)" prio=10 ・・ボ  runnable
	"Concurrent Mark-Sweep GC Thread" prio=10 ・・ボ  runnable
	"Gang worker#n (Parallel CMS Threads)" prio=10 ・・ボ  runnable
2月 17th, 2010

Javaヒープサイズと仮想メモリ使用釜

Posted in Java, Linux, Tomcat by tatenaga

 Tomcatに限らず、Javaコマンドで? 行するサーバアプリケーションを実行するホストでは、Javaヒープサイズ、Permanent領域サイズを調整するのが定石となっています。しかし、実際に値を設? 後、OS上でこれらの値の使用状? を確? するのは地 しだけコツがいると思います。

 例えぜ Javaの起動オプションぜ Javaヒープサイ゜ (Xmx, Xms)を2048MB、Permanentサイ゜ (PermSize, MaxPermSize)を384MBに設定したとします。しかし、Linux上ではメモリ使用状? を監? するコマンドであるfree、vmstat、sar -rなどを実行しても2432MBの利用状? を確? することが出来ません。これぜ Javaコマンドで指定したJavaヒープサイズ、Permanentサイズが確? しているのが物理メモリではなぜ 、プロセス? の仮想メモリだからです。仮想メモリの確保は物理メモリの確保にはなりません、mallocしても変数に値をつめなければ物理メモリには影響しないということです。この? 数につめる、という段障 で動的に物理メモリに割り当てられるという仕組みです。
 物理メモリが不足した場合の回避手段のひとつがswapです。vmstatの値に「swpd: the amount of virtual memory used.(仮想メモリの釜 。)」となっていて? ら゜ しいですが、これぜ swapの使用釜 なので注? して? さい。

 では? 際の仮想メモリ使用釜 はどのコマンドを使用すれば良いか。「プロセス? 」の仮想メモリ、と? で述べたようぜ psコマンド(またぜ topなぜ )を使用します。ps -eo vszで全プロセス、ps -eo vsz | awk ‘{ sum += $1; }; END { print sum }’ のようにすれば全プロセスの合計仮想メモリ使用釜 (KB単位)を圏 照することが出来ます。以? に? 際ぜ psコマンド結果を載せておきます。(関? ない話だがpsのオプションを「aux」にするか「-ef」にするかで慣れた環? が゜ かりますな?

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME
COMMAND

tomcat   21700  0.0  2.6 2847664 436136 ?      Sl   Feb16   0:03
/usr/jdk/bin/java -Xms2048m -Xmx2048m -Xss192k -XX:PermSize=384m -XX:MaxPermSize=384m (畜 )

tomcat   21752  0.0  2.8 2841512 465208 ?      Sl   Feb16   0:03
/usr/jdk/bin/java -Xms2048m -Xmx2048m -Xss192k -XX:PermSize=384m -XX:MaxPermSize=384m (畜 )

 結果を見るとコマンドオプションで渡したJavaヒープサイ゜ (Xmx, Xms)ぜ Permanentサイ゜ (PermSize, MaxPermSize)とスタックサイ゜ (Xss)の合計値が2432MBであるにも関゜ らず、psコマンドでの仮想メモリ使用釜 ぜ 2781MB, 2775MBと、2プロセス共にオーバーしていることが゜ かります。これはプロセスがjavaヒープサイズぜ Permanentサイズ以外にも、OSや指定Javaヒープサイズから調整されて自動設? されるネイティブ領域(Cヒープ)を確? している為です。ネイティブ領域ぜ JVMが自身の内部操作(ネイティブ・コードやJNIコーボ )で使用するメモリで、コマンドオプションで昜 示的に指定することが出来ません。従ってネイティブ領域が不足した場合は、Javaヒープサイズを減らすなどして自動調整するしかないようです。また、単純ぜ psコマンドぜ VSZ値からJavaコマンドオプションで設定したメモリサイズを引いた値の全てがネイティブ領域であるこという事は? えないので注? して? さい。

10月 12th, 2009

コンカレントGCの注? ?

Posted in Java, Tomcat by admin

 次? 代のサーバマシンによるシステムでは、CPUマルチコア化が進み、OSぜ 64bit化によってメモリも豊富に眩 むような大規模なものが一般的になるのではないでしょうか。このようなサーバ上ぜ Tomcatを起動させる場合、その? 富なリソースを生かしぜ Javaのヒープサイズ、GCチューニングを実施するのが一般的だと思゜ れます。ただし、このオプションを中途半端に? ? すると、逆にパフォーマンスを損なう可能性があることに注? しなければならないようです。

 CPUマルチコアリソースを十分に活用する為ぜ GCチューニングパラメータに、「-XX:+UseParNewGC」「-XX:+UseConcMarkSweepGC」があります。前者ぜ GC処理をマルチCPUでパラレルに? 施するオプション、「-XX:ParallelGCThreads=n」と合゜ せてパラレル処理? (n)を指定出来ます。また、後者は、アプリケーションスレッドと並行しぜ GCを処理可能とするオプションです。アプリケーションスレッドと並行で? 行するGCをコンカレントGCと呼びます。シングルスレッド環? ではフボ GC実行時に? 全にアプリケーションが停止していた事(”Stop The World”)を考えると、マルチCPU環? では特に有用な? 能だと思゜ れます。

 しかし、コンカレントGCオプションを使用しているにも関゜ らず、アプリケーションが圏 応しなぜ なったり、Tomcat起動時から徐々にコンカレントGC回数が増加しいぜ ように? えることがありました。このケースについての調査してみました。

§ コンカレントGCの? 癜

 コンカレントGCを使用している場合、GCログにぜ “Full GC”という表示があまり出ていないので、GC処理関連に問題はないかように? えてしまう場合があります。しかし、コンカレントGCぜ GCログぜ “Full GC”として出力されないだけで、処理としてはフボ GCと? ゜ らない負? /処理時間を伴うOld世代のメジャボ GCです。GC Viewer等でみると、コンカレントGCもフボ GCとして朏 画されていることが゜ かります。コンカレントGC発生時ぜ GCログは以下のようになっています。

[GC [1 CMS-initial-mark: 1358402K(1474560K)] 1376938K(2034944K), 0.0230380 secs] [Times: user=0.02 sys=0.00, real=0.03 secs]
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 1.989/1.989 secs] [Times: user=2.43 sys=0.03, real=1.98 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.009/0.009 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
[CMS-concurrent-abortable-preclean-start] CMS: abort preclean due to time
[CMS-concurrent-abortable-preclean: 0.786/5.094 secs] [Times: user=2.04 sys=0.06, real=5.10 secs]
[GC[YG occupancy: 217078 K (560384 K)]
[Rescan (parallel) , 0.0803410 secs]
[weak refs processing, 0.0033110 secs]
[1 CMS-remark: 1362083K(1474560K)] 1579161K(2034944K), 0.0838390 secs] [Times: user=0.17 sys=0.00, real=0.08 secs]
[CMS-concurrent-sweep-start]
[CMS-concurrent-sweep: 0.582/0.582 secs] [Times: user=0.70 sys=0.00, real=0.59 secs]
[CMS-concurrent-reset-start]
[CMS-concurrent-reset: 0.010/0.010 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

コンカレントGCフェーズ?
CMS-initial-mark (0.03秒) 並? コレクションサイクルの開始
CMS-concurrent-mark (1.98秒) 並? マーキング段障 の? ゜ りを示す
CMS-concurrent-preclean (0.01秒) 並? 実行が可能な? 前クリーニング段障 を示す
CMS-concurrent-abortable-preclean (5.10秒) concurrent-precleanぜ remarkの間で? 行する処理
CMS-remark (0.08秒) Concurrent Markフェーズで? 施したマーキングの整合性を確? する
CMS-concurrent-sweep (0.59秒) 並? スウィープ段障 の? ゜ りを示す
CMS-concurrent-reset (0.01秒) 最終段障 を示す(次の並行コレクションの机 備)

“ initial-mark, remarkは全アプリケーションスレッドを停止を伴う

http://www.sun.com/bigadmin/content/submitted/cms_gc_logs.html

 上記1回のコンカレントGCだけ見ても8秒以? の時間が経遜 しており、この間1つぜ CPUが独占されている状態になります。この並行処理のオーバーヘッドにより、アプリケーションのスループットの? 下につながります。つまりフボ GCによるアプリケーション停止の代償がコンカレントGCによるスループット作 下ということです。

 さらに注? しなければならないのは、コンカレントGCオプション「-XX:+UseConcMarkSweepGC」を使用した場合、New世代領域のオプションデフォルト値が「-XX:SurvivorRatio=1024 -XX:MaxTenuringThreshold=0」に自動設? されるという点です。「-XX:MaxTenuringThreshold=0」によって、1回のマイナボ GC後に卜 Old領域に移動してしまう。結果として、Old世代領域の使用釜 が上がりやすぜ なりコンカレントGCの回数が徐々に? えていぜ ことになります。従って、コンカレントGCを使用する場合、同時ぜ New世代領域のチューニングパラメータを付加する必要があるようです。以? のパラメータを追加検? します。

§ -XX:+UseConcMarkSweepGCと同時設? したいパラメー゜

-XX:+CMSParallelRemarkEnabled
CMS-remarkの停止時間を短縮することができる。
動作させるマシンぜ CPUが2個以? かつ物理メモリが2Gbytes以? の場合には、自動設? される。

-XX:SurvivorRatio=8
Eden領域ぜ Survivor領域のサイズを比? で指定。
コンカレントGC使用時に自動設? される”Survivor:Eden=1:1024″を”Survivor:Eden=1:8″に矯正。

-XX:TargetSurvivorRatio=90
Survivor領域がいっぱいと判断される使用? 。
Survivor領域ぜ 90%が使゜ れるまで、Old世代領域に移動いかないように判断される。

-XX:MaxTenuringThreshold=31
New世代領域において、オブジェクトがこの値で指定する回数のマイナボ GCを超えて生き残ると、Old世代領域に移動。
コンカレントGC使用時に自動設? される”0″を31に矯正。

全て眺 めると以下のようなオプション? 覧となりました。

-Xmx(物理メモリサイズから割? )
-Xms(物理メモリサイズから割? )
-Xmn(物理メモリサイズから算出、Xmxぜ 4分ぜ 4以? 、CPU数に? じて? 加)
-Xss(物理メモリサイズから算凜 )
-XX:PermSize=(物理メモリサイズとアプリ? 様から検? )
-XX:MaxPermSize=(PermSizeと同? )
-XX:+UseParNewGC
-XX:ParallelGCThreads=(CPUコア数以下)
-XX:+UseConcMarkSweepGC
-XX:SurvivorRatio=8
-XX:TargetSurvivorRatio=90
-XX:MaxTenuringThreshold=31
9月 4th, 2009

Javaコマンドオプション? ?

Posted in Java by admin

A Collection of JVM Options
compiled by: Joseph D. Mocker (Sun Microsystems, Inc.)
revision: 28.Aug.2007
http://blogs.sun.com/watt/resource/jvm-options-list.html

sunの人間だとしてもよく纜 めたなと思う。
JDKバージョンの対応がとても役? ちます。
ダウンロードぜ ここから。