hotsport源码分析_hotspot20

hacker|
88

文章目录:

如何查看 HotSpot VM 的运行时数据

首页

所有文章

资讯

Web

架构

基础技术

书籍

教程

Java小组

工具资源

如何查看HotSpot VM的运行时数据

2016/09/27 | 分类: 基础技术 | 0 条评论 | 标签: HSDB, JVM

分享到:11

原文出处: 占小狼

本文将借助HSDB工具分析HotSpot VM的运行时数据,运行的java环境为jdk1.8。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

class Test {

static String version = "1.0";

String name;

int id;

Test(String name, int id) {

this.name = name;

this.id = id;

}

static void fn() {}

void fn2(){}

}

public class Main {

static Test t1 = new Test("java", 1);

private Test t2 = new Test("java", 2);

public void fn() {

Test t3 = new Test("java", 3);

}

public static void main(String[] args) {

new Main().fn();

}

}

运行上述代码,会在Java堆中生成3个Test对象,变量t1,t2,t3分别存储在方法区、实例字段和局部变量表中,那么Test对象的内存是如何布局的呢?

在查看运行时数据之前,需要让程序刚好执行完new Main().fn();并暂停,平时可能习惯了在Eclipse、IntelliJ IDEA、NetBeans等Java IDE里使用Java层调试器,但为了减少对外部工具的依赖,本文将使用Oracle JDK自带的jdb工具来完成此任务。

jdb使用步骤如下:

1、jdb -XX:+UseSerialGC -Xmx10m命令启动jdb;

2、stop in Main.fn命令指定在方法入口设置断点;

3、run Main命令指令主类,启动java程序;

4、next命令可以向前执行一步;

采用jps命令查看目前调试java程序的PID

采用命令java -cp sa-jdi.jar sun.jvm.hotspot.HSDB启动HSDB工具,并连接到目标进程上,注意:Windows上Oracle JDK7才可以用HSDB。

连接上之后

默认窗口是Java Threads,显示当前进程的线程列表,双击线程打开一个Oop Inspector窗口,显示该线程在HotSpot VM的对象。

在菜单里选择Windows - Console,打开HSDB里的控制台,用命令查看更多信息。

1、命令universe查看GC堆的大小、地址范围和使用情况;

1

2

3

4

5

6

7

hsdb universe

Heap Parameters:

Gen 0: eden [0x00000000ff600000,0x00000000ff6d50a0,0x00000000ff8b0000) space capacity = 2818048, 30.964980014534884 used

from [0x00000000ff8b0000,0x00000000ff8b0000,0x00000000ff900000) space capacity = 327680, 0.0 used

to [0x00000000ff900000,0x00000000ff900000,0x00000000ff950000) space capacity = 327680, 0.0 usedInvocations: 0

Gen 1: old [0x00000000ff950000,0x00000000ff950000,0x0000000100000000) space capacity = 7012352, 0.0 usedInvocations: 0

可以发现HotSpot在1.8的Java堆中,已经去除了Perm gen区,由youyoung gen和old gen组成。

2、命令scanoops查看指定类型的实例对象,接受两个必选参数和一个可选参数:必选参数是要扫描的地址范围,一个是起始地址一个是结束地址;可选参数用于指定要扫描什么类型的实例对象;

hsdb scanoops 0x00000000ff600000 0x0000000100000000 Test

0x00000000ff6caf08 Test

0x00000000ff6caf40 Test

0x00000000ff6caf58 Test

通过执行结果可以看出,Java堆上的确有3个Test实例对象,对象的开始地址分别为0x00000000ff6caf08、0x00000000ff6caf40和0x00000000ff6caf58。

JVM和Java HotSpot如何区分版本

你的虚拟机(JVM)版本是23.5-b02

java -version出来信息包含两部分:Java软件包发行版本信息和内核(JVM)版本信息。

java的发行包包含三种类型Java ME,Java SE,Java EE,发行包就相当于对外销售的产品包,不同发行包会删减部分特性,因此版本信息首先显示发行包类型和版本。

JVM是Java平台的基础和核心,一般在一个java大版本中JVM版本变化都是比较小的。HotSpot是一种JVM实现技术,相对以往的方式在性能和扩展能力上得到了很大的提升,因此它不是一个独立产品,可以理解Sun(Oracle)实现的JVM版本的品牌商标。

数据挖掘中的Hotspot关联规则

提到关联规则算法,一般会想到Apriori或者FP,一般很少有想到HotSpot的,这个算法不知道是应用少还是我查资料的手段太low了,在网上只找到很少的内容,这篇 ,大概分析了一点,其他好像就没怎么看到了。比较好用的算法类软件,如weka,其里面已经包含了这个算法,在Associate-- HotSpot里面即可看到,运行算法界面一般如下:

其中,红色方框里面为设置的参数,如下:

-c last ,表示目标所在的目标所在的列,last表示最后一列,也是是数值,表示第几列;

-V first, 表示目标列的某个状态值下标值(这里可以看出目标列应该是离散型),first表示第0个,可以是数值型;

-S 0.13,最小支持度,里面会乘以样本总数得到一个数值型的支持度;

-M 2 , 最大分指数;

-I 0.01 , 在weka里面解释为Minimum improvement in target value,不知道是否传统的置信度一样;

相关说明:本篇相关代码参考weka里面的HotSpot算法的具体实现,本篇只分析离散型数据,代码可以在()下载。

1. 数据:

@attribute age {young, pre-presbyopic, presbyopic}

@attribute spectacle-prescrip {myope, hypermetrope}

@attribute astigmatism {no, yes}

@attribute tear-prod-rate {reduced, normal}

@attribute contact-lenses {soft, hard, none}

young,myope,no,reduced,none

young,myope,no,normal,soft

young,myope,yes,reduced,none

。。。

presbyopic,hypermetrope,yes,normal,none

这个数据格式是参考weka里面的,加入最前面的5行是因为需要把各个属性进行编码,所以提前拿到属性的各个状态,方便后续操作;

2. 单个节点定义:

public class HSNode {

private int splitAttrIndex; // 属性的下标

private int attrStateIndex; // 属性state的下标

private int allCount ; // 当前数据集的个数

private int stateCount ; // 属性的state的个数

private double support; // 属性的支持度

private ListHSNode chidren;

public HSNode(){}}

splitAttrIndex 即对应属性astigmatism的下标(应该是第2个,从0开始);attrStateIndex 则对应这个属性的下标,即no的下标(这里应该是0);allCount即12,stateCount即5,support 对应41.57%(即5/12的值);children即其孩子节点;(这里的下标即是从文件的前面几行编码得到的,比如属性age为第一个属性,编码为0,young为其第一个状态,编码为0);

3. 算法伪代码,(文字描述,太不专业了,如果要看,就将就看?)

1. 创建根节点;

2. 创建孩子节点;

2.1 针对所有数据,计算每列的每个属性的’支持度‘support,

if support= MINSUPPORT

把该列的当前属性加入潜在的孩子节点列表;

end

2.2 针对潜在孩子节点列表遍历

if (!当前节点产生的规则序in全局规则序列)

把当前节点加入孩子节点列表;

把当前节点产生的规则加入全局规则中;

end

2.3 遍历孩子节点列表

针对当前节点,返回到2,进行递归;

4. 代码关键步骤具体实现:

4.1 数据读取及初始化:

1) 读取文件的前面几行,初始化两个变量,attributes和attributeStates ,分别对应所有的属性和属性的各个状态;

