Java虚拟机高级特性
方法区:一般放的是我们定义的常量 ,类的相关信息等等
虚拟机栈: 运行程序的时候线程会把当前运行的方法进行打包,然后放到该栈里面运行
本地方法栈;调用本地方法运行的时候放在该栈上面执行
程序计数器:
main(){
…
…
…
}
在这里面记录行数,方便快速查找
堆:所有的对象都在堆里面,栈里面只是引用
ClassA a = new ClassA();
new出来的这个对象就保存在堆里面,也就是实例都放堆里面(new ClassA()在堆上面放着,a是指向该堆里面这个地址)
虚拟机栈、本地方法栈以及程序计数器是每个线程独有的
方法区还有堆是一个java程序中所有的线程共享的部分,尤其是堆,两个线程共享一个对象的时候,靠堆来交换数据的。
运行时数据区域
栈
void a(){
…
b();
}
void b(){
}
调用时创建一个栈帧(局部变量表,方法的返回地址),入栈
b在里面执行完了先弹出栈,然后是a
堆
方法区
基于字节码来解释的。
第一次执行后,会保存成机器码存储,下次调用的时候可以很快的操作
MetaspaceSize元数据空间
直接内存
但是可以在开发的时候通过MaxDirecrtMemorySize去影响这个直接内存
勉强算是运行时数据区域的一部分
**
什么是IO?
**
详解见
直接内存作用:
网络IO通信 ,在这个过程中,网卡缓冲区是系统管理的,如果访问的话,需要从系统内存中拷贝过来,多了拷贝这一部分,会带来性能上的损失,和空间的浪费,所以在网络通信的时候,直接申请一份直接内存,避免了一个拷贝的部分。
有些时候内存溢出就是因为直接内存溢出了
有大小,有空间,就会有不足,所以有几种内存溢出:
OOM out of memory
Java堆溢出
-Xms5M -Xmx5M -XX:+PrintGCDetails -verbose:gc
报错:
方法区和运行时常量池溢出
-XX:MaxMetaspaceSize=3M
虚拟机栈和本地方法栈溢出
-Xss256k
递归容易引起,非递归要比递归效率高
本机直接内存溢出
-Xmx10M -XX:MaxDirectMemorySize=10M
垃圾收集器与内存分配策略
GC
Java实现不用引用计数算法,用的是可达性分析
GC Roots是可达性分析的一个出发点
画叉子的组成了所谓的孤岛,obj4 5 6会被垃圾回收器标记为可回收,然后进行回收
标记-清楚算法(Mark-Sweep)
假设每个都是1k,假设最后一行不存在,还有9k可用的,但是内存里面缺乏一个3K的连续空间,所以这个3k空间是无法分配下去的。这就是该算法存在的问题,为解决这个出现一个复制算法
复制算法(Coping)
但是又会造成内存空间上的浪费
所以又有一种算法
标记-整理算法(Mark-Compact)
但是这样也会浪费时间
所以又引出了
分代收集(把算法们都用上)
Serial是单线程的一个回收
Parallel Scavenge多线程的一个回收
Stop The World
模拟Stop the world
内存泄漏和内存溢出
内存溢出:跟水桶溢出水道理一样
内存泄漏:在写代码的时候,一些应该被垃圾回收的东西,没有被回收,俗话也就是说,本来能用5L的水桶但是实际上只有4L被利用了
(此乃自己根据视频学习的Java虚拟机高级特性自己整理的笔记,作为自己Java路上,一个精进点)