国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

三、JVM-如何判斷對象已死問題

這篇具有很好參考價值的文章主要介紹了三、JVM-如何判斷對象已死問題。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

內(nèi)存模型以及如何判定對象已死問題

體驗與驗證

2.4.5.1 使用visualvm

visualgc插件下載鏈接 :https://visualvm.github.io/pluginscenters.html

選擇對應(yīng)JDK版本鏈接—>Tools—>Visual GC
若上述鏈接找不到合適的,大家也可以自己在網(wǎng)上下載對應(yīng)的版本

2.4.5.2 堆內(nèi)存溢出
  • 代碼
@RestController
public class HeapController {
    List<Person> list=new ArrayList<Person>();
    @GetMapping("/heap")
    public String heap(){
        while(true){
            list.add(new Person());
        }
    }
}

記得設(shè)置參數(shù)比如-Xmx20M -Xms20M

  • 運行結(jié)果

訪問:http://localhost:8080/heap

Exception in thread "http-nio-8080-exec-2" java.lang.OutOfMemoryError: GC overhead limit exceeded
2.4.5.3 方法區(qū)內(nèi)存溢出

比如向方法區(qū)中添加Class的信息

  • asm依賴和Class代碼
<dependency>
    <groupId>asm</groupId>
    <artifactId>asm</artifactId>
    <version>3.3.1</version>
</dependency>
public class MyMetaspace extends ClassLoader {
    public static List<Class<?>> createClasses() {
        List<Class<?>> classes = new ArrayList<Class<?>>();
        for (int i = 0; i < 10000000; ++i) {
            ClassWriter cw = new ClassWriter(0);
            cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
                    "java/lang/Object", null);
            MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
                    "()V", null, null);
            mw.visitVarInsn(Opcodes.ALOAD, 0);
            mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
                    "<init>", "()V");
            mw.visitInsn(Opcodes.RETURN);
            mw.visitMaxs(1, 1);
            mw.visitEnd();
            Metaspace test = new Metaspace();
            byte[] code = cw.toByteArray();
            Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length);
            classes.add(exampleClass);
        }
        return classes;
    }
}
  • 代碼
@RestController
public class NonHeapController {
    List<Class<?>> list=new ArrayList<Class<?>>();

    @GetMapping("/nonheap")
    public String nonheap(){
        while(true){
            list.addAll(MyMetaspace.createClasses());
        }
    }
}

設(shè)置Metaspace的大小,比如-XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=50M

  • 運行結(jié)果

訪問->http://localhost:8080/nonheap

java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_191]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_191]
2.4.5.4 虛擬機棧

三、JVM-如何判斷對象已死問題,JVM,jvm

  • 代碼演示StackOverFlow
public class StackDemo {
    public static long count=0;
    public static void method(long i){
        System.out.println(count++);
        method(i);
    }
    public static void main(String[] args) {
        method(1);
    }
}
  • 運行結(jié)果

三、JVM-如何判斷對象已死問題,JVM,jvm

  • 說明
Stack Space用來做方法的遞歸調(diào)用時壓入Stack Frame(棧幀)。所以當(dāng)遞歸調(diào)用太深的時候,就有可能耗盡Stack Space,爆出StackOverflow的錯誤。

-Xss128k:設(shè)置每個線程的堆棧大小。JDK 5以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。根據(jù)應(yīng)用的線程所需內(nèi)存大小進行調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更多的線程。但是操作系統(tǒng)對一個進程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在3000~5000左右。

線程棧的大小是個雙刃劍,如果設(shè)置過小,可能會出現(xiàn)棧溢出,特別是在該線程內(nèi)有遞歸、大的循環(huán)時出現(xiàn)溢出的可能性更大,如果該值設(shè)置過大,就有影響到創(chuàng)建棧的數(shù)量,如果是多線程的應(yīng)用,就會出現(xiàn)內(nèi)存溢出的錯誤。

思考:什么時候才會進行垃圾回收 ?

關(guān)注的內(nèi)存的回收 收的多 抉擇 :收的多 還是時間短

回收 短到什么程度 短到感知不到 1次網(wǎng)絡(luò)延遲時間

CPU使用率很高的情況下 適當(dāng)降低垃圾回收的頻率

對象的生命周期

三、JVM-如何判斷對象已死問題,JVM,jvm

創(chuàng)建階段

(1)為對象分配存儲空間

(2)開始構(gòu)造對象

(3)從超類到子類對static成員進行初始化

(4)超類成員變量按順序初始化,遞歸調(diào)用超類的構(gòu)造方法

(5)子類成員變量按順序初始化,子類構(gòu)造方法調(diào)用,并且一旦對象被創(chuàng)建,并被分派給某些變量賦值,這個對象的狀態(tài)就切換到了應(yīng)用階段

應(yīng)用階段

