`

JVM总结

    博客分类:
  • java
jvm 
阅读更多

1.JVM内存模型

1.本地方法栈(Native)   调用c部分
2.程序计数器  (程序代码行数)  JVM支持多个线程同时运行,每个线程都有自己的程序计数器。倘若当前执行的是 JVM 的方法,则该寄存器中保存当前执行指令的地址;倘若执行的是native 方法,则PC寄存器中为空。
3.栈 stack :每个线程有一个私有的栈,随着线程的创建而创建。栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用)、操作数栈、方法出口等信息。栈的大小可以固定也可以动态扩展。当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误
4.堆  heap(存实际对象) 堆内存是 JVM 所有线程共享的部分,在虚拟机启动的时候就已经创建。所有的对象和数组都在堆上进行分配。这部分空间可通过 GC 进行回收。当申请不到空间时会抛出 OutOfMemoryError
5方法区  :主要用于存储类的信息、常量池、方法数据、方法代码等。方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。 关于方法区内存溢出的问题会在下文中详细探讨

2.ClassLoader双亲委派机制 可以保护jvm自己的安全

   双亲委派机制 : 一层一层的让父类去加载,如果顶层的加载器不能加载,然后再向下类推
 // BootStrap (最顶层) 01 java.lang.String rt.jar   /jdk/jre/lib/ 下面的jar
 // ExtClassLoader 02     /jdk/jre/lib/ext/下面的jar
  // AppClassLoader 03   //AppClassLoader
     // 双亲委派机制 可以保护java的核心类不会被自己定义的类所替代
<wiz_code_mirror>
 
 
 
 
 
1
// -XX:+TraceClassLoading
2
public static void main(String[] args) {
3
        Object o = new Object(); // jdk 自带的
4
        Demo01 demo01 = new Demo01();  // 实例化一个自己定义的对象
5
        // null 在这里并不代表没有,只是Java触及不到!Bootstrap
6
        System.out.println(o.getClass().getClassLoader()); // null
7
        System.out.println(demo01.getClass().getClassLoader()); // AppClassLoader
8
        System.out.println(demo01.getClass().getClassLoader().getParent()); // ExtClassLoader
9
        System.out.println(demo01.getClass().getClassLoader().getParent().getParent()); // null
10
    }
 
 
<wiz_code_mirror>
 
 
 
 
 
1
 // 思考:为什么我们刚才自己定义的 java.lang.String 没有生效?
2
 //Bootstrap 优先加载 没找到main方法  双亲委派机制 一层层加载
3
public class String {
4
    public static void main(String[] args) {
5
        System.out.println("hello");
6
    }
7
}
 
 
 
<wiz_code_mirror>
 
 
 
 
 
1
public class Demo01 {
2
    private static int m=0;
3
    public static void main(String[] args) {
4
        System.out.println(Parent.str);//没加会输出static init1 str如果加了final不会输出staticinit  没加final会先输出static init
5
        System.out.println(Parent2.str);
6
        Parent.kk();
7
    }
8
    static class Parent{
9
        public final static String str="hello";//会优先放常量池
10
        static  {
11
            System.out.println("static init1");
12
        }
13

14
        public static void kk() {
15
            m++;
16
            System.out.println(m);
17
            kk();
18
        }
19
    }
20
    static class Parent2{
21
        public static final String str=UUID.randomUUID().toString();//会输出静态代码块内容
22
        static  {
23
            System.out.println("static init2");
24
        }
25
    }
26
}
 
 

3.JDK1.8之后和1.7区别

JDK1.7之前 
永久代:用于存储一些虚拟机加载类信息,常量,字符串、静态变量等等。。。。这些东西都会放到永久代中; 
永久代大小空间是有限的:如果满了 OutOfMemoryError:PermGen 
JDK1.8之后 
彻底将永久代移除 HotSpot jvm ,Java Heap 中或者 Metaspcace(Native Heap)元空间; 
元空间就是方法区在 HotSpot jvm 的实现; 
方法区重要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。。。。。。 
元空间和永久代,都是对JVM规范中方法区的实现。 
元空间和永久代最大的区别:==元空间并不在Java虚拟机中,使用的是本地内存!== 
-XX:MetasapceSize10m 
 

4.方法区渊源

Method Area 方法区 是 Java虚拟机规范中定义的运行是数据区域之一,和堆(heap)一样可以在线程之间共享!栈不能共享

天上飞的理念都会有落地的实现!

JDK1.7之前

永久代:用于存储一些虚拟机加载类信息,常量,字符串、静态变量等等。。。。这些东西都会放到永久代中;

永久代大小空间是有限的:如果满了 OutOfMemoryError:PermGen

JDK1.8之后

彻底将永久代移除 HotSpot jvm ,Java Heap 中或者 Metaspcace(Native Heap)元空间;

元空间就是方法区在 HotSpot jvm 的实现;

方法区重要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。。。。。。

元空间和永久代,都是对JVM规范中方法区的实现。

元空间和永久代最大的区别:==元空间并不在Java虚拟机中,使用的是本地内存!==

-XX:MetasapceSize10m

5.堆内存和GC过程

Java7之前: 
Heap 堆,一个JVM实例中只存在一个堆,堆的内存大小是可以调节的。 
可以存的内容:类、方法、常量、保存了类型引用的真实信息; 
分为三个部分: 
新生区:Young (Eden-s0-s1)  Eden-s0-s1默认8:1:1
养老区:Old Tenure   大对象(-XX:PretenureSizeThreadshold=1024)直接进入老年代,在新生代里面长期存活的对象进入老年代。老年代对应的是major gc。
新生区和养老区默认1:2
永久区:Perm 
堆内存在==逻辑上==分为三个部分:新生、养老、永久(JDK1.8以后,叫元空间) 
物理上只有 新生、养老;元空间在本地内存中,不在JVM中! 
GC 垃圾回收主要是在 新生区和养老区,又分为 普通的GC 和 Full GC,如果堆满了,就会爆出 OutOfMemory; 
新生区 
新生区 就是一个类诞生、成长、消亡的地方! 
新生区细分: Eden、s(from to),所有的类Eden被 new 出来的,慢慢的当 Eden 满了,程序还需要创建对象的时候,就会触发一次轻量级GC;清理完一次垃圾之后,会将活下来的对象,会放入幸存者区(),....... 清理了 20次之后,出现了一些极其顽强的对象,有些对象突破了15次的垃圾回收!这时候就会将这个对象送入养老区!运行了几个月之后,养老区满了,就会触发一次 Full GC;假设项目1年后,整个空间彻彻底底的满了,突然有一天系统 OOM,排除OOM问题,或者重启; 
Sun HotSpot 虚拟机中,内存管理(分代管理机制:不同的区域使用不同的算法!) 
Eden from to 
99% 的对象在 Eden 都是临时对象; 
养老区 
15次都幸存下来的对象进入养老区,养老区满了之后,触发 Full GC 
默认是15次,可以修改! 
永久区(Perm) 
放一些 JDK 自身携带的 Class、Interface的元数据; 
几乎不会被垃圾回收的; 
OutOfMemoryError:PermGen 在项目启动的时候永久代不够用了?加载大量的第三方包! 
JDK1.6之前: 有永久代、常量池在方法区; 
JDK1.7:有永久代、但是开始尝试去永久代,常量池在堆中; 
JDK1.8 之后:永久代没有了,取而代之的是元空间;常量池在元空间中; 
闲聊:方法区和堆一样,是共享的区域,是JVM 规范中的一个逻辑的部分,但是记住它的别名 非堆 
元空间:它是本地内存! 

6.堆内存调优和常用参数(初识)

1.8之后permSize和MaxPermSize被-XX:MetaspaceSize和-XX:MaxMetaspaceSize取代
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
 -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集
 

-XX:+PrintGCDetails:输出详细的GC处理日志

-XX:+PrintGCTimeStamps:输出GC的时间戳信息

-XX:+PrintGCDateStamps:输出GC的时间戳信息(以日期的形式)

-XX:+PrintHeapAtGC:在GC进行处理的前后打印堆内存信息

-Xloggc:(SavePath):设置日志信息保存文件

Minor GC ,Full GC 触发条件

Minor GC触发条件:当Eden区满时,触发Minor GC。

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法去空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

Java堆:所有线程共享。虚拟机启动时创建。存放对象实力和数组。所占内存最大。分为新生代(Young区),老年代(Old区)。新生代分Eden区,Servior区。Servior区又分为From space区和To Space区。Eden区和Servior区的内存比为8:1。 当扩展内存大于可用内存,抛OOM。

 

GC流程  ,对象如何晋升到老年代

对象优先在新生代区中分配,若没有足够空间,Minor GC; 大对象(需要大量连续内存空间)直接进入老年态;长期存活的对象进入老年态。如果对象在新生代出生并经过第一次MGC后仍然存活,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。

 

  1. 【对象优先在Eden中分配,当Eden中没有足够的空间分配时会促发一次Minor GC。每次Minor GC结束后,Eden区会清空,因为它会把Eden中还依然存活的对象放到Survivor中,当Survivor中放不下时,则由分派担保进入老年代中。
  2. 大对象直接进入老年代中。-XX:+PretenuerSizeThreshold 控制”大对象的“的大小。即当创建的对象大于这个临界值时,则该对象直接进入老年代。
  3. 长期存活的对象将进入老年代。虚拟机对每个对象定义了一个对象年龄(Age)计数器。当年龄增加到一定的临界值时,就会晋升到老年代中,该临界值由参数:-XX:MaxTenuringThreshold来设置。如果对象在Eden出生并在第一次发生Minor GC时仍然存活,并且能够被Survivor中所容纳的话,则该对象会被移动到Survivor中,并且设Age=1;以后每经历一次Minor GC,该对象还存活的话会被移动到另一个Survivor区中,并且Age=Age+1。
  4. 动态对象年龄判定:如上所示,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升到老年代,如果在Survivor区中相同年龄(设年龄为age)的对象的所有大小之和超过Survivor空间的一半,年龄大于或等于该年龄(age)的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。】
老年代的垃圾回收称作Full GC。老年代所占用的内存大小为-Xmx对应的值减去-Xmn对应的值。
<wiz_code_mirror>
 
 
 
 
 
1
/**
2
 * 默认情况:
3
 * maxMemory : 1808.0MB (虚拟机试图使用的最大的内存量  一般是物理内存的 1/4)
4
 * totalMemory : 123.0MB (虚拟机试图默认的内存总量 一般是物理内存的 1/64)
5
 */
6
// 我们可以自定堆内存的总量
7
// -XX:+PrintGCDetails; // 输出详细的垃圾回收信息
8
// -Xmx: 最大分配内存; 1/4
9
// -Xms: 初始分配的内存大小; 1/64
10

11
// -Xmx1024m -Xms1024m -XX:+PrintGCDetails
12
public class Demo01 {
13
    public static void main(String[] args) {
14
        // 获取堆内存的初始大小和最大大小
15
        long maxMemory = Runtime.getRuntime().maxMemory();
16
        long totalMemory = Runtime.getRuntime().totalMemory();
17

18
        System.out.println("maxMemory="+maxMemory+"(字节)、"+(maxMemory/1024/(double)1024)+"MB");
19
        System.out.println("totalMemory="+totalMemory+"(字节)、"+(totalMemory/1024/(double)1024)+"MB");
20

21
    }
22
}
 
 
 
<wiz_code_mirror>
 
 
 
 
 
1
/*
2
 * -Xmx8m -Xms8m -XX:+PrintGCDetails
3
 *
4
 * 分析GC日志:
5
 *
6
 *  [Times: user=0.00 sys=0.00, real=0.00 secs]
7
 * 1、GC 类型  GC:普通的GC,Full GC :重GC
8
 * 2、1536K 执行 GC之前的大小
9
 * 3、504K  执行 GC之后的大小
10
 * 4、(2048K) young 的total大小
11
 * 5、0.0012643 secs 清理的时间
12
 * 6、user 总计GC所占用CPU的时间   sys OS调用等待的时间   real 应用暂停的时间
13
 *
14
 * GC :串行执行 STW(Stop The World)  并行执行   G1
15
*/
16

17
public class Demo02 {
18
    public static void main(String[] args) {
19
        System.gc(); // 手动唤醒GC(),等待cpu的调用
20
        String str = "ilovecoding";
21
        while (true){
22
            str += str
23
                    + new Random().nextInt(999999999)
24
                    + new Random().nextInt(999999999);
25
        }
26
        // 出现问题:java.lang.OutOfMemoryError: Java heap space
27
    }
28
}
 
 

GCDump分析内存泄露分析

安装JProfile
运行时加上参数:-XX:+HeapDumpOnOutOfMemoryError   生成的文件在项目根目录下/同级
分享到:
评论

相关推荐

    jvm总结.rtf

    jvm总结.rtf

    JVM调优总结(java)

    FYI. JVM调优总结 JVM调优总结 JVM调优总结

    JVM知识点总结的思维导图

    JVM总结

    JVM调优总结

    1.1 JVM调优总结-序3 1.2 JVM调优总结(一)-- 一些概念 4 1.3 JVM调优总结(二)-一些概念 7 1.4 JVM调优总结(三)-基本垃圾回收算法 9 1.5 JVM调优总结(四)-垃圾回收面临的问题 12 1.6 JVM调优总结(五)-分代...

    个人对JVM总结图.png

    个人对JVM的总结图。包括JVM的五部分(Program Counter Register、JVM Stack、Native Method Stack、heap、method area)。欢迎各位网友指正错误,互相学习讨论

    jvm总结整理.pptx

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

    精简版JVM总结.pdf

    JVM 内存区域 线程私有 程序计数器 当前线程所执行的字节码的行号指示器 对于 Java 方法,记录正在执行的虚拟机字节码指令的地址;对于 native 方法,记录值为空 (Undefined) 唯一一个Java 虚拟机规范中没有规定...

    JVM总结.docx

    资源回答:HotSpot的垃圾收集器最常用有哪些?平时开发遇到oom?怎么分析oom?出现OOM问题多方面的原因有哪些?属于高频面试题

    JVM调优总结 JVM调优总结

    JVM调优总结 JVM调优总结 JVM调优总结

    JVM调优总结.pdf

    这回添加的东西主要集中在基础的一些问题上,还有一些这两年思考的问题。这些问题可能平时我们不会刻 意去想,但是真正看清楚了,却发现还是大有裨益的:)希望对大家都有帮助~

    JVM思维导图

    JVM总结 JVM JVM思维导图

    JVM性能调优总结.docx

    个人JVM性能调优经验总结

    JVM调优总结PDF,带原理图

    JVM调优总结PDF,带原理图,延时如何进行分代垃圾回收

    jvm干货总结图

    jvm干货总结图

    JVM调优总结 Xms -Xmx -Xmn -Xss

    JVM调优总结 -Xms -Xmx -Xmn -Xss JVM调优总结 -Xms -Xmx -Xmn -Xss

    jvm自己学习总结

    jvm自己学习总结,对JVM的工作原理进行记录学习笔记

    JVM调优总结 -Xms -Xmx -Xmn -Xss

    JVM调优总结 -Xms -Xmx -Xmn -Xss

    JVM规范--高手总结

    JVM规范--高手总结 Java相关 1 1.1Java定义 1 1.2Java的开发流程 1 1.3Java运行的原理 2 1.4半编译半解释 3 1.5平台无关性 4 JVM内存模型 4 2.1 JVM规范 5 2.2 Sun JVM 8 2.3 SUN JVM内存管理(优化) 10 2.4 SUN JVM...

    JVM调优总结.doc

    JVM调优总结

    JVM入门总结 .pdf

    JVM基础总结

Global site tag (gtag.js) - Google Analytics