2017-07-01

本文是应InfoQ总编郭蕾的约稿,对当前的Java技术进行总结和展望。 InfoQ文章的连接

Java语言的发展回顾。

Java语言源于1991年Sun公司James Gosling领导的的Ork项目,1995年Sun公司正式起名为Java,并提出“Write once, Run anywhere"的口号。

1996年1月Java 1.0发布,提供了一个解释执行的Java虚拟机,其时恰逢互联网开始兴起,Java的Applet能在Mozilla浏览器中运行,被看作是未来的互联网语言。

1997年2月Java 1.1发布,Java语言的基本形态基本确定了,比如反射(reflection), JavaBean, 接口和类的关系等等,一直到今天都保持一致。然而,Java最初的一些目标,如在浏览器中执行Applet,以及跨平台的图形界面Awt很快遭遇到负面的评价。

1998年12月,Java第一个里程碑式的版本,即Java 1.2发布了。这个版本使用了JIT(Just in time)编译器技术,使得语言的可迁移性和执行效率达到最优的平衡,同时Collections集合类设计优良,在企业应用开发中迅速得到了广泛使用。Sun公司把Java技术体系分成三个方向,分别是J2SE(面向桌面和通用应用开发),J2EE(面向企业级应用开发),J2ME(面向移动终端开发)。这个分类影响非常久远,体现出主流语言设计者的思想:针对于不同的应用领域,在形态,API集合等进行划分。

2000年5月,Java 1.3发布,这个版本中Corba作为语言级别的分布式对象技术,成为J2EE的一个技术前提。J2EE受到Corba的设计的影响较大,早期EJB的Home,接口和实现就是Corba在C语言的实现,被移植到Java语言之中。J2EE中的Servlet规范获得了极大的成功,伴随着互联网的兴起,和浏览器直接通过HTTP协议交互的Servlet,和众多的MVC框架,成为Web1.0的网红。

2002年2月,Java 1.4发布,Java语言真正走向成熟,提供了非常完备的语言特性,如NIO,正则表达式,XML处理器等。同年微软的.NET框架发布,两者开始了为期十几年的暗自竞争。从语言特性上来说,.NET后发先至,一直处于优势。但Java依赖良好的开发者生态,绝大多数大型软件公司的使用者众多和不断贡献,以及对Linux操作系统良好的支持,渐渐的在服务器端获得优势地位。

2004年9月,Java 5发布,Sun不再采用J2SE, J2EE这种命名方式,而使用Java SE 5, Java EE 5这样的名称。我认为Java 5是第二个里程碑式的版本。Java语言语法发生很大的变化,如注解(Annotation),装箱(Autoboxing),泛型(Generic),枚举(Enum),foreach等被加入,提供了java.util.concurrent并发包。Java 5对于Java语言的推动是巨大的,特别是注解的加入,使得语言定义灵活了很多,程序员可以写出更加符合领域定义的描述性程序。

2006年5月, JavaEE 5发布,其中最主要是EJB3.0的版本升级。在此之前,EJB2.X版本被广泛质疑,SpringFramework创建者Rod Johnson在经典书籍“J2EE Development without EJB“中,对EJB2代表的分布式对象的设计方法予以批驳。EJB3则重新经过改造,使用注解方式,经过应用服务器对POJO对象进行增强来实现分布式服务能力。在某种程度,可以说EJB3挽救了JavaEE的过早消亡。

2006年12月,Java 6发布,这个语言语法改进不多,但在虚拟机内部做了大量的改进,成为一个相当成熟稳定的版本,时至今日国内的很多公司依然以Java6作为主要Java开发版本来使用。同年Sun公司做出一个伟大的决定,将Java开源。OpenJDK从Sun JDK 1.7版本分支出去,成为今天OpenJDK的基础。OpenJDK6则由OpenJDK7裁剪而来,目前由红帽负责维护,来满足Redhat Enterprise Linux 6.X 用户的需要。

2009年12月,JavaEE 6发布,这个版本应该说是JavaEE到目前为止改进最大影响最深远的一个版本。因为JavaEE5只有EJB3适应了Java注解语法的加入,而EE6全面接纳了注解。CDI和BeanValidation规范的加入,在POJO之上可以定义完备的语义,由容器来决定如何去做。Servlet也升级到3.0版本,并在接口上加入异步支持,使得系统整体效率可以大幅提高。EE划分为Full Profile和Web Profile,用户可以根据自己的需要选择不同的功能集。

