Google发布的Android studio 3.0已经出来好久了,虽然在编译效率上大大提高,但是在内存使用效率上还是不如人意,所以我们有必要使用JVM的知识,对Android Studio内存使用进行优化,在这之前,有必要研究一下,与Android studio相关的JVM相关的知识。
本文主要分下3个点:1)JVM 回收算法简介 2)idea系列配置JVM项的介绍
1)JVM 回收算法简介
JVM在内存处理上,历史上有3类算法,1 串行回收 2 并发回行 3 并行回收,
串行
程序们按一个队列,一个一个执行,适合单核CPU执行。
并发
一个并发程序是具备处理多个任务的能力。并发并不需要有多个CPU,单个CPU通过时间片的方式,不同时间片处理不同任务,可以让程序“看起来”是都在执行的。
并行
并行表示在同一个时间点,有多个任务都在进行当中。并行是需要多个CPU才可以完成的。如果说每一个CPU都在运行一个程序,那么4个CPU就可以让4个程序“并行”运算。
Java垃圾回收器
串行处理器
–Serial收集器:
用于新生代,单线程并Stop The World
一般用于单CPU的应用,设置-XX:+UseSerialGC,可以保证较高的吞吐率
–SerialOld收集器:
用于老年代,单线程。
并行收集器
–ParNew收集器
用于新生代,用户响应时间比较短,适用于server。是CMS默认的新生代收集器
–Parallel Scavenge收集器
用于新生代,吞吐量比较高,但是用户响应时间比较长,适用于后台。
–Parallel Old收集器
用于老年代,响应时间较长,吞吐量较大。适用于后台,和Parallel Scavenge配合使用。
并发收集器
–CMS(Concurrent Mark Sweep),可以对老年代进行并行的垃圾回收。值得注意的是,jdk6以前,如果老年代使用了CMS,那么新生代只能使用Serial或ParNew收集器。
–G1(Garbage First),并行和并发,降低Stop The World的时间
2)idea系列配置JVM项的介绍
Android studio属于idea公司系列之一,在idea系列出来前,开发者多数一直是使用Eclipse,Eclipse的特点是内存相对占用较少,所以使用的是串行内存回收算法来处理内存的回收,到了这几年,多核计算机的流行,并发成了程序提高性能的主要突破点,所以idea上使用了并行回收内存算法来处理内存,而并发的后果是,多个程序占用的内存,远远超过了eclipse使用的量。因此,idea公司使用了并发收集器,也就是上文采用的方式之一“ CMS(Concurrent Mark Sweep”,也就是旧生代使用CMS回收,新生代采用ParNew回收。下面列出所有IDEA产品可以加载的JVM项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
-Xms128m //设置JVM初始内存为128m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。 -Xmx3072m //设置JVM最大可用内存为3072m -XX:ReservedCodeCacheSize=240m //保留代码占用的内存容量 -XX:+UseConcMarkSweepGC //对老生代采用并发标记交换算法进行GC -XX:SoftRefLRUPolicyMSPerMB=50 //这可以指定每兆堆空闲空间的 soft reference 保持存活(一旦它不强可达了)的毫秒数,这意味着每兆堆中的空闲空间中的 soft reference 会(在最后一个强引用被回收之后)存活1秒钟, -ea //启用断言 -Dsun.io.useCanonCaches=false //? -Djava.net.preferIPv4Stack=true //在ipv4的机器上想获取到完整的机器名 -XX:+HeapDumpOnOutOfMemoryError //当首次遭遇OOM时导出此时堆中相关信息 -XX:-OmitStackTraceInFastThrow //强制要求JVM始终抛出含堆栈的异常 -XX:+UseCompressedOops //转成32位指针 -server //与-client对应, 这两个参数用于设置虚拟机使用何种运行模式,client模式启动比较快,但运行时性能 和内存 管理效率不如server模式,通常用于客户端应用程序。相反,server模式启动比client慢,但可获得更高的运行性能 -XX:+UseParNewGC //对年轻代采用多线程并行回收,这样收得快(缩短minor收集的时间,如果设置-XX:+UseConcMarkSweepGC,无须设置-XX:+UseParNewGC,是默认的) -XX:+DisableExplicitGC //禁止System.gc():免得程序员误调用gc方法影响性能 -Xverify:none //关闭字节码验证的方法 -XX:CMSInitiatingOccupancyFraction=80//80说明年老代到80%满的时候开始执行对年老代的并发垃圾回收(CMS) -XX:CompileThreshold=100 //来确定计数器的阈值,从而控制编译的条件。但是如果降低了这个值,会导致JVM没有收集到足够的信息就进行了编译,导致编译的代码优化不够(不过影响会比较小) -XX:NewSize=256m//新生代对象生成时占用内存的默认值 -XX:MaxNewSize=768m//新生成对象能占用内存的最大值 -XX:PermSize=96m //设定96兆内存的永久保存区域 -XX:MaxPermSize=96m //设定96兆最大内存的永久保存区域 -XX:NewRatio=3 //新生代内存容量与老生代内存容量的比例 -Xss16m //设置每个线程的堆栈大小为16M -XX:+CMSParallelRemarkEnabled //降低标记停顿 ,为了减少第二次暂停的时间 -XX:ConcGCThreads=4 //选项增加标记线程(marking threads)的数量. -XX:+TieredCompilation //与-server配对 -Djsse.enableSNIExtension=false//让IntelliJ IDEA 13 支持svn1.6 -XX:+AlwaysPreTouch //在调用main函数之前,使用所有可用的内存分页。这个选项可以用来测试长时间运行的系统,所有的内存都已被分配 -XX:+UseCodeCacheFlushing//当代码缓存被填满时让JVM放弃一些编译代码,如果代码缓存不断增长, -XX:InitialHeapSize=750m //等价于-Xms,初始堆内存 -XX:MaxHeapSize=1500m //等价于-Xmx,最大堆内存 -XX:ParallelGCThreads=4//表示JVM在进行并行GC的时候,用于GC的线程数 -XX:MaxTenuringThreshold=1/这个参数用于控制对象能经历多少次Minor GC才晋升到旧生代,默认值是15 -XX:SurvivorRatio=8//参数 -XX:SurvivorRatio 与 -XX:NewRatio 类似,作用于新生代内部区域。-XX:SurvivorRatio 指定伊甸园区(Eden)与幸存区大小比例. 例如, -XX:SurvivorRatio=10 表示伊甸园区(Eden)是 幸存区To 大小的10倍(也是幸存区From的10倍).所以,伊甸园区(Eden)占新生代大小的10/12, 幸存区From和幸存区To 每个占新生代的1/12 .注意,两个幸存区永远是一样大的.. -XX:+UseCodeCacheFlushing //,当代码缓存被填满时让JVM放弃一些编译代码 -XX:+AggressiveOpts // 加快编译 -XX:+CMSClassUnloadingEnabled//? -XX:+CMSIncrementalMode //该标志将开启CMS收集器的增量模式。增量模式经常暂停CMS过程,以便对应用程序线程作出完全的让步 -XX:+CMSIncrementalPacing // 根据应用程序的行为自动调整每次执行的垃圾回收任务的数量 -XX:+CMSParallelRemarkEnabled // 降低标记停顿 -XX:+CMSScavengeBeforeRemark//在执行CMS remark之前进行一次youngGC,这样能有效降低remark的时间 -XX:+UseCMSInitiatingOccupancyOnly//标志来命令JVM不基于运行时收集的数据来启动CMS垃圾收集周期 -XX:-TraceClassUnloading//打印类卸载信息 -XX:CMSInitiatingOccupancyFraction=68//该值代表老年代堆空间的使用率,超过就产生回收 -XX:+UseCMSCompactAtFullCollection //对老年代进行压缩,可能影响性能,但是可以消除碎片 -XX:CMSFullGCsBeforeCompaction=10 //多少次后进行内存压缩 |
注,在站内下载区,已经提供相关文件,需要者可以直接从该区域下载AS的JVM配置文件