Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[java] ClassLoader: classes\functies in een project listen

Pagina: 1
Acties:
  • 133 views sinds 30-01-2008
  • Reageer

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Hoi hoi

Ik ben een code coverage aspect in AspectJ aan het ontwikkelen en wil hierbij ontdekken welke functies niet aangeroepen worden .

De java.* classes laat ik buiten beschouwing, die zullen wel kloppen. Nu heb ik een stukje code van een collegegenoot gehad die het ook weer ergens vandaan heeft, maar dat vind ik niet echt de bedoeling van de opdracht.

Wat ik wil doen is alle functies (al dan niet via de respectievelijke classes) uit de classloader zien te vissen en in een vector te mikken, en dan elke functie aanroep af te vangen met een pointcut afvangen en die uit de vector trekken.

Dat lukt me wel, maar ik zie nog steeds niet in hoe alle functies uit de code kan halen via de classloader (ja allang gelezen enzo, en RTFM).

Kan iemand me een bumpje de goede richting in geven? Aan een bumpje heb ik genoeg, code is niet nodig :)

Verwijderd

Gebruik maken van de klasse Class en de functies getDeclaredMethods?

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
ja maar hoe kan ik dan alle classes vinden in zo'n applicatie? :)
want het zijn meerdere classes .

^^ is iig een oplossing voor het vinden van de functies van een klasse. thanks.

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 12:54
Op deze manier blijft code coverage rapportage wel erg beperkt natuurlijk, want je blijft dan steken op method coverage, terwijl branch coverage en statement coverage juist het meest interessant zijn. Een volledig overzicht van wel of niet uitgevoerde instructies krijg op deze manier dus bij lange na niet.
Als je serieus bezig bent met het ontwikkelen van een code coverage analyse tool, dan zal je toch de kant van source code instrumentation of byte code instrumentation op moeten (of een combinatie daarvan).

In ieder geval, als je het op de door jouw beschreven manier gaat oplossen kan je een overzicht van alle geladen klassen krijgen door gebruik te maken van reflection. Een ClassLoader houdt intern een Vector bij van alle geladen klassen, alleen is die volledig afgeschermd van de buitenwereld en alleen toegankelijk via reflection. Dat zou voor alle ClassLoaders moeten werken m.u.v. de bootstrap ClassLoader, maar daar was je toch niet in geïnteresseerd.
Een tweede manier is het bijhouden van een register in een Singleton, als je toch alleen geïnteresseerd bent in jouw eigen classes. Als je alle klassen zichzelf bij die Singleton laat registreren, dan heb je een mooi overzicht van alle klassen die je relevant vind (zonder het harige reflection beest wakker te maken).

  • YopY
  • Registratie: September 2003
  • Laatst online: 06-11 13:47
Of je gebruikt een tool als JCoverage, een tool die precies datgene nagaat. Een voorbeeld van gebruik van JCoverage is bijvoorbeeld Cobertura, die de coverage van JUnit tests controleert mbv JCoverage en een netjes rapport daarover levert (in html of xml).

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 12:54
YopY schreef op woensdag 19 december 2007 @ 10:29:
Of je gebruikt een tool als JCoverage, een tool die precies datgene nagaat. Een voorbeeld van gebruik van JCoverage is bijvoorbeeld Cobertura, die de coverage van JUnit tests controleert mbv JCoverage en een netjes rapport daarover levert (in html of xml).
Ja, of EMMA, of Clover of... :)
Ik denk niet dat het de bedoeling is dat je voor een programmeeropdracht komt aanzetten met een off-the-shelf oplossing. Tenzij je een ontzettend naïeve docent hebt...

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
ik weet wel zeker dat het niet de bedoeling is.
branch en code coverage wordenn iet gevraagd, alleen method. als de docent daar genoegen mee neemt: prima, dan doen we dat gewoon :)
Ik ga denk ik de bovenste tactiek van de 2 toepassen, dank je wel ;)

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 20-11 13:37

Robtimus

me Robtimus no like you

