2013-12-22 18 views
0

這是我正在嘗試解決的問題,也許是JRE中的一個錯誤,請投票重新打開此問題。如果你沒有足夠的能力去理解某些問題,這是非常自私的方法來標記某個主題。JVM在創建線程和在其中執行網絡操作時發生JVM突然關閉

Java版本

Java版本 「1.7.0_45」 的Java(TM)SE運行時環境(建立1.7.0_45-B18) 的HotSpot的Java(TM)64位服務器VM(建24.45-B08,混合模式)

繼兩個版本碼產生相同的崩潰。

客戶機調用使用在Windows Server上運行的2003 64位,使用Oracle 10g數據庫和Hibernate 3.0的服務器MACHING在Tomcat中部署7一個Servlet。

當我嘗試把負載上的Servlet進行負載測試我寫了下面這只是創建一個線程,並調用同步方法,但沒有登錄我的過程在Eclipse termiates的任何堆棧跟蹤兩種方法。

我不知道崩潰的原因,如果我創建500個線程,然後崩潰487,如果我創建線程1000然後它在874崩潰,我不知道真正的原因是什麼。我配置了一個StuckThreadDetectionValve來檢測長時間運行的線程。

https://stackoverflow.com/a/7484800/185022

我會在這裏分享所有的更新。至少如果你知道什麼可能是錯誤的,請給我一個提示。

**兩個碼產生相同的碰撞**

代碼1:

public class TokenTest { 
    static int count = 0; 

    public static void main(String[] args) { 
     try { 
      System.out.println("Start " + new Date()); 
      final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class); 
      final int max = 50; 
      ExecutorService executor = Executors.newFixedThreadPool(max); 

      for (int i = 1; i <= max; i++) { 

       executor.execute(new Runnable() { 
        public void run() { 
         try { 
          System.out.print(++count +","); 
          app.verifyToken("7056451004350030976"); //Network Synchronous Operation, calls a Servlet that is deployed in another Server Machine, Using Tomcat 7.0 
         } catch (Exception ex) { 
          ex.printStackTrace(); 
         } 

        } 
       }); 
      } 
      executor.shutdown(); 

      while (!executor.isShutdown()) { 
       System.out.println("END " + new Date()); 
      } 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

} 

代碼2:

public class TokenTest { 
    static int count = 0; 

    public static void main(String[] args) { 
     try { 
      System.out.println(new Date()); 
      final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class); 
      final int max=250; 
      for (int i = 1; i <= max; i++) { 
       Thread t = new Thread() { 
        public void run() { 
         app.verifyToken("7056451004350030976");//Network Synchronous Operation 
         System.out.print(count++); 
         System.out.print(", "); 
         if (count >= max) 
          System.out.println("\n" + new Date()); 
        } 
       }; 

       t.start(); 
      } 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 



} 

注: 該服務器託管在另一臺Windows Server 2003 64位機器上。

更新 它只是終止在Eclipse中我的Java進程,如果我給像5000值,那麼它停留在2800的東西,什麼都不會發生既不是終止我的過程。這是一個控制檯快照。

Console

更新* 感謝給S.Yavari。他導致了正確的方向。在Tomcat配置Stuck_Thread_Detection_Valve並中斷該Stuck Threads我能夠生成服務器上500K的客戶端負載線程沒有任何問題,也給人100 miliseconds睡眠開始新的請求之前後。

下面是代碼:

public class StageOne { 

    final ApplicationServiceClient appClient = WSClient.getClient(Main.url, ApplicationServiceClient.class); 
    final SecureWebServiceClient secureClient = WSClient.getClient(Main.url, SecureWebServiceClient.class); 
    final static List<Long> times = new Vector<Long>(); 
    String token = ""; 

    public String authenticateClient() { 

     token = appClient.authenticateClient("az_y", "az", "0"); 
     // System.out.println("Registration Response: " + token); 
     return token; 
    } 

