class: center, middle, inverse # Java 8: Type Annotations ## by [Daniel Stankiewicz](https://github.com/danielstankiewicz) --- class: center, middle, inverse # about.me ### (mostly) Java Developer since 2005 ### currently [@AssecoPolandSA](http://asseco.com/pl/home-en/) ### *inspired by Java 8* ### privately husband, dad, guitarist --- class: center, middle, inverse # Java 8 New Features ## and Type Annotations amongst them --- layout: true ### Java 8 New Features --- ## Annotations on Java Types (JSR-308) A brief look at [Open JDK Type Annotations](http://openjdk.java.net/projects/type-annotations/) project: JSR 308, Annotations on Java Types lays the foundations for .blue[**stronger typing**] in Java by extending the language to .blue[**allow annotations**] on essentially .blue[**any use of a type**]. ??? Szybki rzut oka na projekt Adnotacje Typow: Silniejsze typowanie przez mozliwosc adnotowania dowolnego uzycia typu. --- ## First Naive Test ``` public List<@TypeUse String> typeUse() { @TypeUse String s = "abc"; List<@TypeUse String> list = new ArrayList<>(); list.add(s); list.add("def"); boolean isTypeUse = "def" instanceof @TypeUse String; System.out.println("@TypeUse String: " + isTypeUse); return list; } ``` **Wow! No compilation errors!!!** ??? Pierwszy naiwny test, wow, zadnych bledow kompilacji. Ale na razie niewiele z tego wynika. --- layout: false class: center, middle, inverse # A Deeper Dive into Specification ## or a piece of more organized knowledge ??? Pora na zaglebienie sie w specyfikacje --- layout: true ### A Deeper Dive into Specification --- ## Declaration vs type context * Before Java 8 annotations could be used only in *declaration contexts* * Annotation could be accessed by reflection, .red[except for `ElementType.LOCAL_VARIABLE`] * Java 8 extends *declaration context* to the use of **type parameter declarations**. * It also introduces *type context* for annotations - **types used in declarations and expressions**. ??? Przed Java 8 adnotacje mogly byc uzywane tylko w kontekscie deklaracji typow, pol, metod i tak dalej Mozna sie bylo do nich dostawac przez refleksje, oprocz adnotacji zmiennej lokalnej. Java 8 rozszerza kontekst deklaracji o typy parametryzowane i wprowadza pojecie kontekstu typu, czyli typow uzytych w deklaracjach i wyrazeniach. --- ## Declaration context @Target * ElementType.PACKAGE * ElementType.TYPE * ElementType.ANNOTATION_TYPE * ElementType.FIELD * ElementType.CONSTRUCTOR * ElementType.METHOD * ElementType.PARAMETER * ElementType.LOCAL_VARIABLE ??? Dotychczasowy kontekst deklaracji -- * .green[ElementType.TYPE_PARAMETER] ??? Pojawia sie mozliwosc adnotowania deklaracji typu parametryzowanego. -- ##.green[Type context @Target] * .green[ElementType.TYPE_USE] ??? oraz nowy kontekst typu, oznaczany przez @Target ElementType.TYPE_USE --- ## Declaration context @Target * ElementType.PACKAGE * .blue[ElementType.TYPE] * .blue[ElementType.ANNOTATION_TYPE] * ElementType.FIELD * ElementType.CONSTRUCTOR * ElementType.METHOD * ElementType.PARAMETER * ElementType.LOCAL_VARIABLE * .blue[ElementType.TYPE_PARAMETER] ## Type context @Target * .blue[ElementType.TYPE_USE] `ElementType.TYPE_USE` .blue[includes elements of declaration context] ??? TYPE_USE, czyli uzycie typu, zawiera dla wygody takze TYPE, ANNOTATION_TYPE i TYPE_PARAMETER --- ## ElementType.TYPE_PARAMETER usages Type parameter of generic class (or interface) ``` public class GenericClass<@TypeParameter V extends Number> ``` Type parameter of generic constructor ``` public <@TypeParameter A> GenericClass(V value, A another) ``` Type parameter of generic method ``` public <@TypeParameter K> Map
getSingletonMap(K key) ``` ??? Uzycia TYPE_PARAMETER to deklaracje parametru typu w klasie (czy tez interfejsie), konstruktorze lub metodzie parametryzowanej --- ## ElementType.TYPE_PARAMETER reflection Since Java 8 `java.lang.reflect.TypeVariable` interface extends `java.lang.reflect.AnnotatedElement` interface: ``` TypeVariable
>[] typeParameters = GenericClass.class.getTypeParameters(); TypeParameter annotation = typeParameters[0].getAnnotation(TypeParameter.class); ``` ??? Do adnotacji o typie TYPE_PARAMETER mozna sie dostawac przez refleksje, tak jak do pozostalych z kontekstu deklaracji, poniewaz TypeVariable od Javy 8 rozszerza AnnotatedElement --- ## ElementType.TYPE_USE usages ### Declaration context ``` @TypeUse("class") public class DeclarationContext <@TypeUse("type parameter") V extends Number> { public <@TypeUse("type parameter") K> Map
getMap(K key) {} @TypeUse("annotation") public @interface AnnotationExample {} @TypeUse("interface") public interface InterfaceExample {} @TypeUse("enum") public enum EnumExample {} } ``` Usages of `ElementType.TYPE_USE` in declaration contexts can be also accessed by reflection. ??? Uzycia TYPE_USE w kontekscie deklaracji: klasy, parametru typu, adnotacji, interfejsu, enuma. Do takich uzyc adnotacji mozna sie takze dostawac przez refleksje. --- ## ElementType.TYPE_USE usages ### Type context in declarations **`extends`** or **`implements`** clause of a class declaration ``` public class TypeContext implements @TypeUse Serializable ``` **`extends`** clause of an interface declaration ``` public interface InterfaceExample extends @TypeUse Runnable ``` Return type of a method ``` public @TypeUse String getValue() ``` ??? Rzeczywiste uzycia TYPE_USE w kontekscie typu dziela sie na uzycia typu w deklaracjach i wyrazeniach. Uzycia w deklaracjach to na przyklad: w deklaracjach typow, po slowach kluczowych extends lub implements w deklaracjach metod, przy typie zwracanym --- ## ElementType.TYPE_USE usages ### Type context in declarations **`throws`** clause of a method or constructor ``` public void throwException() throws @TypeUse Exception ``` **`extends`** clause of a type parameter declaration ``` public
Integer getInteger(N number) ``` Field declaration including an enum constant ``` private @TypeUse String value; private enum Status {@TypeUse OK, @TypeUse ERROR} ``` ??? w deklaracjach metod przy rzucanych wyjatkach po slowie kluczowym extends w deklaracjach parametrow typu w deklaracjach pol, lacznie ze stalymi enuma --- ## ElementType.TYPE_USE usages ### Type context in declarations Parameter of a method, constructor, or lambda expression ``` public List
filterCars(@TypeUse List
cars, int year) { return cars.stream() .filter((@TypeUse Car c) -> c.getYear() == year) .collect(Collectors.toList()); } ``` Receiver parameter of a method (explicit **`this`** parameter) ``` public void show(@TypeUse TypeContext this, boolean other) ``` ??? w parametrach metod, konstruktorow i wyrazen lambda oraz w domniemanym parametrze this metody --- ## ElementType.TYPE_USE usages ### Type context in declarations Local variable declaration ``` @TypeUse Date date; ``` Exception parameter of a **`catch`** clause ``` catch (@TypeUse NumberFormatException e) ``` ??? w deklaracji zmiennej lokalnej w deklaracji wyjatku w klauzuli catch --- ## ElementType.TYPE_USE usages ### .red[Type context in declarations != Declaration context] Some of the above examples may look like use of annotations of declaration context, but .red[don't be tricked], they are not! They cannot be accessed by reflection: ``` private @TypeUse String value; TypeContext.class.getDeclaredField("value") .getDeclaredAnnotation(TypeUse.class) ``` returns `null`. ??? .red[Tutaj wazna uwaga:] kontekst typu w deklaracjach to cos innego niz kontekst deklaracji. Niektore z wczesniejszych przykladow moga wygladac jak uzycia adnotacji w kontekscie deklaracji. Ale nie dajmy sie zwiesc! Nie da sie do nich dostac przez refleksje. --- ## ElementType.TYPE_USE usages ### Type context in expressions Explicit type parameter of a constructor or method invocation or **`new`** operator ``` <@TypeUse Long>this(0l); new <@TypeUse String> GenericClass<@TypeUse Long>(123l, "abc") .<@TypeUse Integer> getSingletonMap(123); ``` Class instance creation (including anonymous) ``` new @TypeUse Thread(new @TypeUse Runnable() { @Override public void run() {} }); ``` ??? Kontekst typu w wyrazeniach: przy jawnym uzyciu parametru typu przy typie uzytym w tworzeniu instancji klasy, takze anonimowej --- ## ElementType.TYPE_USE usages ### Type context in expressions Type of element in array creation ``` Integer[] array = new Integer @TypeUse[] {}; ``` Cast operator ``` String s = (@TypeUse String) "abc"; ``` **`instanceof`** operator ``` boolean isInstance = s instanceof @TypeUse String; ``` ??? przy typie elementu tablicy w operatorach rzutowania i instanceof --- ## ElementType.TYPE_USE usages ### Type context in expressions Method reference expression ``` @TypeUse GenericClass::new List<@TypeUse String>::size Arrays::<@TypeUse Integer> sort ``` Element type of an array ``` @TypeUse int[] a; // annotates the primitive type int int @TypeUse[] b; // annotates the array type int[] int @TypeUse[][] c; // annotates the array type int[][] int [] @TypeUse[] d; // annotates the array type int[] as component // of array int[][] ``` ??? W referencjach do metod przy typach elementow tablic takze wielowymiarowych --- ## ElementType.TYPE_USE usages ### Type context in expressions Type argument of a parametrized type ``` List<@TypeUse Integer> integers; Set extends @TypeUse Number> set; Collection super @TypeUse Number> collection = new ArrayList<>(); ``` ??? Przy parametrach typu w typach parametryzowanych. --- ## .red[Quasi ElementType.TYPE_USE usages] .red[Warning! The following are not type uses and such annotations are not allowed here] ``` // Annotation uses @/* quasi @TypeUse */Deprecated String s; // Class literal Class
clazz = /* quasi @TypeUse */GenericClass.class; // Import syntax import java.io./* quasi @TypeUse */Serializable; // Static member access String title = /* quasi @TypeUse */ GenericClass.TITLE; // Scoping (e.g. inner class) String v = /* quasi @TypeUse */TypeContext.this.getValue(); ``` ??? Uwaga, mozemy sie rozpedzic i chciec postawic adnotacje w innych, podobnych miejscach: uzycie adnotacji uzycie literalu class import dostep do statycznego pola czy metody okreslenia zakresu (np. dostep do metod klasy zewnetrznej w klasie wewnetrznej) Nie sa to uzycia typu!!! --- layout: false class: center, middle, inverse # The Checker Framework ## or who is the main culprit? ??? Jak widac, jest tego duzo i mozemy teraz tak napisac kod, ze bedzie w nim wiecej adnotacji, niz samego kodu. Ale skad to sie wszystko wzielo i kto jest glownym winowajca tego calego zamieszania? --- layout: true ### The Checker Framework --- ## A piece of history * Rationale for JSR-308 was to allow building tools for more thorough source code analysis * The Most Innovative Java SE/EE JSR of the Year award in... 2007 :) * [The Checker Framework](http://types.cs.washington.edu/checker-framework/), an extendable set of compiler plugins that find bugs, has been already up and running much before Java 8 with a bunch of other tools * Until Java 8, Checker Framework's own compiler had to be used to process type annotations, also written in comments: `/* @TypeUse */` * Better late than never - .red[type annotations in Java 8] in 2014 :) ??? Uzasadnieniem dla JSR-308 byla mozliwosc bardziej szczegolowej analizy kodu przez narzedzia do szukania bledow. Specyfikacja wygrala nagrode dla najbardziej innowacyjnego JSRa w 2007 roku :) Pierwszym narzedziem, ktory uzywal JSR-308 byl Checker Framework, zestaw pluginow do szukania powtarzalnych bugow, rozwijany przez te same osoby, ktore specyfikowaly JSRa. Nie tracili czasu, framework dziala juz od dawna, trzeba jedynie uzywac ich kompilatora, ktory procesuje adnotacje, takze w komentarzach. wreszcie lepiej pozno niz pozniej - adnotacje typow pojawily sie w 2014 roku w Javie 8 --- ## What do we have out of the box? .pull-left[ * Nullness Checker * Initialization Checker * Map Key Checker * Interning Checker * Lock Checker * Fake Enum Checker * Tainting Checker * Regex Checker ] .pull-right[ * Format String Checker * Property File Checker * Internationalization Checker * Signature String Checker * Units Checker * Linear Checker * Mutation Checkers * Subtyping Checker ] Each checker with a set of suitable annotations, there is also ability to write our own checkers. We have pre-annotated JDK classes and a way to annotate external libraries by file stubs. ??? Co mamy z pudelka? Wielki zestaw wbudowanych Checkerow, kazdy z wlasnym zestawem adnotacji i algorytmem sprawdzania. Mamy tez mozliwosc latwego pisania wlasnych checkerow. Dostajemy preadnotowane klasy z JDK i mozliwosc wlasnorecznego adnotowania innych zewnetrznych bilbiotek poprzez stuby. 1. Nullness Checker - null pointer errors 1. Initialization Checker - czy wszystkie pola ustawione w konstruktorze 1. Map Key Checker - jakie wartosci sa kluczami w mapach 1. Interning Checker - bledy uzycia porownania referencji zamiast equals 1. Lock Checker - bledy wspolbieznosci i blokowania 1. Fake Enum Checker - stale string int jako enumy 1. Tainting Checker - bledy bezpieczenstwa, sql injection 1. Regex Checker - prawidlowe wyrazenia regularne 1. Format String Checker - prawidlowe stringi formatujace 1. Property File Checker - prawidlowe klucze plikow properties 1. Internationalization Checker - prawidlowa internacjonalizacja 1. Signature String Checker - Class.forName, odpowiednie uzycie nazw klas 1. Units Checker - uzycie odpowiednich jednostek (np sekundy a milisekundy) 1. Linear Checker - zapobieganie re-uzywaniu referencji 1. Mutation Checkers - niepozadane efekty uboczne 1. Subtyping Checker - kwalifikatory typu --- ## Annotations as Type Qualifiers In the Checker Framework type annotations act as type qualifiers: * **`@Nullable Integer`** - an `Integer` that may become `null` * **`@NonNull Date`** - a `Date` that will never become `null` * **`@Regex String`** - a `String` that is a valid regular expression * **`@Tainted String`** - a `String` that may contain dangerous content * **`@Untainted String`** - a `String` that has been checked and is safe to be used * **`@Interned Integer`** - an `Integer` that can be safely tested for equality by reference comparison `==` * **`@ReadOnly List
`** - a read-only list of `String` objects ??? W Checker Framework adnotacje dzialaja jak kwalifikatory typow: typ Integer, ktory moze miec wartosc null typ Date, ktory nigdy nie bedzie miec wartosci null typ String, ktory jest wyrazeniem regularnym typ String, ktory moze zawierac niebezpieczna tresc, np. SQL injection typ String, ktory na pewno zawiera bezpieczna tresc internowany typ Integer, czyli taki, w ktorym obiekty mozna bezpieczenie porownywac przez referencje zamiast equals lista obiektow Stringow z dostepem tylko do odczytu --- ## Tainting Checker Type Hierarchy .center[] ??? zobaczmy na hierarchie typow, definiowana przez Tainting Checker ooo... wielokrotne dziedziczenie w Javie :) Nie musimy adnotowac wszystkiego, bo w tym przypadku @Tainted jest wartoscia domyslna. --- ## Tainting Checker SQL Injection Prevention Security sink in an application, it should allow only untainted values: ``` public String createQuery(@Untainted String lastName) { return "SELECT p.id FROM person p " + "WHERE p.last_name = " + lastName; } ``` Method to sanitize values entered from the outside: ``` public @Untainted String sanitize(@Tainted String tainted) { for (char c : tainted.toCharArray()) { if (!Character.isLetterOrDigit(c) && !Character.isWhitespace(c)) { throw new IllegalArgumentException("SQL Injection!"); } } return new @Untainted String(tainted); } ``` ??? Jak mozna uzyc Tainting Checker do zapobiegania SQL injection? Mamy takie miejsce w aplikacji, w ktorym niebezpiecznie jest uzywac niesprawdzonych wartosci - konstruowanie zapytania do bazy przez konkatenacje z wartoscia od uzytkownika. Trzeba to miejsce oadnotowac, ze przyjmuje tylko nieskazone Stringi jako parametr. Metoda sanitize sprawdza, czy string jest bezpieczny oznacza go jako nieskazony. --- ## Tainting Checker SQL Injection Prevention Proper, safe use of security sink: ``` public String getSafeQuery(@Tainted String lastName) { return createQuery(sanitize(lastName)); } ``` Vulnerability in code: ``` public String getVulnerableQuery(@Tainted String lastName) { // use of a @Tainted String without sanitizing return createQuery(lastName); } ``` ??? Prawidlowe, bezpieczne uzycie wartosci przekazanej przez uzytkownika. Dziura bezpieczenstwa polega na bezposrednim uzyciu wartosci bez uzycia metody sanitize. --- ## Tainting Checker SQL Injection Prevention Compiler doesn't warn, despite the vulnerability in code. However Tainting Checker **finds a security hole**: ```no-highlight [INFO] --- checkerframework-maven-plugin:1.8.0:check (default) @ java8-type-annotations --- [INFO] Running Checker Framework version: 1.8.0 [INFO] Running processor(s): org.checkerframework.checker.tainting.TaintingChecker [INFO] Run with debug logging in order to view the compiler command line [WARNING] ...src\main\java\pl\jug\warszawa\typeannotations\checker\ TaintingExample.java:[31,27] [argument.type.incompatible] incompatible types in argument. found : @Tainted String required: @Untainted String ``` **Et voilĂ !** ??? Kompilator oczywiscie nie zglasza zadnych problemow, ale juz Tainting Checker z Checker Framework stwierdza, ze uzyty zostal skazony String, a oczekiwano nieskazonego. --- layout: false class: inverse # Links ### JSR-308 Specification http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html ### Java 8 Language Specification - 9.6.4.1. `@Target` http://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.1 ### The Checker Framework http://types.cs.washington.edu/checker-framework/ ### Source code of this presentation https://github.com/danielstankiewicz/type-annotations ??? Jeszcze garsc linkow, jakies pytania? --- layout: false class: center, middle, inverse # The End Slideshow created with [remark](http://gnab.github.com/remark).