java内存优化牛刀小试

  小猿作了两年的c++,上个月居然被调到java项目,因而第一篇随笔就想八一八java的内存优化。html

  首先优化这种事,确定是应该放到最后去作的,不过在写代码的过程当中养成良好的习惯也是很重要的。在这里先推荐一本书《编写高质量代码:改善Java程序的151个建议.秦小波》。html5

  首先,在写代码的时候,尽可能少用对象,能用基本变量代替的就用基本变量,这点下面会举例。java

  其次,不少时候你想作一个功能,写一段代码,不是用时间换空间就是用空间换时间。要根据这个功能究竟是看中时间,仍是看中空间,常访问到的必然是要放到内存里的,可是是否是能够进行压缩这个也要看对效率是否有影响。c++

  其余的就很少说,相信各位都有本身的好习惯。app

  主要想说说内存优化。工具

  小猿如今作的项目须要解析大量数据保存起来,因此如何节省内存很是重要,否则导入一个100M的文件,就占用1G的内存,客户简直要疯掉了。优化

  因而小猿进行第一步,排查内存的占用状况。ui

  首先先使用的工具是jdk自带的,jconsole.exe。spa

  用这个软件能够清晰的看到你程序内存、CPU、线程的状况。线程

  刚开始小猿发现明明本身程序堆使用内存量没有那么大啊,怎么所有加起来和任务管理器的不一致!再细观察之,程序的eden space占用量很小。原来是没有设置eden space的参数,这个要到启动配置文件去设置:-Xmn,-XX:NewSize,-XX:MaxNewSize,-XX:NewRatio这些项均可以根据本身的须要去设置。

  由于若是没有强制变量直接申请在old gen,变量是先申请在eden gen的,而后通过gc以后,若是这个变量幸存下来,就进入survivor区,而后再通过几回gc,变量就存在old gen区了。

  事实上程序启动稳定以后,可能大部分变量都已经到了old gen区去了,若是你的eden区内存分配过大,总量减去survivor减去eden以后剩下的old区就会不够用了,这个时候虚拟机干什么呢,虚拟机会自动根据你设置的-Xms和-Xmx去扩容,因而你其实虚拟机得到的系统内存里有不少是空闲内存,形成任务管理器里看到的内存比你实际使用的大得多。

  因而小猿第一步调好了启动参数,内存果珍降了一些,但其实这是假象,虚拟机里实际占用的内存仍是没有变。

  小猿想知道更详细的内存使用,这就须要MemoryAnalyzer这个工具了,可是使用这个工具前,得生成程序的dump文件,天哪我居然百度出来的方法有利用增长启动参数+HeapDumpOnOutOfMemoryError而且手动增长异常OutOfMemory来生成dump文件。

  好吧小猿异常出来了,机子down掉了,好心塞。

  终于找到了好的方法,其实jdk自带的jconsole就能够生成的。

  在MBean->com.sun.management->HotSpotDiagnostic->操做->dumpHeap,把p0的值改为你生成dump文件的路径,点dumpHeap就能够。不过dump文件的后缀可不是dump!!!是hprof!!!

  生成以后,用MemoryAnalyzer打开,leak Suspects以后,将会看到一个神奇的饼图。里面显示的就是当前哪些instance占用多少内存,有个details,点之。

  话说打不开MemoryAnalyze的孩纸大家jdk安了么,java环境变量都配好了么。

  看到详细的内存占用信息,有多少个object等等。

  小猿这下终于发现能够优化的地方了。

  以前就对java的String心存怨念,这下怨念更深了,就是以前的那句,能用基本类型就用基本类型。

  小猿发现,有100000个String的object,还有100000个char[]的object。

  好吧,你用String存一个字符串,实际上是用他里边的char存字符串,而后他本身还自带了各类亲戚。

  你存一个“0”,String给你的对象大小但是比1Byte大得多!

  因此你能够调String的toCharArray()方法转成char[]保存。

  这里再八一八何时用String,何时用StringBuffer,何时用char。

  其实定义一个经常使用的常量字符串用String那是极好的。

  好比

  String strTemp = “01”;

  String strTemp2 = “01”;

  这样定义的话,strTemp和strTemp2其实是共用了一个对象,只不过这个对象的引用是2!

  因此这样定义10000000000个也只是占了一个String对象,这是String特有的常量池。

  那为何还要用StringBuffer和StringBuild呢?

  由于StringBuffer和StringBuild的append比String的+要好!

  并且String自己设计的时候就是按常量去设计的,而StringBuffer和StringBuild才是真正可改变的字符串。

  可是若是程序要保存大量的没有规则的字符串,这个时候就建议转成char来存。

  这只是字符串类型,其余的int等也是这样的原则,尽可能用基本变量保存。

  纵观高大上的java,宣称没有内存泄露的java,若是咱们使用不当,是会形成内存浪费的。

  虽然退出程序的那一刻内存都会被正确的释放掉,可是咱们有时候更关心运行中的内存使用状况。

  只要一个变量的引用计数不为0,gc就没法回收他,也许你这个object暂时没用了,却把他加到一个到程序结束才能被释放的arraylist里去,那这块内存在运行中就被浪费掉了。

  java是不存在内存泄露,可是释放的时机也很重要,一个对象对咱们来讲其实没用了,却被不当心把这个对象的钥匙借给了一个生命周期比他长的对象,对咱们来讲就是内存泄露。

  能够好好的看看MemoryAnalyze,分析下如今存在的对象,是否是真的都有用,若是有无用的,必定是被哪里引用了。

  小猿终于完成了第一篇java的随笔。java速成一个月以后,下个月就要转战html5了,勿念…………………………

相关文章
相关标签/搜索