Java - 非池化字符串

3
  • 有没有合法的方法可以强制JVM不将特定的String实例存储在长期字符串池中?

  • new String()是否提供此功能,我可以100%确定以这种方式创建的值将被放入堆中而不是池中,除非我调用intern()


池仍然在堆中,长期存在的对象将被垃圾回收。 - Eugene
3
因此,Console类的readPassword()方法返回char[]类型。因此,我会说,“一开始就不要创建String”。 - daniu
@daniu 是的,这正是我提出这个问题的原因 :) - voismager
1个回答

3
除了不使用字符串字面量初始化它之外,恐怕没有其他合法的方法来强制JVM不将特定的String实例存储在长期存在的字符串池中。
是的(请注意,如果您编写`String str1 = new String(“Hello”);`,那么由`str1`引用的`String`实例将不会被内部化,而为字面字符串`“Hello”`创建的`String`实例将会被内部化)。
另请注意,池存储在堆中的确切位置取决于JVM的版本,如此处所述。

当为字面字符串“Hello”创建的String实例将会如此,我想我应该坚持使用原始的char[] - voismager
1
如果安全是您的考虑因素,您应该绝对使用char [],因为它可以被明确地擦除(通过覆盖其内容)。 即使String没有最终出现在字符串池中,也无法保证GC何时收集它(即使在此之后,直到内存被其他对象重用,原始字节也会持久存在)。 - crizzis
2
@crizzis 使用 char[] 只是在假装有更高的安全性,但实际上并不存在。在垃圾回收堆中,可能会有任意数量的副本飞来飞去,而你只是覆盖其中一个。此外,在数组上执行最后一个操作时进行覆盖,可能会被 JVM 优化掉。 - Holger
@Holger 或许我过于简化了我的观点。这里有一个更详细的关于这个主题的讨论。 - crizzis
@crizzis 嗯,这是一个相当复杂的话题,但它与 OP 关于 的关注点完全无关。如果池有一个字符串实例的引用,并且没有其他引用,它仍将被垃圾回收。但是,如果有一个引用,不在池中也不会有任何区别。如果您构造了一个新的 String 实例,它永远不会在池中。但是,如果您怀疑某人可能会调用 intern(),请不要忘记同样的人可能会调用 new String(yourCharArray).intern()。因此,这与 无关。 - Holger
1
一种选择是使用直接的ByteBuffer来存储安全信息,例如私钥。这将只存在于内存中的一个位置,并且在不使用时可以被覆盖。 - Peter Lawrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接