字节码如何防止内存错误及提高代码质量

SonarQube与SonarLint实战:构建从本地到集成的代码质量防护体系 在软件工程领域,代码质量是保障软件可靠性与可维护性的基石。其核心原理在于通过静态代码分析技术,在不运行程序的情况下,对源代码进行自动化检查,识别潜在的缺陷、安全漏洞和代码坏味道。这项技术的核心价值在于将质量保障活动“左移”,在开发早期低成本地发现并修复问题,从而显著降低后期测试与维护成本,有效控制技术债务。在实际应用场景中,开发团队常面临本地开发与持续集成环节的质量管控脱节问题。本文聚焦于SonarQube与SonarLint这对黄金组合,深入解析如何通过SonarLint实现开发阶段的即时反馈与预防,并利 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> http://java.sun.com/jdc/JDCTechTips/2001/ 字节码防止内存错误及提高代码质量 翻译:Cherami email:cherami@163.net 开始使用JAVAP 大多Java程序员知道他们的程序通常不会被编译为本机代码而是被编译为由java虚拟机(JVM)执行的字节码格式。然而,很少有java程序员曾经看过字节码因为他们的工具不鼓励他们去看。大多Java 调试工具不允许单步执行字节码,它们要么显示源代码行,要么什么也不显示。 幸运的是JDK提供了javap,一个命令行工具,它使得查看字节码很容易。让我们看一个范例: public class ByteCodeDemo { public static void main(String[] args) { System.out.println("Hello world"); } } 在编译这个类后,你可以用十六进制编辑器打开.class文件然后参照虚拟机规范翻译字节码。幸运的是有更简单的方法。JDK包含一个命令行的反汇编器:javap,它可以转换字节码为一种可读的助记符形式,可以像下面这样通过传递'-c'参数给javap得到字节码列表: javap -c ByteCodeDemo 你应该会看到输出类似这样: public class ByteCodeDemo extends java.lang.Object { public ByteCodeDemo(); public static void main(java.lang.String[]); } Method ByteCodeDemo() 0 aload_0 1 invokespecial #1 4 return Method void main(java.lang.String[]) 0 getstatic #2 3 ldc #3 5 invokevirtual #4 8 return 仅仅从这个短小的列表你可以学到很多字节码的知识。从main方法的第一个指令开始: 0 getstatic #2 开始的整数是方法中的指令的偏移值,因此第一个指令以0开始。紧随偏移量是指令的助记符(mnemonic)。在这个范例中,'getstatic' 指令将一个静态成员压入一个称为操作数堆栈的数据结构,后续的指令可以引用这个数据结构中的成员。getstatic 指令后是要压入的成员。在这个例子中,要压入的成员是"#2 " 。如果你直接检查字节码,你会看到成员信息没有直接嵌入指令而是像所有由java类使用的常量那样存储在一个共享池中。将成员信息存储在一个常量池中可以减小字节码指令的大小,因为指令只需要存储常量池中的一个索引而不是整个常量。在这个例子中,成员信息位于常量池中的#2处。常量池中的项目的顺序是和编译器相关的,因此在你的环境中看到的可能不是'#2' 。 分析完第一个指令后很容易猜到其它指令的意思。'ldc' (load constant) 指令将常量"Hello, World."压入操作数栈。'invokevirtual'指令调用println方法,它从操作数栈弹出它的两个参数。不要忘记一个像println这样的实例方法有两个参数:上面的字符串,加上隐含的'this'引用。 字节码如何预防内存错误 Java语言经常被吹捧为开发互联网软件的"安全的"语言。表面上和c 如此相似的代码如何体现安全呢?它引入的一个重要的安全概念是防止内存相关的错误。计算机罪犯利用内存错误在其它情况下安全的程序中插入自己的恶意的代码。Java字节码是第一个可以预防这种攻击的,像下面的范例展示的: public float add(float f, int n) { return f n; } 如果你将这个方法加入上面的范例中,重新编译它,然后运行javap,你将看到的字节码类似这个: Method float add(float, int) 0 fload_1 1 iload_2 2 i2f 3 fadd 4 freturn 在方法的开始,虚拟机将方法的参数放入一个称为局部变量表的数据结构中。将像名字暗示的那样,局部变量表也包含了你声明的任何局部变量。在这个例子中,方法以三个局部变量表的项开始,这些都是add方法的参数,位置0保存this引用,而位置1和2分别保存float和int参数。 为了实际的操作这些变量,它们必须被加载(压入)到操作数栈。第一个指令fload_1将位置1处的float压入操作数栈,第二个指令iload_2将位置2处的int压入操作数栈。这些指令的一个引起注意的事情是指令中的'i'和'f'前缀,这说明Java字节码指令是强类型的。如果参数的类型和字节码的类型不匹配,VM将该字节码作为不安全的而加以拒绝。更好的是,字节码被设计为只需在类被加载时执行一次这样的类型安全检查。 这个类型安全是如何加强安全的?如果一个攻击者能够欺骗虚拟机将一个int作为一个float或者相反,它就可以很容易的以一个预期的的方法破坏计算。如果这些计算涉及银行结余,那么隐含的安全性是很明显的。更危险的是欺骗VM将一个int作为一个Object引用。在大多情况下,这将导致VM崩溃,但是攻击者只需要找到一个漏洞。不要忘记攻击者不会手工搜索这个漏洞--写出一个程序产生数以亿计的错误字节码的排列是相当容易的,这些排列试图找到危害VM的幸运的那个。 字节码的另一个内存安全防护是数组操作。'aastore' 和 'aaload' 字节码操作Java数组并且它们总是检查数组边界。如果调用程序越过了数组尾,这些字节码将抛出一个ArrayIndexOutOfBoundsException。也许所有最重要的检查都使用分支指令,例如,以if开始的字节码。在字节码中,分支指令只能转移到同一方法中的其它指令。在方法外可以传递的唯一控制是使它返回:抛出一个异常或者执行一个'invoke'指令。这不仅关闭了很多攻击,同时也防止由于摇荡引用(dangling reference)或者堆栈冲突而引发的令人厌恶的错误。如果你曾经使用系统调试器打开你的程序并定位到代码中的一个随机的位置,那么你会很熟悉这些错误。 所有这些检查中需要记住的重要的一点是它们是由虚拟机在字节码级进行的而不是仅仅由编译器在源代码级进行的。一个例如c 这样的语言的编译器可能在编译时预防上面讨论的某些内存错误,但是这些保护只是在源代码级应用。操作系统将很乐意加载执行任何机器码,无论这些代码是由精细的c 编译器产生的还是心怀恶意的攻击者产生的。简单的讲,C 仅仅是在源代码级上面向对象而Java的面向对象的特性扩展到编译过的代码级。 分析字节码提升代码质量 Java字节码的内存和安全保护无论我们是否注意都是存在地,那么我们为什么还费心查看字节码呢?在很多情况下,知道编译器如何将你的代码转换为字节码可以帮助你写出更高效的代码,而且在某些情况下可以防止不易发觉的错误。考虑下面的例子: //返回 str1 str2 的串连 String concat(String str1, String str2) { return str1 str2; } //将 str2 附加到 str1 void concat(StringBuffer str1, String str2) { str1.append(str2); } 猜猜每个方法需要多少个方法调用。现在编译这些方法并且运行javap,你会得到类似下面的输出: Method java.lang.String concat1(java.lang.String, java.lang.String) 0 new #5 3 dup 4 invokespecial #6 7 aload_1 8 invokevirtual #7 11 aload_2 12 invokevirtual #7 15 invokevirtual #8 18 areturn Method void concat2(java.lang.StringBuffer, java.lang.String) 0 aload_1 1 aload_2 2 invokevirtual #7 5 pop 6 return concat1方法执行了5个方法调用s: new, invokespecial和三个invokevirtuals,这比concat2方法执行了更多的工作,后者只执行了一个invokevirtual调用。大多Java程序员已经得到过警告,因为String是不可变的,而使用StringBuffer进行字符串连接效率更高。使用javap分析这个使得这点变得很生动。如果你不能肯定两个语言构造在性能上是否相等,你应该使用javap分析字节码。然而,对just-in-time (JIT)编译器要小心,因为JIT编译器将字节码重新编译为本机代码而能执行一些javap不能揭示的附加优化。除非你有你的虚拟机的源代码,否则你应该补充你的字节码的基准性能分析。 最后的一个范例展示了检查字节码如何帮助防止程序中的错误。像下面那样创建两个类,确保它们在独立的文件中。 public class ChangeALot { public static final boolean debug=false; public static boolean log=false; } public class EternallyConstant { public static void main(String [] args) { System.out.println("EternallyConstant beginning execution"); if (ChangeALot.debug) System.out.println("Debug mode is on"); if (ChangeALot.log) System.out.println("Logging mode is on"); } } 如果你运行EternallyConstant,你会得到信息: EternallyConstant beginning execution. 现在试着编辑ChangeALot,修改debug和log变量的值为true(两个都为true)。只重新编译ChangeALot。再次运行EternallyConstant,你将看到下面的输出: EternallyConstant beginning execution Logging mode is on debug变量怎么了?即使你将debug设置为true,信息"Debug mode is on"并没有出现。答案在字节码中。对 EternallyConstant运行javap你会看到: Method void main(java.lang.String[]) 0 getstatic #2 3 ldc #3 5 invokevirtual #4 8 getstatic #5 11 ifeq 22 14 getstatic #2 17 ldc #6 19 invokevirtual #4 22 return 惊奇吧!在log成员上有一个'ifeq'检查,而代码根本没有检查debug成员。因为debug成员被标记为final类型,编译器知道debug成员在运行时永远不会改变,因此它通过移除'if'声明进行优化。这确实是一个非常有用的优化,因为它允许你在程序中嵌入调试代码而在将它设置为false时不用付出运行时的代价。不幸的是这个优化能够导致主要的编译时混乱。如果你改变一个final成员,你必须记住重新编译任何可能引用该成员的类。这是因为这个'reference'可能已经经过优化了。Java开发环境不能总是发现这个微妙的相关性,一些能导致非常奇怪的错误。因此,古老的C 格言对于java环境仍然有效:"When in doubt, rebuild all."(有疑问,重新编译所有的代码)。 知道一些字节码的知识对于使用java编程的程序员都是有价值的。javap工具使得查看字节码很容易。有时候,使用javap检查你的代码以期提高性能和捕获特殊的不易察觉的错误时是没有用的。 字节码和VM是相当的复杂的,这已经超过这个技巧可以涵盖的范围。要知道更多东西,看看Bill Venners写的《Inside the Java Virtual Machine》(译者注:http://www.artima.com/insidejvm/ed2/ 有该书的1、2、3、4、5、7、8、9和20章的免费html版,英文。)
PHP 7 新特性 PHP 7 带来了许多新特性和改进,这些改进旨在提高性能、增强安全性和简化开发过程。对于 PHP 开发者来说,了解和掌握这些新特性对于提高开发效率和代码质量具有重要意义。 阅读详情

