转载

Java对象在JVM中长啥样

Java 是门面向对象的开发语言,那么我们自己编写的 Java 类生成的对象是什么样的?它肯定保存在虚拟机的内存中,但它以怎样的结构来保存的呢?带着疑问往下看看。

关于Klass

Java 层的开发可能不太熟悉 Klass,但肯定熟悉 class,我们只要知道 Klass 是 class 在 JVM 中的表示即可,即 Java class 对应 JVM Klass。C++ 中的继承关系如下:

class MetaspaceObj
    class Metadata
        class Klass

Klass 类用来描述 Java 类信息,包括描述类型自身布局、类名、父类、子类、兄弟类等等。

关于oop

按前面 class 对应的方式,那么对象也应该有 JVM 内部与之相对应的表示吧?没错,就是 oop(ordinary object pointer),普通对象指针。它的定义如下:

typedef class oopDesc*                            oop;

其中 oopDesc 类是所有 oop 的基类。在 JVM 中,不同的 oop 用于描述特定类型的对象。比如类对象用 instanceOopDesc,数组用 arrayOopDesc。

Klass+oop模型

Java 对象在 JVM 中的结构如下,包括 header 和对象内容。如下图中,左边的是 instanceOopDesc,即一般的类对象,header 包括了标识和元数据,标识用于存储运行时记录信息,包括哈希码、GC锁和线程锁等等。而右边的为 arrayOopDesc,即数组对象,header 多了个 length,用于记录数组长度。

Java对象在JVM中长啥样

来个demo

public class Test {

	private String[] flag = { "a", "b", "c" };
	private String name = "test";

	public static void main(String[] args) throws Exception {
		Test test = new Test();
		String _name = "test";
		System.out.println(test.flag);
		System.out.println(_name);
	}
}

对象结构

在上面程序中打个断点,通过 jps 查出 pid,然后使用下面命令打开 hsdb,根据 pid 连接到 JVM。

jhsdb hsdb
Java对象在JVM中长啥样

查看 main 线程的栈内存,我们主要是要拿到 Test 对象的地址,即 0x000000008a105dd0

Java对象在JVM中长啥样

接着用 inspector 来查看 0x000000008a105dd0 地址对应的 oop,看到这个 oop 就是我们的 Test 类生成的对象结构了,包含了 mark 和 metadata。这里可能会有个疑问,就是前面不是说数组还有一个 length 来表示数组长度的吗?但图中的 flag 数组变量并没有看到 length 啊。

Java对象在JVM中长啥样

其实数组 oop 并不是没有 length,而是 C++ 并没有声明这个变量,而是通过指针来直接将数组长度保存到对应的内存了,所以这里是看不到的。通过下面具体的实现代码就能清楚了解到原因了。是不是我们就没办法看到这个长度值呢?并不是,下面继续看如何来看这个值。

int length() const {
    return *(int*)(((intptr_t)this) + length_offset_in_bytes());
  }
  
void set_length(int length) {
    *(int*)(((intptr_t)this) + length_offset_in_bytes()) = length;
  }

前面我们可以得到 flag 数组 oop 的地址为 0x000000008a105de8 。64位机器上 _mark 为8字节, _metadata 为4字节,那么将地址加12,得到 0x000000008a105df4 。然后用 hsdb 命令行的 examine 得到地址的值,得到 0x8a105e0800000003 ,其中 00000003 便是。

hsdb> examine 0x000000008a105df4
0x000000008a105df4: 0x8a105e0800000003

-------------推荐阅读------------

我的2017文章汇总——机器学习篇

我的2017文章汇总——Java及中间件

我的2017文章汇总——深度学习篇

我的2017文章汇总——JDK源码篇

我的2017文章汇总——自然语言处理篇

我的2017文章汇总——Java并发篇

跟我交流,向我提问:

Java对象在JVM中长啥样

公众号的菜单已分为“读书总结”、“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。

为什么写《Tomcat内核设计剖析》

欢迎关注:

Java对象在JVM中长啥样
原文  https://juejin.im/post/5af632256fb9a07ab458b127
正文到此结束
Loading...