11 个简单的 Java 性能调优技巧

article/2025/11/9 8:28:03

大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是完全错误的。优化应用程序以获得最佳性能不是一件容易的事情。但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有11个易于遵循的建议和最佳实践可以帮助你创建一个性能良好的应用程序。

0?wx_fmt=jpeg

大部分建议是针对Java的。但也有若干建议是与语言无关的,可以应用于所有应用程序和编程语言。在讨论专门针对Java的性能调优技巧之前,让我们先来看看通用技巧。

1.在你知道必要之前不要优化

这可能是最重要的性能调整技巧之一。你应该遵循常见的最佳实践做法并尝试高效地实现用例。但是,这并不意味着在你证明必要之前,你应该更换任何标准库或构建复杂的优化。

在大多数情况下,过早优化不但会占用大量时间,而且会使代码变得难以阅读和维护。更糟糕的是,这些优化通常不会带来任何好处,因为你花费大量时间来优化的是应用程序的非关键部分。

那么,你如何证明你需要优化一些东西呢?

首先,你需要定义应用程序代码的速度得多快,例如,为所有API调用指定最大响应时间,或者指定在特定时间范围内要导入的记录数量。在完成这些之后,你就可以测量应用程序的哪些部分太慢需要改进。然后,接着看第二个技巧。

2.使用分析器查找真正的瓶颈

在你遵循第一个建议并确定了应用程序的某些部分需要改进后,那么从哪里开始呢?

你可以用两种方法来解决问题:

  • 查看你的代码,并从看起来可疑或者你觉得可能会产生问题的部分开始。

  • 或者使用分析器并获取有关代码每个部分的行为和性能的详细信息。

希望不需要我解释为什么应该始终遵循第二种方法的原因。

很明显,基于分析器的方法可以让你更好地理解代码的性能影响,并使你能够专注于最关键的部分。如果你曾使用过分析器,那么你一定记得曾经你是多么惊讶于一下就找到了代码的哪些部分产生了性能问题。老实说,我第一次的猜测不止一次地导致我走错了方向。

3.为整个应用程序创建性能测试套件

这是另一个通用技巧,可以帮助你避免在将性能改进部署到生产后经常会发生的许多意外问题。你应该总是定义一个测试整个应用程序的性能测试套件,并在性能改进之前和之后运行它。

这些额外的测试运行将帮助你识别更改的功能和性能副作用,并确保不会导致弊大于利的更新。如果你工作于被应用程序若干不同部分使用的组件,如数据库或缓存,那么这一点就尤其重要。

4.首先处理最大的瓶颈

在创建测试套件并使用分析器分析应用程序之后,你可以列出一系列需要解决以提高性能的问题。这很好,但它仍然不能回答你应该从哪里开始的问题。你可以专注于速效方案,或从最重要的问题开始。

速效方案一开始可能会很有吸引力,因为你可以很快显示第一个成果。但有时,可能需要你说服其他团队成员或管理层认为性能分析是值得的——因为暂时看不到效果。

但总的来说,我建议首先处理最重要的性能问题。这将为你提供最大的性能改进,而且可能再也不需要去解决其中一些为了满足性能需求的问题。

常见的性能调整技巧到此结束。下面让我们仔细看看一些特定于Java的技巧。

5.使用StringBuilder以编程方式连接String

有很多不同的选项来连接Java中的String。例如,你可以使用简单的+或+ =,以及StringBuffer或StringBuilder。

那么,你应该选择哪种方法?

答案取决于连接String的代码。如果你是以编程方式添加新内容到String中,例如在for循环中,那么你应该使用StringBuilder。它很容易使用,并提供比StringBuffer更好的性能。但请记住,与StringBuffer相比,StringBuilder不是线程安全的,可能不适合所有用例。

你只需要实例化一个新的StringBuilder并调用append方法来向String中添加一个新的部分。在你添加了所有的部分之后,你就可以调用toString()方法来检索连接的String。

下面的代码片段显示了一个简单的例子。在每次迭代期间,这个循环将i转换为一个String,并将它与一个空格一起添加到StringBuilder sb中。所以,最后,这段代码将在日志文件中写入“This is a test0 1 2 3 4 5 6 7 8 9”。

StringBuilder sb = newStringBuilder(“This is a test”);

for (int i=0; i<10; i++) {

   sb.append(i);

    sb.append(”“);

}

log.info(sb.toString());

