This question already has answers here:
String Constant Pool
(5 answers)
Closed 9 years ago.
If I pass a String literal to some metohd as:
String s=new String("stack");
String s2=s.concat("overflow");
where string "overflow" will be stored.
one of my friends arguing that it is created in String constant pool and I'm opposing him.
please let me know
Thanks in advance.
All String literals go in the constant pool. The End. In this case, two constants, "stack" and "overflow", go into the pool. A new String is created that holds the same value as the "stack" in the pool, and then another String is created by concatenating the "overflow" from the constant pool to it.
Excerpt from javap -c -verbose Test:
Constant pool:
#1 = Methodref #10.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // java/lang/String
#3 = String #21 // stack
#4 = Methodref #2.#22 // java/lang/String."<init>":(Ljava/lang/String;)V
#5 = String #23 // overflow
#6 = Methodref #2.#24 // java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
This question is certainly undecidable, yet you can find out how a certain combination of java compiler and JVM does it.
As far as I can see, nothing could stop one from writing a java compiler that, when it sees a string constant, emits byte code to create that string in the heap in some way as long as the rules stated in the JLS concerning string literals are still maintained. For example, String.intern could maintain a global Map, and the compiler could compile a String literal like follows:
create a char array of the desired size
put character at index 0
put character at index 1
...
put character at index (length-1)
construct the actual string object
pass the String just created to String.intern and leave result on the stack
Actually, one could have a pre-processor changing all string constants to
(extra.HeapString.createString(new char[] { ... }))
and have createString create a String instance in such a way that the rules for String literals hold. And you couldn't write a program that could detect if it was compiled from the original source or from the preprocessed one (except through reflection on extra.HeapString).
The string stack will be in the heap, the string overflow is in the constant pool, the third string as the result of concatenation stackoverflow in the constant pool.
Related
This question already has answers here:
How many string objects will be created in memory? [duplicate]
(4 answers)
Closed 3 days ago.
String a="hello";
String b=a+"Bye";
How many Strings are formed?
From my understanding of Java.
What happens in this code is:
String a="hello"; // hello is created in string pool
String b=a+"bye"; // new StringBuilder(a).append("bye")
So totally 2 strings are to be created, right?
1.Hello
2.HelloBye (In the Heap)
Or does Java create 3?
1.Hello
2.Bye
3.HelloBye
If this is the case, does append method create the appending strings in the string pool?
String a = "hello";
JVM will create one string in the string pool. (FIRST STRING IN POOL)
Now, here comes the tricky part>
b = a + "bye";
Internally + operator uses StringBuffer for concatenating strings.
String b= new StringBuilder(a).append("bye").toString(); (The toString() method of StringBuilder is returning a new String which will be definitely in the Heap since it is created with new String(...). So "bye" will be SECOND STRING IN POOL.)
Now,
b="hellobye" ("hellobye" will be THIRD STRING IN POOL)
First string "hello" is created and added to the string pool.
Next, the String "Bye" is created and added to the string pool.
The concatenation of a and "Bye" results in a new String "helloBye",
which is also added to the string pool.
A total of 3 Strings will be created in the pool: "hello", "Bye",
and "helloBye".
When you create a new StringBuilder and append a string to it, the resulting string will not be added to the string pool. Instead, a new String object will be created in the heap memory to represent the combined string.
So, the code new StringBuilder(a).append("bye") will create one new String object in the heap memory to represent the combined string and one string in pool for "a".
The only part of your question that can be answered with complete certainty is this:
Does append method create the appending strings in the string pool?
The answer is No. The result of a string concatenation that is not a constant expression is not placed in the string pool. At least not in any implementation of mainstream Java to date. However, there is no specification that actually guarantees this.
There are a couple of reasons why we don't know for sure how many strings are "formed".
We don't know when the String objects corresponding to the literals are actually created. In some Java implementation they will be created (and interned) when the code is loaded. In others, the string creation could occur the first time this code is run.
We don't know whether one or both of those literals are used by another class ... and hence whether this code is "forming" them.
Depending on the Java implementation, interning a string (to put it in the string pool) may result in a new String object being created. So you might get a scenario where two String objects get "formed" for each literal.
In short there is enough ambiguity that we cannot be 100% sure of the precise number of strings that are created during the execution of that code.
Does it matter that we don't know for sure?
Frankly, no. It should make zero difference to the way that you write your code1. Let the Java compiler and runtime take care of it ... and use a recent version of Java to get the benefit of the work they have done on optimizing this.
1 - But it is still wise to avoid string concatenation loops. I don't know if they can be optimized.
In your commented version you wrote:
String a = "hello"; // hello is created in string pool
String b = a + "bye"; // new StringBuilder(a).append("bye")
Both of those comments are questionable:
The "hello is created in string pool" comment is questionable for reasons that I gave above.
The new StringBuilder(a).append("bye") pseudo-code is questionable because that is an implementation detail. In Java 9 and later, expressions that involve string concatenations are translated to a invokedynamic bytecode. The JIT compiler generates native instructions directly. See How much does Java optimize string concatenation with +? for more information.
This question already has answers here:
What is the difference between "text" and new String("text")?
(13 answers)
Closed 3 years ago.
I know that there's a String pool which is supposed to keep some created strings in order to not duplicate them. So, if a user wants to create a string with the same value as another string, it won't be created once again (unless the new String() was called), it'll be a reference to the same object.
So, my question is why the result of this code is "false false"?
String a = "string1";
String b = "string1";
String c = new String("string1");
System.out.println(a==b);
System.out.println(a==c);
What interests me is WHY it's that way, not how to make Java use the pool.
The correct output for the above code is true false.
And the answer to why is string pool there is to simply optimise the memory usage. Whats the point of storing same string every time in heap memory when it can be saved once in a pool and used as long as JVM runs.
On the other hand when we are explicitly mentioning java to create an new object String s = new String("test") then it should be created as a new object and should be stored separately in heap(not in the string pool) and thereby can be updated every time when referencing this particular reference ( object s) which will not affect the string pool at all.
Other reason why string pool concept works fine for Strings is associated with the immutability of string in java.
And coming on how to decide on when to use what ?
Java recognises and stores every string literals in string pool .
If in your particular usecase there is a lot of playing involved with strings, you should be using literals carefully because it may eventually cause memory error if your code is creating massive amounts of strings in string pool. Also while working with concatenation of heavy string objects, it should be totally avoided.
String a = "Testing"
String b ="this"
String c = "I am " + a + b + "code";
Scenarios like this should be handled with stringbuffer or stringbuilder.
In all, Massive use of string pooling should be avoided. On should switch to string builder instead when using such scenarios. Things like string constants like - "HEADER" , "http://" etc that are being used multiple times are still good to be used as string literals.
This question already has an answer here:
String s = "a" + "b" + "c"; Can anyone tell for this statement how many object will be created [duplicate]
(1 answer)
Closed 8 years ago.
How many object will be created for this syntax
String a="b" +"c" +"d";
I tried asking with different people some say it will create 4 object some say 1 object.
Only one!
Expression String a="b" +"c" +"d"; is a compile time constant and after compilation you will just have one String instance and that is "bcd"
For a constant concatenation: only the resulting String.
If there are String variables involved, a StringBuilder is new-ed and then everything appended, so the second object is the resulting String.
One!
Since your creating ONE String object, "b","c","d" are constants, the compiler won't allocate a space for them on the stack.
The jls spec clearly states that 1 String will result as a result of a constant expression.
That still results in more than one object, as the String itself is composed of a char[].
One object will be created!
String a="b" +"c" +"d"; bcd will show up at the class constant pool .(literal object)awesome answer by fellow stackoverflow member
You can even see this in the bytecode:
LDC "bcd"
ASTORE 1
One object will be created at the constant pool
people. I wonder whether it is possible in Java. I want to log a long string message. For example
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
But to keep my source code readable I don't want to write it in one line since otherwise any code reader will have to scroll all the time. So I wrote it like
"aaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaaa" +
"aaaaaaaaaaaaaaaaa"
However, since Java creates a new object for each string, and for concatenation it creates even more temporary objects, this kind of notation produces plenty of overhead. The construct is in a loop in my code, so performance issue is very important.
Are there any other ways to write the string efficiently? I searched the web but did not find anything except for using StringBuffer.
BR
Ewgenij
If the strings are known at compile time, they will be concatenated automatically, so you don't have any penalties at all.
If the strings are generated at runtime, use a StringBuilder (not a StringBuffer, it's slower because of the synchronization overhead).
StringBuilder builder = new StringBuilder("aaaaaaaaaaa");
builder.append("aaaaaaaaaaaaaaaaaa");
builder.append("aaaaaaaaaaaaaaaaa");
builder.toString(); //This returns "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
However, in your case, with hard-coded string, doing
String msg = "aaaaaaa" +
"aaaaaaa" +
"aaaaaaa"
Will compile into
String msg = "aaaaaaaaaaaaaaaaaaaaa";
If the string can be evaluated at compile time, the compiler will take care of combining them for you then. If you're building long strings at runtime, use a StringBuilder.
Here's an example of how the compiler deals with concatenation at compile time:
Source
String foo = "asdf" + "fdsa";
Class file
Constant pool:
#1 = Methodref #6.#17 // java/lang/Object."<init>":()V
#2 = String #18 // asdffdsa
...
#18 = Utf8 asdffdsa
I am studying for the SCJP exam and I have a sample set of questions that I am working through.
One questions answer I am unsure about and was hoping someone here might be able to help me put this question to bed.
Here is the question,
Given:
11. public String makinStrings() {
12. String s = "Fred";
13. s = s + "47";
14. s = s.substring(2, 5);
15. s = s.toUpperCase();
16. return s.toString();
17. }
How many String objects will be created when this method is invoked?
A. 1
B. 2
C. 3
D. 4
E. 5
F. 6
Thank you in advance for any help offered.
I greatly appriciate it.
Let's go through it line by line.
Line 11
An easy start, no strings created here.
Line 12
We're assigning the String "Fred" to s. Although it looks like a String is created here, this string will live in the constant pool. The JVMS section 2.17.6 Creation of New Class Instances guarantees that the objects for string literals will at latest be created when the surrounding class is loaded, which by definition is before the method is invoked. So no new string objects are created on this line.
Line 13
The literal string "47" is referenced, which again will have been created statically (as above). However there's also the invocation of the + operator, which will create a new String in order to hold the result of the concatenation. So that's the first string created.
Line 14
The substring method does indeed create a new String. It shares the underlying character array with its parent - and so takes up hardly any extra memory - but since Strings are immutable, each different string representation requires a different String object. (This is probably a gotcha - my first instinctive response was "ah, string created by substring are special" but of course it still has to create a new object).
Line 15
As above - the uppercase representation is different, so a new String must be created to hold the result.
Line 16
Strings override the toString() method to simply return this - hence no additional String is created.
The scores on the doors
By my count that's three String objects created during this method (with two of those objects sharing the same underlying character array, and with two pre-existing objects referenced for the string literals).
Actually, it would be possible to make the whole method into a single constant. It's possible, but the compiler isn't allowed to do so. Hence, there are 3 Strings created using 2 from the constant pool.
Fred47
ed4 (note: using same backing char[] as Fred47 though)
ED4
2 and 3 are pretty easy as the compiler isn't allowed to optimize away this method invocations but the String is changed. Sting.toString() only returns this, so no new String either. But let's have a look on line 13 using disassembled byte code (javap -c is your friend here):
public java.lang.String makinStrings();
Code:
0: ldc #16; //String Fred
2: astore_1
3: new #18; //class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #29; //String 47
16: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
// SNIP
}
As you see, "Fred" and "47" are loaded from the constant pool (ldc) to populate a StringBuilder that will finally become a String (StringBuilder.toString()).
So that makes 2 constant Strings plus 3 newly created Strings per method invocation.
I'd say 3: the ones at lines 12, 13 and 15.
The reason why the line 14 (substring) doesn't create a new object is because of the internal way String works. Due to necessary optimization of substring (everything, including compiler, rely on substring), the String class has two pointers to the start and end of the string. Doing a substring only moves this pointers, and does not "copy" the object into a new one.
it will create the 5 objects of string
string is immutable class so for every new string it will create an object.
example
public String makinStrings() {
String s = "Fred"; (this line create 1--- Fred string)
s = s + "47"; (this line create 2- 47 string + 3- Fred47)
s = s.substring(2, 5); (this line create 4-ed4)
s = s.toUpperCase();(this line create 5-ED4)
return s.toString();
So according to me it will create 5 object