Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-184
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 184
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 184

Mac OS X: Java in Depth

Digital Media • 56:10

This session details the differences between Java development on Mac OS 9 and Mac OS X, including application embedding issues in Carbon with Java, JDirect 3, bridging technologies, and other issues.

Speaker: Blaine Garst

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

My name is Blaine Garst. I'm the manager of one of the Java groups at Apple. And what we're going to talk about today is Java in Depth. I want to just jump into it. I'm actually going to try to have some fun today. So hopefully you'll have some fun with me. We're going to try to do a few demos and show you what's really going on inside Mac OS X, inside the Java.

The demo gods struck early. At 8:00 this morning, the system wouldn't boot off of our boot disk. We got that figured out at 8:30. At 10:00 to 8:00, we figured out that our login usernames weren't quite the same as what they were the last time we ran the demo. They're striking early, but I think by the time we get to that point, we'll have things pretty much in control.

So, so far at this conference you heard from Steve Naroff about the overview of what we're doing, where we've been, where we are now, and some of what we're trying to go, where we're trying to go. You may have slipped over and listened to the QuickTime talk after that, found out how to do really cool graphics programming on Mac OS X, much as you do on 9. You may have gone to Pete Steinhauer's talk on how to cook up a Java application.

I'm not going to try to repeat very much of... those previous slides nor the performance talk either but what i do want to talk about is um some of the stuff that's that's uh that didn't get talked about so this is the talk where you get to ask questions where we're going to try to give you detail more detail more type that when project builder doesn't quite do what it's supposed to be doing for you quite yet some of the tricks we use or some of the things we have to use in the interim until it does so It's 9 o'clock.

Have you had your Java yet? Pop quiz. What do the following screenshots all have in common? Setup Assistant, the first program that runs after you boot Mac OS X. Network Manager, when you find yourself in a strange and unworldly NFS environment. This is the program you run to untangle yourself.

Blast app, source code, and a game that ships on your Ships on your CD. An applet, perhaps you're kind of getting the idea here. JBuilder, you saw that running yesterday. It unfortunately is not shipping on your CD, and you're supposed to go talk to Blake if you would like to see it shipping on your CD sometime. QuickTime Digital Media, as I mentioned before. And of course, the answer is they're all written in Java. Now, this isn't supposed to be all that remarkable, is it? But I think it's really kind of neat.

Java, I mean, these applications are kind of like when you walk up to Mac OS X, they're like the walls of the house. I mean, you know, you've got a TV room, you've got a kitchen, you've got your living room and stuff. I mean, when you're inside the house of Mac OS X running these applications, you don't really think about how they run or you're not really supposed to.

But for the folks of you inside this room, when the wiring is what is important to you, that is why you're here. So what we're going to talk about is what's inside the walls of that house, you know, the Java wiring in detail. So as a brief overview, we're going to talk about the wiring in a certain degree of depth.

We're going to talk about once you get your app up and running. And. More or less working, you know, how to run a little bit of profiling stuff against it, where we'd like to go with that, where we where we think we'll be going with that. How to do some debugging right now, both for your benefit and possibly for ours.

There are a few things that you do to augment your applications, so we're going to try to go through a little bit more detail on how to do that. In other words, how to use JNI in our kind of environment, how you have to do it today versus how we'd like to see you do it, and a few other topics. So let's just get going.

When you write your Java application, what you think about are the classes you write and, of course, when the program is running, the data it takes up. You can't just go and read data forever because eventually, despite what we do in terms of memory reclamation and things like that, if you're just leaking memory by holding onto it forever, it's not going to work. The rest of the system, however, is a little bit more complex.

So, you're going to have to do a lot of work to get the data out of your system. What's under those covers is the stuff that we generally worry about at Apple, and we try to make the bottom part of this diagram as efficient as possible. So I'd just like to talk... so let me go through the diagram first.

So, of course, you've got the JDK classes, all... I can't remember how many thousands of them there are that you might be using. The runtime, which does all that synchronization and garbage collection and compilation, the compiler below that. And then the runtime, which does all that synchronization and garbage collection and compilation, the compiler below that.

On the side, what I have in green are JNI support libraries, both the ones that we use to keep things going, and I just put two up there. We have about nine. And the JNI libraries that you might be writing as well, because you're bringing across some legacy code and stuff like that. Below us all are the frameworks that are common to Mac OS X.

Things like Carbon, things like the kernel, things like, you know, all that other stuff that's below us that we all are clients of. Now, private data is a little thin there. It's actually... private data extends all the way down the side of that diagram in truth. I just wanted to put up the sort of the Java private data in this diagram. But let's talk about the Java VM first of all. If you were at Pete's talk yesterday, you saw that... The Java VM framework is sort of the fuse panel for Java inside Mac OS X.

We have inside that framework lots and lots of stuff. We have the virtual machines that execute your Java bytecodes. We have all of our system jars in the classes folder, things like that. We have the JNI support libraries wedged into some other little subdirectory. We have headers because this is a C environment for those of you writing JNI code. We have a few headers for that. Actually, probably on DP4, a few more headers than we really need to have out there.

So the ones that you should be thinking about are pretty much just JNI. We have the Java home with the system properties file and there's a whole bunch of stuff and I'll let you wander around and take a look at that. But that is sort of the moral equivalent to, if you're an MRJ programmer, the MRJ libraries folder.

So in DP4, I'll tell you the truth.

[Transcript missing]

So we do some trickery such that that's all that any program that needs to do JNI ever sees when it does a link. That way, if it ever comes to pass that you need to switch your Java VMs, you can reset that one symbolic link, which in Macintosh terms is an alias really on HFS file systems, to be the VM of your choice.

So we ship, in some ways, three VMs. We ship Hotspot Client Compiler as the default VM. We also have a debug version of that same technology, and I'll tell you a little bit about that later, and again, the classic interpreter. So there are several ways to get at that.

I really hope that you'd never have to reset that symbolic link, honestly, because we do have lots of ways to get to it. Here are two of them. One is you can simply type -classic or -hotspot in order to have the JNI invocation code pick the right library to go after, load up, and initialize with.

If you can't get to it via the command line or that's inconvenient for you, you can use an environment variable. The Java JVM library environment variable is also looked at. And in that last line, this is the preferred way to get to the, say, the debug version of Hotspot.

Now, I want to caution you, the debug version of Hotspot is slower because it has thousands of assertions compiled in. And so lots of C++ inlining that makes things really fast isn't inlined, and so it's considerably slower. But you're not really going to get to it. You don't really care about that if you're at that stage. And I'll tell you when you might get to that stage. So here's a little bit about profiling.

The JDK 1.2, the Java 2 specification for the runtime, has a very nice interface. It's called the Java Virtual Machine Profiling Interface. And the implementation of that for the classic interpreter works pretty well. But the implementation for that in the hotspot interpreter does not quite run there in your DP4.

We are working really hard with our folks in developer technical support to figure out a pathway to get you some updates to what's on your CD. I mean, the bits that are on your CD are about two weeks old. So that's a lifetime for us. So what we have running up on stage and what you see on your CDs is slightly different. And it's our goal to try to get you what we have on stage. Including some project builder stuff out to you via the web very soon. So in the interim, however, we're going to be working on a lot of things.

So Hotspot itself is just chock full of very interesting technology. So one of the things that makes Hotspot really good is that it chooses which methods need to be compiled on the fly and based on their usage patterns which methods can and ought to be inlined inside of there. In order to do that, it has its own sampling technology to figure out, "Hey, what's going on?" So every now and then, clock ticks wise, it goes and takes a look at the stacks and figures out which methods are being interpreted.

And so an interesting side effect of that is that they've enabled that in sort of a profiling kind of a manner such that you can get to that using the -xprof flag. So we actually have used that recently in the past two weeks. We've used that to improve the launch time of ADPT-based applications by two or three seconds. So what I'd like to do now is--. I'll show you a little bit of a demo of that. And I'm going to have Jens Alfke join me on stage now.

Jens has a few demos picked up for us. But if we could get-- there we go. Let's put this one away. This demo is going to be in a terminal. We're not supposed to do that, but it's really the only way to show off X-Prof right now. So I have a command line all set up here. What I've done is I've CD'd into the directory of one of the silly little sample applets that you all know and love. This one is Arctest.

And I'm going to run Java command. I'm paranoid because this is a demo, so I'm going to force it to use Hotspot. And I'm using the magic -X-Prof flag. And then the regular Java arguments, in this case just Arctest, the name of the main class. So what's going to happen is that it's going to launch Arctest normally, but every time a thread finishes, it's going to spit out to the console some profiling data about that thread. So as we launch Arctest, which is going to come up in the background, you'll first see the main thread finish, and it dumps out some stuff there.

