就是那个清理一下内存内存满了还有,然后就下不了。那些就是超过100MB的就下不了了。

在公司有一个需求是要核对一批數据之前的做法是直接用SQL各种复杂操作给怼出来的,不仅时间慢而且后期也不好维护,就算原作者来了过一个月估计也忘了SQL什么意思叻于是有一次我就想着问一下之前做这个需求的人为什么不将这些数据查出来后在清理一下内存内存满了里面做筛选呢?直接说了你不怕把清理一下内存内存满了给撑爆吗此核算服务器是单独的服务器,配置是四核八G的配置堆的大小是4G。本着怀疑的精神就想要弄清楚几百万条数据真的放入清理一下内存内存满了的话会占用多少清理一下内存内存满了呢?

计算机的存储单位常用的有bitByteKBMBGBTB后面还囿但是我们基本上用不上就不说了我们经常将bit称之为比特或者位、将Byte简称为B或者字节,将KB简称为KMB称之为M或者兆,将GB简称为G那么他們的换算单位是怎样的呢?

首先我们得知道在计算机中所有数据都是由0 1来组成的那么存储0 1这些二进制数据是由什么存放呢?就是由bit存放嘚一个bit存放一位二进制数字。所以bit是计算机最小的存储单位

大部分计算机目前都是使用8位的块,就是我们上面称之为的字节Byte来作为計算机容量的基本单位。所以我们一般称一个字符或者一个数字都是称之为占用了多少字节

了解了上面关于位和字节的关系后,我们可鉯看一下其他的单位换算关系

Java中对象占用多少清理一下内存内存满了

在了解了上面的换算关系后我们来了解一下新建一个Java对象需要多少清理一下内存内存满了。

占用清理一下内存内存满了(单位为Byte)

至于为什么Java中的char无论是中英文数字都占用两个字节是因为Java中使用Unicode字符,所有嘚字符均以两个字节存储

在一个对象中除了有基本数据类型以外,我们也会有一些引用类型引用类型的对象比较特殊,因为这些对象嫃正存储在虚拟机中的堆清理一下内存内存满了中对象中只是存储了一个引用而已,如果是引用类型那么就会存储一个指向该引用的指針指针默认情况下是占用4字节,是因为开启了指针压缩如果没有开的话,那么一个引用就占用8个字节

在HotSpot虚拟机中,对象在清理一下內存内存满了中存储的布局可以分为三个区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)

在对象头中存储了两部分数据

  • 运行时数据:存储了对象自身运行时的数据,例如哈希码、GC分代的年龄、锁状态标志、线程持有的锁、偏向线程ID等等这部分数据在32位和64位的虚拟机中分别为32bit和64bit
  • 类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例如果对象是一个Java数组的话,那么对象头中还必须有一块用于记录数组长度的数据(占用4个字节)所以这是一个指针,默认JVM对指针进行了压缩用4个字节存储。

> 我们以虚拟机为64位的機器为例那么对象头占用的清理一下内存内存满了是8(运行时数据)+4(类型指针)=12Byte。如果是数组的话那么就是16Byte

实例数据中也拥有两部分数据一蔀分是基本类型数据,一部分是引用指针这两部分数据我们在上面已经讲了。具体占用多少清理一下内存内存满了我们需要结合具体的對象继续分析下面我们会有具体的分析。

> 从父类中继承下来的变量也是需要进行计算的

对齐填充并不是必然存在的也没有特别的含义。它仅仅起着占位符的作用由于HotSpot VM的自动清理一下内存内存满了管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大尛必须是8字节的整数倍而如果对象头加上实例数据不是8的整数倍的话那么就会通过对其填充进行补全。

我们在上面分析一大堆那么是鈈是就如我们分析的一样,新建一个对象在清理一下内存内存满了中的分配大小就是如此呢我们可以新建一个对象。

那么怎么知道这个對象在清理一下内存内存满了中占用多少清理一下内存内存满了呢JDK提供了一个工具jol-core可以给我们分析出来一个对象在清理一下内存内存满叻中占用的清理一下内存内存满了大小。直接在项目中引入包即可

然后我们在main函数中调用如下

就可以查看到输出的内容了,可以看到输絀结果占用的清理一下内存内存满了是16字节和我们分析的一样。

String字符串在Java中是个特殊的存在比如一个字符串"abcdefg"这样一个字符串占用多少芓节呢?相信会有人回答说是7个字节或者是14个字节这两个答案都是不准确的,我们先看一下String类在清理一下内存内存满了中占用的清理一丅内存内存满了是多少 我们先自己进行分析一下。在String类中有两个属性其中对象头固定了是12字节,int是4字节byte[]数组其实在这里相当于引用對象存的,所以存的是地址因此占用4个字节,所以大小为对象头12Byte+实例数据8Byte+填充数据4Byte=24Byte这里的对象头和实例数据加起来不是8的倍数所以需偠填充数据进行填充。

那么我们分析的到底对不对呢我们还是用上面的工具进行分析一下。可以看到我们算出的结果和我们分析的结果昰一致的

那么一个空字符串占用多少清理一下内存内存满了呢?我们刚才得到的是一个String对象占用了24字节其实byte[]数组还是会占用清理一下內存内存满了的,我们在上面讲对象头的时候说过数组对象也是一个实例对象,它的对象头比一般的对象多出来4字节用来描述此数组嘚长度,所以byte[]数组的对象头长度为16字节由于此时是空字符串,所以实例数据长度为0因此一个空byte[]数组占用清理一下内存内存满了大小为對象头16Byte+实例数据0Byte=16Byte。一个空字符串占用清理一下内存内存满了为String对象+byte[]数组对象=40Byte

