jvm、jre、jdk之间的关系

java virtual machine java 虚拟机,
java runtime environment java运行环境,包括jvm和基础类库
java development kits java开发工具包 ,包括java运行环境和开发工具

内存结构

程序计数器

作用:记录下一条jvm指令的执行地址
特点:
线程私有
不会存在内存溢出问题

虚拟机栈(stack)

每个线程运行时所需要的内存,叫栈
栈由多个栈帧(frame)组成,栈帧指的是每次方法调用时所占用的内存
每个线程只能有一个活动栈帧,对应着正在执行的方法

线程运行所需要的内存空间
栈帧:方法运行所需要的内存空间
栈帧中包含参数、局部变量、返回值
先进后出
jstack pid 查询进程详情

常见异常:stackOverFlowError,outOfMemory

本地方法栈

调用本地方法时,即native方法所在的区域

堆是java虚拟机管理内存最大的一块内存区域,因为堆存放的对象是线程共享的,所以多线程的时候也需要同步机制。
-Xmx(最大值)和-Xms(最小值)

方法区

jdk8中改为元空间
保存jvm加载过的的类的信息、包括常量、静态变量。在类加载的时候就保存在了这个区
存在垃圾回收:用户自定义类加载器加载的一些类,可能会被垃圾回收
具体包含:类型、字段元信息、方法、静态变量、对类加载器的引用、对class的引用

垃圾回收

如何判断对象可以回收

1.1 引用计数法:无法解决循环引用的场景
1.2 可达性分析法:GC roots对象
1.3 四种引用

  1. 强引用
    • 只有所有GC roots对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
  2. 软引用(softReference)
    • 仅有【软引用】引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用对象
    • 可以配合引用队列来释放引用自身
  3. 弱引用
    • 仅有【弱引用】引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
    • 可以配合引用队列来释放弱引用自身
  4. 虚引用
    • 必须配合引用队列使用,主要配合ByteBuffer使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用虚引用相关方法释放直接内存
  5. 终结器引用

    • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第二次GC时才能回收被引用对象

      垃圾回收算法

  6. 标记清除算法:先标记,再清除(记录回收内存起始地址),会产生内存碎片

  7. 标记整理算法:先标记,再整理,清除,不会产生内存碎片,但是整理过程比较费劲,速度慢,涉及到引用地址的修改
  8. 复制算法:先标记,后复制(该步骤就会清理掉内存碎步),再交换,效率高,但是会占用双倍的内存

    分代垃圾回收

    Minor GC:只对新生代进行垃圾回收
    Full GC:全部区域进行垃圾回收
  • 新生代
    • 伊甸园
    • 幸存区from
    • 幸存区to
  • 老年代

步骤:

  1. 对象首先会分配在伊甸园区域
  2. 新生代空间不足时,触发minor GC,伊甸园和from存活的对象使用copy复制到to中,存活的对象年龄加一,并且交换from to
  3. minor GC会引发stop the world,暂停其他用户的线程,等垃圾回收结束,用户线程才恢复运行
  4. 当对象寿命超过阈值时,会晋升至老年代,最大阈值时15次,存储在对象头中(4bit)
  5. 当老年代空间不足,先进性minor GC,如果空间仍不足,那么触发full GC,也会stop the world,时间更长

    垃圾回收器

  6. 串行(SerialGC)

    • 单线程
    • 堆内存较小,适合个人电脑
  7. 吐量优先(ParallelGC)
    • 多线程
    • 堆内存较大,多核cpu,适合服务器
    • 让【单位时间】内stop the world的时间最短
  8. 响应时间优先(CMS)
    • 多线程
    • 堆内存较大,多核cpu,适合服务器
    • 尽可能让【单次】stop the world的时间最短
  9. G1

    类加载核字节码技术

类加载器

名称 加载哪的类
Bootstarao ClassLoader (启动类加载器) JAVA_HOME/jre/lib
Extension ClasssLoader (拓展类加载器) JAVA_HOME/jre/lib/ext
Application ClassLoader (应用程序类加载器) classpath
自定义类加载器

双亲委派模式
线程上下文类加载器

运行期优化

即时编译:在代码运行期间,通过识别热点代码,进行优化,将字节码翻译成机器码,
逃逸分析:判断变量是否存在逃逸,如果没有,就不创建该对象
方法内联:

内存模型JMM

定义了一套在多线程读写共享数据时(成员变量、数组),对数据的可见性、有序性、和原子性的规则和保障
synchronized:
既可以保证可见性,也可以保证原子性
volatile 易变性(避免从高速缓存中读取数据,强制从主存中读取;可以禁用指令重排):
不能保证操作的原子性,比如i++;只适用于一个写,多个读

有序性的理解:
在单个线程内,在保证不影响执行结果的前提下,jvm可能调整命令的顺序,这种特性称之为【指令重排】

乐观锁和悲观锁
CAS 乐观锁,先使用,再检验,可以实现无锁并发
synchronized悲观锁,先锁住,再使用

原子操作类
java.util.concurrent

synchronized内部优化
线程之间无竞争,开启轻量级锁,如果有竞争,先自旋,如果还获取不了锁,就开启重量级锁
偏向锁:

reentrantlock

五大内存区域: