2012-07-04 80 views
1

嗯,首先,這可能是愚蠢和瘋狂的。Java源代碼依賴關係圖

我正在嘗試構建(或使用,如果已經存在的話)一個框架,它接收大量Java源文件並輸出這些文件交互的方式;例如,file1.java可能會導入 file2.java; file2.java可以從file3.java調用靜態方法。如果這可以在不編譯或運行該組文件的情況下完成,那理想情況下會很好。我意識到Reflection API可以讓我探索一個類的各個部分,但是我正在尋找什麼?

此外,如何將其擴展到其他語言,例如Python或Lisp(在此添加任何其他語言)?

我真的不確定如何構建問題標題,所以如果之前有人問過這樣的問題,我會很高興能否將我與該問題聯繫起來。

+0

從技術上說,你不要導入文件 - 導入僅僅是由編譯器使用時,使用非完全限定類名來解決完全限定類名。 –

+0

通過反射,您可以查看類中的字段,方法的參數和返回類型 - 但反射不會告訴您有關在*方法中使用的類的任何內容。 –

+0

查看OpenJDK的來源?我認爲你正在做一些編譯器已經在做的事情。 – nhahtdh

回答

1

你有兩個問題,我會試着解決第一個問題。我相信你正在對java文件進行一些源分析,看看它們是如何相互交互的(至少這就是我所理解的)。所以基本上,要做到這一點,你必須像Eclipse IDE一樣行事。掃描每個.java文件中的源代碼並構建java保留字和構造的數據結構。一旦分析了每個.java文件,您就可以繼續發現它們之間的鏈接。

ex。

  1. 存儲類,它的名字和它的範圍
  2. 存儲所有聲明的變量,它們的值的HashMap和其範圍
  3. 查看源文件的方法和存儲他們的名字的包名, in + out參數和範圍

您也可以做更多的事情,並檢測這些結構,您必須編寫自己的(或網上找到的東西)解析器並使用正則表達式來檢測這些結構。您將它們存儲在您的程序中,然後一旦分析完所有源文件,就可以開始查看交互。

ex。

源文件1位於軟件包x.y中,有3個公共方法和2個軟件包範圍方法。 源文件2位於包z中,有1個公共方法和3個私有方法。

所以你可以得出結論,文件1可以通過調用該公共方法與文件2進行交互。你可以對所有文件進行相同的分析。

+0

這聽起來很有趣,但我不確定它有多可行。我可能會等待更多的答案。 – Gooner

+0

這是100%可行的,我們在大學學習這個東西。通常當然是以「編譯器構造」的名義。你基本上是在編碼解析器和分析源代碼並映射它的每一個部分。然後,您只需根據規則找到映射之間的連接。並且這些規則在JVM規範中定義。 –

+0

如果有時間我可以給你寫一個示例程序,它可以完成我所提到的任務。如果你懷疑我建議的可行性,就像是一個真正基礎的概念證明。 –

2

我目前工作的一個項目,主要功能是非常相似,你所提到的,我用的是JavaParser類:http://code.google.com/p/javaparser/

JavaParser類是非常強大的,它可以幫助我們在源代碼分析了很多,但即使我使用javaparser,也很難獲得完整的依賴關係和類交互。

例如: 如果您想獲得類的所有依賴關係,最直接的方法是獲取源代碼的「導入」區域 - 使用javaparser可以非常容易。但是隻有「導入」是不夠的,如果ClassA - 您當前正在分析的類叫做ClassB - 它與ClassA位於同一個包中,那麼ClassB將不會出現在導入區域中。

所以在這種情況下,我們無法得到ClassB的依賴。

對於類的交互,如果你不能100%獲得一個類的正確依賴關係,那麼你不能100%知道類之間的正確的交互。

但無論如何,到目前爲止,javaparser是我能找到的功能最強大,最實用的java源代碼分析工具。

+0

好的,我建議這次使用:ANTLR(http://www.antlr.org/)。 ANTLR是編程語言解析和處理的最佳解決方案。 –

0

我知道你說你寧願不做編譯,但通過類文件瀏覽會容易得多。在字節碼和常量池之間,你可以得到你需要的一切,而不必求助於重寫javac。使用Apache BCEL,你大部分都在那裏。顯然沒有工具能夠找到通過反射訪問的依賴關係;爲此,您需要使用自定義類加載器或其他方法進行運行時分析。

https://en.wikipedia.org/wiki/Java_class_file http://commons.apache.org/proper/commons-bcel/

+0

它可能會更容易,但它也是錯誤的。 javac在源文件中內聯常量,這意味着您可以使A.java取決於B.java,但A.class不參考B.class。 –