11

This might be a stupid question (or just make me look stupid :)), however I would be interested in how to work with long String objects in the context of short-lived objects.

Think about long SQL queries in cron job or anonymous, command or function-like classes. These are very short-lived classes and even will use these long Strings once in their lifetime for most of the time. What is better? To construct a String inline and let it be collected with the instance, or make it static final anyway and let them sit in the memory useless until the classes next instantiation?

user1405469
  • 195
  • 9

4 Answers4

8

Well, there's only so much control you can have over what happens to the String.

Even if you create it inline, that String will most probably be added to the String constant pool of the JVM, and will be reused when you declare it again, so in practice, you'll probably be reusing the same String object either way.

Unless the String is so huge that it has an impact on your application's performance, I wouldn't worry about it and choose the option that seemed more readable to me.

If that String will be used only in one particular point of the code, inside a method, I would declare it inline, I prefer to have my variables in the smallest scope that I can, but opinions here may vary. If there is no change whatsoever, and it seems to make sense in your particular use case, by all means declare the String as static, again, I doubt it will affect performance.

pcalcao
  • 15,789
  • 1
  • 44
  • 64
2

String constants go into the constant pool of a class, and cannot be optimized away, i.e. are handled sufficiently well.

Creating long strings one does not do statically. For SQL use prepared statements with a ? place holder. The same holds for strings with placeholders: use MessageFormat.

To be explicit. The following does not cost anything extra:

static final String s = "... long string ...";
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I really liked the first and last part of your comment. Your prepared statement and message format ideas do not apply in my situation as these objects/cronjobs really just execute a single, but long sql update and be done with it. No parameters no nothing. However, though you use prepared statements and strings with placeholders, you still have to store those long strings somehow :). – user1405469 Apr 17 '13 at 09:13
-2

When remaining memory is limited JVM will normally do perm gen space cleaning and unload unused/unreferenced classes. So having the long strings as static variable won't do much harm in my opinion

Dev Blanked
  • 8,555
  • 3
  • 26
  • 32
  • You can read more about memory cleanup at this blog http://www.javaworld.com/jw-06-1998/jw-06-techniques.html – AurA Apr 17 '13 at 09:03
  • @loki have you used 'CMSClassUnloadingEnabled' JVM option or looked at memory usage via JConsole etc of an application ? – Dev Blanked Apr 17 '13 at 09:03
  • You should not use "CMSClassUnloadingEnabled" option unless exceptional circumstances are there or else you will keep loading and unloading classes. Just read how classes are unloaded without that option. – Lokesh Apr 17 '13 at 09:15
  • @loki please refer oracle documentation for recommended server settings http://docs.oracle.com/cd/E13209_01/wlcp/wlss30/configwlss/jvmgc.html. This has used the CMSClassUnloadingEnabled option – Dev Blanked Apr 17 '13 at 09:18
  • Its makes sense for server but no way for normal program, it will become a big overhead. So if a class is used initially and at the end of program then you load and unload it twice? Isn't it overhead? – Lokesh Apr 17 '13 at 09:26
  • @loki unloading will only happen during garbage collection i.e: when remaining memory is limited – Dev Blanked Apr 17 '13 at 10:00
-2

If you feel your Strings can occupy lots of memory then dont make them static or declare them using String literal. As both of these will get stored in permgen space and will almost mever be garbage collected [there is chance but slim, statics may never be garbage collected is you have not created your own classloader]. So create String using new operator so that will be created in heap and can be easily garbage collected i.e.

String str = new String("long string");

EDIT:

How strings are stored: http://www.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html

EDIT:

There has been a long discussion below regarding how new String works. Argument presented is that new String will create 2 objects one in heap and one in pool. THIS IS WRONG, it is not true by default and you can force java to do it by calling intern method. In order to back my argument following is the javadoc from Strin class for intern method:

intern

public String intern() Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification

As can be seen by above doc that if new String always created an object in pool then intern method will be completely useless!! Also logically it doesn't makes any sense.

EDIT:

Also read the answer for this post : String pool creating two string objects for same String in Java

Community
  • 1
  • 1
Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • In this case str could possibly be garbage collected, but "long string" is stored in permgen anyway isn't it? – mjaggard Apr 17 '13 at 09:05
  • So u mean to say all string go to permgen whether you create literal or using new?? Whats the use of intern() method then? What do you really need to create String using new? – Lokesh Apr 17 '13 at 09:07
  • See here about the only good use for `new String("string")` http://stackoverflow.com/questions/390703/what-is-the-purpose-of-the-expression-new-string-in-java/390854#390854 – mjaggard Apr 17 '13 at 09:20
  • @mjaggard: Doers it say that new String puts the string in constant pool? It doesn't say tht. Just read about intern() method , if your logic is correct then why do we need intern?? its not needed then – Lokesh Apr 17 '13 at 09:22
  • 1
    no I'm not saying that all strings will go to permgen, but I think the String you create implicitly `"long string"` will be stored AS WELL as the string you create explicitly `new String()` – mjaggard Apr 17 '13 at 09:22
  • Why?? then whts the use of new String? Isn't that a wastage of space? Show me any doc to back that? If that happens i will downgrade my answer on my own :) – Lokesh Apr 17 '13 at 09:25
  • Check this doc: http://www.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html – Lokesh Apr 17 '13 at 09:27
  • That doc seems to have a fairly good description. Did you see my link to the question about the only useful purpose of `new String`? – mjaggard Apr 17 '13 at 09:30
  • ahh... how is that link related to my answer. I am just saying new String will be in heap not in pool? All i am asking is can you back your argument? I have given many reasons. – Lokesh Apr 17 '13 at 09:33
  • I liked the answer and the discussion as well. Thanks for the linked doc, btw! – user1405469 Apr 17 '13 at 09:37
  • Yes, the new string will be in the heap. The string will also be in the pool because you have defined it using "long string" in order to pass it into the constructor of String. The line `new String("long string")` creates TWO string objects. – mjaggard Apr 17 '13 at 10:56
  • You have so far not given any doc to back that. I VERY MUCH doubt that. Logically it doesn't make sense. Let me do the job of finding the doc for this!! – Lokesh Apr 17 '13 at 11:00
  • @mjaggard: You argument is incorrect. see my edit or go to javadoc for string class and see documentation for intern method. – Lokesh Apr 17 '13 at 11:45
  • More evidence to the contrary: http://stackoverflow.com/questions/1881922/questions-about-javas-string-pool I think the key here is not what current implementations of Java do, but the spec. There's nothing in the spec to say when a String will NOT be in the pool - the only guarantee is that it WILL be in the pool if you call `intern()` – mjaggard Apr 17 '13 at 13:03
  • Also, your answer is now more wrong because it states that you can create 2 objects by calling `intern()` this actually does the opposite, `intern()` forces there to be ONE object - in the String pool. `String s1 = "blah"; String s2 = new String(s1);` will (most likely) cause `s1 != s2` but running `s1.intern(); s2.intern();` will cause `s1 == s2` – mjaggard Apr 17 '13 at 13:06
  • Well, i dont think i can explain any better :). I can see at many places it does says that 2 strings are created by new but none is standard one. Let me give one more try [a logical one] if you dont agree then we can happily disagree :). If 2 strings were always created then why would intern() javadoc say htis "Otherwise, this String object is added to the pool and a reference to this String object is returned." does this ring a bell? My second point is what does java achieve by this? I can't see any advantage it looks like a big overhead which eats up permgen if your logic is correct. – Lokesh Apr 17 '13 at 14:01