B4J Library jCompiler

This may or may not be useful to others but I thought I would share it just in case.

The library 'jCompiler' allows you to compile a java class from a source file, and then load it into the B4J running program.

There are five methods in the library.

1, Compile - you specify the 'java' file name with the path to it.
2, loadTheClass - you specify the class name and the path to the newly compiled file.
3, runCodeNoParams - run the method in the class that takes no parameters. (Java 7 users see note at end of this post)
4, runCodeWithParams - run the method in the class and supply the parameters for it.(Java 7 users see note at end of this post)
5, listMethods - this simply lists out the declared public methods. (for debugging).

Requirements (Java 8 users use jCompiler, Java 7 users use jCompiler7)

It uses the eclipse compiler to generate the class file, so , obviously you need to download the file
ecj-4.4.jar (latest available one to date for windows) from here http://download.eclipse.org/eclipse/downloads/drops4/R-4.4-201406061215/#JDTCORE
its under 3MB. It needs to be placed in the B4J/Libraries so it can be found.

I have included a small test java file (hello.java) that works with the sample B4J application, and I have documented the sample B4J program.

If you create several methods that take parameters, that are all called the same name, the library will find the correct one for the parameters you supply ie,

public int add(Integer a,Integer b){...}
public long add(long a, long b){...}
public double add(double a, double b){...}

also, you can use variable arguments ie,

public String doSomething(int a,String... s){...}
called by
xx.runCodeWithParams(className,methodName,array as Object(3,array as String("one","two","three"))
(following the usual java practice that the variable args must be the last ones on the call)

In theory, you could use it to load classes from remote sources** so any 'sensitive' code would never appear in the jar, only at run time. So unless someone dumped the VM they would not be able to see your code. Or only load fully working code to registered users.
(If anyone wants to try this I will upload the version that allows for in-memory file objects)

** remember to add a security manager policy file to prevent remote classes doing bad things.

Have fun.

Note: Uploaded version of Library for java 1.7 named jCompiler7
Minor change to running methods in this version so you may need to change the calls in test program.
RunCodeNoParams --> becomes --> run
RunCodeWithParams --> becomes --> run2
(thought i'd save you some typing :) )


Update: uploaded a demo 'Demo-2'
Inside you will find a small demo of what the compiler can be used for (findFiles.java)
Don't worry about the layout file not being loaded by project. I just use it to get the methods from the controls.
You will need to change the hard coded path to point to where you have mp3 files. (It will search sub directories from where you start)

Feel free to use any of the code for your own projects, although a mention would be nice. :)
 

Attachments

  • hello.zip
    250 bytes · Views: 368
  • jCompiler.zip
    3.6 KB · Views: 410
  • jCompilerTest.zip
    1.1 KB · Views: 367
  • jCompiler7.zip
    3.5 KB · Views: 391
  • demo-2.zip
    4.5 KB · Views: 359
  • findclass.zip
    2.4 KB · Views: 343
Last edited:

BPak

Active Member
Licensed User
Longtime User
I get an error when trying to compile the test example supplied. - Unsupported major.minor version 52.0
java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: java.lang.UnsupportedClassVersionError: jCompiler/jCompiler : Unsupported major.minor version 52.0
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:114)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:82)
at b4j.example.main.<clinit>(main.java:16)
Caused by: java.lang.UnsupportedClassVersionError: jCompiler/jCompiler : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at anywheresoftware.b4a.shell.Shell.getCorrectClassName(Shell.java:455)
at anywheresoftware.b4a.shell.Shell.createObject(Shell.java:442)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:239)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
... 2 more
Exception in thread "main"
 

Daestrum

Expert
Licensed User
Longtime User
Oops, forgot to mention that - yes it was.
Will upload java 7 version of library 'jCompiler7' shortly.

@BPak Sorry totaly forgot not everyone runs java 8.
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Uploaded a better demo file 'demo-2' , not commented much, but hey it's fun to learn. :)
The java file inside (findFiles.java) is the one it compiles

Note users of jCompiler will need to change the calls from ??.run(...) to ??.runCodeNoParams(...), jCompiler7 users should be ok (ish).
 

Daestrum

Expert
Licensed User
Longtime User
Added another demo - findclass

I find it quite useful when using java objects, as I can look up any Java class (in jre libraries) and find the full name to use in the initialize statement, and get all the public methods for the class.

If you are using Java 7 - change the line to jc.Compile("; -1.8 ....") to -1.7

Lost track of runCode... and run... so you may need to change those lines too.
 
Top