2015-07-10 75 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,堆结构等信息。