关于Java字符串常量池

9
这是关于Java字符串常量池的内容。在我的一个程序中,我正在解密数据库密码并将其存储在一个字符串中。我听说Java字符串将存储在常量池中,它们不会在VM重新启动或加载字符串的ClassLoader退出时被销毁。
如果这是事实,我的密码将存储在字符串池中。我非常担心这个问题。是否有其他方法来销毁这些文字或我可以采取其他措施?
请就此提供建议,
敬礼, Sunny。
3个回答

8
这里涉及到几个不同的问题。首先,“常量池”一词仅指用于存储字符串和数字文字的类文件的一个非常特定的部分,或者是驻留在JVM中的从该部分类文件生成的数据结构。密码不会存储在此处,除非它们是类文件的一部分。
然而,一些String对象通过字符串驻留确实在整个程序中存储和共享。任何字符串字面值都会自动驻留,您调用intern()方法的任何字符串也会被驻留。据我所知,除此之外没有其他字符串以这种方式存储,因此,除非您自己自动驻留持有密码的字符串,否则我认为您不需要担心这一点。
还有一个需要注意的问题是,如果您不希望密码存储在内存中,则可能需要注意垃圾回收,因为不再引用的String仍然可能存在于内存中。同样,如果使用一些字符串方法(如substring)在字符串之间共享支持表示,则可能在使用完密码字符串后仍保留完整的密码字符串。
但是,如果您担心其他Java代码能够看到已经被驻留或仍然存在于内存中的旧密码,那么您不需要担心。没有办法迭代或查看驻留的字符串池的元素,也无法打开String以查看其支撑数组。

1
可能不容易从代码中找到这些字符串,但它们会在堆转储中。如果我想要获取它们,我会尝试触发一个堆转储并尝试分析转储文件。 - Ryan

3

这仅适用于字符串字面量和您已经调用了 intern() 方法的字符串。想一想:如果它适用于所有字符串,那么在处理具有不同(String)值的请求参数的 servlet 应用程序中,您很快就会耗尽内存。


Java 1.8.20引入了一个后台字符串去重特性,这非常类似于在没有任何人调用intern()的情况下对您的字符串进行intern()处理... - Ryan
由于字符串调用intern()仍然受普通垃圾回收的影响,因此 treating all strings, as if intern() was applied after construction,不会增加内存需求。实际上,堆中的字符串实例将更少。但是,这样做将导致性能灾难... - Holger

-1
哥们,用字符串缓冲区来获取密码和进行您(可能)需要进行的字符串类型操作。
StringBuffer 将字符串存储为 char[],可以被删除、覆盖或做其他操作。 例如:StringBuffer.delete(0,StringBuffer.length());
或者直接将数据库密码作为 char[] 获取并直接在其上操作——但我认为如果您已经使用了 String 方法,那么 StringBuffer 的方法会更容易些。

如果您控制接口,那么char[]非常好用。但是,如果您必须调用一个以String形式接收密码的方法,迟早会创建一个String对象... - Ryan

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