アカウント名:
パスワード:
GCを利点として挙げる人がいますが、それも僕はどうかと思っています。 GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。
C++ でマルチスレッドプログラムを書く時のメモリ管理の難しさといったら。まあ,気にしなくても動きますけど(皮肉なことに)。
いいえ。G7さんが紹介してくれましたURLがよい資料なので、詳しくは そちらを見てください。ここでは簡単に言いますと、GCは古典的には、
確認ですが、
Java の Heap に関しては、激しくオブジェクトの生成/回収を繰り返してもフラグメンテーションによって新規オブジェクトが生成できない、とゆー事態には陥ったことがない
というのは、異なるサイズのオブジェクトを生成、回収した場合ですか? というのは、同じサイズばっかりだったらそもそも空きメモリの断片化は問題にならないはずなので。
ちなみに、アドレス空間を長持ちさせると(Unixのkernelはその典型)、オブジェクトの生成にともなう再初期化が大きなオーバヘッドになってきます。これは、オブジェクトが不要になった時、その中身はオブジェクトが初めて生成された時とほぼ同じになっていることが多いためです(eg 連結リストの要素の場合、前後へのポインタは初期化時も解放時もnull)。
これを解決する方法として、解放されたばかりのオブジェクトを直ちに再利用に回すことが挙げられます。Solarisのslab allocatorはこの方法を用い、オブジェクトの割り当てと初期化時間を最大で8割減らすことができています。Javaでもこういうことはやってるんでしょうか?
それ、もしかして、解放された領域を、「同じ種類」ごとに別々のフリーリストにぶら下げたりする、んでしょうか?
厳密には、page level allocator(つまりvirtual memory)から切り出してきた、free objectのcacheに放り込みます。このcacheはper object typeです。
だとしたら、種類という概念がクラスのおかげ(乱暴な言いかただが)でC的世界よりずっとはっきりしているoop処理系においては、より旨くやれるんではないでしょうか?
それはなんともいえません。Uresh Vahaliaは著書Unix Internals: The New Frontiers [amazon.com]の中で、以下のようなslab allocatorの欠点を指摘しています(以下は邦訳より)。
スラブ・アロケータの1つの欠点は、それぞれのオブジェクトの種類に対してことなるキャッシュを持つことに起因する、管理上のオーバヘッドである。 (中略) (キャッシュに含まれる)要素が少なく、あまり使用されないキャッシュの場合のオーバヘッドは、しばしば、無視できないものである。
となると、cacheを使うか否かを決める問題が生じます。Solarisの場合、私が本や実装を(誰か1994年夏のUsenix [usenix.org]予稿集持ってませんか?)見た限りでは、cacheを使うか否かはobject type毎にhardcodeされている(すなわち人間が決めている)ようです。Unix kernelならこれでも何とかなりますが、個々のプログラムを支える枠組み、すなわち言語処理系やruntime libraryなどの場合は機械的に決めないと使いものにならないでしょう。Solarisがこれをやっていないということは、機械的な決定は難しいということでしょうか。
私の印象だと、heap pointerが使えるのにはCopying GCの存在が強く効いています。端的にいえば、GCをやるのだからfree listは要らんと。わざわざGCをやっているのに、加えてO(free listの断片数)(=~O(object数))のcostがかかるfree listの管理をするのは無駄でしょうね。
ただし、これは割り当てしか高速化できません。objectの初期化までは高速化できません(instructionが増える、footprintが削れない)。せめて即値代入で済むようなものぐらいはcacheが使えればなぁ...
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程度でも十分できそう)。
> GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。 これは、null なのに使おうとしたって事で、C++とJavaに差は余り無い気がします。 GCとは関係ないのでは?
> 1時間ぐらいだったら動くけど長時間動かしているとVMが落ちることがありますし、その時のバグを見つけるのが非常に大変です。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
アレゲは一日にしてならず -- アレゲ見習い
Javaの必要性 (スコア:1)
僕はいまいちJavaの良さが分かりません。
誰かJavaのすばらしさを語ってもらえないでしょうか。
Re:Javaの必要性 (スコア:1)
Java Applet のことだったり、 JavaScript のことだったりする
ことがあるので、いっかい問い詰めてみたほうがいいです。
Re:Javaの必要性 (スコア:2, 参考になる)
JITの技術がありますが本質的な解決策では無いと思います。
しかもテキスト処理なんかはJITを使ってもAwkよりもPerlよりも遅い。
次に移植性です。
Write Once Run Anywareとか言っていますがはっきり言って実現されて無いと思います。
移植性 + 速度
で考えるとCの方が上だと思っています。
GCを利点として挙げる人がいますが、それも僕はどうかと思っています。
GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。
1時間ぐらいだったら動くけど長時間動かしているとVMが落ちることがありますし、その時のバ
GCの必要性 (スコア:2, 参考になる)
C++ でマルチスレッドプログラムを書く時のメモリ管理の難しさといったら。まあ,気にしなくても動きますけど(皮肉なことに)。
Re:GCの必要性 (スコア:1)
>テーションを防ぐためのものと考えれば,その恩恵は計り知れないと思います。
え?
http://www.is.s.u-tokyo.ac.jp/~vu/jugyo/processor/process/soft/compilerresume/gc/gc.html
>Copying GCの興味深い性質は、コピーするときにオブジェクトの空きをつめるため、fragmentationが発生しないということである。
によると、フラグメンテーションを無くす機能(つーか嬉しい副作用?)を期待できるかどうかは
GCのアルゴリズム次第であって、GC一般の性質ではない、と読めますけど?
それとも、その副作用のあるGCしか使う予定が無い、言い換えれば
使おうとしている処理系のGCがお望みのアルゴリズムであることが既に判っている、
という状況なのでしょうか?
そりゃそうと、メモリリークが無くなるってのについては、有り難いと思いますよ。
1:unixプロセスモデル配下の短寿命プロセスならば、最悪でも「間もなく」OSがメモリを回収してくれる
ので有り難味は少ないかもだが、そうでないならそれ以外の管理が必要になる。
2:開放タイミングを決定するのが結構面倒なプログラミング形態も、ある。
ので、あーゆーものは、(プログラマの技量次第というよりも(笑))状況次第で、凄く欲しくなると思うんですが。
Re:GCの必要性 (スコア:1)
(中略)
> フラグメンテーションを無くす機能(つーか嬉しい副作用?)を期待できるか
> どうかは GCのアルゴリズム次第であって、GC一般の性質ではない、と読め
> ますけど?
元コメントは、フラグメンテーションがプログラマに不可視になることを言いたかったんだと、愚考します。
# 違ったらどうしよう。^_^;
新しいjavaコマンド(VM)は並列GCを実装していますね。どんなアルゴリズムを使ってるんでしょうか。興味があります。106CPUでもちゃんと動いてくれるでしょうか。:-)
Generational Mostly Parallel GC (スコア:0)
> アルゴリズムを使ってるんでしょうか。興味があります。
Generational Mostly Parallel GC です。
詳細は ISMM2000 (International Symposium on Memory
Management) の T. Printezis と D.Detlefs の論文を読めば
分ると思います。
p.s.
Detlefs は SUN ラボの人です。
Re:GCの必要性 (スコア:1)
> GCのアルゴリズム次第であって、GC一般の性質ではない、と読めますけど?
GC がどのようなアルゴリズムで行われるにせよ、compaction は
行われてるのではないでしょうか? compaction されるというこ
とは、その時点でフラグメンテーションも解消される、ということ
ですよね?違う?
Java の Heap に関しては、激しくオブジェクトの生成/回収を
繰り返してもフラグメンテーションによって新規オブジェクトが
生成できない、とゆー事態には陥ったことがないため漠然とそう
思ってたんですけど…。
UNIX のようにプロセスを起こすコストが結構大きい OS がサーバ
で主流な昨今、比較的容易にお行儀のいい長寿命プロセスを作成
出来る Java は非常に有用だと思います。
Only Jav^Hpanese available :-)
Re:GCの必要性 (スコア:1)
いいえ。G7さんが紹介してくれましたURLがよい資料なので、詳しくは そちらを見てください。ここでは簡単に言いますと、GCは古典的には、
Re:GCの必要性 (スコア:1)
確認ですが、
というのは、異なるサイズのオブジェクトを生成、回収した場合ですか? というのは、同じサイズばっかりだったらそもそも空きメモリの断片化は問題にならないはずなので。
ちなみに、アドレス空間を長持ちさせると(Unixのkernelはその典型)、オブジェクトの生成にともなう再初期化が大きなオーバヘッドになってきます。これは、オブジェクトが不要になった時、その中身はオブジェクトが初めて生成された時とほぼ同じになっていることが多いためです(eg 連結リストの要素の場合、前後へのポインタは初期化時も解放時もnull)。
これを解決する方法として、解放されたばかりのオブジェクトを直ちに再利用に回すことが挙げられます。Solarisのslab allocatorはこの方法を用い、オブジェクトの割り当てと初期化時間を最大で8割減らすことができています。Javaでもこういうことはやってるんでしょうか?
Re:GCの必要性 (スコア:1)
> 行われてるのではないでしょうか? compaction されるというこ
> とは、その時点でフラグメンテーションも解消される、ということ
> ですよね?違う?
> Java の Heap に関しては、激しくオブジェクトの生成/回収を
> 繰り返してもフラグメンテーションによって新規オブジェクトが
> 生成できない、とゆー事態には陥ったことがないため漠然とそう
> 思ってたんですけど…。
私も空きメモリの合計が 要求メモリサイズを上回っているうちから
out of memory を出すへたれな JavaVM は見たことのないです。
ただ、GC が行われた後はフラグメンテーションが解決されているか
と言うと必ずしもそうではないと思います。
例えば、普段の GC はフラグメンテーションの解決を行わないけど、
断片化されない最大の空き領域のサイズが要求サイズを満たさない
場合にはしょうがないので、フラグメンテーションを解決する GC
を改めて起こすという方法があります。
特に他の Java スレッドを止めずに GC スレッドがメモリを回収
して回る On-the-flay 型 GC は、生きているオブジェクトの位置
をむやみに動かせませんし、、、
コンタミは発見の母
Re:GCの必要性 (スコア:1)
実際に compaction を行わない GC 実装が存在することはもちろ
ん知っていますし、JavaVM Spec. が Heap 管理については 100%
実装者の裁量に任せている、ことも分かっていますが、しかし、
ご存じの通り Java にはポインタがありませんから、C でのよう
にプログラム側でフラグメンテーションに対処することが非常に難しく、
となると、まっとうな実装者ならばフラグメンテーションが起こら
ないように GC を設計するのではないか、という予想のもと、こと
現代的な実装の JavaVM に関していうなら、G7 さんの書込みでい
うところの「それとも、その副作用のあるGCしか使う予定が無い、
言い換えれば使おうとしている処理系のGCがお望みのアルゴリズム
であることが既に判っている、という状況」といえるのではないか、
前の書込みに補足すれば「GC がどのようなアルゴリズムで行われ
るにせよ、JavaVM においては常に compaction は行われている
と考えていいのではないでしょうか?」というのが趣旨です。
#組み込み系まで含めると必ずしも真ではないかもしれませんが、
#J2SE 以上の各社の実装を見ているとそう言えるのではないかと。
J2SE 以上の実装では半ば常識的なことながら、JavaVM Spec. で
はっきり規定された仕様ではない、という点を、G7 さんは暗に指
摘されていたのかな…?
Only Jav^Hpanese available :-)
Re:GCの必要性 (スコア:1)
>にプログラム側でフラグメンテーションに対処することが非常に難しく、
ああ。メモリプールというかmallocに相当するものを自作するという話題ですか。
たしかにjavaでは何処をどういじってもソレっぽいことは出来ないですね。
>現代的な実装の JavaVM に関していうなら、G7 さんの書込みでい
>うところの「それとも、その副作用のあるGCしか使う予定が無い、
>言い換えれば使おうとしている処理系のGCがお望みのアルゴリズム
>であることが既に判っている、という状況」といえるのではないか、
それを称して「現代的」と呼ぶんでしょうか?>識者諸兄
俺は知らないんですが。
>JavaVM においては常に compaction は行われている
そこでいう「JavaVM」がどこまでを指すか?に拠るでしょうね。
Sunなりなんなりの1つ(^^;の実装について語りたいなら、
メーカーに質問するとか、気に入らないなら(金を出して)変更を迫るとか、
いろんな手が有り得そうです。
でも、KaffeやWavaみたいな偽Java(^^;とか、あるいは各種(?)小型組み込み向けJavaとか、も
含めて考えると、その期待が満たされてるかどうかは、また違う話になるわけですよね。
>#J2SE 以上の各社の実装を見ているとそう言えるのではないかと。
上に書きましたが、Kaffeって、どう捉えたらいいんでしょうね?(^^;
J2SEとは…あ、どうせ言えないのか。
Java1.2相当にも、まだなってないんでしたっけかあれ?
… http://www.kaffe.org/ … あ。まだ1.1相当かあ。
あんまり厳密に考える必要はないけど... (スコア:1)
意味で使っていると思うのですが、
厳密に言うと GC の世界では compaction は in place(同じ領域内で)にオブジェクトをつめる処理を指すので、
3. の Copying GC も compaction はやらないと思います。
コンタミは発見の母
Re:GCの必要性 (スコア:1)
それ、もしかして、解放された領域を、「同じ種類」ごとに
別々のフリーリストにぶら下げたりする、んでしょうか?
だとしたら、種類という概念がクラスのおかげ(乱暴な言いかただが)で
C的世界よりずっとはっきりしているoop処理系においては、
より旨くやれるんではないでしょうか?
つまり卑近に言えば、多くてもせいぜいClassの数と同じ数のフリーリストを作ればいい、
リストをDictionaryにぶらさげて、リストをDictの中で選択するためのキーはjava.lang.Classである、
みたいな感じで…?(^^;
#そういう意味では、所詮(ごめん)C世界でしかないunix系カーネルとは
#いっしょにならんというか、もっともっとエレガントにやれるというか、ではないかなあ。
Re:GCの必要性 (スコア:1)
厳密には、page level allocator(つまりvirtual memory)から切り出してきた、free objectのcacheに放り込みます。このcacheはper object typeです。
それはなんともいえません。Uresh Vahaliaは著書Unix Internals: The New Frontiers [amazon.com]の中で、以下のようなslab allocatorの欠点を指摘しています(以下は邦訳より)。
となると、cacheを使うか否かを決める問題が生じます。Solarisの場合、私が本や実装を(誰か1994年夏のUsenix [usenix.org]予稿集持ってませんか?)見た限りでは、cacheを使うか否かはobject type毎にhardcodeされている(すなわち人間が決めている)ようです。Unix kernelならこれでも何とかなりますが、個々のプログラムを支える枠組み、すなわち言語処理系やruntime libraryなどの場合は機械的に決めないと使いものにならないでしょう。Solarisがこれをやっていないということは、機械的な決定は難しいということでしょうか。
フリーリストは使わんです (スコア:1)
空き領域の管理をフリーリストではなく、下から順番に詰めて
使って行くヒープポインタ(というのか?)で管理していると思われます。
ヒープポインタを確保したサイズ分増やすだけなので総合的に見てスピードが速いのです。
少なくも SUN JDK1.3、1.4 はこの方式です。
ClassiVM はインスタンスを指すハンドラとハンドラの実体
に分かれていて、ハンドラ領域はフリーリスト管理で、実体を
格納するヒープ領域はヒープポインタ管理です。
# ハンドラは全部同じ大きさ。
コンタミは発見の母
現代的な GC (スコア:1)
> 俺は知らないんですが。
compaction をやることが現代的な GC だとは思いません。
長い GC の歴史の中である程度 よい GC の条件が見えてきています。
非並列 GC の場合に限ると以下の 4点ぐらいを押さえた GC が現代的
な GC ではないでしょうか?
1. オブジェクトの寿命を意識すること
オブジェクトには生成されたけど一度も使われずに終わる
単寿命なやつから VM が終わるまで居続ける長生きなオブ
ジェクトまで寿命に差があります。
現代の GC はこの性質を旨く使う事が何より求められています。
2. キャッシュを意識すること
現代的なプロセッサはキャッシュの性能におんぶでだっこ。
GC といえどもキャッシュミスヒットを避ける努力が必要です。
3. 排他制御は最小に
fetch & add や compare & swap のようなアトミック命令は
最初にするのが吉です。
OS の同期オブジェクトの極力使わないことが求められます。
4. 処理は短く
それぞれの操作(例えば 1回の new)にかかる時間を減らすことも
重要です。
それ以外にも stop the world を掛けてから本当にすべてのスレッド
が止まって GC がはじまるまでのタイムラグだとかがあります。
コンタミは発見の母
Re:フリーリストは使わんです (スコア:1)
私の印象だと、heap pointerが使えるのにはCopying GCの存在が強く効いています。端的にいえば、GCをやるのだからfree listは要らんと。わざわざGCをやっているのに、加えてO(free listの断片数)(=~O(object数))のcostがかかるfree listの管理をするのは無駄でしょうね。
ただし、これは割り当てしか高速化できません。objectの初期化までは高速化できません(instructionが増える、footprintが削れない)。せめて即値代入で済むようなものぐらいはcacheが使えればなぁ...
Re:フリーリストは使わんです (スコア:1)
複数のスレッドが 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 の言語仕様をきちんと満たす形で実装するためには、
初期化はあんまりサボれないです。
コンタミは発見の母
Re:フリーリストは使わんです (スコア:1)
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程度でも十分できそう)。
Re:フリーリストは使わんです (スコア:1)
>> ほとんど逃げようがないです。
> 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 ) );
コンタミは発見の母
続き (スコア:1)
> んか? もちろん、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 されている必要があるのです。
コンタミは発見の母
いいわけ (スコア:1)
「現代的」は JavaVM にかけたのであって GC にかけたつもりはないのです。GC に関しては nminoru さんのおっしゃる通りだと思います (というか僕はそこまで理解していませんでした)。
とはいえ、「ヒープを詰める」処理 (compaction という用語が不適切だそうなので) を行わない VM が現代的でない、と言えないことは、G7 さんがすでに指摘されており、僕も納得しています。
いろいろなトレードオフの中の一要素、ということですよね。事実、kaffe の実装では詰めないようですし…。
Only Jav^Hpanese available :-)
Re:GCの必要性 (スコア:1)
ええ、その通りです。さまざまなサイズのオブジェクト (実際にはさまざまなサイズの文字列や byte[] を持ついろいろなクラスのインスタンス) が相当激しく生成/消滅を繰り返している環境です。寿命も短いものは 1 method 内から、長いものは 1 hour、1 day 程度まであるような状況です。1 hour くらいの寿命のインスタンスが大量に GC されるような瞬間には、FullGC に 5~10 sec 程度 (PentiumIII 1GHz を持ってしても) かかる状況でした。
余談ですが、Java で高いスループットを得たい時には、この FullGC の時間をいかに減らすかはそうとう重要だと思いました。インスタンスの寿命やボリュームに結構気を使わなければいけません。
後半のテーゼについては僕はまったく分かりません。すみません。
Only Jav^Hpanese available :-)
Re:GCの必要性 (スコア:1, 参考になる)
> GCを利点として挙げる人がいますが、それも僕はどうかと思っています。
> GCがあるためにむちゃくちゃなプログラムでもある程度動いてしまいます。
これは、null なのに使おうとしたって事で、C++とJavaに差は余り無い気がします。
GCとは関係ないのでは?
> 1時間ぐらいだったら動くけど長時間動かしているとVMが落ちることがありますし、その時のバグを見つけるのが非常に大変です。
これは、メモリリークしているということだとすると、GCのおかげで、それは無くなるんではないでしょうか?
メモリが無くなっているとしても、直接には、別の原因でVMが落ちているのでは無いでしょうか?
GCのおかげで、deleteを書かなくて良いとか、ポインタ変数を、参照出来なくなっても良いとか言うのはかなり良いと思います。
それと、APIまでJava言語に含まれているおかげで、スレッドも大抵のJavaの本で触れられているし、C++に比べ簡単になること自体で本の内容がそれを埋める分だけ色々増えているのは良いです。
Re:GCの必要性 (スコア:1)
関係はあると思います。
ガベージコレクタがオブジェクトの回収をやってくれるおかげで、メモリリークが顕在化しにくくなったため、オブジェクトの管理がいい加減なプログラムでも、それなりに動いてしまう、という話では?
で、その結果、真綿で首を絞めるように、回収されない(できない)オブジェクトがじわじわと蓄積して、
となると。
「Java(の)メモリリーク」などと呼ばれるようです。
# 私自身は「だからGCに利点はそれほどない」とは思いませんが。