2.6.1. Java 内存模型
在 Java 中,内存被划分为以下几个区域:
- 堆(Heap):存储对象实例和数组,是垃圾回收的次要区域。
- 栈(Stack):存储局部变量和办法调用。每个线程有本人的栈。
- 办法区(Method Area):存储类信息,如类的构造、办法、字段等。
- 本地办法栈(Native Method Stack):存储本地办法(如 JNI)的调用。
- 程序计数器(Program Counter Register):批示以后线程执行的字节码指令。
2.6.2. Java 对象的生命周期
Java 对象的生命周期分为以下几个阶段:
- 创立:应用
new
关键字创建对象实例。 - 应用:对象被程序援用和应用。
- 不可达:对象没有任何援用指向它,无奈被程序拜访。
- 垃圾回收:垃圾回收器回收不可达对象所占用的内存。
- 内存开释:内存被开释并归还给零碎。
2.6.3. 垃圾回收
Java 的垃圾回收器主动回收不再应用的对象。垃圾回收的目标是开释无用对象占用的内存,防止内存透露。垃圾回收过程次要产生在堆内存区域。
垃圾回收器的工作原理:
- 标记:垃圾回收器会找出所有不可达的对象,并将它们标记为垃圾。
- 革除:垃圾回收器会回收被标记的对象所占用的内存。
Java 中罕用的垃圾回收算法:
- 援用计数法:每个对象保护一个援用计数,当援用计数为 0 时,对象被视为垃圾。但这种办法无奈解决循环援用问题。
- 标记 - 革除(Mark-Sweep):分为标记和革除两个阶段,标记阶段标记所有不可达对象,革除阶段回收它们的内存。但可能产生内存碎片。
- 标记 - 整顿(Mark-Compact):在标记 - 革除根底上,将存活对象整顿到内存的一端,回收边界以外的内存。解决了内存碎片问题。
- 分代收集(Generational Collection):将堆内存划分为新生代和老年代,针对不同代采纳不同的垃圾回收策略。新生代应用复制算法(Copying),老年代应用标记 - 革除或标记 - 整顿算法。
2.6.4. 内存透露与内存溢出
- 内存透露:程序中某个对象不再应用,但依然被援用,导致无奈被垃圾回收器回收。内存透露可能导致内存溢出。
- 内存溢出:程序申请的内存超过了零碎可调配的最大内存,导致程序解体。
防止内存透露的办法:
- 及时开释不再应用的对象援用。
- 防止动态汇合类援用长期占用内存的对象。
- 应用 WeakReference、SoftReference 等弱援用类型。
2.6.5. 示例
上面的示例展现了一个简略的类及其实例化过程,以及垃圾回收的触发。
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {Student student1 = new Student("Alice", 20); // 创立一个 Student 实例
Student student2 = new Student("Bob", 22); // 创立另一个 Student 实例
student1 = student2; // student1 援用指向 student2,此时原先的 "student1" 实例无法访问,成为垃圾
System.gc(); // 倡议 JVM 进行垃圾回收(留神:这并不保障立刻进行垃圾回收)}
}
在这个示例中,咱们创立了两个 Student
实例。当 student1
援用指向 student2
时,原来的 student1
实例变得不可达,成为垃圾。咱们应用 System.gc()
倡议 JVM 进行垃圾回收。须要留神的是,System.gc()
并不保障立刻进行垃圾回收,具体的回收机会取决于 JVM 的实现。
这一节咱们具体解说了 Java 内存治理与垃圾回收的相干常识,包含内存模型、对象的生命周期、垃圾回收原理及算法、内存透露与内存溢出等内容。咱们还通过一个简略的示例展现了垃圾回收的触发。心愿这些内容对你有所帮忙,如果你还有其余问题,请随时发问。
举荐浏览:
https://mp.weixin.qq.com/s/dV2JzXfgjDdCmWRmE0glDA
https://mp.weixin.qq.com/s/an83QZOWXHqll3SGPYTL5g