小猿做了两年的c++,上个月竟然被调到java项目,于是第一篇随笔就想八一八java的内存优化。

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

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

  其次,很多时候你想做一个功能,写一段代码,不是用时间换空间就是用空间换时间。要根据这个功能到底是看中时间,还是看中空间,常访问到的必然是要放到内存里的,但是是不是可以进行压缩这个也要看对效率是否有影响。

  其他的就不多说,相信各位都有自己的好习惯。

  主要想说说内存优化。

  小猿现在做的项目需要解析大量数据保存起来,所以如何节省内存非常重要,不然导入一个100M的文件,就占用1G的内存,客户简直要疯掉了。

  于是小猿进行第一步,排查内存的占用情况。

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

  用这个软件可以清晰的看到你程序内存、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了,勿念…………………………

java内存优化牛刀小试的更多相关文章

  1. java 内存优化

    计数器pc 2.2 虚拟机栈和程序计数器一样,虚拟机栈也是线程私有的,它的生命周期与线程相同.虚拟机栈描述的是java方法执行的内存模型. 每个方法(不包含native方法)执行的同时都会创建一个栈帧 ...

  2. Java内存优化和性能优化的几点建议

    1.没有必要时请不用使用静态变量 使用Java的开发者都知道,当某个对象被定义为stataic变量所引用,这个对象所占有的内存将不会被回收.有时,开发者会将经常调用的对象或者变量定义为static,以 ...

  3. Java虚拟机内存优化实践

    前面一篇文章介绍了Java虚拟机的体系结构和内存模型,既然提到内存,就不得不说到内存泄露.众所周知,Java是从C++的基础上发展而来的,而C++程序的很大的一个问题就是内存泄露难以解决,尽管Java ...

  4. java虚拟机和内存优化总结

    前一段时间总结了spring和springmvc相关的知识,面试中常问到的除了这些基本的框架之外,还有底层的基础知识,比如与java虚拟机相关的知识点,这一部分也是面试中经常问到的,在面试中高级jav ...

  5. Java代码优化方案 J2ME内存优化

    Java代码优化方案 J2ME内存优化 从几本书上,N个网站上整理的一些JAVA代码优化方案,最近的项目只有1M内存可用,必须很抠门了~J2ME项目更要注意的 避免内存溢出 l 不用的对象释放(置空) ...

  6. Android内存优化5 了解java GC 垃圾回收机制3

    引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Andro ...

  7. Android内存优化3 了解java GC 垃圾回收机制1

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  8. Android内存优化1 了解java内存分配 1

    开篇废话 今天我们一起来学习JVM的内存分配,主要目的是为我们Android内存优化打下基础. 一直在想以什么样的方式来呈现这个知识点才能让我们易于理解,最终决定使用方法为:图解+源代码分析. 欢迎访 ...

  9. JVM性能优化系列-(1) Java内存区域

    1. Java内存区域 1.1 运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.主要包括:程序计数器.虚拟机栈.本地方法栈.Java堆.方法区(运 ...

随机推荐

  1. 开启mysql慢查询

    Linux查看mysql 安装路径一.查看文件安装路径由于软件安装的地方不止一个地方,所有先说查看文件安装的所有路径(地址).这里以mysql为例.比如说我安装了mysql,但是不知道文件都安装在哪些 ...

  2. java PKCS7Padding 加密Cannot find any provider supporting AES/CBC/PKCS7Padding 解决办法

    在java中用aes256进行加密,但是发现java里面不能使用PKCS7Padding,而java中自带的是PKCS5Padding填充,那解决办法是,通过BouncyCastle组件来让java里 ...

  3. Android中Spanner获取选中内容和选中位置,根据位置选择对象

    作为一名菜鸟,关于spanner获取选中的内容文字代码,网上后很多 但是根据给出的位置来自动选择对象,这个代码一直没找到 后来找人问了问,才知道就一句话的事,特意在这里记录下 array.xml  X ...

  4. 20 Web 编程 - 《Python 核心编程》

  5. sqoop sample code

    本文使用的数据库是mysql的sample database employees. download url:https://launchpad.net/test-db/employees-db-1/ ...

  6. [转]Try Cloud Messaging for Android

    本文转自:https://developers.google.com/cloud-messaging/android/start

  7. MongoDB配置多个ConfigDB的问题(笔记)

    由于在部署集群之前没有做好的规划,在集群中只有一个configserver和一个mongos.网上都推荐多个configserver,本人在使用的过程中发现在启动mongos进程时,congfigdb ...

  8. runv kill 流程分析

    1.runv/kill.go Action: func(context *cli.Context) 该函数做的工作很简单,就是通过grpc客户端,发送一个grpc请求而已,如下: c.Signal(n ...

  9. codeforces 577E E. Points on Plane(构造+分块)

    题目链接: E. Points on Plane time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  10. poj2387 Til the Cows Come Home 最短路径dijkstra算法

    Description Bessie is out in the field and wants to get back to the barn to get as much sleep as pos ...