这里主要研究虚拟机对于用户定义的class的处理,对应于 InstanceKlass相关代码
ClassState
按照ClassState这个枚举可以知道有以下几种状态
卸载
虽然在<加密Java虚拟机>中提到类的生命周期还有卸载,但是根据继承关系可以知道InstanceKlass是继承MetaspaceObj,而allocation.hpp里对于MetaspaceObj的delete操作定义如下,看上去这些对象不会被删除
void operator delete(void* p) { ShouldNotCallThis(); }
调用链路
使用 \bnew.*\bInstanceKlass\( 做正则表达式搜索可以发现只有一个地方调用了InstanceKlass的构造方法,那就是InstanceKlass::allocate_instance_klass这个静态方法
allocate
根据下面代码可以看出可能allocate_instance_klass创建父类,也可能是创建子类,这个和继承关系保持一致
InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
bool is_hidden_or_anonymous = parser.is_hidden() || parser.is_unsafe_anonymous();
const int size = InstanceKlass::size(parser.vtable_size(),
parser.itable_size(),
nonstatic_oop_map_size(parser.total_oop_map_count()),
parser.is_interface(),
parser.is_unsafe_anonymous(),
should_store_fingerprint(is_hidden_or_anonymous));
const Symbol* const class_name = parser.class_name();
assert(class_name != NULL, "invariant");
ClassLoaderData* loader_data = parser.loader_data();
assert(loader_data != NULL, "invariant");
InstanceKlass* ik;
// Allocation
if (REF_NONE == parser.reference_type()) {
if (class_name == vmSymbols::java_lang_Class()) {
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(parser);
}
else if (is_class_loader(class_name, parser)) {
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);
} else {
ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_kind_other);
}
} else {
ik = new (loader_data, size, THREAD) InstanceRefKlass(parser);
}
// Check for pending exception before adding to the loader data and incrementing
// class count. Can get OOM here.
if (HAS_PENDING_EXCEPTION) {
return NULL;
}
return ik;
}
new
注意里面的new和构造函数之间的括号,这里使用了C++的操作符重载,而对于new的重载最典型的应用是placement new,也就是在指定的内存地址创建对象,而这里不完全是.jvm中对于这个new操作的重载定义在allocation.cpp
void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,
size_t word_size,
MetaspaceObj::Type type, TRAPS) throw() {
// Klass has it's own operator new
return Metaspace::allocate(loader_data, word_size, type, THREAD);
}
所以即使new作为关键字,也可以像一个函数一样去定义.在这里可以把构造对象时**new SomeType(someArgs)看作是对new(class SomeType,void* someArgs)**方法的调用.这这个方法的实现可以分为以下几步
SomeType *new(class SomeType,void* someArgs){
size_t size=sizeof(SomeType); //获取需要内存大小
void* out=alloc(size); //向OS申请内存,对于replacement new可以复用已有内存
(void *f(void*)) constructor=SomeType.constructor();//获取构造函数
constructor.apply(out,someArgs); //调用构造函数完成初始化
return out;
}
InstanceKlass::InstanceKlass
InstanceKlass.hpp
InstanceKlass的构造方法在instanceKlass.hpp中,代码如下
public:
static const KlassID ID = InstanceKlassID;
...
protected:
InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id = ID);
public:
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
看上去上面使用了默认参数,至于InstanceKlassID的值是定义在KlassID中的枚举,代码如下
// Klass IDs for all subclasses of Klass
enum KlassID {
InstanceKlassID,
InstanceRefKlassID,
InstanceMirrorKlassID,
InstanceClassLoaderKlassID,
TypeArrayKlassID,
ObjArrayKlassID
};
const uint KLASS_ID_COUNT = 6;
InstanceKlass.cpp
至于InstanceKlass的构造方法的代码如下所示.
InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id) :
Klass(id),
_nest_members(NULL),
_nest_host(NULL),
_permitted_subclasses(NULL),
_record_components(NULL),
_static_field_size(parser.static_field_size()),
_nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
_itable_len(parser.itable_size()),
_nest_host_index(0),
_init_state(allocated),
_reference_type(parser.reference_type()),
_init_thread(NULL)
{
set_vtable_length(parser.vtable_size());
set_kind(kind);
set_access_flags(parser.access_flags());
if (parser.is_hidden()) set_is_hidden();
set_is_unsafe_anonymous(parser.is_unsafe_anonymous());
set_layout_helper(Klass::instance_layout_helper(parser.layout_size(),
false));
assert(NULL == _methods, "underlying memory not zeroed?");
assert(is_instance_klass(), "is layout incorrect?");
assert(size_helper() == parser.layout_size(), "incorrect size_helper?");
// Set biased locking bit for all instances of this class; it will be
// cleared if revocation occurs too often for this type
if (UseBiasedLocking && BiasedLocking::enabled()) {
set_prototype_header(markWord::biased_locking_prototype());
}
}
上面使用了一种称之为初始化列表的cpp特性.