44

The stop(), suspend(), and resume() in java.lang.Thread are deprecated because they are unsafe. The Oracle recommended work around is to use Thread.interrupt(), but that approach doesn't work in all cases. For example, if you are call a library method that doesn't explicitly or implicitly check the interrupted flag, you have no choice but to wait for the call to finish.

So, I'm wondering if it is possible to characterize situations where it is (provably) safe to call stop() on a Thread. For example, would it be safe to stop() a thread that did nothing but call find(...) or match(...) on a java.util.regex.Matcher?

(If there are any Oracle engineers reading this ... a definitive answer would be really appreciated.)

EDIT: Answers that simply restate the mantra that you should not call stop() because it is deprecated, unsafe, whatever are missing the point of this question. I know that that it is genuinely unsafe in the majority of cases, and that if there is a viable alternative you should always use that instead.

This question is about the subset cases where it is safe. Specifically, what is that subset?

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • This isn't just a Java phenomenon: in general, the underlying operating system calls that Thread.stop() makes to abruptly stop the thread are also deprecated for this reason. – KV Prajapati Aug 16 '09 at 03:41
  • 2
    @adatapost: Really? I looked at "man pthread_cancel" and it doesn't say it is deprecated. – Stephen C Aug 16 '09 at 04:36
  • 2
    @adatapost: That's simply untrue. Forcibly shutting down a thread or process is not deprecated in any OS I can think of. – Ben S Aug 16 '09 at 05:43
  • The pthread_cancel() function requests that thread be canceled. The target threads cancelability state and type determines when the cancellation takes effect. There's detailed control to prevent cancellation when its not safe. – djna Aug 16 '09 at 05:43
  • @djna: "There's detailed control" is a bit of an overstatement as you have very little control over library functions that include cancellation points. – Fredrik Aug 16 '09 at 06:01
  • 3
    @Fredrik - I thought that the idea was that the target thread has teh control - he can say "not yet"! So pthread_cancel() on the surface appears to do what Stephen wants, but in fact relies on cooperation from the thread. – djna Aug 16 '09 at 06:24
  • At the end of the day, even if someone will define such "subset", Java language and platform doesn't have any facilities to distinguish "safe to stop" code from "unsafe to stop" one (and introducing something for that will GREATELY complicate the language without an obvious need). So, the question is pointless. – Vanya Jul 07 '10 at 06:59
  • @Vanya: 1) Who mentioned changing the language or the runtime system? I didn't!!! 2) My idea (perhaps naive) was that one could come up with a set of rules (e.g. based on annotations) that a static analyser could check. 3) There **is** an obvious need to be able to safely kill Java threads. For example, look at all of the related SO questions. Unfortunately, that need is not met. – Stephen C Jul 07 '10 at 07:27
  • There is no need to kill threads. There is certainly a need to design one's threads with a way to bail out on their own if something doesn't work. This is the only safe way, as far as I know. – Vladimir Dyuzhev Apr 03 '11 at 19:33
  • 2
    @Vladimir - what about the case where you have a **hard requirement** to execute untrusted code ... and kill it when it goes bad. There are use-cases where the ability to kill threads is critical. – Stephen C Apr 03 '11 at 22:30
  • You shouldn't execute untrusted code in a trusted process (first J2EE hosters learned it a hard way, including funny things like System.exit()). You would start a child process. Killing a child process is a safe operation (for your own JVM; it may still mess up external resources). – Vladimir Dyuzhev Apr 04 '11 at 21:09
  • 1
    @Vladimir - circular reasoning alert! The primary reason that you should't run untrusted code in the same JVM as your main app is that you can't kill the untrusted code. Sandboxing using a security manager should take care of other concerns. System.exit() can be blocked by the security manager, for example, as can access to external files, the network, use of reflection, and so on – Stephen C Apr 04 '11 at 22:45
  • @Vladimir - ah. I've just realized that sandboxing is insufficient to stop malicious code from doing things to make itself (at least) *appear* to be not safely killable. Preventing that would probably entail modifying JVM behaviour. – Stephen C Apr 04 '11 at 23:31
  • The situation in this question has happened to me once (only once, though). I was trying to extract raw text from a set of PDF files with iText. However, some of the files made iText screw up and go in an infinite loop. At that time, I had no other alternative library that could do the job, and no way of detecting ahead of time which file would cause the library to go into an infinite loop. The solution: Process each PDF file in a new thread, and if the thread hasn't terminated before a pre-set delay, kill it with Thread.stop from the control thread. That's a legitimate use of that method IMO. – LordOfThePigs Aug 31 '12 at 15:50
  • @LordOfThePigs - It is clearly legitimate to want / need to call `Thread.stop()` in a lot of situations. The point at issue is whether it is safe not whether it is legitimate. (And the fact that it seems to work for you is not sufficient to say that it is *really* safe.) – Stephen C Apr 30 '13 at 13:21

