JavaFX 11 for JME

There’s an open issue for the illegal reflection warnings:
Illegal reflective access in com.jme3.util.ReflectionAllocator · Issue #1085 · jMonkeyEngine/jmonkeyengine · GitHub

This one isn’t reflection or a warning, it’s a module access error, kills the whole app from starting:

(Full text is the error I posted.)

Jme-jfx breaks “the rules” by making a reference to PlatformImpl which is inside com.sun.javafx.application.

From jme-jfx-11 this is where it references the com.sun class at line 648:

private void initFx() {
        PlatformImpl.startup(() -> {

Or were you hinting that I should help fix the JDK 9+ build starting with that? :slight_smile:

No, I was confused. Sorry!

Happens to me more often then I care to admit. lol

Okay, getting to the bottom of this. Examined debug logs from the Gradle run task. Looks like it’s the org.openjfx.javafxplugin Gradle plugin that I have in my sample build file which is adding module configuration… which is what it’s supposed to do.

Apparently this lets NetBeans/Gradle successfully build with JFX packages, and the Sun module access violation is just a run time check. (Why couldn’t that be a compile time check? Whatever…)

The difference is when it’s broken, it’s doing this (look at all the crap it adds for us!):

/home/lou/.sdkman/candidates/java/11.0.2-open/bin/java 
--add-modules javafx.controls,javafx.fxml 
--module-path /home/lou/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-fxml/11.0.2/1b8a331d5f393b48de0aef59b3c967a312967290/javafx-fxml-11.0.2-linux.jar:
/home/lou/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/11.0.2/5f6929050a744aab39ebfc1e8e5dd03bcd2ad47b/javafx-controls-11.0.2-linux.jar:
/home/lou/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/11.0.2/ef4c34f0ca77cd99100b76c2ccf1dce383572bb1/javafx-graphics-11.0.2-linux.jar:
/home/lou/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/11.0.2/8db178adb1085d455e5ef643a48c34959c8771c1/javafx-base-11.0.2-linux.jar -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant 

When it’s working, it’s doing this (which I’m sure is closer to what NB and IntelliJ are doing when we “run” the file):

 /home/lou/.sdkman/candidates/java/11.0.2-open/bin/java 
-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant 

A small :rofl: to add: the –add-exports line I had in the run task change above isn’t even needed. All I needed to do to get the run task working is blow away the JVM args with this:

run {
    doFirst {
        jvmArgs = [
            
        ]
    }
}

So I guess I’ll catch up with overdue reading on Java 9 modularity soon, and maybe figure out a more correct solution.

But pasting that jvmArgs mod into your build.gradle (if you’re using the org.openjfx plugin) seems to resolve the run problem with this trivial demo, for anyone encountering this issue. If you’re using Maven or Ant, your project should be immune I think, which I’m… guessing is one reason others hadn’t noticed it. I’m using NB11’s new Gradle integration.

I am testing your library currently in my game.
I have a JavaFX GUI attached, which plays a video in the background. (MediaView & .mp4)
It was working very smooth with default JavaFX
But now its kinda laggy, any idea how it could improve? I tried:

  • v-sync on/off
  • fixing framerate

It is smoothest when not limiting fps at all. But there are still some hiccups here and there, especially when moving the mouse fast over the JavaFX components e.g. Buttons etc.

I have a hunch that limiting your fps to a derivative of 60 (or even 30) will yield smoother results. 60, 120, 180, etc. I believe jfx runs at 60 fps so when it’s out of sync the movements will be too.

Another thing to remember is not to do work on the javafx thread. Only update the controls on the javafx thread.

There are also jfx best practices such as caching and cachehints to speed. Those are javafx specific and not the implementation itself.

Note that if your game is slow, javafx will be, too. The scene is rendered once per JME loop, so if JME is running at 42 fps, the jfx scene will update at that speed, too.

I’m not on my pc right now but the docs show you can remove the frame limit.

-Djavafx.animation.fullspeed=true

I will try that out, thanks alot :blush:
loving it so far btw!

If you want I can reply to you here if I found sth. that works for me.

1 Like

I think we’d all be interested in what works out!

I think I got it to work properly.

I just fired up MSI Afterburner/RiverStaticsTuner to watch frametimes, and cpu/gpu frequency.

when turning on v-sync or limiting the framerate, my frametimes jumped around quite a bit, due to my clocks changing as well, when fixing CPU & GPU frequency and turning on vsync its very smooth now.

So was more a hardware problem than anything else…

3 Likes

Thanks for the feedback :slight_smile:

1 Like

@NoPoison While it’s good that you found a solution for you own hardware, if I understand you correctly, it doesn’t seem like that’s going to be a good option for your users. :frowning: Anyway, if you want help testing and you’re able to put a small demo on GitHub, I could help with that. (I am on Linux, though.)

@jayfella Btw you have a PR for a readme update, if you intend to keep that in sync. Older version number there tripped me up for a bit with the breaking changes, until I noticed it’s now 1.0 on this post.

2 Likes

Yeah I noticed. I’ll update it as soon as my kids let me back on my pc. It’s the holidays over here.

1 Like

“kids let me back on my pc” :rofl: Sorry

1 Like

Yeah its kinda not was a was hoping for, but not sure if that is fixable.
It would probably help to detach the JavaFX thread from the jme one and let it sit at constant 60 frames, but I don’t think that’s worth the effort.

I could do that, but again I don’t know if there is much to debug for us :sweat:

JavaFx does run on its own thread. The only “tie” to the JME loop is where it asks if enough time has passed to warrant a redraw. But obviously if your game is running at less than 60fps - it can only update the painted javafx texture at that speed. In the background - unless the CPU was completely consumed - it would still be running at 60fps - which can be confirmed by noticing that it “skips” animations instead of slowly drawing each frame.

https://github.com/jayfella/jme-jfx-11/blob/master/src/main/java/com/jayfella/jme/jfx/JavaFxUI.java#L336

I’m not sure why your card keeps cycling up and down. Maybe if jmonkey was actually doing something instead of just displaying a javafx video it would stay at its full cycle? Just a presumption off the top of my head.

2 Likes

Thanks for the clarification! :slight_smile: haven’t looked in the code yet.
I tested it already with just a MediaView and nothing else. And the same thing happens there.
CPU is sitting at 3%.
It could really just be a hardware “issue”… CPU boost isn’t up to the task, idk.
But again it’s manageable if I set the CPU-governor to performance.

If it’s a hardware issue, others could have the same problem (and not know how to fix it, assuming they were even willing to do so), that’s the concern.

So it’s up to you whether you’re able/up for providing a small example to reproduce. But it would increase the chances of someone finding a solution (assuming there’s a reasonable fix possible, and it reproduces on other than your own machine).

We’re definitely in uncharted territory here. But JME + JFX is just too cool to ignore.

Maybe if jmonkey was actually doing something instead of just displaying a javafx video it would stay at its full cycle?

I will try that!

@louhy
I don’t have an account on github, I use the git in our university…
Also not sure how to paste code in here, sorry :confused:

Its as simple as this:

import com.jayfella.jme.jfx.JavaFxUI;
import com.jme3.app.SimpleApplication;
import com.jme3.system.AppSettings;
import evoke.client.config.Config;
import evoke.client.config.ConfigLoader;
import javafx.scene.CacheHint;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;

public class Test extends SimpleApplication {
MediaPlayer videoPlayer;
MediaView mediaView;

@Override
public void simpleInitApp() {
JavaFxUI.initialize(this);

MediaPlayer videoPlayer = new MediaPlayer(new Media(getClass().getResource(“/Pack/test.mp4”).toString()));
videoPlayer.setMute(true);
videoPlayer.setCycleCount(MediaPlayer.INDEFINITE);
videoPlayer.play();
mediaView = new MediaView(videoPlayer);
mediaView.setFitWidth(1920);
mediaView.setFitHeight(1080);
mediaView.setCache(true);
mediaView.setCacheHint(CacheHint.SPEED);
mediaView.setSmooth(true);

JavaFxUI.getInstance().attachChild(mediaView);
inputManager.setCursorVisible(true);
flyCam.setEnabled(false);

}

public static void main(String… args) {
Test main = new Test();
AppSettings settings = new AppSettings(true);
settings.setHeight(1080);
settings.setWidth(1920);
settings.setFrameRate(60);
settings.setVSync(true);
settings.setTitle(“Test!”);
main.setShowSettings(false);
main.setSettings(settings);
main.start();
}
}

1 Like