Java version 18 har publicerats
7 minuter i lästid Java

Java version 18 har publicerats

Version 18 av programspråket Java är en så kallad Non-LTS, vilket innebär en support-tid på bara sex månader, dvs fram till att nästa version släpps.

Numera publicerar Oracle nya versioner två gånger per år, i mars respektive september. Dessa versioner är antingen ämnade för korttidsbruk eller långtidsbruk.

Det senare kallas LTS, vilket står för long-term support och innebär att Oracle släpper uppdateringar under åtta år. Det publiceras en LTS vart annat år. Version 17, som släpptes i september förra året var just en LTS.

Oracle chockade Java världen, i samband med att de publicerade version 11, med nya betydligt striktare licensvillkor. Det här resulterade i att det dök upp många nya aktörer, som med utgångspunkt i att källkoden till Java JDK och JVM är open-source, skapade egna distributioner för nedladdning. Webbplatsen adoptopenjdk.net, var en sådan som kom att få en stor användarbas.

Emellertid har Oracle relaxerat villkoren på senare tid och tillåter att man använder deras officiella JDK LTS fritt under tre år, dvs ett år extra efter att en ny LTS har publicerats. Det här har medfört att flera återvänt till att ladda ned Oracle's officiella Java version igen.

Så hur pass relevant/intressant är det då med en ny version av Java? Tja, det beror lite på vem man frågar, eller rättare sagt den organisation denne representerar. Företaget New Relic, tillhandahåller molnbaserade monitoreringslösningar för storskaliga Java system. Det innebär i korthet att man installerar en insamlings-agent på sina JVM:er, vilken samlar in mätdata och skickar till en central server för lagring och aggregering. I och med att man hållit på med detta under lång tid, så har man har "djupgående" insikter i miljontals affärskritiska Java system världen över.

De genomförde och publicerade en sammanställning över vilken Java version som används mest. Resultatet förvånar oss, som gärna vill ligga i framkanten och testa det allra senaste. Med en förkrossande majoritet av 85%, så är det Java 8 som används. På andra plats kvalar Java 11 in med en användning på 11%. Övriga 4% ligger utspritt på versioner där emellan och några även på lägre versioner än 8. Du hittar en länk till artikeln i länksamlingen nederst på denna sidan.

I ett utslag av sk full disclosure, så nämner jag att jag arbetade som Europeisk professional services consultant några år hos företaget Wily Technology, vilket grundades av Lew Cirne som sedermera efter att CA förvärvat Wily, grundade New Relic. På den tiden det begav sig, så var jag mycket involverad i produktutvecklingen av systemet Introscope, som var en produkt man installerade ute hos kund. Det var alltså innan cloud computing blev poppis. Det var i kontakt med kunder och baserat på affärskritiska monitoreringslösningar, som uppslagen till förbättringar dök upp. Några av alla otaliga uppdrag för Wily har jag beskrivit i bloggform under etiketten/taggen Introscope.

Nyheterna i Java 18, som berör merparten av Java utvecklare, är förvisso något begränsat. Det intressantaste, enligt min mening, är stödet för kompilerbara kodsnuttar (snippets) i JavaDoc kommentarer. Det händer tämligen ofta att när man implementerar en klass och skriver JavaDoc med kodexempel, så över tiden när koden förändras så är JavaDoc kommentarerna oförändrade.

Med det nya stödet i programmet javadoc, kan man implementera demo-klasser och länka hela eller delar av dessa till olika JavaDoc kommentarer. Här kommer ett komplett exempel:

Först har vi våran målklass; klassen ribomation.code_snippets.Numbers, som kan räkna ut några klassiska värden.

package ribomation.code_snippets;
import java.math.BigInteger;

/**
 * Simple numeric functions.
 * Create an object first
 * {@snippet :
 * var n = new Number(n);
 * }
 *
 * A full example using the class is:
 * {@snippet file="NumbersSnippets.java" region="usage"}
 */
public class Numbers {
    private final int argument;

    /**
     * Provide an argument at creation
     * @param argument  used as input for each function
     */
    public Numbers(int argument) {
        this.argument = argument;
    }

    /**
     * Computes the 1+2+...+n
     * @return  sum
     */
    public BigInteger sum() {
        var result = BigInteger.ZERO;
        var n = argument;
        for (; n > 0; --n) result = result.add(BigInteger.valueOf(n));
        return result;
    }

