上周的时候写了一篇博客,static关键字
其中有一段:
那么静态方法保存在哪里呢?
答案:方法区
但是有几个问题需要解决一下:
1.方法区在堆里吗?
不在堆里,java1.7之前,方法区的实现叫做永久代,1.8之后,方法区的实现叫做元空间。
永久代在堆里,元空间是堆外空间。
2.元空间=方法区吗?
方法区是 JVM 的规范,而元空间则是 JVM 规范的一种实现。
3.元空间在堆里吗?
不在,元空间是堆外空间。元空间并不在虚拟机中,而是使用 本地内存。默认情况下,元空间的大小仅受 本地内存 限制
4.Class对象在方法区吗?
JDK7以上版本,静态域存储于定义类型的Class对象中,Class对象如同堆中其他对象一样,存在于GC堆中。
5.方法区存的类信息是Class对象吗?
元数据并不是类的Class对象!Class对象是加载的最终产品,类的方法代码,变量名,方法名,访问权限,返回值等等都是在方法区的
6.到底哪些东西存在方法区?
来看一下《深入理解Java虚拟机》咋说的:
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫作“非堆”(Non-Heap),目的是与Java堆区分开来。
JDK 7及其以后版本的HotSpot虚拟机选择把静态变量与类型在Java语言一端的映射Class对象存放在一起,存储于Java堆之中。
准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段,从概念上讲,这些变量所使用的内存都应当在方法区中进行分配,但必须注意到方法区本身是一个逻辑上的区域,在JDK 7及之前,HotSpot使用永久代来实现方法区时,实现是完全符合这种逻辑概念的;而在JDK 8及之后,类变量则会随着Class对象一起存放在Java堆中,这时候“类变量在方法区”就完全是一种对逻辑概念的表述了
总结一下:
运行时常量池
类型的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等
7.1.7之后,哪些东西从永久代转移到的堆中?
运行时常量池
静态变量
类变量
映射的Class对象
最后这俩问题我还不是很确定,等确定了再改。
其他
另外我还注意到了以前我没注意到的东西。
sychronize关键字锁的对象是啥
在Java里面,最基本的互斥同步手段就是synchronized关键字,这是一种块结构(Block Structured)的同步语法。synchronized关键字经过Javac编译之后,会在同步块的前后分别形成monitorenter和monitorexit这两个字节码指令。这两个字节码指令都需要一个reference类型的参数来指明要锁定和解锁的对象。如果Java源码中的synchronized明确指定了对象参数,那就以这个对象的引用作为reference;如果没有明确指定,那将根据synchronized修饰的方法类型(如实例方法或类方法),来决定是取代码所在的对象实例还是取类型对应的Class对象来作为线程要持有的锁。