对象在内存中实例化的原理

1.我的理解,在内存中也就是在JVM里面
在这里插入图片描述
  这里也叫运行时数据区,存在方法区,栈,堆,程序计数器,还有常量池,本地方法栈等等
  先从方法区说起:首先在idea中写的代码,每个类的后缀名,是XXX.java 文件.接着在程序运行时,通过javac编译器将.java文件生成.class文件.即JVM能看懂的文件(从表面看是将.java文件转化为.class文件。
  而实际上是将Java源代码转化成一连串二进制数字)这里不做深究.然后通过类加载器检查,这里检查也是为代码的安全.
  比如说定义了一个java.lang.Sting的类,则程序运行会报错.这里就是通过类加载器检查出来的(原理:在类加载器中分为三类:根加载器,扩展类加载器,系统加载器.逐级检查其各自jar包中是否含有相同的类的定义.有的话,则不会执行程序中的main方法,而是执行这些加载器中的,放一段代码和截图)
在这里插入图片描述

package java.lang;

public class String {
    public  String toString(){
        return "Hello";
    }public static void main(String[] args) {//这就是main方法
​        String s = new String();
​        s.toString();}/*
​    1.类加载器收到类加载的请求
​    2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
​    3.启动类加载器检查是否能够加载当前的这个类,能加载就结束,使用当前的加载器.否则,抛出异常,通知子加载器进行加载
​    4.重复步骤3
​    ClassNotFound
​    null:java调用不到,用C/c++写的
​    JAVA = c++--:去掉繁琐的东西,指针,内存管理
​    */
}

在这里插入图片描述程序计数器:
在这里插入图片描述

  这里扯远了一点,回到正题,通过加载器之后,说明代码解释没有问题,可以进行下一步,进入运行时数据区.然后源代码中会有new 实例化的代码,在数据区,则会分为几个部分,笼统点说就是引用放在栈里面,具体的实例放在堆里面,方法区放的就是XXX.class,方法区里面还有一些常量池等,一些常量(即用static,final,等等)如下图所示:

在这里插入图片描述
我们来放大栈的内部结构:
在这里插入图片描述
图中栈,包含了两个方法引用,引用就是指对象的引用,从栈到堆中,还有下面方法指向上面方法的子帧和父帧(由于栈是先进后出的,所以最上面一定是程序正在执行的方法,而main方法一定在最下面,因为他是最先进栈的)

1.栈:数据结构
程序 = 数据结构 + 算法
2.栈(FILO):先进后出.后进先出 类似于一个桶
队列 :先进先出,类似于排队 (FIFO) :消息队列
喝多了,吐就是栈.吃多了拉就是队列
栈:占内存,主管程序的运行,生命周期和线程同步;线程结束,栈内存也就释放了,对于栈来说,不存在垃圾回收的问题
一旦线程结束,栈就over了.
栈:八大基本类型+对象的引用,实例的方法
   堆:实例化的对象放在堆中,用图说话(借用知乎的jvm编译原理,链接:https://zhuanlan.zhihu.com/p/81427843):
在这里插入图片描述

  1.在堆内存中开辟一段内存空间, 假设这段内存空间是从0x1111~0x20003
因此通过0x1111就可以找到对应的这段内存空间, 进而获取其中的数据
  2.将0x1111保存在this中, 我们也可以说让this指向这个空间
  3.执行函数. 通过this=0x1111找到内存空间, 在这个空间中保存数据 name:xiaoming,age:20
  4.最后, 将0x1111返回, 保存在stu中

在这里插入图片描述

若程序中有native的则还需有一个本地方法栈,通过一个本地方法接口,引用到本地方法库,这也是为什么java能在C/C++横行的年代里逐渐崛起的原因了

原创文章 32 获赞 52 访问量 649

猜你喜欢

转载自blog.csdn.net/qq_42400763/article/details/105770781
今日推荐