如何处理Java中大量小对象的内存效率

如何处理Java中大量小对象的内存效率,java,oop,memory,Java,Oop,Memory,我有一个应用程序,它从文件中提取数据并存储起来供以后使用。文件中的每一行对应一个对象Foo,该对象包含n对Bar对象,这些对象由单个字符String组成,每个对象都有一个不同的名称。因此,我将这些数据存储为: Foo扩展HashMap 其中,配对以分析我的应用程序,当我深入研究Foo的实例时,我看到: Field Type Retained - this Foo 24750

我有一个应用程序,它从文件中提取数据并存储起来供以后使用。文件中的每一行对应一个对象
Foo
,该对象包含
n
Bar
对象,这些对象由单个字符
String
组成,每个对象都有一个不同的
名称
。因此,我将这些数据存储为:

Foo扩展HashMap

其中,
配对以分析我的应用程序,当我深入研究
Foo的实例时,我看到:

Field           Type             Retained
-               
this            Foo              24750
...             
v table         HashMap$Entry[]  24662
  v [0]         HashMap$Entry    200
    v value     Pair             156
      v first   Bar              60
        ...
        > code  String           36
      v second  Bar              60
        ...
        > code  String           36
    v key       Name             72
      ...
      > name    String           36
  > [1]         HashMap$Entry    200
  > [2]        <HashMap$Entry>   -
  ...
  > [233]       HashMap$Entry    600
  ...
  > [255]      <HashMap$Entry>   -
字段类型保留
-               
这是Foo 24750
...             
v表HashMap$条目[]24662
v[0]HashMap$条目200
v值对156
v第一杆60
...
>代码字符串36
v第二棒60
...
>代码字符串36
v键名称72
...
>名称字符串36
>[1]HashMap$Entry 200
> [2]           -
...
>[233]HashMap$Entry 600
...
> [255]         -
因此,正如你所看到的,所有有用的信息都被大量无用的(对我来说)数据所包围。如果我有更少,更大的对象和相同的数据,我可以看到我的有用:无用的比率会更好,但我看不出我可以用任何其他方式实现这一点。是否有其他方法可以存储数据,但仍然像这样方便易用

编辑


我的应用程序需要可扩展到6000个以上的
Bar
实例,可能还需要扩展到同样多的
Foo
实例。

我不能完全确定我是否正确回答了您的问题,但在这种情况下,使用Flyweights可能会奏效


我认为您的许多问题通常只是面向对象的代码,特别是Unicode转换

在Java中,字符串中的字符需要存储两个字节。因此,与将文件保存在驱动器上相比,您至少可以期望将内存使用率提高一倍

由于JVM需要指向您的对象的指针,所以每个对象、每个小字符串都需要一个字的信息。因此,每对数据都是一个字表示关键字,一个字表示值加上每对数据的实际大小。现在,这些指针被添加到散列中,散列使用一个单词指向自身,并使用几个单词指向入口集。事情就是这样。这是面向对象编程


现在,您可以更改代码,将该对存储为简单字符[2]。这会减少你的记忆足迹。然后,当你想与之交互时,你可以用一个Pair对象来包装数组。

你可以尝试删除Bar和Pair对象,并将一对作为简单的字符串对象存储,例如“ab”(其中“a”、“b”当前对应于由Bar(“a”)和Bar(“b”)组成的一对)

可能使用Flyweight模式共享所有Foo对象的通用名称,因为您有
fooOne.keySet().equals(fooTwo.keySet())
您说:

我有一个应用程序,它从一个文件中获取数据,并将其存储起来以备将来使用 以后使用

后来(在评论中)


我被要求尽可能提高内存效率

我认为最节省内存的解决方案是存储文件并根据请求解析它,而不是提前解析和存储。但是,您真的想这样做并承担相关的性能成本吗?我不认为你的记忆问题特别严重,但是(正如其他人所说的)我会调查这个问题。

看看。您将看到,在JVM堆中存储类(字符串或其他)所需的字节比您想象的要多得多


对于一个1个字符的字符串,36个字节听起来非常正确,因为您需要为包含该字符的对象存储大量元数据(请确保考虑UTF编码)加上字符串类开销。

对于这么多的对象,我不必担心。25MB大约值60美分,可以重复使用。你想象有多少个物体?有许多复杂的策略可以减少内存使用量。e、 g.我有40亿行,有很多列,我想一次加载到Java中,所以我做了很多技巧来提高效率。@PeterLawrey超过6000个
和几千个
Foos
,所以你可能会浪费3.5美元的内存(这可能不会用于其他任何用途)您花多少时间来尽量减少这种情况?我被要求尽可能提高内存效率,我正在用一个全新、令人兴奋、快速、精彩的系统替换现有的系统实现,压缩内存可能会提高内存效率,但速度会变慢。我会从一个通用的CPU/内存分析器开始,找出你在哪里花费了最多的CPU,代码在哪里产生了最多的垃圾。您保留的数据可能只是您花费的时间或产生的垃圾的一小部分。任何其他方法都只是猜测。但是对象可以共享哪些数据?我认为这将是最好的解决方案,因为每个
都重复多次,但我将每个条存储为一个新实例。谢谢我真的应该已经想到了……有一本好书叫《设计模式》。了解其中的大部分意味着您将能够将您的设计问题与已经解决的问题关联起来。不客气:)我的初步实现已将堆大小从25MB减少到13MB!很高兴听到这个消息。更多的优化将在1:DI已经共享了
Name
对象!我也应该分享
Bar
对象。我真的应该说“在合理的范围内尽可能提高内存效率”。时间效率也同样重要。