(1)系統(tǒng)至少維護著對象的一個強引用(Strong Reference)

(2)所有對該對象的引用全部是強引用(除非我們顯式地使用了:軟引用(Soft Reference)、弱引用(Weak Reference)或虛引用(Phantom Reference))

引用的定義:

1.我們的數(shù)據(jù)類型必須是引用類型

2.我們這個類型的數(shù)據(jù)所存儲的數(shù)據(jù)必須是另外一塊內(nèi)存的起始地址

三、JVM-如何判斷對象已死問題,JVM,jvm

引用:

1.強引用

JVM內(nèi)存管理器從根引用集合(Root Set)出發(fā)遍尋堆中所有到達對象的路徑。當(dāng)?shù)竭_某對象的任意路徑都不含有引用對象時,對這個對象的引用就被稱為強引用

2.軟引用

軟引用是用來描述一些還有用但是非必須的對象。對于軟引用關(guān)聯(lián)的對象,在系統(tǒng)將于發(fā)生內(nèi)存溢出異常之前,將會把這些對象列進回收范圍中進行二次回收。

(當(dāng)你去處理占用內(nèi)存較大的對象 并且生命周期比較長的,不是頻繁使用的)

問題:軟引用可能會降低應(yīng)用的運行效率與性能。比如:軟引用指向的對象如果初始化很耗時,或者這個對象在進行使用的時候被第三方施加了我們未知的操作。

3.弱引用

弱引用(Weak Reference)對象與軟引用對象的最大不同就在于:GC在進行回收時,需要通過算法檢查是否回收軟引用對象,而對于Weak引用對象, GC總是進行回收。因此Weak引用對象會更容易、更快被GC回收

4.虛引用

也叫幽靈引用和幻影引用,為一個對象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個對象被回收時收到一個系統(tǒng)通知。也就是說,如果一個對象被設(shè)置上了一個虛引用,實際上跟沒有設(shè)置引用沒有任何的區(qū)別

軟引用代碼Demo:

public class SoftReferenceDemo {
    public static void main(String[] args) {
        //。。。一堆業(yè)務(wù)代碼

        Worker a = new Worker();
//。。業(yè)務(wù)代碼使用到了我們的Worker實例

        // 使用完了a,將它設(shè)置為soft 引用類型,并且釋放強引用;
        SoftReference sr = new SoftReference(a);
        a = null;
//這個時候他是有可能執(zhí)行一次GC的
        System.gc();

        // 下次使用時
        if (sr != null) {
            a = (Worker) sr.get();
            System.out.println(a );
        } else {
            // GC由于內(nèi)存資源不足,可能系統(tǒng)已回收了a的軟引用,
            // 因此需要重新裝載。
            a = new Worker();
            sr = new SoftReference(a);
        }
    }


}

弱引用代碼Demo:

public class WeakReferenceDemo {
    public static void main(String[] args) throws InterruptedException {
        //100M的緩存數(shù)據(jù)
        byte[] cacheData = new byte[100 * 1024 * 1024];
        //將緩存數(shù)據(jù)用軟引用持有
        WeakReference<byte[]> cacheRef = new WeakReference<>(cacheData);
        System.out.println("第一次GC前" + cacheData);
        System.out.println("第一次GC前" + cacheRef.get());
        //進行一次GC后查看對象的回收情況
        System.gc();
        //因為我們不確定我們的System什么時候GC
        Thread.sleep(1000);
        System.out.println("第一次GC后" + cacheData);
        System.out.println("第一次GC后" + cacheRef.get());

        //將緩存數(shù)據(jù)的強引用去除
        cacheData = null;
        System.gc();    //默認(rèn)通知一次Full  GC
        //等待GC
        Thread.sleep(500);
        System.out.println("第二次GC后" + cacheData);
        System.out.println("第二次GC后" + cacheRef.get());

//        // 弱引用Map
//        WeakHashMap<String, String> whm = new WeakHashMap<String,String>();
    }
}

虛引用代碼Demo:

public class PhantomReferenceDemo {
    public static void main(String[] args) throws InterruptedException {
        Object value = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        Thread thread = new Thread(() -> {
            try {
                int cnt = 0;
                WeakReference<byte[]> k;
                while ((k = (WeakReference) referenceQueue.remove()) != null) {
                    System.out.println((cnt++) + "回收了:" + k);
                }
            } catch (InterruptedException e) {
                //結(jié)束循環(huán)
            }
        });
        thread.setDaemon(true);
        thread.start();


        Map<Object, Object> map = new HashMap<>();
        for (int i = 0; i < 10000; i++) {
            byte[] bytes = new byte[1024 * 1024];
            WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue);
            map.put(weakReference, value);
        }
        System.out.println("map.size->" + map.size());


    }
}

finalize方法代碼Demo:

public class Finalize {

    private static Finalize save_hook = null;//類變量

    public void isAlive() {
        System.out.println("我還活著");
    }

    @Override
    public void finalize() {
        System.out.println("finalize方法被執(zhí)行");
        Finalize.save_hook = this;
    }

    public static void main(String[] args) throws InterruptedException {



        save_hook = new Finalize();//對象
        //對象第一次拯救自己
        save_hook = null;
        System.gc();
        //暫停0.5秒等待他
        Thread.sleep(500);
        if (save_hook != null) {
            save_hook.isAlive();
        } else {
            System.out.println("好了,現(xiàn)在我死了");
        }

        //對象第二次拯救自己
        save_hook = null;
        System.gc();
        //暫停0.5秒等待他
        Thread.sleep(500);
        if (save_hook != null) {
            save_hook.isAlive();
        } else {
            System.out.println("我終于死亡了");
        }
    }
}

不可見階段

不可見階段的對象在虛擬機的對象根引用集合中再也找不到直接或者間接的強引用,最常見的就是線程或者函數(shù)中的臨時變量。程序不在持有對象的強引用。 (但是某些類的靜態(tài)變量或者JNI是有可能持有的 )

不可達階段

指對象不再被任何強引用持有,GC發(fā)現(xiàn)該對象已經(jīng)不可達。

如何確定一個對象是垃圾?

要想進行垃圾回收,得先知道什么樣的對象是垃圾。

2.5.1.1 引用計數(shù)法

對于某個對象而言,只要應(yīng)用程序中持有該對象的引用,就說明該對象不是垃圾,如果一個對象沒有任何指針對其引用,它就是垃圾。

弊端:如果AB相互持有引用(循環(huán)引用),導(dǎo)致永遠(yuǎn)不能被回收。

三、JVM-如何判斷對象已死問題,JVM,jvm

2.5.1.2 可達性分析

通過GC Root的對象,開始向下尋找,看某個對象是否可達 根對象(錯誤的)

三、JVM-如何判斷對象已死問題,JVM,jvm

能作為GC Root:類加載器、Thread、虛擬機棧的本地變量表、static成員、常量引用、本地方法棧的變量等。GC Roots本質(zhì)上一組活躍的引用

虛擬機棧(棧幀中的本地變量表)中引用的對象。
方法區(qū)中類靜態(tài)屬性引用的對象。
方法區(qū)中常量引用的對象。
本地方法棧中JNI(即一般說的Native方法)引用的對象。

收集階段(Collected)

GC發(fā)現(xiàn)對象處于不可達階段并且GC已經(jīng)對該對象的內(nèi)存空間重新分配做好準(zhǔn)備,對象進程收集階段。如果,該對象的finalize()函數(shù)被重寫,則執(zhí)行該函數(shù)。

1.會影響到JVM的對象以及分配回收速度

2.可能造成對象再次復(fù)活(詐尸)

終結(jié)階段(Finalized)

對象的finalize()函數(shù)執(zhí)行完成后,對象仍處于不可達狀態(tài),該對象進程終結(jié)階段。

對象內(nèi)存空間重新分配階段(Deallocaled)

GC對該對象占用的內(nèi)存空間進行回收或者再分配,該對象徹底消失。文章來源地址http://www.zghlxwxcb.cn/news/detail-622948.html

