Эта статья участвует в "Месяце тем Java - Заметки по отладке Java", подробности см.Ссылка на мероприятие
Вопрос: Как создать утечку памяти в java?
У меня только что было интервью, где меня попросили создать утечку памяти в Java.
Излишне говорить, что я чувствую себя глупо и даже не знаю, как начать его создавать.
Что такое пример?
Оценки ответили:
Вот хороший способ создать настоящие утечки памяти (объекты, к которым нельзя получить доступ с помощью запущенного кода, но которые все еще хранятся в памяти) в чистой Java:
1. Приложение создает продолжительный поток (или еще быстрее происходит утечка с использованием пула потоков).
2. Поток загружает класс через (необязательно пользовательский). ClassLoader
3. Класс выделяет много памяти (например), сохраняет сильную ссылку на него в статическом поле, а затем сохраняет ссылку в файле . Выделение дополнительной памяти необязательно (достаточно утечки экземпляра класса), но это ускорит утечку. новый байт[1000000]ThreadLocal
-
Приложение очищает пользовательский класс или любые ссылки, которые оно загружает. ClassLoader
-
повторить.
Поскольку этот метод реализован в Oracle JDK, это создает утечку памяти: ThreadLocal
Каждое поле имеет приватное поле, в котором фактически хранятся локальные значения потока. ThreadthreadLocals Каждый ключ в этой карте является слабой ссылкой на объект, поэтому, когда объект очищается сборщиком мусора, его запись удаляется из карты. ThreadLocalThreadLocal Но каждое значение является строгой ссылкой, поэтому, когда значение указывает (прямо или косвенно) на свой ключевой объект, этот объект не удаляется сборщиком мусора и не удаляется с карты, пока поток остается активным. ThreadLocal В этом примере цепочка сильных ссылок выглядит так:
Объект потока → Класс примера карты → Класс примера → Статическое поле → Класс примера объекта → Экземпляр. threadLocalsThreadLocalThreadLocal
(Уязвимость на самом деле не играет роли в создании утечки, она просто усугубляет утечку из-за этой дополнительной цепочки ссылок: класс-пример → → все классы, которые он загружает. Во многих реализациях JVM это хуже, особенно до Java 7, потому что классы и s были размещены непосредственно в постоянных генах и вообще не подвергались сборке мусора.
Вариантом этого шаблона является то, почему контейнер приложения (например, Tomcat) может пропускать память, как решето, если вы часто повторно развертываете приложение, которое использует s, каким-то образом указывая на себя. Это может произойти по многим тонким причинам, и часто их трудно отладить и/или исправить. ThreadLocal
import java.io.IOException;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
/**
* Example demonstrating a ClassLoader leak. 演示类加载器泄漏的示例。
*
* <p>To see it in action, copy this file to a temp directory somewhere,
* and then run:o查看它的运行情况,将此文件复制到某个临时目录中,然后跑
* <pre>{@code
* javac ClassLoaderLeakExample.java
* java -cp . ClassLoaderLeakExample
* }</pre>
*
* <p>And watch the memory grow! On my system, using JDK 1.8.0_25, I start
* getting OutofMemoryErrors within just a few seconds.看着记忆成长!在我的系统上,使用jdk1.8.0\u25
*只需几秒钟就可以摆脱内存错误
*
* <p>This class is implemented using some Java 8 features, mainly for
* convenience in doing I/O. The same basic mechanism works in any version
* of Java since 1.2.
这个类是使用一些Java8特性实现的,主要用于
*方便进行I/O。相同的基本机制适用于任何版本
*从1.2开始的Java。
*/
public final class ClassLoaderLeakExample {
static volatile boolean running = true;
public static void main(String[] args) throws Exception {
Thread thread = new LongRunningThread();
try {
thread.start();
System.out.println("Running, press any key to stop.");
System.in.read();
} finally {
running = false;
thread.join();
}
}
/**
* Implementation of the thread. It just calls {@link #loadAndDiscard()}
* in a loop.
*/
static final class LongRunningThread extends Thread {
@Override public void run() {
while(running) {
try {
loadAndDiscard();
} catch (Throwable ex) {
ex.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
System.out.println("Caught InterruptedException, shutting down.");
running = false;
}
}
}
}
/**
* A simple ClassLoader implementation that is only able to load one
* class, the LoadedInChildClassLoader class. We have to jump through
* some hoops here because we explicitly want to ensure we get a new
* class each time (instead of reusing the class loaded by the system
* class loader). If this child class were in a JAR file that wasn't
* part of the system classpath, we wouldn't need this mechanism.
*/
static final class ChildOnlyClassLoader extends ClassLoader {
ChildOnlyClassLoader() {
super(ClassLoaderLeakExample.class.getClassLoader());
}
@Override protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
if (!LoadedInChildClassLoader.class.getName().equals(name)) {
return super.loadClass(name, resolve);
}
try {
Path path = Paths.get(LoadedInChildClassLoader.class.getName()
+ ".class");
byte[] classBytes = Files.readAllBytes(path);
Class<?> c = defineClass(name, classBytes, 0, classBytes.length);
if (resolve) {
resolveClass(c);
}
return c;
} catch (IOException ex) {
throw new ClassNotFoundException("Could not load " + name, ex);
}
}
}
/**
* Helper method that constructs a new ClassLoader, loads a single class,
* and then discards any reference to them. Theoretically, there should
* be no GC impact, since no references can escape this method! But in
* practice this will leak memory like a sieve.
构造一个新的类加载器,加载一个类,
*然后丢弃对它们的任何引用。理论上,应该有
*没有GC影响,因为没有引用可以转义这个方法!但是在
*练习这个会像筛子一样漏掉记忆。
*/
static void loadAndDiscard() throws Exception {
ClassLoader childClassLoader = new ChildOnlyClassLoader();
Class<?> childClass = Class.forName(
LoadedInChildClassLoader.class.getName(), true, childClassLoader);
childClass.newInstance();
// When this method returns, there will be no way to reference
// childClassLoader or childClass at all, but they will still be
// rooted for GC purposes!
}
/**
* An innocuous-looking class. Doesn't do anything interesting.
*/
public static final class LoadedInChildClassLoader {
// Grab a bunch of bytes. This isn't necessary for the leak, it just
// makes the effect visible more quickly.
// Note that we're really leaking these bytes, since we're effectively
// creating a new instance of this static final field on each iteration!
static final byte[] moreBytesToLeak = new byte[1024 * 1024 * 10];
private static final ThreadLocal<LoadedInChildClassLoader> threadLocal
= new ThreadLocal<>();
public LoadedInChildClassLoader() {
// Stash a reference to this class in the ThreadLocal
threadLocal.set(this);
}
}
}
Проще говоря: продолжайте создавать объекты.
Высокий балл ответа:
Статические поля содержат ссылки на объекты [особенно окончательные поля]
class MemorableClass {
static final ArrayList list = new ArrayList(100);
}
вызвать String.intern() для длинной строки
String str=readString(); // read lengthy string any source db,textbox/jsp etc..
// This will place the string in memory pool from which you can't remove
str.intern();
(не закрытый) открытый поток (файл, сеть и т.д.)
try {
BufferedReader br = new BufferedReader(new FileReader(inputFile));
...
...
} catch (Exception e) {
e.printStacktrace();
}
незамкнутое соединение
try {
Connection conn = ConnectionFactory.getConnection();
...
...
} catch (Exception e) {
e.printStacktrace();
}
Области, недоступные сборщику мусора JVM, например память, выделенная с помощью собственных методов.
В веб-приложении некоторые объекты хранятся в области приложения до тех пор, пока приложение не будет явно остановлено или удалено.
getServletContext().setAttribute("SOME_MAP", map);
Неправильные или неуместные варианты JVM, такие как варианты на IBM JDK, предотвратить неиспользуемую коллекцию мусора NOCLASSGC
См. раздел Параметры IBM JDK.
Статья переведена сstackoverflow.com/questions/6…
Предложение автора: Всегда обращайте внимание на каждое из вышеперечисленных
Искренне благодарю красивых и красивых девушек за то, что увидели это.Если эта статья будет хорошо написана, если вы почувствуете, что есть что-то
Ставьте лайк 👍 Подписывайтесь ❤️ Делитесь 👥 Мне очень полезно с 8 пакетами пресса! ! !
Если в этом блоге есть какие-либо ошибки, пожалуйста, критикуйте и советуйте, это очень ценится! ❤️❤️❤️❤️