Java对象创建过程和内存结构分析
2015-05-03 16:02
761 查看
JAVA内存分配和管理是JAVA的核心技术之一,在看了尚硅谷宋红康老师讲解的JAVA内存知识之后,结合《深入理解JVM这本书》对自己所学的知识进行简单的总结,写了这篇日志。
1.JAVA内存分区
根据存储数据的不同,java内存通常被划分为5个区域:程序计数器(Program Count Register)、本地方法栈(Native Stack)、方法区(Methon Area)、栈(Stack)、堆(Heap)。
程序计数器(Program
Count Register):又叫程序寄存器。JVM支持多个线程同时运行,当每一个新线程被创建时,它都将得到它自己的PC寄存器(程序计数器)。如果线程正在执行的是一个Java方法(非native),那么PC寄存器的值将总是指向下一条将被执行的指令,如果方法是
native的,程序计数器寄存器的值不会被定义。 JVM的程序计数器寄存器的宽度足够保证可以持有一个返回地址或者native的指针。
栈(Stack):又叫堆栈。JVM为每个新创建的线程都分配一个栈。也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。我们知道,某个线程正在执行的方法称为此线程的当前方法。我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的
Java堆栈里新压入一个帧,这个帧自然成为了当前帧。在此方法执行期间,这个帧将用来保存参数、局部变量、中间计算过程和其他数据。从Java的这种分配机制来看,堆栈又可以这样理解:栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
堆(Heap):Java堆(Java
Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域。在此区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存,但是这个对象的引用却是在栈(Stack)中分配。因此,执行String s = new String("s")时,需要从两个地方分配内存:在堆中为String对象分配内存,在栈中为引用(这个堆对象的内存地址,即指针)分配内存,如下图所示。
方法区(Method
Area):当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息,然后把这些类型信息(包括类信息、常量、静态变量等)放到方法区中,该内存区域被所有线程共享,如下图所示。本地方法区存在一块特殊的内存区域,叫常量池(Constant Pool),这块内存将与String类型的分析密切相关。
2.JAVA对象创建过程分析
以创建Person对象为例,分析对象创建过程中在内存中的分配情况以及方法的调用过程。
输出结果:这是person类的静态代码块
这是一个测试的类
这是person的构造代码块
这是person的构造函数
name = wz::age = 20
首先栈中的main函数执行Person = new Person("gao",24);这个简单的语句会涉及到如下几个步骤:
1,由于是要创建Person类对象,java虚拟机(JVM)先去找Person.class文件,如果有的话,将其加载到内存。
2,将类型信息(包括静态变量,方法等)加载进方法区。
3,执行该类中static代码块,如果有的话,对Person.class类进行初始化。(此时输出‘这是person类的静态代码块’)
4,到这时才进行堆内存空间的开辟,并为对象分配首地址。
5,在堆内存中建立对象的成员属性,并对其进行初始化(先进行默认初始化再进行显示初始化。(此时输出 ‘这是一个测试的类’)
6,进行构造代码块的初始化,由此看出构造代码库初始化的优先级要高于对象构造函数的初始化。 (此时输出 ‘这是person的构造代码块’)
7,对象的构造函数进行初始化。(此时输出 ‘这是person的构造函数’);
8,将堆内存中的地址赋给栈内存中的p变量。
以上是我的java虚拟机机制的一些理解,由于JVM的复杂性,完全理解它是很困难的,如果文章中有错误的还望大家指出。
1.JAVA内存分区
根据存储数据的不同,java内存通常被划分为5个区域:程序计数器(Program Count Register)、本地方法栈(Native Stack)、方法区(Methon Area)、栈(Stack)、堆(Heap)。
程序计数器(Program
Count Register):又叫程序寄存器。JVM支持多个线程同时运行,当每一个新线程被创建时,它都将得到它自己的PC寄存器(程序计数器)。如果线程正在执行的是一个Java方法(非native),那么PC寄存器的值将总是指向下一条将被执行的指令,如果方法是
native的,程序计数器寄存器的值不会被定义。 JVM的程序计数器寄存器的宽度足够保证可以持有一个返回地址或者native的指针。
栈(Stack):又叫堆栈。JVM为每个新创建的线程都分配一个栈。也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。我们知道,某个线程正在执行的方法称为此线程的当前方法。我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的
Java堆栈里新压入一个帧,这个帧自然成为了当前帧。在此方法执行期间,这个帧将用来保存参数、局部变量、中间计算过程和其他数据。从Java的这种分配机制来看,堆栈又可以这样理解:栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
堆(Heap):Java堆(Java
Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域。在此区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存,但是这个对象的引用却是在栈(Stack)中分配。因此,执行String s = new String("s")时,需要从两个地方分配内存:在堆中为String对象分配内存,在栈中为引用(这个堆对象的内存地址,即指针)分配内存,如下图所示。
方法区(Method
Area):当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息,然后把这些类型信息(包括类信息、常量、静态变量等)放到方法区中,该内存区域被所有线程共享,如下图所示。本地方法区存在一块特殊的内存区域,叫常量池(Constant Pool),这块内存将与String类型的分析密切相关。
2.JAVA对象创建过程分析
以创建Person对象为例,分析对象创建过程中在内存中的分配情况以及方法的调用过程。
class Person { private String name; private int age; DemoTest dTest = new DemoTest(); public Person(String name, int age) { System.out.println("这是person的构造函数"); this.name = name; this.age = age; } { System.out.println("这是person的构造代码块"); } static { System.out.println("这是person类的静态代码块"); } public void setName(String name) { this.name = name; } public void show() { System.out.println("name = "+name + "::"+"age = "+age); } } class DemoTest { public DemoTest() { System.out.println("这是一个测试的类"); } } public class test { public static void main(String[] args) { Person p = new Person("gao",24); p.setName("wz"); p.show(); } }
输出结果:这是person类的静态代码块
这是一个测试的类
这是person的构造代码块
这是person的构造函数
name = wz::age = 20
首先栈中的main函数执行Person = new Person("gao",24);这个简单的语句会涉及到如下几个步骤:
1,由于是要创建Person类对象,java虚拟机(JVM)先去找Person.class文件,如果有的话,将其加载到内存。
2,将类型信息(包括静态变量,方法等)加载进方法区。
3,执行该类中static代码块,如果有的话,对Person.class类进行初始化。(此时输出‘这是person类的静态代码块’)
4,到这时才进行堆内存空间的开辟,并为对象分配首地址。
5,在堆内存中建立对象的成员属性,并对其进行初始化(先进行默认初始化再进行显示初始化。(此时输出 ‘这是一个测试的类’)
6,进行构造代码块的初始化,由此看出构造代码库初始化的优先级要高于对象构造函数的初始化。 (此时输出 ‘这是person的构造代码块’)
7,对象的构造函数进行初始化。(此时输出 ‘这是person的构造函数’);
8,将堆内存中的地址赋给栈内存中的p变量。
以上是我的java虚拟机机制的一些理解,由于JVM的复杂性,完全理解它是很困难的,如果文章中有错误的还望大家指出。
相关文章推荐
- 黑马程序员-java内存结构和对象创建的过程
- 分享~~黑马程序员-java内存结构和对象创建的过程
- Java中对象的创建过程(内存分析)
- java内存结构和对象创建的过程
- JVM源码分析之Java对象的创建过程
- JVM源码分析之Java对象的创建过程
- java对象创建(内存模型)过程详解
- Java创建对象过程中,内存的分配
- ART运行时为新创建对象分配内存的过程分析
- Java对象创建的过程及对象的内存布局与访问定位
- 浅谈Java内存区域与对象创建过程
- Java内存区域与对象创建过程
- 对象创建的内存结构【走进JAVA-3.3】
- Java内存区域模型、对象创建过程、常见OOM
- java引用对象和创建对象过程分析
- java基础1:对象创建内存分析
- 深入内存分析String对象的创建过程
- Java内存结构、类的初始化、及对象构造过程
- Java内存结构、类的初始化、及对象构造过程
- Java 对象创建的过程和内存的运行机制