JVM是按照运行时数据的存储结构来划分内存结构的,JVM在运行java时,将他们划分成几种不同格式的数据,分别存储在不同的区域,这些数据统一称为运行时数据,运行时数据包括java程序本身的数据信息和JVM运行java需要的额外的数据信息。


JMM要理解

JVM运行时数据区
程序计数器--------线程私有
java虚拟机栈------线程私有
本地方法栈--------线程私有
Jav堆-------------线程公用
方法区------------线程公用

锁机制

JVM内存分配
1:栈内存分配
保存参数、局部变量、中间计算过程和其他数据。退出方法的时候,修改栈顶指针就可以把栈帧中的内容销毁
栈的优点:
存取速度比堆快,仅次于寄存器,栈数据可以共享
栈的缺点:
存在栈中的数据大小、生存期是在编译时就确定的,导致其缺乏灵活性

2:堆内存分配
堆的优点:
动态地分配内存大小,生存期不必事先告诉编译器,他是在运行期动态分配的,垃圾回收器会自动收走不再使用的空间区域
堆的缺点:
运行时动态分配内存,在分配和销毁时要占用时间,因此堆的效率较低

JVM堆结构

JAVA堆结构和垃圾回收

JVM堆配置参数
1:-Xms初识堆大小
   默认物理内存的1/64(<1GB)
2:-Xmx最大堆大小
   默认物理内存的1/4(<1GB),实际中建议不大于4G
3:一般建议设置 -Xms=-Xmx
   好处是避免每次在gc后,调整堆的大小,减少系统内存分配开销
4:整个堆大小=年轻代大小+年老代大小+持久代大小

JVM新生代
1、新生代=1个eden区+2个Survivor区
2、-Xmn年轻代大小(1.4or later)
    -XX:NewSize,-XX:MaxNewSize(设置年轻代大小(for 1.3/1.4))
    默认值大小为整个堆的3/8
3、-XX:NewRatio
    年轻代(包括Eden和两个Suivivor区)与老年代的比值
    Xms=Xmx并且设置了Xmn的情况下,改参数不需要进行设置
4、-XX:SurvivorRatio
    Eden区与 Survivor区的大小比值,设置为8,则两个Survivor区与一个Eden区的比值是2:8,一个Survivor区占整个年轻代的1/10
5、用来存放JVM刚分配的JAVA对象

Java老年代
1、老年代=整个堆-年轻代大小-持久代大小
2、年轻代中经过垃圾回收没有回收掉的对象,被复制到老年代
3、老年代存储对象比年轻代年龄大的多,而且不乏大的对象
4、新建的对象也有可能直接进入老年代
   4.1、大对象,可通过启动参数设置-XX:PretenureSizeThreshold=1024(单位是字节,默认为0)来代表超过多大时就不在新生代分配,而是直接在年老代分配。(一般情况下建议不设置)
   4.2、大的数组对象,且数组中无引用外部对象
5、老年代大小无配置参数

Java持久代
1、持久代=整个堆-年轻代大小-老年代大小
2、-XX:PermSize -XX:MaxPermSize
   设置持久代的大小,一般情况推荐把-XX:PermSize设置成XX:MaxPermSize的值为相同的值,因为永久代大小的调整会导致堆内存需要触发fgc
3、存放Class、Method元信息,其大小与项目的规模、类、方法的数量有关。一般设置为128M就足够,设置原则是预留30%的空间
4、永久代的回收方式
   4.1、常量池中的常量,无用的类信息,常量的回收很简单,没有引用了就可以被回收
   4.2、对于无用的类进行回收,必须保证3点:
       类的所有实例都已经被回收
       加载类的ClassLoader已经被回收
       类对象的Class对象没有被引用(即没有通过反射引用该类的地方)

JVM内存垃圾回收
JVM垃圾收集算法
1、引用计数算法
   每个对象有一个引用技术属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。还有一个问题就是如何解决精确计数。这个已经pass不再使用。
2、根搜索算法
   从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链的时候,则证明此对象是不可用的。不可达对象。
在JAVA语言中GC Roots包括:
虚拟机栈中引用的对象
方法区中类静态属性实体引用的对象
方法区中常量引用的对象
本地方法中JNI引用的对象

JVM垃圾回收算法
1、复制算法(Copy)
    
   复制算法采用从根集合扫描,并将存活对象复制一块新的,没有使用过的空间中,这种算法当空间存活的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间用于就kin型对象的移动
   此算法用于新生代内存回收,从E区回收到S0或者S1
2、标记清除算法(Mark-Sweep)
   
  标记-清除算法采用从根集合进行扫描,对存活的对象标记,标记完毕后,在扫描整个空间中未被标记的对象,进行回收。
  标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法回收不存活的对象,因此会造成内存碎片。
3、标记整理压缩算法(Mark-Compac)
  
  标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针,标记-整理算法是在标记清除算法的基础上,又进行了对象的移动,因此成本高,但是却解决了内存碎片的问题。
名词解释
1、串行回收
   GC单线程内存回收、会暂停所有用户线程
2、并行回收
   收集是指对个GC线程并行工作,但此时用户线程是暂停的,所以,Serial是串行的,Parallel收集器是并行的,而CMS收集器是并发的。
3、并发回收
   是指用户线程与GC线程同时执行(不一定是并行,可能交替,但总体上是在同时执行的),不需要停顿用户线程,(其实在CMS中用户线程还是需要停顿的,只是非常的短,GC线程在另一个CPU上执行)

Serial回收器(串行回收器)
1、是一个单线程的收集器,只能使用一个CPU或一条线程去完成垃圾收集;在进行垃圾收集时,必须暂停所有其他工作线程,直到收集完成。
2、缺点:Stop-The-World
3、优势:简单。对于单CPU的情况,由于没有线程交互开销,反而可以更高效。是Client模式下默认的新生代收集器。

新生代Serial回收器
1、-XX:+UserSerialGC来开启
   Serial New+Serial Old的收集器组合进行内存回收
2、使用复制算法
3、独占式的垃圾回收
   一个线程进行GC,串行,其他工作线程暂停。
老年代Serial回收器
1、-XX:+UserSerialGC来开启
   Serial New+Serial Old的收集器组合进行内存回收
2、使用标记-压缩算法
3、串行的、独占式的垃圾回收器
   因为内存比较大原因,回收比新生代慢

ParNew回收器(并行回收器)

并行回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。但是由于并行回收器使用多线程进行垃圾回收,因此,在并发能力比较强的CPU上,它产生的停顿时间要短于串行回收器,而在单CPU上或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好,由于多线程的压力,他的实际表现很可能比串行回收器差。
新生代ParNew回收器
1、-XX:UserParNewGC开启
   新生代使用并行回收收集器,老年代使用串行收集器
2、-XX:ParallelGCThreads 指定线程数
   默认最好与CPU数量相当,避免过多的线程数影响垃圾收集性能
3、使用复制算法
4、并行的、独占式的垃圾回收器
新生代Parallel Scavenge回收器
1、吞吐量优先回收器
   关注CPU吞吐量,即运行用户代码的时间/总时间,比如:JVM运行100分钟,其中运行用户代码99分钟,垃圾收集1分钟,则吞吐量是99%,这种收集器能最高效的利用CPU,适合运行后台运算。
2、-XX:+UserParallerGC开启
   使用Paraller Scavenge+ Serrial Old收集器组合回收垃圾,这也是在Server模式下的默认值
3、-XX:GCTimeRadio
   来设置用户执行时间占总时间的比例,默认99,即1%的时间用来垃圾回收
4、-XX:MaxGCPausMillis
   设置GC的最大停顿时间
5、使用复制算法
老生代Parallel Old回收器
1、-XX:+UserParallerOldGC开启
   使用Parallel Scavenge +Parallel Old组合收集器进行收集
2、使用标记整理算法
3、并行的、独占式的垃圾回收器。

CMS(并发标记清除)回收器
运行过程分为4个阶段:
    初识标记:只标记GC Roots能直接关联到的对象
    并发标记:进行GC Roots Tracing的过程
    重新标记:修正并发标记期间因用户程序继续运行而导致标记发生改变的那一部分对象的标记
    并发清除:
其中标记和重新标记两个阶段仍然需要Stop-The-World,整个过程中耗时最长的并发标记和并发清除过程中收集器都可以和用户线程一起工作。

CMS(并发标记清除)回收器



GC性能指标
吞吐量    应用花在非GC上的时间百分比
GC负荷    与吞吐量相反,指应用花在GC上的时间百分比
暂停时间  应用花在GC stop-the-world的时间
GC频率
反应速度  从一个对象变成垃圾到这个对象被回收的时间
一个交互式的应用要求暂停时间越少越好,然而,一个非交换性的应用,当然是希望GC符合越低越好。
一个实时系统对暂停时间和GC负荷的要求,都是越低越好。

内存容量配置原则
1、年轻代大小选择
   响应时间优先的应用:尽可能设置大些,直到接近系统的最低响应时间限制(根据实际情况选择)在此种情况下,年轻代收集发生的频率也是最小的,同时减少老年代的对象
   吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度,因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用
   避免设置过小。当新生代设置过小时会导致:
       1、YGC次数更加频繁
       2、可能导致YGC对象直接进入老年代,如果老年代满了,会触发FGC。
老年代大小选择
   响应时间优先的应用:老年代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数,如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间,最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例
   吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是:可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。

























JVM初识、调优的更多相关文章

  1. JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

    摘要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps.jstack.jmap.jhat.jstat.hprof等小巧的工具,本博客希望 ...

  2. JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解(转VIII)

    JVM本身就是一个java进程,一个java程序运行在一个jvm进程中.多个java程序同时运行就会有多个jvm进程.一个jvm进程有多个线程至少有一个gc线程和一个用户线程. JDK本身提供了很多方 ...

  3. JVM参数调优

    JVM参数调优 JVM参数调优是一个很头痛的问题,可能和应用有关系,下面是本人一些调优的实践经验,希望对读者能有帮助,环境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G内存,d ...

  4. Java性能优化权威指南-读书笔记(二)-JVM性能调优-概述

    概述:JVM性能调优没有一个非常固定的设置,比如堆大小设置多少,老年代设置多少.而是要根据实际的应用程序的系统需求,实际的活跃内存等确定.正文: JVM调优工作流程 整个调优过程是不断重复的一个迭代, ...

  5. JVM性能调优

    摘自:http://uule.iteye.com/blog/2114697 JVM垃圾回收与性能调优总结 JVM调优的几种策略 一.JVM内存模型及垃圾收集算法  1.根据Java虚拟机规范,JVM将 ...

  6. JVM 性能调优实战之:一次系统性能瓶颈的寻找过程

    玩过性能优化的朋友都清楚,性能优化的关键并不在于怎么进行优化,而在于怎么找到当前系统的性能瓶颈.性能优化分为好几个层次,比如系统层次.算法层次.代码层次…JVM 的性能优化被认为是底层优化,门槛较高, ...

  7. JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码

    本文是<JVM 性能调优实战之:一次系统性能瓶颈的寻找过程> 的后续篇,该篇介绍了如何使用 JDK 自身提供的工具进行 JVM 调优将 TPS 由 2.5 提升到 20 (提升了 7 倍) ...

  8. (转)JVM参数调优八大技巧

    这里和大家分享一下JVM参数调优的八条经验,JVM参数调优,这是很头痛的问题,设置的不好,JVM不断执行FullGC,导致整个系统变得很慢,网站停滞时间能达10秒以上,相信通过本文的学习你对JVM参数 ...

  9. JVM的GC机制及JVM的调优方法

    内存管理和垃圾回收是JVM非常关键的点,对Java性能的剖析而言,了解内存管理和垃圾回收的基本策略非常重要. 1.在程序运行过程当中,会创建大量的对象,这些对象,大部分是短周期的对象,小部分是长周期的 ...

  10. jvm 性能调优

    [转载]:http://blog.csdn.net/chen77716/article/details/5695893 最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一记录. 一 ...

随机推荐

  1. websocket简单入门

    今天说起及时通信的时候,突然被问到时用推的方式,还是定时接受的方式,由于之前页面都是用传统的ajax处理,可能对ajax的定时获取根深蒂固了,所以一时之间没有相同怎么会出现推的方式呢?当被提及webs ...

  2. 20155234java实验一

    实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 1.没有Linux基础的同学建议先学习Linux基础入门(新版))Vim ...

  3. 20155327 2016-2017-3 《Java程序设计》第4周学习总结

    20155327 2016-2017-3 <Java程序设计>第4周学习总结 教材学习内容总结 一. 理解封装.继承.多态的关系 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方 ...

  4. 20155339 2016-2017-2 《Java程序设计》第1周学习总结

    20155339 2016-2017-2 <Java程序设计>第1周学习总结 教材学习内容总结 第一章 一直以为JAVA应该只是一种语言,研读了书本之后发现原来JAVA也代表了解决问题的平 ...

  5. 成都优步uber司机客户端下载-支持安卓、IOS系统、优步司机端Uberpartner

    国外打车软件优步乘客端大家在手机应用商店里都可以下载到,但是优步司机的App却不好找下载地址:这就跟滴滴打车一样,滴滴的乘客端是滴滴打车,而司机端是滴滴专车,司机版本在应用商店里都找不到,原因不清楚. ...

  6. c++ 结构指针和双向链表

    结构指针 为结构指针动态分配内存 结构中的结构 双向链表 结构指针 struct mytime { //char name[256]; int hour;//时 int min; //分 i ...

  7. 【CF833E】Caramel Clouds

    [CF833E]Caramel Clouds 题面 洛谷 题目大意: 天上有\(n\)朵云,每朵云\(i\)会在时间\([li,ri]\)出现,你有\(C\)个糖果,你可以花费\(c_i\)个糖果让云 ...

  8. 通过java反射机制获取该类的所有属性类型、值

    转自:http://blog.csdn.net/sd4000784/article/details/7448221 方法使用了这俩个包下的 field 和method import Java.lang ...

  9. Python运维三十六式:用Python写一个简单的监控系统

    市面上有很多开源的监控系统:Cacti.Nagios.Zabbix.感觉都不符合我的需求,为什么不自己做一个呢? 用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发 ...

  10. 英特尔® 实感™ 摄像头 (F200) 应用如何实现最佳用户体验

    英特尔开发人员专区原文 由于视频不能直接嵌入, 请点击视频标题观看.谢谢. 英特尔® 实感™ 技术支持我们重新定义如何与计算设备交互,包括允许用户通过手势自然交互. 为了帮助大家了解使用英特尔® 实感 ...