Java String 内存大小

As Picture Down:

    `java.lang.String`:  #bytes: 5722104  #instances: 238421
    5722104 / 238421 = 24,  **why?**
222.jpg
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) 一共是40byte

  • SubString
    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);
}

引用

1.Memory usage of Java Strings and string-related objects

推荐阅读更多精彩内容