1. 强引用
指通过普通方式创建一个对象,并把这个对象赋给一个引用变量。只要还有引用变量指向,就不会被JVM回收,即使在内存不足时。
2. 软引用
通过SoftReference实现。
和强引用类似,区别是当内存不足时会被JVM回收。
public static void main(String[] args) {
SoftReference<User>[] users = new SoftReference[16910];
for (int i = 0; i < users.length; i++) {
users[i] = new SoftReference<User>(new User("name" + i));
}
System.out.println(users[0].get());
System.out.println(users[6].get());
System.gc(); // 垃圾回收
System.runFinalization(); // 执行析构方法
System.out.println();
System.out.println(users[0].get());
System.out.println(users[6].get());
}
设置较小的JVM堆大小以模拟堆内存不足场景:
-Xms2M -Xmx2M。1M会报Too small initial heap for new size specified错误。
输出:
com.john.jvm.User@39443f
com.john.jvm.User@1afae45
null
com.john.jvm.User@1afae45
3. 弱引用
通过WeakReference实现。
弱引用具有很强的不确定性,垃圾回收每次都会回收弱引用的对象。
public static void main(String[] args) {
User user = new User("name");
WeakReference<User> wr = new WeakReference<User>(user);
user = null; // 去除强引用
System.out.println(wr.get());
System.gc(); // 垃圾回收
System.out.println(wr.get());
}
输出:
com.john.jvm.User@c1c428
null
4. 虚引用
通过PhantomReference实现。
软引用和弱引用可以单独使用,虚引用不能单独使用。虚引用的作用是跟踪对象被垃圾回收的状态。程序可以检测与虚引用关联的引用队列是否已经包含了指定的虚引用,从而了解虚引用的对象是否即将被回收。
本身对对象没有影响,类似于没有引用。对象甚至感觉不到引用的存在。如果一个对象只有一个虚引用存在,那么它就类似于没有引用存在。
public static void main(String[] args) {
User user = new User("name");
ReferenceQueue<User> rq = new ReferenceQueue<User>(); // 引用队列
PhantomReference<User> pr = new PhantomReference<User>(user, rq); // 创建一个虚引用,关联指定对象和队列。
user = null;
System.out.println(pr.get()); // 获取虚引用的对象
System.gc(); // 垃圾回收
System.runFinalization();
System.out.println((rq.poll() == pr)); // 取出引用队列的第一个对象与虚引用进行比较
}
输出:
null
true
分享到:
相关推荐
3. 指令集:JVM使用一套基于栈的指令集,这些指令对应于字节码,如`aload`用于加载引用到操作数栈,`iadd`用于执行整数加法等。 4. 执行引擎:解释器负责逐条解释执行字节码,而即时编译器(JIT)会将热点代码编译...
运行时常量池是方法区的一部分,它存放编译期生成的各种字面量和符号引用,并在类加载后被存放至方法区的运行时常量池中。运行时常量池具备动态性,可以在运行期间添加新的常量。 #### 堆(Heap) 堆是JVM中最大的...
4. **解析**:此时,JVM将常量池中的符号引用转换为直接引用。这个阶段不是必需的,可以在类或接口被首次使用时动态解析。 5. **初始化**:最后,JVM执行类的初始化方法(),这包括静态变量的初始化和静态代码块的...
它们在Class文件中存储了Java代码运行时所依赖的元数据,这使得JVM能够解析这些符号引用,完成类加载过程。 在基础篇中,我们还提到了其他语言是否可以使用JVM作为产品交付媒介。这个问题的答案是肯定的。以Groovy...
- 指令手册会列出所有这些指令,比如`iconst_5`表示将整数5压入操作数栈,`aload_0`用于将局部变量表的第一个元素(通常为this引用)加载到操作数栈。 3. **垃圾收集**: - JVM负责自动管理内存,通过垃圾收集...
JVM主要由以下四个关键组件构成: 1. **类的加载机制**:这是JVM的基础,负责加载Java类,并准备执行这些类。类加载机制确保了类的正确加载,并管理类的生命周期。 2. **JVM内存结构**:主要包括堆、栈、方法区等,...
解决内存溢出的方法有两种:一是优化程序代码,减少全局变量的引用,让程序使用完变量的时候释放该引用,能够让垃圾回收器回收,释放资源;二是物理解决,增大物理内存,然后通过调整 JVM 的参数来调整内存的大小。 ...
#### 四、内存模型、锁与同步 **Java内存模型** 主要涉及以下方面: - **主内存**:存储共享变量。 - **工作内存**:每个线程的私有数据区域,存储线程局部变量等。 **锁与同步机制** 包括: - **volatile关键字**...
4. null值处理:aconst_null指令(0x01)用于将null值推送到操作数栈上,表明一个引用类型的空值。 5. 操作数栈:JVM使用一个先进后出(FILO)的数据结构来存储局部变量和中间计算结果,这个结构就是操作数栈。所有...
JVM的内存管理主要分为堆(Heap)、栈(Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)四个部分。堆用于存放对象实例,是垃圾回收的主要区域。栈负责存储局部变量和方法调用的状态,每个线程...
- **回收策略**:从JVM方法栈和本地方法栈引出来的引用开始,把每一个引出来的引用作为根依次搜索(遍历),如果从这个根开始寻找,找不到这个对象,那这个对象就是垃圾。 - **触发条件**:当对象不再被任何引用关联...
垃圾回收是JVM中的一种机制,用于回收无用的对象以释放内存空间。垃圾回收机制可以分为两种:部分垃圾回收和完全垃圾回收。部分垃圾回收是指JVM在年轻代中回收无用的对象,而完全垃圾回收是指JVM在整个堆中回收无用...
- 运行时常量池:方法区的一部分,存储编译期生成的各种字面量和符号引用。 4. **垃圾收集(GC)**: - 垃圾收集的目的是自动回收不再使用的对象所占用的内存。 - 分代收集理论:将堆分为新生代(Eden、Survivor...
4. **类型转换指令**:Java是一种强类型语言,不同数据类型的转换需要特定指令,如`i2d`将int转换为double,`checkcast`用于类型安全的强制转换。 5. **对象创建与访问指令**:`new`用于创建一个新的对象实例,`a...
字节码是一种中间语言,它不是特定于任何一种硬件架构的机器代码,而是设计用于JVM执行的。这种方式确保了Java程序可以在任何安装了JVM的平台上运行。 ##### 1.4 半编译半解释 Java程序采用了一种半编译半解释的...
第四节:垃圾回收算法 1.1标记清除算法 1.2复制算法 1.3 标记整理(标记压缩)算法 第五节:垃圾回收器 1.1Serial/Serial Old收集器 1.2 ParNew收集器 1.3Parallel Scavenge收集器 1.4Parallel Old收集器 1.5CMS...
JVM垃圾回收机制通过两种主要算法来确定对象是否成为垃圾,即“可达性分析算法”和“引用计数法”。 - 可达性分析算法:这种方法通过确定对象的引用链来判断对象是否可达。GC根对象包括虚拟机栈中引用的对象、方法...
"JVM指令手册详细完整版.pdf" 本资源是关于JVM指令的详细手册,涵盖了JVM指令的各种系列命令,包括未归类系列、const系列、push系列、ldc系列、load系列等。每个系列命令都有其特定的功能和用途,下面我们将逐一...
这有助于更深入地理解JVM如何处理不同类型的对象引用和方法分派。 综上所述,Java虚拟机指令集是Java程序执行的关键组成部分。通过深入研究JVM的工作原理和指令集,可以帮助我们更好地理解和优化Java程序的性能。