Je kunt trouwens ook wel vanuit een folder of ZIP (JAR) file alle classes laden. Daar heb ik zelf al een tweetal classes voor geschreven. Wat deze doen, is de folder of ZIP file inlezen, alle .class files eruit halen, en voor al deze proberen Class.forName aan te roepen.

Natuurlijk moet je niet vergeten dat de folder / ZIP file ook in het classpath moet zitten, maar daarvoor heb ik dan weer URLClassLoader gebruikt.

Zelf gebruik ik hem om vanuit een folder of ZIP file alle classes vinden die een specifieke interface implementeren of een specifieke class extenden, voor een soort plugin model. Ipv zelf de class te moeten intypen hoef ik alleen maar de folder / ZIP file te selecteren en dan daaruit de compatible classes selecteren.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

offtopic:
Vector is vies. Gebruik liever een andere List implementatie en wrap die in een Collections.SynchronizedList als je hem gesynchroniseerd wilt hebben of gebruik een klasse uit java.util.concurrent.

Wie trösten wir uns, die Mörder aller Mörder?


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 12:54
IceManX schreef op woensdag 19 december 2007 @ 12:30:
Je kunt trouwens ook wel vanuit een folder of ZIP (JAR) file alle classes laden. Daar heb ik zelf al een tweetal classes voor geschreven. Wat deze doen, is de folder of ZIP file inlezen, alle .class files eruit halen, en voor al deze proberen Class.forName aan te roepen.

Natuurlijk moet je niet vergeten dat de folder / ZIP file ook in het classpath moet zitten, maar daarvoor heb ik dan weer URLClassLoader gebruikt.

Zelf gebruik ik hem om vanuit een folder of ZIP file alle classes vinden die een specifieke interface implementeren of een specifieke class extenden, voor een soort plugin model. Ipv zelf de class te moeten intypen hoef ik alleen maar de folder / ZIP file te selecteren en dan daaruit de compatible classes selecteren.
Zoiets heb ik zelf ook een keer geschreven als JUnit tool, zodat ik automatisch alle TestCase objecten in een bepaalde package structuur kon inventariseren en onderbrengen in een TestSuite.

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
mja dat is niet de bedoeling van de opdracht :p
ik denk dat ik het gewoon eens met reflection ga doen.

confusion: waarom is een vector zo vies?

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 12:54
Boudewijn schreef op woensdag 19 december 2007 @ 13:24:
mja dat is niet de bedoeling van de opdracht :p
ik denk dat ik het gewoon eens met reflection ga doen.

confusion: waarom is een vector zo vies?
Om het vies te noemen gaat misschien wat ver, maar java.util.Vector is een legacy klasse die eigenlijk vervangen is door java.util.ArrayList. Vector was onderdeel van de core API voor de introductie van het collections framework en is daar toen der tijd geforceerd onderdeel van gemaakt door Vector de java.util.List interface te late implementeren. Het enige wezenlijke verschil tussen ArrayList en Vector is dat alle methoden van Vector zijn gesynchroniseerd. In een niet mulit-threaded context kan dat een onnodige performance hit zijn. Als je een ArrayList vanuit een mulit-threaded omgeving wilt gebruiken kan je hem wrappen via Collections.synchronizedList(). Effectief gedraagt die wrapper variant zich dan hetzelfde als een Vector. Ik verkies zelf ook altijd een ArrayList boven een Vector als het gaat om nieuwe implementaties, als je met legacy code werkt heb je soms geen keuze.

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
het gaat hier niet om de Java code, wat mij betreft. ik doe een master CS en het is een practicum over AspectJ. Belangrijker lijkt het me dat die code klopt en doet wat het moet doen, iedereen kan wel Java programmeren (hoop ik dan :+) daar.

Code komt als ik het af heb hier te staan voor het nageslacht :)

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
tijd voor een bescheiden update.

Ik heb de volgende strategie gedefinieerd:

1: Maak een pointcut voor de ClassLoader's loadClass functie.
2: Deze pointcut krijgt alle classes te zien die in de applicatie worden geladen.
3: List alle functies in de classes die die pointcut voorbij ziet komen.
4: Trek daar bij elke functiecall de naam van de gecallde functie vanaf.

