Re: [Java] Function Binding Redux (long post)
John Moeller <[email protected]>
| Newsgroups | gmane.comp.lib.boost.langbinding |
|---|---|
| Message-ID | <[email protected]> |
Rene Rivera wrote: > John Moeller wrote: > >> 2b. Generate the same, except directly in bytecode, and put the result >> in a class file. >> >> Same advantages as (2a), except without the compile time, but the >> drawback that we'd have to maintain bytecode generation (probably not a >> big deal, though). > > There are bytecode generation libraries out there that would make this > even less of a big deal. Right, like BCEL and such. I wanted to feel out your thoughts on such a dependency. Regardless, I think we all agree now that creating bytecode is one of the least of our hurdles here. >> 3. Do the same as (2b), but load the class at runtime with a special >> class loader. This is (from what I understand) the crux of Rene's idea, >> and the most initially appealing. > > Yes, that's what I meant. But using a class loader is only an idea. More > briefly I would want to create the Java "code" and have it bound to the > native code when the library is loaded. It would work something like: That's essentially the process that I'm referring to. By the way, just to avoid confusion, let me define "natural usage" as: in source, referring to a class by name and calling its methods or accessing its fields with regular language syntax, as opposed to using a discovery API or other indirect semantics to call methods or access fields. > When the library is loaded (System.loadLibrary) during the JNI_OnLoad > <http://tinyurl.com/2dmsh8>: > > * It creates bytecode for the classes in the binding and loads it > into the JVM with DefineClass <http://tinyurl.com/2bjzmz>. This isn't really all that different from explicitly loading a class in Java code, and results in the same problems with natural usage. That is, you must get a generated class defined before the classes that use it are loaded. This basically means that if you want to be *assured* that no NoClassDefFoundError will be thrown, you must get the generated class defined *before* the main app class is even loaded. That means a launcher of some sort. Loading a generated class in the entry class' static initializer won't even work, because a JVM is allowed to load any dependent classes for the class that it is currently loading, before it runs any code in that class. That means (potentially) that it could attempt to load the entire retinue of program classes before it runs the static initializer of the entry point class. > * It binds the Java native methods to the C++ functions with > RegisterNatives <http://tinyurl.com/2bjzmz>. > > That allows for the distribution of only the shared library (although it > might be possible to work something equivalent for the embedded use > case). All users need to do is call System.loadLibrary. Sure. I'd like to see any glue code be slim anyway. However, I'd like to point out that if there is any bytecode that can be factored out, it may make more sense to have it in Java classes, but I don't know at this point. I don't see that distributing a jar file along with the library would be all that onerous, but we could aim to avoid it, if you feel it would better suit clients. Another possibility is to let the client package the utility classes within their own jar files. > What I don't > know is how the Java compiler could be made to work without actual > *.class files. You can't (at least not with the Sun Java compiler). You would need stub classes in lieu of the generated classes. Which makes the interface idea more appealing, at least to me. >> I've been trying to think of ways to make this work, but there are some >> major compromises: > > Hm, I think your three points aren't relevant to what I just mentioned > above so I'm refraining from comment until proven otherwise ;-) Ok, I'll try to defend their relevance: 1. I tried an experiment whereby I explicitly loaded class A in the static initializer of class B, and used class A naturally in class B's main method. The main method threw a NoClassDefFoundError, presumably because it tried to load class A to ensure that any bytecode in class B could be run. The alternative is to use the class through the Reflection API. That is, define the class, find its main method, and invoke it, which is all pretty gross, and you have to catch a lot of kinds of exceptions to do it. As I tried to explain above, you won't avoid that with an explicit call to System.LoadLibrary, unless you call it from a launcher class that also explicitly loads the main class. Don't get me wrong; I would, in all honesty, love to be wrong on this one. It would make things a lot easier. But I suspect that we won't get the easy way out. 2. I'll concede this point partially, because you're talking about using the native DefineClass, which lets you set the loader to the app class loader, so you can rid yourself of classpath restrictions that way. You would still need a launcher class to get around point (1), though. 3. Not relevant to what you talked about, but that only makes me happy. I'd like to avoid hacks where we can. Anyway, that's why I suggested the interface approach. It's not foreign to Java programmers, and it would ease a lot of these problems. -- John Moeller [email protected] ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/