Here's Arctest. Do a little bit of stuff with it. that we... quit Arctas, and then all the other threads finish, and we see their profiling information get dumped out too. So what is this stuff? It's really pretty easy to interpret compared to the profiling output from JDK 1.1. It's not quite as in-depth, but it's fairly easy to read. So first, we've got the thread name here, main.

And first it's going to show us the profiling data for the stuff that got interpreted, as opposed to the methods that were running native. It says that the thread took 4.13 seconds, 244 ticks. And this confused me at first. These are not ticks as in Mac OS ticks, which are a sixtieth of a second. Tick here just means samples. So it depends on how many times it sampled it.

We spent 18.3% of the time that this thread was active in JDirect library OS X dot find symbol, which is part of the implementation of JDirect 3, which actually is what goes out and maps the native methods to the actual Carbon or system or whatever functions that back them up.

And the numbers here mean that we spent zero seconds inside of interpreted Java code, or zero ticks were inside of interpreted Java code. Twenty-six ticks were inside of native code. Which makes sense. We spent a whole bunch of time loading Carbon, basically, is what this means. And JDirect looking at Carbon methods and doing some JNI stuff under the hood to plug them up. Then we spent 11.3% of our time down in view.setGeometry, which is part of the core clipping code for heavyweight components. And again, that was all spent down in native code.

Down below here, the next group here is for the same thread, but this is compiled code. So this is time spent in actual methods that have been jitted or compiled into native code by Hotspot. And you can see there's almost nothing here. The main thread just doesn't run very long. It doesn't loop that much. It's mostly doing initialization stuff.

Since that's the thread where the app will actually create the components and initializes the toolkit and all that stuff. So these are a bunch of little threads that aren't doing very much stuff. AWTEventQ0, you'll find is generally where most of the real work is happening in any Java application. That's the event dispatch thread.

Here we spent 20% of our time down in cgsgraphics.awt2quartz draw a line. And so this is where we actually call into Quartz to draw lines. And so you'd expect, yeah, in your typical kind of AWT type app, that's where you're going to be spending a lot of your time.

So as I said, this is pretty straightforward stuff. It's not going to give you the entire stack crawl of how you got to this method where you were spending all of your time, the way the old profiler did. And it does have to be run from a terminal, but both of those limitations are being worked on. And I think by the time we ship, things will be better.

Thanks, Jens. Get the other slide back up. Okay, so the traditional profiling stuff inside the Java VM, HProf, we actually haven't run that recently, so on Classic we believe it works. So we strongly advise you to join that mailing list, Mac OS X Java, that our DTS folks run. Alan Samuels will get up and tell you where that's at again. And join us and help tell us what's there and what's useful to you and share some tips on that.

We strongly believe that the JVMPI is going to be a super interface that third parties, some of whom may be sitting in this room right now, are going to be able to take advantage of right away. We have talked with some folks about this already, and it's our strong hope that we get some rather awesome tools coming onto our platform.

The profiling interface lets you, when it's fully operational, tells you all kinds of things about object allocation, the stacks that were in existence when objects came along. It's a very, very powerful interface, and we think that this is going to bring development on X a leap forward compared to some of the C-based environments where these tools are harder to use. to accomplish.

So, just as in wiring up a house or wiring up a circuit board or something, you have debugging to do. So, again, what you have in TP4 is a classic interpreter that we've been shipping for a long time that has a debugger interface that works. Blaine Garst So, just as in wiring up a house or wiring up a circuit board or something, you have debugging to do. So, again, with Hotspot, we have one that almost works but doesn't quite. And so, there are folks last week working hard on getting the debugger interface up and running.

Unfortunately, we didn't quite get it where we needed it to be for this demo today. So, I can't quite show you JVMDI running on Hotspot today, but you can expect that that will be there very shortly. And again, we're going to try to figure out how to get updates to you so that you can see that as well.

So, what's on your disk? is A debugger interface that works in a classic environment. So again, you have to go to the command line to get use of that. You have to go to JDB to see that. So you should be using JDB-T classic to fire up the runtime and get to set breakpoints and that kind of stuff.

