论坛首页 Java企业应用论坛

Java优化编程--内存管理

浏览 5931 次
该帖已经被评为隐藏帖
作者 正文
   发表时间:2009-09-23  

众所周知,java的JVM有一套自己的垃圾回收机制。因此在许多情况下并不需要java程序开发人员操太多的心。然而也许也因为这样,往往会造成java程序员的过分依赖而致使开发出来的程序得不到很好的优化,或者说性能尚能提高。

    问题的关键在于,不论JVM的垃圾回收机制做得多好,计算机的硬件资源是有限的。内存更是一项紧张资源。因此虽然JVM为我们完成了大部分的垃圾回收。但适当地注意编码过程中的内存管理还是很必要的。这样能让JVM回收得更顺利更高效。最大限度地提高程序的效率。

    mark-1:避免在循环体内创建对象。

    ……

    Object obj = null;//方式一

    for(int i =0; i 91k(1984k),0.0027537 secs]

    ……

    可以看到总共有1984kb的内存被回收,耗时0.0027537秒。

    JVM内存相关的参数

    -XX:NewSize(Set the Newgeneralnation heap size)

    -XX:MaxNewSize(Set the Maximum Newgeneralnation heap size)

    -XX:SurvivorRatio(Set New heap size ratios)

    -Xms(Set minimum heap size)

    -Xmx(Set maximum heap size)

    -Xnoclassgc(取消垃圾回收)

    -Xss(设置栈内存的大小)

    例:java -XX:NewSize = 128m -XX:MaxNewSize = 128m - XX:SurvivorRatio = 8 -Xms 512m -Xmx 512m MyApplication

    mark-8:不同编译方法的类大小

    (1)默认编译方式:javac K.java

    长度=代码+源文件信息+代码行序号表

    (2)调试编译方式:javac -g K.java

    长度=代码+源文件信息+代码行序号表+本地变量表

    (3)代码编译方式:javax -g:none K.java

    长度=代码

    mark-9:经验之谈

    1.尽早释放无用对象的引用(XX = null; )

    2.尽量少使用finalize函数。

    3.注意集合数据类型,如数组,树,图,链表等数据结构,这些数据结构对GC来说回收更复杂。

    4.避免在类的默认构造器中创建大量的,初始化大量的对象。

    5.避免强制系统做垃圾内存回收。

    6.避免显式申请数组空间,不得不显式申请时,尽量准确估计其合理值。

   发表时间:2009-09-23  
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.hadeslee.test5;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Hadeslee
 */
public class Test1 {

    public static void main(String[] args) {
        long from = System.currentTimeMillis();
        List<Person> list = new ArrayList<Person>();
        long free1 = Runtime.getRuntime().freeMemory();
//        Person p = null;
        for (int i = 0; i < 1000000; i++) {
            Person p = new Person("name", i);
            list.add(p);
        }
        System.out.println("time:" + (System.currentTimeMillis() - from) + "ms!");
        System.out.println("memory:" + (free1 - Runtime.getRuntime().freeMemory()) + "bytes");
    }
}

class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 自己测一下,不要以讹传讹.

 在循环体内声明和在循环体外声明是一样的,执行速度并没有差别。

 内存使用就一模一样了。

0 请登录后投票
   发表时间:2009-09-23  
内存使用上肯定有区别的

主要是 创建Person p 上
0 请登录后投票
   发表时间:2009-09-23  
你可以执行看看,内存上一个字节的区别都没有
0 请登录后投票
   发表时间:2009-09-23  
java.lang.Object 写道
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.hadeslee.test5;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Hadeslee
 */
public class Test1 {

    public static void main(String[] args) {
        long from = System.currentTimeMillis();
        List<Person> list = new ArrayList<Person>();
        long free1 = Runtime.getRuntime().freeMemory();
//        Person p = null;
        for (int i = 0; i < 1000000; i++) {
            Person p = new Person("name", i);
            list.add(p);
        }
        System.out.println("time:" + (System.currentTimeMillis() - from) + "ms!");
        System.out.println("memory:" + (free1 - Runtime.getRuntime().freeMemory()) + "bytes");
    }
}

class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 自己测一下,不要以讹传讹.

 在循环体内声明和在循环体外声明是一样的,执行速度并没有差别。

 内存使用就一模一样了。

You called this thing as a test?
I mean your test doesnt do anything, just some "hello world",
right?
0 请登录后投票
   发表时间:2009-09-23  
我不知道我说的对不对,
for(int i = 0 ; i < 10000 ;i++){
   Person person = new Person();


}
如果是这样的话。那么应该每一个次循环都会在栈创建一个引用和在堆中重新开辟一块内存空间,也就是说一万个引用指向一万个堆空间。
Person person = null;
for(int i = 0; i < 10000; i++){
  person = new Person();
}
如果是这样好像在整个循环期间应该只有一个引用。指向不同的堆空间。

我想这还是有性能的差异吧。
0 请登录后投票
   发表时间:2009-09-24  
love~ruby+rails 写道
java.lang.Object 写道
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.hadeslee.test5;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Hadeslee
 */
public class Test1 {

    public static void main(String[] args) {
        long from = System.currentTimeMillis();
        List<Person> list = new ArrayList<Person>();
        long free1 = Runtime.getRuntime().freeMemory();
//        Person p = null;
        for (int i = 0; i < 1000000; i++) {
            Person p = new Person("name", i);
            list.add(p);
        }
        System.out.println("time:" + (System.currentTimeMillis() - from) + "ms!");
        System.out.println("memory:" + (free1 - Runtime.getRuntime().freeMemory()) + "bytes");
    }
}

class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 自己测一下,不要以讹传讹.

 在循环体内声明和在循环体外声明是一样的,执行速度并没有差别。

 内存使用就一模一样了。

You called this thing as a test?
I mean your test doesnt do anything, just some "hello world",
right?

So,what is a test? can you provide a test?
0 请登录后投票
   发表时间:2009-09-24  
ningmenglovesoft 写道
我不知道我说的对不对,
for(int i = 0 ; i < 10000 ;i++){
   Person person = new Person();


}
如果是这样的话。那么应该每一个次循环都会在栈创建一个引用和在堆中重新开辟一块内存空间,也就是说一万个引用指向一万个堆空间。
Person person = null;
for(int i = 0; i < 10000; i++){
  person = new Person();
}
如果是这样好像在整个循环期间应该只有一个引用。指向不同的堆空间。

我想这还是有性能的差异吧。

两种情况栈的大小是完全一样的,而且栈是在方法执行之前先分配的。
不知道传说中的性能差异从何而来。
0 请登录后投票
   发表时间:2009-09-24  
看SUN gc group的建议或许靠谱些:
http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2906.pdf
1 请登录后投票
   发表时间:2009-09-24   最后修改:2009-09-24
你们到底 运行没有这个程序,明明内存上是有差别的吗
结果:
time:297ms!
memory:389280bytes
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics