欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實戰(zhàn)之OutOfMemoryError異常問題及解決方法

 更新時間:2022年04月18日 10:28:21   作者:怪咖軟妹@  
這篇文章主要介紹了Java實戰(zhàn)之OutOfMemoryError異常,主要結(jié)合著深入理解Java虛擬機一書當(dāng)中整理了本篇內(nèi)容,感興趣的朋友一起看看吧

在Java虛擬機規(guī)范的描述中,除了程序計數(shù)器外,虛擬機內(nèi)存的其他幾個運行時區(qū)域都有發(fā)生OutOfMemoryError (下文稱OOM)異常的可能。本篇主要結(jié)合著【深入理解Java虛擬機】一書當(dāng)中整理了本篇博客,感興趣的跟著小編一塊來學(xué)習(xí)呀!

本篇文章和上一篇寫到的 Java內(nèi)存區(qū)域劃分 息息相關(guān),如果您對Java內(nèi)存區(qū)域劃分不是很了解,建議了解一下,不然這篇文章讀起來會很痛苦。。。

一、簡言

本節(jié)內(nèi)容的目的有兩個:

  • 第一,通過代碼驗證Java虛擬機規(guī)范中描述的各個運行時區(qū)域儲存的內(nèi)容;
  • 第二,希望讀者在工作中遇到實際的內(nèi)存溢出異常時,能根據(jù)異常的信息快速判斷是哪個區(qū)域的內(nèi)存溢出,知道怎樣的代碼可能會導(dǎo)致這些區(qū)域的內(nèi)存溢出,以及出現(xiàn)這些異常后該如何處理。

下面代碼的開頭都注釋了執(zhí)行時所需要設(shè)置的虛擬機啟動參數(shù)(注釋中“VM Args”后面跟著的參數(shù)),這些參數(shù)對實驗的結(jié)果有直接影響,請讀者調(diào)試代碼的時候不要忽略掉。(本篇文章所有案例都采用了JDK1.8版本進行測試)

如果讀者使用控制臺命令來執(zhí)行程序,那直接跟在Java命令之后書寫就可以。如果讀者使用Eclipse IDE,可以在Debug/Run頁簽中的設(shè)置。

二、代碼實戰(zhàn)

1、Java堆溢出

Java堆用于儲存對象實例,我們只要不斷地創(chuàng)建對象,并且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數(shù)量到達最大堆的容量限制后產(chǎn)生內(nèi)存溢出異常。

將Java堆設(shè)置大小為20MB,不可擴展(將堆的最小值-Xms參數(shù)與最大值-Xmx參數(shù)設(shè)置為一樣即可避免堆自動擴展),通過參數(shù)-XX:+HeapDumpOnOutOfMemoryError 可以讓虛擬機在出現(xiàn)內(nèi)存溢出異常時Dump出當(dāng)前的內(nèi)存堆轉(zhuǎn)儲快照以便事后進行分析(內(nèi)存堆轉(zhuǎn)儲快照 指的是溢出后,內(nèi)存當(dāng)中的對象占用情況)。

我用的是ider:

設(shè)置啟動參數(shù):
Xms:最小堆內(nèi)存 Xmx:最大可擴展內(nèi)存
XX:+HeapDumpOnOutOfMemoryError:可以讓虛擬機在出現(xiàn)內(nèi)存溢出異常時Dump出當(dāng)前的內(nèi)存堆轉(zhuǎn)儲快照以便事后進行分析

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
    static class OOMObject{
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true){
            list.add(new OOMObject());
        }
}

運行結(jié)果:

因為設(shè)置了-XX:+HeapDumpOnOutOfMemoryError參數(shù),所以生成了 這個報告??梢圆榭磳ο笳加脙?nèi)存。

Java堆內(nèi)存的OOM異常是實際應(yīng)用中最常見的內(nèi)存溢出異常情況。出現(xiàn)Java堆內(nèi)存溢出時,異常堆棧信息"java.lang.OutOfMemoryError”會跟著進一步提示“Java heapspace"。

要解決這個區(qū)域的異常,一般的手段是首先通過內(nèi)存映像分析工具(如EclipseMemory Analyzer、Dier的jprofiler)對dump出來的堆轉(zhuǎn)儲快照進行分析,重點是確認(rèn)內(nèi)存中的對象是否是必要的,也就是要先分清楚到底是出現(xiàn)了內(nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Overflow)。

