java-jvm调优(一)

来源:互联网 发布:有哪些经典算法 编辑:程序博客网 时间:2024/06/11 19:07

很久没写博客了,工作了忙起来也没啥时间,最近在面试,也在看一部分jvm相关的东西,毕竟面试都会有人问到这些,作为菜鸟就要多学点了解下。

博客都是个人观点有错误地方望指出。jvm 是由堆,栈,本地方法栈,方法区组成。


堆(存放new出来的对象):分为:新生代,旧生代,持久带。从字面意思理解,刚创建的对象肯定是放在新生代的,旧生代应该是放一些存活着的对象,持久带肯定就是放一些类、方法的信息,还有一些常量。

新生代(年轻代):分为 eden space 和 survivor space 两个区域,新生成的对象都是由新生代在控制放在eden space区, 当eden space 区内存不够时,就会移动一些在里面一直存在的对象到 survivor space区。新生代可以用 -Xmn(-Xms控制初始化堆大小,-Xmx 控制堆的最大值,后续会详细说明)控制,也可以使用-XX:eden pace / survivor space 的比例控制。survivor space还由 from space 和 to space两个组成。


旧生代(老年代):用于存放经过gc多次回收仍然存在的对象。


持久带:是hotspot jvm 利用旧生代实现的方法区,有些jvm没有旧生代则采用其他方式实现方法区, 不等同于方法区,可以用通过-XX:PermSize -Xms:MaxPermSize来控制初始值和最大值


-Xmx: 最大堆内存 如:-Xmx1024m

-Xms: 初始化堆内存 如:-Xms128m

-XX:MaxNewSize:最大新生代内存

-XX:NewSize:初始化新生代内存,NewSize通常情况为 Xmx的1/3或1/4,新生代=eden + 2 * survivor的大小,可用空间为 eden + 1 * survivor 大小

-XX:PermMaxSize :最大持久代内存

-XX:PermSize:初始化持久代内存

-XX:+PrintGCDetails:打印 gc 信息

-XX:NewRatio:新生代和旧生代的比例,如 -XX:NewRatio=3,则新生代占堆内存的1/4,旧生代占堆内存的3/4

-XX:SurvivorRatio 新生代Eden 与 Survivor的比值,默认值为8,表示Eden占新生代的8/10,Survivor占新生代的1/10( 有两个Survivor)



栈:

每个线程执行每个方法的时候都会在栈中申请一栈帧,每个栈帧包括局部变量区和操作数栈,用来存放方法调用过程中的临时变量、参数和中间结果。

-xss:设置每个线程的堆栈大小,jdk1.5以后,每个线程堆栈大小为1m,正常情况都是够用的。


本地方法栈:

用于存放支持 native 方法的执行,存储了每个native方法调用的状态


方法区

存放了要加载的类信息,静态变量,final类型的常量,属性和方法信息, jvm用持久代 来存放方法区,可通过 -XX:PermSize 和 -XX:MaxPermSize 控制初始值和最大值




垃圾回收按照回收策略分


引用计数

 比较老的回收算法,一个对象有一个引用增加一个计数,删除一个引用则减少一个计数,回收时,只用收集计数为0的对象,缺点:无法处理循环引用的问题。


标记-清除

分为两个阶段,第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除,缺点:需要暂停整个应用,产生内存碎片。


复制

把内存空间划为两个相等的区域,每次只使用其中一个区域,垃圾回收时,遍历当前使用区域,把政治使用中的对象复制到另外一个区域中,算法每次只处理正在被使用中的对象,复制成本较小,同事复制过去以后还能进行相应的内存整理,不会出现碎片问题,缺点:需要占用两倍的内存空间


标记-整理

结合了标记-清除和复制两个算法的优点,分两个阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且存活对象压缩到堆的其中一块,按顺序排放,避免了标记-清除的碎片问题,避免了 复制算法的空间问题。


jvm分别对新生代和旧生代采用不同的垃圾回收机制

新生代的gc


新生代存活时间较短,因此机遇复制算法来进行回收,复制算法就是扫描存活对象,并复制到一块新的完全未使用的空间中,对于新生代,就是在 eden 和 from space 或 to space 之间 复制,新生代采用空间指针的方式来控制gc触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够久出发gc,当连续分配对象时,对象会逐渐从eden 到survivor,最后到旧生代


在执行机制上 jvm提供了串行gc(serial gc),并行回收gc(parallel scavenge), 并行gc(parnew)


串行gc

在整个扫描和复制过程采用单线程方式进行,适用于单cpu,新生代空间较小及对暂停时间要求不是非常高的应用上,是client级别默认的gc方式, 可以通过 -XX:+UseSerialGC来强制制定


并行回收gc

在整个扫描和复制过程中采用多线程的方式进行,适用于多cpu,对暂停时间要求较短的应用上,是server级别默认采用的gc方式,可用 -XX:+UseParallelGC来强制指定,

用-XX:+UseParallelGC来强制制定,用-XX:ParallelGCThreads=4来指定线程数


并行gc

与旧生代的并发gc配合使用


旧生代的gc




指定方式

新生代GC方式

旧生代GC方式

-XX:+UseSerialGC

串行GC

串行GC

-XX:+UseParallelGC

并行回收GC

并行GC

-XX:+UseConeMarkSweepGC

并行GC

并发GC

-XX:+UseParNewGC

并行GC

串行GC

-XX:+UseParallelOldGC

并行回收GC

并行GC

-XX:+ UseConeMarkSweepGC

-XX:+UseParNewGC

串行GC

并发GC

不支持的组合

1、-XX:+UseParNewGC -XX:+UseParallelOldGC

2、-XX:+UseParNewGC -XX:+UseSerialGC










0 0
原创粉丝点击