0

Given this code:

if(somecondition) {
    String one = "one";
    //print one;
}

This string will only be generated when that condition is true?

Appreciate any help.

Edit:

With String pooling, is it safe to say that String one will be added to the pool regardless of a condition.

So, if a variable needs to be resolved from an object, what will happen?

Say,

String hello = "Hello Mr " + user.firstName();

How will this be added to String pool? And when it does get added to String pool, it will not create new String literals right (unless user.firstName() changes).

Faraz
  • 6,025
  • 5
  • 31
  • 88
  • 1
    this String will be generated at run time when somecondition is true , not at compile time – Adnan Feb 14 '20 at 18:27
  • 1
    Does this answer your question? [Runtime vs compile time memory allocation in java](https://stackoverflow.com/questions/12285412/runtime-vs-compile-time-memory-allocation-in-java) – Nexevis Feb 14 '20 at 18:28
  • 2
    Because it's a string literal, the string will exist in the string pool regardless of the condition – khelwood Feb 14 '20 at 18:28
  • Well string literal are handled on a special way by the JVM https://www.baeldung.com/java-string-pool – simbo1905 Feb 14 '20 at 18:32
  • Does this answer your question? [Underlying mechanism of String pooling in Java?](https://stackoverflow.com/questions/27123131/underlying-mechanism-of-string-pooling-in-java) – azurefrog Feb 14 '20 at 18:44
  • tl;dr, nothing exists in memory before you run anything, but the string literals used in a class will be added to the string pool when the class is loaded. – azurefrog Feb 14 '20 at 18:46
  • @khelwood can you please give more elaboration? I am just trying to figure out if I should initialize a String at the start of the method. Or I should only create string inside the catch block – Faraz Feb 14 '20 at 20:20
  • @khelwood I have edited my question – Faraz Feb 14 '20 at 20:27
  • *"So that means this string has already occupied space in heap even before running?"* This is impossible; before you run the program, there is no heap anyway. – kaya3 Feb 14 '20 at 20:47

1 Answers1

4

The string is generated at the time you typed it; but, for that answer to make sense, we need to walk it's life through the transformations in the build and launch of the application.

  1. First you typed it into the *.java file.
  2. Then the compiler copied it into the *.class file as part of the constant pool entries.
  3. Then the program was run, and the class was requested, which triggered the class loader to copy the file from disk to RAM, triggering a object meta-data entry being created to wrap the constant in the constant pool.

So, there's multiple places where it could be "created" depending on your definition of which kind of "creation" you wish to use.

Now, in your first example, the String object isn't realized when you use the string, but when you use the *.class file. However, it's not reference by the running program until you enter the method.

Finally, with String pooling, every time a string is about to be created, the existing pool of strings is searched, and if a matching entry is found, the matching entry is used instead of creating a new string. This reduces the number of strings in a runtime, at the cost of a lot of string searching.

Due to the details of your code, you have three different strings that are eligible for pooling ("Hello Mr ", the value of user.firstName(), and the string combining them both). "Hello Mr " would be pooled with the class loading (assuming pooling is being done). The value of user.firstName() would have happened when the value for the return was originally created. The resulting combined string would be pooled just before the assignment (or reference from the pool, if it already exists in the pool).

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • If I create constants literals `static final String...`, am I correct to assume they would also be stored in String Pool? – Faraz Feb 14 '20 at 21:00
  • @Faraz It depends on the details of the class loader; but, generally the answer is yes. The constant pool doesn't disappear with a String Pool, and the JVM does its best to not keep multiple copies of unnecessary data, so that's why I said "Object metadata" is created. That metadata typically contains the "object interface" of the String in question, but not the RAM that contains the characters, which are in the class constant pool. And for strings, it's heavily optimized, so it gets complicated. – Edwin Buck Feb 14 '20 at 21:04
  • Can you clarify this line please `Now, in your first example, the String object isn't realized when you use the string, but when you use the *.class file. However, it's not reference by the running program until you enter the method.` – Faraz Feb 14 '20 at 21:06
  • When @Faraz asks _"I am just trying to figure out if I should initialize a String at the start of the method. Or I should only create string inside the catch block"_, do what you need to do for your code to work. Don't second-guess string pooling. Of course, it's always great to have insight into what's happening under the covers (thank you @Edwin) - just in case you need to do something unusual with all your strings. Unlikely, for most of us, most of the time. Try to keep your variables [as visible as they need to be](https://www.geeksforgeeks.org/variable-scope-in-java/) - and no more so. – andrewJames Feb 14 '20 at 21:06
  • @Faraz To clarify, there is ram that holds the "String interface" and a different place in RAM that contains the "string characters". That way you can do stuff like `String test = "abc"; abc.length();` because character holding ram doesn't have a place to store method call references. And as andrewjames points out, you don't need to worry about any of this for ClassLoaded strings, because they have a different lifecycle and different (optimized) management handling. – Edwin Buck Feb 14 '20 at 21:12
  • @EdwinBuck do constant take extra memory space as they are static? – Faraz Feb 14 '20 at 21:58
  • @Faraz Since the class can't be part-loaded, if the constant is static or not doesn't matter from a memory space point of view; however, it does have other impacts. Typically in the pre-optimized (not yet compiled by hotspot) JVM instructions, one needs to load the object to make an object-scoped reference. If you are "in" an instance loading a static means switching to the "class" object. This context switch takes time. Not sure if this problem has been optimized away, but it used to be significant. To test against other approaches, one would need to benchmark. – Edwin Buck Feb 16 '20 at 18:21
  • @Faraz They should be constants, but to get a speed boost, you might want to make them non-static. The constant / non-constant isn't really going to affect runtime speed, as the compiler will die with errors if you attempt to change a constant String. – Edwin Buck Feb 16 '20 at 23:22
  • Thanks Edwin I can make this change. I need to read Clean Code and Effective Java 3rd edition. – Faraz Feb 16 '20 at 23:34
  • @Faraz Those are excellent books, but to be honest, I haven't read Clean Code yet, as I saw the video series. But, to get a feel for how the JVM works under the covers, you'll find that information in the actual JVM specification https://docs.oracle.com/javase/specs/jvms/se7/html/index.html and by reading the OpenJDK source code http://hg.openjdk.java.net/jdk7 Together, if you stick with it, you'll have a great understanding of the JVM, which won't be the same as a great understanding of Java, but will permit more work to understand both together. – Edwin Buck Feb 17 '20 at 14:42