Java垃圾回收手册翻译 - 什么是垃圾回收
初看之下,垃圾回收应该要做其名称之事 - 找到和丢掉垃圾。然而事实上它正好做着相反的事,垃圾回收会记录所有仍在使用中的对象,然后将其他标记为垃圾。谨记这点,我们开始挖掘更多Java虚拟机如何实现被称为垃圾回收的自动化内存回收过程的细节。
为了避免一头扎进细节,我们从头开始,解释垃圾回收的一般性质以及核心概念和方法。
免责声明:本手册关注于Oracle Hotspot和OpenJDK的表现,其他运行时甚至其他虚拟机,比如jRockit或IBM J9,会在某些方面有不同于本手册所涵盖的表现。
手动内存管理
在开始现代形式的垃圾回收内容之前,我们先快速回顾一下那些需要手动显示分配和释放数据内存的日子。那时候如果你忘记释放内存,你将不能重用那块内存。这部分内存会被声明到但是没有使用,这种场景叫做内存泄漏。
下面是一个用C语言写的使用手动内存管理的简单例子:
int send_request() {
size_t n = read_size();
int *elements = malloc(n * sizeof(int));
if(read_elements(n, elements) < n) {
// elements not freed!
return -1;
}
// …
free(elements)
return 0;
}
正如我们所见,非常容易忘记释放内存。相比于现在,内存泄漏在过去是更加常见的问题。你只能通过修复代码才能真正的对付它们。因此,一个更好的方法是将回收不用的内存的工作自动化,整体消除可能产生的人为错误。这个自动化操作叫做垃圾回收(简称GC)。
智能指针
一种自动化操作的方式是通过使用析构函数。例如,我们使用C++中的向量vector做上一个例子中同样的事,它会在离开其作用域时自动的调用其析构函数:
int send_request() {
size_t n = read_size();
vector<int> elements = vector<int>(n);
if(read_elements(elements.size(), &elements[0]) < n) {
return -1;
}
return 0;
}
但是再更复杂的情况中,尤其是在多个线程中共享对象时,仅仅使用析构函数并不够。这就引出了垃圾回收最简单的形式:引用计数。对每个对象,你只需要知道它有多少次被引用到,并且当这个计数达到零时这个对象就可以安全的被回收。一个众所周知的例子是C++中的共享指针shared pointers:
int send_request() {
size_t n = read_size();
auto elements = make_shared<vector<int>>();
// read elements
store_in_cache(elements);
// process elements further
return 0;
}
现在,为了避免下次函数调用时再去读这个元素elements,我们可能想要缓存他们。在这个例子中,就不能再当向量vector离开作用域时销毁它。因此,我们使用共享指针shared_ptr,它记录引用到它的数量,当你使用它传值时计数增加,同时当它离开作用域时计数减少。一旦引用的计数降到零,共享指针shared_ptr就会自动地删除下面的向量。
TBC...
原文地址:https://www.cnblogs.com/pyx0/p/9222356.html