Links

  • 1. Sogeti
  • 2. JBoss
  • 3. IBM
  • 4. Oracle
  • 5. SpringSource
  • 6. NL-JUG
  • 7. Java

Archives

Syndication  RSS 2.0

RSS 1.0
RSS 2.0

Bookmark this site

Add 'JCN Blog' site to delicious  Add 'JCN Blog' site to technorati  Add 'JCN Blog' site to digg  Add 'JCN Blog' site to dzone

Posted by Jan-Hendrik Kuperus at 22:15 on Thursday 17 April    Add 'Preventing Bugs By Using A Pluggable Type System' site to delicious  Add 'Preventing Bugs By Using A Pluggable Type System' site to technorati  Add 'Preventing Bugs By Using A Pluggable Type System' site to digg  Add 'Preventing Bugs By Using A Pluggable Type System' site to dzone

Op 16 april was weer de jaarlijkse J-Spring bijeenkomst van de NLJUG. Uiteraard was Sogeti weer aanwezig met een aantal JCN’ers en hebben we onze oren en ogen weer goed open gehouden. Na twee uur te hebben gedaan over de route Rotterdam – Bussum heb ik de keynote gemist en ben ik gelijk doorgegaan met de eerste parallelsessie.

Gelukkig was de koffie niet al te slap want het eerste onderwerp komt rechtstreeks van Associate Professor van MIT. Michael Ernst kwam ons vertellen hoe we in plaats van bugs opsporen bugs kunnen voorkomen met JSR-308 en een paar handige annotation processors.

Om maar gelijk met de deur in huis te vallen: JSR-308 is een uitbreiding op Java Annotations en staat gepland om opgenomen te worden in de set met features van Java 7. Met JSR-308 ‘Annotations on Java Types’ wordt het aantal plaatsen waar annotaties zijn toegestaan flink uitgebreid. Samen met een aantal checkers kunnen op deze manier annotaties worden gebruikt om diverse soorten bugs die zich normaliter op runtime manifesteren al op compile time te detecteren. Klinkt goed! Hoe werkt het dan?

NullPointerExceptions

Een van de meest vervelende en meest voorkomende exceptions is wel de NullPointerException. Je hebt een stuk code geschreven dat in principe helemaal zou moeten werken als je het zo en zo gebruikt. Super, maar dan gaat collega X (of misschien jij zelf wel) aan de slag met jouw class en plots knalt de applicatie er uit: NullPointerException. Vanaf Java 7 kun je in je code informatie opnemen over het wel of niet toestaan van nulls in een variabele:


public class MyClass {

private @NonNull String name;

public MyClass(@NonNull String name) {

this.name = name;

}

public String getName() {

return this.name;

}

}

Wanneer deze klasse wordt gecompileerd (met de null-checker) zal er worden gekeken of er misschien paden door het systeem zijn die er voor zouden kunnen zorgen dat er een null-value wordt opgeslagen in de property name. Is dit het geval, dan zal de compiler aangeven dat er een potential null assignment on a non-null variable wordt gedaan. De bovenstaande klasse zal geen problemen opleveren, maar stel dat een andere klasse deze klasse gebruikt:


public class MyOtherClass {

public static void main(String[] args) {

String arg0 = (args.length > 0) ? args[0] : null;
MyClass clzz = new MyClass(arg0);

}

}

Hier zal de compiler aangeven dat de MyClass constructor een @NonNull String verwacht en dat de variabele arg0 dit niet is (arg0 is @Nullable, de standaard waarde). De compiler heeft hier dus al een mogelijke toekomstige NullPointerException opgespoord nog voordat er ook maar iets in een JVM is geladen. Daarnaast geven de annotaties ook nog extra informatie aan degene die de code leest. Het laat zien dat de ontwikkelaar heeft nagedacht over de mogelijkheid en deze ofwel heeft toegestaan of expliciet heeft verboden.

Type systems, uitbreidingen en compatibility

Wat een checker doet is in principe een eigen type-system controleren. De javac compiler controleert altijd eerst de hele Java file volgens het Java Type System en gaat daarna door alle plugins heen om annotaties te verwerken. Door middel van de @NonNull annotaties wordt bijvoorbeeld de hele type-hierarchy van de applicatie verdubbeld. Van ieder type bestaan dan een @Nullable en een @NonNull variant, waarbij het @NonNull type wel aan @Nullable variabelen mag worden toegekend, maar andersom niet. Zo heb je dus een ‘@Nullable Object’ als type en een ‘@NonNull Object’.

De implementatie van JSR-308 waar Michael momenteel mee bezig is ondersteunt een viertal type-systems die problemen opsporen met Nullability, Interning / Equality (bij String.intern()) en Immutability / Side Effects. Door de generieke opzet van de plugins kan iedereen effectief zijn eigen type system voor de Java language maken.

De uitbreiding die JSR-308 naar de Java taal brengt is momenteel verkrijgbaar als een patch op de OpenJDK en kan al meteen gebruikt worden in projecten. Zelfs als het project gecompiled moet worden met Java 6 of eerder kan er al gebruik worden gemaakt van deze features. De checkers pakken namelijk de annotaties ook op in commentaar. Deze regel zou bijvoorbeeld momenteel een error opleveren als deze met Java 5/6 wordt gecompileerd:

List<@NonNull Integer> lst;

De checkers hebben hier een truc voor in petto: door de annotatie in commentaar te zetten negeert een Java 5/6 compiler hem, maar wordt hij wel opgepikt door de checkers:

List</*@NonNull*/ Integer> lst;

Dit betekent niet dat deze annotaties overal in commentaar worden opgepikt. De checkers zijn slim genoeg om alleen de annotaties te pakken die op plaatsen staan waar deze zinnig zijn.

Door deze truc kan de kracht van JSR-308 al worden toegepast in huidige projecten. Zelfs projecten die nog met Java 1.4 of eerder worden gebuild kunnen het al gebruiken. De checkers zijn beschikbaar als losse plugins voor de gepatchte OpenJDK compiler en als Eclipse plugins. Bovendien kan de compiler uiteraard ook als Ant-task worden gebruikt.

Kan FindBugs dan de koffers pakken? Nee. Michael liet wel zien dat deze pluggable type systems meer (specifieke) potentiele fouten vinden dan FindBugs, Maar FindBugs doet nog veel meer, ook controles die niet met een type system opgelost kunnen worden. JSR-308 is dus een stevige toevoeging aan ons arsenaal van Static Analysis tools. Ik durf te wedden dat Joshua Bloch er net zo blij mee is als Michael zelf.

Go forth and prevent bugs!

Voor wie nog meer wil weten, bijvoorbeeld over @Interned of @Immutable, kan ik nog wel wat voorbeelden produceren. Stuur mij een e-mail op jan-hendrik [punt] kuperus [apedinges] sogeti [puntje] nl en ik roggel het wiel!

–Jan-Hendrik Kuperus


© 2020 Java Competence Network. All Rights Reserved.