kilim.KilimException: Check classpath. Method foo/bar.yield()V could not be located
at kilim.analysis.MethodFlow.visitMethodInsn(MethodFlow.java:204)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at kilim.analysis.ClassFlow.analyze(ClassFlow.java:81)
at kilim.analysis.ClassWeaver.weave(ClassWeaver.java:50)
at kilim.analysis.ClassWeaver.<init>(ClassWeaver.java:41)
at org.demos.Demo.compile(Demo.java:114)
In this problem I've got a task that calls yield. Notice that the same runtime has been able to compile the class, and now I'm weaving it (in memory). It has kilim.Task loaded and all should be set.Is it possible to show the code of your "Demo" program, or is it
inextricably linked with other non-related portions of your work? A
simplified test case would be much appreciated.
--ram.
//node -> java
Map<String, String> codes = create_runner( 1, 1, "", nodes );
//java -> class
DiagnosticCollector<JavaFileObject> diags = new DiagnosticCollector<JavaFileObject>();
CharSequenceCompiler csc = new CharSequenceCompiler(Demo.class.getClassLoader(), null);
Map<String, Class> classes = csc.compile(codes, diags);
// class -> weaved
for (Map.Entry<String, Class> e : classes.entrySet()) {
InputStream bcode = e.getValue().getClassLoader()
.getResourceAsStream(e.getKey() + ".class");
ClassWeaver weaver = new ClassWeaver(bcode, Detector.DEFAULT);
List<ClassInfo> cis = weaver.getClassInfos();
if (cis.size() > 0) {
for (ClassInfo ci : cis) {
/*
* OutputStream o = jfo.openOutputStream();
* o.write(ci.bytes); o.close();
*/
}
}
}
> Quickfix solution: In your generated code, make static calls fully
> qualified.
>
> That is, instead of calling yield(), make it Task.yield().
>
While this is correct, the solution is useless. If, instead of
yield(), you were to call another method foo() defined in the same
class, you'd have the same error because the weaver's classloader
depends on the reflection framework to load the pre-weave class and to
provide signatures for all the methods.
Clearly, the correct solution is to define a classloader for the
weaver, then load the pre-woven classes into the classloader. That
way, it can find a signature for MyTask.foo() while it is weaving
MyTask's bytes.
Watch this space for the solution ..
---sriram.
at org.objectweb.asm.ClassReader.a(Unknown Source)
at org.objectweb.asm.ClassReader.<init>(Unknown Source)
at kilim.analysis.ClassFlow.<init>(ClassFlow.java:41)
at kilim.analysis.ClassWeaver.<init>(ClassWeaver.java:40)
at org.demos.Demo.compile(Demo.java:114)
package analysis;
import java.util.*;
import org.uncommons.maths.random.*;
import org.joda.time.*;
import kilim.*;
public class random extends kilim.TaskWrapper {
public FwdMailBox<TSPoint> output = new FwdMailBox<TSPoint>();
public void execute() throws Pausable{
Random r = new XORShiftRNG(new byte[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20});
double stddev = 2;
double last = 50;
long t = new DateMidnight().getMillis();
int i = 100000;
int c = 0;
while(i-- > 0){
double v = last += r.nextDouble()*stddev;
last= v;
t += 1000*60*60*24l;
output.put(new TSPoint(t, v));
c++;
if(i%10 == 0)
Task.yield();
}
output.put(TSPoint.END);
calculated=true;
}
}
kilim.KilimException: Check classpath. Method analysis/FwdMailBox.put(Ljava/lang/Object;)V could not be located
at kilim.analysis.MethodFlow.visitMethodInsn(MethodFlow.java:204)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at kilim.analysis.ClassFlow.analyze(ClassFlow.java:81)
at kilim.analysis.ClassWeaver.weave(ClassWeaver.java:50)
at kilim.analysis.ClassWeaver.<init>(ClassWeaver.java:41)
at org.demos.Demo.compile(Demo.java:115)
Here's the current situation, and the reason for the problems. When
presented with a method invocation, the weaver calls Class.forName
(via RuntimeMirror) to get the method's signature. Since the weaver
is in the classpath, it is loaded by the system classloader, which
means that it relies on the system classloader to load other classes,
which in turn means that the system relies on the classpath to locate
all the files that need to be woven. In your case, it won't find the
new classes, hence the problems.
The solution is to not rely on the classloader at all. Clearly, the
weaver has access to the bytecode, so it can figure out the method
signatures itself. The complication is that the weaver cannot process
one file at a time. For example, if a class relies on an interface,
one must make sure that the interface is processed (and its method
signatures made available) before the class is processed. A slightly
more complex case is that of circular class references. This means
that the weaver requires two passes, one to absorb all the signatures
of all the classfiles presented to it, then to do the validation and
weaving step. The good thing is that it does not require any
classloader.
Given this, if you can infer what to do from the description above,
feel free to volunteer :) I'll get to it myself in the next couple of
days, but can't promise urgency.
--sriram.
Here's the current situation, and the reason for the problems. When
presented with a method invocation, the weaver calls Class.forName
(via RuntimeMirror) to get the method's signature. Since the weaver
is in the classpath, it is loaded by the system classloader, which
means that it relies on the system classloader to load other classes,
which in turn means that the system relies on the classpath to locate
all the files that need to be woven. In your case, it won't find the
new classes, hence the problems.
The solution is to not rely on the classloader at all. Clearly, the
weaver has access to the bytecode, so it can figure out the method
signatures itself. The complication is that the weaver cannot process
one file at a time. For example, if a class relies on an interface,
one must make sure that the interface is processed (and its method
signatures made available) before the class is processed. A slightly
more complex case is that of circular class references. This means
that the weaver requires two passes, one to absorb all the signatures
of all the classfiles presented to it, then to do the validation and
weaving step. The good thing is that it does not require any
classloader.
Given this, if you can infer what to do from the description above,
feel free to volunteer :) I'll get to it myself in the next couple of
days, but can't promise urgency.
On tiistaina 19. huhtikuuta 2011 at 19.08, Kresten Krab Thorup wrote:
I handle these cases in erjang (multiple class loaders, runtime weaving). Basically you need to introduce a level of indirection so that the weaver does not try to classload it's dependent classes, but acces the meta information through a "class info handler".