虛擬機進行new對象指令時是先分辨是否能引用,然后判斷是否加載(類加載),接著就是分配內(nèi)存,如果gc帶有壓縮整理功能,則分配方式為空閑列表(CMS基于Mark-Sweep算法收集器),如果不帶,就是用指針碰撞的方式分配,Serial,ParNew帶Compact的收集器這類的
對象的創(chuàng)建在虛擬機中是如何保證安全的
1:同步(類似于加鎖)2:分配不同的創(chuàng)建區(qū)域(把兩者想分配在不同區(qū)域,自然就不會有沖突的情況)
如何使用對象
1:句柄訪問,在棧中有一個reference,存的是句柄池句柄的地址,句柄則包含了所有對象的數(shù)據(jù)類型和類型數(shù)據(jù)各自的地址,好處:在復制清除中,只需要修改reference的值,就可以,不需要移動太多的數(shù)據(jù)
2:直接指針訪問:reference存的是對象的地址,好處:速度快,減少開銷
各個位置內(nèi)存溢出的原因
堆溢出:不斷創(chuàng)建新對象,并保證gc到達對象之間有可達路徑避免被清除.對象數(shù)量大于最大容量就會oom
解決辦法:確認內(nèi)存中的對象是否必須存在:
虛擬機棧溢出和本地方法棧溢出
1:線程請求的棧深度大于虛擬機所允許的最大深度,拋出StackOverFlowError
2:虛擬機在擴展棧時,沒有足夠的內(nèi)存空間,拋出OutOfMemoryError
解決辦法:減少單個線程的內(nèi)存,減少最大堆和最小的棧容量來換取更多的線程(單個線程的內(nèi)存越大,越有可能出現(xiàn)內(nèi)存溢出的情況,在多線程的情況下,減少單個線程的內(nèi)存大小,可以盡量避免出現(xiàn)棧溢出的錯誤)
方法區(qū)和運行時常量池溢出:
原因:運行時產(chǎn)生大量的類填滿方法區(qū),
常見的:大量jsp或產(chǎn)生jsp文件的應用,jsp第一次運行會編譯成java類,同個類被不同加載器加載,會被視為不同的類CGlib動態(tài)生成的class
本機直接內(nèi)存溢出
沒有申請分配內(nèi)存,卻通過其他方式來獲取實例進行內(nèi)存分配(想要內(nèi)存,卻沒申請)