java堆内存划分为新生代,老年代。一般jvm默认情况下新生代占用堆空间的1/3,老年代占用堆空间的2/3. 新生代又分为Eden区,from survivor区,to survivor区,默认情况Eden区占用新生代的8/10,from survivor 和to survivor各自占用1/10.from survivor 和to survivor位置不是固定,它们经常是来回变化交换名字。
虚拟机默认划分了堆的空间内存范围,但是其实是可以人为配置的,下面界面配置堆内存的参数:
-Xms20m -Xmx20m 设置堆大小内存空间,一般情况为了防止jvm不断调整内存大小,浪费不必要的性能,通常都将最大最小的内存空间值设置一样。-Xmn10M 设置堆空间新生代的大小,这样新生代和老年代的占用比列就不一定是默认的了-XX:SurvivorRatio=8 设置Eden占用新生代大小为8份常见内存分配和垃圾回收参数:
-XX:+PrintGCDetails: 打印GC日志
-XX:PretenureSizeThreshold=3M:设置大对象直接进入老年代的值
-XX:MaxTenuringThreshold=1: 设置长期存活对象存活多少次转移到老年代,比如MinoGC回收一次依旧 存活则将对象转入老年代。
-XX:-HandlePromotionFailure:内存回收担保
在新生代工作的垃圾回收器:Serial, ParNew, ParallelScavenge 在老年代工作的垃圾回收器:CMS,Serial Old, Parallel Old 同时在新老生代工作的垃圾回收器:G1 -XX:+UseParNewGC : 使用ParNew 垃圾回收器
引用《深入理解Java虚拟机:JVM高级特性与最佳实践》的介绍:
所以,jdk8环境下,默认使用 Parallel Scavenge(新生代)+ Serial Old(老年代)
-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型 -XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断
堆内存中没有被局部变量,静态变量,常量所引用得堆对象,会被垃圾回收线程回收
一个类得加载过程分别是 加载 验证 准备 解析 初始化 使用 卸载
加载: 将class对象加载到方法区 验证: 验证class对象是否符合jvm 规范 准备: 为类分配内存空间,给类变量分配内存空间,进行初始化(没有赋值), 解析: 符号引用替换为直接引用得过程 初始化: 堆类得静态变量进行赋值,实际意义的值
方法区的回收条件比较苛刻 1.该类的所有实列已经被回收 2.该类的类加载器已经被回收 3.该类的字节码对象没有任何引用
方法局部变量,静态变量可以作为GCROOTS
1.强引用
Strutent student = new Student. 软引用
// 强应用 public static Test test = new Test(); // 软应用 public static SoftReference<Test> softReference = new SoftReference<>(new Test()); // 虚引用 public static WeakReference<Test> weakReference = new WeakReference<>(new Test());1.新生代内存空间不够,老年代剩余空间大于新生代所有存活对象,可以触发minorGC 2.老年代剩余空间小于新生代所有存活对象,开启了内存分配担保,老年代剩余空间大于历代进入老年代对象得平均大小,此时可以触发minorGc