B4J Question B4J (undocumented API 'MeasureMultilineTextHeight') crashes on linux

matt humphreys

Member
Licensed User
Longtime User
using the following code works fine on windows platform however my issue is running it on linux.
specifically debian with openjdk 11 and jfx 11

Sub MeasureMultilineTextHeight (Font As Font, Width As Double, Text As String) As Double
Dim jo As JavaObject = Me
Return jo.RunMethod("MeasureMultilineTextHeight", Array(Font, Text, Width))
End Sub

#if Java
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javafx.scene.text.Font;
import javafx.scene.text.TextBoundsType;
public static double MeasureMultilineTextHeight(Font f, String text, double width) throws Exception {
Method m = Class.forName("com.sun.javafx.scene.control.skin.Utils").getDeclaredMethod("computeTextHeight",
Font.class, String.class, double.class, TextBoundsType.class);
m.setAccessible(true);
return (Double)m.invoke(null, f, text, width, TextBoundsType.LOGICAL_VERTICAL_CENTER);
}
#End If
It throws below exception.
The sub exists in the 'Main' module of my B4J code and so I'm not sure what the 'unamed module' actually refers to.
Appreciate any steerage...

main.MeasureMultilineTextHeight (java line: 4512)
java.lang.reflect.InaccessibleObjectException: Unable to make public static double com.sun.javafx.scene.control.skin.Utils.computeTextHeight(javafx.scene.text.Font,java.lang.String,double,javafx.scene.text.TextBoundsType) accessible: module javafx.controls does not "exports com.sun.javafx.scene.control.skin" to unnamed module @1cf25c8b
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at b4j.siborg.joblog.STD.main.MeasureMultilineTextHeight(main.java:4512)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:132)
at b4j.siborg.joblog.STD.main._measuremultilinetextheight(main.java:2414)
at b4j.siborg.joblog.STD.main._buildlabel2(main.java:675)
at b4j.siborg.joblog.STD.main$ResumableSub_PopulateList.resume(main.java:3467)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:136)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:85)
at anywheresoftware.b4a.keywords.Common.CallSub4(Common.java:487)
at anywheresoftware.b4a.keywords.Common.access$0(Common.java:467)
at anywheresoftware.b4a.keywords.Common$CallSubDelayedHelper.run(Common.java:541)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
at java.base/java.lang.Thread.run(Thread.java:831)
 

agraham

Expert
Licensed User
Longtime User
Reflection has found the method but it is failing at m.setAccessible(true); because
com.sun.javafx.scene.control.skin.Utils.computeTextHeight(...)
in the javafx.controls module is not accessible.

Here's a stackoverflow thread about a similar problem.
reflection - How to solve InaccessibleObjectException ("Unable to make {member} accessible: module {A} does not 'opens {package}' to {B}") on Java 9? - Stack Overflow
I don't know eough about the export system of Java 9 and later but Java 8, if you have it available, might work.
 
Upvote 0

matt humphreys

Member
Licensed User
Longtime User
such a lot to learn...thanks.
No question just a comment at this point...
with those additions it compiles on windows platform but does not run on windows platform
Error occurred during initialization of boot layer
java.lang.RuntimeException: Unable to parse --add-opens <module>=<value>: javafx.controls/
unless I remove the space after forward slash
...controls/com...
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Try taking the space out between "controls/ com." -> "controls/com."

Oops, just saw you spotted that. - pls ignore.
 
Upvote 0
Top