AdoptOpenJDK / jitwatch

Log analyser / visualiser for Java HotSpot JIT compiler. Inspect inlining decisions, hot methods, bytecode, and assembly. View results in the JavaFX user interface.
Other
3.08k stars 438 forks source link

Support for Java 11 #308

Closed garyttierney closed 5 years ago

garyttierney commented 5 years ago

Currently the JitWatch UI doesn't compile under Java 11 (actually, since 9+, but those releases are EOL) because JavaFX is no longer shipped with the JRE or provided as an extension/"layer" over the JRE.

EDIT: inspecting the POM a little closer for the Maven builds, it should be as simple as updating from the early access OpenJFX builds to get that working again.

The solution to this seems to be adding a dependency on the newly published OpenJFX binaries that are available on Maven Central. Since these aren't available pre-11, you need to come up with another dependency resolution strategy based on the version of Java you're using. I have a local patch that does this at the moment.

build.gradle

plugins {
    id 'java'
    id 'application'    // similar to mvn exec:java
    id 'maven-publish'
    id 'org.beryx.jlink' version '2.12.0' apply(false)
    id 'org.openjfx.javafxplugin' version '0.0.8' apply(false)
}

def javaVersion = JavaVersion.current()

if (javaVersion == JavaVersion.VERSION_1_8) {
    apply from: "build-jdk8.gradle"
} else if (javaVersion >= JavaVersion.VERSION_11) {
    apply from: "build-jdk11.gradle"
}

dependencies {
    compile project(':core')

    compile 'org.slf4j:slf4j-api:1.7.12', 'ch.qos.logback:logback-classic:1.2.3', 'ch.qos.logback:logback-core:1.2.3'
    testCompile 'junit:junit:4.12'
}

mainClassName = 'org.adoptopenjdk.jitwatch.ui.launch.LaunchUI'

build-jdk8.gradle

def jfxrt = new File("${System.properties['java.home']}/jre/lib/ext/jfxrt.jar").absolutePath

dependencies {
    system(jfxrt)
}

run {
    doFirst {
        classpath += configurations.system
    }
}

build-jdk11.gradle

apply plugin: "org.openjfx.javafxplugin"
apply plugin: "org.beryx.jlink"

def javaVersion = JavaVersion.current()
def openjfxVersion

if (javaVersion == JavaVersion.VERSION_11) {
    openjfxVersion = "11.0.2"
} else if (javaVersion >= JavaVersion.VERSION_12) {
    openjfxVersion = "12.0.1"
} else {
    throw GradleException("Building JITWatch is unsupported on this version of java")
}

javafx {
    version = openjfxVersion
    modules = [ 'javafx.controls', 'javafx.web' ]
}

sourceSets {
    main {
        java {
            srcDir 'src/main/java11'
        }
    }
}

compileJava {
    inputs.property("moduleName", "jitwatch.ui")
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
        ]
        classpath = files()
    }
}

dependencies {
    // Referenced in logback.classic module-descriptor, put on compile path
    // to make jlink happy.
    compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'

    runtimeOnly "org.openjfx:javafx-controls:$javafx.version:linux"
    runtimeOnly "org.openjfx:javafx-web:$javafx.version:linux"
}

jlink {
    addOptions '--bind-services', '--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages', '--vm=server'

    launcher {
        name = 'jitwatch'
        jvmArgs = [
                '--add-opens', 'jdk.jdeps/com.sun.tools.javap=jitwatch.core'
        ]
    }
}

This works quite well (though you may note there are some additional changes in there, like building a runtime image with jlink; I've written module-info files for both modules and only compile them when under Java 11 onwards, you can drop most of build-jdk11.gradle if you don't want modularity).

I can put together a pull request with some or all of these changes, but there are some remaining questions:

Some additional notes:

Using jlink means you can ship a JitWatch bundle that comes with a pre-compiled hsdis plugin, making it effectively one click to download and test out the sandbox.

chriswhocodes commented 5 years ago

Hi @garyttierney ,

First of all, thank you for taking the time to report these issues, it's much appreciated. I've already updated the maven builds to use the mavenised OpenJFX builds and these seem to work on the recent JDKs but I'm not a gradle user so I rely on the community contributions for JITWatch's gradle support.

I'd happily to accept a PR to fix gradle support for recent JDKs.

It's probably time to drop Ant support and it may also be time to drop Java 7 support. With the new Java release cadence and performance improvements I can't imagine many performance-sensitive projects that would care to use JITWatch are stuck at 7.

This would also allow me to start refactoring parts of JITWatch with Java 8+ language features.

A fat jar distribution would also lower the barrier for new users.

I'm wary of modularising JITWatch. For most people this is a desktop app, not a library, and I've always tried not to make changes that raise the barrier to making contributions due to fighting the build system (hence the lack of maven central releases - I've wasted far too much time battling that).

Cheers,

Chris

garyttierney commented 5 years ago

Hey @chriswhocodes,

Thanks for the quick reply!

I did try to build via Maven first, but JavaFX wasn't on the compile classpath for some reason. I tried out the Gradle build instead and have been working through fixing that up.

I'd happily to accept a PR to fix gradle support for recent JDKs.

I'll send a PR shortly. I'm just working on getting a Maven build working locally under JDK 11 at the moment.

It's probably time to drop Ant support and it may also be time to drop Java 7 support. With the new Java release cadence and performance improvements I can't imagine many performance-sensitive projects that would care to use JITWatch are stuck at 7.

I realized there was no real reason that my changes shouldn't support 7, so I've left the support in for now and will leave support in my (upcoming) PR.

A fat jar distribution would also lower the barrier for new users.

I've got this working on a local tree at the moment. The generated fat jar includes the native artifacts for the OpenJFX builds on Windows, Linux, and Mac, so I agree that'd lower the barrier for usage quite a bit since it "just works" on JDK 11 by running java -jar ui-shadow.jar

I'm wary of modularising JITWatch. For most people this is a desktop app, not a library, and I've always tried not to make changes that raise the barrier to making contributions due to fighting the build system (hence the lack of maven central releases - I've wasted far too much time battling that

I agree. In fact, JITWatch is the only modular JavaFX application I've been able to package successfully with jlink, since it's so lean on dependencies. It was a nice experiment :)