while ((tempString = reader.readLine()) != null) {

// 第一行数据是标题

if(tempString.indexOf(HSUtils.FILEFORMAT)==0){

String attr = tempString.substring(HSUtils.FILEFORMAT.length()

, tempString.indexOf("{")).trim();

String[] attrStates =tempString.substring(tempString.indexOf("{")+1,

tempString.indexOf("}")).split(",");

for(int i=0;iattrStates.length;i++){

attrStates[i]=attrStates[i].trim();

}

attrList.add( attr);

line++;

this.attributeStates.put(attr, attrStates);

continue;

}

if(flag){

this.attributes= new String[line];

attrList.toArray(this.attributes);// 复制值到数组中

flag=false;

}

String[] tempStrings = tempString.split(splitter);

lists.add(strArr2IntArr(tempStrings));

}

2) 后面就是把下面的数据转为数值型数组了,strArr2IntArr 函数如下:

/**

* String 数组转为int数组

* @param sArr

* @return

* @throws Exception

*/

private int[] strArr2IntArr(String[] sArr) throws Exception{

int[] iArr = new int[sArr.length];

for(int i=0;isArr.length;i++){

iArr[i]= getAttrCode(sArr[i],i);

}

return iArr;

}

/**

* 获得第attrIndex属性的attrState的编码

* @param attrState

* @param attrIndex

* @return

* @throws Exception

*/

private int getAttrCode(String attrState,int attrIndex) throws Exception{

String[] attrStates = attributeStates.get(attributes[attrIndex]);

for(int i=0;iattrStates.length;i++){

if(attrState.equals(attrStates[i])){

return i;

}

}

throw new Exception("编码错误!");

// return -1; // 如果运行到这里应该会报错

}

这里数据读取主要是把离散型的字符串类型数据转换为数值型数据,编码规则如下:

属性age的状态: [young--0,pre-presbyopic--1,presbyopic--2,]

属性spectacle-prescrip的状态: [myope--0,hypermetrope--1,]

属性astigmatism的状态: [no--0,yes--1,]

属性tear-prod-rate的状态: [reduced--0,normal--1,]

属性contact-lenses的状态: [soft--0,hard--1,none--2,]

4.2 初始化根节点

// 读取文件并赋值

Listint[] intData = readFileAndInitial(HSUtils.FILEPATH,HSUtils.SPLITTER);;

int splitAttributeIndex = attributes.length-1;// 下标需减1

int stateIndex = HSUtils.LABELSTATE;

int numInstances = intData.size();// 数据总个数

int[] labelStateCount = attrStateCount(intData,attributes.length-1);

HSUtils.setMinSupportCount(numInstances);

double targetValue=1.0*labelStateCount[HSUtils.LABELSTATE]/numInstances;

// 创建根节点

HSNode root = new HSNode(splitAttributeIndex,stateIndex,labelStateCount[stateIndex],numInstances);

double[] splitVals=new double[attributes.length];

byte[] tests = new byte[attributes.length];

root.setChidren(constructChildrenNodes(intData,targetValue,splitVals,tests));

labelStateCount即目标属性的各个状态的个数,比如这里目标状态为soft,一共有5个值,一共有24个样本,所以其支持度为5/25=20.82%;

constructChildrenNodes函数为创建所有子节点,接收的参数有:intData:所有的数据(经过编码的);targetValue:当前节点支持度;splitVals和tests数组主要用于针对节点产生规则;

4.3 创建孩子节点:

1) 计算潜在孩子节点:

