JVM深入浅出(二)--了解JVM内存溢出
来源:互联网 发布:虚拟机优化显卡性能 编辑:程序博客网 时间:2024/05/21 12:41
JVM内存溢出大概分为以下几种情况:
1.内存中加载的数据量过大。
比如一次性从数据库加载过多的数据。
2.并发数量太高。
并发数量太高,导致在短时间内创建大量的对象,GC也不及回收。
public class HeapOOM {
public class NewObjectTest { static class ObjectTest { } public static void main(String[] args) { List<ObjectTest > list = new ArrayList<ObjectTest >(); while (true) { list.add(new ObjectTest ()); } }
}
程序输出:
/**
* java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid1820.hprof …
Heap dump file created [24787111 bytes in 0.346 secs]
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2760)
at java.util.Arrays.copyOf(Arrays.java:2734)
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
at java.util.ArrayList.add(ArrayList.java:351)
at com.jacx.NewObjectTest .main(HeapOOM.java:19) `
*/
这是由于集合类中有无用对象的引用,使用完后没有立即清除。
集合类中的对象,如果不手动进行清除,GC不是不会对集合中无用的对象进行回收。
同事代码中存在死循环,递归,或者循环次数过多产生大量的对象。也会导致内存溢出
//线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError如果虚拟机在扩展栈时无法申请到足够的内存空间,将抛出OutOfMemoryError。public class JavaVMStackOOM { int i=0; private void dontStop() { while (true) { } } public void stackLeakByThread() { while (true) { Thread thread = new Thread(new Runnable() { @Override public void run() { dontStop(); } }); i++; System.out.println("i="+i); thread.start(); } } public static void main(String[] args) throws Throwable { JavaVMStackOOM oom = new JavaVMStackOOM(); try { oom.stackLeakByThread(); } catch (Throwable e) { System.out.println("thread num:" + oom.i); throw e; } } }
3.直接内存溢出
虽然使用DerictByteBuffer分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配,而是通过计算得知内存无法分配,于是手动抛出异常,真正申请分配内存的方法是unsafe.allocateMemorypublic class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024; 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); } }
} 法区内存溢出。
方法区存放的是Class类型信息,类名,常量池,修饰符,方法描述等信息。
使用了过多的静态变量。常量池也被大量的占用。
jvm在“运行期间” 产生了大量的类。导致填满了方法区。比如使用反射,动态代理,字节码生成技术会在运行期间产生大量的类和类型信息。如hibernate,spring第三方框架大量使用了cglib技术产生大量的动态类。
大量的jsp在编译生成java类时也有可能产生方法区溢出,GC对方法区的回收非常苛刻的,因为对于一个类的回收条件就很严格。
总而言之:当运行时常量池过大或者类过多时就会导致方法区溢出。
public static void main(String[] args) { // 使用List保持着常量池中对象的引用,避免JAVA回收机制回收常量池行为 List<String> list = new ArrayList<String>(); int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } }
//循环实现方式 public static void main(String[] args) { while (true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable { // TODO Auto-generated method stub return proxy.invokeSuper(obj, arg); } }); enhancer.create(); } } static class OOMObject { }
5.启动时 JVM 内存参数设置过小。这个改变-Xms -Xmx 属性就可以了
- JVM深入浅出(二)--了解JVM内存溢出
- JVM内存溢出分析
- jvm内存溢出
- JVM内存溢出监控
- jvm内存溢出分析
- jvm内存溢出解决方案
- JVM内存溢出
- JVM 内存溢出
- myeclipse-----jvm内存溢出
- jvm内存溢出
- jvm内存溢出问题解决
- JVM虚拟机内存溢出
- JVM:内存溢出问题
- Java JVM:内存溢出
- jvm内存溢出解决办法
- JVM内存溢出示例
- JVM内存溢出
- jvm 内存溢出
- node.js chrome v8简介
- BaseActivity和BaseFragment 的封装
- Mosquitto简介及搭建
- Spring Boot干货系列:(七)默认日志框架配置
- HDFS encryption 实战之背景和架构介绍
- JVM深入浅出(二)--了解JVM内存溢出
- RabbitMQ实战
- WINDOWS编程--32程序操作系统的注册表项的方法
- 将c++封装成dll库及vs调用dll
- PAT_乙级_1010_筱筱
- matlab集合操作
- 混合式app ionic2.x 手动搭建开发环境教程分享(nodejs,jdk,ant,androidsdk)
- Jenkins+maven+SVN+Tomcat持续集成发布环境安装和配置
- 全文检索原理及实现方式