相关推荐

Java必知必会系列:代码质量与重构技术

作者:禅与计算机程序设计艺术 1.背景介绍 写代码是程序员的一个重要工作。但不幸的是,写的代码往往比较臃肿、难以维护。代码的质量问题直接影响到后期维护成本和运行效率,而代码的质量好坏又直接决定了程序员对自己的能力要求。所以作为一名技术专家,编写优秀的代码具有极大的重要性。而如何提高代码的质量并改善其

AI天才研究院 309

检查字节码校验 运行不影响的警告的解决方案

在Java的运行时环境中,字节码校验是一个重要的安全特性,它确保加载到Java虚拟机(JVM)中的字节码是符合Java语言规范且没有潜在的安全风险的。字节码校验通常发生在类加载的过程中,由JVM的类加载器负责执行。然而,在某些情况下,开发者可能会遇到与字节码校验相关的警告,这些警告虽然不一定会导致程序运行失败,但可能暗示了潜在的问题或优化空间。

2301_79779756的博客 2246

5G NR LDPC码(2)—— 从基图到速率匹配:解码5G高速数据信道的标准化设计

本文深入解析了5G NR LDPC码的标准化设计流程。从作为核心骨架的基图(BG1/BG2)出发,详细阐述了其如何通过扩展因子Z灵活生成实际校验矩阵,并协同传输块大小计算与分段策略。文章重点剖析了基于循环缓存和冗余版本的速率匹配机制,以及其如何高效支撑增量冗余混合自动重传请求,从而确保5G高速数据信道在复杂环境下的可靠与高效传输。

