欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解讀Jvm的內(nèi)存結(jié)構(gòu)與GC及jvm參數(shù)調(diào)優(yōu)

 更新時(shí)間:2023年05月05日 10:05:35   作者:兮家小二  
這篇文章主要介紹了解讀Jvm的內(nèi)存結(jié)構(gòu)與GC及jvm參數(shù)調(diào)優(yōu)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、JVM 內(nèi)存結(jié)構(gòu)

1、對(duì)象主要存放在堆內(nèi)存中;方法和屬性主要存放在棧內(nèi)存中。

2、棧是運(yùn)行時(shí)單位,用來解決程序運(yùn)行時(shí)的問題,堆是存儲(chǔ)單位,解決數(shù)據(jù)存儲(chǔ)的問題。

3、堆伴隨著JVM的啟動(dòng)而創(chuàng)建。 

結(jié)構(gòu)圖

1、類加載子系統(tǒng)

負(fù)責(zé)從文件系統(tǒng)或者網(wǎng)絡(luò)加載Class信息,加載的信息存放在一塊稱之方法區(qū)的內(nèi)存空間。 

2、方法區(qū)(method)

存放類、常量、常量池信息、包括字符串字面量和數(shù)字常量等, 只要是 static 關(guān)鍵字修飾的都在方法區(qū)。

方法區(qū)的數(shù)據(jù)是所有線程共享的。 

3、堆(heap)

幾乎所有的對(duì)象實(shí)例都存放到Java堆中,堆空間是所有線程共享,比如new 出來的對(duì)象。

在堆中的分配的內(nèi)存,由java虛擬機(jī)自動(dòng)垃圾回收器來管理。

其中堆又分為了新生代老年代永久代 (jdk 1.8后取消永久代增加元空間)。

優(yōu)點(diǎn):是可以動(dòng)態(tài)地分配內(nèi)存大小,垃圾收集器會(huì)自動(dòng)收走這些不再使用的數(shù)據(jù)。

缺點(diǎn):由于要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存,存取速度較慢

4、棧(stack)

在多線程環(huán)境下,每個(gè)線程擁有一個(gè)棧和一個(gè)程序計(jì)數(shù)器,是線程私有的資源。

方法和屬性主要存放在棧內(nèi)存中。

java中的所有引用都在棧中,并指向堆。

引用是創(chuàng)建對(duì)象的時(shí)候創(chuàng)建的(new ),第二次創(chuàng)建發(fā)現(xiàn)棧中如果有該對(duì)象的引用就使用原引用,不會(huì)新建

優(yōu)點(diǎn):存取速度比堆要快,僅次于直接位于CPU中的寄存器,

缺點(diǎn):存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性,生存期就是他與對(duì)象的關(guān)聯(lián)的時(shí)間

5、本地方法棧

用于本地方法調(diào)用。Java虛擬機(jī)允許Java直接調(diào)用本地方法(通過使用C語言寫) 

6、pc寄存器(了解即可)

PC(Program Couneter)寄存器也是每個(gè)線程私有的空間,

Java虛擬機(jī)會(huì)為每個(gè)線程創(chuàng)建PC寄存器,在任意時(shí)刻,

一個(gè)Java線程總是在執(zhí)行一個(gè)方法,這個(gè)方法稱為當(dāng)前方法,

如果當(dāng)前方法不是本地方法,PC寄存器總會(huì)執(zhí)行當(dāng)前正在被執(zhí)行的指令,

如果是本地方法,則PC寄存器值為Underfined,

寄存器存放如果當(dāng)前執(zhí)行環(huán)境指針、程序技術(shù)器、操作棧指針、計(jì)算的變量指針等信息。 

7、執(zhí)行引擎

虛擬機(jī)核心的組件就是執(zhí)行引擎,它負(fù)責(zé)執(zhí)行虛擬機(jī)的字節(jié)碼,一般戶先進(jìn)行編譯成機(jī)器碼后執(zhí)行。 

8、垃圾收集器

垃圾收集系統(tǒng)是Java的核心,也是不可少的,Java有一套自己進(jìn)行垃圾清理的機(jī)制,開發(fā)人員無需手工清理

二、堆–> 新生代/新生代/永久代

1、新生代

主要是用來存放新生的對(duì)象。一般占據(jù)堆的1/3空間。

由于頻繁創(chuàng)建對(duì)象,所以新生代會(huì)頻繁觸發(fā)MinorGC進(jìn)行垃圾回收。

