En el artículo JDeps: Análisis de Dependencias, hablamos sobre JDeps, una nueva herramienta de línea de comandos que se introdujo en el JDK 8 para detectar el uso de las API’s internas del JDK en nuestros proyectos.

Actualmente, durante los desarrollos de nuevos proyectos java se usa alguna herramienta de construcción que nos ayude a controlar nuestros proyectos y dependencias como maven o gradle. Ambas trabajan con plugins las cuales proveen funcionalidad adicional a los proyectos java. En esta ocasión hablaremos de maven-jdeps-plugin.

Durante el JavaOne 2015, durante una de las sesiones en las que se habló del proyecto Jigsaw, que forma parte de Java 9, se mencionó que maven-jdeps-plugin había sido liberado. El propósito de este plugin es analizar el uso de las API’s internas del JDK durante el tiempo de construcción del proyecto tanto para las clases en las carpetas src/main/java como también src/test/java.

Para hacer uso del plugin, este se debe registrar en la sección plugins:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jdeps-plugin</artifactId>
	<version>3.0.0</version>
</plugin>

Las tareas de plugin son las siguientes:

  • jdkinternals, identifica el uso de API’s internas del JDK en las clases bajo src/main/java.

  • test-jdkinternals, identifica el uso de API’s internas del JDK en las clases bajo src/test/java.

Al ejecutarse estas tareas y de encontrarse uso de API’s internas del JDK el build fallará.

mvn jdeps:jdkinternals

ó

mvn jdeps:test-jdkinternals

En el siguiente ejemplo, agregaremos una clase que haga uso de las clases sun.misc.BASE64Decoder y sun.misc.BASE64Encoder, las cuales son parte del API interna del JDK.

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;

public class Base64Ejemplo {

    public static void main(String[] args) throws IOException {
        BASE64Encoder encoder = new BASE64Encoder();
        String encode = encoder.encode("eddu".getBytes());
        System.out.println(encode);

        BASE64Decoder decoder = new BASE64Decoder();
        byte[] bytes = decoder.decodeBuffer(encode);
        System.out.println(new String(bytes));
    }

}

El pom.xml queda configurado de la siguiente manera:

<?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>io.eddumelendez</groupId>
    <artifactId>jdeps-maven-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jdeps-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>jdkinternals</goal>
                            <goal>test-jdkinternals</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Como se puede ver estamos haciendo uso de las tareas jdkinternals y test-jdkinternals, las cuales estan siendo agregados al ciclo de vida del proyecto. De esta manera cuando ejecutamos mvn clean package las clases en src/main/java y src/test/java van a ser analizadas.

Ahora solo se tiene que ejecutar mvn clean package y ver que el build falla debido al uso de las API’s internas del JDK.

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-jdeps-plugin:3.0.0:jdkinternals (default) on project jdeps-maven-demo: Found offending packages:
[ERROR] sun.misc -> JDK internal API (rt.jar)
[ERROR] -> [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/MojoExecutionException

Para evitar este error en la construcción del proyecto, se deben reemplazar las clases sun.misc.BASE64Decoder y sun.misc.BASE64Encoder por java.util.Base64. Luego de estos cambios la clase luce de la siguiente manera:

import java.util.Base64;

public class Base64Ejemplo {

    public static void main(String[] args) {
        byte[] encode = Base64.getEncoder().encode("eddu".getBytes());
        System.out.println(new String(encode));

        byte[] bytes = Base64.getDecoder().decode(encode);
        System.out.println(new String(bytes));
    }

}

Eddú Meléndez

Java Software Engineer, Open Source Contributor