weixin_29206669的博客 273

Android eclipse中程序调试

一:断点调试 用eclipse开发android程序的时,跟VS一样是可以断点单步调试的.步骤如下.1 设置断点:在编码窗体的左边框上用鼠标双击,或者右键点击菜单,选择 Toggle Breakpoint菜单项即可. 2 在debug模式下运行程序进入调试状态:通过点击工具栏上的小虫按钮或者是在项目右键点击然后选择Debug As,Android Application菜单,启动程序的调试...

weixin_34306593的博客 465

DESeq2差异分析结果不会看?用这个R脚本5分钟生成发表级火山图和热图

本文详细介绍了如何使用R语言快速可视化DESeq2差异分析结果,5分钟内生成可直接用于论文发表的火山图和热图。通过解析DESeq2数据结构、展示ggplot2和EnhancedVolcano包的绘图技巧,以及pheatmap包的热图定制方法,帮助研究者高效呈现差异表达基因分析结果。

weixin_30326515的博客 340

【讯飞星火大模型AI】SpringBoot整合星火API:从零构建智能数据分析助手

本文详细介绍了如何使用SpringBoot框架整合讯飞星火大模型API,从零构建一个智能数据分析助手。通过清晰的步骤,指导开发者完成API密钥申请、项目搭建、SDK集成与核心代码编写,实现用户通过自然语言指令和CSV数据,即可自动获得ECharts图表代码与专业数据分析结论,极大降低数据分析与可视化的门槛。

