[Soot-list] Lazy loading of .class files
Niklas Therning
niklas at therning.org
Mon Jan 2 03:15:07 EST 2012
Hi,
I'm working on an ahead of time (AOT) compiler for java bytecode. What
I'm doing is to compile java bytecode into LLVM bitcode and then use the
LLVM tools and GCC to get an x86/arm/whatever object file that can be
linked into a native executable. I'm basing the standard classes
(java.*, javax.*, etc) on the Apache Harmony project and I've written a
small runtime in C. As of now I'm able to produce x86/x86-64 Linux
executables that work for simple Java programs. I'm also working on an
Eclipse plugin which extends the Eclipse JDT with incremental
compilation of Java to native code using my AOT compiler.
I'm using Soot in the first stage (JVM byte code -> LLVM bitcode) since
Soot's register based Jimple representation is closer to LLVM's bitcode
representation than the byte code of the JVM. And I get Soot's
optimization for free which is very nice! Here's how I'm initializing Soot:
soot.G.reset();
Options.v().set_output_format(Options.output_format_jimple);
Options.v().set_include_all(true);
Options.v().setPhaseOption("jap.npc", "enabled:true");
Options.v().setPhaseOption("jap.abc", "enabled:true");
Options.v().set_print_tags_in_output(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_soot_classpath(getSootClasspath(clazzes));
for (Clazz clazz : clazzes.list()) {
SootClass c =
Scene.v().loadClassAndSupport(clazz.getClassName());
c.setApplicationClass();
}
Scene.v().loadNecessaryClasses();
(clazzes handles the classpath entries and Clazz is a wrapper around a
.class entry in a JAR file or a .class File in a directory)
My problem is that the code above takes about 5 seconds on my machine.
The JRE classes from Harmony are always loaded by the code above so even
if I'm compiling a single .class file more than 3000 .class files from
Harmony have to be loaded by Soot. I would like Soot to load the
required classes lazily when they are needed. This is especially
important when I run the compiler from within my Eclipse plugin.
I've tried to replace the loop and call to loadNecessaryClasses() above
with the following code:
for (Clazz clazz : clazzes.list()) {
SootClass c = Scene.v().loadClass(clazz.getClassName(),
SootClass.DANGLING);
c.setApplicationClass();
}
That doesn't work out of the box so I've patched Soot 2.4 in a few
places. I had to change the checkLevel() method in SootClass to
public void checkLevel( int level ) {
if( resolvingLevel < level ) {
SootResolver.v().resolveClass(this, level);
// String hint = "\nIf you are extending Soot, try to add the
following call before calling soot.Main.main(..):\n" +
//
"scene().addBasicClass("+getName()+","+levelToString(level)+");\n" +
// "Otherwise, try whole-program mode (-w).";
// throw new RuntimeException(
// "This operation requires resolving level "+
// levelToString(level)+" but "+name+
// " is at resolving level
"+levelToString(resolvingLevel) + hint);
}
}
The problem is that even though Soot doesn't complain any longer and I
get Jimple code out of Soot the Jimple looks different and behaves
differently when run than what I get when I use the slower initialization.
So, how can I patch Soot to make lazy loading of required classes
possible without changing the produced Jimple? I know too little yet
about the Soot code to work this out on my own. Any help would be much
appreciated.
Regards,
Niklas Therning
More information about the Soot-list
mailing list