`
love~ruby+rails
  • 浏览: 849592 次
  • 性别: Icon_minigender_1
  • 来自: lanzhou
社区版块
存档分类
最新评论

Java优化编程--内存管理

阅读更多

众所周知,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.避免显式申请数组空间,不得不显式申请时,尽量准确估计其合理值。

分享到:
评论
14 楼 galaxystar 2009-09-24  
obj=null这种优化,只要开启逃逸分析 -XX:+DoEscapeAnalysis 就能得到大幅改善。
13 楼 ZangXT 2009-09-24  
实在想不明白的就去看反汇编代码吧。
javap -verbose 类名
可以看到栈大小

直接比较引用变量在循环内外两种情况的反编译代码也很容易。
12 楼 youngJiang 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();
}
如果是这样好像在整个循环期间应该只有一个引用。指向不同的堆空间。

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

差别是有,但是很小,差别就是创建一个引用和一万一个引用之间的差别吧,但是在循环体内创建的话,一个循环过后该引用就已经失效了,或许在你循环的过程中垃圾回收站已经回收了,如果你循环的次数够多,应该是在循环体内创建的先内存溢出的。
11 楼 realcbb 2009-09-24  
我用"java.lang.Object"的程序测试了一下,两种情况下有差异,但比较小。
又在循环体内每当循环次数为100000的整数倍时,打印内存情况,发现在循环体内声明比在循环体外声明内存占用大 8 byte,每次对应的打印都是这样。
这样看起来,两种情况的确差异很小。
不知测试方法有没有问题,请大家发表看法。
10 楼 wubo19842008 2009-09-24  
<div class="quote_title">java.lang.Object 写道</div>
<div class="quote_div">
<pre name="code" class="java">/*
* 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&lt;Person&gt; list = new ArrayList&lt;Person&gt;();
        long free1 = Runtime.getRuntime().freeMemory();
//        Person p = null;
        for (int i = 0; i &lt; 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;
    }
}
</pre>
<p> 自己测一下,不要以讹传讹.</p>
<p> 在循环体内声明和在循环体外声明是一样的,执行速度并没有差别。</p>
<p> 内存使用就一模一样了。</p>
</div>
<p>对,你可用jprofiler 看一下heap区,看看这个对象的count,声明在循环的里面和外面在循环没有结束是都是不会被gc的。</p>
9 楼 jncz 2009-09-24  
你们到底 运行没有这个程序,明明内存上是有差别的吗
结果:
time:297ms!
memory:389280bytes
8 楼 ZangXT 2009-09-24  
看SUN gc group的建议或许靠谱些:
http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2906.pdf
7 楼 ZangXT 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();
}
如果是这样好像在整个循环期间应该只有一个引用。指向不同的堆空间。

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

两种情况栈的大小是完全一样的,而且栈是在方法执行之前先分配的。
不知道传说中的性能差异从何而来。
6 楼 java.lang.Object 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?
5 楼 ningmenglovesoft 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();
}
如果是这样好像在整个循环期间应该只有一个引用。指向不同的堆空间。

我想这还是有性能的差异吧。
4 楼 love~ruby+rails 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?
3 楼 java.lang.Object 2009-09-23  
你可以执行看看,内存上一个字节的区别都没有
2 楼 vvggsky 2009-09-23  
内存使用上肯定有区别的

主要是 创建Person p 上
1 楼 java.lang.Object 2009-09-23  
<pre name="code" class="java">/*
* 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&lt;Person&gt; list = new ArrayList&lt;Person&gt;();
        long free1 = Runtime.getRuntime().freeMemory();
//        Person p = null;
        for (int i = 0; i &lt; 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;
    }
}
</pre>
<p> 自己测一下,不要以讹传讹.</p>
<p> 在循环体内声明和在循环体外声明是一样的,执行速度并没有差别。</p>
<p> 内存使用就一模一样了。</p>

相关推荐

    java优化编程 java优化编程 java优化编程

    Java优化编程是提升Java应用程序性能的关键技术,涵盖了多个方面的知识,包括代码优化、内存管理、垃圾回收、并发处理以及JVM参数调优等。以下是对这些主题的详细讲解: 1. **代码优化**:编写高效的Java代码是优化...

    java-sizeof-0.0.4:一个查看java对象占用内存大小

    在Java中,理解和管理内存是优化程序性能的关键因素之一。本文将深入探讨Java中的对象内存占用,以及如何使用"java-sizeof-0.0.4"工具来查看Java对象在内存中的大小。 在Java中,内存主要分为堆内存(Heap)和栈...

    Java实时编程-Eric J.Bruno-中文版.pdf

    接着,他详细讲述了Java RTS与标准Java平台的区别,强调了其在并发控制、内存管理、线程调度等方面的优化。 关于并发控制,Java RTS提供了一种名为“锁定时钟”的机制,它允许开发者精确地控制线程间的同步,确保...

    java-1.8.0-openjdk.linux.x86_64

    此外,它还提供了Lambda表达式、函数式接口、Stream API、Optional类等Java 8的新特性,这些特性极大地提升了代码的简洁性和可读性,使得编程更加高效。 对于Linux x86_64架构,这个版本的OpenJDK优化了64位系统上...

    java-8-openjdk-amd64

    使用OpenJDK 8 AMD64版,开发者可以享受到Java 8的新特性和64位平台的优势,如更大的内存分配、更高的并发性能等。同时,由于OpenJDK的开源性质,开发者可以自由查看源码,理解和定制Java运行时环境,这对于学习Java...

    eclipse-java-2022-09-R-win32-x86-64.zip

    该版本特别针对Windows x86_64平台进行了优化,这意味着它能够充分利用64位系统的资源,提供更快的性能和更高的内存管理能力。对于处理大型项目或需要大量内存的Java应用开发来说,64位版本的Eclipse是理想的选择。 ...

    java优化编程ppt讲义,附代码

    **Java优化编程PPT讲义概述** 这是一份专门针对Java优化编程的内部培训资料,旨在帮助中级及以上水平的开发者提升代码性能,实现更高效的应用程序。这份讲义结合了理论与实践,深入探讨了Java语言在实际开发中的...

    java-1.8.0-openjdk-1.8.0.222-2.zip winx64

    5. **IntelliJ IDEA**: 作为一款流行的Java IDE,IDEA提供强大的代码编辑、调试、测试和项目管理等功能。在与OpenJDK集成时,调试功能的优化使得开发者能够更有效地追踪和解决问题,提高开发效率。 6. **安装与配置...

    java优化编程(林胜利版)

    对java编程的优化作了比较详尽的讲解,包括内存怎么优化,程序的优化,ejb、jms的优化

    JAVA优化编程

    《JAVA优化编程》一书深入探讨了JAVA编程中的性能优化技术,旨在帮助开发者提升应用程序的运行效率和系统资源利用率。在JAVA开发过程中,优化是必不可少的一环,它能确保程序在面对大规模数据处理、高并发场景时仍能...

    Java语言编程规范--华为技术有限公司

    - 考虑内存管理,避免内存泄漏,合理使用对象池。 - 优化IO操作,减少磁盘I/O和网络I/O。 这些规范旨在提升代码的规范性、可读性和可维护性,有助于团队之间的协作,以及软件项目的长期稳定发展。通过阅读和遵循...

    butte-java-note-编程文档

    了解JVM的工作原理,包括类加载机制、内存管理(堆、栈、方法区等)、垃圾收集机制以及性能优化策略,对于提高Java程序的效率至关重要。 2. **Java基础**:Java语言的基础知识包括语法特性、面向对象编程(OOP)...

    【程序员面试准备3】-面向对象-C++基础-数据结构-JAVA-内存管理-指针

    【程序员面试准备】系列主要涵盖了六个关键领域,包括面向对象编程、C++基础知识、数据结构、Java语言、内存管理和指针。这些知识点是任何IT专业人员,尤其是面试时需要掌握的核心概念。 首先,面向对象编程(OOP)...

    JAVA优化编程_程序设计

    "JAVA优化编程_程序设计"的主题着重于如何提高Java应用程序的性能,降低资源消耗,提升用户体验。这涉及到一系列的专业知识和技术,包括但不限于内存管理、并发处理、代码优化策略以及垃圾回收机制等。 1. **内存...

    Java动画编程优化技术探讨.pdf

    然而,在进行Java动画编程时,开发者会面临一系列技术挑战,如动画性能问题、内存管理难题和设备兼容性问题等。通过本文档,我们将深入探讨Java动画编程过程中遇到的常见问题以及提出相应的优化措施。 在Java动画...

    JAVA优化编程详解

    在《JAVA优化编程详解》这本书中,作者深入探讨了如何将Java编程技能提升到一个全新的层次,特别是聚焦于性能优化这一关键领域。Java优化不仅仅是关于提高代码运行速度,更是关于资源的有效利用,确保应用程序在复杂...

    JAVA优化编程.zip

    在Java优化编程中,我们关注的是如何提升程序的性能、减少资源消耗以及提高代码的可维护性。这是一项至关重要的任务,特别是在处理大数据、高并发或者长时间运行的服务时。以下是一些关键的知识点: 1. **JVM优化**...

    JAVA优化编程[1

    JAVA优化编程[1] JAVA 虚拟机 算法改进 内存管理

    Java面试突击-V3.0_Java面试文档_java面试_面试_

    5. **内存管理与垃圾回收**:Java的自动内存管理是其一大特色,了解JVM内存模型(堆、栈、方法区等)和垃圾回收机制(GC)对优化程序性能至关重要。 6. **IO流与NIO**:Java的IO流系统用于处理输入输出,NIO(New ...

Global site tag (gtag.js) - Google Analytics