JVMTI开发教程之带引用关系的class柱状图
我们来看下上一节中的显示效果和本节例子的最终显示效果的异同:
Class统计信息柱状图
上图是上一节中例子中的显示效果。带引用关系的Class统计信息柱状图
上图是本节例子中的最终显示效果。可以看到,我们不仅可以获知某个class的实例数量,实例的总占用空间,以及class name。还能观察到class及其整棵引用树上的class的实例数量,空间,name等。
本节没有用到任何新的JVMTI函数。不过比起第二节,会基于更多函数的入参(上一节中,许多入参都是闲置)来实现本例子中的功能。
上一节中,我们了解到,通过FollowReference的jvmtiHeapReferenceCallback可以得到JVMTI函数从Heap root开始扫描其下存活对象的引用关系树,这个过程非常类似GC。
为了实现本例的功能,我们需要利用这个函数,记录它回报的引用关系,并加工就能得到一颗完整的引用关系树。
在记录引用关系的同时,我们还需要注意:
1,递归引用需要排除。比如 A类成员变量也是A类自身。
2,java.lang.Class不需要计算到引用关系中。我们知道任何一个class都有引用它。忽略它可以提高存储和计算效率。
3,节点的祖先不应该出现重复的节点。
比如 A- B- C- A,这里第四层的A就不应该出现在引用关系树上。否则会重复打印(A后面又是 B- C- A- B- C- A…)。
实现代码片段:
完整源码这份源码与上一节中的源码非常类似,主要是 heapFRCallback 函数里添加了引用关系的记录。打印结果的程序片段处,添加递归打印树的函数。此外就是添加了新的数据结构 Referrer 。
下面是完整的源码,copy,另存为,编译即可运行。
JVMTI Tutorial - jmap -histo include reference.Created on: 2011-3-3 Author: kenwu
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Referrer {
public:
Referrer() {
cls_id = 0;
next = NULL;
}
~Referrer() {
cls_id = 0;
delete next;
}
int cls_id;
Referrer *next;
};
class ClassInfo {
public:
ClassInfo() {
name = NULL;
cls_id = 0;
instance_cnt = 0;
instance_size = 0;
cls_obj_flag = 0;
referrer = NULL;
}
~ClassInfo() {
cls_id = 0;
free(name);
instance_cnt = 0;
instance_size = 0;
cls_obj_flag = 0;
delete referrer;
}
int cls_id;
char name;
int instance_cnt;
long instance_size;
int cls_obj_flag;
Referrer referrer;
};
ClassInfo *ci_map;
jvmtiEnv jvmti;
int seq;
int total_cls_size;
int depth = 5;
/**
解析class符号,抽取出class name并格式化。 @return class name/
char getClassName(jclass cls) {
int xl = 0;
char sig;
char data;
jvmti- GetClassSignature(cls, sig, NULL);
if (sig) { }
return data;
jint JNICALL heapFRCallback(jvmtiHeapReferenceKind reference_kind,
const jvmtiHeapReferenceInfo reference_info, jlong class_tag,
jlong referrer_class_tag, jlong size, jlong tag_ptr,
jlong referrer_tag_ptr, jint length, void user_data) {
// clean duplicate
int act_obj = 0;
if (tag_ptr == 0) { tag_ptr = ++seq;
act_obj = 1;
} else if (*tag_ptr cls_obj_flag == 0) {
ci- cls_obj_flag = 1;
act_obj = 1;
}
}
}
jint JNICALL untagCallback(jlong class_tag, jlong size, jlong tag_ptr,
jint length, void user_data) {
*tag_ptr = 0;
return JVMTI_VISIT_OBJECTS;
}
Referrer get_max(Referrer head) {
Referrer *max = head;
while (NULL != head) {
if (ci_map[head- cls_id]- instance_size
ci_map[max- cls_id]- instance_size) {
max = head;
}
head = head- next;
}
return max;
}
void sort_referrers(Referrer head) {
Referrer node = head, *tmp;
int value;
while (NULL != node) {
tmp = get_max(node);
if (node != tmp) {
value = node- cls_id;
node- cls_id = tmp- cls_id;
tmp- cls_id = value;
}
node = node- next;
}
}
bool allOnTree(Referrer *ci, set ref_tree) {
while (NULL != ci) {
if (ref_tree.find(ci- cls_id) == ref_tree.end()) {
return false;
}
ci = ci- next;
}
return true;
}
void printRefInfo(ClassInfo ci, int level, set ref_tree,
set grade_format) {
if (++level = depth)
return;
ref_tree.insert(ci- cls_id);
Referrer referrer = ci- referrer;
sort_referrers(referrer);
int max = 0;
while (referrer != NULL) {
ClassInfo *c1 = ci_map[referrer- cls_id];
if (max++ cls_id) == ref_tree.end()) {
string strbuf(“”);
}
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM jvm, char options,
void reserved) {
/*
}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
// nothing to do
}
本文来源于"阿里中间件团队播客",原文发表时间" 2011-03-17 "
第四章 对象与类 用户自定义类 注意在所有方法中都不要命名与实例域同名的变量 final修饰的大都是基本类型或不可变类的域, 可变类用final休息容易造成混乱 静态类和方法 final修饰的域可以是public的; NumberFormat使用工厂方法生成实例; 不用构造函数实例化的原因是(1)无法命名构造器...
相关文章
- Knockout 新版应用开发教程之创建view models与监控属性
- H3C交换机网线开局教程-无Console线开局
- 【OpenCV-Python】教程:8-2 图像修复 Image Inpainting
- H7-TOOL的LUA小程序教程第4期:I2C总线开发(2022-01-13)
- 【STM32H7教程】第12章 STM32H7的HAL库框架设计学习
- SAP UI5 应用开发教程之十三番外篇 - SAP UI5 应用的暗黑模式 - Fiori 3 Quartz Dark 主题的使用
- SAP UI5 应用开发教程之一百零七 - SAP UI5 OverflowToolbar 容器控件介绍的试读版
- SAP UI5 应用开发教程之八十三 - SAP UI5 的自动化测试套件页面的开发步骤介绍试读版
- SAP UI5 应用开发教程之七十五 - 如何采用SAP UI5 主从表格的联动技术显示复杂表格内容试读版
- [转]Android开发环境搭建(图文教程)
- 最简单的SAP云平台开发教程 - 如何开发UI5应用并运行在SAP云平台上
- SAP UI5 应用开发教程之三十九 - SAP UI5 应用出现白屏的一些常见错误和分析方法分享试读版
- SAP UI5 应用开发教程之七十七 - SAP UI5 动态页面路由的高级用法:路由记录 routes 和 target 的一对多关系试读版
- SAP UI5 应用开发教程之六十一 - 在 SAP UI5 应用里绘制甘特图 Gantt Chart 试读版
- 幼儿园小程序实战开发教程(中篇)
- 腾讯云低代码开发实战教程-布局的实现
- QT开发教程:单播、广播、组播
- 小熊派IoT开发板系列教程正式发布——免费学习
- DevExpress2011控件教程)编辑控件(comboBox,AspxCheckBox) 范例1
- 《Kotlin极简教程》第七章 Kotlin 集成 Springboot开发WebApp
- 【Mac 教程系列】Mac 实用命令大全
- windows安装mongodb服务简洁版教程
- ExtJs自学教程(1):一切从API開始
- 随笔教程:FastAdmin 如何打开新的标签页
- 微信公众平台开发教程(一) 微信公众账号注册流程
- 虚拟机下安装CentOS6.5系统教程
- 加油站会员管理小程序实战开发教程10