正如在代码片段中看到的那样,你可以将String的第一个元素提供给构造方法。这将创建一个新的StringBuilder,新的StringBuilder包含提供的String和16个额外字符的容量。当你向StringBuilder添加更多字符时,JVM将动态增加StringBuilder的大小。

如果你已经知道你的String将包含多少个字符,则可以将该数字提供给不同的构造方法以实例化具有定义容量的StringBuilder。这进一步提高了效率,因为它不需要动态扩展其容量。

6.使用+连接一个语句中的String

当你用Java实现你的第一个应用程序时,可能有人告诉过你不应该用+来连接String。如果你是在应用程序逻辑中连接字符串,这是正确的。字符串是不可变的,每个字符串的连接结果都存储在一个新的String对象中。这需要额外的内存,会减慢你的应用程序,特别是如果你在一个循环内连接多个字符串的话。

在这些情况下,你应该遵循技巧5并使用StringBuilder。

但是,如果你只是将字符串分成多行来改善代码的可读性,那情况就不一样了。

Query q = em.createQuery(“SELECTa.id, a.firstName, a.lastName ”

+ “FROMAuthor a ”

+ “WHEREa.id = :id”);

在这些情况下,你应该用一个简单的+来连接你的字符串。Java编译器会对此优化并在编译时执行连接。所以,在运行时,你的代码将只使用1个String,不需要连接。

7.尽可能使用基元

避免任何开销并提高应用程序性能的另一个简便而快速的方法是使用基本类型而不是其包装类。所以,最好使用int来代替Integer,使用double来代替Double。这允许JVM将值存储在堆栈而不是堆中以减少内存消耗,并作出更有效的处理。

8.试着避免BigInteger和BigDecimal

既然我们在讨论数据类型,那么我们也快速浏览一下BigInteger和BigDecimal吧。尤其是后者因其精确性而受到大家的欢迎。但是这是有代价的。

BigInteger和BigDecimal比简单的long或double需要更多的内存,并且会显著减慢所有计算。所以,你如果需要额外的精度,或者数字将超过long的范围,那么最好三思而后行。这可能是你需要更改以解决性能问题的唯一方法,特别是在实现数学算法的时候。

9.首先检查当前日志级别

这个建议应该是显而易见的,但不幸的是,很多程序员在写代码的时候都会大多会忽略它。在你创建调试消息之前,始终应该首先检查当前日志级别。否则,你可能会创建一个之后会被忽略的日志消息字符串。

这里有两个反面例子。

// don’t do this

log.debug(“User [” + userName + “] called method X with [” + i + “]”);

// or this

log.debug(String.format(“User [%s] called method X with [%d]”, userName, i));

在上面两种情况中,你都将执行创建日志消息所有必需的步骤,在不知道日志框架是否将使用日志消息的前提下。因此在创建调试消息之前,最好先检查当前的日志级别。

// do this

if (log.isDebugEnabled()){

    log.debug(“User [” + userName + “] called method Xwith [” + i + “]”);

}

10.使用Apache Commons StringUtils.Replace而不是String.replace

一般来说,String.replace方法工作正常,效率很高,尤其是在使用Java 9的情况下。但是,如果你的应用程序需要大量的替换操作,并且没有更新到最新的Java版本,那么我们依然有必要查找更快和更有效的替代品。

有一个备选答案是Apache Commons Lang的StringUtils.replace方法。正如Lukas Eder在他最近的一篇博客文章中所描述的,StringUtils.replace方法远胜Java 8的String.replace方法。

而且它只需要很小的改动。即添加Apache Commons Lang项目的Maven依赖项到应用程序pom.xml中,并将String.replace方法的所有调用替换为StringUtils.replace方法。

// replace this

test.replace(“test”,“simple test”);

// with this

StringUtils.replace(test, “test”,“simple test”);

11.缓存昂贵的资源,如数据库连接

缓存是避免重复执行昂贵或常用代码片段的流行解决方案。总的思路很简单:重复使用这些资源比反复创建新的资源要便宜。

一个典型的例子是缓存池中的数据库连接。新连接的创建需要时间,如果你重用现有连接,则可以避免这种情况。

你还可以在Java语言本身找到其他例子。例如,Integer类的valueOf方法缓存了-128到127之间的值。你可能会说创建一个新的Integer并不是太昂贵,但是由于它经常被使用,以至于缓存最常用的值也可以提供性能优势。

