Android技术知识Android技术进阶Android开发经验谈

Android内存结构解析——klass内存分布

2022-11-05  本文已影响0人  谁动了我的代码

.class文件

.class文件是编译.java文件生成的,即所谓的字节码文件。理论上说,不论是什么编程语言,只要经过编译器编译生成的文件符合class文件规范,都可以在JVM上正常运行。这也是如Groovy、Kotlin、Scala……这些语言能够在JVM上运行的本质原因。

想深入学习JVM,字节码文件是避不开的一个知识点。这块知识点相对JVM其他的知识点来说算比较简单的,想深入学习JVM的同学建议补下这块知识。如果你是在看不懂也没关系,我会在VIP课中深入讲解,手动模拟类加载器解析class文件的过程。

instanceKlass类

这是一个C++类,是Java类在JVM中的存在形式,是.class文件经过类加载器子系统加载后生成的。注意:这个类只是Java类在JVM中的存在形式,并不是Class对象。看核心代码

instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,

                                                    ClassLoaderData* loader_data,

                                                    Handle protection_domain,

                                                    KlassHandle host_klass,

                                                    GrowableArray<Handle>* cp_patches,

                                                    TempNewSymbol& parsed_name,

                                                    bool verify,

                                                    TRAPS) {

  ……

    // We can now create the basic Klass* for this klass

    _klass = InstanceKlass::allocate_instance_klass(loader_data,

                                                    vtable_size,

                                                    itable_size,

                                                    info.static_field_size,

                                                    total_oop_map_size2,

                                                    rt,

                                                    access_flags,

                                                    name,

                                                    super_klass(),

                                                    !host_klass.is_null(),

                                                    CHECK_(nullHandle));

    instanceKlassHandle this_klass (THREAD, _klass);

……     

instanceKlass是Klass类的子类,除了完全继承了Klass类的非私有属性外,自己又定义了很多属性用来描述Java类的信息,我们来看看这些属性(标成蓝色的是比较常见的):

Klass类

Klass类是Klass体系的基类,看下继承关系


从类名称上也能看出来,Klass相关类与元空间之间的关系。大多数情况下,Klass的子类是存储在元空间中的。正常情况下在C++中new一个对象,默认是在操作系统内存中的,JVM是如果实现在元空间中分配的呢?答案是重载C++的操作符new,是不是这样呢?看代码

void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data,

                                 size_t word_size, bool read_only,

                                 MetaspaceObj::Type type, TRAPS) throw() {

  // Klass has it's own operator new

  return Metaspace::allocate(loader_data, word_size, read_only,

                             type, CHECK_NULL);

}

Klass类有很多属性,我介绍几个重要的吧:

_layout_helper:如果这个Klass既不是instance也不是array,值为0,如果这个Klass是instance,值为对象的大小,如果这个Klass是array,值为负数。因为数组类型是运行时动态创建的,编译期无法知晓大小。

_java_mirror:这个Klass对于的镜像类的指针

Class对象

JVM并没有将描述Java类元信息的instanceKlass直接暴露给Java程序使用,而是又抽象了一层,即所谓的镜像类:instanceMirrorKlass。jdk8以后,类的静态属性也由存储在instanceKlass实例中转为存放在镜像类的实例中。详情见源码

instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,

                                                    ClassLoaderData* loader_data,

                                                    Handle protection_domain,

                                                    KlassHandle host_klass,

                                                    GrowableArray<Handle>* cp_patches,

                                                    TempNewSymbol& parsed_name,

                                                    bool verify,

                                                    TRAPS) {

……

    // Allocate mirror and initialize static fields

    java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle));

……  

oop java_lang_Class::create_mirror(KlassHandle k, Handle protection_domain, TRAPS) {

……

    Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0);

……

      // Initialize static fields

      InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL);

……

先看下第六行代码:初始化静态字段

再看下第三行代码调用的方法:allocate_instance

instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {

  // Query before forming handle.

  int size = instance_size(k);

  KlassHandle h_k(THREAD, this);

  instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL);

  return i;

}

从代码中可以看出来,是从堆区分配内存的。所以说Class对象是分配在堆上的。


以上就是Android虚拟机中内存结构klass内存解析;这是Android开发中的基础必备;更多Android进阶核心技术学习《Android核心进阶技术》可私:“手册”参与获取免费方式。

结语

总结一下,类加载器将.class文件载入JVM中,parse后生成的是instanceKlass对象,之后会生成这个Klass类对应的镜像类实例,并将Java类中的静态变量初始化后存储在镜像类实例中。这个镜像类就是我们Java代码中的Class对象。

上一篇 下一篇

猜你喜欢

热点阅读