内存管理 要精打细算
爪哇米工作室 陈跃峰
内存管理,是软件开发的一个重点,在功能不变的情况下,如何更有效的利用内存,减少资源的占用是衡量软件性能的重要指标之一。所以,很多公司在招聘时会侧重内存管理的考查。
招聘题目:下面的代码(Java)是否正确地释放了内存空间?为什么?
Image img[] = new Image[10];
for(int i = 0;i < 10;i++){
img[i] = Image.createImage(“/img/” + i + “.png”);
}
img = null; //释放内存
题目答案:该代码未释放全部内存,正确的释放全部内存的代码应该是:
Image img[] = new Image[10];
for(int i = 0;i < 10;i++){
img[i] = Image.createImage(“/img/” + i + “.png”);
}
//依次释放图片占用的内存
for(int i = 0;i < 10;i++){
img[i] = null;
}
img = null; //释放图片数组的内存
代码中,img=null仅仅释放了图片数组对象占用的内存,而每一个图片对象占用的内存没有被释放,所以如果需要释放全部内存,则要先释放每个图片对象占用的内存,再释放图片数组占用的内存,则这样能达到正确释放内存的目的。
不可忽视内存占用
考官出这样的题目,目的是测试程序员是否有工作经验,是否对于内存管理有足够的认识。在软件开发中,内存管理不当会轻则会导致工作效率低下,重则可能会导致系统崩溃,所以内存管理的设计不能有疏忽。
在手机软件的开发中,因为手机内存不大,对内存管理的要求更加严格,有志于从事手机软件的开发的朋友一定要多加注意,多实践,增加程序执行效率的体验,这样才可以在招聘中脱颖而出。
实际应用
在实际的开发过程中,内存是怎么管理的?是如何提高执行速度和效率的?下面我们通过两组代码来进行说明。代码的功能是节约内存,第一组代码的效果不好。
代码1:
public void paint(Graphics g){
……
g.drawString(“loading…”,100,100,Graphics.TOP | Graphics.LEFT);
……
}
点评:该代码的功能是绘制字符串“loading…”,功能可以实现,但是系统每次绘制都需要生成一个字符串对象,比较浪费内存,而且每次都需要计算锚值,这将降低程序的执行效率。
代码2:
public void run(){
……
while(true){
int n = 10;
……
System.gc();
}
}
点评2:在该代码中,在线程run中的循环内部,每次都生命一个int变量n,这样每次都需要为n分配内存,在循环结束时还每次都调用gc方法,效率低下。
第二组代码可以节约内存。
代码1:
public static final int TOPLEFT = Graphics.TOP | Graphics.LEFT; //避免重复计算
private String loadStr = “loading…”; //只生成一次字符串对象
public void paint(Graphics g){
……
g.drawString(loadStr,100,100, TOPLEFT);
……
}
点评:通过声明TOPLEFT常数,避免重复计算,节约内存并提高程序的执行速度。通过声明loadStr对象,使字符串对象只在内存中生成一次,节约内存使用。
代码2:
public void run(){
……
int n = 10;
Runtime rt = Runtime.getRuntime();
while(true){
……
if(rt. freeMemory() < 102400){ //可用内存小于100K
System.gc();
}
}
}
点评:通过在循环中声明变量n,节约内存的使用。在实际的开发中,很多人认为内存管理就是使用System.gc进行内存清理,其实良好的内存使用习惯才是最主要的,频繁的调用System.gc()甚至会显著降低程序的执行效率,所以正确的使用方法是当可用内存小于一定数值时,才调用gc方法进行内存的清理。