JVM重新认识(一)oop-klass模型--HSDB使用验证
一:oop-kclass模型
思考:我们平时写的java类编译成.class文件,JVM加载.class文件,那么加载.class文件之后在JVM中就是oop-kclass(C++)模型形式存在的。
JVM内部基于oop-klass模型描述一个java类,将一个java类分为两个部分进行描述,其中第一个模型是oop,第二个模型是klass.
oop: ordinary object pointer,也即普通对象指针.oop成员众多

这里有个问题,不是说xxxoop吗?怎么类图上怎么就是xxxppDesc了?
原因在于c++描述oop的层级关系时在 oopsHierarchy.hpp 中进行了如下定义:

typedef class oopDesc* oop;
typedef class instanceOopDesc* instanceOop;
typedef class methodOopDesc* methodOop;
typedef class constMethodOopDesc* constMethodOop;
typedef class methodDataOopDesc* methodDataOop;
typedef class arrayOopDesc* arrayOop;
typedef class objArrayOopDesc* objArrayOop;
typedef class typeArrayOopDesc* typeArrayOop;
typedef class constantPoolOopDesc* constantPoolOop;
typedef class constantPoolCacheOopDesc* constantPoolCacheOop;
typedef class symbolOopDesc* symbolOop;
typedef class klassOopDesc* klassOop;
typedef class markOopDesc* markOop;
typedef class compiledICHolderOopDesc* compiledICHolderOop;
其中各类的说明如下:
| 类名 | 说明 |
| oop | oop的顶级父类 |
| instanceOop | 表示java类实例 |
| methodOop | 表示java方法 |
| constMethodOop | 表示java方法中的只读信息(其实就是字节码指令) |
| methodDataOop | 表示性能统计的相关数据 |
| arrayOop | 数组对象,定义了数组oops的抽象基类 |
| objArrayOop | 表示引用类型数组对象 |
| typeArrayOop | 表示基本类型数组对象 |
| constantPoolOop | 表示java字节码文件中的常量池 |
| constantPoolCacheOop | 与constantPoolOop 相伴生,是后者的缓存对象,缓存了字段和方法的访问信息,为允许时环境快速访问字段和方法提供重要作用 |
| symbolOop | symbolOop是规范化字符串。所有symbolOop都位于全局符号表中。 |
| klassOop | 指向jvm内部的klass实例的对象 |
| markOop | oop 的标记对象,表示对象头 |
| compiledICHolderOop | 内联缓存实现的帮助器对象。它包含从编译到解释调用转换时使用的中间值(method+klass对),总是分配在永久区(以避免在清除期间遍历codecache) |
上面的一个类就是描述我们平常创建的Java实例:instanceOopDesc,对象在内存中的布局就是通过它来表示的,关于这一点可以参考之前写的关于
《关于Object=new Object();的美团六问》:https://blog.csdn.net/A7_A8_A9/article/details/105730007 的文章。
里面有个关于对象的内存图:

总结起来就是:
instanceOopDesc包含如下信息:
1. 对象头,也叫Mark Word,主要存储对象运行时记录信息,如hashcode, GC分代年龄,锁状态标志,线程ID,时间戳等;
2. 元数据指针class pointer,即指向方法区的instanceKlass实例 (虚拟机通过这个指针来群定这个对象是哪个类的实例。)
3. 实例数据 instance data;
4. 另外,如果是数组对象,还多了一个数组长度
5:对齐填充(有时候不需要)
klass
- klass 提供一个与java类对等的c++类型描述
- klass 提供虚拟机内部的函数分发机制
- jvm在加载class时,会创建instanceKlass,表示其元数据,包括常量池、字段、方法等,存放在方法区;instanceKlass是jvm中的数据结构;
在new一个对象时,jvm创建instanceOopDesc,来表示这个对象,存放在堆区,其引用,存放在栈区;它用来表示对象的实例信息,看起来像个指针实际上是藏在指针里的对象;instanceOopDesc对应java中的对象实例; - klass是在方法区的。
- 普通的Java类和数组用不同的kclass来表示,后面使用HSDB工具可以看到JVM运行时常量池中的Java实例存在的形式。

之间oop-klass之间的联系:

handle
除了oop,kclass外在JVM中还有一个东西handle:
handle 是对oop的行为的封装.这里需要注意的是:
- 大多数情况下,JVM在访问java类时是一定通过handle的_handle 来得到oop,再通过oop获得对应的klass,这样,handle就能够访问oop的函数了.
- 如果是调用JVM内部的c++类所对应的oop函数,则不需要通过handle,直接通过oop拿到指定的klass即可.
三者的关系如下:

vtable: 该类所有的函数(除了static, final)和 父类的函数虚拟表。
Itable: 该类所有实现接口的函数列表.
二:使用HSDB查看JVM中运行时的内容
HSDB是JDK自带的分析JVM的利器,运行方式在jdk安装目录/lib下有一个 sa-jdi.jar ,运行命令:java -cp sa-jdi.jar sun.jvm.hotspot.HSDB
注意项目上用的jdk和环境配置的jdk要一致,不然就要指定上面那个java是哪个jdk版本的。
运行完会打开如下界面:

用的测试例子如下:已经在运行

我们查看这个进程的id:

得到id之后,操作如下


把刚才的id cp进去点击ok

等待一会出现当前进程的线程栈:

选中main线程,点击Tool下的class browser

看到当前线程所涉及到的类,

@后面是地址,我们cp下TestLog的地址:

