1、程序计数器
作用:记住下一条JVM指令的执行地址。
特点:
1.线程是私有的。
2.不会存在内存溢出。
2、虚拟机栈
2.1定义
1.每个线程运行时所需要的内存,称为虚拟机栈
2.每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存 (栈帧 = 每个方法运行时需要的内存)
3.每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
共享变量需考虑线程安全。
方法内局部变量没有逃离方法的作用访问,它是线程安全的。
局部变量引用对象,并逃离方法作用访问,需要考虑线程安全。
2.2栈内存溢出(StackOverFlowError)
原因:1.栈帧过多(递归调用)
2.栈帧过大
2.3线程运行诊断
例子1:Cpu占用过多
- top定位哪个进程对Cpu占用过高
- ps H -eo pid,tid,%cpi|grep 进程ID(用PS命令定位)
*jstack进程ID(十进制换成十六进制)32655 = 7f99(可以根据线程ID找到有问题的线程,再根据代码行数寻找问题源头。
例子2.线程死锁(deadlock)
*jstack
3、本地方法栈(Native Method Stacks)
如Object、hashcode
4、堆
4.1定义
通过New关键字,创建对象都会使用堆内存。
特点:
1.线程共享,堆中对象都需要考虑线程安全的问题
2.有垃圾回收机制
4.2堆内存溢出(OutOfMemoryError:Java heap space)
堆内存中的空间不足以存放新创建的对象时发生。
4.3 堆内存诊断
1.JPS工具
2.jmap工具
jmap -heap pId
3.jconsole工具
5、方法区
1.6JVM 成为永久代 → 永久代内存溢出
1.8JVM本地内存元空间→元空间内存溢出
运行时常量池
常量池 = 一张表,虚拟机指令根据常量表找到要执行的类名、方法名、参数类等信息。
运行时常量池,*.class文件,当类被加载时,它的常量池信息就会放入运行时常量池,符号地址变为真实地址。
5.5 StringTable
面试题:答案 false true true false
s1-3在StringTable s4在堆中不能相同 s3≠s4
s.intern()将字符串尝试放入串池,有不放,无放。
StringTable特性
1.常量池的字符串是符号,第一次用时为对象
2.利用串池机制,来避免重复创建字符串对象
3.字符串变量拼接原理StringBuilder
4.字符串常量拼接原理编译期优化
5.Intern方法,主动将串池内还没有的字符串对象放入串池
1)1.8 字符串有则不放,无则放,把池内对象返回。
2)1.6 无则将此对象复制,放入串池,把池内对象返回。
6、直接内存
定义:
1.常见于NIO操作,用于数据缓冲区
2.分配回收成本较高,但读写性能高
3.不受JVM内存回收管理
分配和回收原理
1.使用Unsafe对象完成直接内存额分配回收,并且回收需要主动调用freeMemory方法
2.ByteBuffer的实现类内部,使用了Clearner(虚引用)来简则ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Clearner的clean方法调用freeMemory来释放直接内存。