Compilare per una versione precedente di Java con Animal Sniffer

Spesso è necessario compilare le proprie applicazioni Java in modo che siano compatibili con versioni precedenti del Java Runtime Environment (JRE).

Benché sia possibile utilizzare una vecchia versione del compilatore javac, tale soluzione è sconsigliabile in quanto si rinuncia a tutte le più recenti migliorie apportate al compilatore stesso.

javac supporta l’opzione -target che consente di specificare qual è la versione minima su cui si intende far girare la classe compilata. Tale opzione, tuttavia, è necessaria ma non sufficiente a garantire il corretto funzionamento della classe, in quanto se da un lato verifica che non siano state utilizzate caratteristiche del linguaggio non supportate dalla versione specificata, dall’altro non si accerta che non siano state utilizzate API, ovvero classi e metodi, non presenti in quella versione, a meno che non si prendano precise precauzioni.

A questo proposito, consideriamo un caso pratico: a partire dalla versione 9 di Java, l’interfaccia java.util.Set è stata arricchita di una serie di metodi statici denominati of(…), che consentono, con una sola istruzione, di istanziare degli insiemi contenenti zero o più elementi.

La seguente classe denominata, con molta fantasia, AnimalSnifferExample.java, fa uso proprio di uno di questi metodi:

public class AnimalSnifferExample {

   public static void main(String... args) {
      System.out.println(java.util.Set.of("1st item", "2nd item", "3rd item"));
   }

}

Effettueremo ora delle prove di compilazione ed esecuzione con diverse versioni di javac e java, utilizzando talvolta alcune specifiche opzioni di compilazione:

  • Compilando con javac 11 (l’importante è che la versione sia successiva alla 9) ed eseguendo con java 11 si ha:

    $ /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt/bin/javac -version AnimalSnifferExample.java
    javac 11.0.1-BellSoft
    
    $ /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt/bin/java -showversion AnimalSnifferExample
    openjdk version "11.0.1-BellSoft" 2018-10-16
    OpenJDK Runtime Environment (build 11.0.1-BellSoft+0)
    OpenJDK Server VM (build 11.0.1-BellSoft+0, mixed mode)
    [1st item, 3rd item, 2nd item]
    

    Nessuna sorpresa: il codice compila e funziona correttamente (se vi state chiedendo come mai gli elementi non siano ordinati, potete consultare la documentazione di java.util.Set).

    Se a questo punto provassimo a rieseguire con java 8 la classe compilata con javac 11 otterremmo invece il seguente errore:

    $ /usr/lib/jvm/jdk1.8.0_191/jre/bin/java -showversion AnimalSnifferExample
    java version "1.8.0_191"
    Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
    Java HotSpot(TM) Client VM (build 25.191-b12, mixed mode)
    
    Error: A JNI error has occurred, please check your installation and try again
    Exception in thread "main" java.lang.UnsupportedClassVersionError: AnimalSnifferExample has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
       at java.lang.ClassLoader.defineClass1(Native Method)
       at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
       at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
       at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
       at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
       at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
       at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
       at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
       at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
    

    Ancora una volta, nessuna sorpresa: è normale che una classe compilata con una certa versione di javac, senza aver specificato opportune opzioni, non risulti eseguibile con versioni precedenti di java.

  • Ora compiliamo sempre con javac 11 ma specificando l’opzione -target 1.8 (e conseguentemente anche l’opzione -source 1.8 richiesta dal compilatore); successivamente proviamo ad eseguire la classe con java 8:

    $ /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt/bin/javac -target 1.8 -source 1.8 -version AnimalSnifferExample.java
    javac 11.0.1-BellSoft
    warning: [options] bootstrap class path not set in conjunction with -source 8
    1 warning
    
    $ /usr/lib/jvm/jdk1.8.0_191/jre/bin/java -showversion AnimalSnifferExample
    java version "1.8.0_191"
    Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
    Java HotSpot(TM) Client VM (build 25.191-b12, mixed mode)
    
    Exception in thread "main" java.lang.NoSuchMethodError: java.util.Set.of(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Set;
       at AnimalSnifferExample.main(AnimalSnifferExample.java:4)
    

    L’avviso emesso da javac relativamente al bootstrap class path non andrebbe sottovalutato, tuttavia la compilazione termina con successo. L’esecuzione, invece, termina in errore, segnalando che il metodo java.util.Set.of(…) non esiste. Questa situazione è assolutamente indesiderabile perché si ha un codice apparentemente compatibile con una versione precedente di Java, ma che in realtà va in errore a tempo di esecuzione.

  • Se volessimo rendere compatibile il nostro codice anche con java 7 (-target 1.7), paradossalmente saremmo più fortunati:

    $ /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt/bin/javac -target 1.7 -source 1.7 -version AnimalSnifferExample.java
    javac 11.0.1-BellSoft
    warning: [options] bootstrap class path not set in conjunction with -source 7
    AnimalSnifferExample.java:4: error: static interface method invocations are not supported in -source 7
          System.out.println(java.util.Set.of("1st item", "2nd item", "3rd item"));
                                          ^
      (use -source 8 or higher to enable static interface method invocations)
    1 error
    1 warning
    

    Come si vede, la compilazione fallisce perché il supporto ai metodi statici nelle interfacce è stato introdotto con Java 8, quindi quando si ha un’incompatibilità a livello di linguaggio, si riscontra un errore già a tempo di compilazione. In questa situazione, almeno, non c’è quella pericolosa parvenza di compatibilità sperimentata nel caso precedente.


Fortunatamente esistono diversi modi per far sì che la build notifichi eventuali problemi di compatibilità, evitando, così, spiacevoli problemi a runtime:

  • Se per compilare si utilizza JDK versione 9 o successiva e si intende compilare per JRE versione 6 o successiva, la cosa migliore è aggiungere la nuova opzione -release alla riga di comando del compilatore, seguita dal numero di versione del runtime target desiderato, ad esempio -release 6 per JRE 1.6; fatto questo, il problema si può considerare completamente risolto e non occorre fare altro. Se invece non fosse possibile utilizzare JDK versione 9 o successiva per la compilazione, vedere i punti successivi.

  • Aggiungere l’opzione --boot-class-path al compilatore, specificando il percorso della libreria di runtime Java di interesse, che nel nostro caso è costituita dal file rt.jar incluso nel JRE 1.8:

    $ /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt/bin/javac -source 1.8 -target 1.8 --boot-class-path /usr/lib/jvm/jdk1.8.0_191/jre/lib/rt.jar -version AnimalSnifferExample.java
    javac 11.0.1-BellSoft
    AnimalSnifferExample.java:4: error: cannot find symbol
          System.out.println(java.util.Set.of("1st item", "2nd item", "3rd item"));
                                          ^
      symbol:   method of(String,String,String)
      location: interface Set
    1 error
    

    Prima di tutto si nota che non viene più emesso il warning relativo al bootstrap class path, dopo di che la compilazione fallisce perché il compilatore non trova il metodo of(...) all’interno della libreria di runtime specificata.
    Si tratta di una soluzione assolutamente valida; il problema, tuttavia, è che non sempre si ha a disposizione il runtime necessario, specialmente se si utilizza un ambiente di build (ad esempio di continuous integration) fuori dal proprio controllo.

  • Utilizzare Animal Sniffer dopo la compilazione. Animal Sniffer è uno strumento open source che fa parte del progetto MojoHaus. Se integrato nel processo di build, è in grado di esaminare i file compilati (.class) per verificare che siano effettivamente compatibili con versioni precedenti del runtime Java. Questo controllo è reso possibile da opportune firme (signature) generate a partire dalle stesse librerie di runtime e rese disponibili sempre da MojoHaus. Vi sono anche firme specifiche per versioni particolari del JRE, anche proprietarie (ad es. Apple e IBM).

Nulla vieta, infine, di mettere in atto entrambi questi ultimi due accorgimenti.


Utilizzo di Animal Sniffer con Maven

Utilizzare Animal Sniffer con Maven è estremamente semplice, è sufficiente aggiungere l’apposito plugin nel pom.xml e il gioco è fatto:

<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>animal-sniffer-maven-plugin</artifactId>
   <version>1.16</version>
   <executions>
      <execution>
         <phase>process-classes</phase>
         <goals>
            <goal>check</goal>
         </goals>
      </execution>
   </executions>
   <configuration>
      <signature>
         <groupId>org.codehaus.mojo.signature</groupId>
         <artifactId>java18</artifactId>
         <version>1.0</version>
      </signature>
   </configuration>
</plugin>

Occorre impostare artifactId e version della signature a seconda della compatibilità desiderata. In generale le ultime cifre dell’artifactId indicano la versione del runtime di riferimento (ad esempio 18 corrisponde al JRE 1.8).

Tutte le firme disponibili sono consultabili sul repository Maven Central; ove fossero presenti più versioni dello stesso artefatto, conviene scegliere la più recente.

Un’ultima considerazione riguarda la fase di esecuzione, qui impostata su process-classes; in alcuni esempi presenti in rete viene preferita la fase verify, ma poiché verify è successiva a package, la segnalazione di errore si avrebbe ad artefatto ormai prodotto (sebbene non installato), invece con process-classes o test, Animal Sniffer interviene subito dopo la compilazione.

Esempio completo con Maven Vedi su GitHub

Prepariamo la seguente alberatura di progetto:

├── src
│   └── main
│       └── java
│           └── AnimalSnifferExample.java
└── pom.xml

Il contenuto del file AnimalSnifferExample.java è stato già presentato; segue invece il listato completo del file pom.xml di Maven:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>
   <groupId>com.example</groupId>
   <artifactId>animal-sniffer-example-mvn</artifactId>
   <version>0.0.1</version>

   <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>

   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>animal-sniffer-maven-plugin</artifactId>
            <version>1.16</version>
            <executions>
               <execution>
                  <phase>process-classes</phase>
                  <goals>
                     <goal>check</goal>
                  </goals>
               </execution>
            </executions>
            <configuration>
               <signature>
                  <groupId>org.codehaus.mojo.signature</groupId>
                  <artifactId>java18</artifactId>
                  <version>1.0</version>
               </signature>
            </configuration>
         </plugin>
      </plugins>
   </build>

</project>

Notare le righe evidenziate in cui sono presenti i riferimenti alle firme del runtime Java 1.8.

A questo punto, eseguendo Maven con Java 9 o versioni successive (di norma Maven utilizza il JDK referenziato dalla variabile di ambiente JAVA_HOME) si ha:

$ mvn clean package -V
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-24T20:41:47+02:00)
Maven home: /opt/maven
Java version: 11.0.1-BellSoft, vendor: BellSoft, runtime: /usr/lib/jvm/jdk-11-bellsoft-arm32-vfp-hflt
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.14.79-v7+", arch: "arm", family: "unix"
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< com.example:animal-sniffer-example-mvn >---------------
[INFO] Building animal-sniffer-example-mvn 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ animal-sniffer-example-mvn ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ animal-sniffer-example-mvn ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /tmp/animal-sniffer-example-mvn/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ animal-sniffer-example-mvn ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /tmp/animal-sniffer-example-mvn/target/classes
[INFO]
[INFO] --- animal-sniffer-maven-plugin:1.16:check (default) @ animal-sniffer-example-mvn ---
[INFO] Checking unresolved references to org.codehaus.mojo.signature:java18:1.0
[ERROR] /tmp/animal-sniffer-example-mvn/src/main/java/AnimalSnifferExample.java:4: Undefined reference: java.util.Set java.util.Set.of(Object, Object, Object)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.422 s
[INFO] Finished at: 2018-12-15T09:17:14+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.16:check (default) on project animal-sniffer-example-mvn: Signature errors found. Verify them and ignore them with the proper annotation if needed. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Come è evidente, la build fallisce, prevenendo eventuali errori a tempo di esecuzione. L’output segnala inoltre il riferimento non valido al metodo java.util.Set.of(Object, Object, Object) che infatti in Java 8 non esiste.

Ulteriori informazioni sono disponibili sul sito di MojoHaus, nella pagina dedicata all’Animal Sniffer Maven Plugin.


Utilizzo di Animal Sniffer con Ant

Usare Animal Sniffer con Ant è leggermente più complicato rispetto a Maven, ma comunque nulla che richieda più di qualche minuto di messa a punto:

  1. Scaricare il file JAR animal-sniffer-ant-tasks (link) e il file .signature del runtime Java di interesse (link) dal repository Maven Central.
  2. Posizionare i due file scaricati all’interno della directory del progetto, ad esempio in una sottodirectory dedicata: ant/animal-sniffer/
  3. Modificare il file build.xml aggiungendo all’elemento <project> l’attributo xmlns:as="antlib:org.codehaus.mojo.animal_sniffer", in modo da definire un namespace as.
  4. Aggiungere, sempre al build.xml, un target che effettui il controllo delle classi compilate, ad esempio:

    <target name="check-signature">
       <typedef uri="antlib:org.codehaus.mojo.animal_sniffer">
          <classpath path="ant/animal-sniffer/animal-sniffer-ant-tasks-1.16.jar" />
       </typedef>
       <as:check-signature signature="ant/animal-sniffer/java18-1.0.signature">
          <path path="build/classes" />
          <classpath>
             <fileset dir="lib" erroronmissingdir="false">
                <include name="*.jar" />
             </fileset>
          </classpath>
       </as:check-signature>
    </target>
    

    Il task as:check-signature deve essere configurato con lo stesso classpath utilizzato dal task javac (che tipicamente si trova nel target compile). Verificare anche la correttezza dei riferimenti al JAR animal-sniffer-ant-tasks e al file .signature.

Esempio completo con Ant Vedi su GitHub

Prepariamo un’alberatura come la seguente, scaricando manualmente animal-sniffer-ant-tasks-1.16.jar e java18-1.0.signature dal repository Maven Central:

├── ant
│   └── animal-sniffer
│       ├── animal-sniffer-ant-tasks-1.16.jar
│       └── java18-1.0.signature
├── src
│   └── AnimalSnifferExample.java
└── build.xml

La classe AnimalSnifferExample.java è sempre la stessa; segue invece il listato completo del file build.xml di Ant:

<?xml version="1.0" encoding="UTF-8"?>
<project name="animal-sniffer-example-ant" xmlns:as="antlib:org.codehaus.mojo.animal_sniffer">

   <target name="clean">
      <delete dir="build" />
   </target>

   <fileset id="classpath" dir="lib" erroronmissingdir="false">
      <include name="*.jar" />
   </fileset>

   <target name="compile">
      <mkdir dir="build/classes" />
      <javac srcdir="src" destdir="build/classes" source="1.8" target="1.8" includeantruntime="false" debug="true">
         <compilerarg value="-version" />
         <classpath>
            <fileset refid="classpath" />
         </classpath>
      </javac>
   </target>

   <target name="check-signature">
      <typedef uri="antlib:org.codehaus.mojo.animal_sniffer">
         <classpath path="ant/animal-sniffer/animal-sniffer-ant-tasks-1.16.jar" />
      </typedef>
      <as:check-signature signature="ant/animal-sniffer/java18-1.0.signature">
         <path path="build/classes" />
         <classpath>
            <fileset refid="classpath" />
         </classpath>
      </as:check-signature>
   </target>

</project>

Notare la riga evidenziata in cui è presente il riferimento alle firme del runtime Java 1.8.

Eseguendo Ant con Java 9 o versioni successive (anche Ant, come Maven, utilizza il JDK referenziato dalla variabile di ambiente JAVA_HOME) si ha:

$ ant clean compile check-signature
Buildfile: /tmp/animal-sniffer-example-ant/build.xml

clean:

compile:
    [mkdir] Created dir: /tmp/animal-sniffer-example-ant/build/classes
    [javac] Compiling 1 source file to /tmp/animal-sniffer-example-ant/build/classes
    [javac] javac 11.0.1-BellSoft
    [javac] warning: [options] bootstrap class path not set in conjunction with -source 8
    [javac] 1 warning

check-signature:
[as:check-signature] In createClasspath
[as:check-signature] Checking unresolved references to /tmp/animal-sniffer-example-ant/ant/animal-sniffer/java18-1.0.signature
[as:check-signature] Ignoring the signatures from file to be checked: /tmp/animal-sniffer-example-ant/build/classes
[as:check-signature] /tmp/animal-sniffer-example-ant/build/classes/AnimalSnifferExample.class:4: Undefined reference: java.util.Set java.util.Set.of(Object, Object, Object)