如果是內(nèi)存泄漏,可進一步通過工具查看泄漏對象到GC Roots的引用鏈。于是就能找到泄漏對象是通過怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無法自動回收它們的。掌握了泄漏對象的類型信息,以及GC Roots引用鏈的信息,就可以比較準(zhǔn)確地定位出泄漏代碼的位置。

如果不存在泄漏,換句話說就是內(nèi)存中的對象確實都還必須存活著,那就應(yīng)當(dāng)檢查虛擬機的堆參數(shù)(-Xmx與-Xms),與機器物理內(nèi)存對比看是否還可以調(diào)大,從代碼上檢查是否存在某些對象生命周期過長、持有狀態(tài)時間過長的情況,嘗試減少程序運行期的內(nèi)存消耗。

后面我會專門寫一篇關(guān)于內(nèi)存分析工具的博客,XX:+HeapDumpOnOutOfMemoryError這個只是有內(nèi)存占用情況,工具可以幫我們看到對象的引用鏈情況。

2、虛擬機棧和本地方法棧溢出

由于在HotSpot虛擬機中并不區(qū)分虛擬機棧和本地方法棧,因此對于HotSpot來說,-Xoss參數(shù)(設(shè)置本地方法棧大小)雖然存在,但實際上是無效的,棧容量只由-Xss參數(shù)設(shè)定。關(guān)于虛擬機棧和本地方法棧,在Java虛擬機規(guī)范中描述了兩種異常。
注意:HotSpot虛擬機的棧容量是不可以動態(tài)擴展的。

  • 如果線程請求的棧深度大于虛擬機所允許的深度,將拋出StackOverflowError異常
  • 允許棧空間動態(tài)擴展時,當(dāng)擴展時無法申請到足夠的內(nèi)存時會拋出OutOfMemoryError異常
public class JavaVMStackSOF {
    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}
  1. 當(dāng)聲明是基本類型的變量的時,其變量名及值(變量名及值是兩個概念)是放在JAVA虛擬機棧中
  2. 當(dāng)聲明的是引用變量時,所聲明的變量(該變量實際上是在方法中存儲的是內(nèi)存地址值)是放在JAVA虛擬機的棧中,該變量所指向的對象是放在堆類存中的。

實驗結(jié)果表明:在單個線程下,無論是由于棧幀太大,還是虛擬機棧容量太小,當(dāng)內(nèi)存無法分配的時候,虛擬機拋出的都是StackOverflowError異常。換成遠(yuǎn)古時代的Classic虛擬機,這款虛擬機可以支持動態(tài)擴展 棧內(nèi)存的容量,這時候就會報StackOverflowError異常了。

也就是當(dāng)我設(shè)置-Xss128k和不設(shè)置都是報同樣的錯誤,并沒有出現(xiàn)內(nèi)存溢出異常,原因就是 HotSpot虛擬機的棧容量是不可以動態(tài)擴展的,但是值得注意的是我的電腦是16G運行內(nèi)存的,當(dāng)我設(shè)置-Xss128k的時候輸出的長度是將近1000,當(dāng)我不限制-Xss128k大小的時候輸出的長度是20000左右,也就意味著每個線程的棧幀大小默認(rèn)最大是2MB。

如果測試時不限于單線程,通過不斷地建立線程的方式倒是可以產(chǎn)生內(nèi)存溢出異常,在這種情況下,給每個線程的棧分配的內(nèi)存越大,反而越容易產(chǎn)生內(nèi)存溢出異常。

原因其實不難理解,操作系統(tǒng)分配給每個進程的內(nèi)存是有限制的,譬如32位Windows的單個進程 最大內(nèi)存限制為2GB。HotSpot虛擬機提供了參數(shù)可以控制Java堆和方法區(qū)這兩部分的內(nèi)存的最大值。那么虛擬機棧和本地方法棧內(nèi)存如下:

虛擬機棧和本地方法棧內(nèi)存=2GB-最大堆容量-最大方法區(qū)容量-程序計數(shù)器容量

因此為每個線程分配到的棧內(nèi)存越大,可以建立的線程數(shù)量自 然就越少,建立線程時就越容易把剩下的內(nèi)存耗盡。

通過上面了解到,出現(xiàn)StackOverflowError異常時有錯誤堆??梢蚤喿x,相對來說,比較容易找到問題的所在(一般出現(xiàn)死循環(huán)可能會導(dǎo)致)。

