JVM调优总结——基本概念

 2023-01-25
原文作者:乐享非凡 原文地址:https://juejin.cn/post/6909424856719163405

数据类型

Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。

堆和栈

栈是运行时的的单位,堆是存储数据的单位。Java中一个线程就会相应有一个线程栈与之对应,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值、 基本类型和堆中对象的引用 。堆中存的是对象,一个对象的大小是不可估计的,或者说是可以动态变化的。 但是在栈中,一个对象只对应了一个4btye的引用。

Java对象的大小

基本的类型都是已知的。对于非基本类型的Java对象,其大小不是固定的。在Java中,一个空的Object对象是8byte,这个大小只是保存堆中一个没有任何属性的对象的大小。

    Object o=new Object();

这行语句所占用的空间是4Byte+8Byte,4Byte是栈中引用的大小,8Byte是堆中对象的大小。因为所有的Java对象都继承了Object对象,所有不论是什么对象,其大小必定大于8Byte。

有了Objcet对象的大小,就可以计算其他对象的大小了。

    Class NewObject{    int count;    boolean flag;    Object o;}

其大小为空对象(8Byte)+int类型(4Byte)+boolean(1Byte)+空对象Object的引用(4Byte)=17Byte

但是Java在对对象分配内存大小都是以8的整数倍来分的。所有实际上对象的大小为24Byte。

这里需要注意一下基本类型的包装类型的大小。因为这种包装类型已经成为对象了,因此需要把他们作为对象来看待。包装类型的大小至少是12byte(声明一个空Object至少需要的空间),而且12byte没有包含任何有效信息,同时,因为Java对象大小是8的整数倍,因此一个基本类型包装类的大小至少是16byte。这个内存占用是很恐怖的,它是使用基本类型的N倍(N>2),有些类型的内存占用更是夸张(随便想下就知道了)。 因此,可能的话应尽量少使用包装类。

引用类型

对象引用类型分为强引用、软引用、弱引用和虚引用。

强引用:就是我们一般声明对象是时虚拟机生成的引用,强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收

软引用:软引用一般被做为缓存来使用。与强引用的区别是,软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来决定是否对软引用进行回收。如果剩余内存比较紧张,则虚拟机会回收软引用所引用的空间;如果剩余内存相对富裕,则不会进行回收。换句话说,虚拟机在发生OutOfMemory时,肯定是没有软引用存在的。

弱引用:弱引用与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。

虚引用:如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。