BUILD FAILED
/tmp/animal-sniffer-example-ant/build.xml:26: Signature errors found. Verify them and ignore them with the proper annotation if needed.

Come nel precedente esempio con Maven, anche in questo caso la build fallisce segnalando le classi che contengono riferimenti non validi, inclusi i numeri di riga, se è stato impostato a true l’attributo debug del task javac di Ant.

Ulteriori informazioni sono disponibili sul sito di MojoHaus, nella pagina dedicata agli Animal Sniffer ANT Tasks.

Raspberry Pi – Java

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Le versioni di Java presenti nei repository APT di Raspbian possono essere obsolete o comunque inadeguate alle proprie esigenze, pertanto può essere desiderabile installarne altre. In questi casi, per consentire di volta in volta una selezione agevole della versione attiva, occorre tenere opportunamente aggiornate le alternative dei vari eseguibili di ciascun Java Development Kit (JDK) in modo da poter poi utilizzare l’utility update-java-alternatives, inclusa in Raspbian.

Oracle JDK

Le istruzioni che seguono si riferiscono alla versione 7u75 che è l’ultima versione di Java 7 rilasciata pubblicamente da Oracle per ARM, ma possono essere adattate ad altre versioni sostituendo 7 e 1.7.0_75 con la versione di interesse.

  1. Scaricare dal sito oracle.com una versione del JDK per Linux ARM in formato tar.gz. La versione JDK 7 più recente è la 7u75 Linux ARM v6/v7 Hard Float ABI. Per effettuare il download può essere richiesto un account Oracle gratuito.
  2. Decomprimere l’archivio nel percorso /usr/lib/jvm/ in modo che ne risulti un’alberatura del tipo /usr/lib/jvm/jdk1.7.0_75/:
    1. Recarsi nella directory contenente l’archivio tar.gz scaricato.
    2. sudo tar xzvf jdk-7u75-linux-arm-vfp-hflt.tar.gz -C /usr/lib/jvm
  3. Creare un link simbolico (alias) per questa versione di Java:
    1. cd /usr/lib/jvm
    2. sudo ln -nsf jdk1.7.0_75 java-7-oracle
  4. Creare il file jinfo (richiesto da update-java-alternatives) e le alternative per gli eseguibili; notare che il valore 1071 rappresenta la priorità e può essere modificato a piacimento (valori tipici sono: 1071 per JDK 7, 1081 per JDK 8):
    1. cd java-7-oracle
    2. sudo mkdir .alternatives && cd .alternatives
    3. sudo wget https://git.io/fAv4G -O alternatives.java
    4. sudo ../bin/javac alternatives.java
    5. sudo ../bin/java alternatives .. /usr/lib/jvm/java-7-oracle 1071
    6. sudo cp -i .java-*-oracle.jinfo /usr/lib/jvm/
    7. sudo ./install-alternatives.sh
  5. In caso di disinstallazione ovvero prima di installare una versione aggiornata, al fine di rimuovere le alternative che altrimenti resterebbero appese (consigliato), si può eseguire il seguente comando che elimina le stesse alternative precedentemente create da install-alternatives.sh:
    sudo /usr/lib/jvm/java-7-oracle/.alternatives/remove-alternatives.sh

BellSoft Liberica JDK

Liberica è un’implementazione di Java per Raspberry Pi totalmente open source. È compilata a partire da OpenJDK, cui BellSoft contribuisce. Le istruzioni che seguono si riferiscono alla versione 9.0.4 ma possono essere adattate ad altre versioni sostituendo 9 e 9.0.4 con la versione di interesse.

  1. Scaricare dal sito bell-sw.com > Get Liberica JDK una versione del JDK per Linux ARMv7&8 32 Bit HardFloat in formato deb:
    1. cd ~/Downloads
    2. wget https://github.com/bell-sw/Liberica/releases/download/9.0.4/bellsoft-jdk9.0.4-linux-arm32-vfp-hflt.deb
  2. sudo apt install ./bellsoft-jdk9.0.4-linux-arm32-vfp-hflt.deb
  3. Creare un link simbolico (alias) per questa versione di Java:
    1. cd /usr/lib/jvm
    2. sudo ln -nsf jdk-9.0.4-bellsoft-arm32-vfp-hflt java-9-bellsoft
  4. Determinare la priorità delle alternative create durante l’installazione:
    1. update-alternatives --display java
    2. Identificare la riga corrispondente al JDK appena installato e la relativa priorità, in questo caso:
      /usr/lib/jvm/jdk-9.0.4-bellsoft-arm32-vfp-hflt/bin/java - priority 1901
  5. Creare il file jinfo (richiesto da update-java-alternatives) utilizzando la priorità predeterminata:
    1. cd java-9-bellsoft
    2. sudo mkdir .alternatives && cd .alternatives
    3. sudo wget https://git.io/fAv4G -O alternatives.java
    4. sudo ../bin/javac alternatives.java
    5. sudo ../bin/java alternatives .. /usr/lib/jvm/java-9-bellsoft 1901
    6. sudo cp -i .java-*-bellsoft.jinfo /usr/lib/jvm/
  6. Cancellare l’archivio originale per recuperare spazio (facoltativo): rm ~/Downloads/bellsoft-jdk9.0.4-linux-arm32-vfp-hflt.deb