如果是建立過多線程導(dǎo)致的內(nèi)存溢出,而不是棧溢出,在不能減少線程數(shù)或者更換64位虛擬機的情況下,就只能通過減少最大堆和減少棧容量來換取更多的線程。如果沒有這方面的經(jīng)驗,這種通過“減少內(nèi)存”的手段來解決內(nèi)存溢出的方式會比較難以想到。

public class JavaVMStackOOM {
    private void dontStop(){
        while (true){

        }
    }

    public void stackLeakByThread(){
        while (true){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }

    public static void main(String[] args) {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

注意 重點提示一下,如果讀者要嘗試運行上面這段代碼,記得要先保存當(dāng)前的工作,由于在 Windows平臺的虛擬機中,Java的線程是映射到操作系統(tǒng)的內(nèi)核線程上,無限制地創(chuàng)建線程會對操 作系統(tǒng)帶來很大壓力,上述代碼執(zhí)行時有很高的風(fēng)險,可能會由于創(chuàng)建線程數(shù)量過多而導(dǎo)致操作系統(tǒng) 假死(電腦可能直接死機)。

在32位操作系統(tǒng)下的運行結(jié)果:
原因:32位有進程大小內(nèi)存限制。

Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread

注意:如果要測試上面內(nèi)存溢出代碼,記住先保存當(dāng)前的工作,避免電腦卡死帶來的麻煩。

3、運行時常量池溢出

由于運行時常量池是方法區(qū)的一部分,所以這兩個區(qū)域的溢出測試可以放到一起進行。前面曾經(jīng) 提到HotSpot從JDK 7開始逐步“去永久代”的計劃,并在JDK 8中完全使用元空間來代替永久代,在此我們就以測試代碼來觀察一下,使用“永久代”還是“元空間”來實現(xiàn)方法區(qū),對程序有什么 實際的影響。

String::intern()是一個本地方法,它的作用是如果字符串常量池中已經(jīng)包含一個等于此String對象的 字符串,則返回代表池中這個字符串的String對象的引用;否則,會將此String對象包含的字符串添加 到常量池中,并且返回此String對象的引用

import java.util.ArrayList;
import java.util.List;

public class RuntimeConstantPoolOOM {
    public static void main(String[] args) {
        // 使用List保持著常量池引用,避免Full GC回收常量池行為
        List<String> list = new ArrayList<>();
        // 10MB的PerSize在integer范圍內(nèi)足夠產(chǎn)生00M
        int i = 0;
        while (true){
            list.add(String.valueOf(i++).intern());
        }
    }
}
  • JDK7及以前(了解):-XX:PermSize設(shè)置永久代初始大小。-XX:MaxPermSize設(shè)置永久代最大可分配空間。(JDK7目前已經(jīng)很少用了,這兩個參數(shù)在JDK8及以后已經(jīng)沒有了,所以不必掌握,了解一下)
  • JDK8及以后:可以使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize設(shè)置元空間初始大小以及最大可分配大小。

使用JDK 7或更高版本的JDK來運行這段程序并不會得到相同的結(jié)果,無論是在JDK 7中繼續(xù)使 用-XX:MaxPermSize參數(shù)或者在JDK 8及以上版本使用-XX:MaxMeta-spaceSize參數(shù)把方法區(qū)容量同 樣限制在6MB,都不會出現(xiàn)溢出異常,循環(huán)將一直進行下去,永不停歇。出現(xiàn)這種變 化,是因為自JDK 7起,原本存放在永久代的字符串常量池被移至Java堆之中,所以在JDK 7及以上版 本,限制方法區(qū)的容量對該測試用例來說是毫無意義的。

在JDK1.7中(包括1.7以上)常量池存儲的不再是對象,而是對象引用,真正的對象是存儲在堆中的。把RuntimeConstantPoolOOM.java運行時的VM參數(shù)改為如下(設(shè)置堆大?。┧荆?/p>

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

運行結(jié)果:

查看生成的堆內(nèi)存快照:

4、方法區(qū)溢出

方法區(qū)用于存放Class的相關(guān)信息,如類名、訪問修飾符、常量池、字段描述、方法描述等。對于這個區(qū)域的測試,基本的思路是運行時產(chǎn)生大量的類去填滿方法區(qū),直到溢出。雖然直接使用Java SE API也可以動態(tài)產(chǎn)生類(如反射時的GeneratedConstructorAccessor 和動態(tài)代理等),但在本次實驗中操作起來比較麻煩。借助CGLib直接操作字節(jié)碼運行時,生成了大量的動態(tài)類。

值得特別注意的是,我們在這個例子中模擬的場景并非純粹是一個實驗,這樣的應(yīng)用經(jīng)常會出現(xiàn)在實際應(yīng)用中:當(dāng)前的很多主流框架,如Spring和Hibernate對類進行增強時,都會使用到CGLib這類字節(jié)碼技術(shù),增強的類越多,就需要越大的方法區(qū)來保證動態(tài)生成的Class可以加載人內(nèi)存。

測試示例:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class JavaMethodAreaOOM {
    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[] args, MethodProxy proxy) throws Throwable {
                    return proxy.invokeSuper(obj, args);
                }
            });
            enhancer.create();
        }
    }

    static class OOMObject {
    }
}

