b JMM java 内存模型

—> go to 总目录

一、JMM内存模型

b JMM java 内存模型

运行过程描述

该过程会串联启内存模型的各个功能便于理解JVM的行为,和JMM的作用

  • java文件被编译成class文件。
    class包含常量信息栈信息方法,和字节码指令类的继承和依赖关系信息

  • jvm启动时,根据启动参数申请内存创建JVM实例,包括方法区,,虚机栈本地方法栈程序计数器

  • 创建bootstarp类加载器,逐次加载系统类和用户类。这些class信息被放在方法区方法区同时还放类信息、常量、静态变量

  • jvm是懒加载机制,new类时会先在方法区中寻找,找不到时会加载,不用时GC会卸载。启动时 bootstarp.classloader会加载luncher类,加载main方法,这也算是主线程。

  • 注意虚拟机栈本地方法栈、和程序计数器,是线程独有的,随着主线程创建会产生。如果运行时有新的线程,也会创建新的。

  • 程序运行时new实例时,对象实例会放在Heap堆中,这时jvm直接管理的一块内存会存储实例数组,注意Sting也算数组,放在上。

  • 虚拟机栈包含局部变量栈操作数栈动态链接返回地址,当前栈帧信息。执行方法时,会根据class定义的信息,把局部变量、操作数压入相应栈。运行时才确定的引用,叫动态链接,也放入栈。

  • 如果指令调用到了本地方法,就会把局部变量,等信息放入本地方法栈

  • 程序计数器是线程级别的,保留着,当前进程的的当前操作数(指令)。这也是多线程不干扰的原因。

  • GC会不定时的,对堆进行压缩,对不用的class进行删除。因此class的卸载也是不可控的。

二、详细介绍

2.1 程序计数器

  • 线程私有,无OOM错误

保持对虚拟机栈操作数栈的引用,持有当前操作数,指示JVM该去执行的行为。

2.2 虚拟机栈

  • 线程私有
  • 每个元素叫栈帧。

线程在调用Java方法时,会为每一个方法创建一个栈帧,来存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法被调用和完成的过程,都对应一个栈帧从虚拟机上入栈和出栈的过程。

  • 示意图
    b JMM java 内存模型

2.3 本地方法栈

  • 线程私有,和虚拟栈类似。
    为线程私有,功能和虚拟机栈非常类似。来存储线程调用本地方法时,本地方法的局部变量表、操作栈等信息。

2.4 堆

  • JVM创建,所有线程共享。
  • 存储实例,数组String
  • 可以被细分老年代,年轻代等(不同GC分法不同),是GC回收的主要地点。

2.5 方法区

  • JVM创建,所有线程共享。
  • 存储class信息常量静态变量,即时编译的代码信息。

三、直接内存和HEAP

b JMM java 内存模型

  • 不属于jvm管理,需要手动清楚
  • 受限于主机内存

它起源于NIO包,网络连接时读和写的缓存区域

四、常见错误

OOM 内存溢出

OutOfMemoryError,指的是内存不够了,已有的内存不满足于申请的内存。

内存泄露

memory leak,是指存在异常的引用,使得空间无法被回收。直到内存溢出。两个不冲突。

五、引用

jmm