Возможный дубликат:
Создание утечки памяти с помощью Java
Какой самый простой способ вызвать утечку Java-памяти?
Возможный дубликат:
Создание утечки памяти с помощью Java
Какой самый простой способ вызвать утечку Java-памяти?
Вы не можете "утечить память" на Java, если вы не:
Я полагаю, что вас интересует последний случай. Общие сценарии:
Хорошим примером может быть:
StaticGuiHelper.getMainApplicationFrame().getOneOfTheButtons().addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
// do nothing...
}
})
Зарегистрированное действие ничего не делает, но это заставит модальное окно задерживаться в памяти навсегда, даже после закрытия, вызывая утечку - поскольку слушатели никогда не регистрируются, а каждый анонимный внутренний объект класса содержит ссылку (невидимую) на его внешний объект. Что еще - любой объект, на который ссылаются из модальных окон, также имеет возможность утечки.
Вот почему библиотеки, такие как EventBus, используют по умолчанию слабые ссылки.
Помимо слушателей, другими типичными примерами являются кеши, но я не могу придумать хороший пример.
"Утечка памяти в компьютерной науке (или утечке в этом контексте) возникает, когда компьютерная программа потребляет память, но не может ее вернуть в операционную систему". (Википедия)
Простой ответ: вы не можете. Java выполняет автоматическое управление памятью и освобождает ресурсы, которые вам не нужны. Вы не можете остановить это. Он ВСЕГДА сможет освободить ресурсы. В программах с ручным управлением памятью это другое. Вы не можете получить некоторую память в C, используя malloc(). Чтобы освободить память, вам понадобится указатель, возвращаемый malloc, и вызов на него free(). Но если у вас больше нет указателя (перезаписан или превышен срок службы), то вы, к сожалению, не можете освободить эту память, и, следовательно, у вас есть утечка памяти.
Все остальные ответы до сих пор в моем определении не являются утечками памяти. Все они стремятся наполнить память бессмысленными вещами очень быстро. Но в любое время вы все равно можете разыменовать созданные вами объекты и освободить память → NO LEAK. Ответ acconrad довольно близок, хотя, как я должен признать, поскольку его решение эффективно просто "сбивает" сборщик мусора, заставляя его в бесконечном цикле).
Долгий ответ: вы можете получить утечку памяти, написав библиотеку для Java с помощью JNI, которая может иметь ручное управление памятью и, следовательно, иметь утечки памяти. Если вы вызовете эту библиотеку, ваш java-процесс будет утечка памяти. Или у вас могут быть ошибки в JVM, так что JVM теряет память. Вероятно, в JVM есть ошибки, возможно, даже некоторые из них известны, поскольку сбор мусора не является тривиальным, но тогда он все еще является ошибкой. По дизайну это невозможно. Возможно, вы запрашиваете какой-то Java-код, который возникает из-за такой ошибки. Извините, я не знаю одного, и в любом случае это может не быть ошибкой в следующей версии Java.
public static List<byte[]> list = new ArrayList<byte[]>();
Затем добавьте (большие) массивы, не удаляя их. В какой-то момент у вас не хватит памяти, не подозревая. (Вы можете сделать это с любыми объектами, но с большими полными массивами вы можете ускорить работу)
В Java, если вы разыскиваете объект (он выпадает из области видимости), он собирает мусор. Поэтому вы должны держать ссылку на него, чтобы иметь проблемы с памятью.
Здесь простой пример
public class finalizer {
@Override
protected void finalize() throws Throwable {
while (true) {
Thread.yield();
}
}
public static void main(String[] args) {
while (true) {
for (int i = 0; i < 100000; i++) {
finalizer f = new finalizer();
}
System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
}
}
}
Поскольку всегда есть ссылка на коллекцию и экземпляр объекта, который владеет коллекцией, сборщик мусора никогда не будет очищать эту память, тем самым вызывая "утечку" с течением времени.
Из того, что я прочитал в наиболее голосуемом ответе, вы, скорее всего, просите утечку памяти типа C. Ну, так как коллекция garbagge, вы не можете выделить объект, потерять все ссылки и заставить его по-прежнему занимать память - это будет серьезной ошибкой JVM.
С другой стороны, может произойти утечка потоков, что, конечно же, вызовет это состояние, потому что у вас будет поток, на котором будут ссылаться ссылки на объекты, и вы можете потерять ссылку на поток. Вы все равно можете получить ссылку на Thread через API - http://www.exampledepot.com/egs/java.lang/ListThreads.html
Добавить случайные целые числа в ArrayList в бесконечном цикле.
Попробуйте этот простой класс:
public class Memory {
private Map<String, List<Object>> dontGarbageMe = new HashMap<String, List<Object>>();
public Memory() {
dontGarbageMe.put("map", new ArrayList<Object>());
}
public void useMemInMB(long size) {
System.out.println("Before=" + getFreeMemInMB() + " MB");
long before = getFreeMemInMB();
while ((before - getFreeMemInMB()) < size) {
dontGarbageMe.get("map").add("aaaaaaaaaaaaaaaaaaaaaa");
}
dontGarbageMe.put("map", null);
System.out.println("After=" + getFreeMemInMB() + " MB");
}
private long getFreeMemInMB() {
return Runtime.getRuntime().freeMemory() / (1024 * 1024);
}
public static void main(String[] args) {
Memory m = new Memory();
m.useMemInMB(15); // put here apropriate huge value
}
}
Кажется, что большинство ответов не являются утечками памяти стиля C.
Я думал, что добавлю пример класса библиотеки с ошибкой, которая даст вам исключение из памяти. Опять же, это не настоящая утечка памяти, а пример того, что не хватает памяти, чего вы не ожидаете.
public class Scratch {
public static void main(String[] args) throws Exception {
long lastOut = System.currentTimeMillis();
File file = new File("deleteme.txt");
ObjectOutputStream out;
try {
out = new ObjectOutputStream(
new FileOutputStream("deleteme.txt"));
while (true) {
out.writeUnshared(new LittleObject());
if ((System.currentTimeMillis() - lastOut) > 2000) {
lastOut = System.currentTimeMillis();
System.out.println("Size " + file.length());
// out.reset();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LittleObject implements Serializable {
int x = 0;
}
Вы найдете исходный код и описание ошибки в
Следующий чрезвычайно надуманный класс Box
будет утечка памяти при использовании. Объекты, которые put
в этот класс, в конечном итоге (после другого вызова put
, если быть точным... при условии, что тот же объект не обращается в него.), Недоступный для внешнего мира. Они не могут быть разыменованы через этот класс, но этот класс гарантирует, что они не могут быть собраны. Это РЕАЛЬНАЯ утечка. Я знаю, что это действительно надуманно, но подобные случаи можно сделать случайно.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Stack;
public class Box <E> {
private final Collection<Box<?>> createdBoxes = new ArrayList<Box<?>>();
private final Stack<E> stack = new Stack<E>();
public Box () {
createdBoxes.add(this);
}
public void put (E e) {
stack.push(e);
}
public E get () {
if (stack.isEmpty()) {
return null;
}
return stack.peek();
}
}