private ListHSNode constructChildrenNodes(Listint[] intData,double targetValue,

double[] splitVals,

byte[] tests) {

// 设置孩子节点

// // 获取子数据集

//

// 针对每个属性的每个state值计算其支持度(需要符合置信度)

PriorityQueueAttrStateSup pq = new PriorityQueueAttrStateSup();

for(int i=0;iattributes.length-1;i++){// 最后一个属性不用计算(为Label)

evaluateAttr(pq,intData,i,targetValue);

}

这里的evaluateAttr主要是判断每个属性的各个状态是否符合要求,是则加入pq

/**

* 是否把第attrIndex属性的state作为备选节点加入pq

* @param pq

* @param intData

* @param attrIndex

* @param targetValue

* @param stateIndex

* @param labelStateCount

*/

private void evaluateAttr(PriorityQueueAttrStateSup pq,

Listint[] intData, int attrIndex, double targetValue) {

int[] counts = attrStateCount(intData,attrIndex);

boolean ok = false;

// only consider attribute values that result in subsets that meet/exceed min support

for (int i = 0; i counts.length; i++) {

if (counts[i] = HSUtils.getMinSupportCount()) {

ok = true;

break;

}

}

if(ok){

double subsetMatrix =0.0;

for(int stateIndex=0;stateIndexcounts.length;

stateIndex++){

subsetMatrix =attrStateCount(intData,attrIndex,stateIndex,attributes.length-1,HSUtils.LABELSTATE);

if(counts[stateIndex]=HSUtils.getMinSupportCount()subsetMatrix=HSUtils.getMinSupportCount()){

double merit = 1.0*subsetMatrix / counts[stateIndex]; //

double delta = merit - targetValue;

if(delta/targetValue=HSUtils.MINCONFIDENCE){

pq.add(new AttrStateSup(attrIndex,stateIndex,counts[stateIndex],(int)subsetMatrix));

}

}

}

}// ok

}

这里首先针对当前数据集计算属性下标为attrIndex的各个状态的计数到counts[]数组中;如果各个状态的所有计数都小于最小支持度,则该属性都不作为备选加入pq中;否则继续判断:计算目标属性的设定状态(比如soft)和当前属性的状态(young)共同出现的次数(第一次应该是2),赋值给subsetMatrix(那么该值就是2);判断subsetMatrix是否=最小支持度,如果是在按照上面的代码进行计算,最后还有个判断是用到置信度的(暂译为置信度),如果满足则把其加入到pq中,即备选子节点列表;

2)生成全局规则,并添加孩子节点

ListHSNode children = new ArrayListHSNode();

ListHotSpotHashKey keyList = new ArrayListHotSpotHashKey();

while(pq.size()0children.size()HSUtils.MAXBRANCH){

AttrStateSup attrStateSup = pq.poll();

// 再次进行过滤

double[] newSplitVals = splitVals.clone();

byte[] newTests = tests.clone();

newSplitVals[attrStateSup.getAttrIndex()]=attrStateSup.getStateIndex()+1;

newTests[attrStateSup.getAttrIndex()] =(byte)2;

HotSpotHashKey key = new HotSpotHashKey(newSplitVals, newTests);

if (!HSUtils.m_ruleLookup.containsKey(key)) {

// insert it into the hash table

HSUtils.m_ruleLookup.put(key, ""); // 需要先增加规则,然后才处理子节点

HSNode child_i= new HSNode(attrStateSup.getAttrIndex(),attrStateSup.getStateIndex(),

attrStateSup.getStateCount(),attrStateSup.getAllCount());

keyList.add(key);

children.add(child_i);

} else {

System.out.println("The potential ,but not included :"+attrStateSup);

}

}

这里的全局规则使用HotSpotHashKey生成,具体规则的含义没有理解(可能和算法原理有关,都找不到一篇相关的paper!)

添加一个节点后,就会添加相应的规则,这样可以避免孩子节点的孩子有相同的规则被重复添加;

3) 针对每个孩子节点,处理其节点的孩子

// 处理子节点

for(int i=0;ichildren.size();i++){

HSNode child = children.get(i);

child.setChidren(constructChildrenNodes(getSubData(intData,child.getSplitAttrIndex(),

child.getAttrStateIndex()),child.getSupport(),keyList.get(i).getM_splitValues(),

keyList.get(i).getM_testTypes()));

}

这里使用递归进行调用,方便处理。需注意节点规则的生成使用的两个数组newSplitValues 和newTests需要往下传递,所以在每个孩子节点生成规则的时候把其加入到一个keyList,这样在遍历孩子节点,处理其节点的孩子时,可以找到对应的规则传递数组;

这里的getSubData即是找到当前数据集中和给定的属性下标即属性状态一样的数据返回,如下:

