パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

Java 1.4SE正式リリース」記事へのコメント

  • 未だにJava人気あるんですね。
    僕はいまいちJavaの良さが分かりません。
    誰かJavaのすばらしさを語ってもらえないでしょうか。
    • 「Java は駄目」とか言う人の話をよく聞いてみると、
      Java Applet のことだったり、 JavaScript のことだったりする
      ことがあるので、いっかい問い詰めてみたほうがいいです。
      • 僕がJavaで駄目だと思うところはまず実行速度です。
        JITの技術がありますが本質的な解決策では無いと思います。
        しかもテキスト処理なんかはJITを使ってもAwkよりもPerlよりも遅い。

        次に移植性です。
        Write Once Run Anywareとか言っていますがはっきり言って実現されて無いと思います。
        移植性 + 速度
        で考えるとCの方が上だと思っています。

        GCを利点として挙げる人がいますが、それも僕はどうかと思っています。
        GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。
        1時間ぐらいだったら動くけど長時間動かしているとVMが落ちることがありますし、その時のバ
        • GCを利点として挙げる人がいますが、それも僕はどうかと思っています。
          GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。

          GC を単にメモリリークを防ぐためのものと考えると大したありがたみはありませんが,メモリフラ

          • >GC を単にメモリリークを防ぐためのものと考えると大したありがたみはありませんが,メモリフラグメン
            >テーションを防ぐためのものと考えれば,その恩恵は計り知れないと思います。

            え?

            http://www.is.s.u-tokyo.ac.jp/~vu/jugyo/processor/process/soft/compilerresume/gc/gc.html
            >Copying GCの興味深い性質は、コピーするときにオブジェクトの空きをつめるため、fragmentationが発生しないということである。

            によると、フラグメンテーションを無くす機能(つーか嬉しい副作用?)を期待できるかどうかは
            GCのアルゴリズム次第であって、GC一般の性質ではない、と読めます
            • > によると、フラグメンテーションを無くす機能(つーか嬉しい副作用?)を期待できるかどうかは
              > GCのアルゴリズム次第であって、GC一般の性質ではない、と読めますけど?

              GC がどのようなアルゴリズムで行われるにせよ、compaction は
              行われてるのではないでしょうか? compaction されるというこ
              とは、その時点でフラグメンテーションも解消される、ということ
              ですよね?違う?

              Java の Heap に関しては、激しくオブジェクトの生成/回収を
              繰り
              --
              Only Jav^Hpanese available :-)
              • 確認ですが、

                Java の Heap に関しては、激しくオブジェクトの生成/回収を繰り返してもフラグメンテーションによって新規オブジェクトが生成できない、とゆー事態には陥ったことがない

                というのは、異なるサイズのオブジェクトを生成、回収した場合ですか? というのは、同じサイズばっかりだったらそもそも空きメモリの断片化は問題にならないはずなので。

                ちなみに、アドレス空間を長持ちさせると(Unixのkernelはその典型)、オブジェクトの生成にともなう再初期化が大きなオーバヘッドになってきます。これは、オブジェクトが不要になった

              • SUN の JavaVM しか知らないのですが、現行のほとんどのJVM は
                空き領域の管理をフリーリストではなく、下から順番に詰めて
                使って行くヒープポインタ(というのか?)で管理していると思われます。
                ヒープポインタを確保したサイズ分増やすだけなので総合的に見てスピードが速いのです。

                少なくも SUN JDK1.3、1.
                --
                コンタミは発見の母
              • 私の印象だと、heap pointerが使えるのにはCopying GCの存在が強く効いています。端的にいえば、GCをやるのだからfree listは要らんと。わざわざGCをやっているのに、加えてO(free listの断片数)(=~O(object数))のcostがかかるfree listの管理をするのは無駄でしょうね。

                ただし、これは割り当てしか高速化できません。objectの初期化までは高速化できません(instructionが増える、footprintが削れない)。せめて即値代入で済むようなものぐらいはcacheが使えればなぁ...

                親コメント
              • free list で一番ネックなのは同期処理の部分だと思います。
                複数のスレッドが free list を手繰るのを防ぐたびに spin lock
                するか、OS の同期オブジェクトを使わざるえないです。

                これが C/C++ だと、自分のスレッド用にある程度のサイズを
                malloc しておいて自前で切り分けて使うことで同期処理の回数を
                減らしたり出来ますが、Java の場合 new が実行される度にヒープ
                を取りに行くしかありませんから ほとんど逃げようがないです。

                > ただし、これは割り当てしか高速化できません。objectの初期化までは高速化できませ
                > ん(instructionが増える、footprintが削れない)。せめて即値代入で済むようなものぐらい
                > はcacheが使えればなぁ...

                VM の実装まで考えると 初期化を飛ばすのはすごく難しいですよ。
                昔 考えたのですが 例えば、

                    class A {
                        int m1 = 10;
                        B m2 = new B();
                    }

                の場合、A のメンバにはコンストラクタ内でセットされます。
                # m1 = 10; m2 = new B(); のコードはコンストラクタコードに化ける。

                A の初期化時にはインスタンスのゼロパディングを省略したい気持ち
                になりますが、(1) A のインスタンス生成 → (2) コンストラクタ起動
                の間に GC が起きちゃうと m2 の内容にゴミが入っていて access violation
                error でダウンです。

                結局 Java の言語仕様をきちんと満たす形で実装するためには、
                初期化はあんまりサボれないです。
                --
                コンタミは発見の母
                親コメント
              • Java の場合 new が実行される度にヒープを取りに行くしかありませんから ほとんど逃げようがないです。

                Dynix allocatorのように、heapをper-cpuにするのではダメでしょうか? GCがcpu数に比例して重くなってしまいますが...

                ちなみに、slab allocatorについてもcacheの同期問題はネックとなるようで、Bonwickはper-cpu cacheなどを将来課題として挙げています。このideaは、現在FreeBSD-currentのmbuf allocatorに実装されています。

                初期化の問題は、cacheに入っているobjectはGCの対象外とすれば何とかなりませんか? もちろん、GCの前にcacheから本当に使われていないものを回収する前処理が必要ですが(LRU程度でも十分できそう)。

                親コメント
              • >> Java の場合 new が実行される度にヒープを取りに行くしかありませんから
                >> ほとんど逃げようがないです。
                > Dynix allocatorのように、heapをper-cpuにするのではダメでしょうか? GCがcpu数に
                > 比例して重くなってしまいますが...

                JavaVM からは OS の挙動は把握しきれないので per-cpu は難しいです。
                per-thread でよいのであれば、Thread-Local Heap (TLH と仮に略します)
                のアイデア/実装はあります。
                ただ、TLH は heap pointer で管理している例しか知りません。
                # global heap から固定サイズの領域(chunk) をとってきて TLH とするタイプです。

                実際のところ heap pointer を使えば allocater の同期ルーチンって
                下のぐらいのコードになっちゃうので、TLH まで持ってきて free list を
                使う理由はあまりないのだと思います。

                char* old_pointer = NULL;
                char* new_pointer = NULL;

                do {
                    old_pointer = ::heap_pointer;
                    new_pointer = old_pointer + size ;
                    if( new_pointer >= heap_end ){
                        // GC
                    }
                } while( compare_and_swap( &::heap_pointer, old_pointer, new_pointer ) );
                --
                コンタミは発見の母
                親コメント
              • > 初期化の問題は、cacheに入っているobjectはGCの対象外とすれば何とかなりませ
                > んか? もちろん、GCの前にcacheから本当に使われていないものを回収する前処理
                > が必要ですが(LRU程度でも十分できそう)。

                私がオブジェクトの初期化をスキップすることが
                難しいと思っている理由なのですが、、、

                Java インスタンスはクラスのフィールドの内容を保持している body 部と、
                属性情報を保持している header 部に分かれます。

                header 部は 実装によりますが、普通 2ワード。多くても4 ワードだと思われます。
                header が 2 ワードの場合、
                1ワードは所属クラスの情報へのポインタとなっているはずです。
                もう1ワードの方には Object.hashCode() で返すハッシュ値や、synchronized で
                使うモニタ情報、GC の時に使うマークビットなどが入っている例が多いです。

                2ワードのうち再利用できるのはクラス情報へのポインタの 1ワードだけです。

                body 部分の再利用はさらに難しいと思われます。

                それと、バイトコードレベルでは new とコンストラクタの実行が完全に
                分離しているという問題もあります。

                Java のソースコード中に

                    member = new B();

                の表記がある場合、

                    new class B // (1)
                    dup // (2)
                    invokespecial B() // (3)
                    aload 0 (this pointer)
                    putfield

                のようなバイトコードを生成するはずです。
                (1) によってヒープからインスタンスが取ってこられるのですが、この時
                インスタンスの body 部は zero padding されることが期待されます。
                初期値がセットされるのは (3) の中です。

                (3) 実行後とメモリイメージが一致する クラス B のインスタンス
                があっても、(1) を出たときは body 部が zero padding されている必要があるのです。
                --
                コンタミは発見の母
                親コメント

物事のやり方は一つではない -- Perlな人

処理中...