0

Is it safe according to the java memory model to be able to pass a String between two threads.

In it's simplest is the following always safe:

    public static void main(String[] args) throws Exception {
        String arg0 = args[0];
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> System.out.println(arg0));
        future.get();
    }

or something like:

    public CompletableFuture<String> reallyNotAGoodImplementation(String arg1, String arg2) throws Exception {
        return CompletableFuture.supplyAsync(() -> arg1 + "," + arg2);
    }

Before yesterday I would have been unequivocal in saying that is definitely safe as String is a nice immutable object etc, but I some cause to believe that this might not be safe all the time.

I have some rare exceptions from a running application that indicate that the once in running in the new thread the Strings appear to be invalid, ie have a null value char array.

said exception:

java.lang.NullPointerException
   at java.lang.String.length(String.java:623)

Caused by: java.lang.NullPointerException
   at java.lang.String.getBytes(String.java:941)

Note that they are NPE's from inside String.length() and String.getBytes() (java 1.8.0_77)

Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
  • 1
    If you don't leave the Java-World this is correct. Would you be able to provide more context on the code failing? Do you have native code, that might manipulate data without Java's safeguards? From the example you provide there is not much one can say. – revau.lt Nov 15 '16 at 10:32
  • *I have some rare exceptions from a running application that indicate that the once in running in the new thread the Strings appear to be invalid, ie have a null value char array.* You really need to post more data on those exceptions. – Andrew Henle Nov 15 '16 at 10:46
  • I'm afraid confidentially means I can't share any specifics. I'm just attempting to sanity check that I thought was true is true. – Gareth Davis Nov 15 '16 at 10:50
  • @revau.lt I'm reasonability certain that there isn't any native code...I'm just going to be looking at Jackson as the string in question is read from a json blob from the network – Gareth Davis Nov 15 '16 at 11:08
  • Is the above posted code representative? Is all data passed to your thread immutable and all `String` objects are passed to your thread either directly or through hierarchies of immutable objects? – revau.lt Nov 15 '16 at 11:08
  • Ok. You find yourself with a String with a null value inside, the question is how this is possible. Can you tell us how the String in question gets constructed? Any special charsets, maybe? – revau.lt Nov 15 '16 at 11:18
  • The only thing to consider is memory ordering, make sure there is always an *happen-before* (or a *synchronize-with*, as it implies the first) relationship between the write and read of the string. Creating a thread create an *happen-before* relationship, `volatile` creates a *synchronize-with* relationship. – Margaret Bloom Nov 15 '16 at 14:22
  • The problem comes from within the String class. Since the char[] value within String is final initialization and publication of String is safe if the public constructors are used, the only possibility is that a String is modified or created unsafely. http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3 http://stackoverflow.com/questions/37707497/nullpointerexception-at-java-lang-string-lengthstring-java611 . Is this your case, e.g. a deserialization framework? – revau.lt Nov 15 '16 at 16:02

0 Answers0