揭秘Java中的JVM虚拟机

学过java的就应该知道 JVM虚拟机是Java 这门编程语言的一大特点,所以,了解Java的虚拟机,能更好地解决一些内存问题,和一些代码的优化问题。

 一、虚拟机内存中的堆和栈

在我们的Java虚拟机中的内存堆栈模型图,如下:

对程序中的对象或线程所存在的区域,简单描述如下:

方法区中:类class信息、static静态字段、运行时常量等

堆中: 对象(数组也是对象)

栈中:线程执行代码的地方,每个方法调用一个栈帧,通过局部变量、this关键字引用)它的特点是:先进后出(首先执行的,最后退出,例如,某程序首先从main()方法开始执行,程序将结束的时候,也是要回到main()方法中)
常见的几种内存溢出异常:

OutOfMemoryError:Metaspace:方法区内存溢出
OutOfMemoryError:Heap space 堆内存溢出错误
StackOverflowError栈内存溢出

二、垃圾回收机制

 

GC发现垃圾的算法

  1. 引用计数法,特点:在虚拟机中有一个变量专门用来计算某个对象被使用的次数,一个对象被赋值给一个变量时,引用计数+1; 持有引用的变量退出作用域时,引用计数-1,刚开始创建的时候,计数器默认为1 ,如果变成0,则成为垃圾,将会被垃圾回收器回收,它的局限性就是无法发现两个相互引用的垃圾对象。

  2. 根搜索算法,特点:根据某个对象是否有根来判断是否为垃圾(根:如下图中的对象实例1被其他来自方法区或者某栈帧引用了这个对象,那么,这个对象就是有根的,而对象实例3虽然被对象实例5引用,但是,对象实例5缺没有被其他方法区或者栈引用,所以对象实例3和对象实例5是没有根的,也就是垃圾对象)

Java虚拟机中常见的GC回收垃圾(清理垃圾)算法:

  1. 标记清除算法 

    特点: 清除效率高,性能高、简单,但是会造成内存碎片太多,使内存使用效率不高

  2. 分段复制算法 

    特点:将内存空间,分成两半用一半,留一半,避免内存碎片,效率高,但是执行动静太大,容易造成服务器卡顿

  3. 标记-整理算法

    特点:整理成,连续的标记清除法的改良版

  4. 分代收集算法

    新生代:伊甸园:刚创建的对象,通常寿命较短,(短命对象) 在这个区域中将会被回收掉大量的垃圾对象
                   生存区(From, To 区),经过伊甸园的筛选,存活下来的对象,就会存到这个区域中,这个区域中的对象被回收的几率较大
    老年代:通过层层回收,从新生代存活下来的对象,就进入了老年代,这个区域中的对象,被回收几率减小,
    永久代:经过很多次的回收还存活下来的对象,说明,这些对象可能最近这一段时间不会是垃圾,这个区域的对象,基本上是不会回收的。

内存泄漏:该回收的内存/对象,无法回收,导致内存一直占用

内存溢出:内存不够了,导致,程序崩溃,程序代码写的不够规范,不够优化,所以导致,产生很多的"垃圾", 无法回收这个时候,(内存泄漏),达到一定程度,,就会导致内存溢出

内存泄漏和内存溢出的关系为:内存溢出,很大的可能是由于内存泄漏而导致的。

垃圾回收清理算法

        垃圾回收级别:

  第一级:Minor GC (小范围回收),对小范围内的垃圾进行回收和整理, 主要是在,新生代

  第二级:Major GC (大范围回收) 对大范围内的所有垃圾进行回收和整理, 新生代和老年代 ,内存占用大概超过60%甚至70% 的时候启用第二等级的回收策略(加大力度回收垃圾)

  第三级:Full  GC (所有范围回收) 对小范围的垃圾回收和整理,所有的区域,(新生代,老年代,永久代)


三、高效代码技巧

  • 尽量不要在循环中:使用try ---catch,new 对象等操作
  • 把频繁使用的短命对象(在伊甸园中的对象,称为短命对象),缓存起来
  • 尽可能使用栈内变量(方法内局部变量)
  • 不要用异常来控制代码流程
  • 用线程池,连接池,不要自己创建
  • 学会读java核心API源代码

最后,推荐两本书,希望对你学习java有所帮助:

  1. java基础:《java编程思想(第四版)》

  2. Java进阶:《Effecitve java》

 

     

         
 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现一个JVM虚拟机,需要深入了解JVM的内部实现原理和Java语言规范。一般来说,JVM虚拟机由以下几个模块组成: 1. 类加载器:负责从文件系统、网络或其他来源加载Java类文件,并将其转换为JVM能够理解的格式。 2. 运行时数据区:Java程序运行时需要的内存空间,包括Java堆、方法区、虚拟机栈、本地方法栈、程序计数器等。 3. 执行引擎:负责执行Java字节码,将它们转换为机器码并执行。 4. 垃圾收集器:负责回收未使用的对象,释放内存空间。 5. 本地方法接口:允许Java代码调用本地方法(C/C++代码)。 下面是一个简单的Java虚拟机实现的示例: ```java public class JVM { private ClassLoader classLoader; private RuntimeDataArea runtimeDataArea; private ExecutionEngine executionEngine; private GarbageCollector garbageCollector; private NativeMethodInterface nativeMethodInterface; public JVM() { classLoader = new ClassLoader(); runtimeDataArea = new RuntimeDataArea(); executionEngine = new ExecutionEngine(); garbageCollector = new GarbageCollector(); nativeMethodInterface = new NativeMethodInterface(); } public void run(String className) { // 加载类 Class clazz = classLoader.loadClass(className); // 初始化类 clazz.initialize(runtimeDataArea); // 执行方法 Method mainMethod = clazz.getMethod("main", String[].class); executionEngine.execute(mainMethod); } } ``` 这个简单的JVM实现只包含了类加载器、运行时数据区和执行引擎三个部分。在实现时,还需要考虑Java语言规范的各种细节,如异常处理、线程安全等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值