使用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完成,业务层面不再使用 后点击"执行垃圾回收"按钮,可以看到堆使用量大幅下降,说明大量过期对象已被回收。

相关推荐
M1A11 小时前
Spring Boot YAML 配置读取完全指南:从基础到微服务
java
古法安卓1 小时前
Android-SELinux 策略调试实战:从 AVC 日志到策略修复
android·java·android studio
todoitbo1 小时前
飞算JavaAI的多租户权限隔离实测
java·springboot·ai编程·java开发·飞算javaai·java代码生成
星空1 小时前
Springboot复习
java·spring boot·spring
Dicky-_-zhang1 小时前
大模型部署架构:从推理引擎到弹性扩缩容的工程实践
java·jvm
vHelios2 小时前
【电商项目】商品搜索开发复盘(1):根据需求拆解搜索接口的设计逻辑
java·微服务·es
极创信息2 小时前
国产化信创适配认证高频术语:信创适配、软件自主可控、国产化率、代码溯源率、代码自主率、代码开源率是什么?
java·python·struts·eclipse·开源·php·hibernate
Data_Journal2 小时前
什么是 CAPTCHA,它是如何工作的?
java·大数据·服务器·前端·数据库
mqiqe2 小时前
响应式流中的错误处理:Project Reactor 异常治理全体系
java·架构