Obviously, we don't think this is the way you really ought to be doing debugging. And so we've been working with folks on the project builder team to make this a much more pleasant environment. And we do have some success stories with that. And I think Jens is going to share one of those with you a little bit later. So the truth is, you're going to have to find out-- if you need to do JDB-level debugging, you're going to have to find out how to launch this thing from the command line at the moment.

So, if you happen to write those JNI libraries, then you're writing in C. And so, it might happen that you don't write perfect code the first time. It might happen that you'll be interested in running GDB on that part of your program that's written in C that gets called into across the JNI interface. In which case, you need to learn how to launch GDB on the real Java binary. So, the real Java binary is kind of wedged off in that little moral equivalent of MRJ libraries. It's wedged in the Java VM framework.

And so, mentally concatenate the first two lines of this slide. The font on this system, or for the slides, wasn't all that good. So, you might want to learn how to do that. You essentially have to GDB the true Java, you know, bring up executable in order to get attached to that process. There are a few things that you can do. If you run with classic, you don't have to run with classic. But if you run with classic, the next two lines, the call dump threads and the call dump monitors work.

And these are, to some degree, the equivalents to some of the MRJD commands. That let you inside the runtime and see what's going on in a little bit more detail. The last line is simply GDB syntax for doing a backtrace on all different threads. So, that'll give you some idea of what's going on, which ones have some of your code in the middle of it.

So I'm a little bit, I mean, I'm optimistic, but I'm also a realist. So given that the hotspot that we have, oh, now we're going to skip the debugging demo right now. We're going to do that a little bit later. Given that the hotspot you have is actually fairly young, it's very mature technology and it runs Everything we can throw at it, except that it's not fully functional, but it's very solid.

But there might be some occasions where you'll trip across something that doesn't quite work right. So one thing you can do for us is help, you know, for yourselves, but is determine whether or not some strange crash you see is your fault or ours. So if your Java code crashes, one thing that you could do right away is just try running it in Classic.

Since it's a whole different technology underneath and it may well work there. That's not proof positive that it's our fault, but it's a good signal that it might be. So if your code runs in Classic but doesn't with the default hotspot, you can do us a favor by running it with that debug version of hotspot.

Because, again, there's lots of assertions in there and if there's something funky going on, which might actually be your fault, if you're passing in something that's not your fault, you're going to have to run it in Classic. Blaine Garst Blaine Garst: Yeah. So if you're passing in, say, a zero for a JNI environment pointer, the debug version of hotspot's going to catch that and throw an assertion, whereas the compiled version of that won't or might not.

So there are some cases where it might catch some things that are your fault and it certainly will catch things earlier if they are our fault. And so obviously if you find something that is our fault, we want to know about it. And so I'm putting my email address up there right now for that. You can mail us an email at jni.com/hotspot.

me the details of that, and I'll see that we get some attention paid to that. Clearly, if you're on our discussion list, Mac OS X Java discussion list, folks out there might well want to know a little bit about it also. So, again, this is how you set up the Hotspot There is an underbar between hotspot and debug. It's hardly visible on this monitor, but anyway. So don't forget those underbars. They are important. OK, so again, this is a Unix environment.

How many of you out there have been exclusively MRJ programmers? Okay, there's just a few hands. And so let me try to ask a different question. How many of you have already programmed in sort of a UNIX or a Windows environment? The vast majority. So you all know what this is going to be about.

Okay, so how do you build, you know, a JNI support library? You write some Java code with natives, you compile it with Java C, you build the C header as necessary, you then copy the C header over as your template and start hacking in your C code. You build the library. About the only thing that's different about this on Mac OS X is that the ending library, you know, the end of the library There are two different types of libraries on Mac OS X. One's called a bundle, and the other's called-- there are several kinds of libraries.

There are two types of dynamic libraries. One is called a bundle, and the other is called a dynamic library. So we happen to like the bundle variant of-- the libraries for our purposes. And so from a command line viewpoint, this is a very simple way to build one of those guys. You just remember the dash bundle magic.

But, I mean, this is kind of messy, and what we really want to do is put all this stuff inside of Project Builder. And so one of our friends on the Project Builder team, Dave Ewing, has been staying up till midnight his time, which is Denver time, trying to make this stuff happen. So I'd like to bring Jens back up on stage to see what some of this might look like inside Project Builder where it belongs.

Let's get the monitor. Can you put it on both screens this time? I don't know whether that's easy or not. I'm bringing up a PBX project showing a very simple JNI example. Blaine wrote the JNI example, and then Dave Ewing made the PBX project, so I'm just here to be Vanna White and show it off. We have a couple of files here. We have calcengine.c, which is our native code. It just contains a couple of JNI methods.