Feit is dat ik 2+3+4 voor elkaar krijg, maar 1 niet.
Dit komt doordat de loadClass functie met een generic werkt:

code:
1
public Class<?> loadClass(String name)     throws ClassNotFoundException
met als overlad:
code:
1
protected Class<?> loadClass(String name, boolean resolve) throws classNotFoundException

Nu is het zo dat ik daar dus een pointcut voor tracht te schrijven, en ik heb al eea geprobeerd, maar de pointcut wordt gewoon niet getriggerd:
code:
1
    after() returning(Class <?> c):  target(ClassLoader) &&  call (Class<?> loadClass(..))  && !within(SWE35)

Noot: SWE35 is het huidige aspect.
Ik neem aan dat het met de generic te maken heeft, ik heb ondertussen het schrijven van gewone aspects wel onder de knie geloof ik :) . Heb wat ge-experimenteerd met de notatie, maar ik krijg het niet voor elkaar.

Kan iemand me helpen? :) Dmv een hint of evt wat code (hint is meer dan goed genoeg hoor, ik wil geen script-request-warning aan mijn broek).

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 12:54
Waarom laat je de generics-notatie niet in zijn geheel achterwege? Een quote uit het AspectJ 5 Developer's Notebook:
The simplest way to work with generic and parameterized types in pointcut expressions and type patterns is simply to use the raw type name. For example, the type pattern List will match the generic type List<E> and any parameterization of that type (List<String>, List<?>, List<? extends Number> and so on.

This ensures that pointcuts written in existing code that is not generics-aware will continue to work as expected in AspectJ 5. It is also the recommended way to match against generic and parameterized types in AspectJ 5 unless you explicitly wish to narrow matches to certain parameterizations of a generic type.

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
True, maar dan wordt de pointcut alsnog niet 'getriggerd' :)
Ik test het btw met deze code vanuit mijn IDE.
code:
1
2
3
4
5
6
7
8
    public static void main(String[] args) 
    {
        System.out.println("Doe iets");
        foobar foo=new foobar();
        foo.foo();
        foo.bar();
        System.out.println("Einde");
    }

Waarbij foo een nutteloze class is ,maar wel wordt geladen. en dus zou i kverwachten dat de pointcut aangesproken wordt.

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
lief klein schopje :)

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
nou ja zeg, nog een schopje :)

ik ben er nog steeds niet uit namelijk.
Afaik wordt de functie wel gecalled (loadClass) maar dat kan ik niet verifieren.

Kan het zo zijn dat ik hier tegen een beveiliging van de JVM aanloop oid?

Verwijderd

De Classloader zit in de "bootstrap" classloader en daar kunnen aspecten standaard niet in friemelen. Heb je de JVM zo geconfigureerd dat je dit wel mag?

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Hmm hoe regel je dat af?
Sowieso: zijn er nog andere methoden om mijn doel te bereiken?
Reflection lijkt me ook niet erg practisch namelijl.

Verwijderd

Als je Load Time Weaving gebruikt dan lukt het gewoon niet, zie documentatie. Je zou compile-time het moeten doen en hier een nieuwe jar voor moeten maken, en die met "-Xbootclasspath" als override op moeten geven. Let wel op want dit is spelen met vuur en illegaal voor productiedoeleinden.

Als alternatief kun je kijken naar offline bytecode enhancers (zo doen bijna alle code coverage tools het) met cglib/asm/javassist oid. Het voordeel daarvan is dat je ook inzicht krijgt in classes die helemaal niet worden geladen (itt de classloader manier).

In dit topic is al een aantal volwassen open source Java tools genoemd. Heb je al gespiekd hoe zij dit probleem oplossen? ;)

  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

Topicstarter
Uhhh hoe zou ik dat daaraan moeten zien? Hun hele source doorspitten? :?

Dit is puur voor een practicum-opdracht, iig dat doel bereiken is de opdracht. Feit is dat de Classloader approach met een aspect mij het makkelijkst lijkt , en een byecode ehancer etc is niet de bedoeling (het is een AspectJ opdracht... dus dan zal je dat wel moeten gebruiken als oplossings-middel).
Pagina: 1