自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

高性能Java代碼之內(nèi)存管理

開發(fā) 后端
Java語言,我想大家都不陌生了,本文主要介紹java程序語言在代碼的內(nèi)存管理方面用法,讓我們一起來看。

本文通過幾個(gè)方面,來介紹Java代碼的內(nèi)存管理。

有的代碼,GC根本就回收不了,直接系統(tǒng)掛掉。GC是一段程序,不是智能,他只回收他認(rèn)為的垃圾,而不是回收你認(rèn)為的垃圾。

GC垃圾回收:

Grabage Collection相信學(xué)過JAVA的人都知道這個(gè)是什么意思.但是他是如何工作的呢?

首先,JVM在管理內(nèi)存的時(shí)候?qū)τ谧兞康墓芾砜偸欠中聦?duì)象和老對(duì)象。新對(duì)象也就是開發(fā)者new出來的對(duì)象,但是由于生命周期短,那么他占用的內(nèi)存并不是馬上釋放,而是被標(biāo)記為老對(duì)象,這個(gè)時(shí)候該對(duì)象還是要存在一段時(shí)間。然后由JVM決定他是否是垃圾對(duì)象,并進(jìn)行回收。

所以我們可以知道,垃圾內(nèi)存并不是用完了馬上就被釋放,所以就會(huì)產(chǎn)生內(nèi)存釋放不及時(shí)的現(xiàn)象,從而降低了內(nèi)存的使用。而當(dāng)程序浩大的時(shí)候。這種現(xiàn)象更為明顯,并且GC的工作也是需要消耗資源的。所以,也就會(huì)產(chǎn)生內(nèi)存浪費(fèi)。

JVM中的對(duì)象生命周期里談內(nèi)存回收:

對(duì)象的生命周期一般分為7個(gè)階段:創(chuàng)建階段,應(yīng)用階段,不可視階段,不可到達(dá)階段,可收集階段,終結(jié)階段,釋放階段。

創(chuàng)建階段:首先大家看一下,如下兩段代碼:

test1:

 

  1. forint i=0; i<10000; i++)  
  2. Object obj=new Object(); 

 

test2:

 

  1. Object obj=null;  
  2. forint i=0; i<10000; i++)  
  3. obj=new Object(); 

 

這兩段代碼都是相同的功能,但是顯然test2的性能要比test1性能要好,內(nèi)存使用率要高,這是為什么呢?原因很簡單,test1每次執(zhí)行for循環(huán)都要?jiǎng)?chuàng)建一個(gè)Object的臨時(shí)對(duì)象,但是這些臨時(shí)對(duì)象由于JVM的GC不能馬上銷毀,所以他們還要存在很長時(shí)間,而test2則只是在內(nèi)存中保存一份對(duì)象的引用,而不必創(chuàng)建大量新臨時(shí)變量,從而降低了內(nèi)存的使用。

另外不要對(duì)同一個(gè)對(duì)象初始化多次。例如:

 

  1. public class A{  
  2. private Hashtable table = new Hashtable();  
  3. public A(){ table = new Hashtable();  
  4. // 這里應(yīng)該去掉,因?yàn)閠able已經(jīng)被初始化.  
  5. }  

 

這樣就new了兩個(gè)Hashtable,但是卻只使用了一個(gè)。另外一個(gè)則沒有被引用.而被忽略掉.浪費(fèi)了內(nèi)存.并且由于進(jìn)行了兩次new操作.也影響了代碼的執(zhí)行速度。

應(yīng)用階段:即該對(duì)象至少有一個(gè)引用在維護(hù)他.

不可視階段:即超出該變量的作用域。這里有一個(gè)很好的做法,因?yàn)镴VM在GC的時(shí)候并不是馬上進(jìn)行回收,而是要判斷對(duì)象是否被其他引用在維護(hù).所以,這個(gè)時(shí)候如果我們?cè)谑褂猛暌粋€(gè)對(duì)象以后對(duì)其obj=null或者obj.doSomething()操作,將其標(biāo)記為空,可以幫助JVM及時(shí)發(fā)現(xiàn)這個(gè)垃圾對(duì)象.

不可到達(dá)階段:就是在JVM中找不到對(duì)該對(duì)象的直接或者間接的引用。

可收集階段,終結(jié)階段,釋放階段:此為回收器發(fā)現(xiàn)該對(duì)象不可到達(dá),finalize方法已經(jīng)被執(zhí)行,或者對(duì)象空間已被重用的時(shí)候。

