jvm 05JVM - 对象的创建 ,对象内存分配 ,oop模型,字符串常量池

01.JVM - 对象的创建

1.1、对象的创建的方式
在这里插入图片描述
Java语言中,对象创建的方式有六种:

  • new关键字:最常见的形式、Xxx的静态方法、XxxBuilder、XxxFactory的静态方法。

  • Class类的newInstance()方法:通过反射的方式创建对象,调用类的无参构造器进行对象的创建,且其访问权限为public。

  • Constructor的newInstance()方法:通过反射的方式创建对象,调用类的无参、有参构造器进行对象的创建,对构造器访问权限没有要求。

  • 使用clone()方法:不调用任何构造器,但是要求当前类实现Cloneable接口,重写clone()方法。

  • 使用序列化:从文件、网络中获取一个对象的二进制流。

  • 使用第三方库:Objenesis。

1.2 创建过程:
在这里插入图片描述
1.2.1
在这里插入图片描述
1.2.2 对象内存分配
在这里插入图片描述
1.2.2.1
在这里插入图片描述

1.2.2.2

在这里插入图片描述在这里插入图片描述

1.2.3
在这里插入图片描述
1.2.4在这里插入图片描述

在这里插入图片描述
1.2.5
在这里插入图片描述

02.oop模型

2.1oop模型

在这里插入图片描述
1、非数组对象 InstaceOopDesc

2、数组对象 arrayOopDesc

    2.1 基本数据类型数组 typeArrayOopDesc

    2.2 引用类型数组 objArrayOopDesc

3、MarkOopDesc

    存放锁信息、分代年龄等

2.2 oop和Klass关系

1、InstanceKlass是JVM中表示类的对象的数据结构。JVM在加载class时,会创建instanceKlass,表示其元数据,包括常量池,字段,方法等,存放在方法区,instanceKlass是JVM中的数据结构;
2、 InstanceOopDesc是JVM中表示实例对象的数据结构。在new一个对象时,JVM创建instanceOopDesc来表示这个对象,存放在堆中,其引用存放在栈中;instanceOopDesc对应Java中的对象实例;
3、new操作返回的instanceOopDesc类型指针指向instanceKlass,而instanceKlass指向对应类型的Class实例的instanceOopDesc;
4、在JDK6中,Class对象存放在方法区,JDK7和JDK8中,Class对象存放在Java堆中。

03.字符串常量池

即String Pool,但是JVM中对应的类是StringTable,底层实现是一个hashtable,看代码

class StringTable : public Hashtable<oop, mtSymbol> {
……

Key的生成方式

1、通过String的内容+长度生成hash值
2、将hash值转为key

hashValue = hash_string(name, len);
index = hash_to_index(hashValue);
// Pick hashing algorithm
unsigned int StringTable::hash_string(const jchar* s, int len) {
  return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
                                    java_lang_String::hash_code(s, len);
}
  // Bucket handling
  int hash_to_index(unsigned int full_hash) {
    int h = full_hash % _table_size;
    assert(h >= 0 && h < _table_size, "Illegal hash value");
    return h;
  }

Value的生成方式

将Java的String类的实例instanceOopDesc封装成HashtableEntry

String的两种创建方式:

第一种方式是在常量池中获取字符串对象。
第二种方式是直接在堆空间创建一个新的字符串对象。
//先检查字符串常量池中有没有“apesource”,如果字符产常量池中没有,则创建一个,然后str1指向字符串床常量池中的对象,如果有,则直接将str1指向“apesource”
String str1 = "apesource";
String str2 = new String("apesource");//堆中创建一个新的对象
String str3 = new String("apesource");//堆中创建一个新的对象

System.out.println(str1 == str2);//false
System.out.println(str2 == str3);//false

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
字符串拼接:
01.
在这里插入图片描述
02.
在这里插入图片描述
03.

public class TestString_5 {

    public static void main(String[] args) {

    }

    public static void test2() {
        String s1 = "1";
        String s2 = "1";

        String s = s1 + s2;
    }
}

在这里插入图片描述
用到了StringBuilder ,最后用
return new String(this.value, 0, this.count);
不会去查常量池的

双引号 + new String

public class TestString_6 {

    public static void main(String[] args) {

    }

    public static void test2() {
        String s1 = "1";
        String s2 = new String("1");

        String s = s1 + s2;
    }
}

在这里插入图片描述

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值