How to configure metaspace with SBT - sbt

I'm trying to configure metaspace for SBT
export SBT_OPTS="-XX:+CMSClassUnloadingEnabled -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=256M -Xms2G -Xmx2G"
but when I run sbt -v, I have the following output :
[process_args] java_version = '1.8.0_11'
# Executing command line:
java
-XX:+CMSClassUnloadingEnabled
-XX:MaxMetaspaceSize=512M
-XX:MetaspaceSize=256M
-Xms2G
-Xmx2G
-Xms1024m
-Xmx1024m
-XX:ReservedCodeCacheSize=128m
-XX:MaxMetaspaceSize=256m
-jar
/usr/local/Cellar/sbt/0.13.7/libexec/sbt-launch.jar
The problem seems that my custom value for MaxMetaspaceSize is overrided with another value, as shown in output above.
SBT version : 0.13.7
Java version : 1.8
OS : OSX

(copy-pasted from a dear coworker who found the solution)
sbt -mem 2048
=>
-Xms2048m
-Xmx2048m
-XX:ReservedCodeCacheSize=256m
-XX:MaxMetaspaceSize=512m
the default metaspace is based on the xmx value specified with the "-mem" option ;-)

When using sbt 0.13.6 or higher you can create a .sbtopts file in your project root with:
-J-XX:MaxMetaspaceSize=512M

It seems that memory options are only correctly handled when they are specified in JAVA_OPTS
setting export JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=256M -Xms2G -Xmx2G"
gives
sbt -v
[process_args] java_version = '1.8.0_40'
# Executing command line:
java
-XX:+CMSClassUnloadingEnabled
-XX:MaxMetaspaceSize=512M
-XX:MetaspaceSize=256M
-Xms2G
-Xmx2G
-jar
/usr/local/Cellar/sbt/0.13.8/libexec/sbt-launch.jar
[info] Loading global plugins from /Users/ant/.sbt/0.13/plugins
[info] Set current project to ant (in build file:/Users/ant/)
>
Not sure if it's a bug or a feature

export SBT_OPTS="-XX:MaxMetaspaceSize=512m -Xms1024m -Xmx1024m"
works for me in sbt 0.13.11:
sbt -v
[process_args] java_version = '1.8.0_91'
# Executing command line:
java
-XX:MaxMetaspaceSize=512m
-Xms1024m
-Xmx1024m
-jar

Related

java.lang.UnsatisfiedLinkError: Invalid URL for class: jar:rsrc:javafx.graphics.jar!/com/sun/glass/utils/NativeLibLoader.class

I'm trying to run an application using the command prompt. It's built in Eclipse, using JavaFx. It's a digital diary program that I've been writing for a while and would like to send it to some friends. It is exported with packaged libraries as a runnable jar file.
I'm using the line
java -jar -Djavafx.verbose=true main.jar --module-path /users/home/javafx-sdk-11.0.2/lib --add-modules javafx.controls,javafx.fxml
to run it.
I've traced the errors (through use of -Djavafx.verbose=true) to java.lang.UnsatisfiedLinkError.
One of them is as follows:
WARNING: java.lang.UnsatisfiedLinkError: Invalid URL for class: jar:rsrc:javafx.graphics.jar!/com/sun/glass/utils/NativeLibLoader.class
What's causing this error?
EDIT after moving the --add-modules before main.jar, I get some new errors.
Exception in thread "main" java.lang.ExceptionInInitializerError
...
Caused by: java.lang.IllegalStateException: This operation is permitted on the event thread only; currentThread = main
...
When specifying arguments for the java virtual machine being run with a -jar command, these arguments need to go before the jar file name in the command line.
Do not use this
It will treat the module arguments as program arguments rather than VM arguments:
java -jar -Djavafx.verbose=true main.jar --module-path /users/home/javafx-sdk-11.0.2/lib --add-modules javafx.controls,javafx.fxml
Instead, use this
java --module-path /users/home/javafx-sdk-11.0.2/lib --add-modules javafx.controls,javafx.fxml -Djavafx.verbose=true -jar main.jar

HelloFX.java:1: error: package javafx.application.Application does not exist

OS: Raspbian
CPU: RPi (armv7l)
JDK: Zulu11.31+16 (build 11.0.3+7)
JavaFX: self-built https://github.com/openjdk/jfx/archive/jdk-11+7.tar.gz
Problem:
$ export PATH_TO_FX=/usr/lib/jvm/javafx-sdk-armv6hf-11-0-7-b1/lib
$ ls $PATH_TO_FX
javafx.base.jar
javafx.controls.jar
javafx.fxml.jar
javafx.graphics.jar
javafx.media.jar
javafx-swt.jar
javafx.web.jar
<bunch of lib*.so>
$ jar -t --file $PATH_TO_FX/javafx.graphics.jar | grep Application
javafx.graphics/javafx/application/Application.class
$ export MODULES=javafx.controls,javafx.graphics
$ wget https://raw.githubusercontent.com/openjfx/samples/master/HelloFX/CLI/hellofx HelloFX.java
$ javac --module-path $PATH_TO_FX --add-modules $MODULES HelloFX.java
HelloFX.java:1: error: package javafx.application.Application does not exist
import javafx.application.Application
I've checked and double-checked $PATH_TO_FX, and $MODULES, they are seem to be correct. If i run javac with -verbose, than I see jdk modules loaded, but jfx are not.
Update, 2020.12.19:
Turned out the problem was my build of JavaFX SDK. For whatever reason Gradle
generated module jars with module name as the root folder. Once I stripped
module names and repacked jars SDK works fine. Looking into Gradle issue now.

How do you run jlink to create a runtime for your JavaFX application?

Backstory:
I'm trying to distribute my openJDK11,openJFX application to my friend.
I'm using this tutorial:
https://medium.com/azulsystems/using-jlink-to-build-java-runtimes-for-non-modular-applications-9568c5e70ef4
You can see here that javafx is listed in my dependencies:
You can see here that my module-info is set up as might be required to run the application:
module FractalFriend_m {
requires javafx.base;
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
opens com.potatospy;
}
You can see here that my VM Options are entered correctly:
--module-path=C:\Users\USERNAME\Documents\javafx-sdk-11.0.2\lib --add-modules=javafx.controls,javafx.fxml,javafx.base,javafx.graphics
Running:
jdeps --module-path C:\Users\USERNAME\Documents\javafx-sdk-11.0.2\lib --list-deps FractalFriend_m.jar
Results in:
java.base
javafx.base
javafx.controls
javafx.fxml
javafx.graphics
And finally, I run jlink to hopefully produce something anyone can run:
jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules javafx.controls,javafx.fxml,javafx.base,javafx.graphics --output java-runtime
Which results in:
Error: Module javafx.base not found
JavaFX should be downloaded separately and on calling jlink it should be specified with the -p (--module-path) argument.
jlink --no-header-files --no-man-pages --compress=2 --strip-debug -p <path_java_fx_sdk_lib> --add-modules javafx.controls,javafx.fxml,javafx.base,javafx.graphics --output java-runtime

sbt-proguard issue with Java 1.8

I'm trying to get smaller scalar executable jar file with sbt-proguard.
I added project/plugin.sbt these two lines of code:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.13.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-proguard" % "0.2.2")
The first one is to get uberjar file, and I could get uberjar with sbt assembly that works fine.
Then, I executed sbt proguard:proguard to get this error message.
[error] Error: Can't read [/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home/jre/lib/rt.jar] (Can't process class [apple/applescript/AppleScriptEngine.class] (Unsupported class version number [52.0] (maximum 51.0, Java 1.7)))
java.lang.RuntimeException: Proguard failed with exit code [1]
at scala.sys.package$.error(package.scala:27)
...
at java.lang.Thread.run(Thread.java:745)
[error] (proguard:proguard) Proguard failed with exit code [1]
From the hint from this post: ProGuard says Unsupported class version number [52.0] (maximum 51.0, Java 1.7) with sbt-proguard,
I switched to both Java 1.7 and Java 1.6 with export JAVA_HOME=/usr/libexec/java_home -v '1.6*' command to run proguard to get the slim-lined jar file, but this doesn't run.
Invalid or corrupt jarfile target/scala-2.11/proguard/myproject_2.11-1.0.jar
What might be wrong? These are the lines that are added to build.sbt.
proguardSettings
ProguardKeys.options in Proguard ++= Seq("-dontnote", "-dontwarn", "-ignorewarnings")
ProguardKeys.options in Proguard += ProguardOptions.keepMain("core.HelloWorld")
I believe this is documented in the pro guard docs.
Running your application with java -classpath <jarpath> --class classname <program-arguments> should work.
This happens because pro guard by default removes all MANIFEST files from the jar hence the java runtime cannot find the jar class entries. Another way to do this would be to keep the MANIFEST.md file and run it using the java -jar option but I have never tried that.
Define a recent Proguard version that supports Java 1.8
ProguardKeys.proguardVersion in Proguard := "5.3.3"
Also a couple of useful ones if you run out of mem are
javaOptions in (Proguard, ProguardKeys.proguard) := Seq("-Xmx2G")
javaOptions in (Proguard, ProguardKeys.proguard) += "-Xss1G"

error javac: invalid flag: -J-Xmx1028m in sbt

I have OutOfMemoryError when I compile my project using sbt. So I need to enlarge the java compiler heap space. I use java 6. And I have set JAVA_HOME to java 6 in my bash env.
I tried to add this line to build.sbt
javacOptions ++= Seq(<other arguments>,"-J-Xmx1028m")
When I compile, I have error like this:
[error] javac: invalid flag: -J-Xmx1028m
[error] Usage: javac <options> <source files>
[error] use -help for a list of possible options
The funny thing is: this error disappears when I specify the javaHome in build.sbt, which I have already done it in my bash env:
javaHome := Some(file("path to java 6"))
Does it mean that I have to specify JAVA_HOME twice? once in bash env, once in build.sbt? I don't want to specify a absolute path in build.sbt, which makes it may not work properly on other computers.

Resources