新生代又分為 Eden區(qū)、ServivorFrom、ServivorTo三個(gè)區(qū)。

Eden :Java新對(duì)象的出生地(如果新創(chuàng)建的對(duì)象占用內(nèi)存很大,則直接分配到老年代)。當(dāng)Eden區(qū)內(nèi)存不夠的時(shí)候就會(huì)觸發(fā)MinorGC,對(duì)新生代區(qū)進(jìn)行一次垃圾回收

ServivorTo :保留了一次MinorGC過程中的幸存者。

ServivorFrom :上一次GC的幸存者,作為這一次GC的被掃描者。

MinorGC 是采用復(fù)制算法來清理垃圾

2、老年代

主要是用來存放頻繁使用的對(duì)象。一般占據(jù)堆的2/3空間。

老年代的對(duì)象比較穩(wěn)定,所以MajorGC不會(huì)頻繁執(zhí)行。

在進(jìn)行MajorGC前一般都先進(jìn)行了一次MinorGC,使得有新生代的對(duì)象晉身入老年代,導(dǎo)致空間不夠用時(shí)才觸發(fā)。

當(dāng)無法找到足夠大的連續(xù)空間分配給新創(chuàng)建的較大對(duì)象時(shí)也會(huì)提前觸發(fā)一次MajorGC進(jìn)行垃圾回收騰出空間。

MajorGC 是采用標(biāo)記清除算法來清理垃圾

2.1、永久代(jdk1.7前)

指內(nèi)存的永久保存區(qū)域,主要存放Class和Meta(元數(shù)據(jù))的信息,

Class在被加載的時(shí)候被放入永久區(qū)域. 它和存放實(shí)例的區(qū)域不同

GC不會(huì)在主程序運(yùn)行期對(duì)永久區(qū)域進(jìn)行清理,

永久代的區(qū)域會(huì)隨著加載的Class的增多而脹滿,最終拋出OOM異常。

在Java8中,永久代已經(jīng)被移除,被一個(gè)稱為“元數(shù)據(jù)區(qū)”(元空間)的區(qū)域所取代。

2.2、元空間(jdk1.8后)

元空間的本質(zhì)和永久代類似,都是對(duì)JVM規(guī)范中方法區(qū)的實(shí)現(xiàn)。

不過元空間與永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。

默認(rèn)情況下,元空間的大小僅受本地內(nèi)存限制。

類的元數(shù)據(jù)放入 native memory, 字符串池和類的靜態(tài)變量放入java堆中. 這樣可以加載多少類的元數(shù)據(jù)就不再由MaxPermSize控制, 而由系統(tǒng)的實(shí)際可用空間來控制.

三、垃圾回收算法

垃圾回收機(jī)制采用算法一覽圖

1、引用算法

使用于新生代,新創(chuàng)建的對(duì)象,默認(rèn)引用值為15

當(dāng)引用值為 0時(shí),該對(duì)象被垃圾回收機(jī)制回收

如果有地方引用,可達(dá)狀態(tài),則加1, 如果沒有地方引用,不可達(dá)狀態(tài),則減1

引用說明,new對(duì)象的時(shí)候創(chuàng)建,在棧中,并指向堆中的對(duì)象

2、復(fù)制算法(MinorGC)

使用于新生代ds0,ds1中,引用算法的引用值到達(dá)了一定高度次數(shù),就會(huì)晉升到ds0,ds1中

新的頻繁使用的對(duì)象都會(huì)在一個(gè)區(qū)內(nèi),要么在ds0,要么在ds1,每次只會(huì)有一個(gè)區(qū)會(huì)有數(shù)據(jù)

假如現(xiàn)在數(shù)據(jù)在ds0中,如果ds0有存活的對(duì)象,把存活的對(duì)象賦值到ds1,然后清空ds0,新的頻繁使用對(duì)象也會(huì)晉升在ds1,假如現(xiàn)在數(shù)據(jù)在ds1中,則反之

3、 標(biāo)記清除算法(MajorGC)

標(biāo)記清除算法

首先掃描一次所有老年代,標(biāo)記出存活的對(duì)象,然后回收沒有標(biāo)記的對(duì)象。

- MajorGC的耗時(shí)比較長(zhǎng),因?yàn)橐獟呙柙倩厥铡?/p>

