JAVA內存管理和JVM運行機制、垃圾回收、內存調優

1、JAVA內存管理java

java是跨平臺語言,java預編譯.class文件放置JVM虛擬機中運行;編程

Java的內存結構,也就是運行時的數據區域緩存

                   運行時數據區併發

方法區:常量池、變量等存儲地方;(持久區)jvm

堆:實例對象存儲地方;GC重點關照位置;(新生代和老年代)編程語言

程序計數器:記錄程序下一步指令;工具

Java方法棧:方法程序運行地方;Java棧老是與線程關聯在一塊兒的,每當建立一個線程,JVM就會爲該線程建立對應的Java棧;性能

本地方法棧:java方法與本地相關聯spa

Java內存模型(即Java Memory Model,簡稱JMM)自己是一種抽象的概念,並不真實存在;每一個線程建立時JVM都會爲其建立一個工做內存(有些地方稱爲棧空間),用於存儲線程私有的數據,而Java內存模型中規定全部變量都存儲在主內存,主內存是共享內存區域,全部線程均可以訪問,但線程對變量的操做(讀取賦值等)必須在工做內存中進行,首先要將變量從主內存拷貝的本身的工做內存空間,而後對變量進行操做,操做完成後再將變量寫回主內存,不能直接操做主內存中的變量;JMM與Java內存區域的劃分是不一樣的概念層次,Java內存模型是圍繞着併發編程中原子性、可見性、有序性這三個特徵來創建的;操作系統

 

JVM運行機制:JVM轉入環境和配置(java.exe-->jvm.cfg)、裝載JVM(經過LoadJavaVM來裝載)、啓動JVM得到本地調用接口、運行java程序;

1.類加載器:

包括啓動類加載器(核心庫)(jre/lib內全部class)、擴展類(擴展庫)(jre/lib/ext/內全部class)、應用程序類(加載classpath下的全部class)

流程(五個階段):加載、鏈接(驗證、準備、解析)、初始化

2.執行引擎:執行classes中指令。任何JVM specification實現(JDK)的核心都是執行引擎。

3.運行時數據區又叫JVM內存;

內存區域包括堆和棧,棧後進先出,有大小限制,堆能夠存放很大內容;java虛擬機中的堆主要存放對象實例,棧存放引用和基本類型;

存放大內容:對象實例 大小有限制,後進先出,存放:引用和基本類型
速度快
全部線程共享,生命週期和JVM同步

每一個線程有本身獨立的棧,線程銷燬的時候被銷燬

如:Object o=new Object();   Object存放在堆中,o存放在棧中;

程序計數器:標記程序運行到的位置,JVM至關於一臺抽象計算機;

JVM工做原理和特色主要是指操做系統裝入JVM是經過jdk中Java.exe來完成,經過下面4步來完成JVM環境.

1.建立JVM裝載環境和配置

2.裝載JVM.dll

3.初始化JVM.dll並掛界到JNIENV(JNI調用接口)實例

4.調用JNIEnv實例裝載並處理class類。

2、垃圾回收(GC,全稱:garbage colletion)

JAVA虛擬機的GC有自動的垃圾回收機制,不須要開發人員主動調用;因爲是自動,優先級又低,因此並不能保證必定執行垃圾回收;

(1)何時回收?

當內存不足或者當前空閒的時候進行垃圾回收,GC線程優先級都不過高;

(2)判斷什麼是垃圾?

通常來講,對於沒有引用指向的對象,被標識爲垃圾,沒有對象指向它,也就沒法對它進行操做,這個對象對於咱們來講就是沒用的;

(3)垃圾回收方法

a.finalize方法工做原理:一旦垃圾回收器準備好釋放對象存儲空間時,會調用一次而且僅調一次finalize方法(經過調用System.gc()實現),而且當下一次垃圾回收開始時才真正回收對象佔用內存;因此重現finalize方法便可在回收時從新創建引用關聯,而達到不被回收效果;

b.標記(mark):標記出哪些不是垃圾,回收的時候把沒有標記到的認爲是垃圾,進行回收;

c.引用計數法:針對每一個對象實例的引用進行計算,將計算爲0的做爲垃圾進行回收,弊端,循環引用將沒法進行回收;

d.年輕代:新生成對象放在年輕代中,收集生命週期短的;老年代:被屢次垃圾回收的對象;持久代:用於存放靜態文件,如java類或方法等;

(1)對新生代的對象的收集稱爲minor GC;

(2)對舊生代的對象的收集稱爲Full GC;

(3)程序中主動調用System.gc()強制執行的GC爲Full GC。

不一樣的對象引用類型, GC會採用不一樣的方法進行回收,JVM對象的引用分爲了四種類型:

(1)強引用:默認狀況下,對象採用的均爲強引用(這個對象的實例沒有其餘對象引用,GC時纔會被回收)

(2)軟引用:軟引用是Java中提供的一種比較適合於緩存場景的應用(只有在內存不夠用的狀況下才會被GC)

(3)弱引用:在GC時必定會被GC回收

(4)虛引用:因爲虛引用只是用來得知對象是否被GC

3、內存調優

