java虚拟机内存溢出和泄漏实例

时间:2022-12-27 11:58:04

测试参数设置:

1、循环调用new A()实现堆溢出,java.lang.OutOfMemoryError: Java heap space,

虚拟机参数:-Xms1M -Xmx1M -XX:+HeapDumpOnOutOfMemoryError,解释:将-Xmx和-Xms设置为一样可以避免堆自动扩展,-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的堆内存转储快照

1
2
3
//        while (true){
//            new A().do2();
//        }

 

2、循环调用对象引用的方式实现栈溢出。java.lang.*Error,

虚拟机参数:-Xss128k,

解释:设置虚拟机栈的大小为128kn

在单线程下,无论栈帧太大还是虚拟机栈容量太小,内存无法分配的时候都会抛出以上错误

1
2
3
void  do2(){
     do2();
};

 

3、循环调用String.intern()方法来写入常量池,常量池溢出。java.lang.OutOfMemoryError: PermGen space

1
2
3
4
while  ( true )
       {
           list.add(String.valueOf(i++).intern());
       }

 

虚拟机参数:-XX:PermSize=10M -XX:MaxPermSize=10M,

解释:表示JVM初始分配的永久代的容量和最大容量。(永久区内存不足,1.8后都在堆上。方法区=永久代,PermGen space”,即永久代)

 

  • 四种引用状态:(类继承extends WeakReference<Car>)

1、强引用:Object obj = new Object(),只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象;

2、软引用:SoftReference,被软引用关联的对象会在内存不够时被回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常;SoftReference<byte[]> sr = new SoftReference<byte[]>(bytes);

3、弱引用:WeakReference,被弱引用关联的对象只能生存到下一次垃圾回收之前;

4、虚引用:PhantomReference,虚引用是用于跟踪对象的回收状态

 

触发GC的时机:

1、当年轻代或者老年代满了,Java虚拟机无法再为新的对象分配内存空间了,那么Java虚拟机就会触发一次GC去回收掉那些已经不会再被使用到的对象

2、System.gc(),Runtime.getRuntime().gc()方法,通常这样会触发一次的Full GC以及至少一次的Minor GC,不一定就立即回收。

3、在当前服务器空闲或堆中老年代等占用率较大时触发。

回收无引用对象占据的空间,而不是对象本身。

但真正垃圾回收机制具体在什么时间点开始发生动作这同样是不可预料的(未开源),这和抢占式的线程在发生作用时的原理一样。

 

分代收集算法:

新生代收集器和老年代收集器。

标记-清除算法

标记-整理算法

 

内存溢出和内存泄露的区别:

1、内存溢出:程序在分配内存的时候没有足够大的空间了。

2、内存泄漏:程序在申请内存之后,没有办法释放掉内存,它始终占用着内存,即被分配的对象可达但无用。内存泄露一般都是因为内存中有一块很大的对象,但是无法释放。            会导致内存溢出。

并行与并发:

1、并行:指多条垃圾收集器线程运行;

2、并发:指用户线程和垃圾收集器线程同时工作。

类加载机制:

1、加载(生成java.lang.class对象)、验证、准备、解析、初始化(赋值过程)、使用(Using)和卸载(Unloading)这7个阶段

2、其中验证(字节流包含的信息是否正确,是否符合jvm)、

            准备(为类变量即静态变量赋值,赋0)、

            解析(将符号引用替换为直接引用,class文件转内存)3个部分统称为连接(Linking)

3、加载阶段:获取.class文件的二进制流;

                       将类信息、静态变量、字节码、常量这些.class文件中的内容放入方法区

                       在内存中生成一个代表这个.class文件的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

4、初始化阶段做的事就是调用client>方法给static变量赋予用户指定的值以及执行静态代码块。

双亲委派模型:(启动类加载器>扩展类加载器>应用程序类加载器>自定义类加载器)

一个类加载器收到了类加载的请求,把这个请求委派给父类加载器去完成,父类完不成,自己才去完成。

先行发生原则:

Java内存中的有序性仅仅依靠synchronized和volatile来约束是不行,依靠程序调用次序规则判断setter和getter顺序。

 

Minor GC :  清理年轻带内存, 无法为一个新的对象分配空间。

Major GC : 是清理老年代,许多 Major GC 是由 Minor GC 触发的

Full GC : 是清理整个堆空间—包括年轻代和老年代