點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達(dá)
結(jié)合幾個面試題來學(xué)習(xí)
1、簡單講一下Java的內(nèi)存模型?
2、Java 的 GC機制
3、Java內(nèi)存管理:常見的變量,在內(nèi)存的不同區(qū)域,GC的回收;
相關(guān)資料
相關(guān)文章:Java虛擬機 平行系列二
1、Java內(nèi)存模型
1.1、JVM整體介紹:
java(javac)--> class文件(JVM把class文件翻譯成機器碼) --> Linux、Windows等平臺(只認(rèn)識機器碼101010)。
JVM可以理解為一個翻譯,把class文件翻譯成機器碼,所以JVM具有跨平臺性。

1.2、運行時數(shù)據(jù)區(qū):

1.3、Java內(nèi)存模型
內(nèi)存模型設(shè)計:由兩個部分的數(shù)據(jù)非常關(guān)鍵,堆內(nèi)存和方法區(qū),因為這兩個區(qū)域的存放的是所有線程共享的數(shù)據(jù),因此數(shù)據(jù)會比較多。而線程私有的數(shù)據(jù)區(qū)如程序計數(shù)器,本地方法棧、虛擬機棧里面的數(shù)據(jù)跟線程的生命周期有關(guān),一旦線程被銷毀,這些數(shù)據(jù)也就被回收了,因此不用過多關(guān)注。

2、垃圾回收算法
2.1、如何判斷某個對象是否是垃圾?
https://www.cnblogs.com/dolphin0520/p/3783345.html
我們先來了解一個最基本的問題:如果確定某個對象是“垃圾”?既然垃圾收集器的任務(wù)是回收垃圾對象所占的空間供新的對象使用,那么垃圾收集器如何確定某個對象是“垃圾”?———即通過什么方法判斷一個對象可以被回收了。
public class Main {
public static void main(String[] args) {
MyObject object1 = new MyObject();
MyObject object2 = new MyObject();
object1.object = object2;
object2.object = object1;
object1 = null;
object2 = null;
}
}
class MyObject{
public Object object = null;
}
最后面兩句將object1和object2賦值為null,也就是說object1和object2指向的對象已經(jīng)不可能再被訪問,但是由于它們互相引用對方,導(dǎo)致它們的引用計數(shù)都不為0,那么垃圾收集器就永遠(yuǎn)不會回收它們。
為了解決這個問題,在Java中采取了 可達(dá)性分析法。該方法的基本思想是通過一系列的“GC Roots”對象作為起點進行搜索,如果在“GC Roots”和一個對象之間沒有可達(dá)路徑,則稱該對象是不可達(dá)的,不過要注意的是被判定為不可達(dá)的對象不一定就會成為可回收對象。被判定為不可達(dá)的對象要成為可回收對象必須至少經(jīng)歷兩次標(biāo)記過程,如果在這兩次標(biāo)記過程中仍然沒有逃脫成為可回收對象的可能性,則基本上就真的成為可回收對象了。
Java垃圾回收-可達(dá)性分析算法
也可以看:深入理解Java虛擬機:JVM高級特性與最佳實踐(第3版) 周志明 3.2章節(jié)
回收算法有3種:
2.2、標(biāo)記-清除
通過可達(dá)性分析的方式來標(biāo)記需要回收的對象。

清除后:

缺點:
堆中所有的對象都會被掃描一遍,從而才能確定需要回收的對象,比較耗時
有空間碎片,空間不連續(xù),導(dǎo)致一些打的對象可能分配不到合適的空間,這樣就還會觸發(fā)GC回收,而GC回收是比較耗時的
2.3、標(biāo)記-復(fù)制

清除后:

優(yōu)點:不會有空間碎片;
缺點:浪費了一半的空間;
2.4、標(biāo)記-整理

整理后:

