在ClassLoader::load_classfile中,下面的代码引起了我的注意。
ClassFileStream* stream = NULL;
int classpath_index = 0;
{
PerfTraceTime vmtimer(perf_accumulated_time());
ClassPathEntry* e = _first_entry;
while (e != NULL) {
stream = e->open_stream(name);
if (stream != NULL) {
break;
}
e = e->next();
++classpath_index;
}
上面的open_stream其实就是返回一个指针。
{
return new ClassFileStream(buffer, filesize, _zip_name);
}
但这个ClassFileStream指针,看到存在new却没有看到delete操作。众所周知,new操作应该与delete配套使用,要不会产生内存的泄露。难道sun公司的那群大牛们会犯这么明显的错误?
仔细看看ClassFileStream的实现,它继承于ResourceObj
class ClassFileStream: public ResourceObj {
.....
}
再看ResourceObj ,它重载了new 和delete操作。
void* ResourceObj::operator new(size_t size) {
address res = (address)resource_allocate_bytes(size);
DEBUG_ONLY(((ResourceObj *)res)->_allocation = RESOURCE_AREA;)
return res;
}
再看resource_allocate_bytes代码
extern char* resource_allocate_bytes(Thread* thread, size_t size) {
return thread->resource_area()->allocate_bytes(size);
}
到此,可以猜想得到继承于ResourceObj的对象是存放在一个叫ResourceArea的地方,这个区域属于thread对象,在thread对象创建的时候创建,随着thread对象的捣毁而捣毁。
看看thread的构造函数
Thread::Thread() {
.....
set_resource_area(new ResourceArea()); //构建ResourceArea
.....
}
再看thread的析构函数
Thread::~Thread() {
....
delete resource_area(); //捣毁ResourceArea
....
}
由上面可以看出,整个ResourceArea就象是线程对象的线程局部存储一样,在整个对象的生命周期,继承于ResourceObj的对象都会存在。但象上面的ClassFileStream指针,由于没有采用delete,故它的析构函数是不会调用的(其实ClassFileStream就没有定义析构函数)