As Picture Down:
`java.lang.String`: #bytes: 5722104 #instances: 238421
5722104 / 238421 = 24, **why?**
openjdk version "1.8.0_202"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_202-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.202-b08, mixed mode)
jinfo -flag UseCompressedOops 22592
-XX:+UseCompressedOops
3.18.6-2.el7.centos.x86_64 #1 SMP Mon Oct 24 13:01:33 CST 2016 x86_64 x86_64 x86_64 GNU/Linux
32Bit- Java 6
String Object:
First
- a char array— thus a separate object— containing the actual characters; [4bytes, ) when no chars, it needs 4 at least
- an integer offset into the array at which the string starts; 4bytes
- the length of the string; 4bytes
- another int for the cached calculation of the hash code. 4bytes
Add Plus Object Header 8 bytes.
4+4*3+8 = 24 bytes! This gives 24 bytes (which is a multiple of 8 so no "padding" bytes are needed so far).
Second
Underlying char array: 16 bytes.
The empty char array: 12bytes
4bytes: length
8bytes: object header
And, plus 4 bytes to padding.
So, Actually, empty String needs 40bytes!
More Deep
1. 17 charactes String:
char array: 17*2 = 34 bytes, plus empty char array 12bytes -> 46bytes.
after Padding -> 48 bytes (a multiple of 8)
So 48 + 24 =** 72 btyes!**
when use C programming, it only 18bytes!
2. SubString
substring will share parent char array. So,
- if you keep on to the parent string after creating the substring, then you will save memory overall;
- if you throw away the parent string after creating the substring, then you will waste memory (if the substring is shorter than the parent).
For example, in the following code:
String str = "Some longish string...";
str = str.substring(5, 4);
It will waste memory, then we can create a new string instead.
String str = "Some longish string...";
str = new String(str.substring(5, 4));
64Bit-Java8
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
String Object: (-XX:-UseCompressedOops): 32bytes
- a char array— thus a separate object— containing the actual characters; [8bytes, ) when no chars, it needs 8 at least
- another int for the cached calculation of the hash code. 4bytes
- Mark work + Class ptr 16bytes
- padding 4bytes
String Object: (-XX:+UseCompressedOops): 24bytes
a char array— thus a separate object— containing the actual characters; [4bytes, ) when no chars, it needs 4 at least
another int for the cached calculation of the hash code. 4bytes
Mark work + Class ptr 8bytes + 4bytes
padding 4bytes
所以上例中24bytes,是因为java8 64bit 环境中,使用 -XX:+UseCompressedOops.
如果加上空数组的大小char[] value (16 bytes) 一共是40byteSubString
java 8 中substring已经改由System.arraycopy实现,不再共用同一个char[].
/**
* Allocates a new {@code String} that contains characters from a subarray
* of the character array argument. The {@code offset} argument is the
* index of the first character of the subarray and the {@code count}
* argument specifies the length of the subarray. The contents of the
* subarray are copied; subsequent modification of the character array does
* not affect the newly created string.
*
* @param value
* Array that is the source of characters
*
* @param offset
* The initial offset
*
* @param count
* The length
*
* @throws IndexOutOfBoundsException
* If the {@code offset} and {@code count} arguments index
* characters outside the bounds of the {@code value} array
*/
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count); // System.arraycopy
}
/**
* Returns a string that is a substring of this string. The
* substring begins with the character at the specified index and
* extends to the end of this string. <p>
* Examples:
* <blockquote><pre>
* "unhappy".substring(2) returns "happy"
* "Harbison".substring(3) returns "bison"
* "emptiness".substring(9) returns "" (an empty string)
* </pre></blockquote>
*
* @param beginIndex the beginning index, inclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if
* {@code beginIndex} is negative or larger than the
* length of this {@code String} object.
*/
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}