最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM類加載,垃圾回收

 更新時(shí)間:2021年07月05日 09:59:57   作者:保護(hù)眼睛  
這篇文章主要介紹了JVM的幾種垃圾回收器,文中通過示例代碼介紹的很詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

類加載子系統(tǒng)

classLoader 只負(fù)責(zé)對(duì)字節(jié)碼文件的加載,至于是否可以運(yùn)行,還要看執(zhí)行引擎。

在這里插入圖片描述

  • 加載的類信息存放于方法區(qū)的內(nèi)存空間,除了類信息之外,還會(huì)存放有運(yùn)行時(shí)常量池的信息,還可能包含字符串字面量和數(shù)字常量。

loading加載:

通過一個(gè)類的全限定名獲得定義此類的二進(jìn)制字節(jié)流。也就是根據(jù)完整的路徑找到對(duì)應(yīng)類的二進(jìn)制字節(jié)流。

將這個(gè)字節(jié)流所代表的靜態(tài)的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運(yùn)行時(shí)的數(shù)據(jù)結(jié)構(gòu)

  • 在內(nèi)存中生成一個(gè)代表這個(gè)類的Java.lang.Class對(duì)象,作為方法區(qū)這個(gè)方法數(shù)據(jù)的入口。

鏈接:驗(yàn)證、準(zhǔn)備、解析

驗(yàn)證:目的在于確保二進(jìn)制字節(jié)流包含的信息符合虛擬機(jī)的要求,保證被加載類的正確性,不會(huì)危害虛擬機(jī)的安全。

驗(yàn)證文件格式、字節(jié)碼、元數(shù)據(jù)、符號(hào)引用的驗(yàn)證

準(zhǔn)備:為類變量分配內(nèi)存并設(shè)置默認(rèn)的初始值,即零值。

不包含被final修飾的類變量

解析:將常量池的符號(hào)轉(zhuǎn)化為直接引用的過程。

初始化:JVM將程序的執(zhí)行權(quán)交給程序。

雙親委派模型

雙親委派模型的原理:如果一個(gè)類加載器收到了類加載的請(qǐng)求的話,它首先不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給自己的父類加載器去完成,每一層的加載器都是如此,因此所有的加載請(qǐng)求都會(huì)傳送到最頂層的啟動(dòng)類加載器中,只有當(dāng)父類加載器反饋?zhàn)约簾o(wú)法加載這個(gè)請(qǐng)求的時(shí)候,即父類搜索不到這個(gè)類的時(shí)候,子類才會(huì)自己嘗試去加載。

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);
                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

在這里插入圖片描述

使用雙親委派模型來(lái)組織類加載之間的關(guān)系,一個(gè)顯而易見的好處就是Java中類隨著它的類加載器一起具備了一種帶有優(yōu)先級(jí)的層級(jí)關(guān)系。因此Object類在程序中的各種類加載的環(huán)境中都能保證是同一個(gè)類。反之,如果沒有雙親委派模型的話,都由各個(gè)的類加載器去加載的話,如果用戶自定義了一個(gè)java.lang.Object的類,并放在ClassPath 中的話,就會(huì)出現(xiàn)多個(gè)Object類,Java中最基礎(chǔ)的體系也就會(huì)無(wú)法保證。

破壞雙親委派模型:

1.雙親委派模型被破壞的第一次就是剛引入雙親委派模型的時(shí)候,是為了兼容JDK1.2之前的代碼

2.雙親委派模型的第二次的破壞就是自生的缺陷導(dǎo)致的。但發(fā)生父類調(diào)用子類的時(shí)候。

3.第三次就是用戶對(duì)于程序動(dòng)態(tài)性的追求而導(dǎo)致的:代碼熱的替換、模塊熱的部署。

垃圾回收

什么是垃圾?

GC 中的垃圾就是特指在內(nèi)存中的、不會(huì)在被使用的對(duì)象。

判斷對(duì)象已死

引用計(jì)數(shù)器法:

每個(gè)對(duì)象添加一個(gè)引用計(jì)數(shù)器,每被引用一次,計(jì)數(shù)器加1,失去引用,計(jì)數(shù)器減1,當(dāng)計(jì)數(shù)器在一段時(shí)間內(nèi)保持為0時(shí),該對(duì)象就認(rèn)為是可以被回收得了。(在JDK1.2之前,使用的是該算法)

