成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JVM問題情景分析

SnaiLiu / 3092人閱讀

摘要:問題分析之死鎖產(chǎn)生死鎖必須同時滿足以下四個條件互斥條件一段時間內(nèi)某資源只能被一個線程進程占有,若有其他請求線程只能等待。問題分析之內(nèi)存泄露內(nèi)存溢出堆內(nèi)存溢出內(nèi)存泄露指的是申請內(nèi)存后無法釋放該內(nèi)存。

問題分析之死鎖

產(chǎn)生死鎖必須同時滿足以下四個條件:

互斥條件:一段時間內(nèi)某資源只能被一個線程(進程)占有,若有其他請求線程只能等待。

不剝奪條件:一個線程占用某資源后只能該線程自己釋放資源,不能被其他線程奪走。

請求和保持條件:一個線程去申請另外一個資源的時候,繼續(xù)占有已分配的資源。

循環(huán)等待條件:存在一個處于等待狀態(tài)的線程集合{p1,...,pi,..},pi等待的資源被p(i+1)占有。

簡單點說,對于兩個線程A,B而言,先有線程A占有鎖X,線程B占有鎖Y,然后A繼續(xù)申請鎖Y,B繼續(xù)申請鎖X,但由于此時鎖Y已經(jīng)被B占有,A只能等待B釋放鎖Y,同理B也在等待A釋放鎖X。此時形成了一個線程分別等待對方釋放鎖的狀況,即產(chǎn)生了死鎖。

public class DeadLock {
    private static Lock lockA = new ReentrantLock();
    private static Lock lockB = new ReentrantLock();
    
    /*private static Object monitor1 = new Object();
    private static Object monitor2 = new Object();*/

    public static void main(String[] args)  {
        
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        new ThreadA().start();
        new ThreadB().start();
        
    }
    
    static class ThreadA extends Thread{
        
        @Override
        public void run() {
            lockA.lock();
            try {
                Thread.sleep(2000);
                
                lockB.lock();
                System.out.println("in lockB");
                lockB.unlock();
                
            } catch (Exception e) {
                // TODO: handle exception
            }finally{
                lockA.unlock();
            }
            
        /*    synchronized (monitor1) {
            
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (monitor2) {
                    System.out.println("in monitor2");
                }
                
                
            }*/
            
        }
        
        
    }
    
    
    static class ThreadB extends Thread{
        
        @Override
        public void run() {
            lockB.lock();
            
            try{
                
                Thread.sleep(4000);
                
                lockA.lock();
                System.out.println("in lockA");
                lockA.unlock();
                
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                lockB.unlock();
            }
            
        /*    synchronized (monitor2) {
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized(monitor1){
                    System.out.println("in monitor2");
                }
            }
            */
            
        }
        
    }
}

上面代碼是一個簡單的例子,產(chǎn)生死鎖一般可以用jstack命令生成線程快照來分析,當然更好用的有jdk自帶的visualVM圖形化工具。在java_home目錄下的bin文件夾里面,可以找到j(luò)visualVM。在linux下可以使用命令行:

cd $JAVA_HOME/bin
./jvisualvm&

當然JAVA_HOME一般都export到PATH下了,可以直接命令行輸入

jvisualvm&

在visualVM中進入對應(yīng)的進程,可以看到visualVM直接幫助我們檢測到了死鎖:

點擊線程dump按鈕,查看dump堆文件:

由于這里的死鎖程序使用的Lock鎖,可以看到兩個線程Thread-0,Thread-1的狀態(tài)為WAITING(如果使用上面程序注釋掉的synchronized鎖,線程狀態(tài)為阻塞)。Thread-1已擁有鎖的id為<...71bc8>,等待鎖id為<...73008>,相反Thread-0擁有鎖<...73008>,正在等待鎖<...71bc8>。

問題分析之內(nèi)存泄露/內(nèi)存溢出 1. 堆內(nèi)存溢出(outOfMemoryError:java heap space)

內(nèi)存泄露memory leak:指的是申請內(nèi)存后無法釋放該內(nèi)存。在java當中指的是存在無用,而且是可達的(導致jvm無法回收)的對象。
內(nèi)存溢出out of memory:指的是申請內(nèi)存時,已沒有足夠的內(nèi)存空間供使用。
內(nèi)存泄露如果大量的堆積,消耗足夠多的內(nèi)存,最后會產(chǎn)生內(nèi)存溢出。

下面是一個內(nèi)存泄露最終導致內(nèi)存溢出的例子:

public class MemoryLeak {
    public static void main(String[] args) {
        sleep(9000);
        Vector v = new Vector();
        long count = 0;
        while (true) {
            Object o = new Object();
            v.add(o);
            o = null;
            count++;
            if (count % 100 == 0) {
                System.out.println("vector size: " + v.size());
                long freeMem = Runtime.getRuntime().freeMemory()
                        / (1024 * 1024);
                System.out.println("freeMemory is " + freeMem + "M in count->"
                        + count);
            }
        }
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

我們加上jvm啟動參數(shù),將最小和最大堆大小均設(shè)為20M:

-Xms20m -Xmx20m

最后得到溢出異常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.Vector.grow(Vector.java:266)
at java.util.Vector.ensureCapacityHelper(Vector.java:246)
at java.util.Vector.add(Vector.java:782)
at com.ethfoo.jvm.MemoryLeak.main(MemoryLeak.java:17)

代碼當中我們不停的往Vector里面加Object對象,并且每個對象的引用o置為null。我們假設(shè)這些Object已是無用對象,雖然我們將o置為null,但其實Vector里面仍然保存每個Object對象的引用,所以O(shè)bject對jvm來說是可達的,jvm無法對其進行回收。

2. 方法區(qū)內(nèi)存溢出(outOfMemoryError:permgem space)

在jvm規(guī)范中,方法區(qū)主要存放的是類信息、常量、靜態(tài)變量等。
所以如果程序加載的類過多,或者使用反射、gclib等這種動態(tài)代理生成類的技術(shù),就可能導致該區(qū)發(fā)生內(nèi)存溢出,一般該區(qū)發(fā)生內(nèi)存溢出時的錯誤信息為:

outOfMemoryError:permgem space

可以使用jvm參數(shù)調(diào)整方法區(qū)的大小分配:

-XX:PermSize -XX:MaxPermSize

3. 線程棧溢出(StackOverflowError)

一般線程棧溢出是由于遞歸太深或方法調(diào)用層級過多導致的。
可以使用以下參數(shù)來調(diào)整棧大小的分配,線程棧越大遞歸調(diào)用的深度越大,但同時由于總的內(nèi)存大小限制,會使總體能夠啟動的線程數(shù)目減小。

-Xss

4. 直接內(nèi)存溢出(OutOfMemoryError: Direct buffer memory)

試運行以下代碼,直接分配大量堆外內(nèi)存:

public static void main(String args[]){
    for(int i=0; i<3024; i++){
            ByteBuffer.allocateDirect(1024*1024*1024);
            System.out.println(i);
            //System.gc();
    }
}

最后導致結(jié)果:

Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.ethfoo.jvm.OutOfMemory.directMemeory(OutOfMemory.java:28)
at com.ethfoo.jvm.OutOfMemory.main(OutOfMemory.java:10)

需要注意的是,直接內(nèi)存是無法觸發(fā)jvm的內(nèi)存回收機制的,直接內(nèi)存可以被垃圾收集器回收,但是只能是由堆中內(nèi)存觸發(fā)gc,同時順便對直接內(nèi)存進行垃圾收集清理。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/64823.html

相關(guān)文章

  • jvm原理

    摘要:在之前,它是一個備受爭議的關(guān)鍵字,因為在程序中使用它往往收集器理解和原理分析簡稱,是后提供的面向大內(nèi)存區(qū)數(shù)到數(shù)多核系統(tǒng)的收集器,能夠?qū)崿F(xiàn)軟停頓目標收集并且具有高吞吐量具有更可預(yù)測的停頓時間。 35 個 Java 代碼性能優(yōu)化總結(jié) 優(yōu)化代碼可以減小代碼的體積,提高代碼運行的效率。 從 JVM 內(nèi)存模型談線程安全 小白哥帶你打通任督二脈 Java使用讀寫鎖替代同步鎖 應(yīng)用情景 前一陣有個做...

    lufficc 評論0 收藏0
  • 同樣是做后端的,為什么你同學年薪80萬,你20多萬?

    摘要:然而偶爾的一次聚會,你聽說和自己一起出道的同學早已經(jīng)年薪萬,而自己卻囊中羞澀。這個時候,你可能會懷疑自己的能力,也痛恨為什么當初自己沒有好好復(fù)習。 作為一個 Java 程序員,我們深知水平的深淺決定你的收入高低,月工資下到七八千,上到十幾萬都是很正常的事情。許多人的現(xiàn)狀是平時總是陷在業(yè)務(wù)開發(fā)...

    鄒強 評論0 收藏0
  • 作為一名Java程序員,因為偷偷接私活被...

    摘要:接私活對程序員這個圈子來說是一個既公開又隱私的話題,不說全部,應(yīng)該大多數(shù)程序員都有過想要接私活的想法,當然,也有部分得道成仙的不主張接私活。 接私活 對程序員這個圈子來說是一個既公開又隱私的話題,不說全部,應(yīng)該大多數(shù)程序員都有過想要接私活的想法,當然,也有部分得道成仙的不主張接私活。但是很少...

    Aomine 評論0 收藏0
  • 麻了,都是科班出身的,學弟月薪卻是我的3倍。

    摘要:可現(xiàn)在五年過去了,他想跳槽卻鮮有人問津。最可氣的是比他晚一年畢業(yè)的學弟,勤勤懇懇在一家中型互聯(lián)網(wǎng)企業(yè)干了年,現(xiàn)在已經(jīng)跳槽到了阿里,月薪是我這個同學的倍。 我有個同學大學畢業(yè),因為卻少工作經(jīng)驗,又不愿意去正經(jīng)的互聯(lián)網(wǎng)企業(yè)做實習生,他嫌工資太低,于是進了家外包公司,那時候感覺待遇還可以。可現(xiàn)在五...

    wangzy2019 評論0 收藏0
  • Java程序員工作3年,薪資為何會被應(yīng)屆生倒掛?

    摘要:同時也會關(guān)注市場上同崗位薪資,以便對企業(yè)內(nèi)部薪資結(jié)構(gòu)做出相應(yīng)調(diào)整。一般來說,相同崗位和職責的員工,薪資低于市場不超過,都屬于合理范疇,因為一個員工不會為了的薪酬而跳槽。同時,還能激勵員工自我提升,以獲得相應(yīng)技能市場所給予的報酬。 各位職場人都聽說過薪資倒掛這詞兒吧,這個情況在行業(yè)內(nèi)早就不是什...

    szysky 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<