在此之前,Oracle已经以74亿美金的价格收购了Sun公司,获得了Java商标和Java主导权。也收购了BEA公司,获得市场份额最大的应用服务器Webogic。JavaEE 6虽然是收购之后发布的版本,但主要的设计工作仍然由原Sun公司的Java专家完成。

2011年7月,Oracle发布Java 7, 其中主要的特性是NIO2和Fork/Join并发包,尽管语言上没有大的增强,但我个人认为,自从Oracle JDK(包括OpenJDK7),Java虚拟机的稳定性真正做到的工业级,成为一个计算平台而服务于全世界。

2013年6月,Oracle发布JavaEE 7,这个版本加入了Websocket,Batch的支持,并且引入Concurrency来对服务器多线程进行管控。然而所有的子规范,算上可选项(Optional)总共有40多项,开发者光是阅读规范文本就很吃力了,更不要说能够全局精通掌握。JavaEE规范的本质是企业级应用设计的经验凝结,每一个API都经过众多丰富经验的专家反复商议并确定。各个版本之间可以做到向后兼容,也就是说,即使是10年前写的Servlet程序,当前的开发者也可以流畅的阅读源码,经过部分代码调整和配置修改,可以部署在当今的应用服务器上。反过来,今后用Servlet4写的程序,浏览器和服务器通信使用全新的HTTP/2协议,但程序员在理解上不会有障碍,就是因为Servlet规范的API非常稳定,基本没有大的变化修改。

2014年3月,Oracle发布Java 8,这个版本是我认为的第三个有里程碑意义的Java版本。其中最引人注目的便是Lambda表达式了,从此Java语言原生提供了函数式编程能力。语言方面大的特性增加还有:Streams,Date/Time API, 新的Javascript引擎Nashorn,集合的并行计算支持等,Java8更加适应海量云计算的需要。

按照原来的计划,Java9应该在今年7月发布,但因为模块化(JPMS)投票未通过的原因,推迟到今年9月份发布。 JavaEE 8也会在今年发布,预计的时间在8-10月。其中最主要更新是Servlet 4.0和CDI 2.0,后者已经完成最终规范的发布和投票。

Java社区情况介绍。

我们按照两个方面介绍Java社区情况:

  1. Java User Group(JUG,Java用户组) 目前全世界范围有100多个JUG组织,分布在各个大洲各个国家,一般来说以地域命名。目前最有影响力的两个JUG分别是伦敦的LJC(London Java Community)和巴西的SouJava,目前都是JCP的EC(执行委员会)成员。 国内目前有GreenTea JUG(北京和杭州),Shanghai JUG,GuangDong JUG, Shenzhen JUG, Nanjing JUG等。 GreanTeaJUG以阿里巴巴研发部门成员为核心,包括北京和杭州两地各个公司从事Java开发的研发人员,过去几年成功举办了很多有业界影响力的活动,特别是邀请到众多国外的Java技术专家来分享知识,目前是国内最大的JUG开发者组织。

  2. Java开源社区 Java是一门开放的语言,其开源社区也是参与者众多。

最有名的应当数Apache社区,目前已经拥有近200个顶级项目,其中绝大多数是Java语言项目。在Java生态圈中,具有重要地位的如Ant,Commons, Tomcat,Xerces,Maven, Struts, Lucene, ActiveMQ, CXF, Camel, Hadoop等等。很多技术时代,一大批Java项目加入,如Web时代的Velocity, Wicket;JavaEE相关的Tomee, OpenJPA, OpenWebBeans,Myfaces;WebService时代的jUDDI, Axis,ServiceMix;Osgi时期的Flex, Karaf;大数据时代的HBase, Hive, Zookeeper, Cassandra;云时代的Mesos,CloudStack等等。涉及到软件开发的方方面面,可以说当今几乎所有的中型以上Java应用中,都会有Apache开源项目的身影。 国内最早参与Apache社区的以国外软件公司国内研发团队成员为主,如红帽,IONA,Intel,IBM研发中心等。如今国内互联网公司和软件公司也不断的参与,特别是开始主导一些Apache项目,如Kylin等。

