探讨深刻Java虚拟机以内存优化

     上一篇咱们讲述了Java虚拟机的体系结构和内存模型,那么咱们就不得不说到内存泄露。你们都知道,Java是从C++的基础上发展而来的,而C++程序的很大的一个问题就是内存泄露难以解决,尽管Java的JVM有一套本身的垃圾回收机制来回收内存,在大多数的状况下并不须要java程序开发人员操太多的心,但也是存在泄露问题的,只是比C++小一点。好比说,程序中存在被引用但无用的对象:程序引用了该对象,但后续不会或者不能再使用它,那么它占用的内存空间就浪费了。java

 

     咱们先来看看GC是如何工做的:监控每个对象的运行状态,包括对象的申请、引用、被引用、赋值等,当该对象再也不被引用时,释放对象(GC本文的重点,不作过多阐述)。不少Java程序员过度依赖GC,但问题的关键是不管JVM的垃圾回收机制作得多好,内存总归是有限的资源,所以就算GC会为咱们完成了大部分的垃圾回收,但适当地注意编码过程当中的内存优化仍是很必要的。这样能够有效的减小GC次数,同时提高内存利用率,最大限度地提升程序的效率。程序员

 

     整体而言,Java虚拟机的内存优化应从两方面着手:Java虚拟机和Java应用程序。前者指根据应用程序的设计经过虚拟机参数控制虚拟机逻辑内存分区的大小以使虚拟机的内存与程序对内存的需求相得益彰;后者指优化程序算法,下降GC负担,提升GC回收成功率。算法

 

经过参数优化虚拟机内存的参数以下所示:
-Xms 
初始Heap大小
app

-Xmx 
java heap最大值 
ide

-Xmn 
young generation的heap大小
优化

-Xss 
每一个线程的Stack大小
ui

上面是三个比较经常使用的参数,还有一些:
-XX:MinHeapFreeRatio=40
Minimum percentage of heap free after GC to avoid expansion.
 
-XX:MaxHeapFreeRatio=70
Maximum percentage of heap free after GC to avoid shrinking.
 
-XX:NewRatio=2
Ratio of new/old generation sizes. [Sparc -client:8; x86 -server:8; x86 -client:12.]-client:8 (1.3.1+), x86:12]
 
-XX:NewSize=2.125m
Default size of new generation (in bytes) [5.0 and newer: 64 bit VMs are scaled 30% larger; x86:1m; x86, 5.0 and older: 640k]
 
-XX:MaxNewSize=
Maximum size of new generation (in bytes). Since 1.4, MaxNewSize is computed as a function of NewRatio.
 
-XX:SurvivorRatio=25
Ratio of eden/survivor space size [Solaris amd64: 6; Sparc in 1.3.1: 25; other Solaris platforms in 5.0 and earlier: 32]
 
-XX:PermSize=
Initial size of permanent generation
 
-XX:MaxPermSize=64m
Size of the Permanent Generation.  [5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.]
编码


下面所说经过优化程序算法来提升内存利用率,并下降内存风险,彻底是经验之谈,仅供参考,谢谢!spa


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

看一段代码:

public List<PageData> parse(HtmlPage page) {

        List<PageData> list = null;        

        try {

            List valueList = page.getByXPath(config.getContentXpath());

            if (valueList == null || valueList.isEmpty()) {

                return list;

            }

            //须要时才建立对象,节省内存,提升效率

            list = new ArrayList<PageData>();

            PageData pageData = new PageData();

            StringBuilder value = new StringBuilder();

            for (int i = 0; i < valueList.size(); i++) {

                HtmlElement content = (HtmlElement) valueList.get(i);

                DomNodeList<HtmlElement> imgs = content.getElementsByTagName("img");

                if (imgs != null && !imgs.isEmpty()) {

                    for (HtmlElement img : imgs) {

                        try {

                            HtmlImage p_w_picpath = (HtmlImage) img;

                            String path = p_w_picpath.getSrcAttribute();

                            String format = path.substring(path.lastIndexOf("."), path.length());

                            String localPath = "D:/p_w_picpaths/" + MD5Helper.md5(path).replace("\\", ",").replace("/", ",") + format;

                            File localFile = new File(localPath);

                            if (!localFile.exists()) {

                                localFile.createNewFile();

                                p_w_picpath.saveAs(localFile);

                            }

                            p_w_picpath.setAttribute("src", "file:///" + localPath);

                            localFile = null;

                            p_w_picpath = null;

                            img = null;

                        } catch (Exception e) {

                        }

                    }

                    //这个对象之后不会在使用了,清除对其的引用,等同于提早告知GC,该对象能够回收了

                    imgs = null;

                }

                String text = content.asXml();

                value.append(text).append("<br/>");

                valueList=null;

                content = null;

                text = null;

            }

            pageData.setContent(value.toString());

            pageData.setCharset(page.getPageEncoding());           

            list.add(pageData);

            //这里 pageData=null; 是没用的,由于list仍然持有该对象的引用,GC不会回收它

            value=null;

            //这里可不能 list=null; 由于list是方法的返回值,不然你从该方法中获得的返回值永远为空,并且这种错误不易被发现、排除

        } catch (Exception e) {            

        }        

        return list;

}



PS:若有任何问题,请直接在群457036818中提出。

相关文章
相关标签/搜索