2010-04-20 91 views
3

我們有一個很大的java代碼庫[〜1 M Lines]。在大型Java程序中查找輸出到System.out的錯誤輸出

代碼庫中的(某處)埋沒了一些舊的調試輸出到System.out,我們想要刪除(其混亂的東西了)。

問題是:out code base非常大,我們無法輕鬆找到輸出的來源。我們想要的是一種方法來查看System.out.println從何處被調用(如來自異常或類似情況的堆棧跟蹤)。

它不適合調試 - 出錯的輸出從一些錯誤的線程來的地方等

有關如何跟蹤這個錯誤的產量下降的根源任何想法?

PS:對System.out調用的99.99%是合法的,而且我們有成千上萬的調用,因此僅僅搜索System.out調用的代碼庫並不是一個解決方案!

+0

@SvrGuy:您可以用適當的日誌記錄調用替換所有* System.out.println *,然後您就會知道它們從哪裏被調用。您也可以通過在* System.out.println *調用中追加類名稱來替換所有* System.out *調用。兩者都可以通過使用一些腳本語言輕鬆完成(某些編程人員必須具備一些腳本技能,但我會離題)。在那裏,做到了這一點:我已經通過100 KLOC Java代碼庫上的Un * x Bash shell腳本自動進行適當的日誌記錄來代替所有System.out.println。 – SyntaxT3rr0r 2010-04-20 22:42:08

+0

@SvrGuy:使用shell腳本並結合諸如* find *,* sed *和* awk *之類的工具是一種破解,但您可以控制沒有任何問題。基本上我會使用* find *來查找每個* .java *文件,並且在每個文件中我會用* System.out.println(*帶* System.out.println(「 .java_file_name「+」*。如果你使用的是一個很酷的DVCS,你可以在瞬間克隆你的1M代碼庫,然後在fork中找到最差的違規者,然後刪​​除「真實」代碼庫中最糟糕的違規者,確保你不會搞砸任何東西 – SyntaxT3rr0r 2010-04-20 22:47:20

回答

6

有一個System.setOut()方法。如果你真的絕望了,把它設置爲一些真正的stdout包裝,並在你的包裝中做任何事情。例如。將書寫的字符串與某些東西進行比較,如果這是錯誤的輸出則拋出。

+0

我認爲這是完全正確的。製作你自己的信息流,當有問題的信息通過時。只需打印堆棧跟蹤: new RuntimeException()。printStackTrace(); – 2010-04-20 22:15:23

+0

很好的回答!它不需要真正的絕望 - 我認爲它可以在幾分鐘內完成。 – 2010-04-21 00:23:29

2

使用AspectJ,您可以輕鬆打印調用System.out的類的簽名。

一個簡單的例子,將由TraceAspect建議如下。重要的部分是該類位於演示包中並調用System.out。該方面還會提示從任何深度演示包的子包中的所有類中調用System.out的所有調用。

package demo; 

public class DemoClass { 

    public void demo() { 
     System.out.println("inside demo method.."); 
    } 

    public static void main(String[] args) { 
     new DemoClass().demo(); 
    } 
} 

要打印出來的包和類名的System.out的調用之前,你可以添加一個看點是這樣的:

@Aspect 
public class TraceAspect { 

    @Pointcut("call(* java.io.PrintStream.*(..))") 
    public void sysoutPointcut() { 
    } 

    @Pointcut("within(demo..*)") 
    public void packagePointcut() { 
    } 

    @Before("sysoutPointcut() && packagePointcut()") 
public void beforeSysoutCallInsideDemoPackage(JoinPoint joinPoint) { 
    System.out.print(joinPoint.getThis().getClass().getName() + ":" 
      + joinPoint.getSourceLocation().getLine() + " - "); 
} 
} 

在DemoClass執行的主要方法的輸出是:

demo.DemoClass:6 - inside demo method.. 

Eclipse和AspectJ的插件,你可以在你的項目中單擊鼠標右鍵,然後單擊配置 - >轉換爲AspectJ項目。然後上面的代碼將工作。

我已經用@AspectJ風格here寫了更多關於AspectJ的內容。