String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true
Убедитесь, что вы понимаете, почему. Это потому, что сравнение ==
сравнивает только ссылки; equals()
метод сопоставляет содержимое по символу.
Когда вы вызываете new для a
и b
, каждый получает новую ссылку, указывающую на "foo"
в таблице строк. Ссылки разные, но контент один и тот же.
Из-за виртуальной памяти чудес, почти невозможно удалить что-то из памяти абсолютно невосполнимым способом. Ваш лучший выбор состоит в том, чтобы обнулить поля значения; однако:
Храните уязвимые данные в массиве, затем "обнулите" их как можно скорее.
Любые данные в RAM могут быть скопированы в диск системой виртуальной памяти. Данные в RAM (или дамп ядра) могут также быть осмотрены средствами отладки. Для сведения к минимуму вероятности этого случая необходимо бороться за следующее
String
, содержать секретыКриптографические API в Java используют этот подход, и любые API, которые Вы создаете, должны поддерживать его также. Например, KeyStore.load
позволяет вызывающей стороне очищать пароль char[]
, и когда вызов завершается, как делает KeySpec для основанного на пароле шифрования.
Идеально, Вы использовали бы a finally
блок для обнуления массива, как это:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = …
char[] pw = System.console().readPassword();
try {
ks.load(is, pw);
}
finally {
Arrays.fill(pw, '\0');
}
Ничто не удалено, то, что это примерно было доступным или не к приложению. Однажды недоступный, пространство становится кандидатом на последующее использование, когда потребность возникнет, и пространство будет перезаписано. В случае прямого доступа к памяти что-то должно всегда там читать, но это мог бы быть спам, и привычка имеют смысл.
Поскольку zacherates сказал, нуль чувствительные поля Вашего Объекта прежде, чем удалить ссылки на него. Обратите внимание, что Вы не можете обнулить содержание Строки, так используйте массивы символов и обнулите каждый элемент.
Путем установки Объекта в NULL не означает, что объект удален из памяти. Виртуальная машина отметит тот Объект как готовый к Сборке "мусора", если больше не будет ссылок на тот Объект. В зависимости от Вашего кода на это можно было бы все еще сослаться даже при том, что Вы установили его в NULL, в этом случае, это не будет удалено. (По существу, если Вы ожидаете, что это будет собрано "мусор", и это не Вы, имеют утечку памяти!)
После того как это отмечается как готовое к набору, Вы не имеете никакого контроля, когда Сборщик "мусора" удалит его. Можно бездельничать со стратегиями Сборки "мусора", но я не советовал бы ему. Представьте свое приложение и посмотрите на объект, и это - идентификатор, и Вы видите то, что ссылается на него. Java предоставляет VisualVM 1.6.0_07 и выше или можно использовать NetBeans
Я думал бы, что Ваш лучший выбор (который не сложен) состоит в том, чтобы использовать символ [] и затем сменить каждое положение в массиве. Другие комментарии об этом являющийся возможным для него, чтобы быть скопированными в памяти все еще применяются.
Нет, если у Вас нет прямого ответа на аппаратные средства. Существует шанс, что переменная будет кэшироваться где-нибудь. Уязвимые данные могут даже храниться в подкачке :) Если Вы касаетесь только о RAM, можно играть со сборщиком "мусора". На высоком уровне langs обычно у Вас нет прямого доступа к памяти, таким образом, не возможно управлять этим аспектом. Например, в.NET существует класс SecureString, который использует interop и прямой доступ к памяти.
Примитивные данные (байт, символ, интервал, дважды) и массивы их (байт []...) являются стираемыми путем записи нового случайного содержания в них.
Данные объектов должны быть санированы путем перезаписи их примитивных свойств; установка в NULL переменной просто делает объект доступным для GC, но не сразу мертвая. Дамп VM будет содержать их, чтобы любой видел.
Неизменные данные, такие как Строка не могут быть перезаписаны всегда. Любая модификация просто делает копию. Необходимо постараться не сохранять уязвимые данные в таких объектах.
P.S. Если мы говорим о паролях, лучше использовать crypto-сильные хеш-функции (MD5, SHA1...), и никогда не работать с паролями в открытом тексте.
Полностью и абсолютно невосполнимый что-то почти невозможное в этот день и возраст. При нормальном удалении чего-то onlything, который происходит, - то, что первое пятно в памяти освобождено. Это первое пятно раньше содержало информацию относительно howfar, память должна была быть зарезервирована для той программы или чего-то еще.
Но все другие информация все еще там, непока она не перезаписывается кем-то еще.
я sudgest или TinyShredder, или использующий набор CCleaner для Gutmann-передачи
Если Вы думаете об обеспечении пароля/управления ключами, Вы могли бы написать некоторый код JNI, который использует определенный для платформы API, чтобы сохранить ключи в безопасном пути и не пропустить данные в память, управляемую JVM. Например, Вы могли сохранить ключи в странице, привязал физическую память и мог препятствовать тому, чтобы шина IO получила доступ к памяти.
Править: Для комментария некоторых предыдущих ответов JVM могла переместить объекты в памяти, не стирая их предыдущие местоположения, таким образом, даже символ [], байты, ints и другие "стираемые" типы данных не является ответом, если Вы действительно хотите удостовериться, что никакая уязвимая информация не хранится в памяти, управляемой JVM, или подкачала на жестком диске.