JAVA的析構(gòu)方法:

可能不會(huì)有人相信,JAVA有析構(gòu)函數(shù)? 是的,有。因?yàn)镴AVA所有類都繼承至Object類,而finalize就是Object類的一個(gè)方法,這個(gè)方法在JAVA中就是類似于C++析構(gòu)函數(shù).一般來說可以通過重載finalize方法的形式才釋放類中對(duì)象.如:

  1. public class A{  
  2. public Object a;  
  3. public A(){ a = new Object ;}  
  4. protected void finalize() throws java.lang.Throwable{  
  5. a = null// 標(biāo)記為空,釋放對(duì)象  
  6. super.finalize(); // 遞歸調(diào)用超類中的finalize方法.  
  7. }  

當(dāng)然,什么時(shí)候該方法被調(diào)用是由JVM來決定的\

一般來說,我們需要?jiǎng)?chuàng)建一個(gè)destory的方法來顯式的調(diào)用該方法.然后在finalize也對(duì)該方法進(jìn)行調(diào)用,實(shí)現(xiàn)雙保險(xiǎn)的做法.

由于對(duì)象的創(chuàng)建是遞歸式的,也就是先調(diào)用超級(jí)類的構(gòu)造,然后依次向下遞歸調(diào)用構(gòu)造函數(shù),所以應(yīng)該避免在類的構(gòu)造函數(shù)中初始化變量,這樣可以避免不必要的創(chuàng)建對(duì)象造成不必要的內(nèi)存消耗.當(dāng)然這里也就看出來接口的優(yōu)勢(shì).

數(shù)組的創(chuàng)建:

由于數(shù)組需要給定一個(gè)長度,所以在不確定數(shù)據(jù)數(shù)量的時(shí)候經(jīng)常會(huì)創(chuàng)建過大,或過小的數(shù)組的現(xiàn)象.造成不必要的內(nèi)存浪費(fèi),所以可以通過軟引用的方式來告訴JVM及時(shí)回收該內(nèi)存.(軟引用,具體查資料).

例如:

 

  1. Object obj = new char[10000000000000000];  
  2. SoftReference ref = new SoftReference(obj); 

 

共享靜態(tài)存儲(chǔ)空間:

我們都知道靜態(tài)變量在程序運(yùn)行期間其內(nèi)存是共享的,因此有時(shí)候?yàn)榱斯?jié)約內(nèi)存工件,將一些變量聲明為靜態(tài)變量確實(shí)可以起到節(jié)約內(nèi)存空間的作用.但是由于靜態(tài)變量生命周期很長,不易被系統(tǒng)回收,所以使用靜態(tài)變量要合理,不能盲目的使用.以免適得其反。

因此建議在下面情況下使用:

1,變量所包含的對(duì)象體積較大,占用內(nèi)存過多.

2,變量所包含對(duì)象生命周期較長.

3,變量所包含數(shù)據(jù)穩(wěn)定.

4,該類的對(duì)象實(shí)例有對(duì)該變量所包含的對(duì)象的共享需求.(也就是說是否需要作為全局變量).

對(duì)象重用與GC:

有的時(shí)候,如數(shù)據(jù)庫操作對(duì)象,一般情況下我們都需要在各個(gè)不同模塊間使用,所以這樣的對(duì)象需要進(jìn)行重用以提高性能.也有效的避免了反復(fù)創(chuàng)建對(duì)象引起的性能下降.

一般來說對(duì)象池是一個(gè)不錯(cuò)的注意.如下:

 

  1. public abstarct class ObjectPool{  
  2. private Hashtable locked,unlocked;  
  3. private long expirationTime;  
  4. abstract Object create();  
  5. abstract void expire( Object o);  
  6. abstract void validate( Object o);  
  7. synchronized Object getObject(){...};  
  8. synchronized void freeObject(Object o){...};  

 

這樣我們就完成了一個(gè)對(duì)象池,我們可以將通過對(duì)應(yīng)的方法來存取刪除所需對(duì)象.來維護(hù)這快內(nèi)存提高內(nèi)存重用.

當(dāng)然也可以通過調(diào)用System.gc()強(qiáng)制系統(tǒng)進(jìn)行垃圾回收操作.當(dāng)然這樣的代價(jià)是需要消耗一些cpu資源.

不要提前創(chuàng)建對(duì)象:

盡量在需要的時(shí)候創(chuàng)建對(duì)象,重復(fù)的分配,構(gòu)造對(duì)象可能會(huì)因?yàn)槔厥兆鲱~外的工作降低性能.