缺點(diǎn):當(dāng)兩個(gè)對(duì)象A、B相互引用的時(shí)候,當(dāng)其他所有的引用都消失之后,A和B還有一個(gè)相互引用,此時(shí)計(jì)數(shù)器各為1,而實(shí)際上這兩個(gè)對(duì)象都已經(jīng)沒有額外的引用了,已經(jīng)是垃圾了。但是卻不會(huì)被回收,引用計(jì)數(shù)器法不能解決循環(huán)引用的問題。

JVM垃圾回收采用的是可達(dá)性分析算法:

在這里插入圖片描述

從GC set中的GC roots 作為起點(diǎn),從這些節(jié)點(diǎn)向下搜索,搜索的路徑被稱為引用鏈,如果一個(gè)對(duì)象不存在引用鏈的話,那么說(shuō)明這個(gè)對(duì)象已死。就會(huì)被GC回收器回收。

GCroots 是:

1.來(lái)自于JVM棧中引用的對(duì)象。比如各個(gè)線程中被調(diào)用的方法堆棧中使用到的參數(shù)、局部變量、臨時(shí)變量等。

2.方法區(qū)中靜態(tài)屬性引用的對(duì)象。比如Java中的引用類型靜態(tài)變量。

3.方法區(qū)中常量引用的對(duì)象。比如字符串常量池(String Table)中的引用。

4.本地方法棧中引用的對(duì)象。

5.Java虛擬機(jī)內(nèi)部的引用。比如基本數(shù)據(jù)類型對(duì)應(yīng)的Class對(duì)象,一些常駐的異常類等,還有系統(tǒng)的類加載器。

6.所有被同步鎖持有的對(duì)象。 …

并不是所有的引用對(duì)象一定就會(huì)被GC 的時(shí)候回收掉。

JDK1.2之后的四種引用類型:

1.強(qiáng)引用:

就是程序中一般使用的引用類型,即使發(fā)生OOM也不會(huì)回收的對(duì)象。

就是為剛被new出來(lái)的對(duì)象所加的引用,它的特點(diǎn)就是,永遠(yuǎn)不會(huì)被GC,除非顯示的設(shè)置null,才會(huì)GC。

比如:

package Reference;
/**
 * user:ypc;
 * date:2021-06-19;
 * time: 9:40;
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("I am FinalReference");
        System.gc();
        System.out.println(stringBuilder);
        //觸發(fā)GC
        byte[] bytes = new byte[1024 * 940 * 7];
        System.gc();
        System.out.println(stringBuilder);
        try {
            byte[] bytes2 = new byte[1024 * 1024 * 7];
        } catch (Exception e) {
        } finally {
            System.out.println("發(fā)生了OOM:");
            System.out.println(stringBuilder);
        }
    }
}

在這里插入圖片描述

2.軟引用:

就是用來(lái)描述一些還有用,但是非必須的對(duì)象,只被軟引用關(guān)聯(lián)著的對(duì)象,在系統(tǒng)將要發(fā)生OOM前會(huì)回收的對(duì)象。如果這次回收還沒有足夠的內(nèi)存,才會(huì)拋出OOM的異常。

package Reference;
/**
 * user:ypc;
 * date:2021-06-19;
 * time: 9:46;
 */
public class SoftReference {
    public static class User {
        private int id;
        private String name;
        User(int id, String name) {
            this.id = id;
            this.name = name;
        }
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    public static void main(String[] args) {
        //user 是強(qiáng)引用
        User user = new User(1001, "小明");
        //softReference 是軟引用
        java.lang.ref.SoftReference<User> softReference = new java.lang.ref.SoftReference<>(user);
        //  顯示的將強(qiáng)引用置為null
        user = null;
        System.out.println(softReference.get());
        System.gc();
        System.out.println("After GC: ");
        System.out.println(softReference.get());
        //觸發(fā)GC
        byte[] bytes = new byte[1024 * 940 * 7];
        System.gc();
        System.out.println(softReference.get());
    }
}

在這里插入圖片描述

3.弱引用:

弱引用也是用來(lái)描述那些非必要的對(duì)象,它的強(qiáng)度比軟引用還低一些。當(dāng)垃圾回收器開始工作的時(shí)候,無(wú)論內(nèi)存是否夠用,都會(huì)回收掉只被弱引用關(guān)聯(lián)著的對(duì)象。