到了這里,關(guān)于三、JVM-如何判斷對象已死問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • JVM 內(nèi)存分哪幾個區(qū),如和判斷一個對象是否存活

    JVM 內(nèi)存分哪幾個區(qū),每個區(qū)的作用是什么 ? java 虛擬機主要分為以下一個區(qū) : 方法區(qū): 1. 有時候也成為 永久代 ,在該區(qū)內(nèi)很少發(fā)生垃圾回收,但是并不代表不發(fā)生 ?GC ,在這里進行的 ?GC 主要是對方法區(qū)里的常量池和對類型的卸載 2. 方法區(qū)主要用來存儲已被虛擬機加載的類

    2024年02月05日
    瀏覽(24)
  • JVM面試題-JVM對象的創(chuàng)建過程、內(nèi)存分配、內(nèi)存布局、訪問定位等問題詳解

    JVM面試題-JVM對象的創(chuàng)建過程、內(nèi)存分配、內(nèi)存布局、訪問定位等問題詳解

    內(nèi)存分配的兩種方式 指針碰撞 適用場合:堆內(nèi)存 規(guī)整 (即沒有內(nèi)存碎片)的情況下。 原理:用過的內(nèi)存全部整合到一邊,沒有用過的內(nèi)存放在另一邊,中間有一個分界指針,只需要向著沒用過的內(nèi)存方向?qū)⒃撝羔樢苿訉ο髢?nèi)存大小位置即可。 使用該分配方式的GC收集器:

    2024年02月08日
    瀏覽(19)
  • JVM對象在堆內(nèi)存中是否如何分配?

    JVM對象在堆內(nèi)存中是否如何分配?

    1:指針碰撞:內(nèi)存規(guī)整的情況下 2:空閑列表: 內(nèi)存不規(guī)整的情況下 選擇那種分配方式 是有 java堆是否規(guī)整而決定的。而java堆是否規(guī)整是否對應(yīng)的垃圾回收器是否帶有空間壓縮整理的能力決定的。 因此當(dāng)使用Serial,ParNew等帶有壓縮整理過程的收集器時,系統(tǒng)采用的分配算法是

    2024年02月16日
    瀏覽(22)
  • Jvm對象回收算法-JVM(九)

    Jvm對象回收算法-JVM(九)

    上篇文章介紹了jvm運行時候?qū)ο筮M入老年代的場景,以及如何避免頻繁fullGC。 Jvm參數(shù)設(shè)置-JVM(八) 老年代分配擔(dān)保機制 這個機制的目的是為了提升效率,在minorGC之前,會有三次判斷,之后再次minorGC速度會很快。 老年代剩余空間是否 大于 年輕代里現(xiàn)在所有對象 大于的話則

    2024年02月13日
    瀏覽(22)
  • JVM-JVM中對象的結(jié)構(gòu)

    JVM-JVM中對象的結(jié)構(gòu)

    對象內(nèi)存布局 對象里的三個區(qū): 對象頭(Header):Java對象頭占8byte。如果是數(shù)組則占12byte。因為JVM里數(shù)組size需要使用4byte存儲。 標(biāo)記字段MarkWord: 用于存儲對象自身的運行時數(shù)據(jù),它是synchronized實現(xiàn)輕量級鎖和偏向鎖的關(guān)鍵。 默認(rèn)存儲:對象HashCode、GC分代年齡、鎖狀態(tài)等

    2024年02月20日
    瀏覽(26)
  • Jvm創(chuàng)建對象之內(nèi)存分配-JVM(七)

    Jvm創(chuàng)建對象之內(nèi)存分配-JVM(七)

    上篇文章介紹了jvm創(chuàng)建,會校驗是否已加載類,沒有則加載,通過之前學(xué)的源碼,classLoader加載完之后,虛擬機開始給類分配內(nèi)存,指針移動分配和free鏈表分配,解決并發(fā)分配情況用cap和TLAB方法。之后設(shè)置對象頭部信息,有mark word線程鎖,分代年齡等,klass pointer。還有指針

    2024年02月13日
    瀏覽(25)
  • 【Jvm】性能調(diào)優(yōu)(拓展)Jprofiler如何監(jiān)控和解決死鎖、內(nèi)存泄露問題

    【Jvm】性能調(diào)優(yōu)(拓展)Jprofiler如何監(jiān)控和解決死鎖、內(nèi)存泄露問題

    Jprofilers是針對Java開發(fā)的 性能分析工具(免費試用10天) , 可以對Java程序的 內(nèi)存,CPU,線程,GC,鎖 等進行監(jiān)控和分析 , 本人IDEA版本是 2020.2.2 ,選擇的Jprofiler版本是 12.0 (早期的版本是純英文的, 12.0支持中文 ,安裝主要考慮是否與IDEA插件兼容即可) 進入Jprofiler官網(wǎng)下載 - Jprofiler 版本這

    2024年02月19日
    瀏覽(24)
  • JVM系列(六) JVM 對象終結(jié)方法finalize

    我們有幾個特別容易混淆的final、finally、finalize, 他們之間的區(qū)別是什么? final 是java finally 是try-catch-finally finalize 是Object 根類的方法 今天我們著重講下 finalize方法 1.finalize方法的原理及調(diào)用 finalize方法也是Java中所有類中必有的方法,因為它是屬于Object根類的方

    2023年04月08日
    瀏覽(21)
  • JVM-JVM中對象的生命周期

    JVM-JVM中對象的生命周期

    申明:文章內(nèi)容是本人學(xué)習(xí)極客時間課程所寫,文字和圖片基本來源于課程資料,在某些地方會插入一點自己的理解,未用于商業(yè)用途,侵刪。 原資料地址:課程資料 對象的創(chuàng)建 常量池檢查 :檢查new指令是否能在常量池中定位到這個類的符號引用,檢查類之前是否被加載過

    2024年02月20日
    瀏覽(22)
  • JVM 對象引用類型

    對象引用類型分為強引用、軟引用、弱引用和虛引用。 強引用 ????????聲明對象時虛擬機生成的引用,是指在程序代碼之中普遍存在的引用賦值。強引用環(huán)境下,垃圾回收時需要嚴(yán)格判斷當(dāng)前對象是否被強引用,如果被強引用,則不會被垃圾回收,當(dāng)內(nèi)存空間不足的時候

    2024年02月09日
    瀏覽(15)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包