1.字节码文件
代码经过javac编译生成字节码文件,然后字节码文件经过Java虚拟机的解释进行运行。
字节码文件的开头几个字节是:0xCAFEBABE(又称魔数)
字节码文件的组成:
工具arthas,动态监控修改运行中的系统
字节码信息反编译源码
2.类的生命周期
应用场景:运行时常量池,类加载器的作用,多态的原理,类加密解密
生命周期:
–1.加载阶段
所谓不同的渠道:本地文件、动态代理生成、网络传输
–2.连接阶段
分为三个小步骤:
验证:
准备:
解析:
–初始化阶段:
3.类加载器
JDK8及之前版本中默认的类加载器:
启动类加载器BootstrapClassLoader(可以用参数扩展加载的核心类),扩展类加载器ExtentionClassLoader(加载通用类),应用程序类加载器ApplicationClassLoader(加载自定义类)
JDK9及之后
– 双亲委派机制
由于JVM中有多个类加载器,双亲委派机制的核心是解决一个类到底由谁加载的问题(优先级:Boot,Ext,Application)
向上查找:如果找到则直接返回已加载的对象
向下加载:检查该类是否在自己配置的加载路径中
–打破双亲委派机制
打破双亲委派机制:重写loadclass方法
自定义类加载器能加载java.lang.String吗?不能,java开头的包在底层被保护起来了,不能自己加载
自定义类加载器的默认父类:
参考Tomcat的应用隔离机制:
类加载器小结:
4.运行时数据区(内存管理)
程序计数器:记录当前执行的字节码指令地址、保存线程切换上下文
java虚拟机栈:
栈默认大小取决于OS和计算机体系结构
堆:OOM
默认堆大小
建议
方法区:
JDK7及之前:方法区在堆上分配永久代,不合理
JDK8及之后:方法区放在元空间中,不受JVM限制,可以使用OS内存上限
字符串常量池:intern()手动将字符串加入常量池,8之后存放于堆上
静态变量存储位置:堆中Class对象,脱离永久代
垃圾回收
方法区回收:
堆回收:
判断堆上对象是否被引用:引用计数法、可达性分析法(java采用的)
1.引用计数法:为对象维护一个引用计数器(简单易用,但是频繁维护影响性能,且无法解决循环引用)
2.可达性分析法:将对象分为两类(根对象、普通对象)
垃圾回收算法:
几种垃圾回收算法:
标记清除算法:
复制算法:
标记整理算法(标记压缩算法):
优化标记清除算法的内存碎片问题,移动碎片到连续空间中
分代GC(主流):
堆被分为:新生代(Eden、Survivor)+老年代
youngGC用的复制算法,年龄到15晋升到老年代,老年代满了后:
垃圾回收器:
G1垃圾回收器:
G1垃圾回收方式:
1.youngGC
2.MixedGC
!!与之前的回收算法不同的是第3步,不是整个GC,而是选择部分区域GC,算是一种改进的复制算法。选择的依据是每个区的平均耗时,作为下次GC的参考,以此来满足用户配置的最大暂停时间
=============================== 分割线:面试篇 =====================================