Per impostare la versione di Java attiva, utilizzare update-java-alternatives:

  1. Elenco versioni installate: update-java-alternatives -l
    java-10-bellsoft               1904       /usr/lib/jvm/java-10-bellsoft
    java-1.6.0-openjdk-armhf       1057       /usr/lib/jvm/java-1.6.0-openjdk-armhf
    java-7-oracle                  1071       /usr/lib/jvm/java-7-oracle
    java-8-oracle                  1081       /usr/lib/jvm/java-8-oracle
    java-9-bellsoft                1901       /usr/lib/jvm/java-9-bellsoft
    jdk-7-oracle-arm-vfp-hflt      317        /usr/lib/jvm/jdk-7-oracle-arm-vfp-hflt
    jdk-8-oracle-arm32-vfp-hflt    318        /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt
  2. Selezione della versione desiderata: sudo update-java-alternatives -s java-7-oracle
  3. Eventuali errori non pregiudicano il buon esito dell’operazione:
    update-alternatives: error: no alternatives for jmc
    update-alternatives: error: no alternatives for jvisualvm
    update-alternatives: error: no alternatives for mozilla-javaplugin.so
  4. Per verificare quale versione è stata effettivamente impostata: java -version
    java version "1.7.0_75"
    Java(TM) SE Runtime Environment (build 1.7.0_75-b13)
    Java HotSpot(TM) Client VM (build 24.75-b04, mixed mode)
    

È consigliabile creare un link simbolico al JDK preferito e impostare la variabile d’ambiente JAVA_HOME, ad esempio:

  1. cd /usr/lib/jvm
  2. sudo ln -nsf java-7-oracle default-java
  3. echo 'JAVA_HOME="/usr/lib/jvm/default-java"' | sudo tee -a /etc/environment

Raspberry Pi – Tomcat

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Prima di iniziare, accertarsi di disporre di una versione di Java compatibile con la versione di Apache Tomcat che si intende installare.

  1. Scaricare una versione Binary Distributions – Core – tar.gz dal sito tomcat.apache.org > Download:
    1. cd /opt
    2. sudo wget http://mirrors.ibiblio.org/apache/tomcat/tomcat-9/v9.0.12/bin/apache-tomcat-9.0.12.tar.gz
  2. Decomprimere l’archivio in /opt/:
    1. sudo tar xzvf apache-tomcat-9.0.12.tar.gz
    2. sudo ln -nsf apache-tomcat-9.0.12 tomcat
    3. sudo rm apache-tomcat-9.0.12.tar.gz
  3. Creare l’utente Linux tomcat:
    1. sudo adduser --disabled-login --disabled-password --gecos "" --home /var/lib/tomcat tomcat
    2. sudo addgroup pi tomcat (efficace solo dopo disconnessione e riconnessione)
    3. sudo chown -R tomcat:tomcat tomcat/
  4. Impostare la variabile di ambiente CATALINA_HOME: echo 'CATALINA_HOME="/opt/tomcat"' | sudo tee -a /etc/environment
  5. Aggiungere gli utenti per le applicazioni manager e host-manager:
    1. sudo nano /opt/tomcat/conf/tomcat-users.xml
    2. Aggiungere le seguenti righe nell’elemento <tomcat-users> per definire gli utenti admin e manager, impostando opportunamente le password:
      <role rolename="manager-gui" />
      <role rolename="admin-gui" />
      <user username="admin" password="ADMIN" roles="manager-gui,admin-gui" />
      <user username="manager" password="MANAGER" roles="manager-gui" />
  6. Configurare la sicurezza di rete per le applicazioni manager e host-manager (verificare e adeguare opportunamente l’espressione regolare degli indirizzi autorizzati, in questo caso tutta la rete locale):
    1. sudo mkdir -p /opt/tomcat/conf/Catalina/localhost
    2. printf '<Context privileged="true" antiResourceLocking="false" docBase="${catalina.home}/webapps/manager">\n\t<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="%s" />\n</Context>\n' '127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[01])\.\d+\.\d+' | sudo tee /opt/tomcat/conf/Catalina/localhost/manager.xml
    3. printf '<Context privileged="true" antiResourceLocking="false" docBase="${catalina.home}/webapps/host-manager">\n\t<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="%s" />\n</Context>\n' '127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[01])\.\d+\.\d+' | sudo tee /opt/tomcat/conf/Catalina/localhost/host-manager.xml
  7. Per limitare l’uso di RAM (raccomandato), prima di avviare: export JAVA_OPTS="-Xms8m -Xmx128m -XX:MaxMetaspaceSize=128m" o meglio scrivere questa riga all’interno di setenv.sh in /opt/tomcat/bin/:
    1. printf '#!/bin/sh\nexport JAVA_OPTS="$JAVA_OPTS -Xms8m -Xmx128m -XX:MaxMetaspaceSize=128m"\n' | sudo tee /opt/tomcat/bin/setenv.sh
    2. sudo chmod 755 /opt/tomcat/bin/setenv.sh
  8. Compilare e installare la libreria Tomcat Native APR per migliorare le prestazioni (facoltativo, richiede OpenSSL >= 1.0.2):
    1. sudo -i
    2. cd /opt/tomcat/bin
    3. wget http://it.apache.contactlab.it/tomcat/tomcat-connectors/native/1.2.18/source/tomcat-native-1.2.18-src.tar.gz
    4. tar xzvf tomcat-native-1.2.18-src.tar.gz
    5. rm tomcat-native-1.2.18-src.tar.gz
    6. apt-get install libapr1-dev libssl-dev
    7. cd tomcat-native-1.2.18-src/native
    8. ./configure (se la variabile d’ambiente JAVA_HOME non è impostata, aggiungere --with-java-home=/usr/lib/jvm/...; per utilizzare una versione particolare di OpenSSL, aggiungere --with-ssl=/usr/local/ssl)
    9. make
    10. make install
    11. cd /usr/local/apr/lib
    12. rm -R /opt/tomcat/bin/tomcat-native-1.2.18-src
    13. mkdir -p /usr/java/packages/lib/arm
    14. cp libtcnative* /usr/java/packages/lib/arm/
    15. exit
  9. Installare haveged per velocizzare l’avvio del server (raccomandato): sudo apt-get install haveged
  10. Per avviare e arrestare Tomcat manualmente, utilizzare i seguenti comandi:
    1. sudo su tomcat -c "/opt/tomcat/bin/startup.sh"
    2. sudo su tomcat -c "/opt/tomcat/bin/shutdown.sh"
  11. Configurare Tomcat come servizio (consigliato):
    1. sudo wget https://git.io/fNhfK -O /etc/init.d/tomcat
    2. sudo chmod 755 /etc/init.d/tomcat
    3. sudo mkdir -p /etc/default
    4. sudo wget https://git.io/fNhf5 -O /etc/default/tomcat
    5. sudo update-rc.d tomcat defaults
    6. sudo systemctl daemon-reload (solo Raspbian Jessie e versioni successive)
  12. Il servizio viene preconfigurato per l’avvio automatico; per disabilitare o abilitare l’avvio automatico (facoltativo):
    • systemd (Raspbian Jessie e versioni successive):
      1. sudo systemctl disable tomcat
      2. sudo systemctl enable tomcat
    • SysV (Raspbian Wheezy):
      1. sudo update-rc.d tomcat disable
      2. sudo update-rc.d tomcat enable

