class Student(二):内存分配情况

问题导向的学习方法

摘要:class Student系列,希望通过对一段非常简单的代码分析,以问题为导向,加深自己对代码的理解。

如题,一段非常简单的代码如下:

class Student {
    int age;
    String name;

    static Student demo() {
        Student xm = new Student();
        xm.age += 10;
        xm.name = "小ming😊";
        return xm;
    }

    public static void main(String[] args) {
        Student.demo();
    }

1. 执行demo方法时,哪些地方分配了哪些内存?分别是多大?

  1. 方法栈压栈一个新的栈帧
  2. 栈帧
    • 局部变量表,有一个指向堆上对象的引用 xm: 8字节

      引用大小一般是机器字长,32位上是4字节,64机器是8字节, 后面讨论默认为64位机器),但是64位寻址空间位4G * 4G = 16GG,一般是用不到这么大内存的,因此部分JVM实现会压缩引用大小,用更少的空间存储引用。后面的讨论不考虑这个实现相关的优化

    • 返回值地址 (8字节

    • 操作数栈

      • 栈式虚拟机才存在,例如:Hotspot,普通的桌面级和server JVM实现 (编译时确定最大深度,根据代码不同而不同 x字节)
      • Android用的Dalvik和ART是寄存器式的,不存在
    • 对常量方法的引用

  3. 堆上分配了一个Student对象,Student对象由四部分组成
    • 对象头(包含了指向class的指针,gc信息,锁情况等相关信息)(16字节左右)
    • field:age int/值 类型4字节
    • field:name String/引用类型 一个机器字长(8字节
    • 对齐填充(一般是4字节或者8字节对齐)(对Student对象来说,需要填充4字节
  4. 常量池里面的 “小ming😊”
    • Java字符串使用UTF-16编码(所以,Character对象是16位),“小ming” = 5 * 2 字节
    • emoji 不在Unicode 常见字符编码内,需要用两个character表示 2字节 (参见Java String注释,CodePoint API)

思考题:10 在哪里?

2. 字符串占用多少内存?编码方式?

如上面,分析过了。Java中使用UTF-16编码,不在常见字符集内的,使用一个codePoint(两个Character)来表示。
其它地方,目前大部分默认使用UTF-8作为默认编码。UTF-8 是变长编码,前面的字符和Asicc兼容,一个汉字用三个字节表示。
字符/Unicode编码是一个比较复杂的话题,我了解的比较浅,这里就不班门弄斧了,有兴趣的小伙伴可以继续深入研究。

3. 方法栈上的内存布局是什么样的?堆上的内存布局?

注意:内存布局和内存大小是两个相关但不同的概念,内存布局含义更丰富一些,例如,内存是连续的还是离散的,不同内存之间的关系。相同的内存消耗,不同的内存布局可能对性能影响非常大

内存布局 (图画的有点久了,将就看下吧)
栈帧的结构

扩展:

1. String 的lazy,cache hashCode

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        int h = hash;
        final int len = length();
        if (h == 0 && len > 0) {
            for (int i = 0; i < len; i++) {
                h = 31 * h + charAt(i);
            }
            hash = h;
        }
        return h;
    }

非常有意思的一点,String的hashCode和平时些的即时计算的代码非常不同,用了一个辅助成员变量来缓存,并且是延迟计算。

我理解主要是基于几点考虑:
1. String对象是不可变的,为缓存hashCode提供了前提
2. 对于字符串长度非常长的情况下,缓存策略可以避免非常严重的badcase(String的hash计算是和字符串长度成正比的, 复杂度O(n))
3. 内存相对是廉价/不敏感的,毕竟对象头都占了16个字节了,一个int的消耗不足挂齿

2. Unicode, Character, String

String.java

/**
  * <p>A {@code String} represents a string in the UTF-16 format
 * in which <em>supplementary characters</em> are represented by <em>surrogate
 * pairs</em> (see the section <a href="Character.html#unicode">Unicode
 * Character Representations</a> in the {@code Character} class for
 * more information).
 * Index values refer to {@code char} code units, so a supplementary
 * character uses two positions in a {@code String}.
 * <p>The {@code String} class provides methods for dealing with
 * Unicode code points (i.e., characters), in addition to those for
 * dealing with Unicode code units (i.e., {@code char} values).
 */

Character.java

/**
 * <p><a name="BMP">The set of characters from U+0000 to U+FFFF</a> is
 * sometimes referred to as the <em>Basic Multilingual Plane (BMP)</em>.
 * <a name="supplementary">Characters</a> whose code points are greater
 * than U+FFFF are called <em>supplementary character</em>s.  The Java
 * platform uses the UTF-16 representation in {@code char} arrays and
 * in the {@code String} and {@code StringBuffer} classes. In
 * this representation, supplementary characters are represented as a pair
 * of {@code char} values, the first from the <em>high-surrogates</em>
 * range, (&#92;uD800-&#92;uDBFF), the second from the
 * <em>low-surrogates</em> range (&#92;uDC00-&#92;uDFFF).
*
 * <p>A {@code char} value, therefore, represents Basic
 * Multilingual Plane (BMP) code points, including the surrogate
 * code points, or code units of the UTF-16 encoding. An
 * {@code int} value represents all Unicode code points,
 * including supplementary code points. The lower (least significant)
 * 21 bits of {@code int} are used to represent Unicode code
 * points and the upper (most significant) 11 bits must be zero.
 * Unless otherwise specified, the behavior with respect to
 * supplementary characters and surrogate {@code char} values is
 * as follows:
 *
 * <ul>
 * <li>The methods that only accept a {@code char} value cannot support
 * supplementary characters. They treat {@code char} values from the
 * surrogate ranges as undefined characters. For example,
 * {@code Character.isLetter('\u005CuD840')} returns {@code false}, even though
 * this specific value if followed by any low-surrogate value in a string
 * would represent a letter.
 *
 * <li>The methods that accept an {@code int} value support all
 * Unicode characters, including supplementary characters. For
 * example, {@code Character.isLetter(0x2F81A)} returns
 * {@code true} because the code point value represents a letter
 * (a CJK ideograph).
 */

Basic Multilingual Plane (BMP)范围内的字符可以使用一个Character表示,范围外的字符需要用两个Character表示

扩展思考

  1. 如何正确的截断一个带有emoji字符的文本?
  2. 为什么要进行对齐?除了对象的对齐之外,哪些地方还用到了对齐?
  3. 为什么我们自己定义的类大部分是直接计算hashCode ?哪些场景下适用String style lazy cache类似的hashCode实现?
  4. 为什么String对象要设计为不可变的?自定义类如何做到不可变?不可变对象有什么好处?
  5. 栈帧的局部变量表里面都有啥?有this?

参考文章:

  1. 精美图文带你掌握 JVM 内存布局
  2. Unicode 编码及 UTF-32, UTF-16 和 UTF-8
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353