主要針對年輕代、年老代、持久代;堆棧等大小進行設置;

內存溢出分2類:

1. 年老代溢出,表現爲:java.lang.OutOfMemoryError:Javaheapspace

2. 持久代溢出,表現爲:java.lang.OutOfMemoryError:PermGenspace

參數說明

  • -Xmx3550m:設置JVM最大堆內存爲3550M。
  • -Xms3550m:設置JVM初始堆內存爲3550M。此值能夠設置與-Xmx相同,以免每次垃圾回收完成後JVM從新分配內存。
  • -Xss128k:設置每一個線程的棧大小。JDK5.0之後每一個線程棧大小爲1M,以前每一個線程棧大小爲256K。應當根據應用的線程所需內存大小進行調整。在相同物理內存下,減少這個值能生成更多的線程。可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右。須要注意的是:當這個值被設置的較大(例如>2MB)時將會在很大程度上下降系統的性能。
  • -Xmn2g:設置年輕代大小爲2G。在整個堆內存大小肯定的狀況下,增大年輕代將會減少年老代,反之亦然。此值關係到JVM垃圾回收,對系統性能影響較大,官方推薦配置爲整個堆大小的3/8。
  • -XX:NewSize=1024m:設置年輕代初始值爲1024M。
  • -XX:MaxNewSize=1024m:設置年輕代最大值爲1024M。
  • -XX:PermSize=256m:設置持久代初始值爲256M。
  • -XX:MaxPermSize=256m:設置持久代最大值爲256M。
  • -XX:NewRatio=4:設置年輕代(包括1個Eden和2個Survivor區)與年老代的比值。表示年輕代比年老代爲1:4。
  • -XX:SurvivorRatio=4:設置年輕代中Eden區與Survivor區的比值。表示2個Survivor區(JVM堆內存年輕代中默認有2個大小相等的Survivor區)與1個Eden區的比值爲2:4,即1個Survivor區佔整個年輕代大小的1/6。
  • -XX:MaxTenuringThreshold=7:表示一個對象若是在Survivor區(救助空間)移動了7次尚未被垃圾回收就進入年老代。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代,對於須要大量常駐內存的應用,這樣作能夠提升效率。若是將此值設置爲一個較大值,則年輕代對象會在Survivor區進行屢次複製,這樣能夠增長對象在年輕代存活時間,增長對象在年輕代被垃圾回收的機率,減小Full GC的頻率,這樣作能夠在某種程度上提升服務穩定性。

 

4、內存溢出常見的哪幾種?

三種:

一、新生代和老年代溢出:java.lang.OutOfMemoryError:java heep space;當98%時間用於垃圾回收時,且可用的Heap size 不足2%的時候將拋出此異常信息;

解決方法:手動設置JVM Heap(堆)的大小

二、持久代溢出:java.lang.OutOfMemoryError: PermGen space

解決方法: 經過-XX:PermSize和-XX:MaxPermSize設置永久代大小便可。

三、棧溢出:java.lang.StackOverFlowError:Thread stack space

棧區遠遠小於堆區,棧區須要的內存大小1-2m左右;出現棧溢出,即說明單線程運行程序須要的內存太大;

解決方法:1:修改程序。2:經過 -Xss: 來設置每一個線程的Stack大小便可。

5、java自帶分析工具:

jstack(查看線程)、jmap(查看內存)和jstat(性能分析)命令

問題彙總:

1.什麼是java虛擬機?爲何java平臺被稱爲「平臺無關的編程語言」?

答:java虛擬機是一個能夠執行java字節碼的虛擬機進程;java虛擬機支持任意平臺上運行,java程序編寫好後,只要編譯成java字節碼(class文件)就能夠在java虛擬機上運行,java程序無須根據不一樣環境進行編譯;

2.java代碼是怎樣運行的?

答:java虛擬機運行時數據區分五個區域:方法區、堆、java方法棧、本地方法棧和pc寄存器;java程序被編譯成java字節碼後,首先要存放在方法區;方能在java虛擬機中運行;爲了提升運行效率,標準JDK中的HotSpot虛擬機採用的是一種混合執行的策略。

3.java虛擬機是如何加載java類的?

答:java虛擬機將字節流轉換java類三個步驟:裝載、連接(驗證、準備、解析)、初始化;

4.jvm的永久代會進行垃圾回收嗎?

答:jvm的永久代(方法區)、常量池和變量的存儲區,垃圾回收不會發生在永久代,當永久代存儲滿了或超過了臨界值後纔會觸發徹底垃圾回收(full gc);jdk8後永久代已經去除,改存元空間區(本地內存區)中;最大可利用空間就變成了整個系統內存的可用空間.

5.對象何時能夠被垃圾回收?

答:當對象再也不被任何對象引用時,能夠被回收

6.System.gc()和Rumtime.gc()會作什麼事情?

答:都是提示JVM要進行垃圾回收,可是具體何時進行垃圾回收要看JVM虛擬機;

7.堆的形狀是一顆()。

  • 徹底二叉樹

  • 滿二叉樹

  • 二叉排序樹

  • 平衡二叉樹

答案:A

相關文章
相關標籤/搜索