8 Answers8

19

Here's my attempt at answering my own question.

I think that the following conditions should be sufficient for a single thread to be safely stopped using Thread.stop():

  1. The thread execution must not create or mutate any state (i.e. Java objects, class variables, external resources) that might be visible to other threads in the event that the thread is stopped.
  2. The thread execution must not use notify to any other thread during its normal execution.
  3. The thread must not start or join other threads, or interact with then using stop, suspend or resume.

(The term thread execution above covers all application-level code and all library code that is executed by the thread.)

The first condition means that a stopped thread will not leave any external data structures or resources in an inconsistent state. This includes data structures that it might be accessing (reading) within a mutex. The second condition means that a stoppable thread cannot leave some other thread waiting. But it also forbids use of any synchronization mechanism other that simple object mutexes.

A stoppable thread must have a way to deliver the results of each computation to the controlling thread. These results are created / mutated by the stoppable thread, so we simply need to ensure that they are not visible following a thread stop. For example, the results could be assigned to private members of the Thread object and "guarded" with a flag that is atomically by the thread to say it is "done".

EDIT: These conditions are pretty restrictive. For example, for a "regex evaluator" thread to be safely stopped, if we must guarantee that the regex engine does not mutate any externally visible state. The problem is that it might do, depending on how you implement the thread!

  1. The Pattern.compile(...) methods might update a static cache of compiled patterns, and if they did they would (should) use a mutex to do it. (Actually, the OpenJDK 6.0 version doesn't cache Patterns, but Sun might conceivably change this.)
  2. If you try to avoid 1) by compiling the regex in the control thread and supplying a pre-instantiated Matcher, then the regex thread does mutate externally visible state.

In the first case, we would probably be in trouble. For example, suppose that a HashMap was used to implement the cache and that the thread was interrupted while the HashMap was being reorganized.

In the second case, we would be OK provided that the Matcher had not been passed to some other thread, and provided that the controller thread didn't try to use the Matcher after stopping the regex matcher thread.

So where does this leave us?

Well, I think I have identified conditions under which threads are theoretically safe to stop. I also think that it is theoretically possible to statically analyse the code of a thread (and the methods it calls) to see if these conditions will always hold. But, I'm not sure if this is really practical.

Does this make sense? Have I missed something?

EDIT 2

Things get a bit more hairy when you consider that the code that we might be trying to kill could be untrusted:

  1. We can't rely on "promises"; e.g. annotations on the untrusted code that it is either killable, or not killable.

  2. We actually need to be able to stop the untrusted code from doing things that would make it unkillable ... according to the identified criteria.

I suspect that this would entail modifying JVM behaviour (e.g. implementing runtime restrictions what threads are allowed to lock or modify), or a full implementation of the Isolates JSR. That's beyond the scope of what I was considering as "fair game".

