This is an extremely preliminary proposal to build a Java interface to Root. It should be viewed as a work in progress, but is put here to solicit interested peoples' comments and suggestions. Offers to help refine or implement any of this are also more than welcome!
This document describes a proposed interface to Root objects from Java. It could be used by anyone wanting to access Root objects from within a Java environment. Possible uses would include:
The author's particular interest is in building an interface to allow Root data to be analyzed alongside many other data formats in Java Analysis Studio (JAS), however the proposal here contains no dependencies on JAS.
Java works a little differently to most other languages in that the Java compiler converts Java source code into machine independent bytecodes, that are either interpreted or more often converted to native machine code at run time. There is no link step involved in running Java programs, and therefore Java cannot trivially be linked with modules written in other languages.
To get around this Java supports a mechanism called the Java Native Interface [JNI], which allows modules written in other languages and compiled into dynamic link libraries (typically Windows .dll or Unix .so files) to be dynamically loaded and called by Java. Calling C routines or Fortran routines using the JNI is fairly straightforward. Making C++ objects available to Java programs is not so easy however, due to problems with different C++ compiler's conventions for name-mangling. Interfacing from Java to C++ usually involves writing a large amount of code by hand to glue the C++ object to its Java counterpart. Some utilities are available to help with this, such as J2C++ available from IBM's Alphaworks site.
Among other things that Root adds to C++ is a powerful run-time type information system similar to that built-in to Java. By exploiting some of the mechanisms put in place within Root to support this run-time type information, it should be possible to automatically build the "glue" code necessary to interface between Java and Root.
One problem associated with mapping from C++ to Java is that C++ supports multiple inheritance of classes while Java does not. In this proposal however, Root classes are mapped to Java interfaces, and Java interfaces do support multiple inheritance, so this should not pose a problem. Another problem is that C++ supports templates whereas Java does not. This problem has been ignored for the time being, but should be addressable by converting each mapping of a C++ template class to a particular concrete class onto a differently named Java class.
A set of Java classes would be created which would make the base functionality of Root available to Java. This would include Java interfaces to objects such as TFile, TTree etc.
For user-defined classes an extended version of rootcint, would be used to automatically:
Due to the differences in C++ and Java it is unlikely that this could be made to work for absolutely any user-defined class, but if the class obeys some reasonable set of constraints (to be defined) it should be possible to automatically generate all of the necessary glue code.
The extra C code would be linked into the normal dynamic load library (.dll or .so file) built by Root so that the same library could be loaded into Root (using gSystem.Load) or into Java (using Java's System.loadLibrary()).
To test the feasibility of this proposal we have taken the user-defined classes in the Root Tutorial (http://root.cern.ch/root/CintGenerator.html#DictionaryIO ) and have built the code to interface them to Java using the methodology described above (but doing the work by hand rather than automatically via rootcint). Currently we are able to open a TFile from Java, read the events in a verify that we can access the Event and Track classes from Java. The main routine to read and analyse the Root data from Java looks like this:
import hep.root.*; // Import Root classes
public class Main
{
public static void main(String[] argv)
{
TRootImpl.loadLibrary("Event"); // load library containing user classes
// assume argv[0] contains the file to open
TFile f = new TFileImpl(argv[0]);
TTree t = (TTree) f.Get("T");
int nEvents = t.GetEntries();
for (int i=0; i<nEvents; i++)
{
int n = t.GetEvent(i);
System.out.println("Read Event "+n);
// Code to manipulate event goes here
}
}
}
The complete set of Java and C++ routines needed to make this work can be found here.
Tony Johnson - Last Modified: Tuesday, January 13, 2004