JVM内存组成、垃圾回收(GC)、对象深浅拷贝,别再说“我不会了”
1. JDK1.8-JVM内存组成
存放 | 共享 | 垃圾回收 | |
---|---|---|---|
堆 | 程序运行时创建的对象实例 字符串常量池 | 所有线程可访问 | 没有被引用的对象 |
方法区 | 虚拟机加载的类的信息、常量、静态变量、方法声明等 | 所有线程可访问 | 常量、类型卸载的信息 不回收常见的静态变量 注意:如果静态常量是引用类型,被引用的对象有可能会被回收 |
程序计数器 | 当前线程执行的字节码指令的行号 (典型应用分支跳转时记录行号) | 线程独有 | |
虚拟机栈 | 主要为java方法服务 | 线程独有 | |
本地方法栈 | 主要为本地方法服务 | 线程独有 |
-
栈帧
存放局部变量、操作栈、动态链接、方法出口等
-线程创建时,虚拟机栈会为线程创建内存区域
-线程执行时,每个方法都会创建一个栈帧(可以看为方法的引用) -
每个方法从被调用到执行完都对应一个栈帧在虚拟机中入栈出栈过程
栈帧可以想象为当前方法在内存中的一个实例
2.垃圾回收GC
Garbage Collection(垃圾回收器)回收不在使用的内存
GC主要任务:
- 分配内存
- 确保引用
- 回收内存
GC回收依据:对象没有任何引用
GC使用有向图记录管理堆中的所有对象,回收不可达的对象
回收算法:
- 引用计数算法
- 跟踪回收算法
- 压缩回收算法
- 复制回收算法
- 按代回收算法
3.内存泄漏
一个不再需要被程序使用的对象或变量依然占用空间
举例
- 静态集合类(不要用static静态关键字描述对象或变量)
- 各种连接(数据库连接、网路连接、IO连接没有关闭)
- 监听器(没有对监听器进行有效控制时)
- 不合理的作用域(作用域最小化)
4.实现对象的浅复制、深复制
- 浅复制:
只对对象或变量值进行复制,引用对象地址不变(两个对象指向相同的引用对象) - 深复制:
不仅对象或变量值进行复制,引用对象也复制(两个对象指向独立的引用对象)
import java.io.*;
/**
* @Author: BaBy
* @Date: 2021/3/8 21:16
*/
public class Student implements Cloneable,Serializable {
private String name;
private Student partner;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getPartner() {
return partner;
}
public void setPartner(Student partner) {
this.partner = partner;
}
public Student deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return (Student) objectInputStream.readObject();
}
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Student s1 = new Student();
s1.setName("s1");
Student s2 = new Student();
s2.setName("s2");
s1.setPartner(s2);
System.out.println("Student s1.hashCode = " + s1.hashCode());
System.out.println("Student s1.getPartner().hashCode = " + s1.getPartner().hashCode());
Student shallow = (Student) s1.clone();
System.out.println("> Student shallow = (Student) s1.clone();");
System.out.println("Student shallow.hashCode = " + shallow.hashCode());
System.out.println("Student shallow.getPartner().hashCode = " + shallow.getPartner().hashCode());
Student deep = s1.deepClone();
System.out.println("> Student deep = s1.deepClone();");
System.out.println("Student deep.hashCode = " + deep.hashCode());
System.out.println("Student deep.getPartner().hashCode = " + deep.getPartner().hashCode());
}
}