写点什么

「Java」几种典型的内存溢出案例,学习 linux 的书籍

用户头像
极客good
关注
发布于: 刚刚

打算把 String 常量池堆满,没想到失败了,JDK1.7 后常量池放到了堆里,也能进行垃圾回收了。


然后换种方式,使用 cglib,用 Class 把老年代取堆满


public static void testPergemOutOfMemory2(){


try {


while (true) {


Enhancer enhancer = new Enhancer();


enhancer.setSuperclass(OOM.class);


enhancer.setUseCache(false);


enhancer.setCallback(new MethodInterceptor() {


@Override


public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {


return proxy.invokeSuper(obj, args);


}


});


enhancer.create();


}


}


catch (Exception e){


e.printStackTrace();


}


}


虚拟机成功内存溢出了,那 JDK 动态代理产生的类能不能溢出呢?


public static void testPergemOutOfMemory3(){


while(true){


final OOM oom = new OOM();


Proxy.newProxyInstance(oom.getClass().getClassLoader(), oom.getClass().getInterfaces(), new InvocationHandler() {


public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


Object result = method.invoke(oom, args);


return result;


}


});


}


}


事实表明,JDK 动态代理差生的类不会造成内存溢出,原因是:JDK 动态代理产生的类信息,不会放到永久代中,而是放在堆中。


本地方法栈溢出


public static void testNativeMethodOutOfMemory(){


int j = 0;


while(true){


Printer.println(j++);


ExecutorService executors = Executors.newFixedThreadPool(50);


int i=0;


while(i++<10){


executors.submit(new Runnable() {


public void run() {


}


});


}


}


}


这个的原理就是不断创建线程池,而每个线程池都创建 10 个线程,这些线程池都是在本地方法区的,久而久之,本地方法区就溢出了。


JVM 栈内存溢出


public static void testStackOutOfMemory(){


while (true) {


Thread thread =


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


new Thread(new Runnable() {


public void run() {


while(true){


}


}


});


thread.start();


}


}


线程的创建会直接在 JVM 栈中创建,但是本例子中,没看到内存溢出,主机先挂了,不是 JVM 挂了,真的是主机挂了,无论在 mac 还是在 windows,都挂了。


温馨提示,这个真的会死机的。


堆溢出


public static void testOutOfHeapMemory(){


List<StringBuffer> list = new ArrayList<StringBuffer>();


while(true){


StringBuffer B = new StringBuffer();


for(int i = 0 ; i < 10000 ; i++){


B.append(i);


}


list.add(B);


}


}


不断往堆中塞新增的 StringBuffer 对象,堆满了就直接溢出了。


测试案例完整代码


public class BlowUpJVM {


//栈深度溢出


public static void testStackOverFlow(){


BlowUpJVM.testStackOverFlow();


}


//不能引起永久代溢出


public static void testPergemOutOfMemory1(){


//方法一失败


List<String> list = new ArrayList<String>();


while(true){


list.add(UUID.randomUUID().toString().intern());


}


}


//永久代溢出


public static void testPergemOutOfMemory2(){


try {


while (true) {


Enhancer enhancer = new Enhancer();


enhancer.setSuperclass(OOM.class);


enhancer.setUseCache(false);


enhancer.setCallback(new MethodInterceptor() {


@Override


public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {


return proxy.invokeSuper(obj, args);


}


});

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
「Java」几种典型的内存溢出案例,学习linux的书籍