As I understand it, String literals are placed in the string pool. So anything inside quotes will be in the pool.
Any time you use the "new" operator, a String is created in the heap. So, if you ONLY had
That line will create TWO string objects - one in the pool for the literal, and one on the heap for the 'new' operator. The object in the pool is never eligible for GC. The object in the heap is eligible once all references to it are removed or unreachable.
So if, after the above line, you have
s2 = null;
then the one in the heap is eligible for gc (assuming there are no other active references). It may never be collected, if the JVM never needs to reclaim memory. The only think you know for sure is that the JVM will run the GC at least once before throwing an OutOfMemory exception. But if you never get close to using your allocated memory, it may indeed never run.
Your example isn't much different
Line 1 causes a String to go into the pool due to the literal.
at Line 2,
java says "well, the literal "abc" is already in the pool, so I don't need to make a new one there. But the 'new' operator requires me to create a new String in the heap, so I will do that, and give it the value of "abc"."
So again, there are two String objects. On line 3, we loose the reference to the literal/pool object, but the objects in the pool aren't ever eligible for GC, so it doesn't really matter.
Line 4 we loose the reference to the heap version of the String, so that on is now eligible, but may never be collected.