diff options
Diffstat (limited to 'user/jkoenig/java')
-rw-r--r-- | user/jkoenig/java/discussion.mdwn | 559 | ||||
-rw-r--r-- | user/jkoenig/java/java-access-bridge.mdwn | 92 | ||||
-rw-r--r-- | user/jkoenig/java/proposal.mdwn | 629 |
3 files changed, 1280 insertions, 0 deletions
diff --git a/user/jkoenig/java/discussion.mdwn b/user/jkoenig/java/discussion.mdwn new file mode 100644 index 00000000..352f6d62 --- /dev/null +++ b/user/jkoenig/java/discussion.mdwn @@ -0,0 +1,559 @@ +[[!meta copyright="Copyright © 2011 Free Software Foundation, Inc."]] + +[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable +id="license" text="Permission is granted to copy, distribute and/or modify this +document under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no Invariant +Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license +is included in the section entitled [[GNU Free Documentation +License|/fdl]]."]]"""]] + +[[!toc]] + + +# General + +Some [[tschwinge]] comments regarding your proposal. Which is very good, if I +may say so again! :-) + +Of course, everyone is invited to contribute here! + +I want to give the following methodology a try, instead of only having +email/IRC discussions -- for the latter are again and again showing a tendency +to be dumped and deposited into their respective archives, and be forgotten +there. Of course, email/IRC discussions have their usefulness too, so we're +not going to replace them totally. For example, for conducting discussions +with a bunch of people (who may not even be following these pages here), email +(or, as applicable, the even more interactive IRC) will still be the medium of +choice. (And then, the executive summary should be posted here, or +incorporated into your proposal.) + +Also, if you disagree with this suggested procedure right away, or at some +later point begin to feel that this thing doesn't work out, or simply takes too +much time (I don't think so: writing emails takes time, too), just say so, and +we can reconsider. + +Of course, as this wiki is a passive medium rather than an active one as IRC +and email are, it is fine to send notices like: *I have updated the wiki page, +please have a look*. + +One idea is that your proposal evolves alongside with the ongoing work, and +represents (in more or less detail) what has been done and what will be done. +Also, we can hopefully use parts of it for documentation purposes, or as +recipes for similar work (enabling other programming languages on the Hurd, for +example). + +For this, I suggest the following procedure: as applicable, you can either +address any comments in here (for example, if they're wrong :-), or if they +require further discussion; think: *email discussion*), or you can address them +directly in your propoal and remove the comments from here at the same time +(think: *bug fix*). + +Generally, you can assume that for things I didn't comment on (within some +reasonable timeframe/upon asking me again) that I'm fine with them. Otherwise, +I might say: *I don't like this as is, but I'll need more time to think about +it.* + +There is also a possibility that parts of your proposal will be split off; in +cases where we think they're valuable to follow, but not at this time. (As you +know, your proposal is not really a trivial one, so it may just be too much for +one person's summer.) Such bits could be moved to [[open_issues]] pages, +either new ones or existing ones, as applicable. + + +# GSoC Site Discussion + + * Discussion items from + <http://www.google-melange.com/gsoc/proposal/review/google/gsoc2011/jkoenig/1> + should be copied here: + + * technical bits (obviously); + + * also the *why do we want Java bindings* reasoning; + + * CLISP findings should also be documented somewhere permanently. + + * We should probaby open up a *languages for Hurd* section on the web + pages ([[!taglink open_issue_documentation]]). + + +# Java Native Interface (JNI) + + * <http://en.wikipedia.org/wiki/Java_Native_Interface> + * <http://download.oracle.com/javase/7/docs/technotes/guides/jni/> + * <http://java.sun.com/products/jdk/faq/jnifaq.html> + * <http://java.sun.com/docs/books/jni/> + + +## Java Native Access (JNA) + + * <http://jna.java.net/> + * <https://github.com/twall/jna#readme> + +This is a different approach, and *while some attention is paid to performance, +correctness and ease of use take priority*. + +As we plan on only having a few native methods (for invoking `mach_msg`, +essentially), JNA is probably the wrong approach: portability and ease of use +is not important, but performance is. + +## Compiled Native Interface (CNI) + + * <http://gcc.gnu.org/onlinedocs/gcj/About-CNI.html> + * <http://per.bothner.com/papers/UsenixJVM01/CNI01.pdf> + +Probably faster than JNI, but only usable with GCJ. + +> Given that we have very few JNI calls, +> it might be interesting to take a "dual" approach +> if CNI actually improves performance +> when compiling to native code. +> --[[jkoenig]] 2011-07-20 + +# IRC, freenode, #hurd, 2011-07-13 + +[[!tag open_issue_documentation]] + + <jkoenig> Yes, I guess so. Maybe start investigating mig because it may + have repercussions on what the best approach would be for some aspects of + the Mach bindings. + <tschwinge> I still think that making MIG emit Java code is not too + difficult, once you have the required Java infrastructure (like what + you're writing at the moment). + <tschwinge> On the other hand, if there's another approach that you'd like + to use, I'm not trying to force using MIG. + <braunr> i still have a problem understanding your approach + <braunr> at which level are your bindings located ? + <jkoenig> I expect mig it will be the easiest route, but of course possibly + it won't. + <tschwinge> jkoenig: Yeah, be give some high-level to low-level overview? + <jkoenig> ok, so + <jkoenig> at the very core, low-level, we have a very thin amount of JNI + code to access (proper) system calls. + <jkoenig> by "proper" I mean things like mach_task_self, mach_msg and + mach_reply_port, which are actually system calls rather than RPCs to the + kernel. + <braunr> right + <jkoenig> at this level, we manipulate port names as integers, and the + message buffers for mach_msg are raw ByteBuffers (from the java.nio + package) + <jkoenig> actually, so-called /direct/ ByteBuffers, which are backed by + memory allocated outside of the Java heap, rather than as a byte[] array + <jkoenig> we can retreive the pointer from the JNI code and use the buffer + directly. + <jkoenig> (so, good for performance and it's also portable.) + <braunr> ok + <braunr> i'm more interested in the higher level bindings :) + <jkoenig> ok so, higher up. + <jkoenig> design goal from my proposal: "the memory safety of Java should + be maintained and extended to Mach primitives such as port names and + out-of-line memory regions" + <jkoenig> so integer port names are not "safe" in the sense that they can + be forged and misused in all kinds of way + <jkoenig> which is why I have a layer of Java code whose job is to wrap + this kind of low-level Mach stuff into safe abstractions + <jkoenig> and ideally the user should only use these safe abstractions. + <tschwinge> (Not to restrict the programmer, but to help him write correct + code.) + <jkoenig> right. + <braunr> so you can't use mach RPCs directly + <jkoenig> tschwinge, also to actually restrict them, in a Joe-E / + object-capability context, but that's not the primary concern right now + ;-) + <braunr> or you force your wrappers to have these abstractions as input + <jkoenig> braunr, well, actually at this level you still have Mach RPC + <jkoenig> but for instance, port names are encapsulated into "MachPort" + objects which ensure they are handled correcly + <tschwinge> As I understand it, you use these abstractions to prepare a + usual mach_msg message, and then invoke mach_msg. + <braunr> ok + <jkoenig> and message buffers are wrapped into "MachMsg" objects which both + help you write the messages into the ByteBuffer and prevent you from + doing funky stuff + <jkoenig> and ensure the ports which you send/receive/pseudo-receive after + an error/... are deallocated as required, etc. + <braunr> what's the interface to use IPC ? + <tschwinge> Is MIG doing that, too, I think? (And antrik once found some + error there, which is still to be reviewed...) + <jkoenig> braunr, so basically as a user you would be free to use either + one of these layers, or to use MIG-generated classes which would + construct and exchange messages for you using the second (safe) layer. + <braunr> ok, let's just finish with the low level layer before going + further please + <jkoenig> tschwinge, MIG does some type checking on the received message + and saves you the trouble of constructing/parsing them yourself, but I'm + not sure about how mach_msg errors are handled + <braunr> what are the main methods of MachMsg for example ? + <jkoenig> braunr, you may want to have a look at + http://jk.fr.eu.org/hurd-java/doc/html/classorg_1_1gnu_1_1mach_1_1MachMsg.html + <braunr> right, sorry + <braunr> grabbed the code at work and forgot here + <jkoenig> and also + https://github.com/jeremie-koenig/hurd-java/blob/master/HelloMach.java + which uses it + <jkoenig> but roughly, you'd use setRemotePort, setLocalPort, setId to + write your message's header + <jkoenig> then use one of the putFoo() methods to add data items to the + message + <braunr> ok, the mapping with the low level C interface is very clear + <braunr> that's good for me + <jkoenig> the putFoo() methods would write the appropriate type + descriptors, then the actual data. + <braunr> we can go on with the MiG part if you want :) + <jkoenig> right, + <jkoenig> so here you may want to look at the UML class diagram from + http://www.bddebian.com/~hurd-web/user/jkoenig/java/proposal/ + <jkoenig> so in the C case, mig generates 3 files + <jkoenig> a header file which has the prototypes of the mig-generated + stubs, + <jkoenig> a *User.c which has their actual implementation + <jkoenig> and a *Server.c which handles demultiplexing the incoming + messages and helps with implementing servers. + <jkoenig> so we would do something along these lines, more or less: + <jkoenig> mig would generate the code for a Java interface in lieu of the + *.h file. + <jkoenig> a generated FooUser class would implement this interface by doing + RPC + <jkoenig> (so basically you would pass a MachPort object to the + constructor, and then you could use the resulting object to do RPC with + whatever is on the other end) + <jkoenig> and the generated FooServer class would do the opposite, + <braunr> ok + <braunr> issues with threads ? + <jkoenig> you would pass an object implementing the Foo interface to the + constructor, + <braunr> i'm guessing the demux part may have to create threads, right ? + <jkoenig> and the resulting object would handle messages by using the + object you passed. + <jkoenig> braunr, right, so that would be more a libports kind of code, + <braunr> the libports-like library, i see + <jkoenig> to which you could pass Server objects (for instance the + FooServer above), and it would handle incoming messages. + <braunr> how is message content mapped to a java interface ? + <jkoenig> this would be determined from the .defs files and MIG would + generate the appropriate code, hopefully. + <braunr> so the demux part would handle rpc integer identifiers ? + <jkoenig> right. + <braunr> but hm + <jkoenig> also mapping .defs files to Java interfaces might prove to be + tricky. data types conversion and all + <antrik> tschwinge: my mamory is rather hazy. IIRC the issue was that the + MIG-generated stubs deallocate out-of-line port arrays after the + implementation returns, before returning to the dispatcher + <braunr> i'll just overlook this specific implementation detail + <jkoenig> but we could use some annotation-based system if we need to + provide more information to generate the java code. + <antrik> but the Hurd (or rather glibc) RPC handling also automatically + deallocates everything if an error occurs + <antrik> so I changed the MIG code to deallocate only when no error occurs + <braunr> jkoenig: ok, we'll talk about that when there is more progress and + you have a better view of the problem + <antrik> at that time I was pretty sure that this is a correctly working + solution, but it always seemed questionable conceptually... however, I + wasn't able to come up with a better one, and nobody else commented on it + <braunr> antrik: shouldn't the hurd be changed not to deallocate something + it didn't allocate in the first place ? + <antrik> braunr: no, the server has to deallocate stuff before returning to + the client. the request message is destroyed before returning the reply. + <tschwinge> jkoenig, braunr: That's what I had in mind where MIG might be a + bit awkward. Then we can indeed either add annotations to the .defs + files, or reproduce them in some other format. That's some work, but + it's mostly a one-time work. + <tschwinge> After all, the RPC interface is a binary one, and there may be + more than one API for creating these messages, etc. + <antrik> jkoenig: actually, at least in the Hurd, server-side and + client-side headers are separate -- so MIG actually creates four files + <jkoenig> tschwinge, wrt to annotations I was more thinking about Java + ones, such as: @MIGDefsFile("mach/task.defs") @MIGCType("task_t") public + interface Task { } + <jkoenig> antrik, oh, ok, it makes sense. + <braunr> jkoenig: anything else ? + <jkoenig> braunr, nothing that I can think of + <braunr> ok + <antrik> tschwinge: I think it would be a *very* bad idea to introduce + redundancy regarding RPC definitions + <braunr> thanks for the tour :) + <antrik> (the _request.defs/_reply.defs mess is bad enough...) + <jkoenig> did I speak about the "Unsafe" pseudo-exception? that's + interesting :-) + <tschwinge> jkoenig: Also, virtual memory abstractions? + <braunr> jkoenig: you didn't + <tschwinge> antrik: Well, then we could create some other super-format. + But that's just a detail IMO. + <jkoenig> ok, so wrt virtual memory, a page we received can be wrapped with + some JNI help into a (direct) ByteBuffer object. + <jkoenig> deallocating sent pages will be tricky, though. + <tschwinge> antrik: To put it this way: for me the .defs files are just one + way of expressing the RPC interfaces' contracts. (At the same time, they + happen to be the actual reference for these, too. But the specification + itself could just as well be a textual one.) + <jkoenig> on approach I've been thinking about would be to "wrap" the + ByteBuffer object into an object which has the sole reference to it, so + that when it's deallocated the reference can be replaced with "null", and + further attempts to access the buffer would throw exceptions. + <braunr> sounds reasonable + <jkoenig> but that's still in flux in my head, we may end up needing our + own implementation of ByteBuffer-like objects. + <tschwinge> The problem being that there is no mechanism to ``revoke'' an + object once a reference to it has been shared. + <jkoenig> right. + <tschwinge> A wrapper is one possibility indeed. + <antrik> tschwinge: they are called interface *definitions* for a reason + :-) + <tschwinge> This is a very similar problem as with capabilities when there + is no revoke operation for these, too. + <tschwinge> antrik: Yes, because they define MIG's input. :-P + <tschwinge> Isn't that what is called a membrane in the capability world? + <antrik> I do not say that we have to consider the format of the .defs to + be set in stone; but I do insist on using a canonical machine-parsable + source for all language bindings + <tschwinge> attenuation + <jkoenig> tschwinge, you mean the revokable proxy contruct ? (It's the same + principle indeed) + <tschwinge> A common design pattern in object-capability systems: given + one reference of an object, create another reference for a proxy object + with certain security restrictions, such as only permitting read-only + access or allowing revocation. The proxy object performs security checks + on messages that it receives and passes on any that are allowed. Deep + attenuation refers to the case where the same attenuation is applied + transitively to any + <tschwinge> objects obtained via the original attenuated object, + typically by use of a "membrane". + <tschwinge> http://en.wikipedia.org/wiki/Object-capability_model + <tschwinge> Yes. + <tschwinge> Good. I understood something. ;-) + <tschwinge> antrik: OKAY! :-P + <tschwinge> jkoenig: And hopefully the JVM will optimize away all the + additional indirection... :-D + <tschwinge> jkoenig: Is there anything more to say about the VM layer? + <jkoenig> tschwinge, "hopefully", yes :-) + <tschwinge> Like, the data that I'm sharing -- is it untyped, isn't it? + <jkoenig> tschwinge, you mean that within the received/sent pages ? + <tschwinge> Yes. + <tschwinge> But that'S how it is, indeed. + <jkoenig> well actually the type descriptor should indicate what they + contain. + <tschwinge> I cannot trust anything I receive from externally. + <jkoenig> it's most often used for MACH_MSG_TYPE_CHAR items I guess, and it + will be type checked when retreive + <tschwinge> Yeah, and that then just *is* arbitrary data, like a block read + from a disk file. + <jkoenig> you would have something like: ByteBuffer + MachMsg.getBuffer(MachMsg.Type expected), and MachMsg would check the + type descriptor against that which you specified + <tschwinge> Or a packet transmitted over the network. + <tschwinge> OK, yes. + <antrik> jkoenig: in theory ints should be used quite often too. the whole + purpose of the type descriptors is to allow byte order swapping when + messages are passed between hosts with different architecture... + <jkoenig> tschwinge, right, except for out-of-line port arrays, which need + to be handled differently obviously. + <antrik> (which is totally irrelevat for our purposes -- especially since + the actual network IPC code doesn't exist anymore ;-) ) + <jkoenig> antrik, oh, interesting + <tschwinge> Yes, that was one original idea. + <jkoenig> actually my litmus test for what the bindings should be, is you + should be able to implement such a proxy in Java :-) + <tschwinge> antrik: And hey, you now have processors that can switch + between different modes during runtime... :-) + <jkoenig> (although arguably that's a little bit ambitious) + <braunr> tschwinge: there should be bits in page tables to indicate the + endianness to use on a page .. :) + <tschwinge> Hehe! + <tschwinge> jkoenig: Don't worry -- you're already known for ambitious + projects. One more can't hurt. + <jkoenig> Also, actually the word size is not something that I've been able + to abstract so far, so I'll be hardcoding little-endian 32 bits for now. + <braunr> why is that ? + <antrik> some of the Hurd RPC break the idea anyways BTW + <jkoenig> the org.vmmagic package (from Jikes RVM and JNode) could help + with that, but GCJ does not support it unfortunately (not sure about + OpenJDK) + <jkoenig> braunr, Java does not allow us to define new unboxed types + <braunr> jkoenig: does it have its own definition of the word size ? + <jkoenig> braunr, nope. + <jkoenig> (although, maybe, and also we could use JNI to query it) + <braunr> even if virtual, i'd expect a machine to have such a defnition + <jkoenig> braunr, maybe it has, but basically in Java nothing depends on + the word size + <jkoenig> 'int' is 32 bits, 'long' is 64 and that's it. + <braunr> oh right, i remember most types are fixed size, right ? + <jkoenig> right. + <braunr> if not all + <jkoenig> now Jikes RVM's "org.vmmagic" provides an interface to defined + new unboxed types which can depend on the actual word size, but Jikes RVM + is its own JVM so obviously they can use and provide whatever extensions + they need :-) + <jkoenig> (but maybe they've implemented them in OpenJDK for bootstrap + purposes, I'm not sure) + <tschwinge> I'm missing this detail: where does the word size come into + play here? + <jkoenig> anyway, I _could_ indiscriminately use 'long' for port names, and + sparkle the code with word size tests but that would be very clumsy + <braunr> jkoenig: port names are actually ints :/ + <jkoenig> tschwinge, the actual format of the message header and type + descriptors, for instance. + <braunr> jkoenig: ok, got your point + <jkoenig> braunr, by 'long' I mean 64-bits integers (which they are on + 64-bits machines I think?) + <braunr> :) + <braunr> jkoenig: port names are as large as the word size + <braunr> but in C at least, they're int, not long + <braunr> it doesn't change many things, but you get lots of warnings if you + try with a long :) + <tschwinge> What is the reason that port names are an + architecture-dependent word size's width, and not simply 32 bit? + <jkoenig> "4 billions of port names should be enough for everyone" :-) + <braunr> tschwinge: an optimization is to use them as pointers in the + kernel + <antrik> tschwinge: the machine's native word size is what it can process + most efficiently, and what should be used for most normal + operations... it makes sense to define stuff as int, except for network + communication + <tschwinge> jkoenig: Well, yeah, but if you want to communicate with a + peer, you have to agree on the maximum number anyway (not for port names, + though, which are local). + <braunr> antrik: int isn't the word size everywhere + <braunr> antrik: the most common type matching the word size is long, at + least on ILP32/LP64 data models + <antrik> braunr: that's just because some idiots assumed int would always + be 32 bits, and consequently when 64 architectures came up the compiler + guys chickened out ;-) + <braunr> without int, you wouldn't have a 32 bits type + <antrik> that's not true for all architectures and/or operating systems + though AFAIK + <braunr> or a 16 bits one + <braunr> antrik: windows guys got even more scared, so windows 64 is LLP64 + <antrik> BTW, I haven't checked, but it's quite possible that 32 bit + numbers are actually preferable even on AMD64... + <tschwinge> jkoenig: So, back on track. :-) + <tschwinge> jkoenig: You didn't find anything yet in Mach's VM interfaces + as well a MemoryObject, etc., that can't be used/implemented in the Java + world? + <braunr> antrik: they consume less memory, but don't have much effect on + performance + <jkoenig> tschwinge, once we have the basic system calls and the + corresponding abstractions in place, I don't think anything else + fundamentally problematic could possibly show up + <antrik> braunr: if you really *need* a type of a certain bit size, you + should use stdint types. so not having a 16 or 32 bit type in the + short/int/long canon is *not* an excuse + <tschwinge> jkoenig: That speaks for the Mach designers! + <braunr> antrik: right + <jkoenig> tschwinge, on trick is that for instance, mach_task_self would + still be unsafe even if it returned a nicely wrapped Task object, because + you could still wreck your own address space and threads with it. So we + would need the "attenuation" pattern mentionned above to provide a safe + one. + <jkoenig> (which would disallow thinks such as the port/thread/vm calls) + <braunr> jkoenig: you mentioned the unsafe pseudo exception earlier + <jkoenig> braunr, right, so the issue is with distinguishing safe from + unsafe methods + <antrik> braunr: BTW, the Windows guys actually broke a lot of stuff by + fixing long at 32 bits -- this way long doesn't match size_t and pointer + types anymore, which was an assumption that was true for pretty much any + system so far... + <tschwinge> jkoenig: Yes. (And again hope for the JVM to optim...) + <braunr> antrik: that's right :) + <braunr> antrik: that's LLP64 + <braunr> antrik: long long and pointers + <jkoenig> braunr, so basically the idea is that unsafe methods are declared + as "throws Unsafe" + <jkoenig> the effect is that if you use such a method you must either + "throw Unsafe" yourself, + <jkoenig> or if you're building a safe abstraction on top of Unsafe + methods, you'll "catch" the "exception" in question to tell the compiler + that it's okay. + <jkoenig> it's more or less inspired from the "semantic regimes" idea from + the org.vmmagic paper which is referenced in my original proposal, + <jkoenig> only implementing by hijacking the exception checking machinery, + which has a behaviour similar to what we want. + <braunr> ok + <braunr> but hmm this seems pretty normal, what's the tricky part ? :) + <tschwinge> braunr: The idea is that the programmer explicitly has to + acknowledge if he'S using an unsafe interface. + <braunr> tschwinge: sounds pretty normal too + <jkoenig> braunr, the trick is that you would not usually declare + exceptions which are never actually thrown (and actually since the + compiler does not know it's never thrown, I need to work around it in a + few places) + <braunr> oh, ok + <braunr> jkoenig: that's interesting indeed + <jkoenig> braunr, the org.vmmagic paper provides an example which uses some + annotations called @UncheckedMemoryAccess and @AssertSafe to the same + effect (which is kind of cleaner), but it would be a headache to + implement without help from the compiler I think (as far as I can tell + the annotation processor would have to inspect the bytecode) + <braunr> but hm + <braunr> what's the true problem about this ? + <jkoenig> (the paper advocates "high-level low-level programming" and is a + very interesting read I think, + http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.151.5253&rep=rep1&type=pdf, + for what it's worth) + <braunr> what's wrong if you just declare your methods unsafe and don't + alter anything else ? + <tschwinge> Yes, I read it and it is interesting. Unfortunately, it seems + I forgot most of it again... + <jkoenig> braunr, declare? alter? + <jkoenig> you mean just tag them with an annotation? + <braunr> just stating a method "throws Unsafe" + <jkoenig> braunr, well some compiler will output a warning because they can + tell there's no way the method is going to throw such an exception. + <jkoenig> and then some other compiler will complain that my + @SuppressWarnings("unused") does not serve any purpose to them :-) + <jkoenig> also, when initializing final fields, I need to work around the + fact that the compiler thinks "Unsafe" might be thrown. + <jkoenig> see for instance MachPort.DEAD + <braunr> jkoenig: ok + <jkoenig> braunr, but I'm more than willing to accept this in exchange for + a clear, compiler-enforced materialization of the border between safe an + unsafe code. + <jkoenig> actually another question I have is the amount of static typing I + should add to the safe version, for instance should I subclass MachPort + into MachSendRight, MachReceiveRight and so on. I don't want to depart + from the C inteface too much but it could be useful. + <braunr> jkoenig: can't answer that :) + <braunr> jkoenig: keep them in mind for later i think + <tschwinge> jkoenig: What's the safety concern w.r.t. having MachPort (not) + final? + <jkoenig> tschwinge, actually I'm partly wrong in that we only need name() + and a couple other methods to be final + <tschwinge> jkoenig: That's what I was thinking. :-) + <tschwinge> I though I'm missing something here. + <jkoenig> tschwinge, the idea is that the user (ie., the adversary :-) + could extend MachPort and inject their own fake port name into messages + <jkoenig> by overriding name() or clear() + <tschwinge> Yeah, but if these are final, that's not possible. + <jkoenig> right. + <tschwinge> And that *should* be enough, I think. + <tschwinge> Unless I'm missing something. + <jkoenig> I don't think so. Also I hope it is, because as mentionned above + there might be some value in subclassing MachPort. + <tschwinge> Yep. + <jkoenig> incidentally, declaring the class or the method final will allow + the JVM to inline them I think. + <tschwinge> It will help the JVM, yes. It can also figure that out without + final, though. (And may have to de-optimize the code again in case there + are additional classes loaded during run-time.) + <tschwinge> jkoenig: The reference counting in MachPort. I think I'm + beginning to understand this. + <jkoenig> oh ok + <jkoenig> tschwinge, yes the javadoc is maybe a bit obscure so far. + <jkoenig> but basically you don't want the port name you acquire to become + invalid before you're done using it. + <tschwinge> But how is this different from the C world? + <jkoenig> here my goal is to provide some guarantees if you use only safe + methods + <jkoenig> like, you can't forge a port name and things like that + <jkoenig> so basically it should never be possible to include an invalid + port name in a message if you use only safe methods. + <tschwinge> Ah, I see! + <tschwinge> Now that does make sense. + <jkoenig> but the mechanism in itself is similar to the Hurd port cells and + user_link structures + <tschwinge> It's again ``only'' helping the programmer. + <jkoenig> right, no object-capability ulterior motives :-) + <jkoenig> another assumption which the javadoc does not state yet it that + basically there should be exactly one MachPort object for each mach-level + port name reference (in the sense of mach_port_mod_refs) + <tschwinge> Yes, I figured out that bit. diff --git a/user/jkoenig/java/java-access-bridge.mdwn b/user/jkoenig/java/java-access-bridge.mdwn new file mode 100644 index 00000000..57c87068 --- /dev/null +++ b/user/jkoenig/java/java-access-bridge.mdwn @@ -0,0 +1,92 @@ +[[!meta copyright="Copyright © 2011 Free Software Foundation, Inc."]] + +[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable +id="license" text="Permission is granted to copy, distribute and/or modify this +document under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no Invariant +Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license +is included in the section entitled [[GNU Free Documentation +License|/fdl]]."]]"""]] + +[[!tag open_issue_porting]] + +Debian's *openjdk-7-jre* package depends on *libaccess-bridge-java-jni* (source +package: *java-access-bridge*). + +The latter one has *openjdk-6-jdk* as a build dependency, but that can be +hacked around: + + # ln -s java-7-openjdk /usr/lib/jvm/java-6-openjdk + +Trying to build it: + + $ LD_LIBRARY_PATH=/usr/lib/jvm/java-7-openjdk/jre/lib/i386/jli dpkg-buildpackage -b -uc -d + [...] + make[3]: Entering directory `/media/erich/home/thomas/tmp/libaccess-bridge-java-jni/java-access-bridge-1.26.2/idlgen' + /usr/lib/jvm/java-6-openjdk/bin/idlj \ + -pkgPrefix Bonobo org.GNOME \ + -pkgPrefix Accessibility org.GNOME \ + -emitAll -i /usr/share/idl/bonobo-activation-2.0 -i /usr/share/idl/at-spi-1.0 -i /usr/share/idl/bonobo-2.0 \ + -fallTie /usr/share/idl/at-spi-1.0/Accessibility.idl + /usr/share/idl/at-spi-1.0/Accessibility_Collection.idl (line 66): WARNING: Identifier `object' collides with a keyword; use an escaped identifier to ensure future compatibility. + boolean isAncestorOf (in Accessible object); + ^ + /usr/share/idl/at-spi-1.0/Accessibility_Component.idl (line 83): WARNING: Identifier `Component' collides with a keyword; use an escaped identifier to ensure future compatibility. + interface Component : Bonobo::Unknown { + ^ + Exception in thread "main" java.lang.AssertionError: Platform not recognized + at sun.nio.fs.DefaultFileSystemProvider.create(DefaultFileSystemProvider.java:71) + at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:108) + at java.nio.file.FileSystems$DefaultFileSystemHolder.access$000(FileSystems.java:89) + at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:98) + at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:96) + at java.security.AccessController.doPrivileged(Native Method) + at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(FileSystems.java:95) + at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(FileSystems.java:90) + at java.nio.file.FileSystems.getDefault(FileSystems.java:176) + at sun.util.calendar.ZoneInfoFile$1.run(ZoneInfoFile.java:489) + at sun.util.calendar.ZoneInfoFile$1.run(ZoneInfoFile.java:480) + at java.security.AccessController.doPrivileged(Native Method) + at sun.util.calendar.ZoneInfoFile.<clinit>(ZoneInfoFile.java:479) + at sun.util.calendar.ZoneInfo.getTimeZone(ZoneInfo.java:658) + at java.util.TimeZone.getTimeZone(TimeZone.java:559) + at java.util.TimeZone.setDefaultZone(TimeZone.java:656) + at java.util.TimeZone.getDefaultRef(TimeZone.java:623) + at java.util.TimeZone.getDefault(TimeZone.java:610) + at java.text.SimpleDateFormat.initializeCalendar(SimpleDateFormat.java:682) + at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:619) + at java.text.DateFormat.get(DateFormat.java:772) + at java.text.DateFormat.getDateTimeInstance(DateFormat.java:547) + at com.sun.tools.corba.se.idl.toJavaPortable.Util.writeProlog(Util.java:1139) + at com.sun.tools.corba.se.idl.toJavaPortable.Skeleton.writeHeading(Skeleton.java:145) + at com.sun.tools.corba.se.idl.toJavaPortable.Skeleton.generate(Skeleton.java:102) + at com.sun.tools.corba.se.idl.toJavaPortable.InterfaceGen.generateSkeleton(InterfaceGen.java:159) + at com.sun.tools.corba.se.idl.toJavaPortable.InterfaceGen.generate(InterfaceGen.java:108) + at com.sun.tools.corba.se.idl.InterfaceEntry.generate(InterfaceEntry.java:110) + at com.sun.tools.corba.se.idl.toJavaPortable.ModuleGen.generate(ModuleGen.java:75) + at com.sun.tools.corba.se.idl.ModuleEntry.generate(ModuleEntry.java:83) + at com.sun.tools.corba.se.idl.Compile.generate(Compile.java:324) + at com.sun.tools.corba.se.idl.toJavaPortable.Compile.start(Compile.java:169) + at com.sun.tools.corba.se.idl.toJavaPortable.Compile.main(Compile.java:146) + make[3]: *** [org/GNOME/Accessibility/Accessible.java] Error 1 + make[3]: Leaving directory `/media/erich/home/thomas/tmp/libaccess-bridge-java-jni/java-access-bridge-1.26.2/idlgen' + make[2]: *** [all-recursive] Error 1 + make[2]: Leaving directory `/media/erich/home/thomas/tmp/libaccess-bridge-java-jni/java-access-bridge-1.26.2/idlgen' + make[1]: *** [all-recursive] Error 1 + make[1]: Leaving directory `/media/erich/home/thomas/tmp/libaccess-bridge-java-jni/java-access-bridge-1.26.2' + make: *** [debian/stamp-makefile-build] Error 2 + dpkg-buildpackage: error: debian/rules build gave error exit status 2 + + +IRC, freenode, #hurd, 2011-08-10: + + < jkoenig> and with my latest fix (hardwire os.name as "Linux"), + java-access-bridge actually built \o/ + < youpi> I wouldn't call it a "fix" :) + < jkoenig> true, but pretty much everything assumes we're either solaris, + linux or windows :-/ + < jkoenig> also we're actually using the Linux code which it is used to + select throughout the JDK + < jkoenig> if it's any consolation, os.version stays "GNU-Mach + 1.3.99/Hurd-0.3" :-) + < youpi> ideally it should simply be changed to "GNU" diff --git a/user/jkoenig/java/proposal.mdwn b/user/jkoenig/java/proposal.mdwn new file mode 100644 index 00000000..feb7e9dc --- /dev/null +++ b/user/jkoenig/java/proposal.mdwn @@ -0,0 +1,629 @@ +[[!tag stable_URL]] + +# Java for Hurd (and vice versa) + +Contact information: + + * Full name: Jérémie Koenig + * Email: jk@jk.fr.eu.org + * IRC: jkoenig on Freenode and OFTC + +## Introductions + +I am a first year M.Sc. student +in Computer Science at University of Strasbourg (France). +My interests include capability-based security, +programming languages and formal methods +(in particular, object-capability languages and proof-carrying code). + +### Proposal summary + +This project would consist in improving Java support on Hurd. +The first part would consist in +fixing bugs and porting Java-related packages. +The second part would consist in +creating low-level Java bindings for the Hurd interfaces, +as well as libraries to make translator development easier. + +### Previous involvement + +I started contributing to Hurd last summer, +during which I participated to Google Summer of Code +as a student for the Debian project. +I worked on porting Debian-Installer to Hurd. +This project was mostly a success, +although we still have to use a special mirror for installation +with a few modified packages +and tweaked priorities +to work around some uninstallable packages +with Priority: standard. + +Shortly afterwards, +I rewrote the procfs translator +to fix some issues with memory leaks, +make it more reliable, +and improve compatibility with Linux-based tools +such as `procps` or `htop`. + +Although I have not had as much time +as I would have liked to dedicate to the Hurd +since that time, +I have continued to maintain the mirror in question, +and I have started to work +on implementing POSIX threads signal semantics in glibc. + +### Project-related skills and interests + +I have used Java mostly for university assignments. +This includes non-trivial projects +using threads and distributed programming frameworks +such as Java RMI or CORBA. +I have also used it to experiment with +Google App Engine +(web applications) +and Google Web Toolkit +(a compiler from Java to Javascript which helps with AJAX code), +and I have some limited experience with JNI +(the Java Native Interface, to link Java with C code). + +My knowledge of the Hurd and Debian GNU/Hurd is reasonable, +as the Debian-Installer and procfs projects +gave me the opportunity to fiddle with many parts of the system. + +Initially, +I started working on this project because I wanted to use +[Joe-E](http://code.google.com/p/joe-e/) +(a subset of Java) +to investigate the potential +[[applications of object-capability languages|objcap]] +in a Hurd context. +I also believe that improving Java support on Hurd +would be an important milestone. + +### Organisational matters + +I am subscribed to bug-hurd@g.o and +I do have a permanent internet connexion. + +I would be able to attend the regular IRC meetings, +and otherwise communicate with my mentor +through any means they would prefer +(though I expect email and IRC would be the most practical). +Since I'm already familiar with the Hurd, +I don't expect I would require too much time from them. + +My exams end on May 20 so I would be able to start coding +right at the beginning of the GSoC period. +Next year's term would probably begin around September 15, +so that would not be an issue either. +I expect I would work around 40 hours per week, +and my waking hours would be flexible. + +I don't have any other plans for the summer +and would not make any if my project were to be accepted. + +Full disclosure: +I also submitted a proposal to the Jikes RVM project +(which is a research-oriented Java Virtual Machine, +itself written in Java) +for implementing a new garbage collector into the MMTk subsystem. + +## Improve Java support + +### Justification + +Java is a popular language and platform used by many desktop and web +applications (mostly on the server side). As a consequence, competitive Java +support is important for any general-purpose operating system. +Better Java support would also be a prerequisite +for the second part of my proposal. + +### Current situation + +Java is currently supported on Hurd with the GNU Java suite: + + * [GCJ](http://gcc.gnu.org/java/), + the GNU Compiler for Java, is part of GCC and can compile Java + source code to Java bytecode, and both source code and bytecode to + native code; + * libgcj is the implementation of the Java runtime which GCJ uses. + It is based on [GNU Classpath](http://www.gnu.org/software/classpath/). + It includes a bytecode interpreter which enables + Java applications compiled to native code to dynamically load and execute + Java bytecode from class files. + * The gij command is a wrapper around the above-mentioned virtual machine + functionality of libgcj and can be used as a replacement for the java + command. + +However, GCJ does not work flawlessly on Hurd.r +For instance, some parts of libgcj relies on +the POSIX threads signal semantics, which are not yet implemented. +In particular, this makes ant hang waiting for child processes, +which makes some packages fail to build on Hurd +(“ant” is the “make” of the Java world). + +### Tasks + + * **Finish implementing POSIX thread semantics** in glibc (high priority). + According to POSIX, signal dispositions should be global to a process, + while signal blocking masks should be thread-specific. Signals sent to the + process as a whole are to be delivered to any thread which does not block + them. By contrast, Hurd has per-thread signal dispositions and signals + sent to a process are delivered to the main thread only. I have been + working on refactoring the glibc signal code and implementing the POSIX + semantics as a per-thread option. However, due to lack of time I have not + yet been able to test and debug my code properly. Finishing this work + would be my first task. + * **Fix further problems with GCJ on Hurd** (high priority). While I’m not + aware of any other problems with GCJ at the moment, I suspect some might + turn up as I progress with the other tasks. Fixing these problems would + also be a high-priority task. + * **Port OpenJDK 6** (medium priority). While GCJ is fine, it is not yet + 100% complete. It is also slower than OpenJDK on architectures where a + just-in-time compiler is available. Porting OpenJDK would therefore + improve Java support on Hurd in scope and quality. Besides, it would also + be a good way to test GCJ, which is used for bootstrapping by the Debian + OpenJDK packages. Also note that OpenJDK 6 is now the default Java + Runtime Environment on all released Linux-based Debian architectures; + bringing Hurd in line with this would probably be a good thing. + * **Port Eclipse and other Java applications** (low priority). Eclipse is a + popular, state-of-the-art IDE and tool suite used for Java and other + languages. It is a dependency of the Joe-E verifier (see part 3 of this + proposal). Porting Eclipse would be a good opportunity to test GCJ and + OpenJDK. + +### Deliverables + + * The glibc pthreads patch and any other fixes on the Hurd side + would be submitted upstream + * Patches against Debian source packages + required to make them build on Hurd would be submitted + to the [Debian bug tracking system](http://bugs.debian.org/). + + +## Create Java bindings for the Hurd interfaces + +### Justification + +Java is used for many applications and often taught to +introduce object-oriented programming. The fact that Java is a +garbage-collected language makes it easier to use, especially for the less +experienced programmers. Besides, its object-oriented nature is a +natural fit for the capability-based design of Hurd. +The JVM is also used as a target for many other languages, +all of which would benefit from the access provided by these bindings. + +Advantages over other garbage-collected, object-oriented languages include +performance, type safety and the possibility to compile a Java translator to +native code and +[link it statically](http://gcc.gnu.org/wiki/Statically_linking_libgcj) +using GCJ, should anyone want to use a +translator written in Java for booting. +Note that Java is +[being](http://www.linuxjournal.com/article/8757) +[used](http://oss.readytalk.com/avian/) +in this manner for embedded development. +Since GCJ can take bytecode as its input, +this expect this possibility would apply to any JVM-based language. + +Java bindings would lower the bar for newcomers +to begin experimenting with what makes Hurd unique +without being faced right away with the complexity of +low-level systems programming. + +### Tasks summary + + * Implement Java bindings for Mach + * Implement a libports-like library for Java + * Modify MIG to output Java code + * Implement libfoofs-like Java libraries + +### Design principles + +The principles I would use to guide the design +of these Java bindings would be the following ones: + + * The system should be hooked into at a low level, + to ensure that Java is a "first class citizen" + as far as the access to the Hurd's interfaces is concerned. + * At the same time, the memory safety of Java should be maintained + and extended to Mach primitives such as port names and + out-of-line memory regions. + * Higher-level interfaces should be provided as well + in order to make translator development + as easy as possible. + * A minimum amount of JNI code (ie. C code) should be used. + Most of the system should be built using Java itself + on top of a few low-level primitives. + * Hurd objects would map to Java objects. + * Using the same interfaces, + objects corresponding to local ports would be accessed directly, + and remote objects would be accessed over IPC. + +One approach used previously to interface programming languages with the Hurd +has been to create bindings for helper libraries such as libtrivfs. Instead, +for Java I would like to take a lower-level approach by providing access to +Mach primitives and extending MIG to generate Java code from the interface +description files. + +This approach would be initially more involved, and would introduces several +issues related to overcoming the "impedance mismatch" between Java and Mach. +However, once an initial implementation is done it would be easier to maintain +in the long run and we would be able to provide Java bindings for a large +percentage of the Hurd’s interfaces. + +### Bindings for Mach system calls + +In this low-level approach, my intention is to enable Java code to use Mach +system calls (in particular, mach_msg) more or less directly. This would +ensure full access to the system from Java code, but it raises a number of +issues: + + * the Java code must be able to manipulate Mach-level entities, such as port + rights or page-aligned buffers mapped outside of the garbage-collected + heap (for out-of-line transfers); + * putting together IPC messages requires control of the low-level + representation of data. + +In order to address these concerns, classes would be encapsulating these +low-level entities so that they can be referenced through normal, safe objects +from standard Java code. Bindings for Mach system calls can then be provided +in terms of these classes. Their implementation would use C code through the +Java Native Interface (JNI). + +More specifically, this functionality would be provided by the `org.gnu.mach` +package, which would contain at least the following classes: + + * `MachPort` would encapsulate a `mach_port_t`. (Some of) its constructors + would act as an interface for the `mach_port_allocate()` system call. + `MachPort` objects would also be instantiated from other parts of the JNI + C code to represent port rights received through IPC. The `deallocate()` + method would call `mach_port_deallocate()` and replace the encapsulated + port name with `MACH_PORT_DEAD`. We would recommend that users call it + when a port is no longer used, but the finalizer would also deallocate the + port when the `MachPort` object is garbage collected. + * `Buffer` would represent a page-aligned buffer allocated outside of the + Java heap, to be transferred (or having been received) as out-of-line + memory. The JNI code would would provide methods to read and write data at + an arbitrary offset (but within bounds) and would use `vm_allocate()` and + `vm_deallocate()` in the same spirit as for `MachPort` objects. + * `Message` would allow Java code to put together Mach messages. The + constructor would allocate a `byte[]` member array of a given size. + Additional methods would be provided to fill in or query the information + in the message header and additional data items, including `MachPort` and + `Buffer` objects which would be translated to the corresponding port names + and out-of-line pointers. + A global map from port names to the corresponding `MachPort` object + would probably be needed to ensure that there is a one-to-one + correspondence. + * `Syscall` would provide static JNI methods for performing system calls not + covered by the above classes, such as `mach_msg()` or + `mach_thread_self()`. These methods would accept or return `MachPort`, + `Buffer` and `Message` objects when appropriate. The associated C code + would access the contents of such objects directly in order to perform the + required unsafe operations, such as constructing `MachPort` and `Buffer` + objects directly from port names and C pointers. + +Note that careful consideration should be given to the interfaces of these +classes to avoid “safety leaks” which would compromise the safety guarantees +provided by Java. Potential problematic scenarios include the following +examples: + + * It must not be possible to write an integer at some position in a + `Message` object, and to read it back as a `MachPort` or `Buffer` object, + since this would allow unsafe access to arbitrary memory addresses and + mach port names. + * Providing the `mach_task_self()` system call would also provide access to + arbitrary addresses and ports by using the `vm_*` family of RPC operations + with the returned `MachPort` object. This means that the relevant task + operations should be provided by the `Syscall` class instead. + +Finally, access should be provided to the initial ports and file descriptors +in `_hurd_ports` and provided by the `getdport()` function, +for instance through static methods such as +`getCRDir()`, `getCWDir()`, `getProc()`, ... in a dedicated class such as +`org.gnu.hurd.InitPorts`. + +A realistic example of code based on such interfaces would be: + + import org.gnu.mach.MsgType; + import org.gnu.mach.MachPort; + import org.gnu.mach.Buffer; + import org.gnu.mach.Message; + import org.gnu.mach.Syscall; + import org.gnu.hurd.InitPorts; + + public class Hello + { + public static main(String argv[]) + /* Parent class for all Mach-related exceptions */ + throws org.gnu.mach.MachException + { + /* Allocate a reply port */ + MachPort reply = new MachPort(); + + /* Allocate an out-of-line buffer */ + Buffer data = new Buffer(MsgType.CHAR, 13); + data.writeString(0, "Hello, World!"); + + /* Craft an io_write message */ + Message msg = new Message(1024); + msg.setRemotePort(InitPorts.getdport(1)); + msg.setLocalPort(reply, Message.Type.MAKE_SEND_ONCE); + msg.setId(21000); + msg.addBuffer(data); + + /* Make the call, MACH_MSG_SEND | MACH_MSG_RECEIVE */ + Syscall.machMsg(msg, true, true, reply); + + /* Extract the returned value */ + msg.assertId(21100); + int retCode = msg.readInt(0); + int amount = msg.readInt(1); + } + } + +Should this paradigm prove insufficient, +more ideas could be borrowed from the +[`org.vmmagic`](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.151.5253&rep=rep1&type=pdf) +package used by [Jikes RVM](http://jikesrvm.org/), +a research Java virtual machine itself written in Java. + +### Generating Java stubs with MIG + +Once the basic machinery is in place to interface with Mach, Java programs +have more or less equal access to the system functionality without resorting +to more JNI code. However, as illustrated above, this access is far from +convenient. + +As a solution I would modify MIG to add the option to output Java code. MIG +would emit a Java interface, a client class able to implement the interface +given a Mach port send right, an a server class which would be able to handle +incoming messages. The class diagram below, although it is by no means +complete or exempt of any problem, illustrates the general idea: + +[[gsoc2011_classes.png]] + +This structure is somewhat reminiscent of +[Java RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation) +or similar systems, +which aim to provide more or less transparent access to remote objects. +The exact way the Java code would be generated still needs to be determined, +but basically: + + * An interface, corresponding to the header files generated by MIG, would + enumerate the operations listed in a given .defs files. Method names would + be transformed to adhere to Java conventions (for instance, + `some_random_identifier` would become `someRandomIdentifier`). + * A user class, corresponding to the `*User.c` files, + would implement this interface by doing RPC over a given MachPort object. + * A server class, corresponding to `*Server.c`, would be able to handle + incoming messages using a user-provided implementation of the interface. + (Possibly, a skeleton class providing methods which would raise + `NotImplementedException`s would be provided as well. + Users would derive from this class and override the relevant methods. + This would allow them not to implement some operations, + and would avoid pre-existing code from breaking when new operations are + introduced.) + +In order to help with the implementation of servers, some kind of library +would be needed to associate Mach receive rights with server objects and to +handle incoming messages on dedicated threads, in the spirit of libports. +This would probably require support for port sets at the level of the Mach +primitives described in the previous section. + +When possible, operations involving the transmission of send rights +of some kind would be expressed in terms of the MIG-generated interfaces +instead of `MachPort` objects. +Upon reception of a send right, +a `FooUser` object would be created +and associated with the corresponding `MachPort` object. +If the received send right corresponds to a local port +to which a server object has been associated, +this object would be used instead. +This way, +subsequent operations on the received send right +would be handled as direct method calls +instead of going through RPC mechanisms. + +Some issues will still need to be solved regarding how MIG will convert +interface description files to Java interfaces. For instance: + + * `.defs` files are not explicitly associated with a type. For instance in + the example above, MIG would have to somehow infer that io_t corresponds + to `this` in the `Io` interface. + * More generally, a correspondence between MIG and Java types would have + to be determined. Ideally this would be automated and not hardcoded + too much. + * Initially, reply port parameters would be ignored. However they may be + needed for some applications. + +So the details would need to be flushed out during the community bonding +period and as the implementation progresses. However I’m confident that a +satisfactory solution can be designed. + +Using these new features, the example above could be rewritten as: + + import org.gnu.hurd.InitPorts; + import org.gnu.hurd.Io; + import org.gnu.hurd.IoUser; + + class Hello { + static void main(String argv[]) throws ... + { + Io stdout = new IoUser(InitPorts.getdport(1)); + String hello = “Hello, World!\n”; + + int amount = stdout.write(hello.getBytes(), -1); + + /* (A retCode corresponding to an error + would be signalled as an exception.) */ + } + } + +An example of server implementation would be: + + import org.gnu.hurd.Io; + import java.util.Arrays; + + class HelloIo implements Io { + final byte[] contents = “Hello, World!\n”.getBytes(); + + int write(byte[] data, int offset) { + return SOME_ERROR_CODE; + } + + byte[] read(int offset, int amount) { + return Arrays.copyOfRange(contents, offset, + offset + amount - 1); + } + + /* ... */ + } + +A new server object could then be created with `new IoServer(new HelloIo())`, +and associated with some receive right at the level of the ports management +library. + +### Base classes for common types of translators + +Once MIG can target Java code, and a libports equivalent is available, +creating new translators in Java would be greatly facilitated. However, +we would probably want to introduce basic implementations of file system +translators in the spirit of libtrivfs or libnetfs. They could take the form +of base classes implementing the relevant MIG-generated interfaces which +would then be derived by users, +or could define a simpler interface +which would then be used by adapter classes +to implement the required ones. + +I would draw inspiration from libtrivfs and libnetfs +to design and implement similar solutions for Java. + +### Deliverables + + * A hurd-java package would contain the Java code developed + in the context of this project. + * The Java code would be documented using javadoc + and a tutorial for writing translators would be written as well. + * Modifications to MIG would be submitted upstream, + or a patched MIG package would be made available. + +The Java libraries resulting from this work, +including any MIG support classes +as well as the class files built from the MIG-generated code +for the Mach and Hurd interface definition files, +would be provided as single `hurd-java` package for +Debian GNU/Hurd. +This package would be separate from both Hurd and Mach, +so as not to impose unreasonable build dependencies on them. + +I expect I would be able to act as its maintainer in the foreseeable future, +either as an individual or as a part of the Hurd team. +Hopefully, +my code would be claimed by the Hurd project as their own, +and consequently the modifications to MIG +(which would at least conceptually depend on the Mach Java package) +could be integrated upstream. + +Since by design, +the Java code would use only a small number of stable interfaces, +it would not be subject to excessive amounts of bitrot. +Consequently, +maintenance would primarily consist in +fixing bugs as they are reported, +and adding new features as they are requested. +A large number of such requests +would mean the package is useful, +so I expect that the overall amount of work +would be correlated with the willingness of more people +to help with maintenance +should I become overwhelmed or get hit by a bus. + + +## Timeline + +The dates listed are deadlines for the associated tasks. + + * *Community bonding period.* + Discuss, refine and complete the design of the Java bindings + (in particular the MIG and "libports" parts) + * *May 23.* + Coding starts. + * *May 30.* + Finish implementing pthread signal semantics. + * *June 5.* + Port OpenJDK + * *June 12.* + Fix the remaining problems with GCJ and/or OpenJDK, + possibly port Eclipse or other big Java packages. + * *June 19.* + Create the bindings for Mach. + * *June 26.* + Work on some kind of basic Java libports + to handle receive rights. + * *July 3.* + Test, write some documentation and examples. + * *July 17 (two weeks).* + Add the Java target to MIG. + * *July 24.* + Test, write some documentation and examples. + * *August 7 (two weeks).* + Implement a modular libfoofs to help with translator development. + Try to write a basic but non-trivial translator + to evaluate the performance and ease of use of the result, + rectify any rough edges this would uncover. + * *August 22. (last two weeks)* + Polish the code and packaging, + finish writing the documentation. + + +## Conclusion + +This project is arguably ambitious. +However, I have been thinking about it for some time now +and I'm confident I would be able to accomplish most of it. + +In the event multiple language bindings projects +would be accepted, +some work could probably be done in common. +In particular, +[ArneBab](http://www.bddebian.com/~hurd-web/community/weblogs/ArneBab/2011-04-06-application-pyhurd/) +seems to favor a low-level approach for his Python bindings as I do for Java, +and I would be happy to discuss API design and coordinate MIG changes with him. +I would also have an extra month after the end of the GSoC period +before I go back to school, +which I would be able to use to finish the project +if there is some remaining work. +(Last year's rewrite of procfs was done during this period.) + +As for the project's benefits, +I believe that good support for Java +is a must-have for the Hurd. +Java bindings would also further the Hurd's agenda +of user freedom by extending this freedom to more people: +I expect the set of developers +who would be able to write Java code against a well-written libfoofs +is much larger than +those who master the intricacies of low-level systems C programming. +From a more strategic point of view, +this would also help recruit new contributors +by providing an easier path to learning the inner workings of the Hurd. + +Further developments +which would build on the results of this project +include my planned [[experiment with Joe-E|objcap]] +(which I would possibly take on as a university project next year). +Another possibility would be to reimplement some parts +of the Java standard library +directly in terms of the Hurd interfaces +instead of using the POSIX ones through glibc. +This would possibly improve the performance +of some Java applications (though probably not by much), +and would otherwise be a good project +for someone trying to get acquainted with Hurd. + +Overall, I believe this project would be fun, interesting and useful. +I hope that you will share this sentiment +and give me the opportunity to spend another summer working on Hurd. + |