在 Java 中节省内存:实现最小的内存占用

本文将介绍接下来的技巧和主题:
 

  • 在包装器上使用基元字段(例如,布尔值 ->布尔值)
  • 减少形成平面结构的类的数量(在一个或多个类中折叠类)
  • 尽可能使用窄数据类型(例如,代替,代替等)short``int``long``Date
  • 使用掩码将一种类型隐藏在另一种类型中(例如,短内有许多布尔值)
引入要简化的类结构 
让我们切入正题,回顾一下我们将在示例中使用的类 。我们将改变其结构并逐步估计其大小四次 。
在 Java 中节省内存:实现最小的内存占用

文章插图
 
计算第一个快照大小
如上所述,我建议查看之前的文章以了解内存计算过程 。在我们的例子中,我们将使用基于 64 位 JAVA 的计算 。我们将使用Alexey Shipilev开发的JOL核心库验证所有计算 。您可以在本手册中找到此库的示例 。
启动用户对象
首先,让我们创建 3 个对象并设置所有字段 。在我们的示例中,我们将使用所有唯一对象,甚至对于布尔值,我们也将使用新实例(通过使用) 。在这种情况下,我们的计算将是最悲观的(从大小的角度来看),但完全正确:new boolean
在 Java 中节省内存:实现最小的内存占用

文章插图
 
现在让我们计算每个对象的大小(再次考虑到甚至所有布尔实例都是唯一的):
在 Java 中节省内存:实现最小的内存占用

文章插图
 
所以毕竟,总大小的实例是 320 字节(包括和实例一起) 。为了验证它,让我们使用 JOL 核心库并打印它们的大小:User``UserSalary``UserPayment
在 Java 中节省内存:实现最小的内存占用

文章插图
 
打印结果为 56 字节、136 字节和 320 字节 。
现在让我们改进这个荒谬的例子并正确启动布尔值 。
在前面的示例中,我将布尔值作为唯一对象启动 。在这里,我们将以重用sameandreferences的方式启动(这也是你经常初始化它们的方式) 。通过这样的初始化,我们的例子将更加现实 。(此步骤不是优化,它只是解释内存计算如何工作的附加步骤 。Boolean.true``Boolean.false
在 Java 中节省内存:实现最小的内存占用

文章插图
 
现在我们必须重新计算所有对象,因为我们基本上改变了布尔初始化:
在 Java 中节省内存:实现最小的内存占用

文章插图
 
打印结果符合预期:56 字节、136 字节和 208 字节(从 320 字节减少) 。
第一个内存优化:用基元替换所有包装器
在这里,我们通过仅使用原语而不是包装器对象来进行第一次真正的优化 。在这种情况下,我们将失去空收益选项,默认情况下将初始化所有值 。
在 Java 中节省内存:实现最小的内存占用

文章插图
 
现在,让我们重新计算快照大小,考虑到所有基元值都没有额外的引用并保留在其容器对象中:
在 Java 中节省内存:实现最小的内存占用

文章插图
 
如您所见,所有包装器对象都会添加 16 个额外的字节 。这种转换将总大小从 208 字节减少到 112 字节,几乎减少了 2 倍 。
第二次内存优化:在一个类中折叠数据
在大多数情况下,这种优化是不可能的,或者至少使 OOP 结构的可读性和可维护性降低;但是在某些内存不足的紧急情况下,您别无选择 。因此,让我们将所有字段移动到一个类上,并查看改进:


推荐阅读