作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问题?
开发人员的病态?
架构师需要干什么?
Java VS C++:
垃圾收集机制为我们打理了很多繁琐的工作,大大提高了开发的效率,但是,垃圾收集也不是万能的,懂得JVM内部的内存结构、工作机制,是设计高扩展性应用和诊断运行时问题的基础,也是Java工程师进阶的必备能力。
C语言需要自己来分配内存和回收内存,Java全部交给JVM进行分配和回收。
Java 生态圈?
Java的跨平台性:
字节码:
多语言混合编程:
自己写个 JVM:
Java 重大事件:
1990年,在Sun计算机公司中,由Patrick Naughton、MikeSheridan及James
Gosling领导的小组Green Team,开发出的新的程序语言,命名为Oak,后期命名为Java
1995年,Sun正式发布Java和HotJava产品,Java首次公开亮相。
1996年1月23日Sun Microsystems发布了JDK 1.0。
1998年,JDK1.2版本发布。同时,Sun发布了JSP/Servlet、EJB规范,以及将Java分成了J2EE、J2SE和J2ME。这表明了Java开始向企业、桌面应用和移动设备应用3大领域挺进。
2000年,JDK1.3发布,Java HotSpot Virtual Machine正式发布,成为Java的默认虚拟机。
2002年,JDK1.4发布,古老的Classic虚拟机退出历史舞台。
2003年年底,Java平台的scala正式发布,同年Groovy也加入了Java阵营。
2004年,JDK1.5发布。同时JDK1.5改名为JavaSE5.0。
2006年,JDK6发布。同年,Java开源并建立了OpenJDK。顺理成章,Hotspot虚拟机也成为了OpenJDK中的默认虚拟机。
2007年,Java平台迎来了新伙伴Clojure。
2008年,oracle收购了BEA,得到了JRockit虚拟机。
2009年,Twitter宣布把后台大部分程序从Ruby迁移到Scala,这是Java平台的又一次大规模应用。
2010年,Oracle收购了Sun,获得Java商标和最真价值的HotSpot虚拟机。此时,Oracle拥有市场占用率最高的两款虚拟机HotSpot和JRockit,并计划在未来对它们进行整合:HotRockit
2011年,JDK7发布。在JDK1.7u4中,正式启用了新的垃圾回收器G1。
2017年,JDK9发布。将G1设置为默认GC,替代CMS
同年,IBM的J9开源,形成了现在的Open J9社区
2018年,Android的Java侵权案判决,Google赔偿Oracle计88亿美元
同年,Oracle宣告JavagE成为历史名词JDBC、JMS、Servlet赠予Eclipse基金会
同年,JDK11发布,LTS版本的JDK,发布革命性的ZGC,调整JDK授权许可
虚拟机概念:
Java 虚拟机:
Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。
JVM平台的各种语言可以共享Java虚拟机带来的跨平台性、优秀的垃圾回器,以及可靠的即时编译器。
Java技术的核心就是Java虚拟机(JVM,Java VirtualMachine),因为所有的Java程序都运行在Java虚拟机内部。
Java虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台上的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里。
特点:
①一次编译,到处运行
②自动内存管理
③自动垃圾回收功能
JVM 的位置:
Java编译器输入的指令流基本上是一种基于栈的指令集架构,另外一种指令集架构则是基于寄存器的指令集架构。具体来说:这两种架构之间的区别:
基于栈的指令集架构特点:
基于寄存器的指令级架构特点:
两种架构的举例:
同样执行2+3这种逻辑操作,其指令分别如下:
基于栈的计算流程(以Java虚拟机为例):
iconst_2 //常量2入栈
istore_1
iconst_3 // 常量3入栈
istore_2
iload_1
iload_2
iadd //常量2/3出栈,执行相加
istore_0 // 结果5入栈
而基于寄存器的计算流程
mov eax,2 //将eax寄存器的值设为1
add eax,3 //使eax寄存器的值加3
如何反编译字节码文件:
public class StackStruTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int k = i + j;
}
}
javap -v StackStruTest.class
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_2 // 将常量 2 压入栈中
1: istore_1 // 将常量 2 保存至变量 i 中
2: iconst_3 // 将常量 3 压入栈中
3: istore_2 // 将常量 3 保存至变量 j 中
4: iload_1 // 加载变量 i
5: iload_2 // 加载变量 j
6: iadd // 执行累加操作
7: istore_3 // 加法结果保存在变量 k 中
8: return
LineNumberTable:
line 10: 0
line 11: 2
line 12: 4
line 22: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
2 7 1 i I
4 5 2 j I
8 1 3 k I
}
虚拟机的启动:
虚拟机的执行:
虚拟机的退出有如下的几种情况:
查看虚拟机进程:
public class StackStruTest {
public static void main(String[] args) {
int i = 2;
int j = 3;
int k = i + j;
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello");
}
}
exit() 方法源码分析:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class Runtime
are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the Runtime
object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {
}
public void exit(int status) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkExit(status);
}
Shutdown.exit(status);
}
static void exit(int status) {
boolean runMoreFinalizers = false;
synchronized (lock) {
if (status != 0) runFinalizersOnExit = false;
switch (state) {
case RUNNING: /* Initiate shutdown */
state = HOOKS;
break;
case HOOKS: /* Stall and halt */
break;
case FINALIZERS:
if (status != 0) {
/* Halt immediately on nonzero status */
halt(status);
} else {
/* Compatibility with old behavior:
* Run more finalizers and then halt
*/
runMoreFinalizers = runFinalizersOnExit;
}
break;
}
}
if (runMoreFinalizers) {
runAllFinalizers();
halt(status);
}
synchronized (Shutdown.class) {
/* Synchronize on the class object, causing any other thread
* that attempts to initiate shutdown to stall indefinitely
*/
sequence();
halt(status);
}
}
static void halt(int status) {
synchronized (haltLock) {
halt0(status);
}
}
static native void halt0(int status);
/* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
private static native void runAllFinalizers();
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
Sun Classic VM:
Exact VM:
为了解决上一个虚拟机问题,jdk1.2时,Sun提供了此虚拟机。
Exact Memory Management:准确式内存管理。也可以叫Non-Conservative/Accurate Memory Management
虚拟机可以知道内存中某个位置的数据具体是什么类型。
①具备现代高性能虚拟机的维形
②热点探测(寻找出热点代码进行缓存)
③编译器与解释器混合工作模式
只在Solaris平台短暂使用,其他平台上还是classic vm,英雄气短,终被Hotspot虚拟机替换
HotSpot VM:
HotSpot历史:
①最初由一家名为“Longview Technologies”的小公司设计
②1997年,此公司被Sun收购;2009年,Sun公司被甲骨文收购。
③JDK1.3时,HotSpot VM成为默认虚拟机
目前Hotspot占有绝对的市场地位,称霸武林。
① 不管是现在仍在广泛使用的JDK6,还是使用比例较多的JDK8中,默认的虚拟机都是HotSpot
②Sun/oracle JDK和openJDK的默认虚拟机
③因此本课程中默认介绍的虚拟机都是HotSpot,相关机制也主要是指HotSpot的GC机制。(比如其他两个商用虚机都没有方法区的概念)
从服务器、桌面到移动端、嵌入式都有应用。
名称中的HotSpot指的就是它的热点代码探测技术。
①通过计数器找到最具编译价值代码,触发即时编译或栈上替换
②通过编译器与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡
JRockit:
IBM的J9:
KVM和CDC / CLDC Hotspot:
Oracle在Java ME产品线上的两款虚拟机为:CDC/CLDC HotSpot Implementation VM
KVM(Kilobyte)是CLDC-HI早期产品目前移动领域地位尴尬,智能机被Android和iOS二分天下。
KVM简单、轻量、高度可移植,面向更低端的设备上还维持自己的一片市场
①智能控制器、传感器
②老人手机、经济欠发达地区的功能手机
所有的虚拟机的原则:一次编译,到处运行。
Azul VM:
Liquid VM:
Apache Marmony:
Micorsoft JVM:
Taobao JVM:
由AliJVM团队发布。阿里,国内使用Java最强大的公司,覆盖云计算、金融、物流、电商等众多领域,需要解决高并发、高可用、分布式的复合问题。有大量的开源产品。
基于OpenJDK开发了自己的定制版本AlibabaJDK,简称AJDK。是整个阿里Java体系的基石。
基于OpenJDK Hotspot VM发布的国内第一个优化、深度定制且开源的高性能服务器版Java虚拟机。
①创新的GCIH(GCinvisible heap)技术实现了off-heap,即将生命周期较长的Java对象从heap中移到heap之外,并且GC不能管理GCIH内部的Java对象,以此达到降低GC的回收频率和提升GC的回收效率的目的。
②GCIH中的对象还能够在多个Java虚拟机进程中实现共享
③使用crc32指令实现JvM intrinsic降低JNI的调用开销
④PMU hardware的Java profiling tool和诊断协助功能
⑤针对大数据场景的ZenGC
taobao vm应用在阿里产品上性能高,硬件严重依赖inte1的cpu,损失了兼容性,但提高了性能
目前已经在淘宝、天猫上线,把Oracle官方JvM版本全部替换了。
Dalvik VM:
Graal VM:
2018年4月,Oracle Labs公开了GraalvM,号称 “Run Programs Faster
Anywhere”,勃勃野心。与1995年java的”write once,run anywhere"遥相呼应。
GraalVM在HotSpot VM基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”
的运行平台使用。语言包括:Java、Scala、Groovy、Kotlin;C、C++、Javascript、Ruby、Python、R等
支持不同语言中混用对方的接口和对象,支持这些语言使用已经编写好的本地库文件
工作原理是将这些语言的源代码或源代码编译后的中间格式,通过解释器转换为能被Graal VM接受的中间表示。Graal VM提供Truffle工具集快速构建面向一种新语言的解释器。在运行时还能进行即时编译优化,获得比原生编译器更优秀的执行效率。
如果说HotSpot有一天真的被取代,Graalvm希望最大。但是Java的软件生态没有丝毫变化。
总结: