Java 对象内存模型系列-2nd

知行合一:知之真切笃实处即是行,行之明觉精察处即是知。

上一篇文章中我们搞明白对象的组成及其所占内存大小。口说无凭,事实为证。有些朋友希望能亲自验证结论是否正确。

安排,今天他来了

在这里插入图片描述

一. JOL(Java Object Layout)


1.1 JOL(Java Object Layout)的简介

深入了解的请移步至:JOL的官方地址

引用其介绍的一段话:
JOL (Java Object Layout) is the tiny toolbox to analyze object layout schemes in JVMs. These tools are using Unsafe, JVMTI, and Serviceability Agent (SA) heavily to decoder the actual object layout, footprint, and references. This makes JOL much more accurate than other tools relying on heap dumps, specification assumptions, etc.

大致意思就是:JOL是是分析JVM中对象布局方案的小工具箱。由于大量使用Unsafe,JVMTI 和Serviceability Agent(SA) 去解码实际的对象布局,内存占用以及引用。这使得相较于其他依赖堆的分析工具更加准确。


1.2 引入JOL的jar包

这里采用的是IDEA开发工具,首先我们需要将JOL引入到项目中。

  1. 进入到 Project Structure选项中,Mac下的快捷键Cmd + ;
    在这里插入图片描述

  2. 搜索关键字org.openjdk.jol即可。
    在这里插入图片描述

  3. 等一切就绪,你就可以在项目的lib目录中,看到jol的jar包。
    在这里插入图片描述

1.3 使用JOL进行对象分析

先定义一个实例:

public class Car {
    public String color;
    public String branch;//品牌
    public boolean isSport;
    public char alias;//缩写,如BMW
    public short tires; // 轮胎数量
    public int kilometers;//公里
    public float price;
}

/**
 * @author bertking
 * @Package generic
 * @Description: someLearn
 * @date 2020/7/30-10:53 下午
 */
public class CarJOL {
    public static void main(String[] args) {
        System.out.println("**********JVM相关信息***********");
        System.out.println(VM.current().details());

        System.out.println("**********Car.class对象的信息***********");
        System.out.println(ClassLayout.parseClass(Car.class).toPrintable());

        System.out.println("**********Car具体对象的信息***********");
        System.out.println(ClassLayout.parseInstance(new Car()).toPrintable());
    }
}

运行结果如下(这里暂时可以不去关心内容,后面系列文章会详细讲解):
在这里插入图片描述

通过打印内容,我们可以看到一个Carl对象的大小以及由于对齐填充的需要而浪费的空间大小。

在 实际的开发工作中,我们不可能按照上面的代码去写测试代码来分析项目中所有的类,So crazy…
Idea的社区这么强大,那有没有相应的插件帮我们解决这个问题呢?这个必须有

二. JOL插件

JOL的插件地址,具体的安装过程就不在这里展开讨论啦,如果有需要请自行百度…

这里需要稍微注意一下:JOL插件的使用。

2.1 JOL插件的使用

  1. 在具体的类(这里以Car为例)上面,点击右键,出现如下界面:
    在这里插入图片描述

  2. 在编辑器的右边,将会出现如下界面:
    在这里插入图片描述

  3. 聪明的读者会发现,这里的数值和代码运行的数值有差别,难道是插件有问题?

注意红色框的内容,可以选择对应虚拟机的配置(类型位数以及是否开启指针压缩(COOPS))

在这里插入图片描述

我们可以通过代码打印当前系统虚拟机的信息来看一下:

/**
 * @author bertking
 * @Package jols
 * @Description: someLearn
 * @date 2020/7/30-11:50 下午
 */
public class JOLVMDetails {
    public static void main(String[] args) {
        System.out.println(VM.current().details());
    }
}

运行结果:
在这里插入图片描述

真相就是:插件默认没有开启指针压缩,导致数据过大。当我们选择COOPS时,就会发现两者显示的内容完全相同。

三. JOL插件和JOL库两者的联系

我们通过上面结果的对比,很清楚的发现两者的区别。但是插件能配置虚拟机参数,使用代码可以吗?

1. 『JOL插件的效果』等价于『ClassLayout.parseClass().toPrintable()』
2. 使用代码来达到插件的VM配置效果

废话不多说,Talk is cheap, show you the code.

public class JOLVMOptions {
    public static void main(String[] args) {

        Layouter layouter = new CurrentLayouter();
        printInfo(layouter);
        System.out.println("========HotSpotLayouter===========");
        layouter = new HotSpotLayouter(new X86_32_DataModel());
        printInfo(layouter);

        layouter = new HotSpotLayouter(new X86_64_DataModel());
        printInfo(layouter);

        layouter = new HotSpotLayouter(new X86_64_COOPS_DataModel());
        printInfo(layouter);

        System.out.println("========RawLayouter===========");
        layouter = new RawLayouter(new X86_32_DataModel());
        printInfo(layouter);

        layouter = new RawLayouter(new X86_64_DataModel());
        printInfo(layouter);

        layouter = new RawLayouter(new X86_64_COOPS_DataModel());
        printInfo(layouter);

    }

	public static void printInfo(Layouter layouter){
        System.out.println(ClassLayout.parseClass(Car.class,layouter).toPrintable());
    }
    
}



四. 总结

我们可以通过两种方式来查看对象的信息。我们下一篇文章,将带领大家逐步揭开对象的神秘面纱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值