2013. július 15., hétfő

PMD - XPath alapú kódellenőrző plugin fejlesztés 2.

Még mindig az XPath alapú plugin fejlesztésnél maradunk, de most egy kicsit összetettebb példát fogok bemutatni.

Explicit (forráskódbeli) GC hívások kijelzése 


A kódból nem javasolt a szemétgyűjtés kikényszerítése, mivel ilyenkor mindig teljes GC-zés történik, azaz a fiatal és öreg heap területeken is megtörténik a takarítás, ami akár hosszabb időre is megállítja az alkalmazás futását. Bár a -DisableExplicitGC JVM argumentummal letiltható az explicit gc használata, a kódbeli hívás tiltása mégis javasolt a "véletlenül kifelejtett" beállítások miatt!

A szabály elkészítéséhez először is kigyűjtöttem a GC forráskódból történő meghívásainak az eseteit:

1. Runtime.getRuntime().gc();
2. Runtime rt=Runtime.getRuntime(); rt.gc();
3. java.lang.Runtime.getRuntime().gc();
4. Java.lang.Runtime rt=java.lang.Runtime.getRuntime(); rt.gc();
5. System.gc();
6. java.lang.System.gc();
7. Runtime és System statikus importja, getRuntime().gc(); ill gc(); meghívása.

Az egyszerűség kedvéért az alábbi szabály most csak az 1. és a 2. esetet fedi le, azonban könnyen kibővíthető a többi eset detektálásához is. Lássuk!

//StatementExpression/PrimaryExpression/PrimaryPrefix
[
./Name[@Image = 'Runtime.getRuntime'] and ../PrimarySuffix[@Image = 'gc']
or
ends-with(Name/@Image, '.gc') and substring-before(Name/@Image, '.') = 
//VariableDeclarator/VariableDeclaratorId/
@Image[../../../Type/ReferenceType[ClassOrInterfaceType/@Image='Runtime']]
]


A szabály a //StatementExpression/PrimaryExpression/PrimaryPrefix kifejezésre illeszkedő csomópontok halmazára fogalmaz meg két feltételt egy logikai vagy kapcsolattal elválasztva. A feltétel első része azokra a csomópontokra illeszkedik, amelyeknek PrimaryPrefix alatti Name csomópontjának a neve Runtime.getRuntime és a PrimaryExpression csomópont alatt tartalmaz egy olyan PrimarySuffix-es node-ot, aminek a neve gc. A feltétel második része pedig olyan Runtime típusú példány deklarációkat keres ahol is a példányon a gc() metódus meghívásra került az adott lokális scope-on belül.

Mivel a feltétel második részének a megvalósítása összetettebb kifejezést eredményezett, ezért a részletes ismertetést az alábbi AST alapján fogom bemutatni.


Az ends-with(Name/@Image, '.gc') kifejezésrész olyan csomópontokra fog rámutatni ami a PrimaryPrefix alatt található és a neve a .gc –re végződik. Az AST példában ez lesz a Name:rt.getRuntime.gc csomópont.

substring-before(Name/@Image, '.')=//VariableDeclarator/VariableDeclaratorId/@Image[../../../Type/ReferenceType[ClassOrInterfaceType/@Image = 'Runtime'

A fenti kifejezés pedig az előzőleg kiválasztott csomópontok névből levágja a legelső pont előtti előtagot, a példa szerint az rt-t, ezután a változó deklarációkra illesztett útvonallal (//VariableDeclarator/VariableDeclaratorId) visszakeresi hogy a lokális scope-n belül ennek a példánynak a típusa Runtime volt-e. Amennyiben talál ezen feltételeknek megfelelő csomópontot a szabály kijelzi a hibát.

Összegzésként elmondhatom hogy az XPath alapú kifejezésekkel általában tömören és jól olvashatóan fogalmazhatjuk meg a szabályainkat. Ha netán mégis nehézségekbe ütköznénk akkor arra is megvan a lehetőség hogy Java nyelven fogalmazzuk meg a szabályainkat.

Nincsenek megjegyzések:

Megjegyzés küldése