Fork me on GitHub

Jvm介绍

跨平台

java通过jdk中的javac编译成字节码文件.class,字节码文件可以在任意一个装有jvm的平台运行。

而C和C++虽然可以在其他平台运行,但是调用系统的指令是不一样的,换一个平台就要重新编写代码。不能做到“once write run everwhere”。

JDK、JRE、JVM关系

代码类型

所有的代码只分三种类型:指令、数据、控制

JVM区域类型

JVM中分为两个区域,指令区和数据区。

 其中指令区是线程独享的。(图为逻辑图)

指令区域

程序计数器

用途:指向当前线程(java中线程是最小的执行单位 )正在执行的字节码指令的地址(行号)。

生命周期:与线程相同。为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。(线程私有)

虚拟机栈

用途:描述Java方法执行内存模型,存储当前线程运行方法时所需要的数据、指令、返回地址。在虚拟机栈中每执行一个方法都会创建一个栈帧入栈(Xxx就是虚拟机栈深度(栈帧最大数)),用来存储局部变量表、操作数栈、动态链接、方法出口,方法执行完成时出栈。

生命周期:与线程相同。(线程私有)

局部变量表

第一个是this、然后是形参、然后是方法内部声明的变量(如果是对象动态链接到Heap堆)。

操作数栈

执行指令,解析字节码文件指令(可用javap查看.class字节码指令)。

    public String method1(int i){
        int j =0;
        int sum = i+j;
        Object object = new Object();
        return null;
    }

javap编译

  public java.lang.String method1(int);
    Code:
       0: iconst_0      //初始化变量j的值并压入到操作数栈0位置
       1: istore_2      //操作数栈出栈(j变量),压入局部变量表2位置
       2: iload_1       //局部变量表1位置加载数据到操作数栈中
       3: iload_2       //局部变量表2位置加载数据到操作数栈中
       4: iadd          //进行加操作
       5: istore_3      //将相加的结果存入到局部变量表3位置
       6: new           #3                  // class java/lang/Object
       9: dup           
      10: invokespecial #8                  // Method java/lang/Object."<init>":()V
      13: astore        4
      15: aconst_null   
      16: areturn       //return指令
    LineNumberTable:
      line 20: 0
      line 21: 2
      line 22: 6
      line 23: 15
    LocalVariableTable:   //局部变量表
      Start  Length  Slot  Name   Signature
             0      17     0  this   LDemo;  //第一个变量是this
             0      17     1     i   I       //形参i
             2      15     2     j   I             //局部变量j
             6      11     3   sum   I       //局部变量sum值
            15       2     4 object   Ljava/lang/Object;  //对象Object变量object,动态链接到堆中

初始化一个int变量会先把值存入操作数栈,然后出栈存到局部变量表

第一行int j=0解析指令如下,iconst_0初始化int值压到操作数栈中,istore_2从操作数栈中出栈并压到局部变量表第三个位置。

动态链接

对象变量链接到堆中

方法出口

return指令

本地方法栈

用途:加载本地的方法(如dll文件中的方法),与虚拟机栈类似,给Native方法使用。(线程私有)

生命周期:与线程相同。(线程私有)

数据区

方法区

存储已被虚拟机加载的类信息、常量(JDK1.7有变化)、静态变量、JIT、即时编译器编译后的代码等数据。

溢出时会报错java.lang.OutOfMemoryError: PermGen space,需要设置MaxPermSize

-XX:PermSize=256M JVM初始分配的非堆内存
-XX:MaxPermSize=512M JVM最大允许分配的非堆内存,按需分配

堆区

用途:存放对象实例。

生命周期:虚拟机启动时创建。(线程共享)

设置大小:-Xmx和-Xms。这里设置的堆内存初始大小是不会回收的。

Xms:256m     #memoryStart(初始内存大小)
Xmx:1G       #memoryMax(内存最大大小)

Demo

方法区存储类信息、常量、静态变量

成员变量基本类型存储在虚拟机栈中,对象存储在堆中

成员方法存储在虚拟机栈中(一个方法一个栈帧)

内存模型JMM

 

Java虚拟机每次使用新生代中的Eden和其中一块Survivor(From),在经过一次Minor GC后,将Eden和Survivor中还存活的对象一次性地复制到另一块Survivor空间上(这里使用的复制算法进行GC),最后清理掉Eden和刚才用过的Survivor(From)空间。将此时在Survivor空间存活下来的对象的年龄设置为1,以后这些对象每在Survivor区熬过一次GC,它们的年龄就加1,当对象年龄达到某个年龄(默认值为15)时,就会把它们移到老年代中。 

堆=新生代+老年代,不包括永久代(方法区)

总结图

参考

http://www.cnblogs.com/lovesong/archive/2018/05/04/8993033.html

https://blog.csdn.net/qq_19734597/article/details/80958817 

posted @ 2019-03-12 08:52  秋夜雨巷  阅读(575)  评论(0编辑  收藏  举报