Detección programática: modo de vista previa en JRE

8

Desde Java 11, se puede habilitar un MODO DE VISTA PREVIA en Java Compiler y Runtime. Permite previsualizar nuevas funciones. ( JEP 12 )

java --enable-preview

¿Cómo puedo detectar desde Java si la JVM se ha iniciado con el modo de vista previa habilitado?

La intención es describir el contenedor en ejecución en una página de estado de la aplicación / json, para obtener una descripción general de devops.

Hasta ahora examiné las propiedades del sistema y los indicadores, ninguno contenía una pista.

alfonx
fuente
2
Intente ejecutar código explícitamente usando la función que necesita y maneje si la JVM se queja.
Thorbjørn Ravn Andersen
2
Solo me preguntaba, ¿por qué querrías hacerlo? Dado que dicho código está obligado a compilarse solo con el conjunto de indicadores o de lo contrario ni siquiera se compilaría, olvide la ejecución.
Naman
Quizás esta respuesta podría funcionar, ya sea directamente o quizás como un punto de partida. No he hecho esto yo mismo, pero parece ser similar a lo que estás preguntando.
kaan
2
@naman puede compilar la mayoría del código para java 11 y luego compilar el resto para lo que contenga la vista previa. Si ese código se carga dentro de un bloque de prueba, puede manejar la falla.
Thorbjørn Ravn Andersen
2
@kaan explícitamente solicita una función de punto de acceso que hace que el proveedor del código dependa.
Thorbjørn Ravn Andersen

Respuestas:

4

Puede consultar el archivo de clase Java minor_version. Si 0xFFFFel archivo de clase se compila con --enable-preview. Para más detalles, consulte https://stackoverflow.com/a/58821511/868941 .

A continuación se proporciona un programa simple para verificar esto (¡cuidado, código Java 13 con funciones de vista previa habilitadas!).

public final class ClassFileVersion {

    private final int major;
    private final int minor;

    private ClassFileVersion(int major, int minor) {
        this.major = major;
        this.minor = minor;
    }

    public static ClassFileVersion of(Class<?> classFile) throws IOException {
        try (InputStream is = classFile.getResourceAsStream("/%s.class".formatted(classFile.getName().replace('.', '/')))) {
            var buffer = new byte[8];
            if (is.read(buffer) != buffer.length) {
                throw new AssertionError("Not a Java Class File!");
            }
            return new ClassFileVersion(readUnsignedShort(buffer, 6), readUnsignedShort(buffer, 4));
        }
    }

    public String getVersionNumber() {
        return "%d.%d".formatted(major, minor);
    }

    public boolean isEnablePreview() {
        return major >= 55 && minor == 0xFFFF;
    }

    @Override
    public String toString() {
        return (major < 49 ? "JDK " : "Java SE ") +
            switch(major) {
                case 45 -> "1.1";
                case 46 -> "1.2";
                case 47 -> "1.3";
                case 48 -> "1.4";
                case 49 -> "5";
                case 50 -> "6";
                case 51 -> "7";
                case 52 -> "8";
                case 53 -> "9";
                case 54 -> "10";
                case 55 -> "11";
                case 56 -> "12";
                case 57 -> "13";
                case 58 -> "14";
                default -> throw wrongVersion();
            } +
            switch(minor) {
                case 0 -> "";
                case 3 -> {
                    if (major != 45) {
                        throw wrongVersion();
                    }
                    yield "";
                }
                case 0xFFFF -> " --enable-preview";
                default -> throw wrongVersion();
            };
    }

    private static int readUnsignedShort(byte[] buffer, int offset) {
        return ((buffer[offset] & 0xff) << 8) + (buffer[++offset] & 0xff);
    }

    private AssertionError wrongVersion() {
        return new AssertionError("Wrong Java Class File Version: %d.%d".formatted(major, minor));
    }
    // to run this code (JDK 13 needed):
    // java --enable-preview --source 13 ClassFileVersion.java 
    public static void main(String[] args) throws IOException {
        // prints "Java SE 13 --enable-preview"
        System.out.println(ClassFileVersion.of(ClassFileVersion.class));
    }

}
rmuller
fuente