欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JVM学习(3):运行时数据区

程序员文章站 2022-04-16 09:39:32
类由静态到动态,会经历运行时数据区这一步: 静态编译:把Java代码编译成字节码文件Class文件,它以静态方式存在 类加载器:把Java字节码文件加载到内存中 【方法区】与【堆】是运行时数据区在所有线程间共享的,它们是存数据的地方 【虚拟机栈】,【本地方法栈】,【程序计数器】是运行时数据区线程私有 ......

类由静态到动态,会经历运行时数据区这一步:

 JVM学习(3):运行时数据区

 

静态编译:把java代码编译成字节码文件class文件,它以静态方式存在

类加载器:把java字节码文件加载到内存中

 

【方法区】与【堆】是运行时数据区在所有线程间共享的,它们是存数据的地方

【虚拟机栈】,【本地方法栈】,【程序计数器】是运行时数据区线程私有的,它们是执行逻辑的地方

 

以下代码为例:

public class person {
    string name;
    public void say(string name){
        system.out.println(name);
    }

    public static void main(string[] args) {
        person person = new person(); 
        person.say("hello world!");
    }
}

方法区:

person是存放在方法区的,方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码(jit)

jit:java编译成bytecode(静态编译)然后交由cpu执行本地指令,在cpu执行本地指令之前,会将一些热点代码存储下来保存在方法区,以提高效率,例如:

        for (int i=0;i<10000;i++){
            function();
        }

堆:

当我们new person的时候,这个对象实例会存在堆中,几乎所有的对象实例都在这里分配内存

当堆里面没有可分配内存的时候,会报oom错误(内存超出)

 

程序计数器:类似汇编语言的寄存器(指令寄存器),用于存放下一条指令所在单元的地址的地方

虚拟机栈:存放局部变量表,操作数栈,动态连接/方法返回地址,分配基本类型和自定义对象的引用(局部变量表)

本地方法栈:为了native的执行和调出(java源码中的很多native方法)

 

在某些虚拟机中,本地方法栈+虚拟机栈+程序计数器=栈区

通常栈底是主方法main,先入后出,第一个放入的方法是main,最后执行的方法是main

当死循环或递归调用栈中方法过多时候,会报*错误

 

堆栈之间如何配合:

观察以下代码:

        string s = "1" + "2" + "3";
        string s1 = "hello";
        string s2 = new string("hello");
        system.out.println(s1 == s2);
        system.out.println(s1.equals(s2));

打印的是:false\ntrue,说明s1和s2的值相同,地址不同

第一行创建了一个对象,编译的时候进行了字符串折叠(老版本jdk没有优化,会创建四个对象)

第二行只创建一个对象,先在常量池创建字符串“hello”,然后将地址给s1

第三行创建了一个string对象,然后创建常量池字符串,所以栈中变量s2先指向堆中string对象地址,string对象地址再指向常量池中的字符串

因此s1和s2的地址不同

 

继续看上面的这段代码:

public class person {
    string name;
    public void say(string name){
        system.out.println(name);
    }

    public static void main(string[] args) {
        person person = new person(); 
        person.say("hello world!");
    }
}

(1)还没new之前,person存入栈中的局部变量表(局部变量表可以存八种基本类型和引用类型)

(2)new person之后会产生一个实例,存在堆中,局部变量表中的person引用指向堆中的实例

(3)在方法区中保存了person类信息,比如属性name和方法say

(4)调用say方法,局部变量表的person引用指向堆的person实例,person实例指向方法区say方法的地址,完成了一系列调用