Develop iOS Android app in java, Cross platform java virtual machine , the minimal jvm .
Features
Architecture
Build for iOS/Android platform
Build for Windows/Linux/MacOS platform
How to debug source
Using miniJVM in project
Documentation
- Jvm Build pass: iOS / Android / mingw-w64 32|64bit / MSVC 32|64bit / MacOS / Linux
- No dependence Library
- Minimal memory footprint
- Minimal binary, embedded jvm
- Minimal bootstrap classlib
- Support java source compiler(janino compiler)
- Jit support
- Low latency java garbage collection
- Java remote debug supported, JDWP Spec
- Translate minijvm classes to C source code to improve execute speed.
- OpenGL ES 3.0
- Swing like gui lib, HTML like XML layout
- Audio/Video Playback and Capture
- Take photo from Camera or Album
- Save and Load file from mobile device
- Api compatible with miniJVM desktop platform, app can running on desktop platform
MiniJVM on web build by Starcommander. Source Web demo
2022.11. Add documentation.
2021.03. Add j2c module, it 's a tool for convert minijvm java source code to c source code , then build it as native application , support desktop and mobile platform .
2020.12. Add build script and release v2.1.
2020.10. Refactor source and remove binary in repository.
2020.10. Https supported.
2020.03. Add xml layout for gui system, add 3D game demo for minijvm, fix jdwp debug for jetbrain idea.
2019.12. Bind cross-platform awtk ui system , see awtk-minijvm
2019.12. Jit enabled, it based on sljit project
2019.10. Jit is developing
2018.12. Optimize performance
2017.09. miniJVM start
Write java code once , running on all of iOS / Android / MacOSX / Win / Linux platforms
There were not essential jar file pre-built, so build these jar file first
Develop IDE: Eclipse, Netbeans or JetBrains Intelli Idea
-
Run script /binary/build_jar.sh or /binary/build_jar.bat to generted jars.
OrBuild maven projects /minijvm/java copy to /mobile/assets/resfiles/minijvm_rt.jar
Build maven projects /mobile/java/glfm_gui, copy to /mobile/assets/resfiles/glfm_gui.jar
Build maven projects /mobile/java/ExApp, copy to /mobile/assets/resfiles/ExApp.jar
Maybe you can change /mobile/java/ExApp/src/main/java/test/MyApp.java , Add your resource to /mobile/java/ExApp/src/main/resource/res/ , such as audio or image etc, Configure /mobile/java/ExApp/src/main/config.txt for icon ,version, boot class, etc -
XCode open /mobile/iosapp ,setup developer account in Signing&Capabilities , build and install app to Device , verify app before running app (Setting->General->Device Management->{Developer account}->Verify App->Trust)
-
Android Studio open /mobile/androidapp build and install app to Android device
-
The AppManager is running
-
Run script /binary/build_jar.sh or /binary/build_jar.bat to generted jars
OrBuild java bootstrap classes /minijvm/java , Maven build jar and copy to /binary/lib/minijvm_rt.jar
Build gui classes /desktop/glfw_gui/java , Maven build jar and copy to /binary/libex/glfw_gui.jar
Build console test case classes /test/minijvm_test , Maven build jar and copy to /binary/libex/minijvm_test.jar
Build gui test app classes /mobile/java/ExApp , Maven built jar and copy to /binary/{platform}/apps/ExApp.jar -
Run /binary/build_mac_linux.sh or /binary/build_wini686.bat or /binary/build_winx64.bat to generted binaries
OrBuild gui jni c dynamic library /desktop/glfw_gui/c by cmake
Build minijvm /minijvm/c by cmake -
Run test script /binary/{platform}/test.sh | test.bat
Almost all Java IDEs support remote debugging. The IDE connects to the debug port of the miniJVM through TCP, and then enters the debugging state. The miniJVM has two options, one is to enable the debugging function, and the other is to wait for the IDE to connect to the debug port after the VM is started, and execute the bytecode only after that. These two options need to be setup before initializing the VM.
These two options defined in jvm.h
struct _MiniJVM {
...
s32 jdwp_enable;// 0:disable java debug , 1:enable java debug and disable jit
s32 jdwp_suspend_on_start;
...
};
-
Open miniJVM debug mode, mini_jvm jdwp listen on port 8000
Desktop platform : Run mini_jvm with flag: -Xdebug for debug mode ,Or change source before build.
/minijvm/c/main.c 134: jvm->jdwp_enable = 1; //change "jdwp" to 1
iOS/Android : change source before build
/mobile/c/glfmapp/main.c 50: refers.jvm->jdwp_enable = 1; //change 0 to 1
If debug on phone device, check the device ip address from General Setting -> wifi ->(i) -
Run the VM with jars eg:
mini_jvm.exe -Xdebug -bootclasspath ../lib/minijvm_rt.jar -cp ../libex/glfw_gui.jar org.mini.glfw.GlfwMain -
IDE open project , eg: /mobile/java/ExApp
Intelli idea : menu Run -> Edit Configurations , + remote , Transport : socket , Debugger mode : attach , host is your mini_jvm running on host ip and port ,ex "127.0.0.1:8000" or "192.168.0.32:8000"
Eclipse : configuration like as idea
Netbeans : menu Debug -> connect to Debugger, Connector : SocketAttach , host is your mini_jvm running on the host and port, ex. "localhost:8000" , Timeout: 10000 -
Then you can set breakpoints and pause vm and watch variables
Awtk-minijvm :AWTK cross platform native ui bind to minijvm
LWJGUI-Mobile : java LWJGL UI library
BiBiX : java instantial messager
G3d : java 3d game demo
MiniJVM web demo : miniJVM on web demo
Oracle CLDC :referenced cldc api
OpenJDK : referenced java api
Miniz :for read jar files
Glfm :for cross platform (android/ios) GUI
Nanovg :for GUI paint function
Stb :for GUI truetype font and image
Glad :for replace openGL/GLES head file
Glfw :for pc cross platform GUI
Dirent :for linux style on win vc file and directory access
Tinycthread :for cross platform thread
JRegex :for java String regex match
Janino :for compile java source file
MiniAudio :for java audio playback and capture
Sljit :Platform independent low-level JIT compiler
Mbedtls :Https support by mbedtls
Avian :referenced java api
C / ObjC: JetBrains CLion, Xcode, Virtual studio
Swift : XCode
Java : Jetbrain Idea, Netbeans
Android : Android Studio
Copy C source /minijvm/c to your project source folder, copy built jar minijvm_rt.jar to you projec resource folder
#include "jvm/jvm.h"
int main(int argc, char **argv) {
char *bootclasspath = "../../binary/lib/minijvm_rt.jar";
char *classpath = "../../binary/libex/minijvm_test.jar;./";
char *main_name = "test.Foo3";
s32 ret = 1;
MiniJVM *jvm = jvm_create();
if (jvm != NULL) {
jvm->jdwp_enable = 0; //value 1 for java remote debug enable
jvm->jdwp_suspend_on_start = 0;
jvm->max_heap_size = 25 * 1024 * 1024; //
ret = jvm_init(jvm, bootclasspath, classpath);
if (ret) {
printf("[ERROR]minijvm init error.\n");
} else {
ret = call_main(jvm, main_name, NULL);
}
jvm_destroy(jvm);
}
return ret;
}
Project: Janino
Janino is a super-small, super-fast Java compiler.
Janino can not only compile a set of source files to a set of class files like JAVAC, but also compile a Java expression, a block, a class body, one .java file or a set of .java files in memory, load the bytecode and execute it directly in the same JVM. Janino compiler is not the full java compiler, see limitation , like :
List<String> list=new ArrayList();
list.add("abc");
String s=(String)list.get(0);//can't ignore (String) cast qualifier.
Download jars :
janino.jar
commons-compiler.jar
#compile /binary/res/BpDeepTest.java
mini_jvm -bootclasspath ../lib/minijvm_rt.jar -cp ../libex/janino.jar:../libex/commons-compiler.jar org.codehaus.janino.Compiler ../res/BpDeepTest.java
Project: Luaj
miniJVM adapted : [Luaj minijvm] https://github.com/digitalgust/minijvm_third_lib
Lightweight, fast, Java-centric Lua interpreter written for JME and JSE, with string, table, package, math, io, os, debug, coroutine & luajava libraries, JSR-223 bindings, all metatags, weak tables and unique direct lua-to-java-bytecode compiling. Download jars :
luaj.jar
mini_jvm -bootclasspath ../lib/minijvm_rt.jar -cp ../libex/luaj.jar Sample
Windows mini_jvm gui | Macos mini_jvm gui | Linux mini_jvm gui | Web mini_jvm gui |
.
├── binary miniJVM binary for build(win32/win64/mac/linux/
├── desktop
│ ├── awtk_gui open source gui frame awtk jni
│ └── glfw_gui desktop openGL, glfw, miniaudio, native module
├── j2c miniJVM java source translate to c tools
│ ├── app
│ └── translator
├── minijvm Core source
│ ├── c miniJVM c source
│ └── java miniJVM runtime library
├── mobile
│ ├── androidapp Android launcher
│ ├── assets mobile app resource, font files, jar files ,pic ,audio etc.
│ ├── c mobile native lib, openGLES, glfm framework, gui jni, glfmapp
│ ├── iosapp iOS launcher
│ └── java mobile java lib, GUI, AppManager, app example
├── screenshot
└── test miniJVM test case
- Outline
- GApplication
- GForm
- GFrame
- GMenu
- GButton
- GLabel
- GCheckBox
- GSwitch
- GScrollBar
- GImageItem
- GList
- GPanel
- GViewPort
- GViewSlot
- GTextBox GTextField
- Custom UI Component
- XML Component common attributes
- Events
- Template
- MultiLanguage
- Style
- Layout
- Script
- Example
- Example Game
-
- Visible UI components are inherited from GObject.
- All GUI application are extends class GApplication, GApplication contains a GForm, and starts by AppManager.
- GForm is a panels of OS window or phone screen, a bottom visible UI container.
- GFrame is an internal closable and movable window container.
- All UI components are placed in a GContainer.
- GContainer can be a child of another GContainer.
- Set a GStyle for all components to change appearance.
- There are two methods to new a GObject , one is manual create an object, the other is added a node to XML file.
- GUI XML layout like HTML, and there is a simple script like javascript for HTML.
- iOS/Android system based on GLFM (/mobile/iosapp/ , /mobile/androidapp/)
- Desktop window system based on GLFW (/desktop/glfw_gui/)
- GUI rendering by Nanovg
- OpenGL 3.3 for desktop and OpenGLES 3.0 for mobile
- The UI consists of two parts, one is compiled into a dynamic link library by the jni native function, and the native function is compiled together with the JVM on the mobile phone, and the other part is the java api.
package test;
import org.mini.apploader.GApplication;
import org.mini.gui.GForm;
public class MyApp0 extends GApplication {
GForm form;
@Override
public GForm getForm() {
if (form != null) {
return form;
}
form = new GForm(null);
return form;
}
}
This is a simplest app, override getForm() to export a GForm to AppManager, Device show the form ,and post events (Keyboard/Mouse/TouchScreen/etc) to the form.
miniJVM core does not contain a graphics system. For desktop and mobile phone, a graphics framework based on OpenGL/GLES is established attached to the JVM. This system will enter the graphical interface of AppManager after starting the VM. This application manager is managing more applications developed by java. It can be installing and deleting applications, etc. The way of installing applications include downloading jars, or uploading jars. These jars applications must contain a config.txt file in the jar, which is used to describe some properties of this application, such as startup class, icon, update address, etc.
config.txt
name=ExApp
app=test.MyApp
icon=/res/hello.png
desc= Mobile app develop example.\n you can upgrade it.
version=1.0.4
upgradeurl=https://github.com/digitalgust/miniJVM/raw/master/mobile/assets/resfiles/ExApp.jar
Save the xml to a file .
<form name="FORM_MAIN" w="100%" h="100%">
</form>
Load the xml file and build form . there 3 attributes descript the form.
Attributes:
name : String , the form name.
w : form width, a percentage of OS window or a abstract int value for pixels. "100%" indicate the form width is window width, or phone screen width.
h : like w, form height.
package test;
import org.mini.apploader.GApplication;
import org.mini.gui.*;
import org.mini.layout.*;
public class MyApp2 extends GApplication {
GForm form;
@Override
public GForm getForm() {
if (form != null) {
return form;
}
//load xml
String xmlStr = GToolkit.readFileFromJarAsString("/res/myapp2-form.xml", "utf-8");
UITemplate uit = new UITemplate(xmlStr);
XContainer xc = (XContainer) XContainer.parseXml(uit.parse(), new XmlExtAssist(null));
int screenW = GCallBack.getInstance().getDeviceWidth();
int screenH = GCallBack.getInstance().getDeviceHeight();
//build gui with event handler
xc.build(screenW, screenH, new XEventHandler() {
@Override
public void action(GObject gobj) {
}
public void onStateChange(GObject gobj, String cmd) {
}
});
form = xc.getGui();
return form;
}
}
The MyApp2 same as MyApp0. Show a form but there is nothing in the form.
<form name="FORM_MAIN" w="100%" h="100%" closable="1">
<frame name="FRAME_TEST" w="80%" h="80%" title="WINDOW" onclose="onTestClose()" oninit="onTestOpen()">
</frame>
</form>
There is a frame show on the form.
Attributes:
closable: 1: the frame can be closed. 0:can't close it.
title: String , the frame's title.
onclose: String , the script function call, this function must in the frame's script partion.
oninit: String , the script function call, this function must in the frame's script partion.