neovim7hacker的博客 277

Android Runtime (ART) 和 Dalvik

Android Runtime (ART) 是 Android 上的应用和部分系统服务使用的托管式运行时。ART 及其前身 Dalvik 最初是专为 Android 项目打造的。作为运行时的 ART 可执行 Dalvik 可执行文件并遵循 Dex 字节码规范。ART 和 Dalvik 是运行 Dex 字节码的兼容运行时,因此针对 Dalvik 开发的应用也能在 ART 环境中运作。不过,Dalvik 采用的一些技术并不适用于 ART。有关最重要问题的信息,请参阅。

范er 3076

使用 Python 和可视化编程控制树莓派机械臂myCobot

这些模块包括逻辑、循环、数学、文本、列表、颜色、变量、函数以及控制机械臂的函数等等,所以用户可以轻松入门编程,只需单击右上角的运行就可以启动程序,做一些有趣的应用。可以搭配任意摄像头进行图像识别,具有4个 USB 端口,可以通过 Raspberry Pi 的微型 HDMI 端口连接到显示器. 最后,40 个GPIO 接头可以进行更多扩展应用,机械臂每个接口都有清晰的标记,面板上还有一个电源开关和一个直流电源插孔。您现在可以将机器人放在地板或桌子上,并用力拧紧吸盘,以确保机械臂的底座在操作过程中不会移动。

m0_62456998的博客 3966

JAVA的编译过程

        JAVA中的编译器和解释器:            Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不...

a874493738的博客 4824

手把手教你用Multisim搭建FM直接调频电路(附完整波形分析)

本文通过Multisim仿真软件,手把手教你搭建FM直接调频电路。详细介绍了从核心概念理解、压控振荡器(VCO)参数设置、电路搭建与波形观测,到带通滤波器设计与信号优化的完整流程。通过对比滤波前后的时域波形与频谱分析,帮助读者直观理解频率调制原理,并提供了常见问题的排查思路与参数调试方法,将抽象的通信理论转化为可操作的实践技能。

weixin_29230773的博客 215

【LLM】ms-Swift框架下SFT与GRPO协同优化的高效训练策略