    private void getDefaultDepartmentName() { 

     String deptname = appClient.getDefaultDepartmentName(); 
     // System.out.println("Department: " + deptname); 
    } 

    private void getLocation() { 

     List<String> location = appClient.listLocation(); 
     // System.out.println("Location: " + location); 
    } 

    private void registerClient_() { 
     secureClient.setToken(token); 
     String respon = secureClient.registerClient("Buddy AZ", "443", "njuy", "1"); 

     // System.out.println(respon); 

    } 

    static int count = 0; 

    public static void main(String[] args) { 

     int pool = 500000; 

     final ExecutorService execotors = Executors.newFixedThreadPool(pool); 

     for (int i = 0; i < pool; i++) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      execotors.execute(new Runnable() { 

       @Override 
       public void run() { 

        long startTime = System.nanoTime(); 

        StageOne one = new StageOne(); 

        one.authenticateClient(); 
        one.getDefaultDepartmentName(); 
        one.getLocation(); 
        one.registerClient_(); 

        long EndTime = System.nanoTime(); 

        // System.out.println("Time in Seconds ("+ (++count) +")" + TimeUnit.NANOSECONDS.toSeconds(EndTime - startTime)); 
        times.add(TimeUnit.NANOSECONDS.toSeconds(EndTime - startTime)); 
       } 
      }); 
     } 
     execotors.shutdown(); 

     while (!execotors.isShutdown()) { 
      try { 
       Thread.sleep(10); 
      } catch (Exception e) { 
       // TODO: handle exception 
      } 
     } 

     Collections.sort(times); 
     long sum = 0; 
     for (int i = 0; i < times.size(); i++) { 
      sum += times.get(i); 
     } 
     long result = sum/Math.max(1, times.size()); 


     System.out.println("Min Response Time: " + times.get(0)); 
     System.out.println("Average Response Time: " + result); 
     System.out.println("Max Response Time: " + times.get(times.size() - 1)); 

    } 

} 
+1

請發佈您的JVM崩潰的詳細信息,包括打印的任何錯誤消息。 –

+0

什麼都不打印,它只是在Eclipse中終止我的過程。 –

+1

它可以在Eclipse之外進行復制嗎? –

回答

3

我覺得這只是一個線程問題。使用此代碼:

public class Test2 { 
    public static final Object LOCK = new Object(); 
    static int count = 0; 

    public static void main(String[] args) { 
     try { 
      System.out.println(new Date()); 
      final ApplicationServiceClient app = WSClient.getClient("http://192.168.1.15:81/az-server", ApplicationServiceClient.class); 
      final int max=250; 
      for (int i = 1; i <= max; i++) { 
       Thread t = new Thread() { 
        public void run() { 
         synchronized (LOCK) { 
          app.verifyToken("7056451004350030976"); 
         } 
         System.out.print(count++); 
         System.out.print(", "); 
         if (count >= max) 
          System.out.println("\n" + new Date()); 
        } 
       }; 

       t.start(); 
      } 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

這種方法(verifyToken)必須是線程安全的,否則你將不得不使用內部線程這種方法這麼多的問題。

+0

它不會幫助。我想做負載測試。 –

+1

這不是JVM問題。崩潰在'verifyToken'方法內。這可能是一個線程問題,或者'verifyToken'不能處理250個併發連接。另一種解決方案:如果可以,爲你的'verifyToken'方法設置超時。 –

+1

如果你的服務器沒有響應,並且你的連接超時是無限的,你的代碼將等待響應而沒有任何活動。 –

1

在代碼1中,代碼沒有崩潰。它按設計工作。該代碼似乎沒有任何問題。

+0

因爲你沒有服務器代碼,這真的是一個擁抱系統和一個客戶產品,所以親愛的我擔心我不能泄露任何服務器端代碼 –

+0

好吧,這就是你所說的,但你還沒有證明。 –

+0

請閱讀更新後的問題。 –

相關問題