So lets rule the untrusted code case out for now. Or at least, acknowledge that malicious code can do things to render itself not safely killable, and put that problem to one side.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • The use of reflection APIs would allow the executing code to be selected dynamically, hence potentially defeating the static analysis, so perhaps you would need to prohibit that? – djna Aug 17 '09 at 07:27
  • If you blow away a thread that happens to be in a synchronized method, and consequently perhaps blocking some other thread, do we know that Java on the death of the first thread will ensure that the other thread will run? – djna Aug 17 '09 at 07:40
  • 1
    The problem for me with static analysis adding information above the documented API is that your application design depends upon "uncontracted" behaviour - the library author has not promised that their next release will not do something (or use another library that does something) unsafe. – djna Aug 17 '09 at 07:44
  • @djna - in practice, is this any different from the library author changing the contract at the next release and breaking things? Either way, the solution is to do what we always do: analyse / test against all of the releases that we "support" and call the rest "unsupported". – Stephen C Apr 03 '11 at 22:21
10

The lack of safety comes from the idea idea of critical sections

Take mutex

do some work, temporarily while we work our state is inconsistent

// all consistent now

Release mutex

If you blow away the thread and it happend to be in a critical section then the object is left in an inconsistent state, that means not safely usable from that point.

For it to be safe to kill the thread you need to understand the entire processing of whatever is being done in that thread, to know that there are no such critical sections in the code. If you are using library code, then you may not be able to see the source and know that it's safe. Even if it's safe today it may not be tomorrow.

(Very contrived) Example of possible unsafety. We have a linked list, it's not cyclic. All the algorithms are really zippy because we know it's not cyclic. During our critical section we temporarily introduce a cycle. We then get blown away before we emerge from the critical section. Now all the algorithms using the list loop forever. No library author would do that surely! How do you know? You cannot assume that code you use is well written.

In the example you point to, it's surely possible to write the requreid functionality in an interruptable way. More work, but possible to be safe.

I'll take a flyer: there is no documented subset of Objects and methods that can be used in cancellable threads, because no library author wants to make the guarantees.

fredley
  • 32,953
  • 42
  • 145
  • 236
djna
  • 54,992
  • 14
  • 74
  • 117
  • @djna: Re your last point. I wouldn't rely on documentation anyway. Rather, I'd want to use a static code analysis tool to ensure that a thread can be safely stopped; e.g. see my answer. – Stephen C Aug 17 '09 at 01:57
  • 1
    Java locks held by terminated threads are released, if I remember right. Which doesn't help with the state of lock-protected objects, which may be half-changed. – Vladimir Dyuzhev Apr 03 '11 at 16:14
  • @Vladimir - that's right. However, if you could figure out that nothing else is going to be influenced by the objects again, then the fact that they are inconsistent would be moot. – Stephen C Apr 04 '11 at 22:49
1

Maybe there's something I don't know, but as java.sun.com said, it is unsafe because anything this thread is handling is in serious risk to be damaged. Other objects, connections, opened files... for obvious reasons, like "don't shut down your Word without saving first".

For this find(...) exemple, I don't really think it would be a catastrophe to simply kick it away with a sutiless .stop()...

