内存位置分析
存储信息
java虚拟机栈:局部变量表、操作数栈、动态链接、方法出口信息。
堆:存放对象实例,几乎所有的对象实例以及数组都在这里分配内存,成员变量。
方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(1.8后方法区改成了直接内存中的元空间) 。
常量池:是方法区的一部分,主要有字面量(常量和字符串)和符号引用(类和接口的符号引用、字段的名称和描述的符号引用、方法的名称和描述的符号引用)。JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池
对于java 和内存之间,有如下几点需要注意:
1.一个Java文件,只要有main入口方法,我们就认为这是一个Java程序,可以单独编译运行。
2.无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。
3.栈中的数据和堆中的数据销毁并不是同步的。方法一旦结束,栈中的局部变量立即销毁,但是堆中对象不一定销毁。因为可能有其他变量也指向了这个对象,直到栈中没有变量指向堆中的对象时,它才销毁,而且还不是马上销毁,需要一定的时间,且受各种因素如内存堆的大小、处理器的速度等影响,所以垃圾回收器真正执行是在启动垃圾回收器后的某个时刻才能执行。
4.以上的栈、堆、代码段、数据段等等都是相对于应用程序而言的。每一个应用程序都对应唯一的一个JVM实例,每一个JVM实例都有自己的内存区域,互不影响。并且这些内存区域是所有线程共享的。这里提到的栈和堆都是整体上的概念,这些堆栈还可以细分。
5 .类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存 。对于static变量,无论创建多少个对象(甚至没有创建对象)都只占一份存储空间。
6.对于静态变量,Java运行时系统在类装载时为这个类的每个静态变量分配一块内存,以后再生成该类的对象 。对于方法或者代码块中声明的变量,编译器不为其赋初始值,使用前必须为其赋其值。
7静态变量是在类装载时初始化的,因此在产生对象前就初始化了,这也就是可以使用类名访问静态变量的原因。.
8.初始化顺序:
①对于static变量,先初始化static变量和static初始化块。
②默认值初始化实例变量(如果继承父类,父类先初始化)
③初始化实例变量和初始化块
④构造方法初始化