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
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