1.JVM中的内存区域
常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息。
堆区:用于存放类的对象实例。
栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构,栈桢中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时,虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。
2.类装载,连接,初始化
2.1 装载
类的加载是由加载器完成的,可分为两种:
1 java虚拟机自带的加载器,包括启动类加载器,拓展类加载器和系统类加载器。
2 用户自定义的类加载器,是java.lang.ClassLoader类的子类的实例。用户可以通过它来制定类的加载器。类的加载器并不需要等到某个类被首次主动使用时再加载它,java虚拟机规范允许类加载器在预料某个类将要被使用时就预先加载它。
加载类就是把类的信息加载到jvm的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。类装载步骤的最终产品就是这个Class对象。
2.2 类的验证
1 类文件的结构检查,确保类文件遵从java类文件的固定格式。
2 语义检查确保本身符号java语言的语法规定,如验证final类型的类没有子类等
3 字节码验证:确保字节码可以被jvm安全的执行,字节码代表java方法(包括静态和实例方法),它是由被称做操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。字节码验证步骤会检查每个操作码是否合法,即是否有合法的操作数。
4 二进制兼容的验证,确保相互引用的之间协调一致,如Worker类的goWork方法会调用Car类的run方法,jvm在验证Worker类时,会检查方法区内是否存在car类的run方法,如不存在会(Worker 类和car类版本不兼容就会出现问题),就会抛出NoSuchMethodError错误。
2.3 类的准备
虚拟机载入了一个类,执行一些验证以后就进入了准备阶段。在这个阶段,java虚拟机会为类变量分配内存,设置默认的初始值。
2.4 类的解析
解析就是在类的常量池中寻找类,接口,字段和方法的符号引用,然后把这些符号引用替换成直接引用。
2.5 初始化
java虚拟机严格定义了类的初始化时机,所有的java虚拟机必须实现:必须在每个类或者接口首次主动使用时初始化
(2)当调用某个类的静态方法(在字节码中执行invokestatic的时候)
(3)使用某个类或者接口的静态字段,或者对该字段赋值时(在字节码中执行getstatic或者putstatic指令时),用final修饰的静态常量表达式除外
(4)当调用某些反射方法的时候,比如:Class中的方法,或者java.lang.reflect包中的类的方法。
(5)当初始化某个类的子类(一个类初始化的时候要求他的父类已经都被初始化完了)
(6)当虚拟机启动时,被标明为启动类的类(包含main方法的类,也是一个静态方法)