2011-12-21 5 views
17

クラスパスを検索する必要があるため、クラスがキャッシュされているだけですクラスが初めて参照されたとき。静的イニシャライザが呼び出されるときだけ頻繁に発生しますが、これはプログラムのライフサイクル中に1回だけです。 (またはより具体的には、クラスローダー)複数の(おそらく未使用の)jarファイルの大きなクラスパスが非効率的です

しかし、多くの多くのライブラリーが含まれている大規模で長寿命のプログラムの場合は、使用される場合もあれば使用されない場合もあります。

Jarファイルがメモリにロードされるため、ほとんどのクラスが使用されないという不都合があります。それは記憶に残るのだろうか?

ディレクトリを参照する方が適切ですか?または、Jarファイルはすでに一時的な場所に解凍されていますか?

ディレクトリメソッドをJarファイルメソッドよりも高速に使用できますか?

すべてのJarファイルを1つのディレクトリに抽出して、クラスパス内の場所の数を減らすのは妥当ですか?これはいい考えですか?

答えて

7

jarファイルの中央ディレクトリ(zipの最後に置かれます)が解析され、メモリにロードされます。ディレクトリはフラットなので、すべてをロードする必要があります。単純なJavaプロセスを開始するときの遅延の重要な部分は、膨大なrt.jarのオープンです。だから、時間とメモリのオーバーヘッドが始まるのです。

各クラスをルックアップするには一定の時間が必要です。しかし、いくつかのO(n)アルゴリズムがあります。したがって、アプリケーション全体では、クラスロードのためのO(n^2)(ただし、定数は非常に小さく、線形時間操作によって支配される可能性があります)。

ファイルのロード中にファイルへのアクセスが非効率的になります。JDKは、jarの前にシステムクラス用のzipを使用していました。

(静的初期化子が存在する場合に実行されるとき、クラスのロードは、静的な初期化の前にいくつかの時間を起こるかもしれません - 。3引数Class.forNameを参照)

+0

セントラルディレクトリは、メモリにマップ(mmap)され、必要に応じて解決されません(コードは完全にはうまくいっていませんが、ほとんど肯定的です) – bestsss

+0

**ファイルのロード中にファイルへのアクセスは非効率です。 JDKは、JARの前にシステムクラス用のzipを使用していました。**これは興味深い点です。 jar(またはzip)ファイルを使用するのはトレードオフです。余分なメモリを使用すると、クラスの読み込みが高速になります。情報をくれてありがとう。 –

+0

@bestsssクラスを見つけようとするとき、それぞれのjarは期限内に開く必要があります。あなたは初期のジャーにすべてのクラスを持っていることは非常に幸運でしょう。たとえば、リソースを探す際に問題が発生することもあります。 –

11

これは問題ではないので、心配する必要はありません。クラスローダーは、必要なクラスをロードするのに十分なほどスマートであり、要求に応じてクラスをロードすることがよくあります(つまり、通常は使用されないコードをロードしません)。これは、アプリケーションの実行時間や長さとは関係ありません。

多くのJARのケースでは、私はJAR Hellをより心配しています。

もっと速いということは、さまざまなアプローチの違いがあると思いますが、実験してみるだけで簡単にテストできます。各アプリケーションがロードするコードが異なるため、状況はアプリケーション固有の可能性があります。

私はsmooth reggae'sと答えています。

+2

@GeorgeBaileyはまた、私の理解特定のJVMの実装-clientと-server JVMからparms。 -client parmは、アプリケーションの初期起動を高速化するために、JVMが必要に応じてクラスをロードするように指示します(そして、しばらく使われていないガベージ・コレクション・クラスさえも)。 -serverオプションを指定すると、ロードされたクラスを分析するときにJVMのロードが遅くなり、使用状況に基づいてどのクラスが長くメモリに保持されるべきかを調べます。長時間実行しているアプリケーションを使用している場合、-serverオプションはしばしばその価値があります。ここでも、JVMでこれらのparmsがあるかどうかを確認してください。 –

+1

@normalocity、私たちは注意します。 ** "ライブラリーの2つの異なるバージョン" **は、疫病のように回避されます。 ** "異なるバージョンが必要です" **おそらく決して発生しませんが、もしそうなら、別のプロセスまたはクラスローダーで処理します。 ** "いくつかの(潜在的に非常に多くの)入れ子になった協力クラスローダー" **は設計により防止されます。しかし、その質問は部分的にしか答えられていません。すべてのjarファイルがメモリにロードされていますか?これにより、実際のクラスではなくクラスファイルを意味します。 –

+0

@Chris、その有益な情報ありがとうございます。 –

3

How classes are foundおよびthe chapter on loading, linking and initializingは、JVM仕様では参考になります。

個人的な経験から、javacのクラスパスが長くなると、コンパイルに時間がかかることを証明できます。これは特に、クラスパスがコンパイルに必要でないJARを備えているときに問題になります。簡単なテストのために、標準のHelloWorld.javaを-cpなしでコンパイルし、いくつかのJARファイルを-cpに追加してから、いくつかのJARファイルを-cpに追加してください。 -cpリストのJARの数が増えると、コンパイルにかかる時間が長くなります。

+0

コンパイルに関する興味深い点。しかし、私の具体的なケースでは、長いクラスパスは実行時のみです。それは小さな部分で起こるので、時間をコンパイルしません。 –

関連する問題