- MajorGC會(huì)產(chǎn)生內(nèi)存碎片,為了減少內(nèi)存損耗,我們一般需要進(jìn)行合并或者標(biāo)記出來方便下次直接分配。----------- 當(dāng)老年代也滿了裝不下的時(shí)候,就會(huì)拋出OOM(Out of Memory)異常。

- 標(biāo)記壓縮法在標(biāo)記清除基礎(chǔ)之上做了優(yōu)化,把存活的對(duì)象壓縮到內(nèi)存一端,而后進(jìn)行垃圾清理。(java中老年代使用的就是標(biāo)記壓縮法)

4、 java 手動(dòng)回收GC

----Java技術(shù)使用finalize()方法在垃圾收集器將對(duì)象從內(nèi)存中清除出去前,做必要的清理工作

----把對(duì)象賦值為null 在 System.gc(); 即可回收,但不保證100%

public class JVMDemo {
	public static void main(String[] args) {
	    // 創(chuàng)建了堆內(nèi)存
		JVMDemo05 jvmDemo05 = new JVMDemo05();
		// 賦值為空后去除該對(duì)象的引用
		//jvmDemo05 = null;
		//手動(dòng)垃圾回收,只有所有線程都無引用的對(duì)象才會(huì)會(huì)GC回收
		System.gc();
	}
   /**
   * obj 方法,垃圾回收前觸發(fā)
   */
	protected void finalize() throws Throwable {
       System.out.println("gc在回收對(duì)象...");
	}
}

四、JVM 參數(shù)調(diào)優(yōu)

堆的常用配置參數(shù)參考

  • -XX:+PrintGC 每次觸發(fā)GC的時(shí)候打印相關(guān)日志
  • -XX:+UseSerialGC 串行回收
  • -XX:+PrintGCDetails 更詳細(xì)的GC日志
  • -Xms 堆初始值
  • -Xmx 堆最大可用值
  • -Xmn 新生代堆最大可用值
  • -XX:SurvivorRatio 用來設(shè)置新生代中eden空間和from/to空間的比例.含以-XX:SurvivorRatio=eden/from=den/to

圖文方式

1、設(shè)置最大堆內(nèi)存

----- 1、堆內(nèi)存默認(rèn)大小4G,我們可以根據(jù)程序大小來指定,默認(rèn)內(nèi)存足夠的情況下不會(huì)觸發(fā)垃圾回收機(jī)制

----- 2、初始的堆大小與最大堆大小設(shè)置為相等,減少垃圾回收次數(shù),如果內(nèi)存一旦達(dá)到初始值,就會(huì)觸發(fā)垃圾回收機(jī)制,頻繁的觸發(fā)垃圾回收機(jī)制影響線程及性能問題

參數(shù):

  • -Xms 堆初始值
  • -Xmx 堆最大可用值
 -Xms512m -Xmx512m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags

2、設(shè)置新生代與老年代優(yōu)化參數(shù)

  • -Xms 堆初始值
  • -Xmx 堆最大可用值
  • -Xmn 新生代大小,一般設(shè)為整個(gè)堆的1/3到1/4左右
  • -XX:SurvivorRatio 設(shè)置新生代中eden區(qū)和from/to空間的比例關(guān)系n/1

參數(shù):

-Xms512m -Xmx512m -Xmn170m -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+UseSerialGC

3、堆內(nèi)存溢出處理

錯(cuò)誤原因

java.lang.OutOfMemoryError Java heap space 堆內(nèi)存溢出

解決辦法

設(shè)置堆內(nèi)存大小,根據(jù)實(shí)際大小設(shè)置

  • -Xms 堆初始值
  • -Xmx 堆最大可用值
  • -XX:+HeapDumpOnOutOfMemoryError 內(nèi)存溢出拋出儲(chǔ)存快照

示例:

-Xms512m –Xmx512m -XX:+HeapDumpOnOutOfMemoryError

4、棧內(nèi)存溢出處理

錯(cuò)誤原因

棧溢出 產(chǎn)生于遞歸調(diào)用,循環(huán)遍歷是不會(huì)的,但是循環(huán)方法里面產(chǎn)生遞歸調(diào)用, 也會(huì)發(fā)生棧溢出。

java.lang.StackOverflowError 棧內(nèi)存溢出

解決辦法

設(shè)置線程最大調(diào)用深度

-Xss5m      設(shè)置最大調(diào)用深度,默認(rèn)為1M大小
 示例:
-Xms512m –Xmx512m -Xss5m -XX:+HeapDumpOnOutOfMemoryError

5、Tomcat內(nèi)存溢出

在catalina.sh 修改JVM堆內(nèi)存大小

JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxNewSize=512m"

五、 JVM 參數(shù)調(diào)優(yōu)二( GC- 垃圾回收器)

1、串行回收(Serial Collector)

------ 單線程執(zhí)行回收操作,回收期間暫停所有應(yīng)用線程的執(zhí)行,client模式下的默認(rèn)回收器,

jvm參數(shù)

-XX:+UseSerialGC      設(shè)置為串行回收

詳細(xì)參數(shù)

-XX:+PrintGCDetails -Xmx512M -Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseSerialGC
-XX:PermSize=32M

2、并行回收(ParallelGC)

------ ParNew (新生代 )并行回收器在串行回收器基礎(chǔ)上做了改進(jìn),他可以使用多個(gè)線程同時(shí)進(jìn)行垃圾回收,對(duì)于計(jì)算能力強(qiáng)的計(jì)算機(jī)而言,可以有效的縮短垃圾回收所需的實(shí)際時(shí)間。

------ ParallelOldGC (老年代) 回收器也是一種多線程的回收器,和新生代的ParallelGC回收器一樣,也是一種關(guān)往吞吐量的回收器,他使用了標(biāo)記壓縮算法進(jìn)行實(shí)現(xiàn)。

jvm參數(shù)

----ParNew設(shè)置(新生代)
XX:+UseParNewGC          設(shè)置為并行回收
XX:ParaleiGCThreads      設(shè)置ParNew回收器工作時(shí)的線程數(shù)量,建議指定為電腦核數(shù)*2
----ParallelOldGC設(shè)置(老年代)
-XX:+UseParallelOldGC     設(shè)置為并行回收
-XX:+ParallelCThread      設(shè)置垃圾收集時(shí)的線程教量, 建議指定為電腦核數(shù)*2

詳細(xì)參數(shù)(UseParNewGC)

-XX:+PrintGCDetails -Xmx512M –Xms512M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:PermSize=32M

詳細(xì)參數(shù)(UseParallelGC)

-XX:+PrintGCDetails -Xmx512M -Xms256M
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:ParallelGCThreads=8
-XX:PermSize=32M

G1回收器了解

G1回收器(Garbage-First)實(shí)在]dk1.7中提出的垃圾回收器,從長(zhǎng)期目標(biāo)來看是為了取代CMS回收器,G1回收器擁有獨(dú)特的垃圾回收策略,G1屬于分代垃圾回收器,區(qū)分新生代和老年代,依然有eden和from/to區(qū),它并不要求整個(gè)eden區(qū)或者新生代、老年代的空間都連續(xù),它使用了分區(qū)算法。

jvm調(diào)優(yōu)總結(jié)

1、初始堆值和最大堆內(nèi)存內(nèi)存越大,吞吐量就越高。

2、最好使用并行收集器,因?yàn)椴⑿惺謾C(jī)器速度比串行吞吐量高,速度快。

3、設(shè)置堆內(nèi)存新生代的比例和老年代的比例最好為1:2或者1:3。

4、減少GC對(duì)老年代的回收。

六、java 代碼中查看大小

public class JvmDemo01 {
	public static void main(String[] args) throws InterruptedException {
		byte[] b1 = new byte[1 * 1024 * 1024];
		System.out.println("分配了1m");
		jvmInfo();		
		Thread.sleep(3000);
		byte[] b2 = new byte[4 * 1024 * 1024];
		System.out.println("分配了4m");
		Thread.sleep(3000);
		jvmInfo();
	}
	static private String toM(long maxMemory) {
		float num = (float) maxMemory / (1024 * 1024);
		DecimalFormat df = new DecimalFormat("0.00");// 格式化小數(shù)
		String s = df.format(num);// 返回的是String類型
		return s;
	}
	static private void jvmInfo() {
		// 最大內(nèi)存
		long maxMemory = Runtime.getRuntime().maxMemory();
		System.out.println("maxMemory:" + maxMemory + ",轉(zhuǎn)換為M:" + toM(maxMemory));
		// 當(dāng)前空閑內(nèi)存
		long freeMemory = Runtime.getRuntime().freeMemory();
		System.out.println("freeMemory:" +freeMemory+",轉(zhuǎn)換為M:"+toM(freeMemory));
		// 已經(jīng)使用內(nèi)存
		long totalMemory = Runtime.getRuntime().totalMemory();
		System.out.println("totalMemory:" +totalMemory+",轉(zhuǎn)換為M"+toM(totalMemory));
	}
}

