JDK1.8が永久世代を放棄するのはなぜですか[1つで十分です]

JDK8-メタスペース(メタスペース)で先導された放棄されたPermGen(PermGen)

1.背景

2.永続的な世代を放棄する理由(PermGen)

3.メタスペースの深い理解(メタスペース)

4.まとめ

========テキスト分割線=====

1.背景

1.1永久世代(PermGen)はどこにありますか?

ホットスポットによると、jvmの構造は次のとおりです(仮想マシンスタックとローカルメソッドスタックが組み合わされています)。

上の図はネットワークから引用されていますが、問題があります。メソッド領域とヒープヒープの両方が、スレッドによって共有されるメモリ領域です。

メソッド領域と永続的な生成について:

HotSpot JVMでは、今回説明する永続的な生成は、上の図のメソッド領域(JVM仕様ではメソッド領域と呼ばれます)です。「Java仮想マシン仕様」は、メソッド領域とその機能の概念のみを規定しており、その実装方法は規定していません。他のJVMには永続的な生成はありません。
 

1.2JDK8永久世代の廃止

JDK8の永続的な生成の変更は次のとおりです。

1.新世代:エデン+サバイバーから+サバイバーへ

2.老齢:OldGen

3.永続的な生成(メソッド領域の実装):PermGen ----->メタスペースに置き換えます(ローカルメモリ内)

 

 2.永続的な世代を放棄する理由(PermGen)

 2.1公式の指示

JEP122:http://openjdk.java.net/jeps/122を参照してください。元のテキストは傍受されます:

動機

これは、JRockitとホットスポットのコンバージェンスの取り組みの一部です。JRockitのお客様は、永続的な世代を構成する必要はなく(JRockitには永続的な世代がないため)、永続的な世代を構成しないことに慣れています。

 つまり、永続世代の削除は、HotSpotJVMとJRockitVMを統合するための取り組みです。これは、JRockitには永続世代がなく、永続世代を構成する必要がないためです。

 2.2実際の使用で問題が発生しやすい

永続的な生成メモリが不十分であるか、メモリリークが発生することが多いため、例外java.lang.OutOfMemoryError:PermGen

3.メタスペースの深い理解

3.1メタスペースのメモリサイズ

メタスペースは、HotSpot jvmのメソッド領域の実装です。メソッド領域は、主にクラス情報、定数プール、メソッドデータ、メソッドコードなどを格納するために使用されます。メソッド領域は論理的にはヒープの一部ですが、ヒープと区別するために、通常は「非ヒープ」と呼ばれます。

メタスペースの性質は、JVM仕様のメソッド領域の実現である永続的な生成の性質と似ています。ただし、メタスペースと永続的な生成の最大の違いは、メタスペースが仮想マシンになく、ローカルメモリを使用することです。、理論的には、32ビット/ 64ビットシステムの仮想メモリサイズに依存します。無制限ではなく、構成パラメーターが必要であることがわかります。

3.2一般的な構成パラメーター

1.MetaspaceSize

初期化されたメタスペースのサイズは、メタスペースで発生するGCのしきい値を制御します。GCの後、MetaspaceSizeを動的に増減します。デフォルトでは、この値はプラットフォームに応じて12Mから20Mまで変化します。Java  -XX:+ PrintFlagsInitialコマンドを使用して、マシンの初期化パラメーターを表示します

2.MaxMetaspaceSize

メタスペースの成長の上限を制限して、特定の状況や他のプログラムに影響を与えるためにメタスペースがローカルメモリを無期限に使用しないようにします。このマシンでのこのパラメーターのデフォルト値は4294967295B(約4096MB)です。

3.MinMetaspaceFreeRatio

Metaspace GCが実行された後、Metaspaceの現在の空き領域比率が計算されます。空き領域比率がこのパラメーターよりも小さい場合(つまり、実際の非アイドル比率が大きすぎてメモリが不足している場合)、仮想マシンはMetaspaceのサイズを増やします。デフォルト値は40、つまり40%です。このパラメータを設定すると、メタスペースの成長率を制御できます。値が小さすぎると、メタスペースの成長が遅くなり、メタスペースの使用が徐々に飽和状態になり、後続のクラスの読み込みに影響を与える可能性があります。値が大きすぎると、メタスペースの成長が速すぎてメモリが浪費されます。