    public static void main(String[] args) {
        User user = new User(1002,"小明");
        java.lang.ref.WeakReference<User> weakReference = new java.lang.ref.WeakReference<>(user);
        user = null;
        System.out.println(weakReference.get());
        System.gc();
        System.out.println("After GC");
        System.out.println(weakReference.get());
    }

在這里插入圖片描述

4.虛引用:

它是最弱的一種引用關(guān)系。剛被創(chuàng)建就會(huì)被GC回收器回收。它的價(jià)值就是在GC 的時(shí)候觸發(fā)一次方法的回調(diào)。

虛擬機(jī)中的并行與并發(fā):

并行:

并行描述的是多條垃圾收集器線程之間的關(guān)系,說(shuō)明同一時(shí)間有多條這樣的線程在同時(shí)的進(jìn)行工作。

并發(fā):

并發(fā)描述的是垃圾收集器線程與用戶線程之間的關(guān)系,說(shuō)明同一時(shí)間垃圾收集器的線程和用戶線程之家同時(shí)在運(yùn)行。

常見的垃圾回收算法:

1.標(biāo)記–清除算法:(Mark–Sweep)

將死亡的對(duì)象標(biāo)記,然后進(jìn)行GC。

在這里插入圖片描述

執(zhí)行的效率不穩(wěn)定。如果堆中有大量的對(duì)象,其中有大部分都是要被回收的話 ,那么必需要進(jìn)行大量的標(biāo)記–清除的步驟,導(dǎo)致執(zhí)行效率的降低。

會(huì)造成內(nèi)存碎片的問題,使空間的利用率降低。標(biāo)記–清除之后會(huì)產(chǎn)生大量的不連續(xù)的內(nèi)存碎片。

2.標(biāo)記–復(fù)制算法:

將空間分為兩部分,一部分始終是未使用的狀態(tài)。當(dāng)進(jìn)行垃圾回收的時(shí)候

將存活的對(duì)象復(fù)制到未使用的空間上,然后將另一半的區(qū)域進(jìn)行全GC。

在這里插入圖片描述

但是標(biāo)記–復(fù)制算法在對(duì)象存活率比較高的時(shí)候就要進(jìn)行多次的復(fù)制操作,效率會(huì)降低。而且每次只有50%的內(nèi)存空間被使用。

3.標(biāo)記–整理算法:

將存活的對(duì)象進(jìn)行移動(dòng),然后進(jìn)行GC。

對(duì)象的移動(dòng)需要STW

在這里插入圖片描述

解決了垃圾碎片的問題

常見的垃圾回收器:

在這里插入圖片描述