Raspberry Pi – Maven

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Prima di iniziare, accertarsi di disporre di una versione di Java compatibile con la versione di Apache Maven che si intende installare.

  1. Scaricare una release dal sito maven.apache.org > Download > Files > Binary tar.gz archive:
    1. cd /opt
    2. sudo wget http://mirrors.ibiblio.org/apache/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz
  2. sudo tar xzvf apache-maven-3.5.4-bin.tar.gz
  3. sudo ln -nsf apache-maven-3.5.4 maven
  4. sudo rm apache-maven-3.5.4-bin.tar.gz
  5. Creare le alternative (la versione associata al link simbolico sarà di norma quella preferita perché a priorità massima):
    1. sudo update-alternatives --install /usr/bin/mvn mvn /opt/maven/bin/mvn 2147483647
    2. sudo update-alternatives --install /usr/bin/mvn mvn /opt/apache-maven-3.5.4/bin/mvn 30504
    3. Per selezionare la versione da utilizzare (in presenza di molteplici versioni): sudo update-alternatives --config mvn
  6. Per limitare l’uso di RAM, impostare la variable di ambiente MAVEN_OPTS prima di eseguire mvn: export MAVEN_OPTS="-client -Xms8m -Xmx96m -DargLine=-Xmx192m"
    • È possibile rendere permanenti queste impostazioni (raccomandato):
      echo 'MAVEN_OPTS="-client -Xms8m -Xmx96m -DargLine=-Xmx192m"' | sudo tee -a /etc/environment
  7. Installare lo script bash di autocompletamento (facoltativo): sudo wget https://git.io/fpNqc -O /etc/bash_completion.d/mvn

Verificare l’avvenuta installazione: mvn -version

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T20:33:14+02:00)
Maven home: /opt/maven
Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /usr/lib/jvm/jdk1.8.0_181/jre
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.14.69-v7+", arch: "arm", family: "unix"

Raspberry Pi – Apache Ant

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Prima di iniziare, accertarsi di disporre di una versione di Java compatibile con la versione di Apache Ant che si intende installare.

  1. Scaricare una release dal sito ant.apache.org > Download > Binary Distributions in formato .tar.gz archive:
    1. cd /opt
    2. sudo wget http://mirrors.ibiblio.org/apache/ant/binaries/apache-ant-1.10.5-bin.tar.gz
  2. sudo tar xzvf apache-ant-1.10.5-bin.tar.gz
  3. sudo ln -nsf apache-ant-1.10.5 ant
  4. sudo rm apache-ant-1.10.5-bin.tar.gz
  5. Creare le alternative (la versione associata al link simbolico sarà di norma quella preferita perché a priorità massima):
    1. sudo update-alternatives --install /usr/bin/ant ant /opt/ant/bin/ant 2147483647
    2. sudo update-alternatives --install /usr/bin/ant ant /opt/apache-ant-1.10.5/bin/ant 11005
    3. Per selezionare la versione da utilizzare (in presenza di molteplici versioni): sudo update-alternatives --config ant
  6. Creare la variabile d’ambiente ANT_HOME (facoltativo): echo 'ANT_HOME="/opt/ant"' | sudo tee -a /etc/environment
  7. Per limitare l’uso di RAM, impostare la variable di ambiente ANT_OPTS prima di eseguire ant: export ANT_OPTS="-client -Xms8m -Xmx96m"
    • È possibile rendere permanenti queste impostazioni (raccomandato):
      echo 'ANT_OPTS="-client -Xms8m -Xmx96m"' | sudo tee -a /etc/environment

Verificare l’avvenuta installazione: ant -version

Apache Ant(TM) version 1.10.5 compiled on July 10 2018

Raspberry Pi – HTOP

HTOP screenshot

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Installazione mediante APT:

  1. sudo apt-get install htop