I'm not going to go into too much detail because there's not time in this talk to really explain JNI. A number of you have probably used it, and there are some very good books out there and a Java soft tutorial. CalcEngine.java, then-- and besides, you probably can't read the text on here anyway unless you're in the front row.

So we have a couple of native methods in here, which are what are going to get bound into that native code. What's interesting in here, and this is just the tantalizing promise because you can't actually do this in DP4, but you're getting used to that line, is we have three targets here. We have the Java target.

which has the calcengine.java source file. And we have a shell script here that's been cleverly set up. So we're going to run bin sh and we're going to run this script that calls user bin java h, run that on calcengine. So that's the post-processing step. So after we compile the Java, we run java h on it, which then generates the header file declaring what the native JNI functions are.

Then we have a second target here for our JNI library itself, which is a regular kind of C target containing the calcengine.c source file, the calcengine.h file that got generated by the Java target. And this one, the product type here is a library, which is going to build a regular OS X bundle dynamic library.

Then we have a third target, and if you're used to Code Warrior, this will be second nature. We have a third target called CalcExample, which is just an aggregate target. And the other targets appear down in here, which means that they are linked to it. They're dependent on it, or it's dependent on them.

So building the CalcExample target will then build first the Java target and then the JNI target and cause everything to be generated. And as Blaine alluded to earlier, the demo gods were not happy. We sacrificed beefy giblets to them, but they really wanted the tuna and egg and became very angry. So we can't actually build this stuff. It's actually more like file permission issues.

But I would have shown it running. But you can just kind of imagine that, yes, it's going to kind of run and do its stuff. We will ship this demo project in this fabled upcoming release where we have the PBX support for doing the JNI stuff. And that's it.

Did I say PBX? Yes. Okay. So, I think one thing in there that you probably maybe noticed was that we had like four methods that were wrapped, like add, subtract, divide, multiply. And I mean, those were the names of the C functions, and those were in fact the names of the native methods that were going to give you access to that.

So, if you've been on MRJ before, you know that that kind of a mapping is like kind of tedious in some ways. So, there is in MRJ a better way to do that, and that has been called JDirect. And so, we have JDirect 3 on Mac OS X that both helps us out and can help you out with that. And so, JDirect 3 is pretty much the same.

as JDirect 2 from your perspective, not entirely the same, but pretty doggone the same. And that's due to the heroic efforts of Nick Kledzik, who put together a JDirect 3 package, which is pretty much entirely rewritten underneath. But from your perspective, it's not going to be that much different.

I will go a little bit into what is different about JDirect 3. So, along with the metaphor, JDirect 3 is kind of like your virtual electrician. You bring this electrician in and he does all this wiring for you and you don't have to do very much work at all.

So, if you've got gobs of existing code or if you look under you in those C frameworks that are below us all and find C code that's kind of interesting to you, and this has been true in the past and it probably may well still be true in the future, and you happen to be a little bit decaffeinated as a programmer and don't want to write all those little methods, even if Project Builder makes it just easy as you can think, the solution is to let JDirect possibly write those. So, we use C functions that glue between the native JNI argument type implementations and the C functions that are being supplied to you somewhere else.

For the AWT, as I said, this is technology that we've been using for a long time. QuickTime also uses this technology. And so, you know, it's been there before. We know about it, and you can count on it as well. So briefly, how do you get this virtual electrician to do its job? And so, What it needs is the name of the library that contains those C functions, You know, can't-- it's not going to go grep and end M the system to find the functions for you. And you need to tell it which class has those native declarations.

That's a pretty simple contract, right? Tell it where the library is, tell it-- tell it what functions you want written for-- on your behalf. And so, you have to tell it in these two ways. You tell the name of the library in a static string inside that class that has those native methods. There are other options as well. And then you tell the-- then you hand the class itself to the, you know, to the constructor of this Jdirect function. So, I actually have a little bit of code here to show you how easy it is.

You can read the code, right? The first line is that string, JDirect_MacOS10. has the value prime.dialibs. Presumably, prime has this very fancy super calc engine kind of technology underneath it. You tell, you ask JDirect in the second line, second functional line, to go ahead and build those stub functions. So you hand it prime.class.