  • Serial/Serial Old收集器 是最基本最古老的收集器,它是一個(gè)單線程收集器,并且在它進(jìn)行垃圾收集時(shí),必須暫停所有用戶線程。Serial收集器是針對(duì)新生代的收集器,采用的是Copying算法,Serial Old收集器是針對(duì)老年代的收集器,采用的是Mark-Compact算法。它的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單高效,但是缺點(diǎn)是會(huì)給用戶帶來(lái)停頓。
  • ParNew收集器 是Serial收集器的多線程版本,使用多個(gè)線程進(jìn)行垃圾收集。
  • Parallel Scavenge收集器 是一個(gè)新生代的多線程收集器(并行收集器),它在回收期間不需要暫停其他用戶線程,其采用的是Copying算法,該收集器與前兩個(gè)收集器有所不同,它主要是為了達(dá)到一個(gè)可控的吞吐量。
  • Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多線程和Mark-Compact算法。
  • CMS(Concurrent Mark Sweep)收集器 是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器,它是一種并發(fā)收集器,采用的是Mark-Sweep算法。
  • G1收集器 是當(dāng)今收集器技術(shù)發(fā)展最前沿的成果,它是一款面向服務(wù)端應(yīng)用的收集器,它能充分利用多CPU、多核環(huán)境。因此它是一款并行與并發(fā)收集器,并且它能建立可預(yù)測(cè)的停頓時(shí)間模型。

新時(shí)代、老年代

Java 中的堆也是 GC 收集垃圾的主要區(qū)域。GC 分為兩種:Minor GC、FullGC ( 或稱為 Major GC )。 Minor GC 是發(fā)生在新生代中的垃圾收集動(dòng)作,所采用的是復(fù)制算法。新生代幾乎是所有 Java 對(duì)象出生的地方,即 Java 對(duì)象申請(qǐng)的內(nèi)存以及存放都是在這個(gè)地方。Java 中的大部分對(duì)象通常不需長(zhǎng)久存活,具有朝生夕滅的性質(zhì)。

當(dāng)一個(gè)對(duì)象被判定為 “死亡” 的時(shí)候,GC就有責(zé)任來(lái)回收掉這部分對(duì)象的內(nèi)存空間。新生代是GC收集垃圾的頻繁區(qū)域。當(dāng)對(duì)象在 Eden ( 包括一個(gè) Survivor 區(qū)域,這里假設(shè)是 from 區(qū)域 ) 出生后,在經(jīng)過一次 Minor GC 后,如果對(duì)象還存活,并且能夠被另外一塊 Survivor 區(qū)域所容納( 上面已經(jīng)假設(shè)為 from 區(qū)域,這里應(yīng)為 to 區(qū)域,即 to 區(qū)域有足夠的內(nèi)存空間來(lái)存儲(chǔ) Eden 和 from 區(qū)域中存活的對(duì)象 ),則使用復(fù)制算法將這些仍然還存活的對(duì)象復(fù)制到另外一塊 Survivor 區(qū)域 ( 即 to 區(qū)域 ) 中,然后清理所使用過的 Eden 以及 Survivor 區(qū)域 ( 即from 區(qū)域 ),并且將這些對(duì)象的年齡設(shè)置為1,以后對(duì)象在 Survivor 區(qū)每熬過一次 Minor GC,就將對(duì)象的年齡 + 1,當(dāng)對(duì)象的年齡達(dá)到某個(gè)值時(shí) ( 默認(rèn)是 15 也就是經(jīng)歷15次GC之后還存活的對(duì)象),這些對(duì)象就會(huì)被移動(dòng)到老年代。

但這也不是一定的,對(duì)于一些較大的對(duì)象 ( 即需要分配一塊較大的連續(xù)內(nèi)存空間 ) 則是直接進(jìn)入到老年代。Full GC 是發(fā)生在老年代的垃圾收集動(dòng)作,所采用的是標(biāo)記-清除算法。

另外,標(biāo)記-清除算法收集垃圾的時(shí)候會(huì)產(chǎn)生許多的內(nèi)存碎片 ( 即不連續(xù)的內(nèi)存空間 ),此后需要為較大的對(duì)象分配內(nèi)存空間時(shí),若無(wú)法找到足夠的連續(xù)的內(nèi)存空間,就會(huì)提前觸發(fā)一次 GC 的收集動(dòng)作。

為什么大對(duì)象會(huì)直接存在老年代?

大對(duì)象的創(chuàng)建和銷毀隨需要消耗的時(shí)間比較多,所以性能也比較滿,如果存到新生代的話,那么有可能頻繁的創(chuàng)建和銷毀大對(duì)象,導(dǎo)致JVM對(duì)的運(yùn)行的效率變低,所以直接存放在老年代。

在這里插入圖片描述

新生代的各個(gè)區(qū)域的占比分別是:8:1:1 新生代與老年代的占比是:1:2

在這里插入圖片描述

總結(jié)

本篇文章就到里了,希望能幫到你,也希望您能多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • java打jar包與找不到依賴包的問題

    java打jar包與找不到依賴包的問題

    這篇文章主要介紹了java打jar包與找不到依賴包的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java的Spring框架中DAO數(shù)據(jù)訪問對(duì)象的使用示例

    Java的Spring框架中DAO數(shù)據(jù)訪問對(duì)象的使用示例

