专栏首页呼延Stackoverflow Oom 死锁OOMStackOverFlow死锁

Stackoverflow Oom 死锁OOMStackOverFlow死锁

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

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


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 抽象类和接口的区别

    定义一个抽象类AbstractDoor,作为门的基类,同时定义一个alarmable的接口.(alarmable是我自己写的,我不知道有没有这个单词,大家懂就好...

    呼延十
  • [设计模式] 责任链模式

    使多个对象都有机会处理请求,从而避免请求的发送者与接受者之间的耦合关系. 将多个接受者连成一条链,沿着该链处理请求,直到请求被处理为止.

    呼延十
  • Java中 Json的使用Java JSONGson的使用

    在上述代码中,首先建立一个 JSON 对象,然后依次添加字符串,整数,布尔值以及数组,最后将其打印为字符串。 输出结果如下:

    呼延十
  • Android仿京东手机端类别页

    京东手机端的类别标签页, 是一个左侧滑动可选择类别, 右侧一个类别明细的列表联动页面. 当用户选择左侧选项, 可在右侧显示更多选项来选择. 实现方式也不少. 最...

    砸漏
  • Java中的深复制和浅赋值

    深复制和浅复制也称为深拷贝和浅拷贝。简单的说就是创建一个和当前对象一模一样的对象。在日常编码的过程中使用的几率并不多,但在面试中却会被经常问到。

    老九学堂-小师弟
  • 挑战程序竞赛系列(57):4.6数列上的分治法

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.n...

    用户1147447
  • Android开发仿新闻头条上方滑动菜单事件

    先来看张效果图,在首页部分,上方分为五个标题,可以滑动展示不同主题的内容。最初的实现是在首页这个frament中加入viewpager但是发现数据不显示。

    黄林晴
  • 代理模式(设计模式)

    代理模式,为其他对象提供了一种代理以控制对这个对象的访问。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中...

    WindSun
  • Netty 如何实现心跳机制与断线重连?

    所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性.

    范蠡
  • Netty 如何实现心跳机制与断线重连?

    所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性.

    Java技术栈

扫码关注云+社区

领取腾讯云代金券