Now, note that this is the prime.class itself, so you're just using that fancy 1.1.class directive to hand it prime.class. You hand an instance of, or hand the class description into JDirect itself. JDirect uses reflection to go find out what methods to write native codes for, allocates some C memory, writes some C functions in that C memory, jams them into a funky little JNI object itself, and hands you back the handle to all those gizmos in that thing called, that we store in linkage.

So you actually need to hold on to that object, that linkage object, because if you're going to do that, you're going to have to do it in a different way. If you don't, it will be garbage collected. And if it's garbage collected and you try to access those functions, well, we're not going to help you with that.

So the last line of this is the actual method that we're, in this example, trying to do. If I would have had more lines on this slide, I would have done the four methods that were in the earlier example. So anyway, JDirect 3 is, in this example, absolutely simple to use.

So you ought to note, though, that JDirect 3 is a rather interesting set of technology. So you can have, there's a slight difference in the types of arguments you can use with it in JDirect 3. You can use scalars and arrays, and arrays of scalars, although arrays of Booleans, I understand, aren't quite there. You cannot pass objects, however. We don't have any way to really map objects in any intelligent fashion.

What we're doing under the covers is... In the case of arrays, is we're actually copying the bits out of the runtime into a privately allocated memory, rummaging with it, and then when we're done with it, copying it back in. This is the contract that JNI has for gaining access to arrays. So we haven't seen issues with that, even for QuickTime. So it's just a note for you.

As I mentioned earlier, there are different ways to name different libraries. If you put that in a library, you can name it. You can put the same string inside of an interface, and then if your class implements that interface, JDirect will do reflection on the interfaces and find those strings. And so you can have several libraries that hold the implementations of a set of methods that are described in one class. You can write code that runs on JDirect 2 in the 118 environment on MRJ.

In that environment, we tune the runtime to look for a very magic... interface. And so if you extended that interface, we knew how to... We knew to call the invoker... Or call the factory to do that glue bindery. We will be writing a tech note for that. And so if that's important to you, then it is possible. It's not too bad. Again, that last line I told you about, you have to hold onto the results of that in order to keep it working.

So final note, one of those frameworks underneath that might be interesting to you is the Carbon framework. The toolbox has now been carbonized, and AWT uses the carbonized toolbox. The contract there is that you cannot go rummaging inside a lot of Carbon objects as you used to be able to do on MRJ. So you have to use the accessor functions just like everybody else does. So in this case, we have an example where you have to use the accessor functions instead of going off to some magic offset and pulling out the data yourself.

Finally, our diagram again. What happens when you need to take an entire Java environment and put it inside another application? That is what we used to do with JManager 2, and we have a successor to that, and we don't have a name for it yet. I guess it's the embedding story for Mac OS X. The person who can best speak to this is none other than Jens. I'll call him back up to stage and see if he can run you through some of these examples. He will obviously speak more knowledgeably about it than I will. Thanks.

So we talk about wiring Java into your Carbon application. There's a little asterisk there because we would eventually like this to be able to work for Cocoa applications as well, but the technology to do so isn't quite available yet. So first the bad news. For all of you JManager fans, JManager is not supported on OS X.

The good news is that, well it's actually good news that JManager 2 is not supported because it's a very complicated API. It requires you to do a lot of work in your application. Everybody who did it ended up doing it in kind of slightly different ways and causing incompatibilities for us and our developers, which is actually kind of our fault in the design of the API.

So the good news is that we have a new API and the API is very simple because we now have a modern, we now have a much more modern environment to work in so we don't have the same kind of limitations we did back when we did JDirect 2. So there are a couple of different pieces to what you need to do. First you need to obviously get Java running and you use absolutely cross platform standard JNI, in fact the JNI Indication API to do that.

You need to describe the kind of code that is that you want to embed. In this case, we're talking about applets, since that's the primary target, is the web browser or other application that can show applets. You can also use other kinds of code. You fill out a fairly simple struct with the information about the location or the contents of the applet.

Then you create a Java control or a Java window. Yes, we are using the control manager now. So for better or for worse, the control manager is the sort of component story for X, at least in Carbon. And we have a Java control that you do by going create Java control. And that is mostly all there is to the story.

Once the control is there, you need to be a good host to controls. You need to make sure that your controls, in particular the Java control, get all the events that they need. And I'll talk about that in more detail in a minute. We have a sort of preview of this in DP4, which is mostly just a header file you can look at and start thinking about. This much promised future add-on release will have a functional implementation of it.

