【JVM学习】1-Java对象占用内存分析-MAT

目录

 

一、文章内容介绍

二、实验环境

三、Java基本类型占用字节数

四、Java对象内存组成

五、Java对象内存实践

六、MAT准备

七、Shallow Heap分析

八、Retained Heap分析

九、小结


一、文章内容介绍

本篇文章介绍Java8 实际占用内存分析,其引用了很多网上文章+个人实践理解,希望可以让读者快速了解实际Java占用内存。

二、实验环境

1、OS:mac os 10.12.6

2、IDE:IntelliJ IDEA 2018.1.4 (Ultimate Edition)
Build #IU-181.5087.20, built on May 17, 2018
Licensed to Rover12421 / Rover12421
You have a perpetual fallback license for this version
Subscription is active until December 31, 2099
JRE: 1.8.0_152-release-1136-b39 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
macOS 10.12.6

3、Java:Java8,64位模式

Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode)

4、Memory Analyzer tool:Eclipse Memory Analyzer Version 1.9.2   官网

5、对象头分析jar

<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

三、Java基本类型占用字节数

Java基本类型 字节数
Byte 1
Boolean 1
Character 2
Short 2
Integer 4
Float 4
Long 8
Double 8

 

 

 

 

 

 

 

四、Java对象内存组成

Java对象内存组成分成(java一个对象占用多少字节?一个Java对象到底占用多大内存?):

对象头+实例数据+对齐填充。

* 本文章主要描述MAT工具分析对象内存,故默认为对象头指针压缩

* 上述实例数据包括原生类型、引用类型自身,但是不包含引用类型实际指向的内存占用(比如Object[],其数组长度不同所占内存不同,这里不计入)。

其中对齐填充是指对象所占内存必须为8字节的倍数,如果不够则进行填充(占用额外内存)。故不同类型实践如下:

类型 对象头 实例数据 对齐填充 总字节数
Byte 12 1 3 16
Boolean 12 1 3 16
Character 12 2 2 16
Short 12 2 2 16
Integer 12 4 0 16
Float 12 4 0 16
Long 12 8 4 24
Double 12 8 4 24
String 12 8(value:4+hash:4字段) 4 24
Object 12 0 4 16
Integer[] 16 0 0 16
Object[] 16 0 0 16
ArrayList 12 12(modCount:4+size:4+elementData:4) 0 24
ArrayList[] 16 0 0 16

 

 

 

 

 

 

 

 

 

 

 

可以看到几个规则(开启压缩模式):

  • 数组类型,对象本身(不计算子项实例)固定占用16字节;
  • 引用类型,对象本身固定4个字节;
  • 原生类型,对象本身占用内存需加上自身占用内存;
  • 最终不足8倍数的,要进行对齐填充。

然后对象本身的内存计算和对象实际内存计算有时不同,比如引用类型,比如数组。

另外同样是String类型,计算单个String对象所占内存时需要计算其内部的value和hash字段,共计24个字节;但如果是作为被应用的对象(比如某个类字段),则只需4个字节;下面通过实验验证。

五、Java对象内存实践

直接上代码,具体pom应用见【一、实验环境】第5条。

package javalearn;

import org.openjdk.jol.info.ClassLayout;

import java.util.ArrayList;
import java.util.List;

class C1 extends Object {
    private int size;
}

class C2 extends Object {
    private String str;
}

class C3 extends Object {
    private Object[] objs = new Object[10];
}

class C4 extends Object {
    private boolean bl;
}

class C5 extends Object {
    private int idInt;
    private long idLong;
    private double idDouble;
    private String name;
    public List<Long> array;
}

public class Howmanybytes {

    public static void main(String[] args) {
        System.out.println("----------------------------------------------");
        System.out.print(ClassLayout.parseClass(Byte.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Boolean.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Character.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Short.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Integer.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Float.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Long.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Double.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(String.class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Object.class).toPrintable());
        System.out.println();
        System.out.println("----------------------------------------------");
        System.out.print(ClassLayout.parseClass(Byte[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Boolean[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Character[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Short[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Integer[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Float[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Long[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout.parseClass(Double[].class).toPrintable());
        System.out.println();
        System.out.print(ClassLayout
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值