但是,当你考虑缓存时,请记住缓存实现也会产生开销。你需要花费额外的内存来存储可重用资源,因此你可能需要管理缓存以使资源可访问,以及删除过时的资源。

所以,在开始缓存任何资源之前,请确保实施缓存是值得的,也就是说必须足够多地使用它们。

总结

正如你所看到的,有时不需要太多工作就可以提高应用程序的性能。本文中的大部分建议只需要你稍作努力就可以将它们应用于你的代码。

但是,最重要的还是那些与是什么编程语言无关的技巧:

  • 在你知道必要之前不要优化

  • 使用分析器查找真正的瓶颈

  • 首先处理最大的瓶颈


http://chatgpt.dhexx.cn/article/cEcbnIsm.shtml

相关文章

Java性能优化

文章目录 一、JVM内存模型1.1、程序计数器&#xff08;Program Counter Register&#xff09;1.2、JVM虚拟机栈&#xff08;JVM Stacks&#xff09;1.3、本地方法栈&#xff08;Native Method Stacks&#xff09;1.4、堆&#xff08;Heap&#xff09;1.5、方法区&#xff08;Me…

Java性能优化的50个细节(珍藏版)

在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要…

GNU-ARM程序开发(一)----GNU开发环境和工具

什么是GNU GNU计划&#xff0c;又称革奴计划。是由Richard Stallman在1983年9月27日公开发起的。目标是创建一套完全免费、自由的操作系统&#xff0c;基本原则是源代码共享及思想共享。 所有在GNU计划下开发的软件均为GNU软件。 为保证GNU软件可以自由地“使用、复制、修改和发…

【ARM编程】ARM介绍

01.ARM目录 ARM目录 01.ARM目录02.前言03.计算机体系结构分类04.ARM公司05.ARM应用领域06.ARM基本架构07.ARM各体系架构版本7.1 ARM版本Ⅰ&#xff1a;V1版架构7.2 ARM版本 Ⅱ&#xff1a;V2版架构7.3 ARM版本 Ⅲ&#xff1a;V3版架构7.4 ARM版本 Ⅳ&#xff1a; V4版架构7.5 A…

ARM开发环境

目录 前言一、Ubuntu及linux系统基础知识1.shell命令的运用2.Tool的安装&#xff1a;3.deb是软件包&#xff0c;dpkg是手动安装工具&#xff0c;apt是自动安装工具&#xff0c;4.Linux文件系统5.gcc编译器 二、开发环境搭建1.vim编辑器2.与windows文件互传3.VSCode使用4.NFS网络…

ARM开发环境下载地址大全

MDK5.3.8a(Keil5)最新下载地址 超链接如下&#xff0c;点击直达&#xff1a; Keil MDK (Keil Licensing) (MDK000) (arm.com) 实际网址如下所示&#xff1a; https://developer.arm.com/downloads/view/MDK000 Arm Compiler for Embedded下载地址 超链接如下&#xff0c;点击直…

什么是ARM?

原文 一、ARM是什么&#xff1f; ARM既可以认为是一个公司的名字 &#xff0c;也可以认为是对一类处理器的统称 &#xff0c;还可以认为是一种技术的名字 。 ARM公司是专门从事基于RISC技术芯片设计开发 的公司&#xff0c;作为知识产权供应商&#xff0c;本身不直接从事芯片…

X86ARM架构

这里写目录标题 cpu架构arm架构ARM架构图 x86架构arm架构和x86架构的区别CISC Vs RISCWindows如何查看系统是ARM64还是X64架构 32位与64位的区别巨头公司国产cpu公司 cpu架构 CPU 的全称是"中央处理单元"&#xff0c;它是计算机的核心&#xff0c;计算都由它来完成。…

ARM开发——常见仿真器

搞嵌入式开发和ARM开发搞了半辈子了&#xff0c;调试程序是不可避免的。接触了那么多的调试规范、调试工具、调试手段&#xff0c;彼此之间的关系却也不是特别清楚&#xff0c;今天就来捋一捋&#xff1a; JTAG协议 JTAG&#xff08;Joint Test Action Group&#xff0c;联合…

ARM开发---基础认识

本文适合初次接触ARM的的初学者&#xff0c;主要以基础知识点和科普为主. 文章目录 前言一、ARM是什么&#xff1f;二、ARM的特点三、ARM的使用场景1.计算机组成2.架构3.指令集4.指令解析5.工作模式 四、寄存器总结 前言 提起ARM&#xff0c;没有接触过的朋友可能第一反应是英…

