JVM底层分析-Java300集笔记整理

目录

1. 面向对象的内存分析

1.1 从属于线程的内存区域

1.2 堆

1.3 方法区

1.4 运行时常量池

1.5 直接内存

2. 程序执行的内存分析过程

2.1 虚拟机栈的特点

2.2 堆的特点

2.3 方法区(静态区)特点

 3. 垃圾回收机制与回收算法

3.1 基本概念

3.2 垃圾回收算法

4. 通用的分代垃圾回收机制

5. 开发中容易造成内存泄漏的操作


1. 面向对象的内存分析

Java虚拟机内存模型概念

1.1 从属于线程的内存区域

JVM的内存划分中,有部分区域是线程私有的,有部分是属于整个JVM进程。

  • 程序计数器,在JVM规范中,每个线程都有自己的程序计数器。存储当前线程正在执行的Java方法的JVM指令地址,即字节码的行号,如果正在执行Native方法,则这个计数器为空。

  • Java虚拟机栈,同样也属于线程私有区域,每个线程在创建的时候都会创建一个虚拟机栈。虚拟机栈内部保持一个个栈帧,每次方法调用都会进行压栈,JVM对栈帧的操作只有出栈和压栈两种,方法调用结束时会进行出栈操作。

  • 本地方法栈,不管

1.2 堆

堆,几乎所有创建的Java对象实例,都是被直接分配到堆上的,堆被所有的线程所共享,在堆上区域,会被垃圾回收器做进一步划分,如新生代、老生代。

1.3 方法区

方法区与堆一样,也是所有的线程所共享,存储被虚拟机加载的元数据,包括类信息、常量、静态变量等。

方法区是一种Java虚拟机的规范,由于方法区存储的数据和堆中存储的数据一致,实际上也是堆。

1.4 运行时常量池

1.5 直接内存

2. 程序执行的内存分析过程

Java虚拟机的内存可以简单的分为三个区域:虚拟机栈stack,堆heap,方法区method area。

2.1 虚拟机栈的特点

  • 栈描述的是方法执行的内存模型,每个方法被调用都会创建一个栈帧

  • JVM为每个线程创建一个栈,用于存放该线程执行方法的信息

  • 栈属于线程私有,不能实现线程间的共享

  • 栈的存储特性是“先进后出,后进先出”

  • 栈是由系统自动分配,速度快,栈是一个连续的内存空间

2.2 堆的特点

  • 堆用于存储创建好的对象和数组

  • JVM只有一个堆,被所有线程共享

  • 堆是一个不连续的内存空间,分配灵活,速度慢

2.3 方法区(静态区)特点

  • 方法区是Java虚拟机规范,可以有不同实现

  • JVM只有一个方法区,被所有线程共享

  • 方法区实际也是堆,只是用于存储类、常量相关的信息

  • 用来存放程序中永远是不变或唯一的内容

 3. 垃圾回收机制与回收算法

3.1 基本概念

垃圾回收主要针对的是堆中的对象,包括对象空间的分配和释放。

  • 对象空间的分配:利用new关键字创建即可

  • 对象空间的释放:将对象赋值为null即可,垃圾回收器将负责回收所有“不可达”对象的内存空间

任何一种垃圾回收算法主要做两件事

  • 发现无用对象

  • 回收无用对象的内存空间

3.2 垃圾回收算法

  • 引用计数法

    堆中每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为null),引用计数器减1,最后如果该对象的引用计数器的值为0,则Java垃圾回收器认为该对象时无用对象并对其进行回收。

    优点:算法简单

    缺点:循环引用的无用对象无法识别

  • 引用可达法(根搜索算法)

    程序把所有的引用关系看作一张图

  • 还有其他方法

4. 通用的分代垃圾回收机制

1.年轻代、年老代、永久代

Eden(年轻代)、Survivor(年轻代)、Tenured/Old(年老代)

所有新生成对象都是在Eden中,年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。当“年轻代”区域存满之后,放入到年老代区域。

年轻代中经历了N(默认15)次清理后仍存在的对象,放入年老代中。

永久代JDK8之后就取消了,用metaspace元数据空间和堆替代。

2.清理工具

Minor GG:清理年轻代区域

Major GC:清理年老代区域

Full GC:清理年轻代、年老代、成本较高,会对性能产生影响

5. 开发中容易造成内存泄漏的操作

  • 创建大量无用对象

  • 静态集合类的使用

  • 各种连接对象(IO流对象,数据库连接对象,网络连接对象)未关闭

  • 监听器的使用

Guess you like

Origin blog.csdn.net/lipengfei0427/article/details/121386611