基础知识:
1字节=8个二进制位
64位计算机中48位用于内存存储,16位作为保留位;
32位机最大内存空间2的32次方=4G,64位机最大内存空间2的48次方=256T。
对象的内存模型:对象头,实例数据,对象填充
对象头:
Mark Word:锁状态
类型指针:基于哪个类生成的对象;
数组长度:当对象是数组时,其长度信息存储;
实例数据:
类中定义的属性
对其填充:
以8字节对齐,不足的话以8字节或其整数倍补充对齐。
关闭指针压缩:-XX:-UseCompressedOops
开启指针压缩:-XX:+UseCompressedOops
【空对象】
package com.kyle.springbase.jvm;
import org.openjdk.jol.info.ClassLayout;
/**
* @author kyle
* @title: MyEmptyObject
* @projectName springbase
* @description: 空对象,检验占用内存大小
* @date 2021/4/11 14:12
*/
public class MyEmptyObject {
/**
* 需要引入包,查看内存占用大小
* <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
* <dependency>
* <groupId>org.openjdk.jol</groupId>
* <artifactId>jol-core</artifactId>
* <version>0.15</version>
* <scope>provided</scope>
* </dependency>
*
*/
public static void main(String[] args) {
MyEmptyObject myEmptyObject = new MyEmptyObject();
System.out.println(ClassLayout.parseInstance(myEmptyObject).toPrintable());
}
}
未开启指针压缩:-XX:-UseCompressedOops
com.kyle.springbase.jvm.MyEmptyObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x00000000183b3028
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
开启指针压缩
在VM中开启:-XX:+UseCompressedOops
com.kyle.springbase.jvm.MyEmptyObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0x2000c105
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Ps:
Mark Word 区大小不随指针压缩是否开启改变大小
类型指针区大小(KClass Pointer):开启指针压缩占用4B,不开启占用8B
对象对齐:不足8B倍数,要补齐
空对象(没有普通属性)占用多大空间?
1、未开启指针压缩:16字节 = 8B(Mark Word区) +8B
2、开启指针压缩:16字节 = 8B + 4B + 0 + 4B
【有属性的对象】
package com.kyle.springbase.jvm;
import org.openjdk.jol.info.ClassLayout;
/**
* @author kyle
* @title: MyNotEmptyObject
* @projectName springbase
* @description: 有属性的对象
* @date 2021/4/11 14:28
*/
public class MyNotEmptyObject {
int a =1;
int b = 2;
double c = 3.0d;
public static void main(String[] args) {
MyNotEmptyObject myNotEmptyObject = new MyNotEmptyObject();
System.out.println(ClassLayout.parseInstance(myNotEmptyObject).toPrintable());
}
}
开启指针压缩:
com.kyle.springbase.jvm.MyNotEmptyObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0) //Mark Word
8 4 (object header: class) 0x2000c105 // KClass Pointer
12 4 int MyNotEmptyObject.a 1
16 8 double MyNotEmptyObject.c 3.0
24 4 int MyNotEmptyObject.b 2
28 4 (object alignment gap) // 对象填充
Instance size: 32 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
32B = 8B + 4B + 4B + 8B + 4B + 4B
关闭指针压缩:
com.kyle.springbase.jvm.MyNotEmptyObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x0000000017e53028
16 8 double MyNotEmptyObject.c 3.0
24 4 int MyNotEmptyObject.a 1
28 4 int MyNotEmptyObject.b 2
Instance size: 32 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
【数组对象】
package com.kyle.springbase.jvm;
import org.openjdk.jol.info.ClassLayout;
/**
* @author kyle
* @title: MyArrayObject
* @projectName springbase
* @description: 数组对象和普通对象的内存占用
* @date 2021/4/11 14:41
*/
public class MyArrayObject {
int a = 1;
int b = 2;
static int[] c = {0, 1, 2};
public static void main(String[] args) {
MyArrayObject myArrayObject = new MyArrayObject();
System.out.println(ClassLayout.parseInstance(c).toPrintable());
System.out.println(ClassLayout.parseInstance(myArrayObject).toPrintable());
}
}
未开启指针压缩:-XX:-UseCompressedOops
[I object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x0000000017920b68
16 4 (array length) 3
16 8 (alignment/padding gap) //头部的填充
24 12 int [I.<elements> N/A
36 4 (object alignment gap) //对其填充
Instance size: 40 bytes
Space losses: 8 bytes internal + 4 bytes external = 12 bytes total
com.kyle.springbase.jvm.MyArrayObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x0000000017d23080
16 4 int MyArrayObject.a 1
20 4 int MyArrayObject.b 2
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
开启指针压缩:-XX:+UseCompressedOops
[I object internals: //数组对象的内存占用
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0) //Mark Word
8 4 (object header: class) 0x2000016d // KClass pointer
12 4 (array length) 3
12 4 (alignment/padding gap)
16 12 int [I.<elements> N/A
28 4 (object alignment gap)
Instance size: 32 bytes
Space losses: 4 bytes internal + 4 bytes external = 8 bytes total
com.kyle.springbase.jvm.MyArrayObject object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0) //Mark Word
8 4 (object header: class) 0x2000c105 //Mark Word
12 4 int MyArrayObject.a 1 //int 类型占用
16 4 int MyArrayObject.b 2 //int 类型占用
20 4 (object alignment gap) // 对象补齐
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
oop:对象指针
jdk中,所有的对象都是以8字节对齐的(1000),所以后三位永远为0,开启指针压缩,就是将oop后面的三个0去掉,使用的时候内存地址后三位补0;
开启指针压缩,指针占用4个字节,然后加上这里去掉的3个位,那么oop最大空间为32+3=35位
开启指针压缩的情况下,如何扩容oop的最大空间?
在后面加0补齐,扩容到2^36
栈溢出的几种方式:
1、调用链太长;
2、死循环;
3、无限递归。
查看栈内存大小: java -XX:+PringFlagsFinal -version grep ThreadStack
栈的最小空间为:160K
如果栈的深度为772,如何计算栈的大小? 160K*1024/772