Sponsored Link •
Bill Venners: Why don't we switch gears and talk a bit about mobile code. I've had a few concerns about the practicality of sending objects across the network, and I would be curious to hear what your thoughts are. Let's start with finalization.
One of the issues that has come up in Jini discussions is cleaning up after mobile objects. If I'm a client and I receive a mobile Jini service object, that object can consume my local resources by firing off a thread, opening a socket, and so on.
From a Jini lookup service, I can grab service objects about whose interface I have absolutely no prior knowledge. I can grab them by name. I can use the browser methods to find things that look interesting and grab them. If I have prior knowledge of the interface of the object, then there's probably a cleanup method that I'm supposed to call when I'm done with it. If the object is nice, it will relinquish all of my resources that it consumed when I invoke the cleanup method.
James Gosling: Right.
Bill Venners: But first of all, it may not be nice. And second of all, I may not have any prior knowledge of that interface. So how do we make sure that clients don't always run out of resources when they're using mobile code?
James Gosling: There are several answers to that. One is when you stop referencing that object, it goes away. And things that it refers to go away. And the finalizer will get called.
In other words, that it's actually pretty rare to bring in some mobile object, not have some idea what interface it implements. Generally, these pieces of mobile code are used in things like editor plug-ins or database plug-ins, and they tend to do a Class.forName() or some sort of look-up that gives you this new Class object. And you do a newInstance() on it. And then you say, well gee, are you a plug-in for this area? Are you a device manager? Or are you a printer device manager? Then you can start talking to it.
If you have absolutely no idea what you're expecting, just take an arbitrary object in, there's not a whole lot you can do with it other than say, "Hey, isn't this nice?" And almost always, people do have standardized interfaces for these things.
And if you're designing one of these standardized interfaces and having the imported stuff go through some active and passive phases where you're getting rid of, dumping resources and that, then defining a method to clean things up is a good thing to do.
Bill Venners: There's also denial-of-service attacks or bugs where even if you do call the cleanup method, if the method forgets to kill a thread, that thread doesn't go away.
James Gosling: Sure. Denial-of-service attacks are generic and are really hard to deal with. And unfortunately, they're hard to deal with in a relatively deep sense. You can throw some signal at a thread. The stop() methods are there. They're deprecated. The manual says, "Don't use this. Bad things will happen." But they are there, right? And so you can stop a thread.
And all the VMs I know of, stop() actually does work. And unfortunately it does have some side effects, it has some consequences. But it's like the consequences that exist in any other system when you try to forcibly shut down something without giving it a chance to clean up. It certainly happens with Unix processes, with threads, anybody. C library, if you just shoot a bullet into its head, it doesn't clean up.
And if there were things that needed cleaning up, like reconstructing some data structure, like this thing representing a filesystem that's linked into some linked list, you could leave that kind of broken.
It absolutely happens with everybody's systems. Whether it's C threads or Unix processes, you have exactly the same problems. It's essentially impossible to stop a process and guarantee that it will be clean, that it will be graceful. All the deprecation of stop says is you can't guarantee that it's graceful.
And it's not any different than what happens with stop in any other system. It's just that we decided that it was important to spell out to people that this is a dangerous thing to do, and what you really ought to do is do something more graceful.
Where you really get into trouble is where people start using things like stop as a standard way of shutting down a thread. And really, the right way to do it is you have some application-specific way of doing it. The cleanest ways are, generally, if you've got like a thread that's in a loop, doing something, then you put a global variable in there that says, "I want it shut down." Have the thread actually testing it. And then at a point when everything is clean, you exit the loop.
Then, if you have your own cleanup method, you call a cleanup method. And unfortunately, graceful shutdowns, because they are dependent on exactly what the semantics of the operation are, they're intrinsically application-dependent.
So the right thing to do is to do the layered approach to shutting down some thread or some object. Namely, you tried to do it gracefully. If a graceful shutdown doesn't work, then depending on the situation you either pull out a gun and you either shoot that thread, or you shoot the entire system.
Bill Venners: I thought you were going to say shoot the programmer who sent you that code.
James Gosling: Well, right. You kind of pick up your pistol and you decide where to aim it at.