So the first step, as I said, is to use JNI to start up the Java virtual machine. And this is exactly how you do it. We typed this in ourselves. We could have torn it out of Sun's Java tutorial or any of the JNI books that are out there at your favorite computer bookstore.

First of all, we set up this Java VM in the arg structure, which is what tells the Java virtual machine all the different parameters it needs for starting up things like the default heap size, stack size, things like that. And we don't care about--we're just going to use the default.

So we fill in the version number in the struct and call JNI get default Java VM init args. And that's going to fill out the structure for us with the default values. And if you wanted to tweak some of those values to increase the heap size or something like that, you could do it after that.

Then all we need is JNI create Java VM. That's going to initialize the Java VM for us and start it up. And it returns us a JVM structure, Java VM structure, which is rarely needed, and a JNI end structure, which is always needed for JNI calls. So we need to save that one off.

Second step is making this magic struct that tells our embedding code where the code you want to run is. In this case, we have a simple example where we're giving it a file path to a local applet that's in our hard disk. So we create this MRJ applet descriptor struct. We do a bit of core foundation magic to create a URL given a Unix style path. And we null out the rest of the structure.

If you wanted to, you could also use a real HTTP or whatever URL to specify that. You can also provide a different code base and doc base. You can also pass in the contents, the raw contents of the applet tag or a pre-parsed set of applet properties. The latter will be more useful to you if you're a web browser and you've already been parsing the HTML. The second step then is to take this MRJ code descriptor and stuff the applet descriptor into it, applets being only one of the ways that you can use to tell which kind of code you want to embed.

Finally, then we embed the control. We need a bounds rectangle that will fill out And then we call Create Java Control, passing in the JNI environment, the window we want the control to go into, the bounding box, and then the code descriptor. And as usual, the last one is an out parameter that actually returns the control back to us.

And that's it. Behind the scenes, the embedding library is going to start up an applet context, go out and load the applet, start up the appropriate threads for it, send it the events, and do some magic stuff with AWT so that the frame that the applet gets embedded into is actually the control in a portion of your window.

So you need to be able to run controls. And for the most part, this is kind of-- Java program or Mac programming 101 type of stuff. There's actually really no extra work to handle Windows that come up. If you-- If you want the applet to come up in a window, or if the applet opens up its own windows after the fact, they simply pop up as windows in your layer.

And the nice thing is that Carbon's event manager does all the work of making sure that events for those windows go to those windows and not into your event loop. So about all you have to do is make sure that you don't step on them. You don't inadvertently, when you're traversing the window list, go and assume that it's one of your windows and dereference the refcon and cast it to your struct and try to do stuff with it. Just pay attention to which windows are yours and which ones aren't.

The same deal goes for menus. If an AWT window is active, it will append menus to your menu bar. And it will remove them when it becomes inactive. And if you go around traversing the menu bar for whatever reason, you need to pay attention to which menus belong to you and which ones don't. And there are some accessor functions in the API that will help you determine whether or not this menu or this window belongs to Java.

For controls, you need to make sure that all the relevant events are dispatched to controls. And in Mac Programming 101 back in the 1984 days, the only kind of things that controls really got were clicks, because the controls were just limited things like buttons and check boxes. With the Appearance Manager, in the last couple of years, things have gotten a lot more sophisticated and controls can now--they can now have focus, they can get key presses, they can do cursor tracking while the cursor's over them, they can do drag and drop.

So there are several new calls in controls.h that are there to allow you to pass those events into the controls. It isn't that much more work to do. There's about three more places in your event loop where you need to do the right kind of control stuff. And the Appearance Manager SDK has all the sample code for how to do that sort of thing.

But the real--the real way to do it, the good way to do it is to have your app adopt the new Carbon event model. If you attended any of the sessions on that yesterday, you'll know that the Carbon event model is incredibly cool. And it's just a vast step forward for the way Mac applications work. Events are dispatched to the objects that they're intended for.

It's a lot more like you're used to with Java programming, where if there's an activate event for a window, well, the Windows event--the Windows event handler will get that event. If there's an event for a control, the controls event handler will get that event. There's no need for the Windows event loop even to get involved. So you get all of this stuff basically for free if you're using the Carbon event model. You put the control on your window and it just runs itself.

