jvm内存泄露虚拟机技术 JVM工作原理

J2EE 码拜 10年前 (2015-04-08) 1274次浏览 0个评论

问题1、什么是JVM?

JVM(java虚拟机)是一种抽象化的计算机,它有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。他是java的核心和基础,他本身也是一种软件,通过字节的方式,将.java文件转换成.class的字节码文件。

将项目中的jar包、java文件 全部转化成JVM自己能识别的对象 ,然后去解析

问题2、程序过程中经常会遇到内存溢出,网上有的资料里面还会提到内存泄漏,但是不知道这个内存溢出和内存泄漏二者有什么区别 为什么会产生?改如何避免?与JVM的关系

答:这跟JVM配置的大小也有关系,当然主要是程序问题。

以发生的方式来分类,内存泄漏可以分为4类: 
1. 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。 
2. 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。
对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。 
3. 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。
比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。 
4. 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,
因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,
不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏

内存溢出和内存泄漏到底有啥区别啊
1.内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。 
2. 内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),
结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。
溢出:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!
下溢:比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。

总结:就是分配的内存不足以放下数据项序列,称为内存溢出. 

这个内存溢出是跟自己设置的有关么,就是说我设置的最大内存是256M,但是系统本身只能提供384M,这个时候就会产生内存溢出么?
答:内存溢出最主要是你的项目运行中超过了你系统分配的内存,所以会内存溢出、

内存泄漏呢?
内存泄露,最常见的应该就是,一直在声明指向或者引用了这个对象分配的内存地址,但是没有真正进行操作,导致无法回收
内存泄露就是说,你本来分配了一块内存给你,但是你却找不到这个内存地址,所以其他程序也没法使用。

比如说我在一个class类里面定义了好几个String类型的对象,并且也进行初始化了,但是程序自始自终都没有调用或者说运行这几个对象,那么这种情况下会产生内存泄漏么?
内存泄露,一般是不断的往容器中存放对象,而容器没有相应的大小限制或清除机制。
内存泄露 说白了,就是在后台没用的对象 占内存的太多,gc没处理过来,然后你程序就挂了.

刚刚查了下资料  一篇博客里说到这个会产生内存泄漏 
Vector<Object> v=new Vector<Object>(10);
for (int i=1;i<100; i++){
       Object o=new Object();
v.add(o);
        o = null;
}
1.也就是说尽管o引用已经被置空,但是Object对象仍然存在其他的引用,是可以被访问到的,所以GC无法将其释放掉。
2.在此循环之后,Object对象对程序已经没有任何作用,那么我们就认为此Java程序发生了内存泄漏

补充:如何处理项目中的异常:
数据库弄一张异常表,对每一个关键代码进行日志记录和异常捕获,或者写一个拦截器,出现宕机的bug,就跳转,然后捕获之后,插入你数据库的异常表
异常表的字段:异常时间、涉及的类、行数等等
这样每天早上上班前,看下异常类就能未卜先知,了解很多异常 (这样能在客户投诉之前快速找到异常)
然后解决~ ,这个就是  反查机制,也可以加入短信提醒功能,重大bug短信提醒

第一种OutOfMemoryError: PermGen space。
第二种OutOfMemoryError:  Java heap space
第三种OutOfMemoryError:unable to create new native thread   网上查的内存溢出总共有三种,但是第一种是我遇到最多的情况,第二种偶尔会遇到,第三种几乎没有遇到过

第一种,在Tomcat部署较多项目的时候很容易碰到,要修改配置文件或者Myeclipse的配置即可解决。 如果是程序报的错误,需要解决程序的问题

第二种,还在整理中

第三种,是因为每台服务器创建最大线程数都是有限制的,需要你限制最大创建线程数,或者纳入线程池管理。

问题3、解释下JVM的原理 和 运行流程

将项目中的jar包、java文件 全部转化成JVM自己能识别的对象,然后去解析。
运行流程:
1、加载。class文件
2、管理并分配内存
3、执行垃圾收集
jvm就是把我们的java文件编译成它可以识别的CLss文件—-知道为什么吗?
你们忽略了jre,java 环境运行就需要jre,jre用到的是jvm技术,jre 和jvm是绑定一体的,jre 和jvm是绑定一体的

jvm有两种线程,你们知道是哪两种吗
线程分为守护线程和非守护线程
每个jvm实例启动的时候都会创建一个守护线程
调用main()方式时启动一个非守护线程
当非守护线程全部结束时jvm生命周期结束

其实说生命周期,大概也就说了 运行流程
1. JVM 启动 
2. 加载类Test 
3. 连接 Test: 验证 Verify, 准备 Prepare, 解析 (Optionally) Resolve   (简而言之就是执行)
4.初始化 initialization 
5. 调用 Test.main
6. 卸载类对象 
7. 程序退出

虚拟机基本原理 就是要弄清楚内存的分配机制
对象的内存 成员变量 局部变量 方法内存 静态的方法 块 变量内存
线程内存
垃圾回收基本步骤
这样编码的时候 能写出节约内存 适合回收算法的程序

以下是 超人气博主  谢宇对JVM的看法:

如果你想问JVM是否有必要学,我的回答是这样的:
      如果你想长期从事Java开发工作,且希望发展技术路线,我觉得这些是必要的,因为一个代码编写者,
应当对自己编写的环境有一定的了解,才有可能去深入发展,那个时候所谓的深入是配合场景去解决一些问题,让自己将理论发挥于实践中。

关于JVM的运行机制,这个得看版本,串行、并行、并发、G1几个机制完全不同,不过目前还保留了基本的分代,这个是从GC角度看。
其次从Java加载类、类的加载与卸载需要从ClassLoader和字节码结束去了解。Java对象的内存结构,
可以让我们更加清晰了解对象在内存是什么样子的,这样写代码会在一些细节思考上用到。这个时候结合一些源代码,例如去看集合类,
或许会有很多新的体会,对于普通开发者的最终目的不是因为学习JVM而学习虚拟机,而是因为我们的代码凌驾于虚拟机上面所以要学习它,
就像你要在一个环境生存得比较好,就要了解环境各种特征和细节,才能有自己的思路去活得更好类似的道理。因此学完了虚拟机,要有一个“然后呢?”,
也就是你有什么样的总结,但这还谈不上“结论”,这些总结就是你认为什么地方可以注意,什么地方应该停下来用什么方式来进行验证,
然后有点点思考再做,而不是代码必须非要怎么去写,这是两者之间的区别。

至于细节的机制,这个回复肯定说不清楚也说不完,很多人写了很多本书也只是谈及到某个方面,如果你期望通过JVM让自己成为一个更好的Java从业者,那么我觉得这些只要去坚持就能越做越好,
或许中途你会遇到很多波折,甚至于会发现还不如不学,那些都是过渡期,走过去就清晰了,依然是坚持。

以上是技术讨论总结。
另:如果想深入了解JVM,可以看看《深入Java虚拟机》这本书

jvm内存泄露虚拟机技术 JVM工作原理
20分
感谢LZ 分享,学习了!
jvm内存泄露虚拟机技术 JVM工作原理
20分
java虚拟机规范也可以

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明jvm内存泄露虚拟机技术 JVM工作原理
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!