Installazione manuale (per ottenere una versione specifica o quella più recente):

  1. Scaricare i sorgenti dal sito hisham.hm/htop > Download > Sources > Stable, tarball:
    1. mkdir ~/htop-build-tmp
    2. cd ~/htop-build-tmp
    3. wget https://hisham.hm/htop/releases/2.2.0/htop-2.2.0.tar.gz
  2. tar xzvf htop-*.tar.gz
  3. cd htop-*/
  4. sudo apt-get install build-essential libncursesw5-dev
  5. Configurazione della build:
    • Build predefinita (consigliata):
      1. ./configure
    • Per abilitare le caratteristiche opzionali:
      1. sudo apt-get install libhwloc-dev libnl-3-dev libnl-genl-3-dev
      2. ./configure --enable-proc --enable-openvz --enable-cgroup --enable-vserver --enable-taskstats --enable-unicode --enable-hwloc --enable-setuid --enable-delayacct
  6. make
  7. sudo make install
  8. cd
  9. rm -R ~/htop-build-tmp

Verificare l’avvenuta installazione: htop --version

Raspberry Pi – VICE Emulator

VICE Emulator screenshot

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.
  1. Scaricare nella directory /opt/ una Source distribution in formato tar.gz dal sito vice-emu.sourceforge.net > Downloads, ad esempio vice-3.2.tar.gz.
  2. cd /opt
  3. sudo tar xzvf vice-3.2.tar.gz
  4. sudo ln -sf vice-3.2 vice
  5. sudo rm vice-3.2.tar.gz
  6. sudo chown -R pi:pi vice/
  7. cd vice
  8. sudo apt-get install build-essential byacc flex xa65 libgtk2.0-dev libreadline-dev libasound2-dev libvte-dev
    • Se si desidera anche il supporto per l’hardware scaling (facoltativo):
      sudo apt-get install libgtkglext1-dev
  9. Configurare la build (PulseAudio e reSID vengono esclusi per motivi di prestazioni):
    ./configure --enable-fullscreen --enable-gnomeui --with-x --with-alsa --without-pulse --without-oss --without-resid
  10. make
  11. cp -R data/ ~/.vice
  12. Per avviare, lanciare manualmente gli eseguibili presenti in /opt/vice/src/ oppure creare e utilizzare dei collegamenti nel menù delle applicazioni:
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=SID Emulator\n' vsid vsid | sudo tee /usr/share/applications/vice-vsid.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore 128\n' x128 x128 | sudo tee /usr/share/applications/vice-x128.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore 64\n' x64 x64 | sudo tee /usr/share/applications/vice-x64.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=C64 Direct-to-TV\n' x64dtv x64dtv | sudo tee /usr/share/applications/vice-x64dtv.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore 64 (accurate)\n' x64sc x64sc | sudo tee /usr/share/applications/vice-x64sc.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore CBM-II (6x0/7x0)\n' xcbm2 xcbm2 | sudo tee /usr/share/applications/vice-xcbm2.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore CBM-II (5x0)\n' xcbm5x0 xcbm5x0 | sudo tee /usr/share/applications/vice-xcbm5x0.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore PET\n' xpet xpet | sudo tee /usr/share/applications/vice-xpet.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore Plus4\n' xplus4 xplus4 | sudo tee /usr/share/applications/vice-xplus4.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=SuperCPU\n' xscpu64 xscpu64 | sudo tee /usr/share/applications/vice-xscpu64.desktop
    printf '[Desktop Entry]\nCategories=Emulator;\nIcon=/opt/vice/src/arch/unix/skyos/icons/%s.ico\nExec=/opt/vice/src/%s\nType=Application\nName=Commodore VIC-20\n' xvic xvic | sudo tee /usr/share/applications/vice-xvic.desktop

Raspberry Pi – VisualVM

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Installazione mediante APT:

  1. sudo apt-get install visualvm

Installazione manuale (per ottenere una versione specifica o quella più recente):

  1. Scaricare il programma dal sito visualvm.github.io > Download > Binaries:
    1. cd /opt
    2. sudo wget https://github.com/visualvm/visualvm.src/releases/download/1.4.1/visualvm_141.zip
  2. sudo unzip visualvm_141.zip
  3. sudo ln -nsf visualvm_141 visualvm
  4. sudo rm visualvm_141.zip
  5. sudo chown -R pi:pi visualvm/
  6. Creare la variabile d’ambiente VISUALVM_HOME (facoltativo):
    echo 'VISUALVM_HOME="/opt/visualvm"' | sudo tee -a /etc/environment
  7. Creare un collegamento nel menù delle applicazioni:
    printf '[Desktop Entry]\nCategories=Application;System;\nExec=/opt/visualvm/bin/visualvm -J-Xmx96m\nType=Application\nIcon=/opt/visualvm/etc/visualvm.icns\nName=VisualVM\n' | sudo tee /usr/share/applications/visualvm.desktop

Raspberry Pi – WildFly

WildFly screenshot

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.