設(shè)置元空間最大空間,和初始化空間參數(shù):
類信息是都存在方法區(qū)的,方法區(qū)在jdk1.8將永久區(qū)改為了元空間。自此以后,常量池在元空間都是存儲的引用。實際對象是在堆中。

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

運行結(jié)果:

方法區(qū)溢出也是一種常見的內(nèi)存溢出異常,一個類如果要被垃圾收集器回收,要達成的條件是比 較苛刻的。在經(jīng)常運行時生成大量動態(tài)類的應(yīng)用場景里,就應(yīng)該特別關(guān)注這些類的回收狀況。這類場 景除了之前提到的程序使用了CGLib字節(jié)碼增強和動態(tài)語言外,常見的還有:大量JSP或動態(tài)產(chǎn)生JSP 文件的應(yīng)用(JSP第一次運行時需要編譯為Java類)、基于OSGi的應(yīng)用(即使是同一個類文件,被不同 的加載器加載也會視為不同的類)等。

5、本機直接內(nèi)存溢出

直接內(nèi)存(Direct Memory)并不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是《Java虛擬機規(guī)范》中 定義的內(nèi)存區(qū)域。但是這部分內(nèi)存也被頻繁地使用,而且也可能導(dǎo)致OutOfMemoryError異常出現(xiàn)。

