知识大全 提高代码质量及字节码如何防止内存错误[1]
Posted 字节
篇首语:提兵百万西湖上,立马吴山第一峰!本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 提高代码质量及字节码如何防止内存错误[1]相关的知识,希望对你有一定的参考价值。
Java进阶:提高代码质量及字节码如何防止内存错误[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
大多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() aload_ invokespecial # return Method void main(java lang String[]) getstatic # ldc # invokevirtual # return
仅仅从这个短小的列表你可以学到很多字节码的知识 从main方法的第一个指令开始
getstatic #
开始的整数是方法中的指令的偏移值 因此第一个指令以 开始 紧随偏移量是指令的助记符(mnemonic) 在这个范例中 getstatic 指令将一个静态成员压入一个称为操作数堆栈的数据结构 后续的指令可以引用这个数据结构中的成员 getstatic 指令后是要压入的成员 在这个例子中 要压入的成员是 # 如果你直接检查字节码 你会看到成员信息没有直接嵌入指令而是像所有由java类使用的常量那样存储在一个共享池中 将成员信息存储在一个常量池中可以减小字节码指令的大小 因为指令只需要存储常量池中的一个索引而不是整个常量 在这个例子中 成员信息位于常量池中的# 处 常量池中的项目的顺序是和编译器相关的 因此在你的环境中看到的可能不是 #
分析完第一个指令后很容易猜到其它指令的意思 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) fload_ iload_ i f fadd freturn
在方法的开始 虚拟机将方法的参数放入一个称为局部变量表的数据结构中 将像名字暗示的那样 局部变量表也包含了你声明的任何局部变量 在这个例子中 方法以三个局部变量表的项开始 这些都是add方法的参数 位置 保存this引用 而位置 和 分别保存float和int参数
为了实际的操作这些变量 它们必须被加载(压入)到操作数栈 第一个指令fload_ 将位置 处的float压入操作数栈 第二个指令iload_ 将位置 处的int压入操作数栈 这些指令的一个引起注意的事情是指令中的 i 和 f 前缀 这说明Java字节码指令是强类型的 如果参数的类型和字节码的类型不匹配 VM将该字节码作为不安全的而加以拒绝 更好的是 字节码被设计为只需在类被加载时执行一次这样的类型安全检查
这个类型安全是如何加强安全的?如果一个攻击者能够欺骗虚拟机将一个int作为一个float或者相反 它就可以很容易的以一个预期的的方法破坏计算 如果这些计算涉及银行结余 那么隐含的安全性是很明显的 更危险的是欺骗VM将一个int作为一个Object引用 在大多情况下 这将导致VM崩溃 但是攻击者只需要找到一个漏洞 不要忘记攻击者不会手工搜索这个漏洞--写出一个程序产生数以亿计的错误字节码的排列是相当容易的 这些排列试图找到危害VM的幸运的那个
字节码的另一个内存安全防护是数组操作 aastore 和 aaload 字节码操作Java数组并且它们总是检查数组边界 如果调用程序越过了数组尾 这些字节码将抛出一个ArrayIndexOutOfBoundsException 也许所有最重要的检查都使用分支指令 例如 以if开始的字节码 在字节码中 分支指令只能转移到同一方法中的其它指令 在方法外可以传递的唯一控制是使它返回 抛出一个异常或者执行一个 invoke 指令 这不仅关闭了很多攻击 同时也防止由于摇荡引用(dangling reference)或者堆栈冲突而引发的令人厌恶的错误 如果你曾经使用系统调试器打开你的程序并定位到代码中的一个随机的位置 那么你会很熟悉这些错误
所有这些检查中需要记住的重要的一点是它们是由虚拟机在字节码级进行的而不是仅仅由编译器在源代码级进行的 一个例如c++这样的语言的编译器可能在编译时预防上面讨论的某些内存错误 但是这些保护只是在源代码级应用 操作系统将很乐意加载执行任何机器码 无论这些代码是由精细的c++编译器产生的还是心怀恶意的攻击者产生的 简单的讲 C++仅仅是在源代码级上面向对象而Java的面向对象的特性扩展到编译过的代码级
cha138/Article/program/Java/hx/201311/27209相关参考
大多Java程序员知道他们的程序通常不会被编译为本机代码而是被编译为由java虚拟机(JVM)执行的字节码格式然而很少有java程序员曾经看过字节码因为他们的工具不鼓励他们去看大多Java调试工具
Java字节码深入解析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一Java字节代码的组织形
深入讨论JAVA字节码加密技术(1) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 如果把的cl
JScript运行时错误JScript运行时错误是指当JScript脚本试图执行一个系统不能运行的动作时导致的错误当正在运行脚本计算变量表达式或者正在动态分配内存时出现JScript运行时错误时错误号
javap是JDK自带的反汇编器可以查看java编译器为我们生成的字节码通过它我们可以对照源代码和字节码从而了解很多编译器内部的工作语法 javap[命令选项]class javap命令用于解
深入Java字节码加密 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 问 如果我把我的clas
深入讨论JAVA字节码加密技术(2) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 这个累加载器
巧用JAVASCRIPT代码限制文本字节数 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 
用Eclipse插件提高代码质量 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 年月日 
JSP验证码代码 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 生成有个随机数字和杂乱背景的图片