IDC

都知道堆内存要回收垃圾,如何在开发中使用对象来减少内存使用

作者:admin 2021-04-11 我要评论

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝。转载本文请联系Java极客技术公众号。 堆内存 我们大家都知道JVM内存是划分了一个是堆内存,一个是非堆内...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝。转载本文请联系Java极客技术公众号。 

堆内存

我们大家都知道JVM内存是划分了一个是堆内存,一个是非堆内存,而堆内存分为了(年轻代),(老年代)这些,而非堆内存就是一个元空间了(1.8之后变更的,之前是永久代)。

相比较来说,大家肯定都非常的熟悉分代的概念,知道对象首先应该放在哪里,然后移动到哪里,最后执行什么样子的方法来进行垃圾回收。而我们今天要说的却是如何考虑运行程序的机器内存限制下,让我们的对象更小一点就能完成我们的功能。

减少对象大小

阿粉和大家都一样,都知道对象会占用一定数量的堆内存,毕竟你新生成的对象首先就是要放到Eden区的,当Eden空间被占满的时候,出发Minor GC,存活下来的对象移动到Survivor区去,而我们想要减少内存的使用,最简单的方法就是在写程序的时候,也需要考虑对象的大小,毕竟如果说如果说以后再做CodeReview的时候,你会发现你的代码运行起来,你看JVM的时候会赏心悦目,但是代码也得好看不是?

阿粉就给大家看看最基础的Java基础实例变量的大小

图1:

实例变量,这是一个和对象息息相关的,一个对象一份实例变量,而实例变量的个数和实例变量的大小也就决定你在占用内存的大小。

大家可以想象一下,如果内存不够,那么有两种方式供你选择:

  • 选择一:增加百分之10的堆内存
  • 选择二:堆中的对象的大小减少百分之10

你会选择什么方式?一般情况你想选择第一种方式,但是这种方式好像不是那么的实际,你堆内存都不够了,你还想再继续增加点?那么只能你来选择第二种了。

但是再你选择了第二种方式之后,你又遇到了一个问题,减少对象的方式也是有两种方式:

  • 方式一:直接减少实例变量的数量
  • 方式二:减少实例变量的大小

其实这两种方式都可以,这个就是要取决于你在之前代码中做过什么,比如说你在之前的代码已经进行过实例变量的优化了,在写代码之前就已经考虑到这件事了,那么你肯定是只能选择第一种。

如果说你之前在代码中并没有去考虑过实例变量的大小,那么选择第一种将会是你最佳的方案

分析对象大小

一个对象的大小,我们要把它分开,由三部分来组成,对象头、实例变量、内存补充,在32位的系统中,假设我们定义一个int i ,那么对象头在其中就要占据 4 字节,int 在对象中占用 4 字节,而如果是64位的话,那么对象头就变了,从4字节变成8字节,在这里我们就得注意一个事情了,如果说成员变量不论是否引用了其他的对象,它占用的字节始终是 4 字节。

这里我们就引入了一个概念:Shallow Size

Shallow Size

其实简单来说,Shallow Size 就是对象本身占用内存的大小,但是不包含其中引用的对象,这局话的后半段就是相对应的阿粉刚才所说的注意事项了。

而 Shallow Size 也是有针对的,就比如说是非数组类型的对象,他的大小就是对象和他所有成员变量大小的总和,

针对数组类型的对象,它的大小是数组元素对象的大小的总和。

举个例子:

  1. public class A(){ 
  2.     private int i ; 
  3.     private boolen x; 

我们的A对象在我们New出来之后,发现,不是一个数组类型的,那么就得看成员变量,然后把成员变量加起来,是不是就等于 Shallow Size 了。

Retained Size

说了Shallow Size了,那么我们就不得不提 Retained Size了,因为阿粉在学习的时候,去专门翻找了资料,发现这都是一体的,你看这个,你发现下面还有和他有关联的,不学吧,弄不明白心里难受,那还是学习吧。

英文复制

Retained Size = 当前对象的大小+当前对象的引用大小(直接或者间接)都是

示例图:

图片网址如下https://www.yourkit.com/docs/java/help/sizes.jsp 里面也有解释,但是阿粉还是要解释一波。

在上图中 obj1 的 Retained Size = obj1 + obj2 + obj4 的 Shallow size

这是左边的,右边的是obj1 的 Retained Size = obj1 + obj2 + obj4 +obj3 的 Shallow size

在我们进行GC的时候,Retained Size是必不可少的,它有助于了解内存的结构(聚类)和对象子图之间的依赖关系,以及查找这些子图的潜在根源。

不过说实在的,因为JVM的存在,他自己的垃圾回收机制已经算是非常的不错了,但是因为我们在日常的业务中的需要,我们仍然需要去学习这些内容,毕竟万一在以后的实际工作中真的遇到了,你会发现你现在学的内容是非常有用的。

文献参考

《YouKit》 《Java性能权威指南》


本文转载自网络,原文链接:https://mp.weixin.qq.com/s/9NKeoaVWHQMdF8H4jmQXEg

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 太棒了!Python和Excel过了这么久终于

    太棒了!Python和Excel过了这么久终于

  • Java编程内功-数据结构与算法「线索化

    Java编程内功-数据结构与算法「线索化

  • 在Java中使用异步编程

    在Java中使用异步编程

  • Kafka性能篇:为何Kafka这么"

    Kafka性能篇:为何Kafka这么"

腾讯云代理商
海外云服务器