直接內(nèi)存:可以使用Native函數(shù)庫直接分配堆外內(nèi)存,然后通過一個存儲在Java堆里面的DirectByteBuffer對象作為這塊內(nèi)存的引用`進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復(fù)制數(shù)據(jù)(但是有一點注意,雖然不占用堆內(nèi)存,但是他占用了服務(wù)器內(nèi)存)。

直接內(nèi)存(Direct Memory)的容量大小可通過-XX:MaxDirectMemorySize參數(shù)來指定,如果不 去指定,則默認(rèn)與Java堆最大值(由-Xmx指定)一致。

代碼示例:

越過了DirectByteBuffer類直接通 過反射獲取Unsafe實例進行內(nèi)存分配Unsafe類的getUnsafe()方法指定只有引導(dǎo)類加載器才會返回實 例,體現(xiàn)了設(shè)計者希望只有虛擬機標(biāo)準(zhǔn)類庫里面的類才能使用Unsafe的功能,在JDK 10時才將Unsafe 的部分功能通過VarHandle開放給外部使用),因為雖然使用DirectByteBuffer分配內(nèi)存也會拋出內(nèi)存溢 出異常,但它拋出異常時并沒有真正向操作系統(tǒng)申請分配內(nèi)存,而是通過計算得知內(nèi)存無法分配就會 在代碼里手動拋出溢出異常,真正申請分配內(nèi)存的方法是Unsafe::allocateMemory()。

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public 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);
        }
    }
}

運行參數(shù):

-Xmx20M -XX:MaxDirectMemorySize=10M -XX:+HeapDumpOnOutOfMemoryError

運行結(jié)果:

我設(shè)置了-XX:+HeapDumpOnOutOfMemoryError發(fā)現(xiàn)運行完成之后并沒有發(fā)現(xiàn)有內(nèi)存快照。

由直接內(nèi)存導(dǎo)致的內(nèi)存溢出,一個明顯的特征是在Heap Dump文件中不會看見有什么明顯的異常 情況,如果讀者發(fā)現(xiàn)內(nèi)存溢出之后產(chǎn)生的Dump文件很小,而程序中又直接或間接使用了 DirectMemory(典型的間接使用就是NIO),那就可以考慮重點檢查一下直接內(nèi)存方面的原因了。

三、JVM常用的啟動參數(shù)

堆:

  • -Xms3550m:設(shè)置JVM初始內(nèi)存為3550M。表示初始化JAVA堆的大小及該進程剛創(chuàng)建出來的時候,他的專屬JAVA堆的大小,一旦對象容量超過了JAVA堆的初始容量,JAVA堆將會自動擴容到-Xmx大小。
  • -Xmx3550m:設(shè)置JVM最大可用內(nèi)存為3550M。表示java堆可以擴展到的最大值,在很多情況下,通常將-Xms和-Xmx設(shè)置成一樣的,因為當(dāng)堆不夠用而發(fā)生擴容時,會發(fā)生內(nèi)存抖動影響程序運行時的穩(wěn)定性。

棧:

  • -Xss128k:規(guī)定了每個線程虛擬機棧及堆棧的大小,一般情況下,256k是足夠的,此配置將會影響此進程中并發(fā)線程數(shù)的大?。ê投咽遣灰粯拥?,不支持動態(tài)擴展)。

方法區(qū):

  • JDK7及以前(了解):-XX:PermSize設(shè)置永久代初始大小。
  • -XX:MaxPermSize設(shè)置永久代最大可分配空間。(JDK7目前已經(jīng)很少用了,這兩個參數(shù)在JDK8及以后已經(jīng)沒有了,所以不必掌握,了解一下)-XX:MaxMetaspaceSize=10m:設(shè)置元空間最大值,默認(rèn)是-1,即不限制,或者說只受限于本地內(nèi)存 大小。
  • -XX:MetaspaceSize=10m:指定元空間的初始空間大小,以字節(jié)為單位,達到該值就會觸發(fā)垃圾收集 進行類型卸載,同時收集器會對該值進行調(diào)整:如果釋放了大量的空間,就適當(dāng)降低該值;如果釋放 了很少的空間,那么在不超過-XX:MaxMetaspaceSize(如果設(shè)置了的話)的情況下,適當(dāng)提高該值。
  • -XX:MinMetaspaceFreeRatio:作用是在垃圾收集之后控制最小的元空間剩余容量的百分比,可 減少因為元空間不足導(dǎo)致的垃圾收集的頻率。類似的還有-XX:Max-MetaspaceFreeRatio,用于控制最 大的元空間剩余容量的百分比。

內(nèi)存:

  • -XX:+HeapDumpOnOutOfMemoryError 可以讓虛擬機在出現(xiàn)內(nèi)存溢出異常時Dump出當(dāng)前的內(nèi)存堆轉(zhuǎn)儲快照以便事后進行分析(內(nèi)存堆轉(zhuǎn)儲快照 指的是溢出后,內(nèi)存當(dāng)中的對象占用情況)

GC:

  • -XX:-PrintGCDetails:每次GC時打印詳細(xì)信息。

四、面試題

public static void main(String[] args) {
    String str1 = new StringBuilder("計算機").append("軟件").toString();
    System.out.println(str1.intern() == str1);
    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str2);
}

這段代碼在JDK 6中運行,會得到兩個false,而在JDK 7中運行,會得到一個true和一個false。在jdk1.8運行也是,true、false。

產(chǎn) 生差異的原因是,在JDK 6中,intern()方法會把首次遇到的字符串實例復(fù)制到永久代的字符串常量池 中存儲,返回的也是永久代里面這個字符串實例的引用,而由StringBuilder創(chuàng)建的字符串對象實例在 Java堆上,所以必然不可能是同一個引用,結(jié)果將返回false。

而JDK 7(以及部分其他虛擬機,例如JRockit)的intern()方法實現(xiàn)就不需要再拷貝字符串的實例 到永久代了,既然字符串常量池已經(jīng)移到Java堆中,那只需要在常量池里記錄一下首次出現(xiàn)的實例引 用即可,因此intern()返回的引用和由StringBuilder創(chuàng)建的那個字符串實例就是同一個。
而對str2比較返 回false,這是因為“java”這個字符串在執(zhí)行String-Builder.toString()之前就已經(jīng)出現(xiàn)過了,字符串常量 池中已經(jīng)有它的引用,不符合intern()方法要求“首次遇到”的原則,“計算機軟件”這個字符串則是首次 出現(xiàn)的,因此結(jié)果返回true。(這塊說實話不好理解,說白了就是java是個特殊的字符串,他在常量池里面就一直存在)

總結(jié):在1.8之后通過intern()添加到常量池,只有字符串在常量池不存在的時候才會返回字符串的引用。

五、總結(jié)

到此為止,我們明白了虛擬機里面的內(nèi)存是如何劃分的,哪部分區(qū)域、什么樣的代碼和操作可能 導(dǎo)致內(nèi)存溢出異常。雖然Java有垃圾收集機制,但內(nèi)存溢出異常離我們并不遙遠(yuǎn),本章只是講解了各 個區(qū)域出現(xiàn)內(nèi)存溢出異常的原因,下一章將詳細(xì)講解Java垃圾收集機制為了避免出現(xiàn)內(nèi)存溢出異常都 做了哪些努力。

到此這篇關(guān)于Java實戰(zhàn)之OutOfMemoryError異常的文章就介紹到這了,更多相關(guān)java  OutOfMemoryError異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Spring的ApplicationEvent實現(xiàn)本地事件驅(qū)動的實現(xiàn)方法

    使用Spring的ApplicationEvent實現(xiàn)本地事件驅(qū)動的實現(xiàn)方法

    本文介紹了如何使用Spring的ApplicationEvent實現(xiàn)本地事件驅(qū)動,通過自定義事件和監(jiān)聽器,實現(xiàn)模塊之間的松耦合,提升代碼的可維護性和擴展性。同時還介紹了異步事件和事件傳遞的相關(guān)知識
    2023-04-04
  • Java面試題 從源碼角度分析HashSet實現(xiàn)原理

    Java面試題 從源碼角度分析HashSet實現(xiàn)原理

    這篇文章主要介紹了Java面試題 從源碼角度分析HashSet實現(xiàn)原理?,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • Java通過SSH連接路由器輸入命令并讀取響應(yīng)的操作方法

    Java通過SSH連接路由器輸入命令并讀取響應(yīng)的操作方法

    最近需要讀取和修改華為路由器的配置,使用Java語言開發(fā),通過SSH連接,輸入命令并讀取響應(yīng),接下來通過本文給大家介紹下Java通過SSH連接路由器,輸入命令并讀取響應(yīng),需要的朋友可以參考下
    2024-01-01
  • Java中抽象類用法與注意點實例詳解

    Java中抽象類用法與注意點實例詳解

    這篇文章主要介紹了Java中抽象類用法與注意點,結(jié)合實例形式詳細(xì)分析了java抽象類的定義、使用及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-08-08
  • Spring使用IOC與DI實現(xiàn)完全注解開發(fā)

    Spring使用IOC與DI實現(xiàn)完全注解開發(fā)

    IOC也是Spring的核心之一了,之前學(xué)的時候是采用xml配置文件的方式去實現(xiàn)的,后來其中也多少穿插了幾個注解,但是沒有說完全采用注解實現(xiàn)。那么這篇文章就和大家分享一下,全部采用注解來實現(xiàn)IOC + DI
    2022-09-09
  • Event?Sourcing事件溯源模式優(yōu)化業(yè)務(wù)系統(tǒng)

    Event?Sourcing事件溯源模式優(yōu)化業(yè)務(wù)系統(tǒng)

    這篇文章主要為大家介紹了Event?Sourcing事件溯源模式優(yōu)化業(yè)務(wù)系統(tǒng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • spring是如何實現(xiàn)聲明式事務(wù)的

    spring是如何實現(xiàn)聲明式事務(wù)的

    這篇文章主要介紹了spring是如何實現(xiàn)聲明式事務(wù)的,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring Boot 項目設(shè)置網(wǎng)站圖標(biāo)的方法

    Spring Boot 項目設(shè)置網(wǎng)站圖標(biāo)的方法

    這篇文章主要介紹了Spring Boot 項目設(shè)置網(wǎng)站圖標(biāo)的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • java實現(xiàn)快速打字游戲

    java實現(xiàn)快速打字游戲

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)快速打字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • Jenkins+Maven+SVN自動化部署java項目

    Jenkins+Maven+SVN自動化部署java項目

    這篇文章主要介紹了Jenkins+Maven+SVN自動化部署java項目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論