JVM內(nèi)存參數(shù)調(diào)優(yōu):

強(qiáng)制內(nèi)存回收對(duì)于系統(tǒng)自動(dòng)的內(nèi)存回收機(jī)制會(huì)產(chǎn)生負(fù)面影響,會(huì)加大系統(tǒng)自動(dòng)回收的處理時(shí)間,所以應(yīng)該盡量避免顯式使用System.gc(),

JVM的設(shè)置可以提高系統(tǒng)的性能.例如:

java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms512m -Xmx512m

具體可以查看java幫助文檔.我們主要介紹程序設(shè)計(jì)方面的性能提高.

JAVA程序設(shè)計(jì)中有關(guān)內(nèi)存管理的其他經(jīng)驗(yàn):

根據(jù)JVM內(nèi)存管理的工作原理,可以通過一些技巧和方式讓JVM做GC處理時(shí)更加有效.,從而提高內(nèi)存使用和縮短GC的執(zhí)行時(shí)間.

1,盡早釋放無用對(duì)象的引用.即在不使用對(duì)象的引用后設(shè)置為空,可以加速GC的工作.(當(dāng)然如果是返回值.....)

2,盡量少用finalize函數(shù),此函數(shù)是JAVA給程序員提供的一個(gè)釋放對(duì)象或資源的機(jī)會(huì),但是卻會(huì)加大GC工作量.

3,如果需要使用到圖片,可以使用soft應(yīng)用類型,它可以盡可能將圖片讀入內(nèi)存而不引起OutOfMemory.

4,注意集合數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu),往往數(shù)據(jù)結(jié)構(gòu)越復(fù)雜,GC工作量更大,處理更復(fù)雜.

5,盡量避免在默認(rèn)構(gòu)造器(構(gòu)造函數(shù))中創(chuàng)建,初始化大量的對(duì)象.

6,盡量避免強(qiáng)制系統(tǒng)做垃圾回收.會(huì)增加系統(tǒng)做垃圾回收的最終時(shí)間降低性能.

7,盡量避免顯式申請(qǐng)數(shù)組,如果不得不申請(qǐng)數(shù)組的話,要盡量準(zhǔn)確估算數(shù)組大小.

8,如果在做遠(yuǎn)程方法調(diào)用.要盡量減少傳遞的對(duì)象大小.或者使用瞬間值避免不必要數(shù)據(jù)的傳遞.

9,盡量在合適的情況下使用對(duì)象池來提高系統(tǒng)性能減少內(nèi)存開銷,當(dāng)然,對(duì)象池不能過于龐大,會(huì)適得其反.

【編輯推薦】

  1. 何時(shí)創(chuàng)建Java對(duì)象實(shí)例
  2. Java多線程程序設(shè)計(jì)詳細(xì)解析
  3. Java在Client/Server中應(yīng)用
  4. Java多線程程序設(shè)計(jì)詳細(xì)解析
責(zé)任編輯:于鐵 來源: 比特網(wǎng)
相關(guān)推薦

2011-04-07 09:25:25

內(nèi)存Java

2015-09-16 15:21:23

Android性能優(yōu)化內(nèi)存

2016-12-22 17:21:11

Android性能優(yōu)化內(nèi)存泄漏

2024-03-20 08:00:00

軟件開發(fā)Java編程語言

2023-02-20 15:27:30

開發(fā)JavaScript內(nèi)存管理

2017-03-14 18:48:06

Android性能優(yōu)化內(nèi)存優(yōu)化

2021-10-03 14:37:06

編程語言程序員代碼

2019-12-31 10:33:57

Netty高性能內(nèi)存

2018-01-12 14:37:34

Java代碼實(shí)踐

2011-02-28 08:57:10

SQL Server資內(nèi)存性能調(diào)優(yōu)

2011-02-22 14:47:52

SQL Server資

2022-12-09 08:40:56

高性能內(nèi)存隊(duì)列

2012-12-17 13:51:22

Web前端JavaScriptJS

2014-04-25 09:02:17

LuaLua優(yōu)化Lua代碼

2012-02-13 16:17:31

PHP

2009-06-24 15:00:39

Javascript代

2011-12-28 13:38:00

JavaJVM

2023-09-18 09:10:11

Golang高性能緩存庫

2023-11-01 11:51:08

Linux性能優(yōu)化

2015-12-17 13:19:29

編寫高性能Swift
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)