填入下面的位置回车:我们就可以看到在JVM中我们定义的TestLog其实是用InstanceKlass来表示的。
我们看到TestLog的Class在JVM中也是用Oop表示的。
1:HotSpot并不把instanceKlass暴露给Java,而会另外创建对应的instanceOopDesc来表示java.lang.Class对象,并将后者称为前者的“Java镜像”就是图中看到的'_java_mirror'属性。
2:InstanceKlass持有指向oop引用(_java_mirror便是该instanceKlass对Class对象的引用)。
3:new操作返回的是对instanceOopDesc类型的引用(在栈中),而instanceOopDesc指针(堆中)指向instanceKlass(方法区),而instanceKlass指向了对应的类型的Class实例的instanceOopDesc(就是那个_java_mirror)

JVM重新认识(一)oop-klass模型--HSDB使用验证的更多相关文章
- 【JVM】JVM内存结构 VS Java内存模型 VS Java对象模型
原文:JVM内存结构 VS Java内存模型 VS Java对象模型 Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清 ...
- 【转】JVM内存结构 VS Java内存模型 VS Java对象模型
JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途. 其中有些区域随着虚拟机进程的启动而 ...
- JVM内存结构 VS Java内存模型 VS Java对象模型
前面几篇文章中, 系统的学习了下JVM内存结构.Java内存模型.Java对象模型, 但是发现自己还是对这三者的概念和区别比较模糊, 傻傻分不清楚.所以就有了这篇文章, 本文主要是对这三个技术点再做一 ...
- 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念
本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...
- [转帖]JVM内存结构 VS Java内存模型 VS Java对象模型
JVM内存结构 VS Java内存模型 VS Java对象模型 https://www.hollischuang.com/archives/2509 Java作为一种面向对象的,跨平台语言,其对象.内 ...
- JVM 系列(二)内存模型
02 JVM 系列(二)内存模型 一.JVM 内存区域 JVM 会将 Java 进程所管理的内存划分为若干不同的数据区域.这些区域有各自的用途.创建/销毁时间: 一. 线程私有区域 线程私有数据区域生 ...
- JVM基础(1)——内存模型
转载:http://blog.csdn.net/weitry/article/details/53264262 系列文章规划: JVM基础(1)——内存模型 JVM基础(2)——内存管理 JVM基础( ...
- [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则
目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...
- asp.net core系列 45 Web应用 模型绑定和验证
一. 模型绑定 ASP.NET Core MVC 中的模型绑定,是将 HTTP 请求中的数据映射到action方法参数. 这些参数可能是简单类型的参数,如字符串.整数或浮点数,也可能是复杂类型的参数. ...
随机推荐
- JavaWeb基础总结:Servlet专题
最近工作中有部分整改老接口的任务,大部分与Spring的拦截器,Tomcat相关,改到一些底层的代码发现,对基础J2EE的知识有些遗忘,需要频繁查阅,索性从头系统的整理一下Servlet和Filter ...
- MySQL、DM 行转列及字段去重(Group_Concat())
最近在使用数据库迁移适配,由MySQL 库迁移到达梦数据库,其中进行行转列时,MySQL转换达梦sql语法有些问题,特记录. 在MySQL 下有Group_Concat(expr) ,在达梦及神通数 ...
- 版本控制比较cvs,svn,git
版本控制比较cvs,svn,git 几个重要概念: 版本库模型(Repository model):描述了多个源码版本库副本间的关系,有客户端/服务器和分布式两种模式.在客户端/服务器模式下,每一用户 ...
- 2021年第一个flag
2021年开始更新本文列出的系列文章,根据书籍和自己的理解整理出spring框架的相关的学习 Spring 的设计理念和整体架构 学习目标 Spring的各个子项目 Spring的设计目标 Sprin ...
- 仅4步,就可通过SQL进行分布式死锁的检测与消除
摘要:本文主要介绍在 GaussDB(DWS) 中,如何通过 SQL 语句,对分布式死锁进行检测和恢复. 分布式数仓应用场景中,我们经常遇到数据库系统 hang 住的问题,所谓 hang 是指虽然数据 ...
- Hadoop支持的压缩格式对比和应用场景以及Hadoop native库
对于文件的存储.传输.磁盘IO读取等操作在使用Hadoop生态圈的存储系统时是非常常见的,而文件的大小等直接影响了这些操作的速度以及对磁盘空间的消耗. 此时,一种常用的方式就是对文件进行压缩.但文件被 ...
- Redis学习之路(四)Redis-cluster java api操作
import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import java.util.Hash ...
- [Statistic] 置信度
背景 调研总体的情况时,常因调研成本等原因难以对总体情况逐一调研给出完全准确的结论.常以随机抽样的方式,通过统计样本估计总体. 单次随机抽样的结果可以看做是对总体结果的近似,但仍有不准确性.比如某次抽 ...
- 树莓派4B智能小车机器套件——入手组装实验记录
树莓派4B智能小车机器套件--入手组装实验记录 4WD智能小车(4WD SMART ROBOT KIT),支持Arduino.51.STM32.Raspberry Pi等4个版本.本套件采用的是树莓派 ...
- 【MySQL 高级】索引优化分析
MySQL高级 索引优化分析 SQL 的效率问题 出现性能下降,SQL 执行慢,执行时间长,等待时间长等情况,可能的原因有: 查询语句写的不好 索引失效 单值索引:在 user 表中给 name 属性 ...