本文深入探讨了ms-Swift框架下监督微调(SFT)与群组相对策略优化(GRPO)的协同训练策略,提升大型语言模型(LLM)的性能与效率。通过创新的架构设计和两阶段训练流程,结合GRPO的群组奖励估计与动态基线调整技术,显著优化了数学推理等任务的准确率。文章还分享了计算资源高效利用和参数调优的实战经验,为LLM训练提供了实用指导。

green的博客 994

字节码防止内存错误及提高代码质量

字节码防止内存错误及提高代码质量 作者:cherami 翻译   加入时间:2003-12-16 13:44:29  开始使用JAVAP大多Java程序员知道他们的程序通常不会被编译为本机代码而是被编译为由java虚拟机(JVM)执行的字节码格式。然而,很少有java程序员曾经看过字节码因为他们的工具不鼓励他们去看。大多Java 调试工具不允许单步执行字节码,它们要么显示源代码行,要么什么也不

Monica_Ja 1165

【异常】Codybuddy Error Code: 14003 too many requests 限流报错问题排查与解决指南

14003报错本质为服务端限流拦截,并非账号封禁或程序致命故障,90%以上的场景可通过等待冷却+规范使用行为解决。通过本文的排查步骤,可快速恢复工具使用,同时规避后续重复触发该问题。

奶爸的编程之路,也就一周冷个三天 1254

提高代码质量及字节码如何防止内存错误

<br />  <br />大多Java程序员知道他们的程序通常不会被编译为本机代码而是被编译为由java虚拟机(JVM)执行的字节码格式。然而,很少有java程序员曾经看过字节码因为他们的工具不鼓励他们去看。大多Java 调试工具不允许单步执行字节码,它们要么显示源代码行,要么什么也不显示。 <br />幸运的是JDK提供了javap,一个命令行工具,它使得查看字节码很容易。让我们看一个范例: <br /> <br />public class ByteCodeDemo { <br />public s

huxin1的专栏 905

【原创教程】汇川H5U入门教案第二课

定时器指令IN输入能流从OFF变为ON时,定时器启动计时,输出Q为ON,IN输入能流从ON变为OFF时,在IN保持为OFF期间,定时器的运行时间是PT参数指定的时间,定时器定时时间达到PT参数指定的时间后,Q变为OFF。IN输入能流为ON时,ET输出值为0,IN从ON变为OFF时,在定时器计时运行期间,ET输出当前的计时时间,定时器计时时间到达PT参数指定的时间后,ET值保持。IN输入能流为ON时,在定时器计时运行期间,ET输出当前的计时时间,定时器计时时间到达PT参数指定的时间后,ET值保持;

Qinmingyue13的博客 2484

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

字节码防止内存错误提高代码质量

为什么80%的码农都做不了架构师?>>> ...

weixin_34336292的博客 87

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

字节码防止内存错误及提高代码质量-Java基础-Java-编程开发

google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//<script type="text/javascript"

java专栏 1235

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

基于字节码的统一异常上报实践

一、前言 二、异常介绍 2.1 认识异常 2.2 Java异常的分类 2.3 异常的处理流程 2.4 异常抛出与捕获的原则 2.5 认识try/catch/finally

java_beautiful的博客 519

java代码安全和性能解析

java代码安全性检查机制 1.由类加载器将类文件,也就是编译后产生的.class文件,加载到虚拟机中,它通过区分本机文件系统的类和网络系统导入的类来增加安全性,这就可以限制任何的特洛伊木马程序,因为本机类总是先被加载,一旦所有的类都被加载完,执行文件的内存就固定了。 2.字节码校验器进行校验,字节码校验器不检查那些可信任的编译器所生成的类文件,而是对那些有意违背命名空间规定和ja...

qq_36760873的博客 645

开始使用JAVAP(转自网络)

链接:http://www.boyunjian.com/do/article/snapshot.do?uid=net.csdn.blog%2Fjava169%2Farticle%2Fdetails%2F2460659 大多Java程序员知道他们的程序通常不会被编译为本机代码而是被编译为由java虚拟机(JVM)执行的字节码格式。然而,很少有java程序员曾经看过字节码因为他们的工具不鼓励他们...

阳光宅男---关注互联网,多线程编程,分布式事务,二阶段提交 160
上一篇: Java之战SUN再次挫败微软
下一篇: 查找数据表的主键
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值