Any way to programmatically determine which Java language features are available on current platform?

This will give you the version of java that the system is running.

 System.getProperty("java.version")

If you're running Java 9 and greater you can use:

Runtime.Version version = Runtime.version();

Java Docs

Just a note the Java versioning naming standard changed at Java 9 as well.

Java Version: 1.7, 1.8, 9, 10, 11

I don't have a solution for you to check for specific features.


A feature could be: JDK 10

  1. Method : Optional.orElseThrow()
  2. API : API for Creating Unmodifiable Collections
  3. System Property : Fore example, to Disable JRE Last Usage Tracking
  4. GC enhancement (Full parallel)
  5. Javadoc Support : (For Multiple Stylesheets)

It Could also be a REMOVAL of feature : also in Java 10

  1. Removal of Support for Using Old LookAndFeel
  2. Removal of Runtime.getLocalizedInputStream and getLocalizedOutputStream Methods
  3. And so on..

So it is hard to check or discover programmatcally if a new feature exist or of it has been removed UNLESS you know what you are looking for, it needs to to be provided by Oracle itself as a documentation, feature name and description.

If we are going to create and API for that, we must get the list first from Oracle docs, and then do required checks for each feature to discover the current version or if it is supported.

Following is an example to programmaticaly check the compiler for a specific functionality.

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Arrays;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject.Kind;

public class CompileSourceInMemory {
  public static void main(String args[]) throws IOException {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

    StringWriter writer = new StringWriter();
    PrintWriter out = new PrintWriter(writer);
    out.println("public class HelloWorld {");
    out.println("  public static void main(String args[]) {");
    out.println("    System.out.println(\"This is in another java file\");");    
    out.println("  }");
    out.println("}");
    out.close();
    JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());

    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);
    CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

    boolean success = task.call();
    for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
      System.out.println(diagnostic.getCode());
      System.out.println(diagnostic.getKind());
      System.out.println(diagnostic.getPosition());
      System.out.println(diagnostic.getStartPosition());
      System.out.println(diagnostic.getEndPosition());
      System.out.println(diagnostic.getSource());
      System.out.println(diagnostic.getMessage(null));

    }
    System.out.println("Success: " + success);

    if (success) {
      try {
        Class.forName("HelloWorld").getDeclaredMethod("main", new Class[] { String[].class })
            .invoke(null, new Object[] { null });
      } catch (ClassNotFoundException e) {
        System.err.println("Class not found: " + e);
      } catch (NoSuchMethodException e) {
        System.err.println("No such method: " + e);
      } catch (IllegalAccessException e) {
        System.err.println("Illegal access: " + e);
      } catch (InvocationTargetException e) {
        System.err.println("Invocation target: " + e);
      }
    }
  }
}

class JavaSourceFromString extends SimpleJavaFileObject {
  final String code;

  JavaSourceFromString(String name, String code) {
    super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
    this.code = code;
  }

  @Override
  public CharSequence getCharContent(boolean ignoreEncodingErrors) {
    return code;
  }
}

See JDK 10 features

Tags:

Java