This is a brief, basic explanation, the actual behavior can vary based on compiler and JVM used. Also there are a lot of articles available that go into this topic in depth and can provide more detailed explanations.
These literals will be put in the JVM's string pool and never be GC'ed. (i.e. they will exist in memory for the duration of the JVM.
"It", "was", " ", " roses", " roses all the way"
Then, as far as the String references are concerned, It depends on the scope of the variables. I will assume local method level for this answer:
String s1 = "It"; // a reference will be created on the stack
String s2 = "was"; // a reference will be created on the stack
String s3 = s1+" "+s2; // a reference will be created on the stack for s3, and then two temp objects will be created in memory, one for s1+" ", one for concatenating the result with +s2. (this operation can vary greatly based on how compiler optimizes), the first one will become eligible for GC immediately.
s2+=" roses"; // same as above.
s3 = s3+s2+" roses all the way"; // same as above but the object s3 was pointing to will become eligible for GC immediately.
System.out.println(s3); // no memory allocation.
When the method ends, s1, s2, and s3 references will be cleared from the stack and any remaining objects pointed to become eligible for GC.
Hope this helps, remember this is a very basic explanation, I recommend reading up on this topic, as how it will actually behave can vary greatly depending on how the compiler decides to optimize. (For example, the compiler may see all these temporary references and concatenations are not needed and discard them)
Note: Since you are concatenating to create strings, you may want to consider the Mutable alternatives like StringBuffer or StringBuilder which can help optimize.