The example I posted a few posts backs, but will include again here for your non-scrolling pleasure, shows exactly what’s so bad about random unchecked errors getting thrown.
public synchronized switchBuffers()
{
ByteBuffer tmp = buffer0;
buffer0 = buffer1;
// If the thread happens to be stopped here, you're screwed.
buffer1 = tmp;
}
If the ThreadDeath gets thrown on the commented line, your application is corrupted and broken, but you will have no indication of anything going wrong until later on when the fact that buffer0==buffer1 causes an error.
You’ll have no way of knowing that the thread.stop() caused it, and you’ll have a VERY hard time reproducing it.
If you compare this to other errors that can occur at random, such as OutOfMemoryError, that one at least makes the jvm spit out a warning on stderr.
Hehe…and I would say to that… Trust me: If you think you need it you just don’t have enough experience with Java and threading to understand how you never HAVE to use it.
I am new to game programming as a specific application type, but not Java or threading.
I challenge anyone on this board to show me one situation where you need stop(). I’ll fix it or show you why stop can’t “stop” it anyways.
err…wrong…returning from run() ends it. Using stop causes ThreadDeath to be thrown which will be thrown all the way through your run() loop which leads to ending your loop, which leads to ends your thread.
[quote]I challenge anyone on this board to show me one situation where you need stop(). I’ll fix it or show you why stop can’t “stop” it anyways.
[/quote]
Third party plugins.
I built a system like that once. It was a server that was supposed to launch third party “game servers” on demand, and we had to isolate the plugins in their own classloaders and theadgroups, then make sure the callbacks they made were thread.kill() safe.
When stopping a game server, we first just called server.stop(), but if they didn’t stop within 50 seconds, we killed the entire threadgroup.
Of course, the CORRECT way to do this is to make sure that there are no bugs in the game servers, but since they were third-party, we couldn’t do that.
Well, I would say you should use a different plugin if it is doing something that requires you to use stop().
It’s either a) in an endless loop or b) using a blocking native call
a) means it’s bad code and shouldn’t be trusted anyway
b) means killing with stop will probably leave lost resources, which if done enough will lead to requiring an OS reboot.
[quote]Of course, the CORRECT way to do this is to make sure that there are no bugs in the game servers, but since they were third-party, we couldn’t do that.
[/quote]
I would make them fix it or not use it, But I see your point. Their bug is making your software liable for whatever damage they cause. In OS’s such as windows this can lead to very nasty issues that would seem to stem from your program.
The code wasn’t trusted at all. It’s running with security restrictions, and couldn’t call native applications.
I’m personally very opposed to using thread.stop(), but I think this was actually one situation that required it.
Of course, if we were just going to run a handful of these servers, we could’ve started each plugin in a separate jvm and killed it with System.exit(0) when the game server refused to play along, but we were supposed to be able to run thousands(*) of games from a single server.
When writing server code, you CANNOT just go “oh, our server can’t shutdown. You can ask it to shutdown, and it might, but then again it might not. It won’t save any data until it’s shutdown; but because it might not shutdown, it might not save any data”.
IIRC there are also still a handful of blocking-socket situations where Thread.interrupt() is ignored but Thread.stop() succeeds. I would have to double-check my bugs to be sure.
Yup, exactly. c.f. my Samuel Jackson quote; this kind of stuff makes thread-stop the only solution.
or c) it uses networking, which in Sun’s JVM’s has some “permanent block” situations (2 in NIO, 3 in IO IIRC - but don’t quote me on that).
In general, this is ridiculous. It doesn’t even get that far: the situation is simply “can you write code that stops the server or can’t you?”. You don’t worry about other people’s liabilities, you just write code that works in the first place.
If being diligent, e.g. with grexengine stuff, I would do:
0. write a method that takes a nuimber of millis to wait for shutdown
switch on a “terminate” boolean
interrupt the thread
wait a little
3.b. the interrupted thread interrutps the waiting thread as soon as it is done
if interrupted, return
else, call thread stop to really kill it
(if really concerned, wait a little longer, and double check the thread is gone)
I have not found a substitute for step 5 that ensures the shutdown actually works yet avoids using Sun’s deprecated methods.
What in nio would you need to use that has permanent blocking that can’t be interrupted?
You can write the code that stops the server without stop(), (unless you show a nio example that illustrtrates why you can’t)
That is a good example but it shouldn’t happen if the code running is out of development. However, for completeness i’ll buy that it’s an option. You made it sound like you use it to shutdown everything.
To summarize where stop should actually be used:
stop() should be called ONLY for circumstances when something that is completely outside of your control because of something that someone may do to extend your application through your API’s after you have realeased it and only as a last resort consequence to handle the possible mis-guided programmer errors that may occur at some point in the future AND where you are confident that you can handle the situation better then letting the underlying operating system terminate the server after releasing all the resources you still have control over and reporting to the user the situation as well as giving them the option to allow you to take over the operating systems role and directly terminate using an API that may not be available in future releases and has known consequences to OS level system stability.
[quote]That is a good example but it shouldn’t happen if the code running is out of development. However, for completeness i’ll buy that it’s an option. You made it sound like you use it to shutdown everything.
[/quote]
Ah, and that’s the thing isn’t it?
In the real world, crap code gets everywhere. Worse, developers are often forced to use it because of management decisions, internal politics, lack of alternatives etc etc. Something like Thread.stop() is a handy method to have around, because there are situations where you need to take a shotgun to a running process - as explained above.
But it’s good that it’s deprecated, as it stops most people using it. It’s bad that it’s deprecated because you technically can’t rely on it.
What we really need is another method annotation that says “don’t use it unless you have to” other than “deprecated”.
Here here. I’ve been saying this for years…pretty much ever since someone decided to blatantly abuse the deprecated tag in a few cases.
@ vorax: as mentioned previously, there are problems with sun’s interfacing with sockets. Most memorable occasion is that with old I/O you cannot interrupt a thread that is blocking on a connection that you KNOW has been closed down on the other end.
As for “this is unusual” that’s just crap. Every few seconds someone disconnects from your server, and they do it in many different ways, and you need to clear up resources for each of them, and do it FAST.
Ditto with dynamic class reloading: if you’re upgrading a class live without restarting the JVM you want to get rid of all instances of objects using the old version and migrate over to the new. You can’t just have method calls that “may or may not stop the thread”.
…and lots of other scenarios I’m sure you can think of…
It’s called “stop” for a reason: it’s “stop”, not “pleaseCleanUpWheneverYoureReady()” (which is all you can do otherwise).
According to Sun, stop() can’t do any better then interrupt for blocked network sockets. My bet, especially in terms of stop()ing sockets would be that you are loosing resources at the OS level from such a call, thus not realy gaining anything.
Again, you may not really be freeing the resource, just making the fact that it is no longer available hidden from your application. I do know a thing or two about programming servers in Java in a fault tolerant, 24/7 environment. I designed and lead the construction of a product that is running all over the world that supports over 1 million simultaneous connections for MMS/SMS (cell phone) services as well as having worked on several other wireless services servers. If you have a cell phone with messaging services, you probably are running some of my code. There is no stop() calls in any of them.
Why not do it the way J2EE does it? Keep both instances active and wait for the clients to drop the references to the old then let them be GC’d as usual.
Ahh…but that’s the point, it may not really clean up
Anyway, your other example is a reasonable reason to use it, so i’ll give you that. It’s a bit of a religious thing. My back ground is in 24/7 systems, so I tend to take a hard line about system stability…though not all situations require such hard/fast rules.