使用Java VisualVM观察过期对象引用现象

《Effective Java》书中第7条中提到:一般来说,只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。

此次测试过程我用的jdk8,在jdk的bin目录下可以找到jvisualvm.exe,双击打开。

idea设置堆内存限制-Xmx100M -Xms100M ,如下图所示

测试代码如下:

java 复制代码
import java.util.Arrays;
import java.util.EmptyStackException;

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final  int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack(){
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e){
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop(){
        if(size == 0){
            throw new EmptyStackException();
        }
        Object element = elements[--size];
        return element;
    }

    private void ensureCapacity(){
        if(elements.length == size){
            elements = Arrays.copyOf(elements, 2 * size +1);
        }
    }
}
java 复制代码
public class ObsoleteReferenceTest {
    public static void main(String[] args) throws InterruptedException {
        Stack stack = new Stack();
        // 压入大量大对象
        for (int i = 0; i < 80; i++) {
            stack.push(new byte[1024 * 1024]);
            System.out.println("压入第 " + i + " 个 1MB 数组");
        }
        // 全部弹出!业务上不再使用这些对象
        for (int i = 0; i < 80; i++) {
            stack.pop();
        }
        System.out.println("所有对象pop完成,业务层面不再使用");

        Thread.sleep(30000);
    }
}

运行代码后,进入Java VisualVM,在左侧找到当前代码运行的程序,双击,然后点击右侧上方的"监视",如下图所示

等待idea控制台输出 所有对象pop完成,业务层面不再使用 后点击"执行垃圾回收"按钮,如下图所示,可以看到,堆内存的使用量并没有明显下降。说明elements 数组内部仍然持有大量byte对象引用。

修改pop()方法,手动清空过期引用

typescript 复制代码
public Object pop(){
    if(size == 0){
        throw new EmptyStackException();
    }
    Object element = elements[--size];
    //手动清空过期引用
    elements[size] = null;
    return element;
}

再次运行代码,点击执行垃圾回收,观察堆使用情况,等待idea控制台输出 所有对象pop完成,业务层面不再使用 后点击"执行垃圾回收"按钮,可以看到堆使用量大幅下降,说明大量过期对象已被回收。

相关推荐
这个昵称不容易15 小时前
SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在
java·springboot·毕设
计算机毕设定制辅导-无忧学长15 小时前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统
文丑颜不良啊16 小时前
LeetCode2221~2240题目解析
java·leetcode
秋饼17 小时前
Computer Use Agent Java 落地实战:感知-行动循环、执行器与安全围栏生产级实现
java·ai·技术分享·后端开发
文丑颜不良啊18 小时前
LeetCode2161~2180题目解析
java·leetcode
文丑颜不良啊20 小时前
LeetCode2141~2160题目解析
java·leetcode
LabVIEW开发20 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
天天被压力21 小时前
【A股分钟级高频数据完全手册 #07】北交所历史分钟K线接口:京市Pro版分时批量
java·人工智能·python
天天被压力21 小时前
【A股分钟级高频数据完全手册 #08】股票日、分时数据接口对比:普通分时与Pro版差异实测
java·人工智能·python
特立独行的猫A21 小时前
AI 时代,我为什么推荐用 cj-tauri 开发桌面应用
java·后端·python