0

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.

Not a bug
  • 4,286
  • 2
  • 40
  • 80
  • 2
    Why are you opposing him? It's a string constant. – Dave Newton Feb 10 '14 at 11:43
  • 2
    The "where are strings created" and "where are parameters stored" aspects of this question have mostly separate answers. The parameter passing mechanism operates the same on Strings and other objects, but depending on the JVM, String literals may or may not be allocated in a special manner. – user2357112 Feb 10 '14 at 11:43

3 Answers3

3

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;
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • 1
    Relevant section of the JLS: http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5 - "Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern." – davmac Feb 10 '14 at 11:53
  • @davmac I actually compiled this code because I wasn't sure whether this would be a compile-time constant ("stack" + "overflow" is), and it was easier than digging through the JLS. – chrylis -cautiouslyoptimistic- Feb 10 '14 at 11:54
  • that's fine. I already upvoted your answer. I added the JLS reference as a comment so it's there if anyone wants it. – davmac Feb 10 '14 at 12:08
  • @davmac Always happy to have a citation. Just not motivated enough to provide it myself right now. ;-) – chrylis -cautiouslyoptimistic- Feb 10 '14 at 12:19
0

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).

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • Opposing string pool and heap is misleading: the string pool may be stored on the main heap (for example it is the case on hotspot since Java 7). – assylias Feb 10 '14 at 11:52
  • 1
    This behavior is explicitly specified in the JLS. You could write a compiler that breaks the rules in all sorts of ways, but it wouldn't be a correct Java compiler. – chrylis -cautiouslyoptimistic- Feb 10 '14 at 11:52
  • 1
    @chrylis that's what I meant. – assylias Feb 10 '14 at 11:54
  • @chrylis Version? Paragraph? Page? – Ingo Feb 10 '14 at 12:19
  • Sorry, it's partly specified in the JLS (per the syntax and semantics of `String` literals) and partly specified in the JVMS referenced by JLS 13.1), which is where the actual `class`-file format is specified. JVMS 3.2 and 3.4 specify the bytecode for accessing constants, and [section 4.4.3](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.3) details the binary format of `String` literals. – chrylis -cautiouslyoptimistic- Feb 10 '14 at 12:26
  • @chrylis The JLS tells only about the properties String instances created from literals must have. There is no mention of a "constant pool". This is merely a way to implement the string literal laws in an efficient way. And, of course, it makes sense that every JVM supports it in the same way. But, I maintain that my hypothetical compiler (see my edit) is JLS conform in that regard, and just does not use some JVM facilities. In particular, compile a program with a standard compiler and with my compiler, and run it on the same JVM, you'll see no difference. – Ingo Feb 10 '14 at 12:36
  • 1
    @Ingo your argument is flawed. Whether or not string literals generate objects on the heap or not does not affect the answer to the question (which is about whether string literals are in the "String constant pool"). The effect of requiring that string literals be intern'd (JLS 3.10.5) is that there is a pool of String constants, and it is mandated by the JLS that String literals yield Strings from this pool. – davmac Feb 10 '14 at 16:03
  • @davmac As I said, the "string pool" is just an implementation technique. The JLS only tells us how literals are expected to behave, not how it should be implemented (the JVM spec tells the latter). Have you considered my thought experiment with the pre-processor? Can you write a program that prints "I was preprocessed" when the pre-processor was used on it? - And, of course, the answer to the original question is: Usually, but it need not be so (as my though experiment shows). – Ingo Feb 10 '14 at 17:47
  • @Ingo, you missed my point. Even with your preprocessor the literal strings are still in the constant pool. The constant pool is an abstract concept, not a concrete implementation; the JLS specifies, effectively, that literal strings are in the constant pool. It doesn't matter how the compiler goes about putting them there. – davmac Feb 11 '14 at 11:53
  • @davmac The JLS specifies nothing like this. Please search http://cr.openjdk.java.net/~mr/se/8/java-se-8-pfd-spec/java-se-8-jls-pfd-diffs.pdf for "constant pool". It doesn't even appear! The constant pool is no abstract concept, but a very real section in the class file. Hence, I ask again, where in the JLS is it stated, that a conforming compiler must make use of the class files constant pool mechanism? Only the following is required: There must be a method String.intern to enable sharing (without saying how exactly) and "a string literal always refers to the same instance of class String" – Ingo Feb 11 '14 at 12:21
  • @Ingo please read (or re-read) my comments above. Maybe there is a constant pool section in the class file, but this question is clearly about language semantics. The "String constant pool" in this case refers not to the class file format, but to a language concept (the set of automatically intern'd strings). Please see the question which this one has been marked a duplicate of. The relevant JLS section, again, is 3.10.5. – davmac Feb 11 '14 at 13:59
  • @davmac I asked an easy question: Where exactly in the JLS is the constant pool mentioned? The answer, as you will have to admit, is: Nowhere. Hence, claiming that a Java compiler that ignores the constant pool for string literals is standard, **provided** the other conditions for string literals are met. I would like you to show the failure in my reasoning, or admit that my preprocessor Gedankenexperiments still obeys the standard (which follows simply from the fact that it creates valid java programs - just without string literals). – Ingo Feb 11 '14 at 14:08
  • @davamac There is no one single word about a "constant pool" in section 3.10.5. Period. Everything else is your interpretation. But in that interpretation, the OP question does not make sense, because nothing can be stored in an "abstract concept". – Ingo Feb 11 '14 at 14:11
  • @Ingo I never claimed the term "constant pool" is used in the JLS, and I also never claimed that your proposed preprocessor does not obey the language standard. I am saying that your answer does not address the question, and that you are not interpreting "constant pool" in the right context. You need to re-read my comments. – davmac Feb 11 '14 at 14:11
  • @davmac Sure it does. It explains at length why that question cannot be answered in general, but only for a certain java compiler. – Ingo Feb 11 '14 at 14:13
  • I have edited my comment above. I have nothing more to say on this matter. – davmac Feb 11 '14 at 14:14
-1

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.

Omoro
  • 972
  • 11
  • 22
  • Mostly wrong, right, wrong. `stack` is in the constant pool, `overflow` is in the constant pool, and `stackoverflow` is on the heap. The constant pool may be on the heap at the discretion of the JVM author. `stackoverflow` won't go into the pool unless it's explicitly interned. – chrylis -cautiouslyoptimistic- Feb 10 '14 at 11:55
  • 2
    "stack" the literal will be in the constant pool but s will refer to a copy of it which will be on the heap (due to `new String(...)`). – davmac Feb 10 '14 at 12:11