OOM,StackOverFlow以及死锁的测试

12 篇文章 0 订阅
2 篇文章 0 订阅

这篇文章主要是记录自己做的一些小的测试.主要包括内存溢出,栈溢出,以及死锁问题.

PS:文章中使用了Arthas工具,用来动态监控JVM的一些资源,非常好用,强烈安利一下.

OOM

OutOfMemory ,内存不够用了,一般是什么原因呢?

  1. 给应用程序分配的内存太小,只能通过增大内存来解决.

  2. 内存泄漏.有一部分内存"无用"了,但是因为编码问题导致的没有被垃圾回收掉,产生了泄漏,最终导致了内存溢出(OOM).

我们来手动写一个OOM.

package javatest;

import java.util.HashMap;
import java.util.Map;

/**
 * created by huyanshi on 2019/3/6
 */
public class OOMTest {

  static class Key{
    int id;

    public Key(int i){
      int id;
    }

    @Override
    public int hashCode() {
      return this.id;
    }
  }

  public static void main(String [] args ) {

    Map<Key, String> testMap = new HashMap<>();
    while (true) {
      for (int i = 0; i < 10000; i++) {
        if (!testMap.containsKey(new Key(i))) {
          testMap.put(new Key(i), "Number:" + i);
        }
      }
    }
  }

}

注意:直接运行可能得到OOM有点慢,可以设置一下Xmx参数小一点.

实现原理:不断的new出新的对象,并将它们放进一个Map里面保持引用.这样一直无法回收,终会OOM.

同时,也可以通过一些工具,比如阿里的Arthas来动态的监控JVM的内存使用情况,如下图.

是可以肉眼看到内存使用量以及占用率不断上升的.

StackOverFlow

栈溢出,首先和内存溢出一样,我们考虑一下栈里面放的是什么?

执行方法时的一些调用环境(比如参数及局部变量),那么什么时候会栈溢出呢?

  1. 无限的递归,相当于你的参数无限多,那么栈放不下.

  2. 局部变量太大了,正常分配的栈空间(1M)不够用.

我们用递归来实现一下:

package javatest;

/**
 * created by huyanshi on 2019/3/6
 */
public class StackOverFlowTest {


  public static void main(String[] args) {

    new StackOverFlowTest().fun(10);
  }


  public int fun(int n) {
    return fun(n);
  }

}

所以当发生StackOverFlow的时候,记得检查一下递归调用的结束条件.

死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

造成死锁的条件有四个:

  1. 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

  2. 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

  3. 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

  4. 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

手动写一个:

package javatest;

/**
 * created by huyanshi on 2019/3/6
 */
public class DeadLockTest {

  public static void main(String[] args) {
    Sy sy = new Sy(0);
    Sy sy2 = new Sy(1);
    sy.start();
    sy2.start();
  }
}

class Sy extends Thread {

  private int flag;

  static Object x1 = new Object();
  static Object x2 = new Object();

  public Sy(int flag) {
    this.flag = flag;
  }

  @Override
  public void run() {
    System.out.println(flag);
    try {
      if (flag == 0) {
        synchronized (x1) {
          System.out.println(flag + "锁住了x1");
          Thread.sleep(1000);
          synchronized (x2) {
            System.out.println(flag + "锁住了x2");
          }
          System.out.println(flag + "释放了x1和x2");
        }
      }
      if (flag == 1) {
        synchronized (x2) {
          System.out.println(flag + "锁住了x2");
          Thread.sleep(1000);
          synchronized (x1) {
            System.out.println(flag + "锁住了x1");
          }
          System.out.println(flag + "释放了x1和x2");
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

实现原理:

定义一个类,类有两个静态对象对象,创建一个对象去锁住1,然后请求对2加锁.

再创建一个对象锁住2,然后请求对1加锁.

使用的锁为synchronized关键字.

然后使用监控工具查看当前jvm的线程,可以发现main方法中启动的两个线程阻塞住了.而且一直也无法释放.


完.





ChangeLog
2019-03-06 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见个人博客------>呼延十

OOM是指Out of Memory,即内存溢出。在Java中,当程序需要的内存超过了JVM分配给程序的内存限制时,就会发生OOM错误。一种常见的情况是堆内存溢出,当程序不断创建新对象占用堆内存时,如果堆内存的大小不够,就会导致OOM错误。引用中提到的方法区溢出也是一种OOM错误,当方法区的内存占用已经达到最大值时,进一步尝试存储类信息将导致溢出异常。 StackOverflow是指栈溢出错误。在Java中,每个线程都有一个与之关联的栈,栈以帧为单位保持线程运行状态。当一个线程调用一个方法时,JVM会将一个新的栈帧压入栈中,只有当方法返回后,该栈帧才会消失。如果方法的嵌套调用层次太多,导致栈中的帧数量超过了设置的栈大小(通过-Xss设置),就会发生StackOverflowError溢出异常。引用中解释了当方法的嵌套调用层次太多时,栈中的帧数量超过栈大小的情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [StackOverflowOOM的区别](https://blog.csdn.net/JAVA_I_want/article/details/103136271)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值