这篇索引并不会介绍过多语言层面的基础概念,侧重点主要在于 JVM 和 JUC 这两块,属于 Java 中比较进阶的知识了,我的知识也主要来自于两本书:《深入理解Java虚拟机》和《Java并发编程的艺术》以及网上搜集的资料,这两本书写的非常棒,入门是够了,通篇基本没废话,我的笔记也基本都是摘录自这两本书。
也正是如此,相关总结就直接放到 Github 了,不抄到这里了,这一篇主要来列一个大纲,以及做一些补充。
相关笔记
点击可直达,基本是我自己总结的书中的重点(我觉得),当然一些太高深我理解不了的东西也跳过了,比如 JVM 的源码,C++、汇编、编译原理相关的。
而 Java 语言基础这里基本不涉及,大多数都是内建 API 和语法之类的东西,有个两三年学习经验的基本都比较熟的,不同语言之间差距也不大,复盘可参考笔记『Java基础复习计划』和我博客里搜索『Java基础』关键字,配合下面 JVM 等相关知识,会有更深入的理解。
由于目前 Java8 已经进入大众阶段,也不再单独介绍相关特性,复盘还是参考我的笔记和博客亦或者《Java8实战》这本书,之前写过相关笔记。
- 深入理解JVM(一)
内存区域划分、GC 前置基础知识、JDK7 之前的内置 GC 解析。 - 深入理解JVM(二)
类文件结构、类加载过程 - 深入理解JVM(补全)
类文件相关补充、常量池、字节码指令、JIT 优化、并发与锁等 - 一入Java深似海
总结自小马哥的课程,对 Java 基础的深入探讨,另一种不同的角度去看待 Java。 - Java11 Features
Java 8 - 11 新特性总结 - Java并发编程
《Java并发编程的艺术》笔记 - 深入JVM第三版补充(未完成)
- 重构的艺术
教你如何优雅的优化你写的代码,除了《重构》另外一本比较老的书没事也可以看看《代码整洁之道》
主要还是侧重 JVM、JUC、Java 基础这些东西,上面的笔记都挺长的,平均每一篇也得至少 1w+ 字,我觉得可都是精华。
JVM知识点
算是提纲吧,看着这个能说出来就不错了,忘记了就去相关笔记里翻吧。
- 运行时数据区域划分与职责
方法区、程序计数器、虚拟机栈、本地方法栈、堆;HotSpot 的实现。
永久代与直接内存(元空间) - 对象访问定位
句柄、直接指针 - GC基础
判断对象死活:引用计数(循环引用)、可达性分析、GCRoots;
引用:强软弱虚;拓展之 ThreadLocal、直接引用;
方法区回收;
HotSpot 实现:枚举根节点 STW、安全点(抢先式中断、主动式中断)、安全区域;
MinorGC、MajorGC/FullGC、动态年龄; - GC方案
分代收集、标记清除、复制算法(担保机制)、标记整理;
收集器:Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS(标记清除、低停顿)、G1;
新收集器:Epsilon、ZGC、Shenandoah - JDK提供的分析工具
经典:jps、jinfo、jstat、jstack、jconsole、jmap、VisualVM;
新增:JFR、JMC、jshell - 类文件
8 字节为单位二进制流、魔数、常量池(u2 自定义大小,包含字面量[表类型]和符号引用)、访问标志、字段表(字段重载)、方法表(重载)、属性表(严格顺序,可定制,其他表引用,32 位 solt 复用,u4/u2 方法长度 Code)、字节码指令(一个字节,非填充对齐,精简 int) - JVM 加载机制
加载、连接(验证、准备、解析)、初始化、使用、卸载;
零值、init/cinit、符号引用、直接引用、对象创建;
类加载器:双亲委派模型、Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader、破坏(模块化与动态性、OSGi、JDBC、SPI、JNDI) - 字节码执行引擎
基于栈(可移植,紧凑、实现简单、速度慢)、基于寄存器、32 bit solt(64 位的原子性问题)、动态连接、虚方法、非虚方法、动态分派(重写覆盖)、静态分派(多态);
重叠操作数栈复用; - 编译器(早期)优化
词法分析、语法分析(AST)、语法糖、注解处理器(Lombok 生成)、语义分析与字节码生成、自动拆箱、循环遍历(迭代器);
方案:常量折叠、final 校验、解语法糖、字节码提升/生成(字符串拼接 SB)、条件编译、泛型擦除;
(动态)提前编译(AOT):JDKJaotc、GCJ 等;以及 Android 的 ART(蹂躏 Dalvik) - 运行时(晚期)优化
解释器+编译器混合模式、逃生门(逆优化)、Client Compiler(c1)、Server Compiler(c2)、分层编译(3 层)、JIT 基于方法;
热点代码:方法(方法调用计数器)、循环(回边计数器,跑分)、基于采样热点探测(除前两种的其他)、基于计数热点探测、热度衰减、栈上替换(OSR)编译;
c1:简单的三段式编译,速度快,优化例如:方法内联、消除访问冗余、复写传播、无用代码消除。
c2:JIT + 监控,激进优化+逃生门,公共子表达式消除、数组边界检查消除、方法内联、逃逸分析(方法、线程逃逸,栈上分配、同步消除、标量替换) - 锁优化
适应性自旋、锁消除、锁粗化、轻量级锁、偏向锁、锁升级(锁膨胀)
在《深入理解JVM》中也提到过一些 JUC 的知识,不过仅仅是入门,这里就不列了放到 JUC 条目中。
选择 GC 的指导原则:
- 如果应⽤属于⼩规模数据应⽤(内存资源⼤概在 100 MB 左右)的话,那么串⾏收集器是⼀种不错的选择(-XX:+UseSerialGC)
- 如果应⽤运⾏在单处理器并对停顿时间不敏感的话,那么它可以考虑串⾏收集器(XX:+UseSerialGC)
- 如果应⽤属于性能敏感但停顿时间要求不⾼(如停顿⼀秒以上)的话,那么它可以选择并⾏收集 器(-XX:+UseParallelGC)
- 如果应⽤认为响应时间⽐吞吐量和停顿时间更为重要的话,那么它可以考虑 CMS 或 G1 收集器
当应⽤在单处理器中运⾏时,Parallel Collector 不会⽐ Serial Collector 表现更好,因为并⾏ 执⾏反⽽需要额外的开销(如同步和线程切换等)
当应⽤在双处理器中运⾏时,即使 Heap 达到中型或⼤型的空间,Serial Collector 可能是最 合适的选择。
Parallel Collector ⽬标调整:
- 最⼤垃圾收集停顿时间(Pause Times),默认无限制
- 吞吐量(Throughput),决定于垃圾收集与其他应⽤执⾏时间的占⽐ 通过 JVM 参数
-XX:GCTimeRatio=<N>
调整 GC 时间与⾮ GC 时间的⽐重,GC 停顿时间等于 1 / N+1 N 默认值为 99,意味着 GC 时间占 1/100 的应⽤执⾏时间 - 内存⾜迹(Footprint),指定各空间的大小。
JVM 默认的优先级顺序就是如上,Parallel Collector 每次垃圾收集过后,收集器将会保存并更新相关的统计信息,如平均的停顿时间。
Java基础
这里暂时先说一下比较容易忽视的知识点或者骚操作,那些面试常客,基本的就略过了。
- 语言基础
Java 访问修饰符是否四种?(JDK9 前后)、异常打印建议限制堆栈的深度;
Java 是否是纯面向对象的?(原生类型)
String 是否是不可变?(反射)、评价 Clone 方法(设计缺陷)、集合的线程安全(View);
可以在 final 修饰类中定义抽象方法?(枚举、字节码提升);
取余转为位运算(限制条件)、函数式编程、ClassLoader 加载(异常)、GC选择 - 集合框架
ConcurrentHashMap 或者说线程安全的 Map,为什么不允许 null 元素?(消歧义);
Set、List、Map、Deque、Navigable*
、Array/Linked/Tree;
单例扩展:Collections.singleton*
、空集合、转换集合接口、列举集合接口(of);
集合包装(Collections):只读(unmodifiable)、同步(synchronized)、类型安全(checked,避免泛型擦除影响);
特殊集合:优先级队列 PriorityQueue,枚举 Set: EnumSet;
覆盖 equals 是否要覆盖 hashcode(建议),反之呢(必须),集合的比较重复逻辑(hashcode && (== || equals)
)
鉴定 Map:IdentityHashMap(覆盖了 hashcode)MethodHandle;
是否有必要覆盖 POJO 的 hashcode 和 eq?(用于 map、比较、排序建议覆盖,默认的递归层次深);
自带排序:插入(7-)、快排(7+)、Tim排序(对象类型,更多的数量) - 并发基础
ReentrantLock、ReentrantReadWriteLock、StampedLock(读多写少,读写锁升级版);
线程池(默认的『无限』等待队列也不是很要紧,Tomcat、Nginx 这种会挡掉大部分);
CountDownLatch、CyclicBarrier、Semaphore 、ThreadPoolExecutor 和 ScheduledExecutorService;
并发集合:CopyOnWrite、ConcurrentSkipList、ConcurrentHashMap、BlockingQueue、Fork/Join、CompletableFuture、Flow(JDK9)、大小计算(并发集合中 size 一般是需要计算的)、InterruptedException;
其他参考并发编程的列举 - Java元编程
JavaBeans(参考 Spring 的 ApplicationContextEvent)、Introspection、APT(Lombok、META-INF) - I/O
NIO2、Fluent API(Builder API、Chain API)、try-with-resources(AutoCloseable);
NIO:Buffers(0 <= mark <= position <= limit <= capacity)、Channels、Selectors、flip、rewind、Channels;
其他:压缩(compact)、标记(mark,mark 设置为 position)、复制(duplicate)等 - 其他
ListIterator、快速失败(fail-fast)、失败安全(fail-safe)、user.dir、-XX:+PrintFlagsFinal
并发编程
这里提一句,美团技术团队的博客写的不错,个人比较推崇的 Java 国内圈俩神仙:美团技术团队和阿里中间件团队。
- 处理器实现原子操作
锁缓存、锁总线、Java 中 CAS 的缺点 - 再谈Volatile
缓存一致性协议,总线嗅探、缓存行对齐(JIT 无效化)、JVM 通过 lock 指令实现 - 再谈Synchronized
偏向锁获得和撤销、轻量级锁及膨胀、优缺点与使用场景 - JMM
解决主要矛盾(如何通讯、如何同步)、解决方案(共享内存和消息传递)、抽象概念;
三种重排、内存屏障、happens-before 规则、顺序一致性、final 域(static、Synchronized) - AQS
等待/通知经典范式(唤醒要继续判断)、等待超时模式、Lock 接口;
AQS 使用方式、可重写方法、模版方法(三类)、同步队列、独占式、共享式、何时阻塞、读写锁;
LockSupport 工具类、Condition 接口、等待队列(多对一) - JUC
ConcurrentHashMap 原理(Java8 前后)、ConcurrentLinkedQueue(HOPS 优化更新频率)、长度计算;
线程池、FutureTask
JVM性能监控与调优
我们并不能保证写的代码都是安全、高效的,尤其是时间紧的情况下,很多时候生产环境下跑才会发现问题,这时候如果有服务器权限并且我们有能力找出问题并解决,那么也是一个非常棒的技能。
最常见的就是 GC (内存泄漏)和线程(死锁、死循环)相关引起的问题。
TBD
临时参考博客的这篇文章
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~