public class HexUtil2 { private static final char[] digits = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' }; public static String toString(int i, int radix, int length) { final char[] buf = new char[length]; final int mask = radix - 1; int charPos = length; do { buf[--charPos] = digits[i & mask]; i /= radix; } while (i != 0); while (charPos > 0) { buf[--charPos] = '0'; } return new String(buf, charPos, (length - charPos)); } public static String toString(byte[] bytes, int radix, int length) { final StringBuffer sb = new StringBuffer(bytes.length * length); for (int i=0; i<bytes.length; i++) { sb.append(toString(bytes[i] & 0xff, radix, length)); //自然数にしたバイト値を、16進数文字列に変換 } return sb.toString(); } public static byte[] toByteArray(String s, int radix, int length) { final char[] buf = s.toCharArray(); final byte[] bytes = new byte[buf.length / length]; for (int i=0; i<buf.length/length; i++) { bytes[i] = (byte)Integer.parseInt(new String(buf, i*length, length), radix); } return bytes; }
2011/12/27
16進数文字列(String)⇔バイト配列(byte[]) プチ高速版
16進数文字列(String)⇔バイト配列(byte[])のプチ高速板を作成してみました。
2011/12/19
JavaのレガシーなCollectionクラスでもスレッドセーフではない?
JDK/JRE 1.x時代から存在するjava.util.Vectorなどのレガシーなクラスは、Thread-safe(スレッドセーフ)です。
これにも関わらず、思うような結果にならないケースがあります。
次は、検証用のサンプル(Java SE 5.0以降)です。
各数字がきれいに1個ずつ出力されないのです。
簡単な図解を作りました。
次のように、Vectorインスタンスにアクセスする範囲全体を排他する必要があります。
これにも関わらず、思うような結果にならないケースがあります。
次は、検証用のサンプル(Java SE 5.0以降)です。
package a; import java.util.Arrays; import java.util.List; import java.util.Vector; class A implements Runnable { //VectorはThread-safeである private List<String> v = new Vector<String>(); public void run() { for(int i=0; i<1000; i++){ //3桁の数字文字列を生成 final String s = createNumberString(i); //文字列sがVectorに含まれていなければ、追加する if(v.contains(s) == false){ v.add(s); } } } //3桁の文字列を生成する(例:1→"001") private static String createNumberString(int i){ final StringBuilder sb = new StringBuilder(String.valueOf(i)); while(sb.length() < 3){ sb.insert(0, "0"); } return sb.toString(); } public static void main(String[] args) throws InterruptedException { //多重度3でA.run()の処理を実行する final A a = new A(); final Thread[] tt = new Thread[3]; for(int i=0; i<tt.length; i++){ tt[i] = new Thread(a); tt[i].start(); } for(Thread t : tt){ t.join(); } //処理結果を出力 final List<String> v = a.v; final String[] ss = v.toArray(new String[v.size()]); Arrays.sort(ss); for(String s : ss){ System.out.println(s); } } }上記プログラムでは、実行するたびに結果が変わりますが、次のように同じ数字が2か3個出力されるでしょう。
各数字がきれいに1個ずつ出力されないのです。
000 001 002 : 169 169 170 170 171 171 172 172 173 173 : 999VectorがThread-safeなのは、Vectorインスタンス内部に限ります。つまりVectorインスタンスの内部ではデータの整合性は保たれますが、Vectorを使う側(上記プログラムではAクラス)では必ずしもデータを正しく操作できることを保証するものではありません。
簡単な図解を作りました。
To use the legacy Collection is not necessarily thread-safe. |
次のように、Vectorインスタンスにアクセスする範囲全体を排他する必要があります。
public void run() { final List<String> v = this.v; for(int i=0; i<1000; i++){ //3桁の数字文字列を生成 final String s = createNumberString(i); synchronized(v){ //文字列sがVectorに含まれていなければ、追加する if(v.contains(s) == false){ v.add(s); } } } }なお今回のようなケースではAクラスでのsynchronizedとVector内部でのsynchronizedとロックが二重になりますから、スレッドセーフではないjava.util.ArrayListを使う方が、速度性能が良くなりますね。
2011/12/06
文字列操作の速度を測ってみた(やっつけ3)
文字列操作の速度を測ってみた(やっつけ2)について、もう少し突っ込んで調べました。
今度は、Java VMオプションを「-server -XX:+PrintCompilation」にして、Java 1.4.2、5.0、6、7のそれぞれで実行してみました。すると、Java 5.0と6との間で出力内容に大きな変化が見られました。
Java SE 5.0の場合
1 java.io.Win32FileSystem::normalize (143 bytes) 2 ! java.net.URLEncoder::encode (378 bytes) 3 java.lang.Character::isLetter (158 bytes) 4 sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes) 5 java.nio.Buffer::(68 bytes) 6 ! java.nio.charset.CharsetEncoder::encode (285 bytes) 7* java.lang.System::arraycopy (0 bytes) 8 java.nio.Buffer::position (43 bytes) 9 java.nio.Buffer::limit (62 bytes) 10 ! java.lang.StringCoding::encode (127 bytes) 11 sun.nio.cs.UTF_8$Encoder::encodeLoop (28 bytes) 12 ! java.io.CharArrayWriter::toCharArray (37 bytes) 13 java.lang.AbstractStringBuilder::expandCapacity (51 bytes) 14 s java.lang.StringBuffer::toString (17 bytes) 15 java.lang.AbstractStringBuilder:: (12 bytes) 16 java.nio.charset.Charset::forName (20 bytes) 17 java.io.CharArrayWriter:: (7 bytes) 1% b.A::measure @ 14 (47 bytes) 18 b.A::measure (47 bytes) //この行以降が2回目のmeasureメソッド呼出し後 2% b.A::measure @ 14 (47 bytes)
Java SE 6の場合
195 1 java.lang.String::charAt (33 bytes) 196 2 java.lang.AbstractStringBuilder::append (40 bytes) 229 3 s java.lang.StringBuffer::append (8 bytes) 231 4 java.lang.CharacterDataLatin1::getProperties (11 bytes) 232 5 ! java.net.URLEncoder::encode (375 bytes) 234 6 java.lang.Character::forDigit (42 bytes) 234 7 java.lang.Character::isLetter (5 bytes) 235 8 java.lang.Character::isLetter (158 bytes) 236 9 java.lang.CharacterDataLatin1::isLetter (20 bytes) 237 10 java.lang.CharacterDataLatin1::getType (10 bytes) 237 11 java.util.BitSet::wordIndex (5 bytes) 237 12 java.util.BitSet::checkInvariants (111 bytes) 238 13 java.util.BitSet::get (69 bytes) 245 14 java.lang.Object::(1 bytes) 250 15 sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes) 261 16 java.lang.Math::min (11 bytes) 267 17 java.nio.Buffer::position (43 bytes) 267 18 java.nio.charset.CoderResult::isUnderflow (13 bytes) --- n java.lang.System::arraycopy (static) 287 19 java.nio.Buffer::limit (62 bytes) 287 20 java.nio.Buffer:: (68 bytes) 306 21 java.lang.String::equals (88 bytes) 326 22 java.nio.Buffer::hasRemaining (17 bytes) 326 23 java.nio.ByteBuffer:: (45 bytes) 326 24 ! java.nio.Bits::byteOrder (119 bytes) 326 25 java.nio.CharBuffer::hasArray (20 bytes) 327 26 java.nio.ByteBuffer::hasArray (20 bytes) 327 27 java.nio.charset.CoderResult::isOverflow (14 bytes) 327 28 java.nio.CharBuffer:: (22 bytes) 327 29 ! java.nio.ByteBuffer::wrap (20 bytes) 328 30 java.nio.HeapByteBuffer:: (14 bytes) 329 31 ! java.nio.CharBuffer::wrap (20 bytes) 329 32 java.nio.HeapCharBuffer:: (14 bytes) 330 33 java.lang.StringCoding::access$000 (6 bytes) 330 34 java.lang.StringCoding::scale (7 bytes) 331 35 java.nio.charset.Charset::atBugLevel (53 bytes) 331 36 java.nio.ByteBuffer::wrap (8 bytes) 332 37 java.nio.charset.CharsetEncoder:: (16 bytes) 332 38 java.nio.charset.CharsetEncoder:: (113 bytes) 334 39 java.nio.charset.CharsetEncoder::replaceWith (81 bytes) 334 40 java.nio.charset.CharsetEncoder::onMalformedInput (26 bytes) 335 41 java.nio.charset.CharsetEncoder::onUnmappableCharacter (26 bytes) 335 42 java.util.Arrays::copyOf (19 bytes) 335 43 java.lang.StringCoding$StringEncoder:: (7 bytes) 336 44 java.lang.StringCoding$StringEncoder:: (35 bytes) 338 45 ! java.lang.StringCoding$StringEncoder::encode (130 bytes) 339 46 java.nio.charset.CharsetEncoder::maxBytesPerChar (5 bytes) 339 47 java.nio.charset.CharsetEncoder::reset (11 bytes) 339 48 ! java.nio.charset.CharsetEncoder::encode (285 bytes) 345 49 java.nio.charset.CharsetEncoder::flush (49 bytes) 345 50 java.nio.charset.CharsetEncoder::implFlush (4 bytes) 345 51 java.lang.StringCoding::access$300 (7 bytes) 347 52 java.lang.StringCoding::safeTrim (30 bytes) 349 53 sun.nio.cs.UTF_8::newEncoder (10 bytes) 350 54 sun.nio.cs.UTF_8$Encoder:: (6 bytes) 351 55 sun.nio.cs.UTF_8$Encoder:: (10 bytes) 352 56 sun.nio.cs.UTF_8$Encoder::isLegalReplacement (26 bytes) 352 57 sun.nio.cs.UTF_8$Encoder::encodeLoop (28 bytes) 462 58 java.util.Arrays::copyOfRange (63 bytes) 463 59 java.nio.charset.Charset::lookup (44 bytes) 465 60 java.nio.charset.Charset::forName (20 bytes) 520 1% b.A::measure @ 14 (47 bytes) 7009 1% made not entrant b.A::measure @ -2 (47 bytes) 7010 48 ! made not entrant java.nio.charset.CharsetEncoder::encode (285 bytes) 7010 61 b.A::measure (47 bytes) //この行以降が2回目のmeasureメソッド呼出し後 7014 2% b.A::measure @ 14 (47 bytes)
java.nioパッケージのAPIに対するJITコンパイルが増えています。
このことから次のような推測が導かれます。
- (Java VM自体の性能改善よりもむしろ)java.nioパッケージを使うように改善したことによる性能差 or / and
- java.nioパッケージ自体の改善による性能差
文字列操作の速度を測ってみた(やっつけ2)
Java1.4.2~Java7.0で文字列操作の速度を測ってみた(やっつけ)を見て気になったので、こちらでも少し測定してみました。
元の記事のものに少しだけ手を加えたプログラムを用意しました。
package b; import java.net.URLDecoder; public class A { private static final String URL = "http://www.google.co.jp/?q=URLEncoder%E3%81%AF%E3%81%A9%E3%82%8C%E3%81%8F%E3%82%89%E3%81%84%E9%81%85%E3%81%84%E3%81%AE%E3%81%8B%E3%80%81commons-codec%E3%81%A8%E6%AF%94%E8%BC%83%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%99"; private static final int TIMES = 1000000; public static void main(String[] args) throws Throwable { measure(); measure(); } public static void measure() throws Throwable { final String input = URLDecoder.decode(URL, "UTF-8"); final long startTime = System.currentTimeMillis(); for (int i=0; i<TIMES; i++) { java.net.URLEncoder.encode(input, "UTF8"); } final long endTime = System.currentTimeMillis(); System.out.println(endTime - startTime); } }
次のようなバッチファイルで測定しました。
SET MYOPTS=-Xint -client D:\jdk4\bin\java -cp bin %MYOPTS% b.A D:\jdk5\bin\java -cp bin %MYOPTS% b.A D:\jdk6\bin\java -cp bin %MYOPTS% b.A D:\jdk7\bin\java -cp bin %MYOPTS% b.A SET MYOPTS=-Xint -server D:\jdk4\bin\java -cp bin %MYOPTS% b.A D:\jdk5\bin\java -cp bin %MYOPTS% b.A D:\jdk6\bin\java -cp bin %MYOPTS% b.A D:\jdk7\bin\java -cp bin %MYOPTS% b.A SET MYOPTS=-client D:\jdk4\bin\java -cp bin %MYOPTS% b.A D:\jdk5\bin\java -cp bin %MYOPTS% b.A D:\jdk6\bin\java -cp bin %MYOPTS% b.A D:\jdk7\bin\java -cp bin %MYOPTS% b.A SET MYOPTS=-server D:\jdk4\bin\java -cp bin %MYOPTS% b.A D:\jdk5\bin\java -cp bin %MYOPTS% b.A D:\jdk6\bin\java -cp bin %MYOPTS% b.A D:\jdk7\bin\java -cp bin %MYOPTS% b.A
測定結果を次に示します(2回目の測定値のみ)。
Java SE | JITなし | JITあり | ||
---|---|---|---|---|
Hotspot ClientVM | Hotspot ServerVM | Hotspot ClientVM | Hotspot ServerVM | |
1.4.2 | 106967 | 114095 | 15716 | 12396 |
5.0 | 134080 | 140290 | 15898 | 11667 |
6 | 134502 | 129110 | 6987 | 4280 |
7 | 125772 | 112755 | 6013 | 3483 |
Java SE 5.0とJava SE 6のJIT (Just In Time)コンパイラの性能差が目立ちます。
また反復処理が多い場合は、Java Hotspot ServerVMの方が良さそうですね。
2011/12/04
InterruptedExceptionは何のためにある?
InterruptedExceptionがスローされるメソッドは結構ありますが、
停止状態(ブロック状態)にあるスレッドを再開するためにInterruptedExceptionをスローするというのが基本的な考え方であって、スレッドをinterruptするのではありません。
言い換えると、InterruptedExceptionは、停止状態(ブロック状態)にある処理を一度キャンセルしてスレッドの処理を再開させるためにあっても、必ずしもブロックの原因となった処理を繰り返し実行してはいけないというわけではないと考えています。
次のようなプログラムを考えてみます。
Queueから要素を取り出すスレッド(11行目で非デーモンに設定)が起動されます。このスレッドは非デーモンなので、mainスレッドが終了してもアプリケーションは即座に終了しないようになっています。
一方、mainスレッドではQueueに10個の要素を挿入し、11個目の要素の挿入で処理を終えるように指示しています。
なお実験的に20行目のコメントを外して、InterruptedExceptionをスローさせることができます。
逆に、すべての要素を処理する必要がないスレッドの場合は、InterruptedExceptionをキャッチして、次の処理に進めるか、あるいはスレッドを即時に終了することを選択することもできます。上記プログラムの場合、59行目のコメントを外せば、whileループを抜けて次の処理に進むことになります。
InterruptedExceptionのスローによって再開されたスレッドにおいて、どのように対応するかはユーザが自由に決めてもいいわけです。予期しないInterruptionなら無視し(NOP:NO Operationとする)、意図したInterruptionなら次の処理に進めることもできます。
一口で言ってしまうとケースバイケースだと考えています。ただ、対象のスレッドがどの処理を実行中であるのかを把握できていないとThread#interruptが効果的に働かないケースが多いのではないかと思うのです。また予期しないInterruptedExceptionがスローされる可能性もないわけではありません。
停止状態(ブロック状態)にあるスレッドを再開するためにInterruptedExceptionをスローするというのが基本的な考え方であって、スレッドをinterruptするのではありません。
言い換えると、InterruptedExceptionは、停止状態(ブロック状態)にある処理を一度キャンセルしてスレッドの処理を再開させるためにあっても、必ずしもブロックの原因となった処理を繰り返し実行してはいけないというわけではないと考えています。
次のようなプログラムを考えてみます。
Queueから要素を取り出すスレッド(11行目で非デーモンに設定)が起動されます。このスレッドは非デーモンなので、mainスレッドが終了してもアプリケーションは即座に終了しないようになっています。
一方、mainスレッドではQueueに10個の要素を挿入し、11個目の要素の挿入で処理を終えるように指示しています。
なお実験的に20行目のコメントを外して、InterruptedExceptionをスローさせることができます。
package queue; import java.util.concurrent.LinkedBlockingQueue; public final class A { private static final LinkedBlockingQueue<Item> queue = new LinkedBlockingQueue<Item>(); public static void main(String[] args) { //QueueからItemを取りだすスレッドを起動 final Thread thread = new Thread(new Service()); thread.setDaemon(false); thread.start(); //QueueにItemを入れる for(int i=0; i<10; i++){ queue.add(new Item(false, "Msg"+String.valueOf(i))); } //BlockingQueue#takeでInterruptedExceptionをスローさせる // thread.interrupt(); //最後のItemを入れる queue.add(new Item(true, null)); } //Item static class Item { private final boolean end; //trueなら最後のItemであることを示す private final String msg; Item(boolean end, String msg){ this.end = end; this.msg = msg; } boolean isEnd(){ return this.end; } String getMsg(){ return this.msg; } } //QueueからItemを取りだすスレッド static class Service implements Runnable { public void run() { boolean roop = true; while(roop){ try { final Item item = queue.take(); //throws InterruptedException if(item.isEnd()==true){ roop = false; //ループを抜ける }else{ System.out.println(item.getMsg()); } } catch (InterruptedException e) { System.out.println("InterruptedException was thrown."); // roop = false; } } } } }このスレッドでQueueにある要素をすべて処理しなければならないと考えるならば、InterruptedExceptionを無視して処理を継続します。たとえば、LoggingのようにすべてのLogを吐き出したいときにはInterruptedExceptionを無視することを選択するでしょう。
逆に、すべての要素を処理する必要がないスレッドの場合は、InterruptedExceptionをキャッチして、次の処理に進めるか、あるいはスレッドを即時に終了することを選択することもできます。上記プログラムの場合、59行目のコメントを外せば、whileループを抜けて次の処理に進むことになります。
InterruptedExceptionのスローによって再開されたスレッドにおいて、どのように対応するかはユーザが自由に決めてもいいわけです。予期しないInterruptionなら無視し(NOP:NO Operationとする)、意図したInterruptionなら次の処理に進めることもできます。
一口で言ってしまうとケースバイケースだと考えています。ただ、対象のスレッドがどの処理を実行中であるのかを把握できていないとThread#interruptが効果的に働かないケースが多いのではないかと思うのです。また予期しないInterruptedExceptionがスローされる可能性もないわけではありません。
2011/09/23
"Strings in switch" in Java 7 (JSR 334)
Java 7で導入されたJSR 334には、「Strings in switch」がありますが、switch構文でString型も扱えるようになっています。それがどのようにコンパイルされるのかを調べてみました。
package a; public class E { public static int a(String s){ switch(s){ case "a": return 1; case "b": return 2; default: return 3; } } }
上記ソースをjavacでコンパイルして、javap -verboseしてみました。
Classfile /E:/tmp/java/java7/bin/a/E.class Last modified 2011/09/23; size 491 bytes MD5 checksum 525f1ebe51742f599543582cb206c23c Compiled from "E.java" public class a.E SourceFile: "E.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #7.#18 // java/lang/Object."<init>":()V #2 = Methodref #19.#20 // java/lang/String.hashCode:()I #3 = String #12 // a #4 = Methodref #19.#21 // java/lang/String.equals:(Ljava/lang/Object;)Z #5 = String #22 // b #6 = Class #23 // a/E #7 = Class #24 // java/lang/Object #8 = Utf8 <init> #9 = Utf8 ()V #10 = Utf8 Code #11 = Utf8 LineNumberTable #12 = Utf8 a #13 = Utf8 (Ljava/lang/String;)I #14 = Utf8 StackMapTable #15 = Class #25 // java/lang/String #16 = Utf8 SourceFile #17 = Utf8 E.java #18 = NameAndType #8:#9 // "<init>":()V #19 = Class #25 // java/lang/String #20 = NameAndType #26:#27 // hashCode:()I #21 = NameAndType #28:#29 // equals:(Ljava/lang/Object;)Z #22 = Utf8 b #23 = Utf8 a/E #24 = Utf8 java/lang/Object #25 = Utf8 java/lang/String #26 = Utf8 hashCode #27 = Utf8 ()I #28 = Utf8 equals #29 = Utf8 (Ljava/lang/Object;)Z { public a.E(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 public static int a(java.lang.String); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: aload_0 1: astore_1 2: iconst_m1 3: istore_2 4: aload_1 5: invokevirtual #2 // Method java/lang/String.hashCode:()I 8: lookupswitch { // 2 97: 36 98: 50 default: 61 } 36: aload_1 37: ldc #3 // String a 39: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 42: ifeq 61 45: iconst_0 46: istore_2 47: goto 61 50: aload_1 51: ldc #5 // String b 53: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 56: ifeq 61 59: iconst_1 60: istore_2 61: iload_2 62: lookupswitch { // 2 0: 88 1: 90 default: 92 } 88: iconst_1 89: ireturn 90: iconst_2 91: ireturn 92: iconst_3 93: ireturn LineNumberTable: line 5: 0 line 7: 88 line 9: 90 line 11: 92 StackMapTable: number_of_entries = 6 frame_type = 253 /* append */ offset_delta = 36 locals = [ class java/lang/String, int ] frame_type = 13 /* same */ frame_type = 10 /* same */ frame_type = 26 /* same */ frame_type = 1 /* same */ frame_type = 1 /* same */ }
案の定ハッシュ値を使っていて、次のような流れで処理していることが判ります。
- ローカル変数2を-1で初期化し(60~61行目)、
- 引数のString型のハッシュ値を取得し(63行目)、
- 1つ目のlookupswitchでハッシュ値が同値なら、さらにString.equals()で評価し(64~84行目)、
- 評価結果をローカル変数2に数値を代入して(0または1)(75、76、82、83行目)、
- 2つ目のlookupswitchで、ローカル変数2の値に応じた処理を行う(84~97行目)
2つのlookupswitchを使って条件分岐しているのは意外でした。
2011/09/19
娘の減圧症について
■はじめに
我が家では夫婦ともダイバーで経験本数は共に200本以上で、そこそこの経験と知識を有しています。
そして、娘(10歳)の希望で、PADIのジュニアオープンウォーターダイバーの講習を受けさせました。
結果、PADIの基準以内でダイビングしたにも関わらず、娘は減圧症を起こしました。
以下、減圧症を起こした経緯と治療内容を記述します。
そして、娘(10歳)の希望で、PADIのジュニアオープンウォーターダイバーの講習を受けさせました。
結果、PADIの基準以内でダイビングしたにも関わらず、娘は減圧症を起こしました。
以下、減圧症を起こした経緯と治療内容を記述します。
■海洋実習のログ(1日目)
学科試験に合格し、2011/09/10(土)に神奈川県小田原市石橋で海洋実習を受けました。
以下、ダイビングログですが、PADIの基準に収まる正しいダイビングが行われていたようです。
以下、ダイビングログですが、PADIの基準に収まる正しいダイビングが行われていたようです。
◆1本目
気温32℃、水温25~27℃
最大水深12m、平均水深8m
潜水時間30分、エア消費190→70気圧
◆休憩
72分
◆2本目
気温32℃、水温26~27℃
最大水深12m、平均水深5m
潜水時間36分、エア消費190→50気圧
最後に水深3mで6分間遊ぶ(安全停止)
■海洋実習終了直後(1日目)
2本目終了後、2時間後に耳の激痛を訴え、救急車で東海大学医学部付属病院に運ばれ、「急性中耳炎」と診断されました。
またそのころから足のシビレと痛みを訴え始めたため、救急科の医師さんより「減圧症」を疑われたのですが、上記ログを見せると「減圧症は考えにくいので様子を見よう」となり、そのまま帰宅しました。
■三保耳鼻咽喉科で受診(2日目)
◆2011/09/11(日)潜水医学に詳しいという三保耳鼻咽喉科で、耳を診てもらいました。
診断結果は以下です。
診断結果は以下です。
- 鼻の細菌が耳抜きにより、中耳に押し込まれ、急性中耳炎になったと考えられる。全治約1週間。
- 急性中耳炎の後に、滲出性中耳炎(聞こえは悪いけど痛くない状態)が続き、全治3~4週間。
- 滲出性中耳炎は、潜水医学を知らない近所の耳鼻科でも治療可能。
- 耳抜きが悪かった時に起こるような内出血(中耳気圧外傷)は見当たらず、耳抜きはうまくできていた模様。
当時、足のシビレと痛みもあったのですが、様子見でよいだろうと親は考え、その先生に相談しませんでした。後になってみると、その時に相談すればよかったと後悔しています。
■みなと赤十字病院(3~8日目)
◆2011/09/12(月)
娘が足のシビレと痛みを強く訴えるようになり、学校にも歩いて行きたがらない様子だったので、みなと赤十字病院の小児科で診てもらいました。
触診で異常が見当たらず。重いタンクを背負ったことによる脊椎の損傷か?とのこと。
触診で異常が見当たらず。重いタンクを背負ったことによる脊椎の損傷か?とのこと。
◆2011/09/13(火)
MRIで脊椎周りを撮影。
◆2011/09/16(金) 午前
MRIの結果、異常は見当たらず。救急科に回され、受診するも不明。神経内科を呼んでも不明。
救急科より、潜水医学に詳しい東海大学医学部付属病院に問い合わせていただきました。
救急科より、潜水医学に詳しい東海大学医学部付属病院に問い合わせていただきました。
- 減圧症は確定診断ができない(レントゲンや触診などでは減圧症を特定できない)ので、特殊な治療を受けて経過を見るしかない
- 急性中耳炎よりも減圧症の治療を優先するべき
上記理由により、高圧酸素治療(高気圧酸素療法)の設備を備えている近くの横浜労災病院に行くように勧められました。
もし地理的に東海大学医学部付属病院に近ければ、そこを勧められていたと思われます。
もし地理的に東海大学医学部付属病院に近ければ、そこを勧められていたと思われます。
■横浜労災病院(7日後~8日後)
◆2011/09/16(金) 午後
紹介状を持参して、横浜労災病院に移動し、救急科で受診しました。
やはり触診で異常が見当たらず減圧症を疑うしかないとのことで、高気圧酸素治療を受けるために、耳鼻科で両耳の鼓膜切開の手術を受けました。
やはり触診で異常が見当たらず減圧症を疑うしかないとのことで、高気圧酸素治療を受けるために、耳鼻科で両耳の鼓膜切開の手術を受けました。
鼓膜切開は10分間の麻酔の後に、穴をあける程度の簡単な手術ですが、数日~1週間くらい後に鼓膜は塞がるとのことです。
その後、神経内科の先生による触診により「減圧症の疑いが非常に濃厚」と初めて断言されました。
また高圧酸素治療の技師より「潜水水深や時間には問題は見られないが、タンクの空気の消費量が多すぎるのが気になる」という指摘も受けました。
また高圧酸素治療の技師より「潜水水深や時間には問題は見られないが、タンクの空気の消費量が多すぎるのが気になる」という指摘も受けました。
◆2011/09/16(金) 夜
19:30~1:30の6時間、高圧酸素治療を受けました。
チャンバーといわれる特殊な設備の中に入って、1.8気圧に上げて20分間、0.9気圧に下げた状態で5分間酸素呼吸というのを何セットも繰り返す治療です。
チャンバーといわれる特殊な設備の中に入って、1.8気圧に上げて20分間、0.9気圧に下げた状態で5分間酸素呼吸というのを何セットも繰り返す治療です。
治療後、娘に聞いてみると、「足のシビレと痛みを10段階で表すなら、治療前後で10→1に減った」とのことで、効果はありました。
ただ、深夜に治療が完了し、娘も眠い状態なので、翌朝に来るように言われました。
ただ、深夜に治療が完了し、娘も眠い状態なので、翌朝に来るように言われました。
◆2011/09/17(土) 午前
当日は娘の小学校の運動会だったのですが、欠席し、横浜労災病院に向かいました。
神経内科の先生の問診および触診により「治療の効果は見られる。少し痛みが残っているが自然治癒されるだろう。でも再発防止のために1回高圧酸素治療を受けてください」と。
神経内科の先生の問診および触診により「治療の効果は見られる。少し痛みが残っているが自然治癒されるだろう。でも再発防止のために1回高圧酸素治療を受けてください」と。
◆2011/09/17(土) 午後
2回目の高圧酸素治療を受け、治療後はすっかりシビレも痛みも消え去ったようです。
治療は完了の方向だが、念のために翌水曜日に再来院してくださいとのこと。
治療は完了の方向だが、念のために翌水曜日に再来院してくださいとのこと。
■高圧酸素治療(高気圧酸素療法)
高圧酸素治療は特に痛みなどを伴う治療ではありませんが、閉所に閉じ籠る治療なので、閉所恐怖症などを抱える方は治療を受けられないようです。
突発性難聴の患者さんの治療にも高圧酸素治療がよく使われるようです。
突発性難聴などの場合、高圧酸素療法による治療は2時間前後ですが、減圧症の場合は、4~6時間前後と長くなります。
突発性難聴の患者さんの治療にも高圧酸素治療がよく使われるようです。
突発性難聴などの場合、高圧酸素療法による治療は2時間前後ですが、減圧症の場合は、4~6時間前後と長くなります。
病院関係者の話では、通常、減圧症の患者は「エア切れによる緊急浮上」「ダイビング終了後の安全停止ミス」「ダイビング後の高所移動」など明らかな理由があり、すぐ高圧酸素治療を受けるとのことです。
しかし今回の娘の場合はそのような明確な理由がなく、減圧症の疑いが強まるまでに時間を要してしまいました。症状が軽かったとはいえ、早期に高圧酸素治療を受ければ1回で済んだだろうとのことでした。
しかし今回の娘の場合はそのような明確な理由がなく、減圧症の疑いが強まるまでに時間を要してしまいました。症状が軽かったとはいえ、早期に高圧酸素治療を受ければ1回で済んだだろうとのことでした。
なお高圧酸素治療は保険が効きますが、それでも1回で25,000円もします。
ちなみに神奈川県で、高圧酸素治療の設備(チャンバー)を有する病院は以下です。
ちなみに神奈川県で、高圧酸素治療の設備(チャンバー)を有する病院は以下です。
- 東海大学医学部付属病院
- 横浜労災病院
- 北里病院
■あとがき
減圧症にかかった後は、次の点に留意する必要があるとのことです。
- 3ヶ月間は、呼吸が乱れるような激しい運動は禁止。高所移動も禁止。
- 6カ月~1年間は、ダイビングは見合わせること。
幸運にも娘は、急性中耳炎と減圧症を同時に患いながらも、海に対する情熱が冷めていないようで、親としてはその点では安堵しています。再発防止のために、現在、ダイビングのインストラクターおよびPADIにもエスカレートして相談しているところです。
最後になりますが、緊急の手話通訳派遣依頼にも応えてくださった横浜市聴覚障害者情報提供施設の方々、手話通訳の方々、丁寧にご説明してくださった医療関係者の皆さま、感謝の気持ちでいっぱいです。ありがとうございました。
2011/09/04
聴覚障害教育これまでとこれから
私は乳児~高校時代まで(2つの異なる)ろう学校で育ち、聾学校の先生を目指した時期があって、中学~高校の教員免許状を持っています。
結局、就職活動を始める直前にソフトウェア開発が本当に好きだという自分に目覚めて教員にはならなかったのですが、今でもろう教育の状況はどうなってるんだろう、ろう学校の教員になった何人かの知人・友人たちは元気で頑張っているだろうかと、ふと気になることがあります。
また難聴児を持つ親御さんからも相談を受けることがあるのですが、たいていはうまくアドバイスできないんですよね。それで少しでも何か知っておきたいということで、知人に次の本を紹介してもらいました。
脇中さんのように率直で、優れた自己表現をされる教員が、昔の聴覚口話法に疑問を持たれつつ、「日本手話と対応手話を区別する必要性を強く感じていない」としているところに「惜しいなぁ!」と感じました。私なら「日本手話と対応手話をしっかり区別し、双方の観点からのアプローチを考える」としたいなぁと。
断続的な引用になりますが、次の文章がありました(カッコ内は私の補足)。
上記の考え方には、やはり違和感や疑問が湧き出てくるのを禁じ得ません。なぜなら、私の知る限り、日本語で考える習慣(日本語の音韻意識)が弱い子どもは、中・高校生以降でもその習慣が向上した例を見たことがないからです。逆に言うと、日本語の音韻意識が優れている子どもは、幼い時から優れていました。
今度は、自分を例に挙げます。幼い時期から日本語が正しく書けていて教育関係者などを驚かせたものですが、実は大学入学前までの私の自己表現力は-目を覆いたくなるほどではないが-ひどいものでした。こんな私でも、大学入学後に、このブログをご覧のように人並みの文章が書けるようになり、両親を驚かせたのも事実です。読書も作文も好きではない私が、なぜここまで改善できたのでしょうか。大学入学を機に、否応(いやおう)でも、日本語または手話を使って人に説明しなければならない機会が増え、推敲する時間が増えたからではないかと思うのです。
一方、学生時代も含め、日本語を含めた「学力」が私と同程度か少し劣っていても、私が足元に及ばないくらい優れた自己表現ができる方々が結構いらっしゃるのです!また日本語がマジョリティ言語とはいえ、日本語が苦手でもご本人の適応力によって、同僚が手話を覚えてくれ、楽しい職場生活を送られた例もあるのです。そのような方々のことも考えなければならないように思います。
以上、回り道をしましたが、
日本手話を用いた教育の場面において、日本語のCALPが育つかどうかを脇中さんは懸念されています。でも逆に、対応手話を使って音韻意識を形成させる試みも、多くの子どもにとっては上達する可能性がすこぶる低いのではないかと、私の経験から来る直感が感じています。(直感でゴメンなさい・・・)
つまり、日本語にしろ手話にしろ自己表現力の切磋琢磨は、ご本人の思考、推敲、あるいは、練習の蓄積によるものがあると思うのです。すなわち考えたり感じたりする力です。
子どもに合わせた教育を実践できるのが望ましいのですが、現実的に学校のようなクラス制では個別教育ができる部分があまりないだろうと思います。
考えたり感じたりする力の蓄積を、日本手話で育む子どもがいれば対応手話で育む子どももいると思うのですが、うまくいかなかった場合の人格形成のリスクを考えると、やはり後者の方が懸念されるべきではないかと警鐘を鳴らし続けていきたいです。
結局、就職活動を始める直前にソフトウェア開発が本当に好きだという自分に目覚めて教員にはならなかったのですが、今でもろう教育の状況はどうなってるんだろう、ろう学校の教員になった何人かの知人・友人たちは元気で頑張っているだろうかと、ふと気になることがあります。
また難聴児を持つ親御さんからも相談を受けることがあるのですが、たいていはうまくアドバイスできないんですよね。それで少しでも何か知っておきたいということで、知人に次の本を紹介してもらいました。
「聴覚障害教育これまでとこれから―コミュニケーション論争・9歳の壁・障害認識を中心に」本の内容は知人のブログ「聴覚障害教育これまでとこれから」でよくまとめておられますが、私も読書して面白かったです。著者の脇中さんのご姿勢にも好感を抱き、特にBICSとCALPは勉強になりました。私はろう教育も含め何もかも詳しくないのですが、素人なりに感想を述べます。
脇中さんのように率直で、優れた自己表現をされる教員が、昔の聴覚口話法に疑問を持たれつつ、「日本手話と対応手話を区別する必要性を強く感じていない」としているところに「惜しいなぁ!」と感じました。私なら「日本手話と対応手話をしっかり区別し、双方の観点からのアプローチを考える」としたいなぁと。
断続的な引用になりますが、次の文章がありました(カッコ内は私の補足)。
音韻意識の形成のために2つの手話を包含する新しい方向性の追求が必要であると考えます。
日本語で考える習慣のない子どもは、習慣のある子どもと比べると、日本語の定着が難しいと思われるので、手話の早期導入を図りながらも、「(日本語の)音韻意識」の形成や定着に留意する必要があると考えます。
上記の考え方には、やはり違和感や疑問が湧き出てくるのを禁じ得ません。なぜなら、私の知る限り、日本語で考える習慣(日本語の音韻意識)が弱い子どもは、中・高校生以降でもその習慣が向上した例を見たことがないからです。逆に言うと、日本語の音韻意識が優れている子どもは、幼い時から優れていました。
今度は、自分を例に挙げます。幼い時期から日本語が正しく書けていて教育関係者などを驚かせたものですが、実は大学入学前までの私の自己表現力は-目を覆いたくなるほどではないが-ひどいものでした。こんな私でも、大学入学後に、このブログをご覧のように人並みの文章が書けるようになり、両親を驚かせたのも事実です。読書も作文も好きではない私が、なぜここまで改善できたのでしょうか。大学入学を機に、否応(いやおう)でも、日本語または手話を使って人に説明しなければならない機会が増え、推敲する時間が増えたからではないかと思うのです。
一方、学生時代も含め、日本語を含めた「学力」が私と同程度か少し劣っていても、私が足元に及ばないくらい優れた自己表現ができる方々が結構いらっしゃるのです!また日本語がマジョリティ言語とはいえ、日本語が苦手でもご本人の適応力によって、同僚が手話を覚えてくれ、楽しい職場生活を送られた例もあるのです。そのような方々のことも考えなければならないように思います。
以上、回り道をしましたが、
日本手話を用いた教育の場面において、日本語のCALPが育つかどうかを脇中さんは懸念されています。でも逆に、対応手話を使って音韻意識を形成させる試みも、多くの子どもにとっては上達する可能性がすこぶる低いのではないかと、私の経験から来る直感が感じています。(直感でゴメンなさい・・・)
つまり、日本語にしろ手話にしろ自己表現力の切磋琢磨は、ご本人の思考、推敲、あるいは、練習の蓄積によるものがあると思うのです。すなわち考えたり感じたりする力です。
子どもに合わせた教育を実践できるのが望ましいのですが、現実的に学校のようなクラス制では個別教育ができる部分があまりないだろうと思います。
考えたり感じたりする力の蓄積を、日本手話で育む子どもがいれば対応手話で育む子どももいると思うのですが、うまくいかなかった場合の人格形成のリスクを考えると、やはり後者の方が懸念されるべきではないかと警鐘を鳴らし続けていきたいです。
2011/06/21
Java HotSpot Garbage Collectionの翻訳
Java HotSpot Garbage Collectionを翻訳しました。
第1章 The Garbage-First Garbage Collector
The Garbage-First Garbage Collector (or G1 GC for short) is a new GC that is being introduced in the Java HotSpot VM in JDK 7. An experimental version of G1 has also been released in Java SE 6 Update 14. G1 is the long-term replacement for HotSpot's low-latency Concurrent Mark-Sweep GC (widely referred to as CMS).
Garbage-First Garbage Collector (短縮名:G1 GC)は、JDK 7のJava HotSpot VMで導入される新しいGCです。実験バージョンのG1は、Java SE 6 Update 14でもリリースされました。G1は、HotSpotの低レイテンシ性のConcurrent Mark-Sweep GC(広くCMSと呼ばれている)に、長期的に置き換わるものです。
1.1. Attributes (属性)
G1 is a “server-style” GC and has the following attributes.
G1はサーバ向けGCで、次の属性を持ちます。
Parallelism and Concurrency. G1 takes advantage of the parallelism that exists in hardware today. It uses all available CPUs (cores, hardware threads, etc.) to speed up its “stop-the-world” pauses when an application's Java threads are stopped to enable GC. It also works concurrently with running Java threads to minimize whole-heap operations during stop-the-world pauses.
並行と並列性:G1は最新のハードウェアに搭載されている並行性を利用します。G1はすべての利用可能なCPU(コアやハードウェア・スレッドなど)を使用し、GC実行時にアプリケーションのJavaスレッドがすべて停止される「stop-the-world」を短縮化します。G1は、stop-the-world中の全ヒープに対する操作を最小限にするために、複数のJavaスレッド上で並列に動作します。
Generational. Like the other HotSpot GC's, G1 is generational, meaning it treats newly-allocated (aka young) objects and objects that have lived for some time (aka old) differently. It concentrates garbage collection activity on young objects, as they are the ones most likely to be reclaimable, while visiting old objects infrequently. For most Java applications, generational garbage collection has major efficiency advantages over alternative schemes.
世代:他のHotSpot GCのように、G1も世代別に動作します。新しく割り当てられたばかりの若いオブジェクトと、生存期間の長い古いオブジェクトを別々に扱います。G1は、まれに古いオブジェクトを監視すると同時に、若いオブジェクトに対するガーベジコレクション活動に集中します。なぜなら、若いオブジェクトのほとんどが回収されるからです。
世代別ガーベジコレクションは、ほとんどのJavaアプリケーションにおいては、他の方法に勝る大きな効果をもたらします。
Compaction. Unlike CMS, G1 performs heap compaction over time. Compaction eliminates potential fragmentation problems to ensure smooth and consistent long-running operation.
コンパクション(圧縮):CMSと違って、G1は常にヒープ圧縮を行います。コンパクションは、長時間にわたって円滑かつ調和がとれた運用ができるように、潜在的な断片化問題を除去します。
Predictability. G1 is expected to be more predictable than CMS. This is largely due to the elimination of fragmentation issues that can negatively affect stop-the-world pause times in CMS. Additionally, G1 has a pause prediction model that, in many situations, allows it to often meet (or rarely exceed) a pause time target.
予測:G1はCMSよりも予測可能であることが期待されています。これは、CMSでのstop-the-worldに悪影響を与える断片化問題の除去による効果が大きいです。くわえて、G1は停止予測モデルを持っています。停止予測モデルは、さまざまな状況においてG1が停止時間目標に常に対応できる(または、停止時間目標を滅多に超過しない)ようにします。
1.2. Description(解説)
G1 takes a very different approach to heap layout than other HotSpot GCs. In G1, there is no physical separation between the young and old generations. Instead, there is a single contiguous heap which is split into same-sized regions. The young generation is a set of potentially non-contiguous regions, and the same is true for the old generation. This allows G1 to flexibly move resources as needed from the old to the young generation, and vice versa.
G1のヒープ設計に対する取り組みは、他のHotSpot GCとは異なります。G1では、Young世代領域とOld世代領域を物理的に分離しません。その代わりに、1つの連続したヒープ領域を、同サイズの領域に分離します。Young世代領域は、一組の非連続領域の場合もあります。Old世代領域も同様です。これは、G1が必要に応じてOld世代領域からYoung世代領域(逆方向も含む)へのリソース移動が柔軟にできるようにするためです。
Collection in G1 takes place through evacuation pauses, during which the survivors from regions referred to as the collection set are evacuated to another set of regions (the to-space) so that the collection set regions can then be reclaimed. Evacuation pauses are done in parallel, with all available CPUs participating. Most evacuation pauses collect the available young regions, thus are the equivalent of young collections in other HotSpot GCs. Occasionally, select old regions may also be collected during these pauses because G1 piggybacks old generation collection activity on young collections.
「退避停止」の間に、G1のコレクションが発生します。退避停止とは、生存オブジェクトが、「コレクションセット」と呼ばれる領域から、片方の領域(To領域)に退避される間ずっと停止されるものです。退避停止の目的は、コレクションセット領域を回復させるためです。退避停止は、すべての利用可能なCPUを利用して、パラレル(並列)に実行されます。ほとんどの退避停止では、利用可能なYoung世代領域に対して、他のHotSpot GCのYoung世代領域に対するコレクションと同様に、コレクションを実行します。時々、選ばれたOld世代領域に対しても、コレクションが実行される場合があります。これはG1がYoung世代領域に対するコレクション活動にOld世代領域に対するコレクション活動を乗せているためです(これを「ビギーバック方式」という)。
Like CMS, G1 periodically performs a concurrent marking phase. The main role of this phase is to identify which old regions are mostly full of garbage objects, as these are the most efficient and desirable to collect. Unlike CMS, G1 does not perform a concurrent sweeping phase. Instead, the most profitable old regions identified by the concurrent marking phase are collected during subsequent evacuation pauses (the piggybacking mentioned above).
CMSと同様に、G1は、周期的にコンカレント・マーキング・フェーズを実行します。このフェーズの主な役割は、どのOld世代領域が不要オブジェクト(ゴミ)で一杯になっているかを特定することです。これはコレクションを実行するのに、効率的で望ましいことだからです。CMSと違って、G1はコンカレント・スィーピング・フェーズを実行しません。その代わり、コンカレント・マーキング・フェーズで特定されたOld世代領域に対して、続いて発生する退避停止の間に、コレクションを実行します(前述のビギーバッキング方式)。
1.3. Using G1(G1の使用にあたって)
G1 is still considered experimental and can be enabled with the following two parameters:
G1はまだ実験段階ですが、次の2つのオプションで有効にすることができます。
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC
|
To set a GC pause time goal, use the following parameter:
GC停止時間の最大目標値を設定するには、次のオプションを使用します。
-XX:MaxGCPauseMillis=50 (for a pause time target of 50ms)(停止時間目標を50ミリ秒に設定)
|
With G1, a time interval can be specified during which a GC pause should last no longer than the time given above:
次のオプションで、GC停止を合計で MaxGCPauseMillisミリ秒 まで許可するようにインターバル時間を設定することができます。
-XX:GCPauseIntervalMillis =200 (for a pause interval target of 200ms)(停止感覚目標を200ミリ秒に設定)
|
Note that the above two options represent goals, not promises or guarantees. They might work well in some situations but not in others, and the GC might not always be able to obey them.
注意:上の2つのオプションは、目標を設定するものであって、設定されたとおりに動作することを約束するものでも保障するものでもありません。いくつかの場面では設定された通りに動作しますが、そうでない場面もあります。CGは必ずしもそれらの設定値に従うことができるわけではありません。
Alternatively, the size of the young generation can be specified explicitly to impact evacuation pause times:
あるいは、退避停止時間を短縮させるために、Young世代領域のサイズを明示的に指定することもできます。
-XX:+G1YoungGenSize=512m (for a 512 megabyte young generation)(Young世代領域を512MBに設定)
|
G1 also uses the equivalent of survivor spaces, which are, naturally, a set of (potentially non-contiguous) regions. Their size can be specified with the usual parameters (e.g., -XX:SurvivorRatio=6).
G1も他のGCと同様にSurvivor領域を使用します。Survivor領域は従来とおりの一組の領域で、非連続領域の場合もあります。これらのサイズは、従来と同じオプションで設定することができます(例:-XX:SurvivorRatio=6)
Finally, to run G1 at its full potential, try setting these two parameters which are currently disabled by default because they may uncover a rare race condition:
最終的にこれらの2つのオプションを設定してみて、最大限の可能性でG1を実行してください。これらの2つのオプションは、まれに競合する可能性があるため、デフォルトでは無効になっています。
-XX:+G1ParallelRSetUpdatingEnabled -XX:+G1ParallelRSetScanningEnabled
|
One more thing to note is that G1 is very verbose compared to other HotSpot GCs when -XX:+PrintGCDetails is set. This is because it prints per-GC-thread timings and other information very helpful in profiling and trouble-shooting. If you want a more concise GC log, please switch to using -verbosegc (though it is recommended that the more detailed GC log be obtained).
注意:G1は、"-XX:+PrintGCDetails"オプションが設定されてるとき、他のHotSpot GCに比べてログ出力が冗長になります。これはGCのスレッドごとに、プロファイリングやトラブルシューティングに有用なタイミングや他の情報を出力するためです。出力を簡潔にしたい場合は、"-verbose"オプションを使ってください。ただし、詳細なGCログを出力することを推奨します。
1.4. Status(事情)
G1 development is now focused primarily on resolving any remaining reliability issues and improving performance, and also on removing the following limitations:
G1の開発は、未解決の信頼性問題の解決、性能の改良に主に焦点を合わせています。また、次の制限事項の解除にも焦点を合わせています。
l G1 does not fully support the JVM Tool Interface (JVM TI) or Java Management Extensions (JMX), so it is likely that monitoring and management tools will not work correctly with G1.
G1はJVM Tool Interface(JVMTI)とJava Management Extensions(JMX)を完全にサポートしていません。したがって、G1使用時は、モニタリングやマネジメントを行うツールは正常に動作しません。(訳注:JConsoleなどはG1GCに未対応ということ)
G1はJVM Tool Interface(JVMTI)とJava Management Extensions(JMX)を完全にサポートしていません。したがって、G1使用時は、モニタリングやマネジメントを行うツールは正常に動作しません。(訳注:JConsoleなどはG1GCに未対応ということ)
l G1 does not support incremental permanent generation collection. If an application does a lot of class unloading and requires permanent generation collection, this will be done during Full GCs.
G1はPermanent世代領域に対するインクリメント機能をサポートしていません。なお、アプリケーションが大量のクラスをアンロードし、Permanent世代領域に対するコレクションが必要となった場合に発生するFull GCにおいて、インクリメントが実行されます。
G1はPermanent世代領域に対するインクリメント機能をサポートしていません。なお、アプリケーションが大量のクラスをアンロードし、Permanent世代領域に対するコレクションが必要となった場合に発生するFull GCにおいて、インクリメントが実行されます。
l In terms of GC pause times, G1 is sometimes better and sometimes worse than CMS. Work is ongoing to make G1 consistently as good as, if not better than, CMS.
GC停止時間に関しては、G1は時々CMSよりよく、時々CMSより悪いです。G1がCMSよりよくない場合は、首尾一貫してCMSと同じくらいになるように、開発を行っています。
GC停止時間に関しては、G1は時々CMSよりよく、時々CMSより悪いです。G1がCMSよりよくない場合は、首尾一貫してCMSと同じくらいになるように、開発を行っています。
1.5. Resources(リソース)
l Description of HotSpot GCs: Memory Management in the Java HotSpot Virtual Machine White Paper: http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
l The original CMS paper: Printezis, T. and Detlefs, D. 2000. A generational mostly-concurrent garbage collector. In Proceedings of the 2nd international Symposium on Memory Management (Minneapolis, Minnesota, United States, October 15 - 16, 2000). http://portal.acm.org/citation.cfm?id=362422.362480 (requires access to ACM's portal)
l The original G1 paper: Detlefs, D., Flood, C., Heller, S., and Printezis, T. 2004. Garbage-first garbage collection. In Proceedings of the 4th international Symposium on Memory Management (Vancouver, BC, Canada, October 24 - 25, 2004). http://portal.acm.org/citation.cfm?id=1029879 (requires access to ACM's portal)
l G1 talk from JavaOne 2008: http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&yr=2008
登録:
投稿 (Atom)