/**

* 获取和splitAttributeIndex相同下标的属性以及stateIndex的所有数据

* @param intData

* @param splitAttributeIndex

* @param stateIndex

* @return

*/

private Listint[] getSubData(Listint[] intData,

int splitAttributeIndex, int stateIndex) {

Listint[] subData = new ArrayListint[]();

for(int[] d:intData){

if(d[splitAttributeIndex]==stateIndex){

subData.add(d);

}

}

return subData;

}

4.4 打印规则树

/**

* 打印规则树

* @param node

* @param level

*/

public void printHSNode(HSNode node,int level){

printLevelTab(level);

System.out.print(node+"\n");

ListHSNode children= node.getChidren();

for(HSNode child:children){

printHSNode(child,level+1);

}

}

private void printLevelTab(int level) {

for(int i=0;ilevel;i++){

System.out.print("|\t");

}

}

这里可以看到针对当前节点,使用直接打印的方式,因为这里覆写了toString方法,所以可以这样,其toString 方法如下:

/**

* 格式化输出

*/

public String toString(){

return HSUtils.getAttr(this.splitAttrIndex)+"="+HSUtils.getAttrState(splitAttrIndex, attrStateIndex)

+" ("+HSUtils.formatPercent(this.support)+" ["+this.stateCount+"/"+this.allCount+"])";

}

4.5 算法调用:

package fz.hotspot;

import fz.hotspot.dataobject.HSNode;

public class HotSpotTest {

/**

* @param args

* @throws Exception

*/

public static void main(String[] args) throws Exception {

String file = "D:/jars/weka-src/data/contact-lenses.txt";

int labelStateIndex = 0; // 目标属性所在下标

int maxBranches=2; // 最大分支数目

double minSupport =0.13; // 最小支持度

double minConfidence=0.01;// 最小置信度(在weka中使用的是minImprovement)

HotSpot hs = new HotSpot();

HSNode root = hs.run(file,labelStateIndex,maxBranches,minSupport,minConfidence);

System.out.println("\n规则树如下:\n");

hs.printHSNode(root,0);

}

}

打印的规则树如下:

contact-lenses=soft (20.83% [5/24])

| astigmatism=no (41.67% [5/12])

| | tear-prod-rate=normal (83.33% [5/6])

| | | spectacle-prescrip=hypermetrope (100.00% [3/3])

| | spectacle-prescrip=hypermetrope (50.00% [3/6])

| tear-prod-rate=normal (41.67% [5/12])

| | spectacle-prescrip=hypermetrope (50.00% [3/6])

可以看到和weka给出的是一致的。

最近在看《暗时间》,上面提到说有想法最好写下来,这样不仅可以加深自己的理解,同时在写的过程中,比如一些表达之类的 也可以加强(身为程序员,这方面的能力确实欠缺),同时也可以让别人检验到自己的思维盲点。

文中相关算法理解,仅代表自己观点。

分享,成长,快乐

脚踏实地,专注

转载请注明blog地址:

文章最后发布于: 2015-03-10

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:

展开全文

Hotspot的源码应该怎样阅读

如果你下的只是HotSpot VM的代码的话那好办,Oracle JDK 6/Oracle JDK 7/OpenJDK 6/OpenJDK 7里的HotSpot VM基本上目录结构都是一样的。

├—agent Serviceability Agent的客户端实现

├—make 用来build出HotSpot的各种配置文件

├—src HotSpot VM的源代码

│ ├—cpu CPU相关代码(汇编器、模板解释器、ad文件、部分runtime函数在这里实现)

│ ├—os 操作系相关代码

│ ├—os_cpu 操作系统+CPU的组合相关的代码

│ └—share 平台无关的共通代码

│ ├—tools 工具

│ │ ├—hsdis 反汇编插件

│ │ ├—IdealGraphVisualizer 将server编译器的中间代码可视化的工具

│ │ ├—launcher 启动程序“java”