idea 設(shè)置參數(shù)

進(jìn)入編輯找到對(duì)應(yīng)的啟動(dòng)類,VM哪填寫JVM參數(shù)就好了

eclipse 設(shè)置參數(shù)

設(shè)置

啟動(dòng)jar 項(xiàng)目設(shè)置參數(shù)

java -jar -Xms20m -Xmx20m xxxxx.jar

其他:壓力測(cè)試工具 JMeter,可測(cè)試接口吞吐量(每秒的并發(fā)量)

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解MyBatis的SqlSession獲取流程

    詳解MyBatis的SqlSession獲取流程

    SqlSession的獲取是通過SqlSessionFactory的openSession() 方法,那么具體的獲取流程是什么,所以本文就給大家詳細(xì)講解一下MyBatis的SqlSession獲取流程,需要的朋友可以參考下
    2023-07-07
  • SpringBoot靜態(tài)資源與首頁配置實(shí)現(xiàn)原理深入分析

    SpringBoot靜態(tài)資源與首頁配置實(shí)現(xiàn)原理深入分析

    最近在做SpringBoot項(xiàng)目的時(shí)候遇到了“白頁”問題,通過查資料對(duì)SpringBoot訪問靜態(tài)資源做了總結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • Spring中@Autowired和@Resource注解的使用區(qū)別詳解

    Spring中@Autowired和@Resource注解的使用區(qū)別詳解

    這篇文章主要介紹了Spring中@Autowired和@Resource注解的使用區(qū)別詳解,@Autowired默認(rèn)根據(jù)type進(jìn)行注入,找到與指定類型兼容的?Bean?并進(jìn)行注入,如果無法通過type匹配到對(duì)應(yīng)的?Bean?的話,會(huì)根據(jù)name進(jìn)行匹配,如果都匹配不到則拋出異常,需要的朋友可以參考下
    2023-11-11
  • Spring數(shù)據(jù)庫連接池url參數(shù)踩坑及解決

    Spring數(shù)據(jù)庫連接池url參數(shù)踩坑及解決

    這篇文章主要介紹了Spring數(shù)據(jù)庫連接池url參數(shù)踩坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 一文快速掌握Spring?Cloud?Stream

    一文快速掌握Spring?Cloud?Stream

    這篇文章主要介紹了Spring?Cloud?Stream詳解,本篇文章所涉及到的demo練習(xí)使用的cloud?2021.0.3+?springboot2.6.8,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • java字節(jié)字符轉(zhuǎn)換流操作詳解

    java字節(jié)字符轉(zhuǎn)換流操作詳解

    這篇文章主要介紹了java字節(jié)字符轉(zhuǎn)換流操作,結(jié)合實(shí)例形式詳細(xì)分析了Java字符流轉(zhuǎn)換相關(guān)原理、實(shí)現(xiàn)方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-09-09
  • SpringBoot讀取多環(huán)境配置文件的幾種方式

    SpringBoot讀取多環(huán)境配置文件的幾種方式

    這篇文章主要給大家介紹了SpringBoot讀取多環(huán)境配置文件的幾種方式,文章通過代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-10-10
  • Spring Boot Admin(監(jiān)控工具)的使用

    Spring Boot Admin(監(jiān)控工具)的使用

    今天我們將會(huì)講解一個(gè)優(yōu)秀的監(jiān)控工具Spring Boot Admin。 它采用圖形化的界面,讓我們的Spring Boot管理更加簡(jiǎn)單,需要的朋友可以參考下
    2020-02-02
  • JMeter配置元件詳解

    JMeter配置元件詳解

    JMeter提供了豐富的配置元件,常用的包括參數(shù)化配置元件、HTTP請(qǐng)求默認(rèn)值、HTTP信息頭管理器、計(jì)數(shù)器等,本文就詳細(xì)的介紹一下這些元件的使用,感興趣的可以了解一下
    2021-12-12
  • IDEA上實(shí)現(xiàn)JDBC編程的方法步驟

    IDEA上實(shí)現(xiàn)JDBC編程的方法步驟

    本文主要介紹了IDEA上實(shí)現(xiàn)JDBC編程的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06

最新評(píng)論