JVM之内存模型

JVM 内存模型以及分区

栈区

栈分为java虚拟机栈本地方法栈

java虚拟机栈是线程私有,生命周期和线程相同。

每个方法都会创建一个栈帧,用于存放局部变量表,操作栈,动态链接,方法出口等。每个方法被调用,直到执行完毕,对于着一个栈帧的入栈到出栈的过程。

方法区 (也可以叫永久代)

方法区也叫作永久代,主要存放虚拟机加载的类信息,常量和静态变量等数据。

JDK8中叫元空间(MetaSpace),移除出JVM。直接使用在内存中

程序计数器

当前线程执行的行号指示器,在循环,分支,跳转,以及多线程之间交易都会使用这个,它是线程私有的。

堆区

堆是所有线程共享的,唯一目的就是存放对象实例

堆区分为新生代和老年代,新生代又分为三个区域,比例为8:1:1

新生代采用的复制算法来回收对象。

老年代采用标记清除算法和标记-整理法

堆区参数有:-Xms 堆最小值 -Xmx 堆最大值, 一般情况下,可以讲堆内存设置到物理内存的百分之八十。两者相等可以避免内存的跳动
新生代堆参数有:-XX:NewSize 新生代最小值,-XX:MaxNewSize 新生代最大值
永久代大小调整:-XX:MaxPermSize JDK8已经取消了,转移到外部内存中
-XX:MaxTenuringThreshold 设置新生代对象转到老年代需要经过多少次垃圾回收

类加载

类加载的过程

  1. 加载
    获取二进制字节流,同时将静态存储结构转换为方法区数据结构
  2. 验证
    主要验证字节流的格式规范
  3. 准备
    此阶段主要分配变量比如static的变量,分配类变量的初始值。只有final才会被分配的正确的值
  4. 解析
  5. 初始化
    这一步主要初始化静态代码块,构造函数,父类的初始化等
  6. 使用
  7. 卸载 由GC来处理

双亲委派模型:Bootstrap ClassLoader、ExtensionClassLoader、ApplicationClassLoader。

类加载器按照层次,从顶层到底层,分为以下三种:

(1)启动类加载器(BootstrapClassLoader)

这个类加载器负责将存放在JAVA_HOME/lib下的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。

(2)扩展类加载器(ExtensionClassLoader)

这个加载器负责加载JAVA_HOME/lib/ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器

(3)应用程序类加载器(ApplicationClassLoader)

这个加载器是ClassLoader中getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径(Classpath)上所指定的类库,可直接使用这个加载器,如果应用程序没有自定义自己的类加载器,一般情况下这个就是程序中默认的类加载