zoukankan      html  css  js  c++  java
  • JVM(随手笔记)

    谈谈对jvm的理解?
    java8虚拟机和之前的变化更新?
    什么是OOM,什么是栈溢出StackOverFlowError?怎么分析?
    jvm的常用调优参数有哪些?
    内存快照如何抓取,怎么分析Dump文件?
    谈谈jvm中类加载器?rt-jar

    jvm位置
    在这里插入图片描述
    1、类加载器
    作用:加载Class文件(new Student()具体实例,引用放在栈中,具体的人放在堆中)
    类是抽象的(模板),而对象是具体的。
    (1)虚拟机自带的加载器
    (2)启动类(根)加载器
    (3)扩展类加载器
    (4)应用程序加载器

    双亲委派机制
    1、类加载器收到类加载的请求
    2、将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
    3、启动类加载器检查是否加载当前这个类,能加载就使用当前的加载器,否则,抛出异常,通知子加载器进行加载
    4、重复步骤3
    App—>EXC—>BOOT(最终执行根加载器)
    参考链接(https://www.jianshu.com/p/1e4011617650)
    沙箱安全机制
    参考链接(https://blog.csdn.net/qq_30336433/article/details/83268945)

    native关键字
    凡是带了native关键字,说明java的作用范围达不到了,会去调用底层C语言的库,会进入本地方法栈,调用本地方法接口(JNI)
    JNI作用:扩展java的使用,融合不同的编程语言为java所用。最初:C、C++
    *(java诞生的时候,C、C++横行,想要立足,必须要有调用C、C++
    它在内存专门开辟了一块标记区域:Native Method Stack。登记native方法,它最终执行的时候,加载本地方法库中的方法通过JNI)
    *

    PC寄存器
    程序计数器:Program Counter Register
    每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向一条指令的地址,也即是即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

    方法区(Method Area)
    方法区是被所有线程共享的,所有字段和方法字节码,以及一些特殊方法,如:构造函数、接口代码也在此定义。简单来讲:此区域属于共享区间
    静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中和方法区无关
    static、final、Class、常量池

    **栈:**先进后出
    main压栈,其次是方法压栈,执行完毕弹出。直到所有方法都执行完,main方法才弹出。
    栈溢出:递归调用
    栈:栈内存,主管程序的运行,生命周期和线程同步;线程结束,栈内存也就释放,对于栈来说,不存在垃圾回收问题。
    一旦线程池结束,栈就Over
    栈:8大基本类型+对象引用+实例的方法
    栈运行原理:程序在执行的时候一定是在栈顶

    栈、堆、方法区的交互关系:
    一个对象实例化的过程在内存中
    队列:先进先出

    三种JVM
    1、Sun公司 HotSpot


    Heap ,一个JVM只有一个堆内存,堆内存的大小可以调节。
    类加载器读取类文件后,一般把什么文件放在堆中?类、方法、变量、常量等,保存我们所有引用类的真实对象。
    堆中还要细分三个区域:
    1、新生区(伊甸园区)
    类:诞生和成长的地方,甚至死亡;
    伊甸园区,所有的对象都是在伊甸园区new出来的
    幸存区:
    经过研究,99%的对象都是临时对象
    2、养老区:新生区满了之后经过轻GC之后,活下来的进入到养老区
    3、永久区
    这个区域是常驻内存的,用来存放jdk自身携带的Class对象,存储的是java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存。
    一个启动类加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满,就会出翔OOM
    jdk1.6之前:永久代,常量池在方法区
    jdk1.7: 永久代,但是慢慢退化了(去永久代),常量池在堆中
    jdk1.8之后:无永久代,常量池在元空间(元空间逻辑上存在,物理上不存在)
    在这里插入图片描述
    heap调优
    在这里插入图片描述 在这里插入图片描述
    GC垃圾回收主要在伊甸园区和养老区,假设堆内存满了(会报OOM),堆内存不够!
    JDK8以后,永久存储区改了名字(元空间)

    如果在一个项目中,突然出现OOM故障,那么该如何排错?
    1、能够看到代码第几行出错:内存快照分析工具,MAT、Jprofiler
    2、Debug,一行行分析代码

    MAT、Jprofiler作用:
    分析Dump内存文件,快速定位内存泄漏
    获得堆中的数据
    获得大的对象
    dump文件

    GC垃圾回收

    GC的作用区域
    在这里插入图片描述
    JVM在进行GC时,并不是对这三个区域统一回收,大部分时候回收是在新生代
    新生区
    幸存区
    老年区
    GC两种类:轻GC(普通的GC),重GC(全局GC)

    GC题目:

    JVM的内存模型和分区,详细到每个分区放什么?

    堆里面的分区有哪些?Eden、from、to、老年区,说说他们的特点?

    GC的算法有哪些?标记清除法、标记压缩、复制算法、引用计数法,怎么使用的?
    复制算法
    好处:没有内存的碎片
    坏处:浪费了内存空间,多了一半空间永远是空的,to
    复制算法最佳使用场景:对象存活度较低的时候(新生区)
    在这里插入图片描述
    在这里插入图片描述
    标记清除算法
    在这里插入图片描述
    优点:不需要额外的空间
    缺点:两次扫描严重浪费时间,会产生内存碎片。

    标记压缩算法
    防止内存碎片产生,再次扫描,向一端移动存活的对象,但是多了一个移动成本
    先标记清除几次在这里插入图片描述
    再压缩
    在这里插入图片描述
    总结
    内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)
    内部整齐度:复制算法=标记压缩算法>标记清除算法
    内存利用率:标记压缩算法=标记清除算法>复制算法

    难道没有最优的算法吗?
    答案:没有,没有最好的算法,只有最合适的算法—>GC:分代收集算法

    年轻代:
    存活率低,复制算法
    老年代:
    区域大:存活率
    标记清除(内存碎片不是太多)+标记压缩混合实现

    轻GC和重GC分别在什么时候发生?
    Young GC的触发时机:Young GC其实一般就是在新生代的Eden区域满了之后就会触发,采用复制算法来回收新生代的垃圾。
    Full GC的触发时机如下:
    (1)发生Young GC之前进行检查,如果“老年代可用的连续内存空间” < “新生代历次Young GC后升入老年代的对象总和的平均大小”,说明本次Young GC后可能升入老年代的对象大小,可能超过了老年代当前可用内存空间
    此时必须先触发一次Old GC给老年代腾出更多的空间,然后再执行Young GC。
    (2)执行Young GC之后有一批对象需要放入老年代,此时老年代就是没有足够的内存空间存放这些对象了,此时必须立即触发一次Old GC。
    (3)老年代内存使用率超过了92%,也要直接触发Old GC,当然这个比例是可以通过参数调整的。
    概括成一句话,就是老年代空间也不够了,没法放入更多对象了,这个时候务必执行Old GC对老年代进行垃圾回收。

  • 相关阅读:
    软件工程个人作业02
    第三周学习进度条
    《构建之法》阅读笔记01
    第二周学习进度条
    软件工程个人作业01
    大道至简第三章读后感
    动手动脑课后实践
    JAVA数字想加并输出
    大道至简第二章读后感
    大道至简读后感
  • 原文地址:https://www.cnblogs.com/kiki-study/p/13656120.html
Copyright © 2011-2022 走看看