因此,我仍然在学习内存管理的一般知识,而不仅仅是Java。我在这个白龙文章上读过。
本文展示了以下代码的示例:
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方法之后,它将被垃圾收集。
但如果场景是豆子的话。考虑一下Spring项目中的这个示例:
@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应该仍然在内存中,不应该被垃圾收集,那么有什么区别呢?
发布于 2022-01-27 09:30:52
你从错误的角度看它。最后,决定垃圾收集器是否收集对象的不是静态的,也不是作为bean的。
唯一的条件是:该对象是否仍然被认为是活动的?!
当可以从正在运行的线程的上下文“到达”对象时,这些对象被认为是活动的。
换句话说:静态成员由相应的类对象引用。而加载类的ClassLoader则(很可能)引用了这些类。因此,静态成员通常是活着的,不会被收集。
对于bean示例,重点是:这是一个在外部REST请求传入时将被调用的方法。接下来:处理请求,准备响应数据,将响应数据与答案一起发送出去。
现在:响应对象引用了bean对象。但是,在答复发出后,再也没有提到答复。因此,没有对bean的引用。因此,list对象不再是活动的,list、bean、response都是垃圾收集的对象。
但是:是的,UserController实例不断向字段添加用户对象。因此,存在一个用于内存泄漏的潜在。
如果Spring框架丢弃了,那么这些UserContext对象:没有内存泄漏。如果它一次又一次地使用同一个对象,那么这个列表就会增加,并导致内存泄漏。
https://stackoverflow.com/questions/70876040
复制相似问题