Prima di iniziare, accertarsi di disporre di una versione di Java compatibile con la versione di WildFly che si intende installare.

  1. Scaricare una release dal sito wildfly.org > Downloads:
    1. cd /opt
    2. sudo wget http://download.jboss.org/wildfly/14.0.1.Final/wildfly-14.0.1.Final.tar.gz
  2. Espandere l’archivio in /opt/:
    1. sudo tar xzvf wildfly-14.0.1.Final.tar.gz
    2. sudo ln -nsf wildfly-14.0.1.Final wildfly
    3. sudo rm wildfly-14.0.1.Final.tar.gz
  3. Creare l’utente Linux wildfly:
    1. sudo adduser --disabled-login --disabled-password --gecos "" --home /var/lib/wildfly wildfly
    2. sudo chown -R wildfly:wildfly wildfly/
  4. Creare gli utenti WildFly management (a) e application (b): sudo /opt/wildfly/bin/add-user.sh
  5. Per limitare l’uso di RAM (raccomandato), modificare il file /opt/wildfly/bin/standalone.conf variando i valori della riga JAVA_OPTS che contiene le opzioni -Xms e -Xmx:
    1. sudo nano /opt/wildfly/bin/standalone.conf
    2. JAVA_OPTS="-Xms16m -Xmx192m -XX:MaxMetaspaceSize=128m -Djava.net.preferIPv4Stack=true"
  6. Definire variabili di ambiente (raccomandato):
    1. echo 'WILDFLY_HOME="/opt/wildfly"' | sudo tee -a /etc/environment
    2. echo 'JBOSS_HOME="/opt/wildfly"' | sudo tee -a /etc/environment
  7. Per avviare il server manualmente: sudo su wildfly -c "/opt/wildfly/bin/standalone.sh"
    • Per consentire l’accesso da indirizzi diversi da localhost (facoltativo), eseguire in alternativa: sudo su wildfly -c "/opt/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0"
    • In caso di errore “Server VM is only supported on ARMv7+ VFP”, modificare il file /opt/wildfly/bin/standalone.conf aggiungendo alla riga JAVA_OPTS l’opzione -client prima di -Xms
  8. Per arrestare il server manualmente: sudo su wildfly -c "/opt/wildfly/bin/jboss-cli.sh --connect command=:shutdown"
    • In caso di timeout (WFLYPRT0023), aggiungere le seguenti righe nell’elemento <jboss-cli> del file jboss-cli.xml: sudo nano /opt/wildfly/bin/jboss-cli.xml
      <command-timeout>90</command-timeout>
      <connection-timeout>90000</connection-timeout>
  9. Configurare WildFly come servizio (consigliato):
    1. sudo wget https://raw.githubusercontent.com/wildfly/wildfly-core/master/core-feature-pack/src/main/resources/content/docs/contrib/scripts/init.d/wildfly-init-debian.sh -O /etc/init.d/wildfly
    2. sudo chmod 755 /etc/init.d/wildfly
    3. sudo mkdir -p /etc/default
    4. sudo wget https://raw.githubusercontent.com/wildfly/wildfly-core/master/core-feature-pack/src/main/resources/content/docs/contrib/scripts/init.d/wildfly.conf -O /etc/default/wildfly
    5. Per consentire l’accesso da indirizzi diversi da localhost (facoltativo):
      echo 'JBOSS_OPTS="-b 0.0.0.0 -bmanagement 0.0.0.0"' | sudo tee -a /etc/default/wildfly
    6. sudo update-rc.d wildfly defaults
    7. sudo systemctl daemon-reload (solo Raspbian Jessie e versioni successive)
  10. Il servizio viene preconfigurato per l’avvio automatico; per disabilitare o abilitare l’avvio automatico del servizio (facoltativo):
    • systemd (Raspbian Jessie e versioni successive)
      1. sudo systemctl disable wildfly
      2. sudo systemctl enable wildfly
    • SysV (Raspbian Wheezy)
      1. sudo update-rc.d wildfly disable
      2. sudo update-rc.d wildfly enable

Raspberry Pi – Connessione Desktop remoto (XRDP)

L’autore declina ogni responsabilità per eventuali danni di qualsiasi genere derivanti direttamente o indirettamente dall’uso delle informazioni contenute in quest’articolo.
  1. sudo apt-get install xrdp
  2. Non occorre riavvio. Il servizio viene configurato per l’avvio automatico. Per disabilitare (sconsigliato) o riabilitare l’avvio automatico eseguire uno dei due comandi seguenti:
    1. sudo systemctl disable xrdp xrdp-sesman
    2. sudo systemctl enable xrdp-sesman xrdp
  3. Personalizzare le sessioni predefinite (facoltativo):
    1. sudo nano /etc/xrdp/xrdp.ini
    2. Modificare le impostazioni presenti sotto il commento ; Session types, ad esempio, per preimpostare i parametri di una connessione VNC:
      [vnc-any]
      name=vnc-any
      lib=libvnc.so
      ip=asklocalhost
      port=ask5900
      username=na
      password=ask
    3. sudo service xrdp restart

Per connettersi da Microsoft Windows:

  1. Aprire l’applicazione Connessione Desktop remoto.
  2. Nel campo Computer inserire l’indirizzo IP del Raspberry Pi (es. 192.168.1.2) e fare clic su Connetti.
  3. Impostare i parametri a seconda del tipo di sessione desiderata:
    1. Se non si desidera accedere alla sessione attiva, selezionare Xorg e inserire le credenziali di accesso. Le credenziali Xorg possono essere anche inserite a monte (Mostra opzioni/Show options > Consenti salvataggio credenziali/Allow me to save credentials).
    2. Se si desidera accedere alla sessione attiva, selezionare vnc-any, ip localhost, port 5900 e la password impostata per l’accesso VNC. Per questo tipo di accesso occorre che sia attivo un server VNC opportunamente configurato per l’autenticazione VncAuth con password dedicata.

Nota: XRDP e VNC possono coesistere e anche operare congiuntamente; XRDP ha il vantaggio di non richiedere software aggiuntivo su client Windows.