浅谈Java程序运行机制及错误分析
作者:Iceflame
JVM(Java虚拟机)一种用于计算设备的规范,可用不同的方式(软件或硬件)加以实现。编译虚拟机的指令集与编译微处理器的指令集非常类似。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。
Java虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。
1.为什么要使用Java虚拟机
Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编 译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台 相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字 节码时,把字节码解释成具体平台上的机器指令执行。
Java运行机制
Java程序的运行必须经过编写 、编译 、运行 三个步骤。
编写是指在Java开发环境中进行程序代码的输入,最终形成后缀名为.java的Java源文件。
编译是指使用Java编译器对源文件进行错误排查的过程,编译后将生成后缀名为.class的字节码文件,这不像C语言那样最终生成可执行文件。
运行是指使用Java解释器将字节码文件翻译成机器代码,执行并显示结果
字节码文件是一种和任何具体机器环境及操作系统环境无关的中间代码,它是一种二进制文件,是Java源文件由Java编译器编译后生成的目标代码文件。编程人员和计算机都无法直接读懂字节码文件,它必须由专用的Java解释器来解释执行,因此Java是一种在编译基础上进行解释运行的语言。
Java解释器负责将字节码文件翻译成具体硬件环境和操作系统平台下的机器代码,以便执行。因此Java程序不能直接运行在现有的操作系统平台上,它必须运行在被称为Java虚拟机的软件平台之上。
Java虚拟机(JVM)是运行Java程序的软件环境,Java解释器就是Java虚拟机的一部分。在运行Java程序时,首先会启动JVM,然 后由它来负责解释执行Java的字节码,并且Java字节码只能运行于JVM之上。这样利用JVM就可以把Java字节码程序和具体的硬件平台以及操作系 统环境分隔开来,只要在不同的计算机上安装了针对于特定具体平台的JVM,Java程序就可以运行,而不用考虑当前具体的硬件平台及操作系统环境,也不用 考虑字节码文件是在何种平台上生成的。JVM把这种不同软硬件平台的具体差别隐藏起来,从而实现了真正的二进制代码级的跨平台移植。JVM是Java平台 无关的基础,Java的跨平台特性正是通过在JVM中运行Java程序实现的。
Java语言这种“一次编写,到处运行(write once,run anywhere)”的方式,有效地解决了目前大多数高级程序设计语言需要针对不同系统来编译产生不同机器代码的问题,即硬件环境和操作平台的异构问题,大大降低了程序开发、维护和管理的开销。
需要注意的是,Java程序通过JVM可以达到跨平台特性,但JVM是不跨平台的。也就是说,不同操作系统之上的JVM是不同的,Windows平台之上的JVM不能用在Linux上面,反之亦然。
JAVA程序运行错误分析
一般来说,一个已经投入运营的大型项目出现问题的可能最多如下几种情况:
1.异常的CPU使用
1)查看CPU使用率,与目标进程的使用情况,再查看每个内核的使用情况。可以辅助定位是单个线程问题或线程池问题。
2)有时,程序在正常一段时间后,突然CPU垂直升高,那么可能与程序内的锁有关(如果锁持有的时间很短,不如试试cas+yield来实现自旋锁)
3)死锁,直接导出调用栈,寻找问题解决。
2.异常的内存
1)内存泄漏,没什么好说的,dump出堆栈查找问题
2)频繁的GC也会导致性能不足,在程序经常出现GC的情况下,就要注意了,调高新生代大小如果仍然不能解决则需要定位大量创建临时对象的代码(可以使用对象池技术来避免内存重复申请的情况)
3.某个工作线程的意外终止
4.异常的IO
1)查看打开文件,IO操作占用,磁盘使用率。可以使用命令 df iostat 等
2)查看是否有程序占用监听,网络使用率,可以使用命令 netstat 等
使用工具分析故障
1.jmap
jmap pid 默认查看JAVA进程中内存使用相关信息
jmap -histo pid 查看内存中活跃的实例数量
jmap -dump:format=b,file=(文件名) pid 完整导出java程序内存。完整分析分三个流程,在程序初始化完毕后执行一次 jmap -dump:format=b,file=a.bin 然后在内存占用开始出现上涨的时候执行一次,最后等达到上限后再执行一次,用JHat或者第三方工具来打开dump文件。
3.jstack或者JCONSOLE
默认 可以查看进程调用栈信息,用来分析IO超时,死锁,或者其他情况。程序出现异常必须要分析的信息,可以辅助问题的定位和排除。
jstat -gc pid gaptime 查看GC相关信息
jstat -compiler pid 查看实时编译信息
4.kill -3
同上,适用于没有安装develop工具的服务器,可以输出调用栈信息和部分GC信息
5.iftop 查看网口
查看网络出入流量与目标服务器之间的流量,可以辅助排查是否由攻击引起的
pstack 虚拟机堆栈
需要安装gdb,一般用于检查c/c++程序,在某些虚拟机级错误的时候。
总结
Java程序的执行过程,必须经过先编译,后解释两个步骤。有关Java程序运行机制及错误分析的介绍就到这里,希望对大家有所帮助。感兴趣的朋友可以参阅本站其他专题,在此希望大家对本站多多支持。