1. 什么是JVM
- jvm的定义:jvm指的是Java虚拟机,本质上是运行在计算机上的程序,他的职责 是运行java字节码文件。
- 作用:是为了支持Java的跨平台性,编写一次,到处运行
- 功能:
- 解释和运行:对字节码文件中的指令实时的解释成机器码,让计算机执行
- 内存管理:自动为对象、方法分配内存,自动的垃圾回收机制,回收不再使用的对象
- 即时编译:对热点代码进行优化,提高执行效率
- Java虚拟机的组成
- 源代码通过编译器编译生成字节码文件。
- 字节码文件通过类加载器加载,以二进制流的方式读取字节码文件,将字节码文件存储到内存当中。
- java虚拟机管理的内存部分叫做运行时数据区,其中包括了堆、栈、方法区、程序计数器
- 堆:主要存放了new关键字创建的对象,线程共享
- 栈:包括java虚拟机栈与本地方法栈,线程不共享
- java虚拟机栈:其中包括局部变量表、操作数栈、帧数据
- 局部变量表:主要存放了实例方法的this对象、参数、方法中的局部变量
- 操作数栈:主要是存放执行操作的临时数据
- 帧数据:主要是存放动态链表、方法出口、异常表
- java虚拟机栈:其中包括局部变量表、操作数栈、帧数据
- 方法区:
- 主要包括类的元信息、运行时常量池、字符串常量池
- jdk6及之前方法区主要在堆内,常量池再方法区内
- jdk7 方法区主要在堆内,但是字符串常量池由方法区移到堆内存中
- jdk8及之后方法去主要是在直接内存中,与堆内存无关。但是字符串常量池依旧处于堆内存中
- 执行引擎
- 解释器
- 即时编译器
- 垃圾回收器
- 本地接口:主要是执行本地已经编译好的方法。
2. 了解过字节码文件的组成
- 查看字节码文件的常用工具
- 字节码文件本质上是一个二进制文件,无法通过记事本等工具直接打开查看
- 开发环境 应用jclasslib工具
- 服务器环境 javap -v命令
- 字节码文件的组成
- 基本信息
- 魔数Magic
- 主副版本号
- 访问标识
- 父类和接口
- 常量池
- 保存了字符串常量、类或接口名、字段名
- 字段
- 当前类或接口声明的字段信息
- 方法
- 当前类或接口声明的方法信息
- 属性
- 类的属性,比如源码的文件名
- 基本信息
3. 请讲一下运行时数据区
运行时数据区主要是应用程序在运行过程中的内存部分,其中主要包括了线程不共享的,随着线程的创建而创建,随着线程的销毁而销毁的程序计数器、本地方法栈、java虚拟机栈,线程共享的堆、方法区,总共5部分。
- 程序计数器:主要是用来存放下一次要执行的字节码指令的内存地址
- 控制程序指令的进行,实现分支、跳转、异常等逻辑
- 在多线程执行情况下,Java虚拟机需要程序计数器记录cpu切换前解释执行到哪一句指令,并继续执行
- 本地方法栈:其实现与java虚拟机栈类似,采用先进后出的栈数据结构,为本地方法提供内存
- java虚拟机栈:采用栈结构,线程不共享,每个方法的调用使用栈帧来保存,每一次调用方法,就往栈内放入当前方法的栈帧,栈帧主要保存了局部变量表,操作数栈,帧数据
- 局部变量表中保存了实例方法的this对象,方法的参数,方法中的局部变量
- 操作数栈主要是为了方法在执行过程中提供的存放临时数据的地方
- 帧数据其中主要包括方法出口,动态链表,异常表
- 堆:一般Java程序中堆内存是空间最大的一块内存区域,创建出来的对象都在堆内存中。
- java虚拟机栈内的局部变量表中,可以存放堆内存对象的引用。静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间共享
- 堆是垃圾回收的最主要的部分,堆结构的详细划分与垃圾回收器有关。
- 方法区:主要包括类的元信息,运行时常量池,字符串常量池
- jdk6及以前:方法区位于堆内存中,字符串常量池与运行时常量池相同
- jdk7:将方法区内的字符串常量池从方法去中移到堆内存中
- jdk8及之后:将方法区从堆内存中移到了直接内存中。
4. 哪些区域会出现内存溢出
- 在运行时数据区内存溢出的部分主要是栈、堆、方法区
- 堆内存溢出:
- 堆内存溢出主要是在堆内存上分配的对象空间超过了堆内存的大小,从而导致的内存溢出,jvm设置堆内存最大值参数是-Xmx total值为-Xms
- 栈内存溢出
- 栈内存溢出主要是指所有栈帧所占用的空间超过了最大的栈内存空间,最大值用-Xss进行 设置,例如-Xss256k代表所有栈帧占用的内存空间不能超过256k,超过256k会抛出StackOverflow
- 方法区溢出
- 方法区的内存溢出指的是存放在方法区的内容比如类的元信息,运行时常量池,字符串常量池超过了方法区的最大内存,jdk7及之前的版本方法区位于永久代来实现,jdk8以及之后位于元空间来实现
- 堆内存溢出: