跨平台
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
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/17803.html