Java的类加载
- 过程
- 加载过程
- 类的二进制流 –> 运行时数据结构 –> 生成一个Class对象作为这个类各种数据的访问入口
- 验证
- 确保Class文件符合虚拟机要求
- 准备
- 为类变量分配内存空间,设置零值
- 解析阶段
- 将常量池中的符号引用替换为直接引用的过程
- 符号引用
- 通俗的说可以认为是类的全路径
- 直接引用
- 可以是指针、相对偏移量、句柄等可以定位到目标的量
- 初始化
- 执行真正的初始化工作
- 加载过程
类加载器
- 分类
- Java的类加载器
- OSGI
- 类与类加载器是一一对应的关系,同一类经过不同加载器加载就是不同的类
- 双亲委托模型
- 涉及的角色
- 启动类加载器、扩展类加载器、应用类加载器、自定义类加载器
- 工作过程
- 请求都会委派给父类加载器,当父加载器反馈无法加载时,子加载器才会去加载
- 优缺点
- 优点是不会产生重复加载问题
- 缺点是当基础类需要调回用户代码时,会产生问题,灵活性不够
- Java设计团队解决方案是引入上下文类加载器
- 涉及的角色
Minor GC 与 Full GC
- Minor GC 新生代
- 一般采用复制算法,效率比较高; 通过两个S区来配合进行垃圾回收
- 触发条件,当Eden区内存使用到达一定限度时,就会进行垃圾回收
- Hotspot方案为每次使用一块大的Eden和其中一块S区,当回收时,就将Eden区 和使用的S区中存活的放入到另一个S区,然后清理使用过的S区和Eden区,当S区空间不足时就会触发空间分配担保
- Full GC 老年代
- 一般采用标记整理算法
- 触发条件,老年代空间使用到达一定限度时,或者新生代的空间分配担保失败时(有参数,可以冒险也可以不冒险,不冒险时就会触发)
内存分配与回收策略
- 优先在新生代进行分配
- 大对象直接进入老年代(所以尽量避免短命大对象,容易导致提前触发垃圾收集)
- 长期存活的对象将进入老年代,默认年龄是15岁(当移入S区时年龄设置为1,每经历一次MinorGC年龄就增加一岁)
- 动态年龄判定——当相同年龄的对象大小总和大于S区大小的一半时
- 空间分配担保
- 堆空间够晋升的对象分
- 不够的话再判断历届晋升的平均大小
Full GC频繁发现?解决方案
- 使用 jstat -gcutil pid 进行查看
- 或者使用jconsole 可视化工具也可以看出来
- 解决方案
- 需要根据具体的场景,分析各个区的占用情况来总和分析
- 可能的原因一个是因为空间分配担保失败