1.Java内存泄露和内存溢出对比
1.1 Java内存泄露
内存泄露是指一个不再被程序使用的对象或变量还在内存中占用空间。
1.1.1判断内存空间是否符合垃圾回收的标准
在Java语言中,判断一个内存空间是否符合垃圾回收的标准有两个:
给对象赋予了空值null,以后再也没有不会被使用;给对象赋予了新值,重新分配了内存空间。
1.1.2内存泄漏的情况
一般来说,内存泄露主要有两种情况:
在堆中申请的空间没有被释放;对象已不再使用但是还仍然在内存中保留着。
垃圾回收机制的引入可以有效地解决第一种情况,但是对第二种情况却没有办法解决,因此Java语言中内存泄露主要指的是第二种情况。
1.1.3造成内存泄露的对象的特点
在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,
这些对象是可达的,即在有向图中,存在通路可以与其相连;这些对象是无用的,即程序以后不会再使用这些对象。
如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。
1.1.4 引起内存泄露的原因
在Java语言中,容易引起内存泄露的原因有很多,主要可以分为以下几种。
静态集合类。例如HashMap和Vector,如果这些容器是静态的,那么它们的声明周期与程序一样,在程序结束之前这些容器所占的空间将得不到释放,从而造成内存泄露;各种连接。比如Connection、Statement、ResultSet等如果使用之后不显示地关闭,会造成大量的对象无法回收,造成内存泄露;监听器。在java中,往往一个程序使用多个监听器,但是在释放对象的时候却没有删除相应的监听器对象就会导致内存泄露;变量不合理的作用域。如果一个变量定义的作用范围大于其使用范围 ,就有可能造成内存泄露,另一个方面如果没有及时地把一个对象设置为null,也有可能导致内存泄露;单例模式可能会造成内存泄露。如果以静态的方式存储单例对象的话,那么它在JVM的整个生命周期中都存在,就会导致内存泄露。
1.2内存溢出
内存溢出是指程序要求的内存,超出了系统所能分配的范围,从而发生溢出。
2.JVM命令行工具
2.1 jps
虚拟机进程状况工具;
只运行jps输出的是当前运行的java进程(Java程序的进程ID,main函数);
运行jps –q只输出进程ID,而不输出类的名称;
jps –m输出传递给Java进程(主函数)的短名称;
jps –l输出主函数的完整路径;
jps –v输出传递给JVM的参数。
2.2 jstat
虚拟机统计信息监视工具;可以用于观察Java应用程序运行时信息的工具。
jstat可以实时显示本地或远程JVM进程中类装载、内存、垃圾收集、JIT编译等数据(如果要显示远程JVM信息,需要远程主机开启RMI支持)。
如果在服务启动时没有指定启动参数-verbose:gc,则可以用jstat实时查看gc情况。
在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,jstat是运行期定位虚拟性能问题的首选工具。
如jstat –gc 2764 250 20表示查询进程2764垃圾收集状况,每250ms查询一次,一共查询20次。后面两个参数省略时表示只查询一次。
命令格式为jstat option vmid interval count.
其中option主要分为3类:类装载、垃圾收集、运行期编译。
2.3 jinfo
Java配置信息工具;用于查询当前运行时的JVM属性和参数的值。
jinfo可以使用如下选项:
-flag:显示未被显示指定的参数的系统默认值 -flag [+|-]name或-flag name=value: 修改部分参数 -sysprops:打印虚拟机进程的System.getProperties()
命令格式:jinfo [option] pid
2.4 jmap
java内存映像工具;
用于显示当前Java堆和永久代的详细信息(如当前使用的收集器,当前的空间使用率等).
jmap –heap:显示java堆的相信信息,如使用哪种收集器、参数配置、分代状态等。jmap-dump:生成java堆转储快照。
2.5jhat
虚拟机堆转储快照分析工具;
用于分析使用jmap生成的dump文件,是JDK自带的工具,使用方法为: jhat -J -Xmx512m [file]
2.6 jstack
Java堆栈跟踪工具;
用于生成当前JVM的所有线程快照,线程快照是虚拟机每一条线程正在执行的方法,目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情或者是在等待什么资源。
-F:当正常输出的请求不被响应时,强制输出线程堆栈-l:除堆栈外,显示关于锁的附加信息-m:如果调用到本地方法的话,可以显示C/C++的堆栈
命令格式:jstack [option] vmid
例如jstack –l 3500会显示3500编号的进程的带有锁信息的堆栈信息。
2.7HSDIS
JIT生成代码反汇编。
2.8现在JVM中有一个线程挂起了,如何用工具查出原因?
线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情或者是在等待什么资源。用于生成当前JVM的所有线程快照,线程快照是虚拟机内每一条线程正在执行的方法堆栈集合,目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的原因。
3.JDK可视化工具
3.1JConsole工具
是JDK自带的图形化性能监控工具。通过JConsole工具,可以查看Java应用程序的运行概况,监控堆信息、永久区使用情况、类加载情况。
在JConsole中可以查看堆的详细信息,包括堆的大小、使用率、eden区大小、survivor区大小、永久区大小。
JConsole可以方便地查看系统内的线程信息,并且可以快速定位死锁问题。
JConsole的类页面可以显示系统已经装载的类数量。
JConsole的VM摘要显示了当前Java应用程序的基本信息,如虚拟机类型、虚拟机版本、系统线程信息、操作系统内存信息、堆信息、垃圾回收器信息以及路径信息等。
3.2VisualVM
3.3用什么工具调试程序?
JConsole工具
4.Java Class文件
4.1格式
Class文件是一组以8位字节为基础单位的二进制流。
各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存。
当遇到需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。
4.2内容
每个Class文件的头4个字节称为魔数,它的唯一作用就是确定这个文件是否为一个能被虚拟机接收的Class文件。
紧着着魔数之后的4个字节存储的Class文件的版本号,后面是常量池入口。
后面是代表访问标志的两个字节,这个表示用于识别一些类或者接口层次的访问信息。
再往后就是类索引、父索引与接口索引集合。
字段表集合用户描述接口或者类中声明的变量。
方法表集合、属性表集合。
魔数--->版本号--->常量池入口--->访问标志--->类索引、父索引与接口索引集合