- 双亲委派模式:
- 当某个类加载器加载某一个.class文件时,会首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级类加载器没有加载,才会自己加载。
- 好处:1.防止重复加载同一个.class 2.保证核心.class不被篡改,通过委托的方式,不会篡改核心.class,即使篡改也不会加载,即使加载也不是同一个.class对象了。不同的加载器加载同一个.class也不是同一个.class了。保证class的安全。
自定义加载器---->应用程序加载器(程序的类路径,classpath)----->扩展类加载器(jar文件)------>启动类加载器 (jar文件)
2.类加载过程 www.cnblogs.com/chanshuyi/p…
-
加载--->验证(是否符合jvm字节码规范)----》 准备----》解析-----》初始化---》使用---- 》 卸载 -
字节码转化成二进制流加载到内存中,
-
对二进制字节流进行效验,只有符合jvm字节码规范的才能被JVM正确执行。
-
对类变量(静态变量,static关键字修饰的),分配内存并初始化 ():jvm
-
将常量池的符号引用转化成直接引用。:直接引用通过对符号引用进行解析,找到引用的实际内存地址。
-
在初始化阶段,类变量将被赋值为代码期望赋的值:先执行类构造器(按照顺序手机类中所有静态代码块和类变量赋值语句),后执行对象构造器(按顺序收集成员变量赋值和普通代码块,最后收集对象构造器,最终组成对象构造器)/先执行类初始化方法,再执行对象初始化方法( 实例化类对象执行)
-
初始化完成后,jvm就开始执行入口方法
-
用户的程序执行完毕,jvm就开始销毁创建的class,最后负责运行的jvm也将退出内存。
java代码转化成字节码之后,是没有构造方法的该来的,只有初始化方法和初始化对象
3. 方法论
3.1 准备阶段,jvm给类变量分配内存,并初始化零值,final修饰的类变量直接的初始值是代码中的赋值 3.2 初始化入口方法:类加载初始化阶段后,jvm会需要寻找整个main方法的入口,从而初始化main方法所在的class。需要对class进行初始化,先初始化类构造器,再初始化对象构造器。 3.3 初始化类构造器:jvm会按照顺序收集类代码块,类变量赋值语句,最后交由jvm执行。 3.4 初始化对象构造器:jvm会按照顺序手机成员变量赋值语句、普通方法代码块,最后交由jvm执行 3.5 在main方法中,如果遇到其他类的初始化方法,现在执行其他类的初始化方法,加载完后返回,如此循环往复,最后回到main方法所在类,初始化一个类,其父类没有初始化要先初始化父类。 对于静态字段,只有直接定义这个字段的类才会被初始化(执行静态代码块)。 因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
4.jvm结构:blog.csdn.net/rongtaoup/a…
内存结构指的是jvm运行时数据区的分配,也就是栈,堆之类的。java内存模型(JMM)指的是多线程下的内存模型和约束,指的是常说的主内存,工作内存之类 jvm运行时内存=共享内存区+线程内存区
4.1 程序计数器:记录程序执行到哪了(程序计数器存的是下一条指令的地址);类中的方法存放在方法区;本地方法栈:native方法、c/c++
4.2 java堆:在表头进行压栈和入栈,所以是后入先出;栈是线程私有的空间,每个线程都有独立的栈空间。栈帧是栈的元素,每一个方法对应一个栈帧。
4.3 字面量:可以直接存储、使用的数据:整数、小数、字符串、布尔、null、字符
局部变量表:存放基本数据类型的局部变量,和对象引用,但不存储对象内容 操作数栈:程序运行过程中,用于计数计算、参数传递(计算过程中临时的存储区)
4.3 java堆:所有线程共享,主要用于存放:new出来的对象,对象实例、数组 4.4 方法区(包含常量池):方法、类信息、常量、静态变量 String 常量池中;对象引用 pc寄存器:每个线程启动的时候都会创建一个pc寄存器,存储当前指令的jvm地址。
- jvm内存模型、垃圾回收 www.cnblogs.com/zhangke306s…
-
5.1 应用计数器:被引用加1, 释放减1。引用计数器为0,被回收。相互应用,无法回收引用,不适合。
-
5.2 跟踪回收器算法: