In addition to this document, check out our tutorials, which contain a mix of slides and code:


XMLVM is a flexible cross-compilation framework. Instead of cross-compiling source code of high-level programming languages, XMLVM translates byte code instructions. Byte code programs are represented by XML documents and cross-compiled via XSL stylesheets. Section "Overview" provides a brief overview of the XMLVM toolchain. Section "Getting XMLVM" describes how to obtain the source code of XMLVM and Section "Compiling XMLVM" how to build XMLVM from source. The various command line options supported by XMLVM are described in Section "Invoking XMLVM".


XMLVM supports byte code instructions from different virtual machines: the Java Virtual Machine (JVM), the Common Language Runtime (CLR) that is part of the .NET framework, and the YARV byte code from Ruby 1.9. The name XMLVM is inspired by the fact that byte code instructions are represented via XML. Each byte code instruction is mapped to a corresponding XML-tag. Transformations of XMLVM programs are done via XSL stylesheets. The following Figure shows all possible paths through the XMLVM toolchain:

The first step in using XMLVM is to compile a Java or .NET source code program to byte code. This is done with a native compiler such as Sun Microsystem's javac or Microsoft's Visual Studio. The resulting byte code program (either a Java .class file or a .NET .exe file) is fed into the XMLVM toolchain where it is first converted to XML. XMLVMJVM denotes an XMLVM program that contains JVM byte code instructions, whereas a XMLVMCLR program contains CLR byte code instructions. XMLVMDEX makes use of Android's DEX instructions for Dalvik that is is particularly suitable for generating source of other high-level programming languages. It is possible to cross-compile XMLVMCLR to XMLVMJVM with the help of a data flow analysis (denoted as XMLVMCLR-DFA in the Figure above).

XMLVMJVM serves as the canonical representation within the XMLVM toolchain in the sense that it separates the frontend from the backend. That is to say, all code generating backends use XMLVMJVM as their input. As can be seen in the diagram, various paths through the XMLVM toolchain are possible. For example, .NET programs can be cross-compiled to Java class files and Java class files can be cross-compiled to JavaScript amongst others.

The byte code level cross-compilation is only one aspect of XMLVM. The XMLVM distribution also contains compatibility libraries for various targets. For example, when cross-compiling from C# to Java class files, XMLVM contains a compatibility library for WinForms (the Microsoft GUI library) written in Java. This allows C# desktop applications to be cross-compiled to Java desktop applications. Similarly, when cross-compiling from Java to JavaScript, XMLVM features a compatibility library for AWT/Swing written in JavaScript that effectively allows to cross-compile Java desktop applications to AJAX applications. The C backend includes libraries for Cocoa Touch so that cross-compiled applications can be run on iOS devices.

It should be noted that XMLVM is a research project and as such lacks the completeness of a commercial product. Each individual backend requires a significant effort to support different APIs. WinForms, AWT/Swing, and Cocoa Touch are all complex libraries and at this point XMLVM only supports a subset of each. The various paths through the XMLVM toolchain have different levels of maturity that should be taken into consideration when using XMLVM. The C backend is the most complete and it is possible to build complex iOS applications.

Getting XMLVM

XMLVM is released under the L-GPL v2 license and is hosted at SourceForge. We currently do not offer pre-compiled binary packages. The only way to obtain XMLVM is to checkout the latest version from the Subversion repository. You will need a Subversion client to do this. If you are using a command line version of Subversion, you can checkout the trunk of the XMLVM repository via the following command:

svn co

Note that this will give you a read-only version of the repository. You will be able to update (which you should do frequently) but not commit changes to the repository. If you find a bug, please send a mail to the XMLVM mailing list.

XMLVM is developed using the Eclipse IDE. You can also checkout the sources of XMLVM via Eclipse (using an appropriate Subversion plugin such as Subclipse or Subversive). The XMLVM sources contain .project and .classpath files so that Eclipse will recognize XMLVM as an Eclipse project. The benefit of using Eclipse is that it makes it easy to navigate the source code if you intend to study the internals of XMLVM. There are also numerous Eclipse launch configurations (in the etc/ directory) that allow the invocation of various demos.

Compiling XMLVM

XMLVM depends on numerous third-party libraries such as BCEL, JDOM, and Saxon. All these libraries are also released under an Open Source license. To facilitate the compilation process, XMLVM contains binary versions (i.e., jars) of all required libraries. All third-party libraries are contained in the lib directory. Building XMLVM from sources requires Java 1.6 as well as ant. In order to compile XMLVM from command line, simply run ant in the XMLVM root directory:

cd xmlvm
ant demos

After a successful run of ant, there should be a dist/ directory. The ant script packages all dependent libraries and XMLVM's own class files into one jar file. The only file needed to run XMLVM is the jar file dist/xmlvm.jar. This jar file can be copied to a convenient location with the ant install target, as presented below.

Installing / Uninstalling XMLVM

The install procedure is simple and it will ease the user interface with XMLVM libraries

  • Edit file properties/ (or create it if it does not exist). Define there the destination prefix of XMLVM in the variable xmlvm.install
  • If you do not define a specific location, the default installation path would be /usr/local
  • Type ant install
For example, to install it under your home directory, add the following entry to the properties/ file:

The ant install command will install the files $XMLVMINSTALL/lib/xmlvm/xmlvm.jar and $XMLVMINSTALL/bin/xmlvm
Make sure that you have write permissions on the destination paths, e.g. run the target as root.
The executable is found under  $XMLVMINSTALL/bin/xmlvm. Make sure to add the $XMLVMINSTALL/bin location to your $PATH

The uninstall procedure is similar. Make sure again that you have write permissions and then type

ant uninstall

Invoking XMLVM

Java 1.6 is needed to run XMLVM. Invoking XMLVM can be done after installing in the following way:

xmlvm ARGUMENTS...
Make sure that you have the installation location to your path, with a command similar to this:
export PATH=$PATH:/installation/location/of/xmlvm/bin

XMLVM supports various command line options that drive the cross-compilation process. The general pattern of using XMLVM to cross-compile an application is:

xmlvm --in=<input> --out=<output-directory> --target=<target>

The --in option defines the input files to be cross-compiled whereas the --out parameter designates the output directory of the cross-compiled input. The --target option finally defines for which platform XMLVM should generate code. These as well as other options are explained in detail in the following section.

Command Line Options

The behavior of XMLVM is controlled by numerous command line arguments. xmlvm reads in one or more source files, processes them according to the command line options, and then writes out one or more destination files.

  • --in=<path>

    The source files are specified via one or more --in options. If the argument passed to --in is a directory, then this directory is traversed recursively and all files with the suffix .class.exe, or .xmlvm are processed. Files with other suffixes are ignored. It is possible to use wildcards to filter out certain files. It is possible to specify multiple --in parameters. At least one --in parameter is required.

  • --out=<path>

    The output generated by xmlvm is written to a directory specified by the --out parameter. The argument <path> has to denote a directory. If the directory does not exist, xmlvm will create it. All files generated by xmlvm will be written to this directory. The only exception is when using --target=class. In this case the resulting Java class files (ending in suffix .class) are written to appropriate sub-directories matching their package names. Already existing files with the same name will be overwritten. If the --out parameter is omitted, the current directory is the default.

  • --target=[xmlvm|jvm|clr|dfa|class|exe|js|c|posix|python|qooxdoo|iphone]

    This option defines the output format of the target. These correspond with the various backends for code generation supported by XMLVM. The different targets are explained in the following:

    • xmlvm: The input files are cross-compiled to XMLVM. *.class files will be cross-compiled to XMLVMJVM*.exe files will be cross-compiled to XMLVMCLR*.xmlvm files will be copied unchanged. This option is the default for --target.
    • jvm: The input files are cross-compiled to XMLVMJVM.
    • clr: The input files are cross-compiled to XMLVMCLR
    • dfa: A DFA (Data Flow Analysis) is performed on the input files. Currently the DFA will only be performed for XMLVMCLR programs. This option cannot be used in conjunction with any other code generating option.
    • class: The input files are cross-compiled to Java class files.
    • exe: The input files are cross-compiled to a .NET executable.
    • js: The input files are cross-compiled to JavaScript.
    • c: The input files are cross-compiled to C.
    • posix: The input files are cross-compiled to a self-contained C program that includes all dependent classes such as java.lang.System.
    • python: The input files are cross-compiled to Python.
    • qooxdoo: Cross-compiles an application as a web application. The business logic is cross-compiled to JavaScript and a Java or .NET compatibility library is copied alongside. The output directory specified by --out will contain a ready to deploy web application. The environment variable QOOXDOO_HOME needs to point to the base directory of the Qooxdoo qooxdoo installation. This option implies --target=js and requires option --app-name.
    • iphone: Cross-compiles an application to the iPhone. The output directory specified by --out will contain a ready to compile Xcode project. This option requires the option --app-name.

  • --app-name=<app_name>

    This option can only be used in conjunction with targets iphone or qooxdoo. It specifies the name of the iPhone or Qooxdoo application whose name will be <app_name>.

  • --debug=[none|error|warning|all]

    • none: Be completely quiet, no information is printed
    • error: Only errors will be printed
    • warning: Warning and errors will be printed
    • all: All debug information (including errors and warnings)

  • --deps=<dep1<,dep2>...>

    This let's you specify addition libraries that your app depends on. This is the same as what you would usually do when you add additional libraries to your classpath in order to compile a regular Java application.
    One or more dependencies can be given. A dependency can be a path on the file system which contains class files or a a JAR file containing the library.
    Only the classes that the app depends on are cross-compiled. Classes not required from the given dependencies will not be processed and thus will not appear in the output.

  • --lib=<libraries>

    Comma separated list of extra libraries required for the specified target. (This is not to be confused with --deps)

  • --resource=<path>

    Colon separated list of external files and directories. These resources (such as images) will be added to the cross-compiled application. If this argument ends with '/', then the contents of this directory will be copied. If it is a directory and does not end with '/', then a verbatim copy of the directory will be performed. This argument can also be used to add extra C/C++/Objective-C source files to the generated Xcode project for the iOS target.

  • --skeleton=<type>

    Creates a new skeleton project to simply the use of XMLVM. <type> can be:
    • iphone: iPhone project skeleton
    • android: Android/iPhone project skeleton
    • android:migrate: Migrate an existing Android project to XMLVM (needs project created by 'android create project' command)
    • iphone:update: Update an existing XMLVM/iPhone project to latest build scripts
    • android:update: Update an existing XMLVM/Android project to latest build scripts


  • xmlvm --in=/foo/bar

    The directory /foo/bar is searched recursively for *.class*.exe, and *.xmlvm files. The default target is xmlvm. For *.class files, XMLVMJVM is generated. For *.exe files, XMLVMCLR is generated. Files with suffix *.xmlvm are copied to the output directory. Other files with different suffices are ignored. Since no --out parameter was given, the default output directory is "." (the current directory).

  • xmlvm --in=/foo/*.class --in=/bar/*.exe --out=/bin

    The directory /foo is searched recursively for *.class and the directory /bar is searched recursively for *.exe files. The default target is xmlvm. Files with other suffices are ignored. For *.class files, XMLVMJVM is generated. For *.exe files, XMLVMCLR is generated. The resulting *.xmlvm files are placed in directory /bin.

  • xmlvm --in=/foo --target=jvm

    The directory /foo is searched recursively for *.class*.exe, and *.xmlvm files. In all cases, the generated output will always be XMLVMJVM. For *.exe files as well as *.xmlvm files containing something other than XMLVMJVM will be cross-compiled XMLVMJVM.

  • xmlvm --in=/foo --target=class

    Same as the previous example, however instead of generating XMLVMJVM files, Java *.class files that can be executed by a Java virtual machine will be generated. The class files will be placed in appropriate sub-directories matching their package names.

  • xmlvm --in=/foo --target=iphone --iphone-app=TheApplication

    Same as the previous example, however instead of creating Java *.class files, an iPhone application will be generated. The output directory will contain the ready to compile Objective-C source code including all necessary auxiliary files such as Info.plist and a Makefile. The iPhone application will be calledTheApplication using a default icon.

  • xmlvm --in=/foo --target=android-on-iphone --iphone-app=TheApplication

    Same as the previous example, but will also copy the Android compatibility library to the output directory. This effectively allows Java-based Android applications to be cross-compiled to the iPhone.

  • xmlvm --in=/foo --qx-app=TheApplication --qx-main=com.acme.Main

    The directory /foo is searched recursively for *.class*.exe, and *.xmlvm files. This option implies --target=js. All files will be cross-compiled to JavaScript. With the help of the Qooxdoo build scripts, the output directory will contain a ready to be deployed AJAX application. The main entry point of the application is com.acme.Main.

iPhone/Android Backend

With the help of XMLVM it is possible to cross-compile Java applications to native iPhone applications. The Apple license agreement does not permit the installation of a virtual machine on the iPhone. By cross-compiling a Java application to a native iPhone application, this restriction of the license agreement is therefore not violated. XMLVM can legally generate native iPhone application and it is not necessary to jailbreak a device in order to run an application cross-compiled by XMLVM.

Apple only supports Objective-C as the development language for the iPhone. The GUI of iPhone applications is based on Cocoa Touch. If Java is to be used as a development language for iPhone applications, two aspects need to be addressed: the cross-compilation of Java to Objective-C and a Java API for Cocoa Touch. The Java API for Cocoa Touch is loosely based on the Objective-C counterpart. While XMLVM makes better use of overloading and interface definitions for delegates to create a strongly-typed API, the description of the various classes and methods can be taken from Apple's official documentation.

Android is an Open Source platform for mobile devices. Initiated by Google, Android has received much attention. Android applications are developed using Java, although a special compiler converts class files to a proprietary, register-based virtual machine that is used on Android devices to execute applications. Android defines its own API for writing mobile applications. With the help of XMLVM it is possible to cross-compile Java-based Android applications to native iPhone applications. The following Figure depicts this process:

The Android application is written in Java and makes use of an Android specific API. XMLVM offers a compatibility library, written in Java, that offers the same API as Android, but only makes use of the Java-based API for Cocoa Touch mentioned earlier. During the cross-compilation process, both the application and the Android compatibility library are cross-compiled from Java to Objective-C and linked with the Cocoa Touch compatibility library to yield a native iPhone application.

As can be seen, compared to the Java-for-the-iPhone portion of XMLVM, the only additional feature added to support Android applications is the Android compatibility library. When the project is defined as an Android project, the Android compatibility library is also attached to the generated project. The Android-based iPhone application can be run in the XMLVM-specific iPhone emulator, the Apple's emulator and the Android emulator.

Sample projects

Under the folder demo, various demo projects exist, to test XMLVM system. This section will describe only iPhone and Android based demo projects. These demo projects can be run either from the command line, or from and IDE, such as Eclipse and Netbeans. The source code of the Java-for-the-iPhone demos is located in directory demo/iphone/, whereas the source code of the Android-to-iPhone demos are located in directory demo/android/.
These are self contained projects, similar with the ones created by the XMLVM skeleton process (see below under How to start a new project under XMLVM).

Android demos need Android SDK to be installed. The SDK should be defined under property file properties/ as:


If the Android SDK is not defined, Android demos will fail to compile.

It is possible to compile all demo projects at once by giving the command:

ant demos

in the base directory of the XMLVM project. It is also possible to go to each project's directory and compile it by itself. Instructions on how to run these projects can be found under section How to run an XMLVM project in this document. In any case, the xmlvm.jar should already be compiled (i.e. go to the base directory of the project and type ant jar to create it).

Here is a list of the available sample applications:
  • iHelloWorld (Portrait): "Hello World" in portrait mode.
  • iHelloWorld (PortraitUpsideDown): "Hello World" in upside down portrait mode.
  • iHelloWorld (Landscape): "Hello World" in landscape mode.
  • iHelloWorld (Fullscreen): "Hello World" in fullscreen landscape mode.
  • iFireworks: iPhone version of the fireworks application.
  • aFireworks: Android version of the fireworks application.
  • Xokoban: Android version of the Xokoban application.

How to start a new project under XMLVM

If the user wants to start a new blank project, the --skeleton command line option can be used. Currently, there are three types of skeleton projects:
  • new iPhone projects
  • new Android projects
  • migration of existing Android projects to the XMLVM scheme

iPhone projects

To create a new iPhone project the iphone skeleton should be used as follows:

xmlvm --skeleton=iphone --out=OUTDIR --app-name=APPNAME

where OUTDIR is the output directory of the project and APPNAME is the name of the project. This template will create a new folder under OUTDIR (if it does not exist) and put all required files inside.

Android projects

To create a new Android project the android skeleton should be used, as follows:

xmlvm --skeleton=android --out=OUTDIR --app-name=APPNAME

where OUTDIR is the output directory of the project and APPNAME is the name of the project. Like in the case of the iPhone project, a new Android project will be created. This project will also be compatible with projects created with the Eclipse plugin for Android, as well as the android create project tool. Some more configuration is required though. Please open file, uncomment the line sdk.dir=SDKPATH and define the location of the Android SDK.

Migration of existing Android projects

If an Android project already exists, it is possible to migrate it in order to be able to use XMLVM targets in parallel with Android targets. In order for the migration to be successful, the project should be a properly set up Android project for Eclipse (without special Eclipse configuration), or a project created and managed by the android create/update project tool. The command to migrate an existing Android project is as follows:

xmlvm --skeleton=android:migrate --out=OUTDIR

where OUTDIR is the location of the existing Android project. If the project was created with the Android android create project tool, the actual build.xml file will be backed up and a new build.xml file will be created. In the case some special configurations or targets exist in this file, these should be manually transferred to the new build.xml file. Note that some targets of the old  file might already exist in the migration project build file, nbproject/androidsupport.xml. Please make sure that these targets are properly executed, or XMLVM project migration could not be performed.

How to configure an XMLVM project

There are two base configurations that should be taken into account, or else the XMLVM projects could not be used:
  • Location of the XMLVM library. This is the property xmlvm.sdk.jar, found in the file nbproject/ This property is usually set automatically by the XMLVM tool.
  • Location of the Android SDK, only in the case of the Android-based projects. This is the property sdk.dir found in the file This property is not set automatically and you have to define it yourself. If you have migrated an Eclipse-based project, which usually does not define the location of the Android SDK, it is required to update this property, or else compilation will fail! For projects already created with the android create project tool, the configuration of this property is usually performed automatically.
Every XMLVM project can be configured, to use specific features, mostly related to the Xcode project creation. By default the templates have used reasonable values for all properties, so that the project could be instantly usable. Configuration parameters are found in file and are as follows:
  • xmlvm.project: the Xcode project type. Valid values are:
    • iphone: iPhone project skeleton
    • ipad: iPad project skeleton
    • ios: iPhone and iPad project skeleton
    • iphone3: Legacy iPhone 3.1 project skeleton. This target is deprecated and is presented here for backwards compatibility only. It is possible that project compilation will fail when compiled with this target.
  • xmlvm.lib: Add extra libraries required for the project. Supported libraries are only system libraries and should have a full qualified name, without path definition. If more than one library is required, then every library should be separated by the comma character. If a library name ends with tilde ~, then a weak linking will be performed by the Xcode, i.e. this library is not strongly required when building this project. In the case an android project is required, then the android library should be defined. Examples:
    • to use QuickTime library, the entry QuickTime.framework should be defined
    • to use ssl library, the entry libssl.dylib should be defined
    • to use object crt1, the entry crt1.o should be defined
    • to use both QuickTime and ssl library, the entry QuickTime.framework,libssl.dylib should be defined
  • xmlvm.resource: Add extra resources required when creating the Xcode project. This is a colon separated list of files that will be used verbatim in Xcode project. Directories can be provided too; if a directory is provided, then if the name ends with "/", the contents of this directory will be used. If not, a verbatim copy of the directory will be used. It is also possible to add source files to the project (in the form of *.c, *.h, *.m, *.cpp, *.c++ and *.mm files). In the case a directory with source code is provided, only one level deep will be searched for source files. For this reason either specific source file should be provided, or a directory ending with "/".
  • bundle.version: The version if this program
  • bundle.identifier: a reverse-DNS naming scheme to identify the current project. Note that this identifier is used only for the produced iOS project and not for the Android project.
  • bundle.displayname: The displayed name of this program.
  • prerenderedicon: whether the project icon is already prerendered (boolean value).
  • statusbarhidden: whether the status bar of the project is hidden when launched (boolean value).
  • applicationexits: whether application does not run in background on suspend. Change to "false" to support multi-tasking (boolean value).
  • xmlvm.trimmer: this is the project source-level optimization. By using this feature compilation time should be shorter and produced binary will be smaller. This option is not yet properly supported for Android projects. Also, in some rare cases, this optimization might break the project compilation. If this happens, please disable this optimization (boolean value).
  • xmlvm.trimmer.seed: randomizing seed of the trimmer process (free integer value).
When using an Android project, there are other configurations that might be needed, like the properties found under or These properties are not managed by the XMLVM tool but from the Android SDK, and should be properly set up in advance.

How to run an XMLVM project

When an XMLVM is properly set up, it is possible to compile it and run it as follows:
  • under the Java Emulator
  • by compiling with the help of Xcode
  • if it is an Android project, to run the project under the Android emulator
In every case, it is either possible to set the way the project is run, and then run it, or set and run it at the same time. Every time the target is set, it is enough to run the project with the same target by issuing the command:

ant run

Run from the command line

To use the Java emulator the following command should be used:

ant use-Java run

or use the equivalent target:

ant run-Java

Likewise, to use Xcode the following command should be used:

ant use-Xcode run

or use the equivalent target:

ant run-Xcode

To run under Android emulator, use the following command:

ant use-Android run

or use the equivalent target:

ant run-Android

In this case the debug version of the binary will be compiled and the default  emulator will be used. The emulator should be defined and run already and only one instance should be present.

It is possible to set once the type of the run target like this:

ant use-Java


ant use-Xcode 


ant use-Android

Using Netbeans

All iPhone projects can be directly imported to Netbeans, as Java projects. Right now there is no support for Android projects.
Standard tools can be used to run the project (e.g. press the play button).
To select between Java emulation and Xcode project creation, select the appropriate configuration.

Using Eclipse

All projects can be imported as Java projects (for iPhone projects) or Android projects (for Android projects). It is possible to use the standard Eclipse tools in order to use these projects (e.g. press play button to start the project). It is recommended though to use the special ant scripts instead, to perform the various tasks, or else some feature will be missing (e.g. plugins or extra resource files). The procedure is described below:

To run the ant scripts under Eclipse, the above specified targets should be defined, as follows:
  • Menu RunExternal ToolsExternal Tools Configurations...
  • Select Ant BuildNew button
  • Under Name: give a proper name (e.g. Projectname Xcode)
  • On tab MainBuildfile: click on Browse Workspace...
  • On the display dialog, select the correct project and then click on build.xml to the file on the right. Press OK.
  • Click on Targets tab, and select the targets you want to use (e.g. first click on use-Xcode and then on run). Target execution order should show use-Xcode, run
  • Click on Run.
The steps are similar for any other target.
These targets are saved by the Eclipse Workspace and next time can be called either from menu RunExternal Tools or from the corresponding External Tools button in the Toolbar.

Using plugins with iPhone projects

Sometimes, the desired iPhone project requires some extra code written in ObjC (or any other C-based language). This source code should be compiled along the produced iPhone code (and together with the iPhone compatibility library), while the corresponding Java class(es) should be present, in order for these objects to be visible when compiling the iPhone project.

To solve this problem, plugins where introduced to the XMLVM system. With plugins it is easy to deliver a single file (a JAR actually) with both, the java source code and the required C-based code, as well as the glue C-Java code.
A demo plugin can be found under demo/iphone/plugins/Zip

To make this plugin, go to the folder of the plugin and perform ant jar. A Zip.jar will be produced under dist/Zip.jar. Take this JAR and add it to the classpath of your project. And that's it! The build scripts will take care of properly extracting the files and use them when required.

To create a custom plugin, use the demo plugin as a reference. Write your own Java glue code under src/java and put all files required for the Xcode project (all C/ObjC etc files) under objc directory. The directory structure could be as deep as you desire, but when exporting these files to Xcode, directories will be flattened. Make sure that no file overriding will be performed, or unexpected results might appear.

If you want to make your own build scripts for plugins, make sure that the created JAR file has a root directory /objc with all files required by Xcode inside.