【问题标题】:Java Memory Leak - Static vs BeansJava 内存泄漏 - 静态与 Bean
【发布时间】:2022-01-27 09:19:56
【问题描述】:

所以我仍在学习一般的内存管理,而不仅仅是 Java。我读过这个Baeldung article

文章展示了以下代码的示例:

public class StaticTest {
    public static List<Double> list = new ArrayList<>();

    public void populateList() {
        for (int i = 0; i < 10000000; i++) {
            list.add(Math.random());
        }
        Log.info("Debug Point 2");
    }

    public static void main(String[] args) {
        Log.info("Debug Point 1");
        new StaticTest().populateList();
        Log.info("Debug Point 3");
    }
}

如果list 是静态的,我在示例中得到了这一点,Java 仍然保留对象而不是垃圾收集它。但是如果我们删除 static 关键字,在我们离开 populateList 方法后,它将被垃圾回收。

但是如果场景是一个 Bean 怎么办。考虑一下 Spring Boot 项目中的这个例子:

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    private List<User> userList = new ArrayList<>();

    @GetMapping("/users")
    public ResponseEntity<List<User>> getAllUser() {
        List<User> userList = userService.findAll();

        for(User u: userList) {
            this.userList.add(u);
        }

        return ResponseEntity.ok(userList);
    }
}

由于使用@RestController 注释,将创建一个bean,但在我自己的测试中,这不会导致内存泄漏,或者至少堆内存不会像static list 一样大如果对象计数相同。在我对 Bean 的理解中,userList 应该仍然在内存中并且不应该被垃圾收集,那么有什么区别呢?

【问题讨论】:

    标签: java spring-boot memory-management static javabeans


    【解决方案1】:

    你从错误的角度看它。最后,决定垃圾收集器是否收集对象的不是static是一个bean

    唯一的标准是:该对象是否仍被视为活着?!

    当对象可以从正在运行的线程的上下文中“到达”时,它们被认为是活动的。

    换句话说:静态成员被相应的类对象引用。那些反过来(最有可能)由加载类的 ClassLoader 引用。因此 static 成员通常是活动的,不会被收集。

    对于您的 bean 示例,要点是:这是一个将在外部 REST 请求进入时调用的方法。接下来:处理请求,准备响应数据,发送响应数据和答案。

    现在:bean 对象被响应对象引用。但是在发送响应之后,就不再引用响应了。因此没有对 bean 的引用。因此,该列表对象不再存在,并且列表、bean、响应,它们都受到垃圾回收的影响。

    但是:是的,那个 UserController 实例不断将 User 对象添加到那个 field。因此存在潜在的内存泄漏。

    如果 Spring 框架丢弃这些 UserContext 对象:没有内存泄漏。如果它一遍又一遍地使用同一个对象,那么该列表将会增长,并导致内存泄漏。

    【讨论】:

    • 所以只是为了确保我明白你在说什么,如果 bean UserController 中的属性 userList 中有成员,但垃圾收集器出于任何原因认为 UserController bean 不再存在,它将被垃圾收集。但是在应用程序的生命周期中,如果另一个请求来自另一个方法从 userList 请求某些东西,它会生成另一个带有空列表的 bean?那么以前的成员可能会丢失吗?
    • 查看我的更新。我想我误读了代码。可能存在内存泄漏,具体取决于框架的具体功能。
    • 对,所以我目前的理解是有些正确的,你帮我更正式地定义了它。您是否可以向我指出任何资源以了解有关内存管理和线程的更多信息?提前谢谢你。
    猜你喜欢
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2012-08-24
    • 2012-08-08
    • 2013-11-06
    相关资源
    最近更新 更多