堆:Old Young(Eden、S0和S1)
哪個算法用在哪個區(qū)域呢?
不同的代用不同的垃圾回收算法
Young區(qū),復(fù)制 ---> 前提條件:每次垃圾回收 存活的對象都比較少 ---> 復(fù)制算法
絕大多數(shù)的對象都被回收掉了 ---> 一般的對象都是朝生夕死的
垃圾回收的過程,GC日志 文章名:Understanding G1 GC Logs https://blogs.oracle.com/poonam/understanding-g1-gc-logs
結(jié)論:Young區(qū)使用復(fù)制算法是沒有問題的。
Old區(qū):一般是存活時間比較長的,意味著很難被回收 --->
當(dāng)需要要回收的對象很少時,使用標(biāo)記整理算法(只標(biāo)記,不清除);
當(dāng)需要回收的對象很多時,使用標(biāo)記清除算法;
總結(jié):
3、面試題
1、簡單講一下Java的內(nèi)存模型?
2、Java 的 GC機制
3、Java內(nèi)存管理:常見的變量,在內(nèi)存的不同區(qū)域,GC的回收;
3.1、簡單講一下Java內(nèi)存模型【垃圾回收相關(guān)】。
JVM的運行時數(shù)據(jù)區(qū)包括線程私有(程序計數(shù)器、本地方法棧、虛擬機棧)和線程共享(堆、方法區(qū))。
而內(nèi)存模型的設(shè)計主要考慮線程共享區(qū)域,因為這兩個區(qū)域存放的是所有線程共享的數(shù)據(jù),因此數(shù)據(jù)會比較多,而線程私有的數(shù)據(jù)跟線程的生命周期有關(guān),一旦線程被銷毀,這些數(shù)據(jù)也就被回收了,因此不用過多關(guān)注。
而線程共享區(qū)域包含有堆和方法區(qū),方法區(qū)也不用關(guān)注,因為方法區(qū)里面的內(nèi)存分配和垃圾回收我們無法控制,那么我們只有一個區(qū)域需要關(guān)注了,那就是堆。
堆可分為老年代和新生代,新生代又分為Eden空間、From Survivor空間、To Survivor空間。(空間比例為8:1:1)。
3.2、簡單講一下新生代和老年代。
https://blog.csdn.net/jisuanjiguoba/article/details/80156781
堆可分為老年代和新生代,新生代又分為Eden空間、From Survivor空間、To Survivor空間。(空間比例為8:1:1)。
1)年輕代(Young Gen):年輕代主要存放新創(chuàng)建的對象,內(nèi)存大小相對會比較小,垃圾回收會比較頻繁。年輕代分成1個Eden Space和2個Suvivor Space(命名為A和B)。當(dāng)對象在堆創(chuàng)建時,將進入年輕代的Eden Space。垃圾回收器進行垃圾回收時,掃描Eden Space和A Suvivor Space,如果對象仍然存活,則復(fù)制到B Suvivor Space,如果B Suvivor Space已經(jīng)滿,則復(fù)制到Old Gen。同時,在掃描Suvivor Space時,如果對象已經(jīng)經(jīng)過了幾次的掃描仍然存活,JVM認(rèn)為其為一個持久化對象,則將其移到Old Gen。掃描完畢后,JVM將Eden Space和A Suvivor Space清空,然后交換A和B的角色(即下次垃圾回收時會掃描Eden Space和B Suvivor Space。這么做主要是為了減少內(nèi)存碎片的產(chǎn)生。
我們可以看到:Young Gen垃圾回收時,采用將存活對象復(fù)制到到空的Suvivor Space的方式來確保盡量不存在內(nèi)存碎片,采用空間換時間的方式來加速內(nèi)存中不再被持有的對象盡快能夠得到回收。
2)年老代(Tenured Gen):年老代主要存放JVM認(rèn)為生命周期比較長的對象(經(jīng)過幾次的Young Gen的垃圾回收后仍然存在),內(nèi)存大小相對會比較大,垃圾回收也相對沒有那么頻繁(譬如可能幾個小時一次)。年老代主要采用壓縮的方式來避免內(nèi)存碎片(將存活對象移動到內(nèi)存片的一邊,也就是內(nèi)存整理)。當(dāng)然,有些垃圾回收器(譬如CMS垃圾回收器)出于效率的原因,可能會不進行壓縮。
3)持久代(Perm Gen):持久代主要存放類定義、字節(jié)碼和常量等很少會變更的信息。
總結(jié):
3.3、GC有多少種垃圾回收的算法,都是什么?
3種,見上。
3.4、我在new一個對象的時候,它是被放在內(nèi)存的那一塊區(qū)域?
堆。
3.5、成員變量和局部變量:在內(nèi)存區(qū)域位置的區(qū)別和回收方面的區(qū)別?
成員變量:放在堆內(nèi)存中,
局部變量:放在 Java Virtual Machine Stacks(Java虛擬機堆棧),
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:
https://blog.csdn.net/songzi1228/article/details/117173102
