JVM内存管理深度剖析
https://blog.csdn.net/qq_44076155/article/details/110676870
深入理解对象与垃圾回收机制
https://blog.csdn.net/qq_44076155/article/details/110676774
Android虚拟机与classLoader类加载机制
https://blog.csdn.net/qq_44076155/article/details/110676784
Java Virtural Machine
一个翻译工具,我们写的程序通过编译后生成字节码文件,字节码文件再通过JVM翻译产生机器语言
不同平台上可以对应不同的JVM版本,可以运行在不同的操作系统上
翻译 .class .jar等
Java内存管理机制,运行数据区
运行时数据区是分配给JVM的内存资源,由JVM自由管理
线程私有(程序计数器,虚拟机栈,本地方法栈)
线程共享 (方法区,堆)
程序计数器
指向当前线程正在执行的字节码指令的地址,记录针对方法体的偏移量 为什么需要程序计数器?(时间片轮转-操作系统层 线程切换)
JVM内存区域中 唯一不会OOM OutOfMemory
虚拟机栈
栈帧(可以理解为一个方法)
局部变量表--存放局部变量,八大基本数据类型+引用
操作数栈--存放方法的执行和操作
动态连接--java语言多态特性
返回地址--正常返回(调用程序计数器中的地址作为返回)、异常的话(通过异常处理器表<非栈帧中的>来确定)
java解释执行是栈(操作数栈)--兼容性好,效率偏低
c是寄存器(硬件)运算—快 移植性差
使用-Xss可以用来限制虚拟机栈大小
虚拟机栈细节 每次进行一次指令必须通过操作数栈
本地方法栈
保存native修饰的本地方法,c语言实现的
HotSpot直接把本地方法栈和虚拟机栈合二为一
每个线程包括一个程序计数器,一个虚拟机栈,一个本地方法栈(有的JVM本地方法栈和虚拟机栈合二为一),线程里面每次进入一个新方法,则往虚拟机栈里加入一个栈帧
线程共享
动静分离,java堆中的东西回收频繁 ,将经常需要和回收的部分和不需要回收的部分区分
从底层深入理解运行时数据区
堆,栈(通常指的是虚拟机栈),方法区
用jps命令可以看到所用的java进程运行信息,图中是五个java进程,每一个进程都会有自己的jvm
获得到进程id之后,配置完参数,用HSDB绑定该进程就可以看到该进程的线程运行情况
可以看到下图中,方法区中存放类信息和一些常量,堆中存放类的实例对象,栈中是每个线程私有的虚拟机栈
堆中的内存是从新生代到老年带的连续的一块内存
堆和栈的区别
-
功能
-
以栈帧的方式存储方法调用的过程,并存储方法调用过程中基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放;
-
而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中;
-
线程独享还是共享
-
栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
-
堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
-
空间大小
栈的内存要远远小于堆内存
虚拟机优化技术
方法内联
减少栈帧的入栈出栈 减少一次max方法
栈帧之间数据共享
堆溢出
内存溢出:申请内存空间,超出最大堆内存空间。
如果是内存溢出,则通过 调大 -Xms,-Xmx参数。
如果不是内存泄漏,就是说内存中的对象却是都是必须存活的,那么久应该检查JVM的堆参数设置,与机器的内存对比,看是否还有可以调整的空间,再从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等情况,尽量减少程序运行时的内存消耗。