【发布时间】:2011-02-21 08:14:00
【问题描述】:
我正在编写一个编解码器来处理使用定制有线协议通过 TCP 发送的消息。在解码过程中,我创建了许多Strings、BigDecimals 和日期。客户端-服务器访问模式意味着客户端发出请求然后解码数千条响应消息是很常见的,这会导致大量重复Strings、BigDecimals等。
因此,我创建了一个 InternPool<T> 类,允许我实习每个类的对象。在内部,池使用WeakHashMap<T, WeakReference<T>>。例如:
InternPool<BigDecimal> pool = new InternPool<BigDecimal>();
...
// Read BigDecimal from in buffer and then intern.
BigDecimal quantity = pool.intern(readBigDecimal(in));
我的问题:我将InternPool 用于BigDecimal,但我是否应该考虑将它也用于String 而不是 String 的intern() 方法,我相信它使用永久代空间?使用 PermGen 空间有什么好处?
【问题讨论】:
-
@kts:如果我要将 byte[] 映射到 BigDecimal,问题是一旦实习池创建/返回 BigDecimal,任何东西都不会引用 byte[]。假设 byte[] 是底层 WeakHashMap 中的键,这将导致条目被删除,尽管相应的 BigDecimal 正在使用中。
-
WeakReference适合这个,还是您应该使用SoftReference? GC 对两者的行为不同,这听起来像是您正在尝试创建一种缓存;弱引用不适用于此目的。出于某些原因,请在此处查看我的答案:stackoverflow.com/questions/2861410/… -
@Adamski 我将仅在 BigDecimal 上使用 SoftReference,并在 BigDecimal 入队后使用 ReferenceQueue 从地图中删除
byte[]s。 (可能需要一个 BiMap)。这可以消除冗余 BigDecimal 对象的构造,从而节省内存/gc 运行时间和执行时间(只需构造一次)。 -
仔细考虑,实习生
byte[]可能是一个更好的主意,并且只有在您真正需要使用它时才转换为 BigDecimal。这个操作也可以被缓存。这提供了byte[] b = pool.intern(getBytes());的简单性和惰性构造的好处。在这两种情况下,您都必须读取字节(或任何您使用的 BigDecimal),但在这种情况下,您只会读取每个唯一 BigDecimal 的 ctor 1。 -
@Adamski:你不能决定“使用 PermGen” [原文如此]。 String 的 intern 机制与 String“池化”有关,但不一定与 PermGen 内存池有关。 PermGen 是特定于 Sun VM 的功能,在语言/VM 规范级别不存在。
标签: java garbage-collection permgen string-interning