At the bottom here, I have a list of some of the new appearance functions that you'll need to use with an old style event loop, create root control, handle control, click, et cetera. And if that's the way you're doing it, then I encourage you to go out and look at the control manager documentation that came out with the appearance manager and with OS 8.5. They're described pretty well in there. So, now I get to be my own demo boy and run the demo back here on this machine.

So I wrote an app pretty quickly that shows off this stuff. And since I wanted to do it pretty quickly, I used the Carbon Event Model. And what I ended up with-- This is probably a little too small for you to read. This is four pages of code, of which the first about two and a half are some kind of generic stuff to Create a new window, add some event handlers to the window, create a text control so we have a text field where we can type in the applet path, add some listeners to that, create a push button so we can push it to run the applet.

very standard Carbon event stuff. We have a window listener function, the text control listener function, And then down here we have the meat, and this all fits on one screen with a little type. We first have Yeah. Down here we have the JNI invocation stuff. And this is almost exactly as it appeared on the slide earlier. We call JNI getDefault, VM init args, and then JNI createJavaVM.

And again, the stuff that shows the applet is almost exactly as it appears. We create a CFStringRef for the path, the CFURLRef, and Then we call Create Java Control. And again, I'm mostly showing the source code just to point out how small this is. There's four pages of code. It took me a very short amount of time to write.

And the application itself looks like this. So being that it's a Carbon Events application, we get all these behaviors for free-- window dragging, window resizing, et cetera. Text field runs. We'll run draw test. Another one of these silly sample applets. Push the Run button, and here's our applet.

We can resize the window. Everything redraws itself as you'd expect. Movable. This applet doesn't happen to do text input, but that works as well.

[Transcript missing]

One more thing to do though. One more thing. Yeah. The debugging demo. The debugging will not work. The demo gods were angry. Pardon? We will not be able to build the application, so we can't run it. I tell you, hours worth of work.

Jens, are you ready to swear in front of all these people? Did debugging work? I solemnly swear that debugging worked. We were able to set breakpoints. Yay, we were even able to step through the code and view stack traces. It was good. It truly is good. Project Builder, which is the intro session that's going on right next to us, which you're not seeing. You've seen a little bit of Project Builder here.

Project Builder is really looking good. We know how to hook up debugging inside of there. Dave Ewing is really doing a great job making all that happen. And we worked really hard to try to get that here to show you, because we honestly don't believe that JDB is the way for you guys to go out and debug Java stuff. Let me try it. Let me try to see that.

Well, there's nothing like praying. OK, if we all bow and cross our fingers. We're just totally living on the edge now, but if we fall down on our pants, please apologize. We'll apologize. So if we can run this thing, then-- so Dave, should I set the breakpoint now? It's in Project Builder. I just hit run. You need to hit debug. How would you debug? Make sure the debugger's set to the Java debugger. Yeah.

[Transcript missing]

Do we have breakpoints set? It says it's waiting to connect. Is this because we're running Hotspot, isn't it? No. Yeah, you're right. Sure. That'll help. You've got to run Java in order to debug Java, it turns out. See, we're loading it lazily. That wasn't good, was it? Forget I tried anything. It worked great before. OK, back to the slides.

Okay, so basically, we know that we've been postponing a lot of questions until now, so we're trying to leave a little bit of time for some questions here. So, you should remember, Java is, you know, wired into the walls of Mac OS X. You shouldn't be shocked at what you find on DP4, because we're going to make it better.

I'm going to point everybody to Alan Samuel to make sure that you know that he's the guy you need to ask about all the updates. Not me. Ask him. So the take home exam, we had a pop quiz at the beginning. Well, I want to just carry the metaphor going, for you to take home.

Write a JNI-enabled Java class, debug your code using a profile of your code to make sure it runs fast, throw away the JNI stuff, use JDirect instead. And finally, since embedding is so simple, I mean, it looks like almost I can program that. And well, anyway, I don't do GUI.

But it'll look simple enough for me to use. So it ought to be simple enough for you guys to use. Roadmap, we only got one other Java session this year at WWDC, and it immediately follows this one. So if you have marketing style questions, if you have kudos for us or non-kudos for us, take those to the feedback forum to find out where we fit in relationship to the rest of the world of Java and things like that. For this session, if you've got technical questions about how something happens and things like that, what I'd like to do is call up members of the Java team. You guys can hit the mics and ask us anything else you want.