Comments
Not everyone reads comments, and as a general rule there aren't many here, but my last post is a bit of an exception. That will probably be the norm now, as Rob and Andrew don't get to make comments in person any more.
Andrew suggested that I look at Michael Grove's OWL Class Loader for Mindswap. I really like what it does, but I have two comments to make.
The first comment is how it relates to what I'd like to do. It's not quite the same thing, as it relies on the classpath of the current JVM in order to find the class files. That's great, but I'm actually thinking about a system that stores a blob with the classfile image. The classloader then loads the class out of the database for instantiation. Why do this instead of relying on the filesystem? Well it is far more dynamic. It allows new classes to be brought in a runtime. This means that classes could be transferred from a remote location, or generated on-the-fly.
I like the idea of generating a class on the fly. That way a class could be described in OWL (or UML) and then built internally. It could then be stored as a blob until needed.
Now only if Sun had chosen to make those compiler classes available in Java 1.5. I read an interview a couple of years ago where James Gosling was talking about making available those classes which model the language tree, along with methods for emitting the corresponding binaries. Obviously, that never happened.
Maybe I can find something like it in an open source compiler implementation, like Kaffe or Jikes. On the other hand, JavaCC probably does exactly what I want, but I'll have to check. It compiles from text to binary, but I want to be able to create an edit the parse tree directly, with no language involved. Of course there are several compiler projects which will do this, but most of them don't give public access to the internal tree.
TBox and ABox
The second comment I have about the OWL Class Loader has very little to say on practicalities. That is to say, the project works exactly as advertised, and meets its objectives perfectly, but I disagree with the structure.
As it stands, the RDF does not appear to be "OWL" at all, and is instance data instead. It is not entirely bereft of ontology data, but it mixes it in. Take the example of the following:
<cl:Object rdf:ID="myHash">
<cl:hasClass>java.util.Hashtable</cl:hasClass>
<cl:hasConstructor>
<cl:Constructor>
<cl:parameterList rdf:parseType="daml:collection">
<cl:Parameter>
<cl:hasClass>int</cl:hasClass>
<cl:withValue>20</cl:withValue>
</cl:Parameter>
<cl:Parameter>
<cl:hasClass>float</cl:hasClass>
<cl:withValue>1.2</cl:withValue>
</cl:Parameter>
</cl:parameterList>
</cl:Constructor>
</cl:hasConstructor>
</cl:Object>
From an ontology perspective (TBox), this code describes a class, with fully qualified name of java.util.Hashtable
, and a constructor which accepts two parameters (an int
and a float
). However, there is instance data mixed in here too, such that a single instance of this class can be constructed. In fact, the whole structure doesn't seem to describe the class so much, as describe an instance of a class.From a data perspective (ABox), this code simply references a class that was defined elsewhere, and creates an instance using one of the constructors (the one that takes an
int
and a float
). Rather than using the predicates hasConstructor
and hasClass
to define the class, it uses these predicates to uniquely identify a class that was defined elsewhere (in the class library).The giveaway here is when you ask the question, "What is the syntax to define a second instance?" This code all needs to be repeated. This would not happen in an ontology.
So why go on about this? Well I think the name is inappropriate. It really looks more like an RDF Class Loader instead of an OWL Class Loader. The documentation keeps referring to OWL code, when it is really RDF code.
Perhaps in the sort of systems that Michael is using this really dictates behaviour, so describing class definitions like this could be at a slightly higher meta-level than usual instance code, but it isn't all the way up at the OWL level. Maybe he needs the MOF. :-)
4 comments:
You can load the classes (or bytes from you're database) at runtime and add them to the current system class loader (there is some code posted by Sun for doing this).
Have you looked at dynamic proxies (java.lang.reflect.Proxy)? they are really cool (they are my shiny new *golden* hammer). A Proxy allows you to return an Object (at runtime) that satisfies a set of interfaces/classes. You get full control of method invocation/binding through the invocation handler interface (java.lang.reflect.InvocationHandler).
I implemented a service with multiple inheritance (sort of) using a Proxy - we wanted a single Service (business delegate) that was a composite of all other services. Multiple dispatch should also be pretty easy to implement using a proxy and name mangling.
Do you know if it is possible to create classes/interfaces at runtime? I guess you could always create the code, compile it and load it into you're application... But that would be a bit of a hack. It would be cool to be able to create Java interfaces from an ontology at runtime and expose them using a Proxy, external applications could generate the same interfaces and they could then trade Objects with one another.
> You can load the classes (or bytes from you're
> database) at runtime and add them to the current
> system class loader (there is some code posted by
> Sun for doing this).
Ahh Grasshopper... I have been doing just this for many years. :-)
Somewhere or another I have a piece of code that takes hexadecimal on stdin, converts it to binary, and uses a classloader to turn it into a runnable class, which then gets run. The idea was to take the text file which was printed on the back of the Plugged In T-Shirt and make it run. It worked fine.
I've been meaning to look at Proxies, but I've only looked at the overview, rather than the nitty-gritty. Thanks for the extra detail. I'm hoping to get to them shortly.
Anyway, I obviously wasn't clear in what I wanted. I want to have a class library which can let me build executable code without having used any text. It might be illustrated best with an example.
Assume I want to be able to build a class (call it "X"), and have a function in it (call it "xxx") with a boolean parameter (I'll call it 'y'). If that parameter is true it will return "yes", otherwise it will return "no". The equivalent code is:
public class X {
public String xxx(boolean y) {
if (y) return "yes";
return "no";
}
}
I want a class library which lets you build all of this as a tree structure. Some hypothetical code might be:
ClassObj c = factory.generateClass("X", ENUM_PUBLIC);
MethodObj m = c.addMethod("xxx", ENUM_PUBLIC, "java.lang.String", new Object[] {Integer});
Statement s = m.addIf(m.getParam(0));
s.getTrue().append(m.return("yes"));
s.getFalse().append(m.return("no"));
byte[] classdata = c.emitBytes();
This is the kind of thing that a compiler does after it has parsed the source code.
With Sun's classes all you can do is generate the code as text, and then invoke the compiler. At least in Java 1.5 they give you easier access to the compiler (see the com.sun.tools.javac.Main class). I'm guess that this was done for Tomcat.
That would be really cool.
I think there are some class manipulation/hack libraries out there. I haven't used any before, but a friend of mine was telling me about them. They make modifications to the class' byte code.
I just wish I knew Java byte code :D
There are quite a few out there. Here is a nice list of open source byte code manipulation libraries:
http://java-source.net/open-source/bytecode-libraries
This is one of the first I looked at: the API looks similar to what you were describing (eg. addMethod() - declareMethod() ):
http://serp.sourceforge.net/docs/serp/bytecode/BCClass.html
Post a Comment