Webサーバー上でWebアプリごとに1つずつ、複数のJavaプロセスを実行したいと思います。サポートするクラスとjarファイルがたくさんあるWebフレームワーク(Play)を使用していますが、Javaプロセスは大量のメモリを使用します。1つのPlayプロセスでは、約225MBの「常駐プライベート」メモリが表示されます。(これは、Java1.7.0_05を使用するMacOS Xでテストしています。)アプリ固有のコードは、わずか数MBである可能性があります。典型的なJavaWebアプリは1つのサーバープロセス(Tomcatなど)に追加されたjarであることがわかっていますが、Playを実行する標準的な方法はスタンドアロンのアプリ/プロセスであるようです。これらがCプログラムの場合、その200MBのほとんどは共有ライブラリであり、各アプリで複製されません。これをJavaで実現する方法はありますか?クラスデータ共有に関するページがいくつかありますが、それはコアランタイムクラスにのみ適用されるようです。
4 に答える
現時点では、Oracle VMでは、これは不可能です。
しかし、私は同意します。特に、Javaにはそれを自動的に行うために必要なすべての情報があるので、これは素晴らしい機能になるでしょう。
何よりも、これが機能しない唯一の理由はJITだと思います。JITは実行時の動作を考慮に入れています。したがって、アプリAがアプリBとは異なるパターンでコードを使用すると、実行時に異なるアセンブラーコードが生成されます。
しかし、通常の「パターン」は「このコードが使用される頻度」です。したがって、アプリAが何らかのメソッドを頻繁に呼び出し、Bが呼び出さなかった場合でも、Aはコードの最適化/コンパイルの代金をすでに支払っているため、コードを共有できます。
試すことができるのは、複数のアプリケーションをWARファイルとして単一のVMにデプロイすることです。しかし、私の経験からすると、スレッドローカルまたはシャットダウンフックを正しくクリーンアップしないコードで問題が発生することがよくあります。
IBM JDKには、これを実現するためのjvmパラメーターがあります。@http://www.ibm.com/developerworks/library/j-sharedclasses/をチェックしてください
そして、これは次のステップに進みます:http ://www.ibm.com/developerworks/library/j-multitenant-java/index.html
仮想ホストをサポートするサーブレットコンテナを使用している場合(Tomcatがサポートしていると思います)、play2-war-pluginを使用できます。Play 2.1から、常にルートアプリであるという要件が解除されるため、おそらく任意のサーブレットコンテナを使用できるようになります。
すべてのクラスが再度読み込まれないように、warファイルを微調整WEB-INF/lib
してサーブレットコンテナのlibディレクトリに移動する必要があり、シングルトンまたは他の形式のクラス共有を使用している場合、アプリに影響を与える可能性があることに注意してください。データ。
JVMインスタンス間でメモリを共有する問題は、モバイルプラットフォームでより差し迫っています。私が知る限り、AndroidにはZygoteでの解決策があります。つまり、VMが初期化され、アプリを実行するとfork()
編集されます。LinuxはRAMページでコピーオンライトを使用するため、ほとんどのデータが複製されることはありません。
Linuxで実行していて、VMとしてDalvikを使用してみたい場合は、このソリューションの移植が可能かもしれません(DalvikにTomcatの移植が機能しているという主張を見ました)。これは膨大な量の作業であり、最終的にはメモリのアップグレードにかかる費用を数ドル節約できると思います。