2014-04-14 70 views
4

我的項目有一套自定義的註釋,可以出現在OSGi 4.3框架中部署的任何包中。我想在類路徑中找到具有這些註釋的任何類。我嘗試使用BundleWiring.listResources(...)Bundle.loadClass(...)找到每個類。我用一些小軟件包做了一些測試,因爲所有的類都加載了,所以它需要將近200MB的永久代JVM內存空間。OSGi中的類路徑掃描

當程序意識到它們沒有這些註釋時,是否有一種方法來釋放加載的類PermGen的內存空間?

有沒有更好的方法在OSGi框架中查找帶註釋的類?

+0

你想用這些帶註釋的類來做什麼? – Aritra

+0

@Aritra我基本上想找到它們,以觸發這些類中使用信息的其他操作。類似的情況可能是基於JAX-RS/JAXB註釋準備Web服務。無論如何這是一個普遍的問題。 – logoff

+1

我一直在過濾要掃描的捆綁包,只從導入註釋包的捆綁包加載類。我正在使用'BundleWiring.getRequiredWires(null)'並使用'BundleWire.getCapability()。getAttributes()。get(BundleRevision.PACKAGE_NAMESPACE).equals(packageName)'查找我的包。它減少了大量的內存消耗和加載類的時間。它似乎不是更好的方法,但它簡化了這個過程。 – logoff

回答

7

我認爲你不應該做註釋掃描,因爲它會減慢啓動速度並且需要大量內存。 JEE應用程序服務器在啓動時進行註釋掃描,以使懶惰的程序員開心,結果非常煩人(例如,掃描JPA或EJB註釋)。

我想你正在實施一種技術,你可以定義規則。我建議你應該定義類似於下列規則:

  • 註釋類
  • 有必須在其中列出的註解類清單頭。

甚至更​​好的解決方案可以是使用具有指定屬性的自定義功能名稱空間。例如: -

Provide-Capability: myNamespace;classes=com.foo.myClass1,com.foo.myClass2 

在你的技術,你應該寫一個調用BundleTracker:

BundleWiring.getCapabilities("myNamespace"); 

如果命名空間存在,你可以發現,應該處理的類。

如果您實施了該技術,則可以考慮對Bnd進行擴展以自動填充MANIFEST標頭。這個擴展可以用於比從命令行或像maven這樣的構建工具啓動bnd時。

btw .:您可以使用ASM來解析類字節碼,或者使用Java的內置可能性build up AST。雖然這些可以解決內存問題,但我仍然認爲應該直接在MANIFEST頭中定義類的列表,因爲它使事情變得更加清晰。您可以閱讀MANIFEST標題,您可以檢查webconsole上的功能,但不能對字節碼進行相同操作。

+0

您當然應該直接使用ASM(或等價的)掃描字節碼,而不是加載類,然後使用反射來檢查註釋。 –

+0

這個迴應給了我有價值的信息,但並沒有回答我的兩個問題。我的意思是,這是一個好主意,但我想按照我在問題中提到的那樣註釋我的課程。 – logoff

+0

根據答案:如果您確實想要掃描所有類,請使用ASM分析其字節碼。在這種情況下,您將不會遇到PermGen問題。但是,最好強制程序員在提供能力MANIFEST標頭中列出帶註釋的類。在這種情況下,您可以使用bundleWiring.getClassLoader()。loadClass(),因爲您不會使用所有類填充Permgen,但只能使用確實具有註釋的類(並且無論如何將加載這些類)。 –

2

通常,在OSGi上下文中,註釋的類路徑掃描是一個壞主意,因爲類路徑更像一個圖。但是,有些情況下這可能會有用。因此,OSGi鼓勵使用Whiteboard Pattern

你可能做的是在OSGi註冊表中註冊每個類作爲服務。然後,創建一個單獨的包,用於跟蹤這些服務並以某種方式轉換/操作它們。例如,this項目會掃描所有使用@Path和@Provider批註進行批註的類,並將它們轉換爲Jersey REST API。