1 语言优劣论

世上只有两种编程语言:一种被人骂,一种没人用。

Java已经诞生20多年了,依然是企业级开发中使用最广泛的语言,也是挨骂最多的语言。技术圈经常有“A语言比B语言更好”的争论,争论的核心有两点:语法和性能,比如“Java性能不如C#、Python语法比Java优雅”。

先谈谈语法的优劣。每个开发者都有自己偏爱的语法。你觉得很舒服的写法,就有人觉得别扭,这是个主观问题。比如Java 8 中的Lambda表达式,可以极大的优化集合操作的代码结构,但是不少人反感 () -> {} 这种符号,不愿意在项目中使用。再举个例子,Java语言定义变量的方式是数据类型前置、变量名后置,如: int maxSize = 100;而Go语言中变量名是前置的,如:var maxSize int = 100,写惯了Java的人肯定不适应变量名前置。习惯的力量太大了,许多人将自己的偏爱当成评判的标准。

再谈性能的优劣。编程语言的开发团队固然希望性能更好,但是性能优化要一步一步来。我们要用发展的眼光看待性能问题,早期的Java编译器和虚拟机性能确实堪忧,发展到如今已经改善了不少,以后也会继续提升。如果一款语言性能真的差到无法接受,绝不会用于企业开发中。每种语言的使用场景不同,C语言的性能固然高于Java或者C#,为什么没有人C开发Web项目?在需求快速迭代的项目里,开发效率更重要,性能够用就行,通俗的说就是人比机器贵。通常项目中遇到的大部分的性能瓶颈,降级需求或者优化设计方案就能解决,许多程序员的水平还没有达到可以指责语言性能的程度。

企业选择某款编程语言作为生产力工具,首先考虑的是人力招聘和培养的成本,其次才是语言特性和开发效率。这些年出现了许多新语言如Golang、Rust,也许概念更先进、性能更好,但是企业不会轻易在核心系统上采用新语言,以免出现不可预估的风险,保持系统的稳定才是最重要的。

2 Java的争议

1995 年 5 月 23 日,Java 正式发布。经过20多年的发展,Java孕育出了大量的开源组件和开发者。在它诞生的年代,相比其他语言有五个优势:

(1)简单易学:没有指针操作和手动内存分配,易学易用,程序员心智负担较小。

(2)面向对象:仅支持面向对象编程,单一的编程范式可以避免工程过度复杂。

(3)网络编程:提供了更简单的网络编程库,适合构建大型的网络分布式系统。

(4)反射机制:通过反射机制增强了语言的动态性,大部分开发框架都用到了这个特性。

(5)跨平台:通过JVM屏蔽了底层硬件的差异性,为上层应用提供统一的接口。应用程序被编译成与计算机结构无关的字节码,可以运行在不同的操作系统中。

事物总是有两面性,为了解决一个问题引入一个特性,也必然带来新的问题。我们应该如何辩证的看待Java广受诟病的几个问题呢?

  • 性能差

通常有GC语言不提供非常底层的内存操作方法,因此不可能达到无GC语言的性能,而且当虚拟机彻底回收垃圾时,应用程序会被强制停止,某些需要低延迟的场景绝不能接受这种状态。事实上,如果进行数值计算的基准测试,Java比 C++没有慢多少,企业开发中的Java项目速度慢的根本原因是框架滥用反射,加载反射代码要比普通程序慢几十倍,编译器没法优化反射代码。在资源紧张或者高性能场景下,C / C++仍然是首选,Java无法胜任。

  • 内存占用大

Java应用程序启动后包含JVM实例,一个“Hello World”都要消耗几十兆内存。每个Java的对象都要包含一个96 bits的对象头,一个32bits的integer就要占用内存96bits+32bits=128bits。向Go这种面向值的语言,每个值的存储消耗最低仅为2bits。企业级框架Spring大量采用HashMap缓存数据,也是极度消耗内存的。

  • GUI弱

Java桌面软件的性能低、开发体验也差。最新的GUI库JavaFX比Swing、AWT进步很多,但是远远不如Qt(C++)、WinForm / WPF (C#) 等框架。从商业角度考虑,多数企业软件并不需要跨平台,运行在Winows就足够了,少量的要兼容MacOS,Java跨平台特性在这种情况下反而是鸡肋。谷歌选择Java语言开发Android应用,看重的是庞大的Java生态,而不是语言特性。

  • 代码啰嗦

Java仅支持面向对象编程范式,书写起来极为啰嗦,比如main方法不能是一个独立的函数,必须放在没有实际意义的class中。好处是风格统一,坏处就是死板和啰嗦。采用Spring框架开发的Java项目,只要遵循基本的代码规范,每个人写出来的都差不多,可读行不会太差。与之相反,C++这种多范式语言,非结构化、结构化、面向对象、宏、模板等等应有尽有,灵活性极大,要精通也很难。维护一个大型的C++项目,就像在读一本百科全书。

3 云原生的考验

云计算是一种实施模式,是指通过互联网方式交付存储、服务器、应用等等。“云”是一种管理 IT 资源的方法,能够取代本地设备和私有数据中心。在云计算模式下,用户无需购买和维护大量的计算、存储和其他 IT 基础设施,直接访问云计算提供商的计算、网络和存储资源即可。云服务提供商能够保障物理设备的正常运转、资源的按需调配等等。

云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生是Cloud+Native的组合词,Cloud表示应用程序位于云中,而不是传统的数据中心;Native表示应用程序从设计之初即考虑到云的环境,原生为云计算而设计,可以充分发挥云计算平台的弹性和分布式优势。云原生架构有4个重要的实施原则:

(1)DevOps:采用自动化工具将应用快速部署到生成环境,并且让开发、运维互相协作。

(2)持续交付:支持频繁持续的发布应用,快速反馈部署故障,有效降低发布风险。

(3)微服务:将庞大复杂的单体服务拆分为更小的微服务,每个微服服可以快速、独立的部署。

(4)容器化:将应用程序及依赖项打包成镜像,以容器化的方式快速分发。

在虚拟化技术没有广泛应用的阶段,部署应用程序是个繁琐的事情。为了让程序在Linux、Windows等平台以及x86、AMD64、SPARC、MIPS、ARM等指令集架构上都能正常运行,必须先将源码编译为对应的可执行文件,或者直接分发源代码,由使用者自行构建可执行文件。Java发布时,提出了一句动人的口号:一次编写,到处运行”(Write Once, Run Anywhere),解决了应用部署的痛点。在云原生架构下,Java以及JVM的特性面临了新的挑战。

在微服务的背景下,围绕业务能力而非技术来构建应用,允许由不同的语言构建应用程序。一个大型的微服务集群,往往有成千上万个容器在运行。为了更有效率的管理容器,对微服务有几个诉求:镜像体积小、内存消耗少、启动速度快,这些却都是Java的弱项。再小的Java程序也带着完整的虚拟机和标准类库,这样会降低拉取镜像和创建容器的效率;Java的程序都会有固定的基本内存开销和启动时间,开源框架Spring等广泛采用的依赖注入也使得容器的启动时间过长。最好解决方案是,将Java源码直接编译为二进制可执行文件,再将可执行文件打包为镜像。

GraalVM是Oracle实验室推出的基于Java开发的开源高性能多语言运行时平台,它既可以在传统的 OpenJDK 上运行,也可以通过 AOT(Ahead-Of-Time)编译成可执行文件单独运行。GraalVM将源代码打包成可执行代码,运行时不包含JRE,实现秒级别的启动,占用内存更小。

知名开源框架 Spring 的研发团队也发布了 Spring Native 项目,利用 GraalVM 将 Spring 应用生成可执行的原生镜像(Native Image)。这些原生镜像的启动速度极快、内存消耗也更少,但是比JVM的构建时间更长、运行时优化也不足。目前 Spring Navtive 仍然处于孵化阶段,国内公司用于生产环境的很少。

参考

https://www.cnblogs.com/JaxYoun/p/16483067.html

https://zhuanlan.zhihu.com/p/333926379

https://zhuanlan.zhihu.com/p/150190166

https://www.codingbrick.com/archives/1130.html

老者Java,奋战一线的更多相关文章

  1. 2020阿里,字节跳动,JAVA岗(一线企业校招、社招)面试题合集

    前言 以下面试题全属于一线大厂社招以及校招的面试真题,各位在做这些题目对照自己的时候请平凡心对待,不要信心受挫.其实 做为致力于一线企业校招或者社招的你来说,能把每个知识模块的一小部分问题去深入学习和 ...

  2. 记一次MyBatis的错误

    错误信息:java.lang.StackOverflowError 关于这个错误的深度解析,大家可以参考这篇博文,比较详细:https://blog.csdn.net/zc375039901/arti ...

  3. 关于模板中的动态取值 ---反射与javascript脚本编译

    在项目中经常遇到一个问题,打印word或者打印excel的时候,我们经常使用一对一的赋值或者批量替换的方式来对模板进行修改. 但是现在遇到两种场景: 1.取值是通过自定以方法进行取值的. 如:一个销售 ...

  4. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  5. 一线互联网企业常见的14个Java面试题,Java面试题集大全等你拿,颤抖吧程序员!

    本文由尚学堂学员们根据自己参加过的面试回忆.总结而成,一线互联网企业常见的14个Java面试题,包括各大互联网企业.创业小公司,互联网企业.传统软件公司.对于刚毕业和想要跳槽的宝宝们,再适用不过啦,赶 ...

  6. 备战金三银四!一线互联网公司java岗面试题整理:Java基础+多线程+集合+JVM合集!

    前言 回首来看2020年,真的是印象中过的最快的一年了,真的是时间过的飞快,还没反应过来年就夸完了,相信大家也已经开始上班了!俗话说新年新气象,马上就要到了一年之中最重要的金三银四,之前一直有粉丝要求 ...

  7. 新知识:Java 利用itext填写pdf模板并导出(昨天奋战到深夜四点,知道今天两点终于弄懂)

    废话少说,不懂itext干啥用的直接去百度吧. ***************制作模板******************* 1.先用word做出界面 2.再转换成pdf格式 3.用Adobe Acr ...

  8. 一线互联网常见的14个Java面试题,你颤抖了吗程序员

    跳槽不算频繁,但参加过不少面试(电话面试.face to face面试),面过大/小公司.互联网/传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺 ...

  9. 一线互联网常见的 14 个 Java 面试题,你颤抖了吗程序员

    跳槽不算频繁,但参加过不少面试(电话面试.face to face 面试),面过大 / 小公司.互联网 / 传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程 ...

  10. 2018“金三”之一线互联网公司Java高级面试题总结

    JVM 1.请介绍一下JVM内存模型??用过什么垃圾回收器都说说呗 2.线上发送频繁full gc如何处理? CPU 使用率过高怎么办? 如何定位问题?如何解决说一下解决思路和处理方法 3.知道字节码 ...

随机推荐

  1. C程序分别实现下列字符阵列的输出

    C程序分别实现下列字符阵列的输出:(https://zhuanlan.zhihu.com/p/443989560    可以参考这个博主写的) 1,左下三角形(代码) 1 #include <s ...

  2. 从零开始写 Docker(四)---使用 pivotRoot 切换 rootfs 实现文件系统隔离

    change-rootfs-by-pivot-root.png 本文为从零开始写 Docker 系列第四篇,在mydocker run 基础上使用 pivotRoot 系统调用切换 rootfs 实现 ...

  3. Java 异常处理(1) : try-catch- finally中finally的使用

    1 package com.bytezero.throwable; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 impor ...

  4. 将Abp移植进.NET MAUI项目(三):构建UI层

    ​ 很开心,终于到了创建页面的时候了! 我们需要两个页面 MainPage 主页面 MusicItemPage 条目编辑页面 编写主页面 新建一个MainPageViewModel.cs,作为Main ...

  5. vetur 和 volar 不要一起装 - vscode插件 已解决

    vetur 和 volar 不要一起装 - vscode插件 会有各种稀奇古怪的问题. 解决方案 利用 vscode 工作区 新建工作区 然后全局 将 volar 禁用工作区,起一个新的vue3项目, ...

  6. Tomcat错误之java.lang.OutOfMemoryError:PermGen space解决方案

    公司的站点是跑在Tomcat环境下的,运行一段时间后,有时会报这样的错误:java.lang.OutOfMemoryError: PermGen space 在网上查询了一下,大部分都说是jvm虚拟机 ...

  7. js之实现页面内所有图片旋转

    javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI=do ...

  8. IO 多路复用原理

    IO 多路复用 普通情况下,一个进程只能监视一个文件描述符(阻塞),如果使用非阻塞 IO,则会使 CPU 频繁陷入内核和空转,降低效率.而IO 多路复用是操作系统提供的接口,他会帮你同时监视多个 fd ...

  9. drf(过滤、排序、异常)

    一. 过滤组件 1 内置过滤组件SearchFilter # 缺点: 外键字段的搜索操作将会抛出异常: Related Field got invalid lookup: icontains # 1) ...

  10. PagerAdapter深度解析和实践优化

    目录介绍 01.PagerAdapter简单介绍 02.PagerAdapter抽象方法 03.PagerAdapter原理介绍 04.PagerAdapter缓存和销毁 05.自定义PagerAda ...