为了垃圾收集而避免创建对象仍然有意义吗?

时间:2017-09-07 08:53:29

标签: java java-8 garbage-collection java-9

例如,在服务适配器中,您可以:

一个。有一个输入数据模型和一个输出数据模型,甚至可能是不可变的,具有不同的类,并使用Object Mappers在类之间进行转换并沿途创建一些短期对象

湾有一个数据模型,一些类可能是可变的,但为输入创建的同一个对象也作为输出发送

还有其他一些用例,你必须在有很多对象的清晰代码和用较少对象的不太清晰的代码之间做出选择,我想知道垃圾收集在这个决定中是否还有权重。

3 个答案:

答案 0 :(得分:4)

我应该将此作为评论,因为它不符合IMO的答案,但它不适合。

即使答案很可能是 - 做任何事情都会使你的代码更具可读性(并且说实话,我仍然一直遵循这一点);我们在代码库中遇到了GC这个问题。

假设你想要创建一个用户图(我们不得不 - 大约一百五十万)并在内存中加载它们的所有属性并对它们进行一些聚合和过滤等(这不是我的决定),因为这些图形对象非常繁重 - 一旦加载16GBJVM OOM失败,GCBitSet将会暂停。这是可以理解的 - 大量数据需要大量内存,你可以逃避它。提出的解决方案和实际工作的解决方案是使用简单的getter s对其进行建模 - 其中每个位都是属性,并且可能与其他一些数据相关联;到目前为止,这是不可读的,并且极其很难维护到今天。大量的转变,大量的数据内在性 - 你必须始终知道3位意味着什么,usernameIncome的{​​{1}}没有让我们说 - 你必须做很多轮班并将其映射到搜索表等等。但它会使GC非常低,至少在我们可以接受的范围内。

因此,除非你能证明GC花了你的应用时间这么多 - 你可能更安全,只需添加更多RAM并增加它(除非你有泄漏)。我仍然会像clear code一样99.(99) %

答案 1 :(得分:2)

较新版本的Java具有非常复杂的机制来处理非常短暂的生命对象,因此它没有像过去那样糟糕。使用现代JVM,我说你不需要担心垃圾收集时间,如果你创建了很多对象,这是一件好事,因为现在有很多它们是在飞行中创建的是旧版Java的情况。

如果创建成本高昂,例如,仍然有效的是保持创建对象的数量较少。访问数据库以从网络操作等中检索数据

答案 2 :(得分:1)

正如其他人所说,我认为编写代码以最佳方式解决问题而不是考虑垃圾收集器(GC)将会做什么更好。

使用GC的关键是查看对象的生命周期。堆(通常)被分成两个主要区域,称为世代,以表示对象已存活多久(因此年轻和老一代)。为了最大限度地减少GC的影响,您希望您的对象在他们还处于年轻一代时(无论是在伊甸园空间还是幸存者空间,但最好是伊甸园空间)才有资格进行收集。 Eden空间中对象的集合实际上是免费的,因为GC不对它们做任何事情,它只是忽略它们并在完成次要GC时重置分配指针。

不是通过System.gc()显式调用GC,而是调整堆更好。例如,您可以使用命令行选项(如-XX:NewRatio=n)设置年轻代的大小,其中n表示新旧比例(例如,将其设置为3将使新比例:旧1:3所以年轻一代将是堆的四分之一)。或者,您可以使用-XX:NewSize=n-XX:MaxNewSize=m明确设置尺寸。 GC可能会在收集期间调整堆大小,因此将这些值设置为相同将使其保持固定大小。

您可以对代码进行概要分析,以确定对象创建速率以及对象通常存活的时间。这将为您提供(理想情况下)配置堆的信息,以最大限度地减少被提升到旧一代的对象数量。你真正不想要的是对象被提升,然后很快变成垃圾。

或者,你可能想看看Azul的Zing JVM(完全披露,我为他们工作)。这使用了一种不同的GC算法,称为C4,它可以与应用程序线程同时压缩堆,从而消除了GC对应用程序延迟的大部分影响。