2015-07-10 78 views
3

我目前正在嘗試編寫一個程序,該程序從蒸汽中獲取字符串化的json對象,並使用該對象確定是否可以在蒸汽市場上購買物品。如何修復java中的內存泄漏

它的工作原理,但我似乎得到大量內存泄漏,我不知道如何解決這個問題,因爲我是一個初學者程序員。這裏是代碼:

import java.io.IOException; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.net.URLConnection; 
import java.util.Scanner; 


public class SteamMarketAlert { 

    @SuppressWarnings("unused") 
    private JAlertWindow alert; 
    private URL jsonUrl; 
    private float walletValue; 
    private boolean itemBuyable; 

    public SteamMarketAlert(URL itemUrl, float walletValue) 
    { 
     this.itemBuyable = false; 
     this.jsonUrl = getJSONurl(itemUrl); 
     this.walletValue = walletValue; 
    } 

    private URL getJSONurl(URL itemUrl) 
    { 
     String jsonString = itemUrl.toString(); 

     String firstPart = jsonString.substring(0, jsonString.indexOf("market/") + "market/".length()); 

     String appid = jsonString.split("/")[5]; 
     String marketHashName = jsonString.split("/")[6]; 

     String secondPart = "priceoverview/?currency=2&appid=" + appid + "&market_hash_name=" + marketHashName; 

     try { 
      return new URL(firstPart + secondPart); 
     } catch (MalformedURLException e) { 
      System.err.println("Failed to create json url"); 
      return null; 
     } 

    } 

    public void checkMarket() 
    { 
     Thread thread = new Thread(){ 
      @Override 
      public void run(){ 
       try { 
        while(!itemBuyable) 
        { 
         sleep(5000);       
         if(isBuyable(getPagehtml())) 
          itemBuyable = true; 
        } 
        alert = new JAlertWindow(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }; 

     thread.start(); 


    } 

    private boolean isBuyable(String pagehtml) 
    { 
     int firstIndex = pagehtml.indexOf(";") +1; 


     float marketValue = Float.parseFloat(pagehtml.substring(firstIndex, firstIndex + pagehtml.substring(firstIndex, pagehtml.length()).indexOf("\""))); 

     return (marketValue <= walletValue)? true:false; 
    } 

    private String getPagehtml(){ 

     try(Scanner scanner = new Scanner(jsonUrl.openConnection().getInputStream())) { 

      scanner.useDelimiter("\\Z"); 
      return scanner.next(); 
     } catch (IOException e) {    
      e.printStackTrace(); 
      return null; 
     } 

    } 

    public static void main(String[] args) 
    { 
     try { 
      float walletValue = 82.64f; 
      URL itemUrl = new  URL("http://steamcommunity.com/market/listings/730/StatTrak%E2%84%A2%20P90%20%7C%20Asiimov%20%28Factory%20New%29"); 
      SteamMarketAlert sma = new SteamMarketAlert(itemUrl,walletValue); 
      sma.checkMarket(); 


     } catch (MalformedURLException e) { 

      e.printStackTrace(); 
     } 

    } 
} 

我已經把問題縮小到checkMarket()方法。但是,我似乎無法弄清楚發生了什麼。你能指出我可以如何解決這個問題(也可能指出我代碼中的所有缺陷),注意JAlertWindow對象只顯示一個帶有「CAN BUY」的JFrame - 沒什麼特別的。

編輯:我更新了自發布和用戶通知我試用資源塊後存在的代碼。感謝所有幫助我理解Java垃圾收集如何工作的人。 :)!

+1

首先,不需要在線程的while循環外部聲明'html'。實際上,您根本不需要'StringBuilder',只需從'getPagehtml'中返回'scanner.next()'的值即可。不是說我會說這對內存泄漏有很大的影響,它只是有點笨拙。 –

+0

請描述「*內存泄漏*」究竟是什麼意思,以及如何證明其存在。 –

+0

當我將它導出到.jar文件並啓動jar時,當它在任務管理器中運行時,內存值隨着時間的推移而上升,因此首先從大約12,000 K開始,然後上升到大約30,000 K 10分鐘......並繼續上升:P。這就是我的意思是內存泄漏。 – James

回答

0

這provbably不是Java的內存泄漏,直到你得到一個OutOfMemoryException或看到不斷垃圾收集。

在10分鐘內使用18MB似乎不像內存泄漏,這正是Java的工作原理。如果你真的想確定,你可以打開詳細的GC,看看它收集的頻率,但我認爲你還沒有真正的問題。

+0

謝謝,我剛剛看到內存不斷攀升,並認爲這是一個問題 - 特別是考慮到我將在相當長的一段時間內運行這個功能。 – James

-4

爲什麼不運行Java分析器?我建議使用YourKit。我用它來查找我在服務器上發生的任何內存泄漏的原因。連接也可以刪除應用程序。你應該玩弄它。

下面是關於如何查找內存泄漏的視頻鏈接; Link

如果您需要更多的幫助,你應該有一個快速的讀通過他們docs

+3

這真的是一個評論,而不是一個答案。有了更多的代表,[你將能夠發表評論](http://stackoverflow.com/privileges/comment)。 –

+0

是的,我從來沒有低估任何你說的話,如果我在尋找內存泄漏方面遇到困難,我會在將來記住這個評論。感謝您的評論。 (我所問的主要問題是沒有發現泄漏,更多的是關於如何修改代碼以避免泄漏) – James

0

您正在提取html頁面,並且因爲某些對象(字符串等)必須分配在每個get的內存中。稍後(一旦不再使用),這些對象將被刪除,內存被GC標記爲空閒。

對不起,很簡單的解釋。如果你想了解更多,請閱讀關於Java GC,堆結構等信息。