    /**
     * Computes the product 1*2*...*n
     * @return  product (a.k.a. factorial)
     */
    public BigInteger product() {
        var result = BigInteger.ONE;
        var n = argument;
        for (; n > 0; --n) result = result.multiply(BigInteger.valueOf(n));
        return result;
    }

    /**
     * Computes the nth Fibonacci number
     * @return  fibonacci
     */
    public BigInteger fibonacci() {
        var f0 = BigInteger.ZERO;
        var f1 = BigInteger.ONE;
        var n = argument;
        for (; n > 0; --n) {
            var f = f0.add(f1);
            f0 = f1;
            f1 = f;
        }
        return f0;
    }
}

Det som är nytt är taggen @snippet, som antingen kan förses direkt med en kodsnutt (första) eller hänvisa till en fil, vilket ju är det mest nya och intressanta här. Klassen NumbersSnippets.java ligger i en separat källkodskatalog, eftersom vi ju inte vill baka in denna med resten av applikationen. Som synes kan man också referera till ett viss utsnitt av koden (region). Kodsnuttsklassen utgörs av NumbersSnippets.java och ser ut så här:

import ribomation.code_snippets.Numbers;
public class NumbersSnippets {
    public static void main(String[] args) {
        // @start region="usage" @highlight region substring="printf" type="highlight"
        var app = new Numbers(10);
        System.out.printf("sum : %s%n", app.sum());
        System.out.printf("prod: %s%n", app.product());
        System.out.printf("fib : %s%n", app.fibonacci());
        // @end @end
    }
}

Här kan du se att man markerar en region med @start och @end. Dessutom går det att markera vissa sektioner. I exemplet ovan, markeras alla förekomster av printf i den subregion som avgränsas med @highlight och @end. De markerade delarna får en CSS klass i den genererade HTML-koden, enligt type attributet. Här följer en liten CSS fil (style.css):

.highlight {
    color: darkorange;
    font-weight: bold;
}

Så här ser ett kommando ut för att generera JavaDoc för målklassen ovan.

javadoc --snippet-path ./snippets/ --add-stylesheet ./snippets/style.css -d ./api/ src/ribomation/code_snippets/Numbers.java

Resultatet ser ut så här:

Generated JavaDoc demonstrating the new @snippet doclet tag

Vad mer finns det då i Java 18? Ja, det finns en liten webbserver, som kan hantera HTTP GET och HEAD, men alltså inte HTTP POST med flera. Tanken är att den kan fungera i enhetstest med mera. Man startar den från kommandoraden med jwebserver. Det är också möjligt att starta den programmatisk, vilket öppnar för några fler konfigureringsalternativ.

$ jwebserver --help
Usage: jwebserver [-b bind address] [-p port] [-d directory]
                  [-o none|info|verbose] [-h to show options]
                  [-version to show version information]
Options:
-b, --bind-address    - Address to bind to. Default: 127.0.0.1 (loopback).
                        For all interfaces use "-b 0.0.0.0" or "-b ::".
-d, --directory       - Directory to serve. Default: current directory.
-o, --output          - Output format. none|info|verbose. Default: info.
-p, --port            - Port to listen on. Default: 8000.
-h, -?, --help        - Prints this help message and exits.
-version, --version   - Prints version information and exits.
To stop the server, press Ctrl + C.

För övrigt, är det en del metoder och klasser som har blivit markerade för borttagning (deprecated). I denna version är det java.lang.Object#finalize(), som med tiden kommer tas bort. Det är metod som anropas av skräpsamlaren (GC) innan ett object städas undan och var tänkt i Java version 1, som ett sätt att återlämna resurser, typ stänga en databasanslutning med mera. Dock har de senaste 27 åren visat att (1) ingen använder metoden och (2) de som gör det ofta på felaktigt sätt.

@Deprecated(since="9", forRemoval=true)
protected void finalize() throws Throwable { }

Är det som så att du använder denna metod på ett affärskritiskt sätt, är nog bra att se över detta och hitta ett bättre sätt att städa undan resurser.

Nu är det förvisso ingen jättepanik; det lär dröja ett flertal Java versioner innan metoden försvinner helt. Som en jämförelse kan vi kika på metoden java.lang.Thread#stop(), som varit deprecated i 25 år... 🤔

@Deprecated(since="1.2", forRemoval=true)
public final void stop() {

Länkar