JBoss开源社区,包含了50多个Java开源项目,其中有Hibernate,Drools,jBPM等业界知名开源项目,也有Undertow,Byteman, Narayana等名气不算大,但绝对是相应领域业界的顶级优秀项目。当前JBoss开源社区主要以企业应用中间件软件为主,Redhat是主要的技术贡献力量。

Eclipse开源社区,之前主要是包含Eclipse IDE的项目,后来也逐步进行多方面的扩展,比如OSGi,服务器等,目前一些知名Java项目,如Jetty,Vertx等都是Eclipse开源组织成员。此外IOT目前是Eclispe的一个重点方向,在这里可以找到完整的IOT Java开发方案。

Spring开源社区,以SpringFramework为核心,包括SpringBoot, SpringCloud, SpringSecurity, SpringXD等开源项目,在国内有广泛的应用场景。

目前大的玩家。

Java语言和品牌都是Oracle公司所有,所以Oracle公司是Java最主要的厂商。绝大多数JSR(Java规范提案)的领导者都是Oracle的雇员。 Java是一个庞大的生态圈,全世界的软件和互联网公司绝大多数都是Java用户,同时也可以参与推动Java语言的发展。任何组织或者个人都可以加入JCP(Java Community Process),并提交JSR来给JavaSE,JavaEE,JavaME等提交新的API或者服务定义。Java拥有当今最完备的语言生态,几乎所有能想到的应用范围,都有软件厂商提出过标准化的构想,其中很多已经被接纳为JSR提案。如今JSR总数已经都400多个。

JCP是发展Java的国际组织,其中的执行委员会(EC)以投票的形式对JSR提案进行表决。 目前EC包括16个合约(Ratified)席位,6个选举(Elected)席位和2个合伙(Associate)席位,以及Oracle作为所有者的永久席位。非永久席位每两年重新选举一次,每次选举为24个席位的一半,即为12个。 当前EC委员会中,对于Java起到最重要作用的,无疑是Oracle,IBM和Redhat三家公司。Oracle自然不用说;Redhat领导着JavaEE8中两项JSR,并且在操作系统,Linux,虚拟化,云计算等基础软件方面是产品领导者;IBM是软硬件最大的厂商,拥有自己的Unix操作系统和JDK版本。这三家软件厂商也是中间件厂商的强者,它们对于Java的影响是至关重要的。前不久投票被否决的JSR 376(JPMS)模块化提案,就是Redhat和IBM先后表示要投反对票,最后才没有通过的。

另外的几个重要的Java参与方分别包括:巨型互联网公司,以Twitter为代表;大型金融公司,以高盛,瑞信为代表;强大的硬件产商,Intel,NXP,Gemalto等;大型系统方案厂商,HP, Fijitsu;当然还有掌握先进Java技术的公司,如Azul,Hazelcast,Tomitribe,Jetrains等等。这些公司共同对Java的发展起到关键作用。

GC方面的进展。

JDK中主要的GC分类有:

  • Serial,单线程进行GC,在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

  • Parallel,相比Serial收集器,Parallel最主要的优势在于使用多线程去完成垃圾清理工作,这样可以充分利用多核的特性,大幅降低GC时间。

  • CMS(Concurrent Mark-Sweep),是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。实现GC线程和应用线程并发工作,不需要暂停所有应用线程。

  • G1(Garbage First Garbage Collector),G设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。相对于CMS的优势而言是内存碎片的产生率大大降低。

目前在JDK8中以上4种GC都可以使用,而在JDK9中G1 GC会成为默认的垃圾收集器。

在OpenJDK方面,Redhat开源并贡献了Shenandoah GC。这是一种新的Java虚拟机GC算法,目标是利用现代多核CPU的优势,减少大堆内存在GC处理时产生的停顿时间。在使用大内存的应用上使用,如>20G堆空间。Fedora24以后,官方源中的OpenJDK即带有Shenandoah算法,不过JDK9中还不会被加入。

无停顿的高性能GC就是Azul公司的C4(Continuously Concurrent Compacting Collector) GC了,但只提供商业版本使用。 另外IBM J9中Balanced GC,表现也很出色,能够保证相对一致的暂停时间而避免破坏性的长时间停顿。Balanced GC应用在各类IBM中间件产品之中。

Java 9目前已经可以确认的特性介绍。

Java9中,最受人关注的新特性就是Jigsaw项目带来的模块化技术特性。

Java语言一直缺乏语言级别的模块化能力,目前模块化技术通过OSGi, JBoss Modules等项目,已经在服务端程序得到了广泛的应用。Java在语言级别引入模块化能力,将极大的促进Java应用程序组件化,模块化的改变。应用程序通过模块化拆分,可以做到更灵活的引入,加载,移除组件,占用更少的内存,更适合云计算时代的要求。在JDK9 EA(预览版)中,原有的rt.jar已经被划分为若干了jmod,通过模块内的module-info.java文件来声明模块间的引用关系。 然而,模块化改造是个渐进而适度的过程,Java9为了可兼容Java8以前应用程序的运行,做出很多的让步,模块定义严格性没有那么苛刻。各个厂商也有对自己现有系统可无缝运行在Java9上的商业诉求。Java模块化提案还得花更多的时间去讨论和修改。

Java9中的jshell工具实现了REPL,即读取,求值,打印,循环。这个工具可以使得开发者交互式的使用Java,方便于系统管理,调试,使用。可以想像到有了jshell后,Java语言更加适合初学者入门学习。

Jlink工具和AOT(预先编译技术)。一直以来,Java运行方式是把程序编译成class文件,然后通过jvm运行的。这种工作方式可以做到跨平台移植,在互联网时代初期,各种Unix繁荣和Windows在桌面的一统局面下,对于占据市场起到决定性作用。 然而到了今天,无论是大型互联网公司还是企业内部,x86平台64位服务器已经成为主要的选择。从运行效率考虑,可以把java程序编译成可执行的二进制文件,更加适应云计算和容器技术发展的需要。 利用jlink/jaotc工具,可以把一个Java程序编译成可执行文件,在Java9推出时,可能只有java.base模块支持AOT。

安全方面的加强。引入新的摘要算法SHA-3,内置ALPN使得更好的支持HTTP/2协议,提供DTLS(数据包传输层安全性协议),可以保证UDP数据传输的安全,PKCS12格式替代原有的JKS成为keystore的默认格式。

此外,统一JVM日志(Unified JVM Logging),多版本共存jar(Multi-release jar files),接口内部的私有方法(Interface provate method)等也是非常重要的新特性。

与其他语言的对比,Java的优势。

Java是最好的语言么?不是,因为在每个领域都有更合适的编程语言。

  • C语言无疑是现代计算机软件编程语言的王者,几乎所有的操作系统都是C语言写成的。C++是面向对象的C语言,一直在不断的改进。

  • Javascript是能运行在浏览器中的语言,丰富的前端界面离不开Javascript的功劳。近年来的Node.js又在后端占有一席之地。

  • Python用于系统管理,并通过高性能预编译的库,提供API来进行科学计算,文本处理等,是Linux必选的解释性语言。

  • Ruby强于DSL(领域特定语言),程序员可以定义丰富的语义来充分表达自己的思想。

  • Erlang就是为分布式计算设计的,能保证在大规模并发访问的情况下,保持强壮和稳定性。

  • Go语言内置了并发能力,可以编译成本地代码。当前新的网络相关项目,很大比例是由Go语言编写的,如Docker.Kubernetes等。

  • 编写网页用PHP,函数式编程有Lisp,编写ios程序有Swift/ObjectiveC

一句话概括,能留在排行榜之上的语言,都是好的语言,在其所在的领域能做到最好。

那么,Java语言到底有什么优势可以占据排行榜第一的位置呢? 其一,语法比较简单,学过计算机编程的开发者都能快速上手。 其二,在若干了领域都有很强的竞争力,比如服务端编程,高性能网络程序,企业软件事务处理,分布式计算,Android移动终端应用开发等等。 最重要的一点是符合工程学的需求,我们知道现代软件都是协同开发,那么代码可维护性,编译时检查,较为高效的运行效率,跨平台能力,丰富的IDE,测试,项目管理工具配合。都使得Java成为企业软件公司的首选,也得到很多互联网公司的青睐。 没有短板,容易从市场上找到Java软件工程师,软件公司选择Java作为主要开发语言,再在特定的领域使用其他语言协作编程,这样的组合选择,肯定是不会有大的问题。 所以综合而言,Java语言全能方面是最好的。

一些个人的心得和经验分享

软件业有个Hype Cycle模型,有很多技术受到市场的追捧而成为明星,也有些身不逢时而备受冷漠。

  1. EJB是一个广泛被误解的技术,在企业应用分布式计算方面,EJB给出了非常完备的技术体系。只是目前所有的应用服务器都实现的不够好。对于目前打算转型微服务设计的架构师,EJB也是一个非常值得学习借鉴的技术。

  2. Java的慢是相对的,有些是当前实现的不够好。比如原来有人对Java的网络IO性能提出质疑,然而稳定的Netty框架出现后,就没有人再怀疑Java处理网络IO的能力了,甚至在JDK8中自身的NIO也相当出色。要知道Java为了实现跨平台能力,采用的是各个操作系统的一个公共能力子集,而且其设计哲学就是给出API框架,实现是可以自行实现和加载服务的。

  3. Java在处理界面方面,Swing和Swt表现可圈可点(Idea和Eclipse分别采用的图形基础库),JavaFX已经运用到很多的行业软件上。在浏览器界面表现上,SpringMVC在模板渲染页面方面使用者最多;GWT似乎使用者不多,但基于GWT的Vaddin在国外企业中用户众多,而且很多服务器管理软件也用GWT写成;JSF也在企业软件中得到广泛使用,状态信息直接在后端进行管理,配合js前端框架,可以充分发挥各种技术的优势。

  4. CDI规范和SpringFramework在服务器程序中作用类似,Spring是一套设计优良,完备的框架,CDI具有更强的可扩展性。通过对注解的语义定义,一家公司可以维护一套自己的组件描述语言,来做到产品和项目之间的软件快速复用。CDI是定义软件组件内部模型的最佳方式,只可惜了解的软件工程师实在太少。

  5. 微服务架构在互联网应用,快速开发运维管理方面,配合容器技术使用,有很强的优势。但并不是所有的应用场景都适合微服务:强事务应用系统,采用单体结构的软件体系设计,更容易从整体方面维护,也能获得更优的性能。Java语言无论在微服务还是单体结构,都有成熟稳定的软件架构供选择使用。

Java语言当前的问题和未来方向的展望

如今的Java,已经在功能上相当丰富了,Java 8加入Lambda特性,Java 9加入模块化特性之后,重要的语言特性似乎已经都纳入进来。如果要说值得考虑的一些功能,我觉得有以下几点:

  1. 模块化改造完毕之后,可能会出现更多专业的JDK发行软件商,提供在功能方面,比如针对于分布式计算,机器学习,图形计算等,纳入相关的功能库作为文件。这样专业行业客户可以选择经过充分优化后的JDK版本。

  2. Java语义上对“模式匹配”有更强的支持,如今的switch语句能力还是比较欠缺,可以向Erlang, Scala等语言借鉴。

  3. 多线程并发处理,Java做的已经很好了。不过我个人觉得可以在多进程多线程配合,以及语言级别数据管道表示上,可以进行改造和优化。

  4. JDK9会有HTTP/2 client端的能力,但毫无疑问会有更多更好的三方库出现,JDK可以和这些三方库通力合作,提供一个更好API界面和SPI参考实现。

  5. 目前Java在云计算方面遇到的最大问题还是占用内存过大。我个人认为从两个方面来看:

    1. 如果该应用的确是长时间运行的服务,可以考虑结构清晰的单体结构,算下来总的内存消耗并不会比多个微服务进程占用的更多。

    2. 微服务应用,未来可以采用编译成本地代码的方式,并使用优化过的三方库,甚至本地so文件,减少单个进程的过多内存占用。

  6. 安全框架更加清晰,SPI可以允许三方库提供更强大更高效的安全功能。

  7. JavaEE方向则有更多的改进的地方:

    1. EJB重构目前的Corba分布通信基础,参考gRPC进行远程系统调用。

    2. 分解EJB规范,把JVM进程相关的特性,如注入/加强/事务/安全都统一到CDI规范中;对EJB进行裁剪,保留远程访问特性和作为独立执行主体分布式对象能力。

    3. 加强JMS和MDB,媲美Akka目前的能力。

    4. JaxRS适度优化,不必要依赖Servlet,或者适度调整,来提供更大的能力。

    5. JPA借鉴JDO,以及融入一部分特性,做到对NoSQL更良好的支持。