Java内存分配和管理是java的核心技术之一。一般java程序运行时会涉及到如下几个存储区域:
一、程序计数器:可以看做是当前所执行字节码的行号指示器。通常是改变计数器字节码的值来抉择下一步索要执行的代码,程序员不直接控制。
二、寄存器:在程序中我们无法直接控制,由编译器管理。
三、栈区:分为3个部分,为基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
1.一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。
2.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义的对象的引用以及局部变量。
3.每个栈中的数据都是私有的,其他栈不能访问。
4.当局部数据用完时,所占内存空间会自动释放。
Jvm栈一个最大的用处是为执行Java方法服务的,每一个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法从调用直至执行完成的过程都对应着一个栈帧在虚拟机中从入栈到出栈的过程。栈的存储与释放数据顺序为先进后出、后进先出。
栈的优势在于存取速度比较快,仅次于寄存器。缺点是存储在栈中的数据的大小和生存周期是确定的,缺乏灵活性。
四、堆区:
1.引用数据类型通过new建立的数组和对象都存储在堆中。
2.每一个对象都有相应的内存地址值。
3.对象中的变量都有默认初始化值。
4.数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个 不确定的时间被垃圾回收器释放掉。
另外要明确的是每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。在java堆中还必须包含能查找到对象类型数据(如对象类型,父类,实现的接口,方法等)的地址信息,这些类型数据(优先于对象存在)都存储在方法区中。
堆的优势在于可以动态地分配内存的大小,生存周期也不必事先告诉编译器,因为它是运行时动态地分配内存的,并用垃圾回收机制回收那些不用的数据。缺点是存取速度比较慢。
五、方法区:方法区本身又分为以下几个区域:
1.静态数据区:存放静态数据的地方
2.常量区:就是下面要介绍的常量池。
3.代码区:存放方法代码的区域
总之,方法区是JVM在装载类文件时,用于存储类型信息的(类的描述信息)地方,是一片给各个线程共享的内存区域。
常量池:
常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。JVM把常量池组织为入口列表的形式,可通过索引来访问常量池中的各个入口,并用入口标识来表示该常量池存储的数据类型。常量池在编译期间就被确定,并被保存在已编译的.class文件中的一些数据,一般分为两大类,字面量和引用量。字面量入全面提到的文本字符串,final变量等。引用量主要有类名和接口名、成员(包括成员变量和成员方法)的名称和描述符。引用量最常见的一种用法是在调用方法的时候,根据方法名找到方法的引用,并以此定位到函数体进进行函数代码的执行。
常量池中主要包括两种常量池
1.byte常量池(用来存储-128~127这之间的255个数字)
对某个int类型的数据进行赋值操作的时候,是要在这255个数字的范围内就会到常量池中寻找数据并直接进行赋值,范围之外的数字,则采用其他赋值方式进行操作。
2.String常量池(String类型是一个特殊的引用类型,主要用来存储在此处)。
一、程序计数器:可以看做是当前所执行字节码的行号指示器。通常是改变计数器字节码的值来抉择下一步索要执行的代码,程序员不直接控制。
二、寄存器:在程序中我们无法直接控制,由编译器管理。
三、栈区:分为3个部分,为基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
1.一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。
2.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义的对象的引用以及局部变量。
3.每个栈中的数据都是私有的,其他栈不能访问。
4.当局部数据用完时,所占内存空间会自动释放。
Jvm栈一个最大的用处是为执行Java方法服务的,每一个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法从调用直至执行完成的过程都对应着一个栈帧在虚拟机中从入栈到出栈的过程。栈的存储与释放数据顺序为先进后出、后进先出。
栈的优势在于存取速度比较快,仅次于寄存器。缺点是存储在栈中的数据的大小和生存周期是确定的,缺乏灵活性。
四、堆区:
1.引用数据类型通过new建立的数组和对象都存储在堆中。
2.每一个对象都有相应的内存地址值。
3.对象中的变量都有默认初始化值。
4.数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个 不确定的时间被垃圾回收器释放掉。
另外要明确的是每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。在java堆中还必须包含能查找到对象类型数据(如对象类型,父类,实现的接口,方法等)的地址信息,这些类型数据(优先于对象存在)都存储在方法区中。
堆的优势在于可以动态地分配内存的大小,生存周期也不必事先告诉编译器,因为它是运行时动态地分配内存的,并用垃圾回收机制回收那些不用的数据。缺点是存取速度比较慢。
五、方法区:方法区本身又分为以下几个区域:
1.静态数据区:存放静态数据的地方
2.常量区:就是下面要介绍的常量池。
3.代码区:存放方法代码的区域
总之,方法区是JVM在装载类文件时,用于存储类型信息的(类的描述信息)地方,是一片给各个线程共享的内存区域。
常量池:
常量池中存储了诸如文字字符串、final变量值、类名和方法名常量。JVM把常量池组织为入口列表的形式,可通过索引来访问常量池中的各个入口,并用入口标识来表示该常量池存储的数据类型。常量池在编译期间就被确定,并被保存在已编译的.class文件中的一些数据,一般分为两大类,字面量和引用量。字面量入全面提到的文本字符串,final变量等。引用量主要有类名和接口名、成员(包括成员变量和成员方法)的名称和描述符。引用量最常见的一种用法是在调用方法的时候,根据方法名找到方法的引用,并以此定位到函数体进进行函数代码的执行。
常量池中主要包括两种常量池
1.byte常量池(用来存储-128~127这之间的255个数字)
对某个int类型的数据进行赋值操作的时候,是要在这255个数字的范围内就会到常量池中寻找数据并直接进行赋值,范围之外的数字,则采用其他赋值方式进行操作。
2.String常量池(String类型是一个特殊的引用类型,主要用来存储在此处)。