If you're using Java8u20 or newer you can try using -XX:+UseG1GC -XX:+UseStringDeduplication
to enable string deduplication.
While this won't avoid the creation of garbage it might reduce memory pressure.
If you really want to create String
instances without the copying cost of the char[]
array you will have to access the package-private constructor java.lang.String.String(char[], boolean)
or the private char[] value
field via reflection, with the appropriate runtime checks/error reporting whether it actually works.
I wouldn't recommend it, but it's an option.
Another option is to stop using Strings and work with ByteBuffer
. You can slice them as needed, return views, return read-only views, recycle them.
And they're also more compact if you work with utf-8 data. The downside is that you can't use APIs that require Strings.
Or just deal in CharSequence/StringBuilder/Charbuffer objects in as many places as you can.
Depending on use-cases you can also create a string cache for your computation. Map<T, String>
where T
is the input parameter of your computation. This way you will only ever need 1 String for each possible value of T
.
return new String(chars, 12 - i, i);
Note that as of Java 8 strings do not store an internal offset, i.e. String objects are not a "view" on some potentially larger backing char array.
This used to be different in the past, but since it was an implementation detail it got changed.
It might be possible to undo that change with a custom String class added via the bootstrap classloader, but that's more likely to break or cause severe performance degradation than not.
as we need to run close to real-time with the default Java GC.
This may be your actual problem.
None of collectors configured by default provide you anything that comes even close to realtime behavior. CMS or G1 can provide much lower pause times, especially on large heaps, than either the Serial or ParallelOld collectors.