<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:工作中常見OOM有哪些?

          共 9429字,需瀏覽 19分鐘

           ·

          2024-04-19 18:19

          面試題大全:www.javacn.site

          今天接著線上問題這個話題,跟大家一起聊聊線上服務出現(xiàn)OOM的場景有哪些?希望對你會有所幫助。

          1 堆內存OOM

          堆內存OOM是最常見的OOM了。

          出現(xiàn)堆內存OOM問題的異常信息如下:

          java.lang.OutOfMemoryError: Java heap space

          此OOM是由于JVM中heap的最大值,已經不能滿足需求了。

          舉個例子:

          public class HeapOOMTest {

              public static void main(String[] args) {
                  List<HeapOOMTest> list = Lists.newArrayList();
                  while (true) {
                      list.add(new HeapOOMTest());
                  }
              }
          }

          這里創(chuàng)建了一個list集合,在一個死循環(huán)中不停往里面添加對象。

          執(zhí)行結果:出現(xiàn)了java.lang.OutOfMemoryError: Java heap space的堆內存溢出。

          很多時候,excel一次導出大量的數(shù)據,獲取在程序中一次性查詢的數(shù)據太多,都可能會出現(xiàn)這種OOM問題。

          我們在日常工作中一定要避免這種情況。

          2 棧內存OOM

          有時候,我們的業(yè)務系統(tǒng)創(chuàng)建了太多的線程,可能會導致棧內存OOM。

          出現(xiàn)堆內存OOM問題的異常信息如下:

          java.lang.OutOfMemoryError: unable to create new native thread

          給大家舉個例子:

          public class StackOOMTest {
              public static void main(String[] args) {
                  while (true) {
                      new Thread().start();
                  }
              }
          }

          使用一個死循環(huán)不停創(chuàng)建線程,導致系統(tǒng)產生了大量的線程。

          執(zhí)行結果:如果實際工作中,出現(xiàn)這個問題,一般是由于創(chuàng)建的線程太多,或者設置的單個線程占用內存空間太大導致的。

          建議在日常工作中,多用線程池,少自己創(chuàng)建線程,防止出現(xiàn)這個OOM。

          3 棧內存溢出

          我們在業(yè)務代碼中可能會經常寫一些遞歸調用,如果遞歸的深度超過了JVM允許的最大深度,可能會出現(xiàn)棧內存溢出問題。

          出現(xiàn)棧內存溢出問題的異常信息如下:

          java.lang.StackOverflowError

          例如:

          public class StackFlowTest {
              public static void main(String[] args) {
                  doSamething();
              }

              private static void doSamething() {
                  doSamething();
              }
          }

          執(zhí)行結果:

          出現(xiàn)了java.lang.StackOverflowError棧溢出的錯誤。

          我們在寫遞歸代碼時,一定要考慮遞歸深度。即使是使用parentId一層層往上找的邏輯,也最好加一個參數(shù)控制遞歸深度。防止因為數(shù)據問題導致無限遞歸的情況,比如:id和parentId的值相等。

          4 直接內存OOM

          直接內存不是虛擬機運行時數(shù)據區(qū)的一部分,也不是《Java虛擬機規(guī)范》中定義的內存區(qū)域。

          它來源于NIO,通過存在堆中的DirectByteBuffer操作Native內存,是屬于堆外內存,可以直接向系統(tǒng)申請的內存空間。

          出現(xiàn)直接內存OOM問題時異常信息如下:

          java.lang.OutOfMemoryError: Direct buffer memory

          例如下面這樣的:

          public class DirectOOMTest {

              private static final int BUFFER = 1024 * 1024 * 20;

              public static void main(String[] args) {
                  ArrayList<ByteBuffer> list = new ArrayList<>();
                  int count = 0;
                  try {
                      while (true) {
                          // 使用直接內存
                          ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
                          list.add(byteBuffer);
                          count++;
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  } finally {
                      System.out.println(count);
                  }
              }
          }

          執(zhí)行結果:

          會看到報出來java.lang.OutOfMemoryError: Direct buffer memory直接內存空間不足的異常。

          5 GC OOM

          GC OOM是由于JVM在GC時,對象過多,導致內存溢出,建議調整GC的策略。

          出現(xiàn)GC OOM問題時異常信息如下:

          java.lang.OutOfMemoryError: GC overhead limit exceeded

          為了方便測試,我先將idea中的最大和最小堆大小都設置成10M:

          -Xmx10m -Xms10m

          例如下面這個例子:

          public class GCOverheadOOM {
              public static void main(String[] args) {
                  ExecutorService executor = Executors.newFixedThreadPool(5);
                  for (int i = 0; i < Integer.MAX_VALUE; i++) {
                      executor.execute(() -> {
                          try {
                              Thread.sleep(10000);
                          } catch (InterruptedException e) {
                          }
                      });
                  }
              }
          }

          執(zhí)行結果:

          出現(xiàn)這個問題是由于JVM在GC的時候,對象太多,就會報這個錯誤。

          我們需要改變GC的策略。

          在老代80%時就是開始GC,并且將-XX:SurvivorRatio(-XX:SurvivorRatio=8)和-XX:NewRatio(-XX:NewRatio=4)設置的更合理。

          6 元空間OOM

          JDK8之后使用Metaspace來代替永久代,Metaspace是方法區(qū)在HotSpot中的實現(xiàn)。

          Metaspace不在虛擬機內存中,而是使用本地內存也就是在JDK8中的ClassMetadata,被存儲在叫做Metaspace的native memory。

          出現(xiàn)元空間OOM問題時異常信息如下:

          java.lang.OutOfMemoryError: Metaspace

          為了方便測試,我修改一下idea中的JVM參數(shù),增加下面的配置:

          -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m

          指定了元空間和最大元空間都是10M。

          接下來,看看下面這個例子:

          public class MetaspaceOOMTest {
              static class OOM {
              }

              public static void main(String[] args) {
                  int i = 0;
                  try {
                      while (true) {
                          i++;
                          Enhancer enhancer = new Enhancer();
                          enhancer.setSuperclass(OOM.class);
                          enhancer.setUseCache(false);
                          enhancer.setCallback(new MethodInterceptor() {
                              @Override
                              public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                                  return methodProxy.invokeSuper(o, args);
                              }
                          });
                          enhancer.create();
                      }
                  } catch (Throwable e) {
                      e.printStackTrace();
                  }
              }
          }

          執(zhí)行結果:程序最后會報java.lang.OutOfMemoryError: Metaspace的元空間OOM。

          這個問題一般是由于加載到內存中的類太多,或者類的體積太大導致的。

          好了,今天的內容先分享到這里,下一篇文章重點給大家講講,如何用工具定位OOM問題,敬請期待。

          課程推薦

          《Java 面試突擊訓練營》是有著 14 年工作經驗(前 360 開發(fā)工程師),9 年面試官經驗的我,花費 4 年時間打磨完成的一門視頻面試課

          整個課程從 Java 基礎到微服務 Spring Cloud、從實際開發(fā)問題到場景題應有盡有,包含模塊如下:

          訓練營系統(tǒng)的帶領大家把 Java 常見的面試題過一遍,遇到一個問題,把這個問題相關的內容都給大家講明白,并且視頻支持永久觀看和一直更新。并且面試訓練營還提供 10 大就業(yè)服務。

          上完訓練營的課程之后,基本可以應對目前市面上絕大部分公司的面試了,想要了解詳情,加我微信:GG_Stone【備注:訓練營】

          瀏覽 95
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久天天操 | 亚洲国产成人精品女人久久久 | 大香蕉久操视频 | 人妻无码中文字幕蜜桃 | 18 无码 高潮 蜜臀 |