│ │ ├—LogCompilation 将-XX:+LogCompilation输出的日志(hotspot.log)整理成更容易阅读的格式的工具

│ │ └—ProjectCreator 生成Visual Studio的project文件的工具

│ └—vm HotSpot VM的核心代码

│ ├—adlc 平台描述文件(上面的cpu或os_cpu里的*.ad文件)的编译器

│ ├—asm 汇编器接口

│ ├—c1 client编译器(又称“C1”)

│ ├—ci 动态编译器的公共服务/从动态编译器到VM的接口

│ ├—classfile 类文件的处理(包括类加载和系统符号表等)

│ ├—code 动态生成的代码的管理

│ ├—compiler 从VM调用动态编译器的接口

│ ├—gc_implementation GC的实现

│ │ ├—concurrentMarkSweep Concurrent Mark Sweep GC的实现

│ │ ├—g1 Garbage-First GC的实现(不使用老的分代式GC框架)

│ │ ├—parallelScavenge ParallelScavenge GC的实现(server VM默认,不使用老的分代式GC框架)

│ │ ├—parNew ParNew GC的实现

│ │ └—shared GC的共通实现

│ ├—gc_interface GC的接口

│ ├—interpreter 解释器,包括“模板解释器”(官方版在用)和“C++解释器”(官方版不在用)

│ ├—libadt 一些抽象数据结构

│ ├—memory 内存管理相关(老的分代式GC框架也在这里)

│ ├—oops HotSpot VM的对象系统的实现

│ ├—opto server编译器(又称“C2”或“Opto”)

│ ├—prims HotSpot VM的对外接口,包括部分标准库的native部分和JVMTI实现

│ ├—runtime 运行时支持库(包括线程管理、编译器调度、锁、反射等)

│ ├—services 主要是用来支持JMX之类的管理功能的接口

│ ├—shark 基于LLVM的JIT编译器(官方版里没有使用)

│ └—utilities 一些基本的工具类

└—test 单元测试

你看到的目录结构应该是类似这样的

如何 成为 hotspot jdk9 源码 贡献者

根据《中国红十字志愿服务管理办法》第二条 红十字志愿服务是不以营利为目的,由各级红十字会组织和红十字志愿者参与,完全自愿为社会和他人提供人道服务的行为。第三条 在红十字志愿服务组织登记注册,参加红十字志愿服务活动,不以获得报酬为目的,以自己的时间、知识、技能、体能和资源,自愿为社会和他人提供人道服务或者协助红十字会工作的中国公民和海外人士,统称为红十字志愿者。不足18岁的青少年参加红十字志愿服务,应征得监护人同意。志愿服务时间每年累计达到20小时的志愿者,经申请即成为注册红十字志愿者。根据《中国红十字志愿者登记注册管理制度》 一、红十字志愿者登记注册采取属地、工作和业务领域管理相结合的管理方法。申请参加红十字志愿服务活动的各界人士,可以通过所在地红十字会、红十字会基层组织及红十字会网站申请登记。三、个人申请加入红十字志愿者,应填写《中国红十字志愿者登记表》,对相关情况进行登记,并在所在地红十字会备案,经报县及县以上红十字志愿服务工作委员会批准后,配发红十字志愿者证、中国红十字志愿服务卡和服饰,即成为红十字志愿者。——由以上条文可知,如果学校有红十字组织(一般在医务室),可去那里报名。如果没有,可到所在乡镇(街道)的红十字会咨询报名。

java学习书籍有哪些比较好?

Thinking in java

这个就不用说了,世界都知道

...

java与模式\深入java虚拟机第二版\Java数据结构和算法中文第二版 都是很经典的书,后面一点的,看书都没用,去找视频或者直接找例子来看,进步更快,

1条大神的评论

  • avatar
    访客 2022-07-09 下午 12:09:37

    添加;3) 针对每个孩子节点,处理其节点的孩子// 处理子节点 for(int i=0;ichildren.size();i++){ HSNode child = children

发表评论