4.MaxMetasaceFreeRatio

メタスペースGCが実行された後、現在のメタスペースの空きスペース比率が計算されます。空きスペース比率がこのパラメーターより大きい場合、仮想マシンはメタスペーススペースの一部を解放します。デフォルト値は70、つまり70%です。

5.MaxMetaspaceExpansion

メタスペースが大きくなるときの最大振幅。このマシンでのこのパラメーターのデフォルト値は5452592B(約5MB)です。

6.MinMetaspaceExpansion

メタスペースが大きくなるときの最小振幅。このマシンでのこのパラメーターのデフォルト値は340784B(約330KB)です。

3.3メタスペースのサイズをテストおよび追跡する

 3.3.1。テスト文字列定数

import java.util.ArrayList;
import java.util.List;

public class StringTest {
    static String  base = "string";

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        for (int i=0;i< Integer.MAX_VALUE;i++){
            String str = base + base;
            base = str;
            list.add(str.intern());
        }
    }
}

 

 最大メモリは20Mに設定されているため、以下に示すように、すぐにオーバーフローします。

 それはjdk8で見ることができます:

1.文字列定数が永続世代からヒープに転送されます。

2.永続的な生成は存在しなくなり、PermSizeMaxPermSizeパラメーターは削除されました。(写真の最後の2行を参照してください)

3.3.2。メタスペースオーバーフローのテスト

定義によれば、クラスをロードすることによってメタスペースのオーバーフローをテストします。コードは次のとおりです。

1パッケージjdk8; 
 2 
 3インポートjava.io.Fileの; 
 4インポートjava.lang.management.ClassLoadingMXBean; 
 5インポートjava.lang.management.ManagementFactory; 
 6インポートのjava.net.URL; 
 7インポートjava.net.URLClassLoader; 
 8 import java.util.ArrayList; 
 9 import java.util.List; 
10 
11 / ** 
12 * 
13 * @ClassName:OOMTest 
14 * @Description:クラスローディングオーバーフローのシミュレーション(メタスペースoom)
15 * @author diandian.zhang 
16 * @date 9:45:40 AM、2017年4月27日
17 * / 
18 public class OOMTest {   
19 public static void main(String [] args){   
20 try {   
21 // Prepare url  
22 URL url = new File( "D:/ 58workplace / 11study / src / main / java / jdk8")。toURI()。toURL();   
23 URL [] urls = {url};   
24 //関連するタイプの読み込みを取得JMXインターフェイス  
25ClassLoadingMXBean LoadingBean = ManagementFactory.getClassLoadingMXBean();   
26 //クラスローダーのキャッシュに使用  
27List <ClassLoader> classLoaders = new ArrayList <ClassLoader>();   
28 while(true){   
29 //ロードタイプとキャッシュクラスローダーインスタンス  
30ClassLoader classLoader = new URLClassLoader(urls);   
31 classLoaders.add(classLoader);   
32 classLoader.loadClass( "ClassA"); 
33 //数量情報(現在有効な、合計でロードされたタイプの数)を表示します。  タイプの数、アンインストールされたタイプの数)  
34 System.out.println( "total:" + loadBean.getTotalLoadedClassCount());  
35 System.out.println( "active:" + loadBean.getLoadedClassCount());  
36 System.out.println( "unloaded:" + loadBean.getUnloadedClassCount());  
37}   
38} catch(例外e){   
39 e.printStackTrace();  
40}   
41}   
42}  

すばやくオーバーフローするには、パラメータを設定します:-XX:MetaspaceSize = 8m -XX:MaxMetaspaceSize = 80m、実行結果は次のとおりです。

 

 上の図は、JDK8のクラスロード(メソッド領域の関数)が永続的なPerGemではなく、Metaspaceにあることを確認しています。より直感的なJVisualVMで見ることができます。

 4、まとめ

この記事では、メタスペースの起源と本質、一般的な構成、および監視とテストについて説明します。メタスペースのサイズは動的に変化しますが、無限ではありません。サーバーのメモリに影響を与えないように、サイズを監視することをお勧めします。

おすすめ

転載: blog.csdn.net/sjmz30071360/article/details/89456177