所有的回收器类型都是基于分代技术来实现的,那就必须要清楚对象按其生命周期是如何划分的。
有了以上这些铺垫之后开始回答 GC 何时开始:
Eden 内存满了之后,开始 Minor GC(从年轻代空间回收内存被称为 Minor GC);升到老年代的对象所需空间大于老年代剩余空间时开始 Full GC(但也可能小于剩余空间时,被 HandlePromotionFailure 参数强制 Full GC)
对什么东西操作,即垃圾回收的对象是什么:
从 root 开始搜索没有可达对象,而且经过第一次标记、清理后,仍然没有复活的对象。
做了什么东西:
主要做了清理对象,整理内存的工作。具体的引申如下
JVM 中类的装载是由 ClassLoader 和它的子类来实现的,Java ClassLoader 是一个重要的 Java 运行时系统组件。它负责在运行时查找和装入类文件的类。
java 的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。
堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用 new 创建的对象都放在堆里,所以,它不会随方法的结束而消失。 方法中的局部变量使用 final 修饰后,放在堆中,而不是栈中。
GC 是垃圾收集的意思(Gabage Collection) ,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃, Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的, Java 语言没有提供释放已分配内存的显示操作方法
当通过 Java 命令启动 Java 进程的时候,会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候,就从对空间中分配内存。GC 是 JVM 内部的一个进程,回收无效对象的内存用于将来的分配。
可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory() 方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。
JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。 Difference between stack and heap memory in Java
加载Loading:通过一个类的全限定名来获取一个二进制字节流、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
验证Verification:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并不会危害虚拟机的自身安全。
准备Preparation:正式为类变量分配内存并设置类变量初始值。
解析Resolution:虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化Initialization:类加载过程的最后一步,到了这个阶段才真正开始执行类中定义的Java程序代码。
使用Using:根据你写的程序代码定义的行为执行。
卸载Unloading:GC负责卸载,这部分一般不用讨论。
强引用:new出的对象之类的引用,只要强引用还在,永远不会回收。
软引用:引用但非必须的对象,内存溢出异常之前回收。
弱引用:非必须的对象,对象只能生存到下一次垃圾收集发生之前。
虚引用:对生存时间无影响,在垃圾回收时得到通知。
Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。
谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。 java 中有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉。由于 Java 使用有向图的方式进行垃圾回收管理,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么 GC 也是可以回收它们的,例如下面的代码可以看到这种情况的内存回收。

