JVM
1、说一下 JVM 的主要组成部分及其作用?
- 类装载:根据给定的全限定名类名来加载class文件到JVM的内存。
- 执行引擎:执行classes中的指令。
- 本地库接口:与本地库交互,是其它编程语言交互的接口。
- 运行时数据区域:这就是我们常说的JVM的内存。
2、说一下JVM 运行时数据区(JVM内存)
- 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令。
- Java 虚拟机栈(Java Virtual Machine Stacks):
Java虚拟机栈也是线程私有的,它的生命周期与线程相同(随线程而生,随线程而灭)。它是用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
- 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
- Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;
- 方法区(Methed Area):方法区只是JVM规范中定义的一个概念,用于存储类信息、常量池
- 、静态变量、JIT编译后的代码等数据,具体放在哪里,不同的实现可以放在不同的地方。而永久代是Hotspot虚拟机特有的概念,是方法区的一种实现,别的JVM都没有这个东西。
很多人喜欢把方法区等同与永久代,永久代既然没了,方法区也就没了。但我认为方法区只是一种逻辑上的概念,永久代指物理上的堆内存的一块空间,这块实际的空间完成了方法区存储字节码、静态变量、常量的功能等等。既然如此,现在元空间也可以认为是新的方法区的实现了。
在永久代移除后,字符串常量池也不再放在永久代了,但是也没有放到新的方法区—元空间里,而是留在了堆里(为了方便回收?)。运行时常量池当然是随着搬家到了元空间里,毕竟它是装静态变量、字节码等信息的,有它的地方才称得上方法区。
3、堆栈的区别
1)栈是运行时的单位,而堆是存储的单位。
2)栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
在Java中一个线程就会相应有一个线程栈与之对应,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。而堆则是所有线程共享的。栈因为是运行单位,因此里面存储的信息都是跟当前线程相关信息的。包括局部变量、程序运行状态、方法返回值等等;而堆只负责存储对象信息。
4、JVM的分代思想
4.1、为什么要分代?
不同的对象的生命周期是不一样的。因此,分代是为了进行模块化管理,管理不同的对象及变量,以提高 JVM 的回收效率。不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。
4.2、新生代
新生成的对象优先存放在新生代中,新生的目标就是尽可能快速的收集掉那些生命周期短的对象。
4.3、老年代(Old)
在新生代中经历了多次GC后仍然存活下来的对象会进入老年代中。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。
4.4、永久代(Permanent)
永久代存储类信息、常量、静态变量、即时编译器编译后的代码等数据,对这一区域而言,