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/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.