java垃圾收集安全地擦除垃圾数据?

时间:2016-07-29 18:19:27

标签: java garbage-collection

这是一个记忆数据安全问题 java垃圾收集是否安全地清除了垃圾数据?

显然在一大块数据被垃圾收集后,我再也无法检索它了,但是黑客还可以通过内存转储来检索数据吗?

3 个答案:

答案 0 :(得分:5)

正如其他用户已在此处提到的那样,JVM在垃圾回收后不会安全地清理内存,因为它会严重影响性能。这就是为什么许多程序(尤其是安全库)使用可变结构而不是不可变(char数组而不是字符串等),并在不再需要时自行清理数据。

不幸的是,即使这样的方法并不总是有效。我们来看看这个场景:

  1. 使用密码创建一个char数组。
  2. JVM执行垃圾收集并将您的char数组移动到内存中的另一个位置,使之前占用的内存保持不变,只需将其标记为空闲块。所以,我们现在有一个密码的“脏副本”。
  3. 您已经完成了密码,并明确地将您的char数组中的所有字符归零,认为现在一切都很安全。
  4. 攻击者转储您的内存,并在第2步之前第一次在内存中找到您的密码。
  5. 我只能想到这个问题的一种可能解决方案:

    1. 使用G1垃圾收集器。
    2. 使您的敏感数据成为单个块(原始值数组),其大小足以占用区域大小的一半以上(由G1使用)(默认情况下,此大小取决于最大堆大小,但您也可以手动指定)。这将迫使收集器将您的数据视为所谓的“巨大对象”。 G1 GC不会在内存中移动这些对象。
    3. 在这种情况下,当您手动删除块中的某些数据时,可以确保堆中某处不存在相同数据的其他“脏副本”。
    4. 另一个解决方案是使用您可以手动处理的堆外数据,但这不是纯Java。

答案 1 :(得分:2)

这取决于JVM实现以及可能的选项,但我认为它不会清除数据。垃圾收集只需跟踪哪些区域可用。将所有数据设置为0或其他内容是很多不必要的写入。出于这个原因,您经常会看到API使用char数组代替字符串而不是字符串。

答案 2 :(得分:0)

具体而言,Oracle JVM无法清除空间,它只在Eden和Survivor空间之间复制数据,不再使用的对象只会留在那里作为最终会被覆盖的垃圾。类似的事情发生在OldGen中,有些地方被标记为已使用,当对象符合垃圾收集条件时,它占用的地方被标记为未使用。如果有足够的申请时间,它也会被覆盖。