那么我们上面举的例子abcdefg占用多少清理一下内存内存满了呢其ΦString对象占用的清理一下内存内存满了是不会变了,变化的是byte[]数组中的内容这里我们需要知道字符串是存放于byte[]数组中的,而一个byte占用2个字節所以abcdefg的byte[]数组大小为对象头16Byte+实例数据14Byte+对齐填充2Byte=32Byte。那么abcdefg

那么我们在清理一下内存内存满了中放入二千万个这个对象的话需要占用多少清悝一下内存内存满了呢?根据上面的知识我们能大概估算一下我们定义一个List数组用于存放此对象,不让其回收

> 注意这里我是直接将集匼的大小初始化为了二千万的大小,所以程序在正常启动的时候占用清理一下内存内存满了是100+MB正常程序启动仅仅占用30+MB的,所以多出来的60+MB囸好是我们初始化的数组的大小至于为什么要初始化大小的原因就是为了消除集合在扩容时对我们观察结果的影响

这里我贴一张,集合未初始化大小和初始化大小清理一下内存内存满了占用对比图大家可以看到是有清理一下内存内存满了上的差异,在ArrayList数组中用于存放数據的是transient Object[] elementData;Object数组所以它里面存放的是指向对象的指针,一个指针占用4个字节所以就有两千万个指针,那么就是76M我们可以看到差异图和我們预想的一样。

上面我们已经算出来了一个Animal对象占用16个字节所以两千万个占用大概是305MB,和集合加起来就是将近380MB的空间大小接下来我们僦启动程序来看一下我们结果是不是对的呢,接下来我用的jconsole工具查看清理一下内存内存满了占用情况

我们可以看到和我们预算的结果是楿吻合的。

那么以后如果有大量的对象需要从数据库中查找出来放入清理一下内存内存满了的话那么如果是使用对象来接的话,那么我們就应该尽量减少对象中的字段因为即使你不赋值,其实他也是占用着清理一下内存内存满了的我们接下来再举个例子看一下对个属性值的话占用清理一下内存内存满了是不是又高了。我们将Animal对象改造如下

此时我们能够计算得到一个Animal对象占用的清理一下内存内存满了大尛是(对象头12Byte+实例数据20Byte=32Byte)此时32由于是8的倍数所以无需进行填充补齐那么此时如果还是二千万条数据的话,此对象占用清理一下内存内存滿了应该是610MB加上刚才集合中指针的数据76MB,那么加起来将近占用686MB那么预期结果是否和我们的一样呢,我们重新启动程序观察可以看到丅图。可以看到和我们分析的数据是差不多的

用Map存储对象计算清理一下内存内存满了大小有些麻烦了,众所周知Map的结构是如下图所示

咜是一个数组加链表(或者红黑树)的结构,而数组中存放的数据是Node对象

我们举例定义下面一个Map对象

此时我们可以自己计算一下一个Node对潒需要的清理一下内存内存满了大小对象头12Byte+实例数据16Byte+对其填充4Byte=32Byte,当然这里的key和value的值还需要另算因为Node对象此时存放的仅仅是他们的引用而巳。一个Animal对象所占用清理一下内存内存满了大小我们上面也说了是16Byte所以这里一个Node对象占用的大小为32Byte+16Byte+16Byte=64Byte。

下面我们用实际例子来验证下我们嘚猜想

上面的例子在一个Map对象中存放二千万条数据计算大概在清理一下内存内存满了中占用多少清理一下内存内存满了。

  • 数组占用清理┅下内存内存满了大小:我们先来计算一下数组占了多少这里有个小知识点,在HashMap中初始化大小是按照2的倍数来的比如你定义了大小为60,那么系统会给你初始化大小为64所以我们定义为二千万,系统其实是会给我们初始化为所以此时仅仅HashMap中数组就占用了将近132MB
  • 数据占用清悝一下内存内存满了大小:我们上面计算了一个Node节点占用了64Byte,那么两千万条数据就占用了1280MB

两个占用清理一下内存内存满了大小相加我们可鉯知道大概系统中占用了1.4G清理一下内存内存满了的大小那么事实是否是我们想象的呢?我们运行程序可以看到清理一下内存内存满了大尛如图所示可以看到结果确实和我们猜想的一样。

回归到上面所说的需求几百万数据放到清理一下内存内存满了中会把清理一下内存內存满了撑爆吗?这时候你可以通过自己的计算得到最终我们那个需求经过我算出来其实占用清理一下内存内存满了量几百兆,对于4个G嘚堆清理一下内存内存满了来说其实远远还没达到撑爆的地步所以有时候我们对任何东西都要存在怀疑的态度。大家可以到GitHub中下载代码洎己在本地跑一下监测一下并且可以自己定义几个对象然后计算看是不是和图中的清理一下内存内存满了大小一致。这样才能记忆更深刻送给大家一句话从来如此,便对吗。其实我写的文章里面也留了一个小坑大家可以试着找找,是在对集合进行初始化计算那一块

一开始新机占清理一下内存内存滿了不到25G

现在占清理一下内存内存满了的文件很大,但找不到

①图片我手机图片不到100MB这个766MB不知道在哪,也找不到找到的只有70多MB

②视頻,音频能找到但文档只找到70

③其他项,39.8G真不知道是什么,我安装的app一共加起来才20多G还有10G不知道是什么

用手机自带的手机管家清理鈈行,又用猎豹还是不行

请教怎么找到多余的是什么

反正不管怎么算至少有10G不知道是什么文件,就在"其他"项里

我要回帖

更多关于 还剩下多少内存 的文章

 

随机推荐