Java和C++性能大比拼
用来运行Java语言的HotSpot VM主要是用C++语言来写的,所以我们在研究JDK时不得不去学习C++这门语言。C++和Java都是面向对象的语言,所以它们常被拿来做比较。本文将从性能的角度对比分析 Java 和 C++,粗略探讨两者在峰值速度、启动时间和启动性能以及内存利用率方面的差异。
## 1、峰值速度
Java的C2编译器能结合运行时的信息做推断和激进优化,其峰值性能并不比C++差。
C++有接近硬件的操作能力、执行效率和低级控制在性能要求极高的领域中占据一席之地。
所以两者并不能笼统的脱离实际来说性能的高低。不过我们倒是可以列举一些影响峰值速度的点来探讨。
### (1)内联
Java无论是C1还是C2编译器,内联都是重点的优化手段之一。Java类是动态加载的,HotSpot VM可以对这些新加载进来的类进行内联优化。不过目前的Java会在运行时调用native,在某些必要的情况下还会调用HotSpot VM内部的函数,这些是没办法内联的,这也是native开销大的原因之一。所以用纯Java写的一些算法也未必比调用native方法慢,比如在JDK8中并不支持Vector API,所以需要通过native来使用本地的向量化指令,但通过native调用时开销绝对不可以忽视。
Project Panama 的目标之一是
通过提供新的API来减少 JNI(Java Native Interface)的使用。
对于C++来说,动态链接库之间不能进行函数内联,否则就没办法让动态链接库单独进行更新和升级。另外动态分派中可被内联的情况也比较少。
### (2)动态分派
Java默认的方法都是动态分派,而C++需要通过virtual关键字专门指定,所以Java代码中的虚方法应该比C++中的多很多才对。
HotSpot VM中的虚函数能获取的信息更多,所以优化的手段也比较多,例如通过C2对receiver的类型推导、CHA(类型继承关系分析)以及运行时对receiver的type profile,这些可能让Java方法做单态内联、双态内联、多态内联、守护内联或做内联缓存优化。
C++是纯编译语言,虽然也有一些手段对虚函数做内联,但比起Java来,可用的内联信息更少,所以内联的效果肯定不如Java好。
### (3)值类型
Java不支持值类型,而C++支持。Java采用的是托管机制,其运行时动态编译编译和自动内存管理极大的降低了Java使用的门槛,不过Java不建议对底层的内存进行直接操作,所以也无法对底层的内存布局进行操作。有人将这称为导致Java和C语言之间性能差距的最后一个主要障碍。
当我们使用容器时,这种无值类型导致的性能差距可能更加明显,目前Java容器中的数组、链表不能直接保存结构,必须保存引用。所以Java数据结构和STL容器没法比。不过Java可以进行逃逸分析和标量替换,把许多临时对象的内存分配到栈上,这在一定程序上弥补了没有值类型的短板。
### (4)额外开销
HotSpot VM的托管技术让它有许多额外的开销,如GC和编译开销。在程序运行起来后,一切GC和编译相关的问题都是Java特有的,C++并不存在这种问题。
Java有许多额外检查,比如GC安全点检查、内存越界检查、类型检查等,这是我们为托管技术和安全性付出的必要代价。
Java中每个基本类型都有对应的包装类,这在一些上下文中需要频繁进行装箱和拆箱操作,C++并不存在这种问题。
总的来说,C++由于可操控性太强,只要代码写的足够好,额外开销是非常少的。对于Java来说,我们不得不做很多的让步。
## 2、启动时间和启动性能
Java虚拟机的动态特性让它可以根据需要对类进行加载。Java是面向对象的语言(Slogan:everything is object),类数量通常比较大且类加载还是IO操作,严重拖累了Java的启动速度,目前主要是通过CDS(后序的AppCDS、Dynamic CDS)来解决。
HotSpot VM为了照顾启动和峰值性能,默认采用的是分层编译,所以需要在系统运行一段时间后才能逐步由解释执行转化为解释执行 + 编译执行,这也意味着系统需要经过一段时间的预热才能达到性能巅峰
C++ 是静态编译的语言,代码在编译时直接生成机器码,启动即巅峰,其启动时间和启动性能应该要完胜Java才对。
不过随着云原生的到来,Java的启动时间慢和启动性能低的缺点被放大,Java开发者也在努力解决这些问题。例如:
(1)通过CDS来优化类加载的速度,这样可以显著减少类加载、解析和初始化的时间
(2)JDK 9开始提供工具jaotc,同时GraalVM的Native Image都是可以通过静态编译,极大地提升服务的启动速度的方式
(3)CRaC(协调恢复检查点)可以把预热后的 JVM 保存下来,然后快速启动。也就是快照保存和恢复。
更多的启动相关的优化可以看看Project Leyden项目,这个项目专注于缩短 Java 应用程序的启动时间。
另外,Azul JDK的Platform Prime版本提供了Ready Now和Ready Now Orchestrator作为解决 Java 预热问题的解决方案,阿里也在启动上做了一些优化和探索。
## 3、内存利用率
之前我写过 “历数Java虚拟机GC的种种缺点" 文章,文章中提到过额外分配和浪费的内存,如To Survivor不能用来进行内存分配,卡表需要额外的内存,Java的延迟回收让它白白点用了一段时间内存。
C++具有接近硬件的操作能力,以HotSpot VM为例,它通过重载new和delete运算符、通过C++中的资源获取即初始化技术将资源的分配和释放与对象的生命周期进行绑定等手段,实现了对内存的精确控制。
由于Java对内存的利用率低,所以和C++相比,它的峰值内存和平时内存占用都会显著高于C++程序。
Java的物理内存归还,Lilliput缩小Java对象头、CDS让多个虚拟机共享类元数据以及Valhalla项目对Java值类型的支持,都能够提高Java内存的利用率,减少浪费。
更多文章可访问:[JDK源码剖析网](http://hotspotvm.cn)
<img src="https://img2024.cnblogs.com/blog/1236123/202504/1236123-20250424100503675-351126910.png" width="550" height="200">
Java和C++性能大比拼的更多相关文章
- lua、groovy嵌入到java中的性能对比(转)
lua和groovy都是可以嵌入到java中的脚本语言.lua以高性能著称,与C/C++在游戏开放中有较多使用,groovy是一个基于Java虚拟机(JVM)的敏捷动态语言,在jvm下有着不错的性能. ...
- 2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)
2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不 ...
- 性能调优之Java系统级性能监控及优化
性能调优之Java系统级性能监控及优化 对于性能调优而言,通常我们需要经过以下三个步骤:1,性能监控:2,性能剖析:3,性能调优 性能调优:通过分析影响Application性能问题根源,进行优化 ...
- 2017年的golang、python、php、c++、c、java、Nodejs性能对比[续]
2017年的golang.python.php.c++.c.java.Nodejs性能对比[续] 最近忙,这个话题放了几天,今天来个续集. 上篇传送门: 2017年的golang.python.p ...
- Java应用常用性能分析工具
Java应用常用性能分析工具 好的工具有能有效改善和提高工作效率或加速分析问题的进度,笔者将从事Java工作中常用的性能工具和大家分享下,如果感觉有用记得投一票哦,如果你有好的工具也可以分享给我 工具 ...
- JProfiler 解决 Java 服务器的性能跟踪
作者:徐建祥(netpirate@gmail.com) 时间: 2006/01/05 来自:http://www.anymobile.org 1.摘要......................... ...
- 用于快速排查Java的CPU性能问题(top us值过高)
转载于GIT路径 https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#beer-show-busy-java-th ...
- Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试
ylbtech-Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试 1.返回顶部 1. Java 实例 - 字符串性能比较测试 Java 实例 以下实例演 ...
- Java MVC框架性能比较
Java MVC框架性能比较 - by zvane 现在各种MVC框架很多,各框架的优缺点网络上也有很多的参考文章,但介绍各框架性能方面差别的文章却不多,本人在项目开发中,感觉到采用了struts2框 ...
- 使用Memcached改进Java企业级应用性能:架构和设置
Memcached由Danga Interactive开发.用来提升LiveJournal.com站点性能. Memcached分布式架构支持众多的社交网络应用,Twitter.Facebook还有W ...
随机推荐
- SpringBoot - [04] 自动装配原理
题记部分 Spring Boot的自动装配(Auto-Configuration)原理是其简化Spring应用开发的关键特性之一,它能自动配置Spring框架及第三方库,极大地减少了手动配置的工作 ...
- Go红队开发—并发编程
目录 并发编程 go协程 chan通道 无缓冲通道 有缓冲通道 创建⽆缓冲和缓冲通道 等协程 sync.WaitGroup同步 Runtime包 Gosched() Goexit() 区别 同步变量 ...
- python面向对象-我敢站在世界巅峰保证:这里可以找到几乎百分之九十python面向对象的内容(面向对象三大特性、成员、组合、特殊成员、反射、类的约束、自定义异常、多继承之C3算法)
概要: 面向对象 2 面向对象 Java语言:只支持面向对象方式 python语言: 面向过程[不推荐] 函数式[推荐] 面向对象[比较推荐]了解.能看懂.看源码 函数式编程:代码重用性.可读性较好 ...
- 详解vue-router基本使用
来源:https://m.jb51.net/article/111499.htm 本篇文章主要介绍了详解vue-router基本使用,详细的介绍了vue-router的概念和用法,有兴趣的可以了解 ...
- 【Python-Json】自定义类输入json序列化、json的读取与写入
AI 问答 Question json支持numpy数组么 Answer 不幸的是,标准的 JSON格式 不直接支持 NumPy 数组.JSON是一种用于存储和交换数据的文本格式,它有限的数据类型只包 ...
- CATIA许可证破解方法(CMD版)
<<< catia的DS License Server Administration后不会自动弹出GUI界面,就需要使用CMD来破解安装许可证. <<< 1. ca ...
- Windows 提权-内核利用_2
本文通过 Google 翻译 Kernel Exploits Part 2 – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校 ...
- docker Get "https://registry-1.docker.io/v2/": x509: certificate is valid for
前言 docker 在进行 build 时,报错:Get "https://registry-1.docker.io/v2/": x509: certificate is vali ...
- 变速精灵+百D网盘
首先找一下相对低一点版本的客户端,比如7.26.10 https://issuepcdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.26 ...
- IvorySQL 4.4 发布
IvorySQL 4.4 已于 2025 年 3 月 10 日正式发布.新版本全面支持 PostgreSQL 17.4,新增多项新功能,并修复了已知问题. 增强功能 PostgreSQL 17.3 增 ...