【嵌入式】Linux开发工具arm-linux-gcc安装及使用

arm-linux-gcc 知识架构及层次 — 程序编译及调试嵌入式交叉编译器安装配置主机目标板开发模式ARM微处理器/Linux系统下编译器编译器下载及安装 arm-linux-gcc工具使用-E-S-c -o-include file-I dir-I-iprefix prefix 和 -iwithprefix dir-l库名 -L目录gcc 优化 课后作业 Linux…

ARM 编译器 Arm Compiler for Embedded 6 相关工具链简介

目录 1, Introduction to Arm Compiler 6 1.1 armclang 1.2 armasm 1.3 armlink 1.4 armar 1.5 fromelf 1.6 Arm C libraries 1.7 Arm C libraries 1,8 Application development &#xff0c;ARM程序开发流程 2&#xff0c;ARM 编译器 5和ARM 编译器 6的兼容性 3&…

ARM处理器开发详解

目录 第一章 嵌入式系统基础知识&#xff08;不考&#xff09;嵌入式系统特点交叉调试调试器 第二章 嵌入式 ARM 技术概论ARM的基本数据类型&#xff08;不考&#xff09;选择ARM芯片的一般原则Cortex-A9内核的八种工作模式流水线&#xff08;不考&#xff09;寄存器组织程序状…

ARM嵌入式常用开发工具介绍及插画开发流程(更新)

这里接着前边的开发环境的配置说&#xff0c;其实用于开发的话&#xff0c;基本的开发环境已经架构好了&#xff0c;不过由于嵌入式开发环境的特殊性(交叉编译)&#xff0c;我们还会用到一些其他的外围工具&#xff0c;这里做简要的说明。并重新介绍一下整个开发环境中&#xf…

ARM介绍

什么是ARM&#xff1f; ARM即可以是一家芯片设计厂商的名字&#xff0c;也可以代表一类微处理器的通称&#xff0c;还可以表示为一种技术的名称&#xff08;这个问题面试的时候可能问道&#xff09; 1、ARM是一个公司&#xff1a;Advanced RISC Machine Acorn RISC Machi…

《 Arm Compiler 5.06 》__ARM编译器官网下载、安装和使用说明(小白也能懂)

目录 一、前言 二、官方网站下载 三、编译器安装在 Keil 软件上 四、Keil选择编译器V5 “ V5.06 update 7(build 960) ” 五、测试 六、我的资源 (*&#xffe3;︶&#xffe3;)创作不易&#xff01;期待你们的 点赞、收藏和评论喔。 一、前言 Keil MDK-Arm5.37不再默认…

arm-linux开发板相关软件的使用

文章目录 1. 串口调试1.1 简介1.2 secureCRT使用步骤 2. 文件传输2.1 文件传输: tftp2.2 文件传输: NFS (相当于将主机作为一个u盘插入开发板) 3. 交叉编译3.1 下载3.2 配置 1. 串口调试 1.1 简介 一般而言&#xff0c;嵌入式开发板使用串口来监控后台。可以使用串口线连接开…

嵌入式:ARM相关开发工具概述

文章目录 JTAG仿真器J-LINK仿真调试器J-Link ARM主要特点 U-LINK仿真调试器ULINK2特点ULINK和JLINK的比较 ADS1.2集成开发环境使用ADS创建工程 JTAG仿真器 JTAG(Joint Test Action Group&#xff1b;联合测试行动小组)是一种国际标准测试协议&#xff08;IEEE 1149.1兼容&…

嵌入式:ARM常用开发编译软件介绍

文章目录 编译器介绍1、ADS1.22、ARM RealView Developer Suite (RVDS)3、IAR EWARM4、KEIL ARM-MDKARM5、WIN ARM-GCC ARM 编译器介绍 1、ADS1.2 ADS&#xff08;ARM Developer Suite&#xff09;&#xff0c;是在1993年由Metrowerks公司开发是ARM处理器下最主要的开发工具。…

北京邮电大学计算机考研资料汇总

北京邮电大学研招网 北京邮电大学计算机学院 北京邮电大学软件学院 北京邮电大学网络空间安全学院 北京邮电大学&#xff08;Beijing University of Posts and Telecommunications&#xff09;&#xff0c;简称北邮&#xff0c;是中华人民共和国教育部直属、工业和信息…