Havenard
  • 27,022
  • 5
  • 36
  • 62
  • Yea ... that is my gut feeling as well. But gut feeling is not good enough when you are trying to build robust servers. – Stephen C Aug 16 '09 at 02:43
  • 1
    It's madness to be calling a deprecated method if anything that isn't for fun. – Noon Silk Aug 16 '09 at 03:00
  • 1
    @silky: it is madness to rule something out *just because* someone else says it is madness :-) – Stephen C Aug 16 '09 at 04:23
  • @Stephen C haha, touche, okay I take that :) But in this case it's the Java Designers telling you; and they're more authorative on their language then either of us :) – Noon Silk Aug 16 '09 at 04:53
  • @silky: But they don't say it is **always** unsafe, do they? – Stephen C Aug 16 '09 at 05:18
  • They say why its unsafe but not clearly enough to get where it is not. -- Same happens in C with functions like strcat() and sprintf(), you must comprehend Buffer Overflows to realize why it is considered unsafe, deprecated, and how to use it safely. – Havenard Aug 16 '09 at 05:40
  • @Havenard: and the point of my question is to try to get a clear(er) picture of when it >>is<< safe! – Stephen C Aug 17 '09 at 13:03
  • It is never safe. Even if your Java thread does literally nothing, native thread may have done something to be properly reversed. – Vladimir Dyuzhev Apr 03 '11 at 16:48
  • @Dyuzheh - this makes no sense to me. Please explain what you are talking about. If the Java thread does absolutely nothing, then so will its native thread ... by definition. – Stephen C Apr 03 '11 at 22:25
  • Native thread may have done more than Java thread before it paused on a lock or sleep(). It most probably went into kernel mode to allocate resources there. It may support multiple client-side threads in NxM model. It cooperates with other native threads within JVM to ensure smooth working of it. Kill it and the consequences are unpredictable. – Vladimir Dyuzhev Apr 04 '11 at 20:54
  • @Vladimir - ah, I see what you are talking about: stuff that happens during a call into a native method. Yes, well there are some issues there ... not least because Sun probably haven't spent lots of time implementing / testing what happens on the JVM native code when a thread is killed. But the simple answer is to say that any thread that executes native calls that are not in some hypothetical "white list" is not safely killable. – Stephen C Apr 04 '11 at 23:23
0

A concrete example would probably help here. If anyone can suggest a good alternative to the following use of stop I'd be very interested. Re-writing java.util.regex to support interruption doesn't count.

import java.util.regex.*;
import java.util.*;

public class RegexInterruptTest {

    private static class BadRegexException extends RuntimeException { }
        final Thread mainThread = Thread.currentThread();
        TimerTask interruptTask = new TimerTask() {
            public void run() {
                System.out.println("Stopping thread.");
                // Doesn't work:
                // mainThread.interrupt();
                // Does work but is deprecated and nasty
                mainThread.stop(new BadRegexException());
            }
        };

        Timer interruptTimer = new Timer(true);
        interruptTimer.schedule(interruptTask, 2000L);

        String s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
        String exp = "(a+a+){1,100}";
        Pattern p = Pattern.compile(exp);
        Matcher m = p.matcher(s);
        try {
            System.out.println("Match: " + m.matches());
            interruptTimer.cancel();
        } catch(BadRegexException bre) {
            System.out.println("Oooops");
        } finally {
            System.out.println("All over");
        }
    }
}
Richard Wheeldon
  • 973
  • 10
  • 25
  • The only alternative would be to run the regex match in a separate JVM that can be killed. (Which is pretty expensive ... ). However, this looks like the kind of use-case where `Thread.stop()` might be safe. – Stephen C Jul 07 '10 at 07:35
  • This is a workaround to a bug (lack of DoS prevention) in the Pattern class. The long-term solution is not to kill a thread, but to fix the Pattern class. – Vladimir Dyuzhev Apr 03 '11 at 19:38
  • 1.6.0_21: no problem with this regexp. Fixed? – Vladimir Dyuzhev Apr 03 '11 at 19:42
  • @Vladimir - have you heard of the Halting Problem? :-) Now I'm not saying that it is impossible to detect regexes that will behave in a pathological fashion. (I don't know the answer to that.) However, it has been proven that it is impossible to determine if an arbitrary deterministic computation will terminate. So there is a clear need to be able to kill such a computation. – Stephen C Apr 04 '11 at 11:32
  • No argument there is a practical need to kill a runaway thread. But it doesn't make the kill a safe operation. One may just hope. Besides, it's not always required to find out if a code will take forever. Enough if the code would have a periodic self-checks or callbacks "am I running for too long?" and stops if it is true. – Vladimir Dyuzhev Apr 04 '11 at 21:01
  • 1
    Regular expressions (excluding backreferences) can process arbitrarily large input in linear time: http://swtch.com/~rsc/regexp/regexp1.html – David Phillips Apr 17 '13 at 00:49
0

