B4J Question How to use Java.exe from a B4JPackager11 packaged app

jmon

Well-Known Member
Licensed User
Hi,

I'm trying to use the Java.exe provided with an app packed using B4JPackager. So far I have failed (I've really really tried to make it work, but there's something I can't figure out).

The reason I want to do that is because I have "Plug-ins" jar that the user can add and use if needed using an app packaged with B4JPackager. I don't want the user to install JavaJDK.

Example:
- I give the user a plug-in called "exportToPDF.jar"
- The user copies it to "c:\Program Files\MyApp\Plug-ins\exportToPDF.jar"
- The main app recognises the plug-in and tries to execute the jar plugin.

I could make it work with Java 8, but can't with java 11.

Here is what I have tried so far (cleaned):
B4X:
Sub Button1_Click
    Dim B4JPackagedAppDir As String = "C:\Program Files\MyApp\"
    Dim TargetJarDir As String = $"c:\Program Files\MyApp\Plug-ins\"$
    Dim TargetJarFileName As String = $"exportToPDF.jar"$
    
    testExecute(B4JPackagedAppDir, TargetJarDir, TargetJarFileName)
End Sub

Sub testExecute(B4JPackagedAppDir As String, Dir As String, FileName As String)
    Dim javaDir As String = File.Combine(B4JPackagedAppDir, "bin")
    Dim javaExe As String = File.Combine(javaDir, "java.exe")
    
    Dim args As List
    args.Initialize
    args.Add("-cp")
    args.Add($"'${Dir}';'${File.Combine(Dir, FileName)}';'${File.Combine(javaDir, "/lib/*")}'"$)   
    args.Add("-m")
    args.Add("b4j/b4j.example.main")   

    Dim shl As Shell
    shl.Initialize("shl", javaExe, args)
    shl.WorkingDirectory = Dir
    shl.Run(-1)
End Sub

Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    Log($"Success: ${Success}"$)
    Log($"ExitCode: ${ExitCode}"$)
    Log($"StdOut: ${StdOut}"$)
    Log($"StdErr: ${StdErr}"$)
End Sub
But I always get this error:
Waiting for debugger to connect...
Program started.
Success: true
ExitCode: 1
StdOut:
StdErr: Error: Could not find or load main class b4j.example.main in module b4j
If I remove the module name "b4j/":
B4X:
Dim args As List
 args.Initialize
 args.Add("-cp")
 args.Add($"'${Dir}';'${File.Combine(Dir, FileName)}';'${File.Combine(javaDir, "/lib/*")}'"$)   
 args.Add("-m")
 args.Add("b4j.example.main")
I get this error:
Waiting for debugger to connect...
Program started.
Success: true
ExitCode: 1
StdOut: Error occurred during initialization of boot layer
java.lang.module.FindException: Module b4j.example.main not found
StdErr:
So I think the JavaFX modules are loaded properly, because if I add "-verbose" to the args, I can see that it loaded all the modules:
StdOut: [0.004s][info][class,load] opened: C:\Program Files\MyApp\lib\modules
[0.012s][info][class,load] java.lang.Object source: jrt:/java.base
[0.012s][info][class,load] java.io.Serializable source: jrt:/java.base
[0.012s][info][class,load] java.lang.Comparable source: jrt:/java.base
[0.012s][info][class,load] java.lang.CharSequence source: jrt:/java.base
[0.012s][info][class,load] java.lang.String source: jrt:/java.base
[0.012s][info][class,load] java.lang.reflect.AnnotatedElement source: jrt:/java.base
[0.013s][info][class,load] java.lang.reflect.GenericDeclaration source: jrt:/java.base
[0.013s][info][class,load] java.lang.reflect.Type source: jrt:/java.base
[0.013s][info][class,load] java.lang.Class source: jrt:/java.base
[0.013s][info][class,load] java.lang.Cloneable source: jrt:/java.base
[0.013s][info][class,load] java.lang.ClassLoader source: jrt:/java.base
[0.013s][info][class,load] java.lang.System source: jrt:/java.base
[0.013s][info][class,load] java.lang.Throwable source: jrt:/java.base
[0.013s][info][class,load] java.lang.Error source: jrt:/java.base
[0.014s][info][class,load] java.lang.ThreadDeath source: jrt:/java.base
[0.014s][info][class,load] java.lang.Exception source: jrt:/java.base
[0.014s][info][class,load] java.lang.RuntimeException source: jrt:/java.base
[0.014s][info][class,load] java.lang.SecurityManager source: jrt:/java.base
[0.014s][info][class,load] java.security.ProtectionDomain source: jrt:/java.base
[0.014s][info][class,load] java.security.AccessControlContext source: jrt:/java.base
[0.014s][info][class,load] java.security.SecureClassLoader source: jrt:/java.base
[0.014s][info][class,load] java.lang.ReflectiveOperationException source: jrt:/java.base
[0.014s][info][class,load] java.lang.ClassNotFoundException source: jrt:/java.base
[0.014s][info][class,load] java.lang.LinkageError source: jrt:/java.base
[0.014s][info][class,load] java.lang.NoClassDefFoundError source: jrt:/java.base
[0.014s][info][class,load] java.lang.ClassCastException source: jrt:/java.base
[0.014s][info][class,load] java.lang.ArrayStoreException source: jrt:/java.base
[0.014s][info][class,load] java.lang.VirtualMachineError source: jrt:/java.base
...
[HERE I TRIMMED THE OUTPUT: there are 100s of lines]
.....
Error occurred during initialization of boot layer
java.lang.module.FindException: Module b4j.example.main not found
StdErr:
so it seems that I'm not adding properly the "b4j.example.main" to the classpath? What am I missing here?

Thanks
 

Erel

Administrator
Staff member
Licensed User
I've tried several things but they didn't work.

You can convert a jar to a module by creating a module-info.java file, compile with javac --patch-module and then add it to the jar with jar -uf (you can see an example in B4JPackager11 CreateModule sub).

The module is listed but I wasn't able to actually add it.

If loading dynamic jars is important for you then it might be better to stick with Java 8 for now.
 
Last edited:

jmon

Well-Known Member
Licensed User
Thanks, me too, I tried so many things, but nothing works.

Today, I finally decided to bundle the JDK 11 (Provided on B4J download page) with my app, a bit like some others bundle Python with applications. I'll do like that for the moment, until I find a solution.

I will also post the question on StackOverflow.

Thank you for your help.
 
Top