学习路线
2020-12-04 09:55:08 0 举报
AI智能生成
登录查看完整内容
JAVA学习路线
作者其他创作
大纲/内容
学习路线
JVM
类加载机制
加载过程
加载
验证
准备
解析
初始化
说明1
说明2
在硬盘上查找并通过IO读入字节码文件,使用类时才会加载,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口
校验字节码文件的准确性
给类的静态变量分配内存,并赋予默认值
将符号引用替换成直接引用,该阶段会把一些静态方法(符号引用)替换成指向数据内存的指针或句柄等(直接引用),这个过程叫做静态链接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为直接引用
对类的静态变量初始化为指定值,执行静态代码块
类被加载到方法区中后主要包含 运行时常量池、类型信息、字段信息、方法信息、类加载器的引用(这个类到类加载器的引用)、对应class实例的引用(类加载器在加载类信息放到方法区后,会创建一个对应的class类型的对象实例放到堆中,作为程序访问方法区中类定义的入口)等信息
主类在运行过程中如果使用到其它类,会逐步加载这些类。jar包或war包里的类不是一次性全部加载的,是使用时才会加载。
类加载器
引导类加载器:BootstrapClassLoader
扩展类加载器:ExtClassLoader
应用程序类加载器:AppClassLoader
自定义类加载器
如果获取类加载器,以及其关系
启动过程
复杂加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar等
加载JRE目录下的位于ext扩展目录中的jar包
负责加载应用classpath路径下的jar包
自定义加载指定路径下的包
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();ClassLoader extClassLoader = appClassLoader.getParent();// 注: 引导类加载器是c++语言实现 java环境打印为空ClassLoader bootstrapClassLoader = extClassLoader.getParent();
单例模式的sun.misc.Launcher,内部会自动创建ExtClassLoader和AppClassLoader,默认使用Launcher的getClassLoader()方法会返回AppClassLoader加载应用
双亲委派机制
父子关系
设计原因
控制核心类库只能由默认的BootstrapClassLoader和ExtClassLoader来加载,防止核心类库被随意篡改
当父类加载过类后,子类不会再进行加载,保证类的唯一性
沙箱安全机制
避免类重复加载
如何打破双亲委派机制
注意
jvm默认类加载器的父子关系是:自定义加载器 => AppClassLoader => ExtClassLoader => BootstrapClassLoader类加载时会一层层往上优先委托父加载器来加载,当父加载器找不到目标时再由子加载器加载
自定义类加载,重写loadClass()方法应用:同一个tomcat部署不同版本的应用、热加载等
同一个JVM中,两个相同包和类名的类对象可以共存,因为他们的类加载器可以不一样,所以判断两个类是否是同一个,不只要看它的包名和类名,还要看他们的类加载器是不是同一个
JVM内存模型
运行时数据区
虚拟机栈(线程栈)
栈帧
局部变量表
操作数栈
动态链接
方法返回地址
其它额外信息
每一个方法从调用开始到执行结束,都对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。在编译期间,栈帧中需要多大的局部变量表,需要多深的操作数栈就已经被分析计算出来,存入到方法表中的Code属性中,也就是说,一个栈帧需要分配多少内存,并不会受到程序运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式。
本地方法栈
程序计数器
方法区
运行时常量池
用于存放类编译期生成的各种字面量和符号引用
堆
线程私有,较小的一块内存空间,可以看成是当前线程所执行字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
线程私有,为每个线程分配的内存空间,通过-Xss配置大小,默认1M。线程运行过程中,每有一个方法执行时,都会同步创建一个栈帧(注意不是嵌套结构),用于存放这个方法的局部变量表、操作数栈、动态链接、方法出口等信息。
线程私有,同虚拟机栈相似,区别只在于本地方法栈是为本地方法服务(native)
线程共享,用于存放类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。JDK7以前也叫永久代(仅针对HotShop虚拟机,其它虚拟机没有永久代概念),到了JDK8使用元空间(metaspace)代替,在JDK7的时候,HotSpot已经把原本放在永久代里的字符串常量池、静态变量等移到了堆中,到了JDK8完全废除永久代,改用元空间存放剩下的类型信息等。
线程共享,存放对象实例,Java中“几乎”(存在栈上分配、标量替换的情况,逃逸分析技术)所有的对象实例都保存在该区域。Java堆是垃圾收集器管理的区域,有些地方又称之为\"GC堆\"。大部分垃圾收集器基于分代收集理论,都会将堆划分为年轻代、老年代,基于复制算法年轻代中又分为较大的Eden区和两个较小的Survivor区。通过-Xmx和-Xms设置堆的大小。
类装载子系统
执行引擎
内存分配与回收策略
对象优先在Eden区回收
大对象直接进入老年代
长期存活的对象进去老年代
对象动态年龄判断
空间分配担保机制
大多数收集器基于分代收集理论,对象在新生代Eden中分配。当Eden区空间不足时触发MinorGC,当Survivor区不足以存放MinorGC后剩余的对象,则直接分配到老年代。
大对象就是指需要大量连续内存空间的Java对象,例如:长字符串、大数组。通过参数:-XX:PretenureSizeThreshold(单位是字节,)设置多大的对象直接进入老年代
子主题
0 条评论
回复 删除
下一页