There are ways to use Thread.stop() relatively stable w/o leaking memory or file descriptors (FDs are exceptionally leak prone on *NIX) but you shall rely on it only if you are forced to manage 3rd party code. Never do use it to achieve the result if you can have control over the code itself.

If I use Thread.stop along w/ interrupt() and some more hacks stuff like adding custom logging handlers to re-throw the trapped ThreadDeath, adding unhandleExceltionHandler, running into your own ThreadGroup (sync over 'em), etc...

But that deserves an entire new topic.

But in this case it's the Java Designers telling you; and they're more authorative on their language then either of us :)

Just a note: quite a few of them are pretty clueless

bestsss
  • 11,796
  • 3
  • 53
  • 63
  • 1
    I'm sorry, but your answer says nothing about when it is **provably** safe to use `Thread.stop`. That's what the question is really about. And the gratuitous insult to the Sun guys isn't helpful either. – Stephen C Dec 27 '10 at 01:28
  • No need to be sorry. Again you should never use thread.stop() to control the flow of any code you have control of. There are cases with 3rd party libraries that you have no other option but use thread.stop(). If you use custom classloader for the 3rd party library it will be almost always safe to use thread.stop(). Might need to clean stuff (imagine registering jdbc driver) to prevent leaks. I gave another example of using custom logging handlers to prevent code like: for(;;){ try{ .... }catch(Throwable _t){//log here } } – bestsss Jan 02 '11 at 22:34
  • Forgot: object monitors are not damaged b/c of thread.stop(); – bestsss Jan 02 '11 at 22:56
  • Upon reflection: the most dangerous about thread.stop() is not leaving any object state inconsistent since you are supposed to be prepared for it and dump anything but exception (ThreadDeath) into class initializers . Any exception there makes the class 'broken', this is why the need to a custom classloader to ensure the classes can also be dumped into the void if need be. Plus any singleton and static states can be discarded. Baring that ThreadDeath (i.e. thread.stop()) is not much different from StackOverflowError (nice pun w/ the name of the site) or any other VirtualMachineError. – bestsss Jan 03 '11 at 10:48
  • *"Again you should never use thread.stop() to control the flow of any code you have control of."* - If it is **provably** safe to call `Thread.stop()` in a given situation, then there is nothing wrong with calling it *in that situation*. For instance, if `Thread.stop()` was safe, it would be a better option than checking the `interrupted` flag all over the place. – Stephen C Sep 22 '11 at 04:31
  • @StephenC, no need to check it all-over-the-place at all. The main problem is how hard it is to prove it's absolutely safe and that the code won't make a call to some shared modification state. The generated JIT code checks something similar to Thread.interrupted, stop() is honored at safe points only after all. If using Thread.stop(), I make sure everything loaded by the current classloader also dies, otherwise there is a risk of damaged shared state. For sand boxing customer deployed code we just pepper the bytecode (dynamically) w/ traps, similar to safe points but w/ more control. – bestsss Sep 22 '11 at 05:55
  • *"The generated JIT code checks something similar to Thread.interrupted, stop() is honored at safe points only after all."* That is a hypothetical solution. In practice, the approach probably fails because tracking the safe points would be too expensive ... even if it is technically possible to do this. – Stephen C Nov 10 '12 at 00:30
  • @StephenC, I am not sure what you mean. The threads routinely check to do some service at the safe points and that includes even revocation of biased locks, waiting for (re)compilation or GC. The check for safe points is not so expensive - a simple polling: it is a load (usually L1 hit) and check (usually predicted by the hardware) - really few CPU cycles. The JVM generally does not put safe points in tight loops. – bestsss Dec 14 '12 at 12:53
  • Hang on. This question is all about being able to *statically* prove that calling `Thread.stop()` is safe in a particular situation. It would be tricky to get hold of JIT'ed code statically ... let alone THE JIT'ed code the the actual execution. Then you have to reverse engineer the safe points from the native code and so on. But it gets worse ... – Stephen C Dec 14 '12 at 23:38
  • The worse-ness is that a GC safe-point or thread switch safe-point is not the same as a point where it is safe to call `Thread.stop()`. The latter needs to take account of such things as whether the thread is interacting with some other thread (sleep/wait or higher level), updating a data structure under a mutex or `Lock` and so on. Figuring out where the "stop safe-points" are would in general be hard. – Stephen C Dec 14 '12 at 23:47
  • @StephenC, where the ThreadDeath exception is raised is sort of random (or shall be considered so). The point was that checking `Thread.interrupted` is not much worse in terms of performance than what `Thread.stop()` does. Like I've told calling `Thread.stop()` the module shall be able to discard any (shared) state. It's hard if the code is not within the domain of the module (e.g. somewhere in java.util.logging) but it's doable. IMO, overall `Thread.stop()` is viable but you just can't use it w/o much extras/framework and then peppering (ClassLoading enhance) the loaded code w/ checks... – bestsss Dec 15 '12 at 14:36
  • ...is also viable and very robust. I still use it in production (for servers that get no restart in months) but it has way too many pitfalls to be used w/o preparation. – bestsss Dec 15 '12 at 14:37
  • about proving: if the code/module (short for thread) does not hop to some of core java classes (but not all, too many to list) and the code stays within it's designated domain, i.e. takes gates/proxies to communicate to other parts of the application -- it'd be safe to stop the thread and I tend to stop the entire thread group the thread belongs. – bestsss Dec 15 '12 at 14:46
  • You may be able to convince yourself that what you are doing is safe, but that does not mean that it actually is. A proof is a proof. If the proof is sound, you have absolute certainty. If not, then ... you might be wrong. My questions is **explicitly** about circumstances where it is **provably** safe to call `stop()` etc on another thread. – Stephen C Dec 16 '12 at 00:57
  • I tried to explain, I will simplify it. You need critical section lock/CAS to be available. Each code path that goes out of the designated domain needs proxy that locks the section, upon return it throws ThreadDeath on its own when a termination is necessary. If the lock is unavailable, then it's not provable and it works similar to Thread.interrupt except you truly expect that *interrupt request* to be honored. The unsafe part includes a lot of built in java stuff (but not that much) - logging/awt/swing, sql needs wrappers, etc. Parent classloader also needs to lock and so on. – bestsss Dec 16 '12 at 23:04
-1

If my understanding is right, the problem has to do with synchronization locks not being released as the generated ThreadInterruptedException() propagates up the stack.

Taking that for granted, it's inherently unsafe because you can never know whether or not any "inner method call" you happened to be in at the very moment stop() was invoked and effectuated, was effectively holding some synchronization lock, and then what the java engineers say is, seemingly, unequivocally right.

What I personally don't understand is why it should be impossible to release any synchronization lock as this particular type of Exception propagates up the stack, thereby passing all the '}' method/synchronization block delimiters, which do cause any locks to be release for any other type of exception.

I have a server written in java, and if the administrator of that service wants a "cold shutdown", then it is simply NECESSARY to be able to stop all running activity no matter what. Consistency of any object's state is not a concern because all I'm trying to do is to EXIT. As fast as I can.

Erwin Smout
  • 18,113
  • 4
  • 33
  • 52
  • 1
    -1 this is wrong. The problem is that locks are released, but that there is nothing to guarantee that the data-structures they protected are in a consistent state. – Stephen C Aug 17 '09 at 01:12
-2

There is no safe way to kill a thread.

Neither there is a subset of situations where it is safe. Even if it is working 100% while testing on Windows, it may corrupt JVM process memory under Solaris or leak thread resources under Linux.

One should always remember that underneath the Java Thread there is a real, native, unsafe thread.

That native thread works with native, low-level, data and control structures. Killing it may leave those native data structures in an invalid state, without a way to recover.

There is no way for Java machine to take all possible consequences into account, as the thread may allocate/use resources not only within JVM process, but within the OS kernel as well.

In other words, if native thread library doesn't provide a safe way to kill() a thread, Java cannot provide any guarantees better than that. And all known to me native implementations state that killing thread is a dangerous business.

Vladimir Dyuzhev
  • 18,130
  • 10
  • 48
  • 62
  • I don't agree since I'm calling thread.stop() on misbehaving threads as last solution and my server since then runs stable for whole year long, which proves that it is safe (enough). – Pavel Niedoba Mar 15 '17 at 12:07
-4

All forms of concurrency control can be provided by the Java synchronization primitives by constructing more complex concurrency controls that suit your problem.

The reasons for deprecation are clearly given in the link you provide. If you're willing to accept the reasons why, then feel free to use those features.

However, if you choose to use those features, you also accept that support for those features could stop at any time.

Edit: I'll reiterate the reason for deprecation as well as how to avoid them.

Since the only danger is that objects that can be referenced by the stoped thread could be corrupted, simply clone the String before you pass it to the Thread. If no shared objects exist, the threat of corrupted objects in the program outside the stoped Thread is no longer there.

Ben S
  • 68,394
  • 30
  • 171
  • 212
  • @Ben: but what if the complex concurrency solutions simply do not solve the problem? For example: http://stackoverflow.com/questions/1282824/how-to-set-a-time-limit-on-a-java-function-running-a-regex – Stephen C Aug 16 '09 at 04:34
  • @Stephen C: I think in such cases, the `Thread` which requires arbitrary interruption should be implemented as a separate `Process` instead, and forcibly shut down using termination signals to be done safely. I've added my answer to the question you referred to. – Ben S Aug 16 '09 at 05:35
  • Even cloning the String doesn't absolutely guarantee safety. You don't know whether the String class does anything clever with the string representations. Does it share buffers for identical strings? Does it cache internal pointers to substrings to optimise searches? When you call myString.find() what processing does it do? – djna Aug 16 '09 at 05:56
  • @djna: "You don't know whether the String class does anything clever with the string representations." Yes, I do. It's open source. Also, by convention, the clone method performs a deep copy of objects which eliminates any possible shared state. This can be seen in the String implementation. – Ben S Aug 16 '09 at 06:01
  • @djna: If the String class was not open source, you could pass a copy of a `char[]` containing the string instead. – Ben S Aug 16 '09 at 06:14
  • 1
    @Ben S. What do we "know"? If we have the source we can by inspection determine whether any code used in a thread can safely be cancelled. For each new release of that source we must perform that inspection. But my point here was that in general we don't have the source for libraries, and even apparently trivial interfaces may have deep **unsafe** complexity. – djna Aug 16 '09 at 06:30
  • 1
    @Ben S. How you create the String is not important to my argument. the String implementation could on construction do all manner of optimisations, such as spotting that it already has seen that array of chars. It could when doing a find() within a String build a little dictionary. We can't infer from the interface what is going on. Simple example of an implementation surprise **x = new Integer(8); y = new Integer(8);** x and y actually point to the same Integer!! There's a cunning internal optimisation for small Integers. – djna Aug 16 '09 at 06:35
  • @djna: The `Integer` optimization is well documented. Because caching like this can cause those issues all of the standard Java classes have clear documentation on whether or not objects are cached. I trust that the Sun engineers have documented their caching, if in doubt, read up on all the classes you use. – Ben S Aug 16 '09 at 06:42
  • @Ben S - Maybe it was a bad example. The point I was trying to make is that a reading of the interface cannot in itself indicate that the cancellation is safe. I thought you were asserting that cloning a String was guranteed to result in a safe cancellation situation. I was trying to illustrate that there can be linkages "under the covers" that can't be directly inferred from the interface. Short of trustworthy documentation we can only look at the implementation. – djna Aug 16 '09 at 07:27
  • @djna: clearly we don't have trustworthy documentation on this point, but I believe that there are other ways to approach this problem. – Stephen C Aug 17 '09 at 13:05