内存溢出分析
溢出区域
内存溢出分为堆内存溢出和栈内存溢出
如果虚拟机在扩展堆时无法申请到足够大的内存空间时,就会抛出outOfMemoryError
如果线程请求的栈深度大于虚拟机所允许的最大深度,则抛出StackOverflflowError
栈溢出
public class TestOverFlow { public static void main(String[] args) { pop(); } public static void pop(){ pop(); } }
堆溢出
public static void main(String[] args) { List<String> list = new ArrayList<>(); while (true) { list.add("Hello"); } //pop(); }
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/xianghan/Desktop/bak -Xmx2m -Xms2m
生成的二进制文件格式为hprof,可以使用jprofifile打开分析具体导致异常的代码
线程数过多导致堆溢出
PS:此代码慎执行!!!! !!!在执行前一定小心保存当前工作内容,防止机器卡死
public static void main(String[] args) { try { while (true){ Thread thread=new Thread(new Runnable() { @Override public void run() { while (true){ } } }); System.out.println(thread.getName()); thread.start(); } } catch (Exception e) { e.printStackTrace(); } }
常量池溢出
// -Xmx10m -Xms10m public static void main(String[] args) { List<String> list = new ArrayList<>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } }
String.intern()是一个Native方法,它的作用是:如果字符串常池中已包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象,否则将此String对象包含的字符串添加到常池中,并且返回此string对象的引用。在JDK1.6及之前的版本中,由于常池分配在永久代内,我们可以通过-XX:PermSize=10M -XX:MaxPermSize=10M。MaxPermSize限制方法区大小从而间接限制其中常量池的容量。
本机直接内存溢出
如果不指定MaxDirectMemorySize那么直接内存与堆内存一样大 PS:运行此代码风险较大直接死机
public static int _1MB=1024*1024; //-Xmx20M -XX:MaxDirectMemorySize=10M public static void main(String[] args) throws Exception{ Field unsafeField= Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe =(Unsafe) unsafeField.get(null); while (true){ unsafe.allocateMemory(_1MB); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!