    這篇文章主要介紹了Java的Spring框架中DAO數(shù)據(jù)訪問對(duì)象的使用示例,分為在Spring中DOA與JDBC以及與Hibernate的配合使用兩種情況來(lái)進(jìn)行演示,需要的朋友可以參考下
    2016-03-03
  • Netty的Handler鏈調(diào)用機(jī)制及如何組織詳解

    Netty的Handler鏈調(diào)用機(jī)制及如何組織詳解

    這篇文章主要為大家介紹了Netty的Handler鏈調(diào)用機(jī)制及如何組織示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Java中常見字符串拼接九種方式詳細(xì)例子

    Java中常見字符串拼接九種方式詳細(xì)例子

    這篇文章主要給大家介紹了關(guān)于Java中常見字符串拼接的九種方式,字符串拼接是我們?cè)贘ava代碼中比較經(jīng)常要做的事情,就是把多個(gè)字符串拼接到一起,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • idea啟動(dòng)springboot報(bào)錯(cuò): 找不到或無(wú)法加載主類問題

    idea啟動(dòng)springboot報(bào)錯(cuò): 找不到或無(wú)法加載主類問題

    這篇文章主要介紹了idea啟動(dòng)springboot報(bào)錯(cuò): 找不到或無(wú)法加載主類問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • maven的安裝配置以及在IDEA中的配置圖文教程

    maven的安裝配置以及在IDEA中的配置圖文教程

    下面小編就為大家分享一篇maven的安裝配置以及在IDEA中的配置圖文教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2017-12-12
  • Spring Boot中定時(shí)任務(wù)Cron表達(dá)式的終極指南最佳實(shí)踐記錄

    Spring Boot中定時(shí)任務(wù)Cron表達(dá)式的終極指南最佳實(shí)踐記錄

    本文詳細(xì)介紹了SpringBoot中定時(shí)任務(wù)的實(shí)現(xiàn)方法,特別是Cron表達(dá)式的使用技巧和高級(jí)用法,從基礎(chǔ)語(yǔ)法到復(fù)雜場(chǎng)景,從快速啟用到調(diào)試驗(yàn)證,再到常見問題的解決,涵蓋了定時(shí)任務(wù)開發(fā)的全過程,感興趣的朋友一起看看吧
    2025-03-03
  • Java如何獲取主機(jī)的基本信息詳解

    Java如何獲取主機(jī)的基本信息詳解

    最近遇到一個(gè)工作需求,上網(wǎng)查了一下怎樣在Java中獲取本機(jī)的ip和主機(jī)名,所以下面這篇文章主要給大家介紹了關(guān)于Java如何獲取主機(jī)的基本信息,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12
  • springboot項(xiàng)目編寫發(fā)送異常日志到企微工具包的操作方法

    springboot項(xiàng)目編寫發(fā)送異常日志到企微工具包的操作方法

    本文介紹了Springboot項(xiàng)目如何編寫發(fā)送異常日志到企業(yè)微信的工具包,內(nèi)容包括創(chuàng)建基礎(chǔ)Bean、配置類、pom依賴等步驟,并展示了如何通過nacos進(jìn)行配置,這為開發(fā)者提供了一種有效的日志管理方案,方便快速定位和處理項(xiàng)目中的異常問題,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • Java通過反射查看類的信息示例

    Java通過反射查看類的信息示例

    這篇文章主要介紹了Java通過反射查看類的信息,結(jié)合實(shí)例形式詳細(xì)分析了java基于反射獲取類信息的相關(guān)原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07

最新評(píng)論

安化县| 甘德县| 西和县| 平湖市| 鲁山县| 通海县| 塔城市| 油尖旺区| 新巴尔虎左旗| 清丰县| 莆田市| 长宁区| 清水河县| 芒康县| 东阿县| 克东县| 马公市| 灵台县| 子洲县| 辰溪县| 甘孜| 商丘市| 兴化市| 宾川县| 东乌珠穆沁旗| 寿光市| 肃北| 喜德县| 泽州县| 从化市| 广平县| 江山市| 景宁| 讷河市| 邹城市| 大城县| 缙云县| 梧州市| 孟连| 吴江市| 英德市|