JAVA GC
直接内存的分配不会受到JAVA堆大小的限制,但是也会受到本机总内存(物理内存,CWAP分区或者分页文件)大小以及处理器寻址空闲的限制,如果只按照实际内存去设置-Xmx等参数信息,忽略到直接内存,使得整个内存区域综合大于物理内存限制(物理和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。方法区的一部分,Class文件中除了有类版本,字段,方法,接口等描述信息,还有一项
文章来由
C/C++ vs java
GC的概念随着JAVA兴起逐渐被人们所熟知,
C/C++ delete/free手动管理内存
java 虚拟机自动内存管理机制
java的GC由于需要后续扫描,执行效率上下降是必然的,但是带来的好处是不会因为遗漏导致内存泄漏,不会因为多次回收导致非法访问
但正因如此,当出现内存泄漏和溢出,不了解虚拟机怎么使用内存,排查会是一项艰难的工作。
好吧,就是因为不经常使用,自己每次查这个比较费劲,整理一下方便自己。
明确问题发生区域
java运行时数据区域

1,程序计数器 Program Counter Register
线程私有(独立存储,互不影响),是一块很小的内存空间,是当前线程所执行字节码的行号指示器,帮助再次获取执行权限时不至于重复执行。
2,Java虚拟机栈 Java Virtual Machine Stack
线程私有,是java方法执行的线程内存模型,每个方法执行时,JVM都会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态连接,方法出口等信息。一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表:存放编译器的基本数据类(boolean,byte,char,short,int,float,long,double),reference类型(对象引用),returnAddress类型(指向一条字节码指令的地址)
3,本地方法栈 Native Method Stacks
与虚拟机栈相似,不同的是为虚拟机使用本地方法Native服务。
4,java堆 Java Heap
虚拟机管理的最大的一块内存,被所有线程共享,存放几乎所有的对象实例和数组。
逃逸分析:栈上分配(私有的小对象),标量替换,同步消除
栈上分配:由于在堆上分布的对象回收消耗了大量的资源,对于确定不会逃逸出线程之外的对象,在栈上分配,随着线程方法结束消耗,大大降低了GC压力。(支持方法逃逸,不支持线程逃逸)
public void m1(){
T t = new T();//可逃逸
}
T t;
public void m2(){
t = new T();//不可逃逸
}
标量替换:
前提是方法中不可逃逸,在执行过程使用对象中的成员变量代替对象本身使用。
class Point{
int x;
int y;
get..
set..
}
Point x = new Point()
x.setX(1);
int xi = x.i;
同步消除:
一个变量不会逃逸出线程,这个变量读写不会有竞争,那么这个变量可以安全消除掉。
public int test(int x){
int xx = x+2;
int num1 = xx;
int num2 = 8;
return num1;
}
//无效代码消除后
public int test(int x){
return x+2;
}
5,方法区 Method Area
线程共享,存储已经被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。
永久代 Permanent Generation
HotSpot虚拟机实现的时候吧手气器的分代设计扩展至方法区,使用永久代实现方法区。使得HotSpot垃圾收集器能够像管理JAVA堆一样管理这部分内存,省去了放去去内存管理代码编写。但这种也带来了JAVA应用更容易出现内存溢出的问题。
由于后续收购了JRockit,在JDK7把原本放在永久代的字符串常量,静态变量等溢出,直至JDK8完全废弃了永久代的概念,改用与JRockit,J9一样在本地内存中实现元空间 Meta-space来代替,吧JDK7中的类型信息全部移到元空间中。
5.1,运行时常量池
方法区的一部分,Class文件中除了有类版本,字段,方法,接口等描述信息,还有一项信息是在常量池表,用于存放编译器生产的各种字面量与符号引用,这部分内存在类加载后存放到方法区的运行时常量池中。
6,直接内存
不是虚拟机运行时数据区的一部分,用于分配Native函数库,通过存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样分配的好处在于避免了JAVA堆和Nacive堆中来回复制数据。
直接内存的分配不会受到JAVA堆大小的限制,但是也会受到本机总内存(物理内存,CWAP分区或者分页文件)大小以及处理器寻址空闲的限制,如果只按照实际内存去设置-Xmx等参数信息,忽略到直接内存,使得整个内存区域综合大于物理内存限制(物理和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。
直接内存(Direct Memory)的容量大小可通过-XX:MaxDirectMemorySize参数来指定,如果不 去指定,则默认与Java堆最大值(由-Xmx指定)一致。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)