Fork me on GitHub

Java底层知识

注意:所有文章除特别说明外,转载请注明出处.

Java底层知识

[TOC]

平台无关性

Java源码首先被编译成字节码,再由不同平台的JVM进行解析,Java语言在不同的平台上运行时不需要进行重新编译,Java虚拟机在执行字节码的时候,将字节码转换成具体平台上的机器指令。

提示:JVM不将源码直接解析成机器码去执行的原因是因为,如果直接解析成机器码执行,那么每次还需要重新检测语法、句法、语义,这样一来整体的性能就会受到影响。

JVM如何加载.class文件

JVM的组成

    1.Class Loader 依据特定格式,加载.class文件到内存

    2.Execution Engine 对命令进行解析

    3.Runtime Data Area JVM内存空间结构模型

    4.Native Interface (本地接口) 作用是融合不同的开发语言的原生库为Java所用

Java反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。

ClassLoader

类从编译到执行的过程

    1.编译器将xxx.java源文件编译成xxx.class字节码文件

    2.ClassLoader将字节码转换成JVM中的Class<xxx>对象

    3.JVM利用Class<xxx>对象实例化为xxx对象

ClassLoader在Java中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流,它是Java的核心组件,所有的Class都有ClassLoader进行加载,ClassLoader负责通过Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接,初始化等操作。

ClassLoader的种类:

    1.BootStrapClassLoader 加载核心库java.*

    2.ExtClassLoader 加载扩展库javax.*

    3.AppClassLoader 加载程序所在目录

    4.自定义ClassLoader

        关键函数

            findClass

            defineClass

ClassLoader双亲委派机制

提示:使用双亲委派机制去加载类的原因:1.避免多份同样字节码的加载。2.

类的加载方式

1.隐式加载 new

2.显示加载 loadClass forName等

    类的装载过程

        1.加载 通过ClassLoader加载class文件字节码,生成Class对象

        2.链接

            1.校验 检查加载的class的正确性和安全性

            2.准备 为类变量分配存储空间并设置类变量初始值

            3.解析 JVM将常量池内的符号引用转换为直接引用

        3.初始化 执行类变量赋值和静态代码块

loadClass | forName 的区别

1.Class.forName得到的class是已经初始化完成的

2.Classloader.loadClass得到的class是还没有链接的

Java 内存模型

程序计数器

1.当前线程所执行的字节码行号指示器(逻辑)

2.改变计数器的值来选取下一条需要执行的字节码指令

3.和线程是一对一的关系,即线程私有

4.对Java方法计数,如果是Native方法则计数器值为undefined

5.不会发生内存泄漏

Java虚拟机栈

1.Java方法执行的内存模型

2.包含多个栈帧


    局部变量表:包含方法执行过程中的所有变量

    操作数栈:入栈、出栈、复制、变换、产生消费变量

JVM性能调优

1.JVM三大性能调优参数

    -Xms 

        规定每个线程虚拟机栈的大小 (堆栈)

    -Xmx

        堆的初始值

    -Xss

        堆能达到的最大值
Java内存中堆和栈的区别(内存分配策略)
1.静态存储:编译时确定每个数据目标在运行时的存储空间需求

2.栈式存储:数据区需求在编译时未知,运行时模块入口前确定

3.堆式存储:编译时或运行时模块入口都无法确定,动态分配

堆和栈的联系:

    1.引用对象、数组时,栈里定义变量保存堆中目标的首地址

        在栈内存中存的地址(指向对应堆内存空间),在堆内存中存的是new出来的对象实例和数组

    2.管理方式:栈自动释放,堆需要GC

    3.空间大小:栈空间大小比堆小

    4.碎片相关:栈产生的碎片远小于堆

    5.分配方式:栈支持静态和动态分配,而堆仅支持动态分配

    6.效率:栈的效率要比堆高

Java垃圾回收机制

可达性分析算法

1.可以作为GC Root的对象

    1.虚拟机栈中引用的对象(栈帧中的本地变量表)

    2.方法区中的常量引用的对象

    3.方法区中的类静态属性引用的对象

    4.本地方法栈中JNI(Native方法)的引用对象

    5.活跃线程的引用对象

2.垃圾回收算法(不再做笔记)

    1.标记-清除

    2.复制

        1.解决碎片化问题

        2.顺序分配内存,简单高效

        3.适用于对象存活率低的场景

    3.标记-整理

    4.分代收集

        1.GC分类:

            1.Minor GC

            2.Full GC

        2.年轻代:尽可能快速地收集掉那些生命周期短的对象

            1.Eden区

            2.两个Survivor区

        3.对象晋升到老年代

            1.经历一定Minor次数依然存活的对象

            2.Survivor区或Eden区中存放不下的对象

            3.新生成的大对象(-XX:+PretenuerSizeThreshold命令控制对象大小)

        4.常用性能调优参数

            1.-XX:SurvivorRatio:Eden和Survivor的比值,默认8:1

            2.-XX:NewRatio:老年代和年轻代内存大小的比值

            3.-XX:MaxTenuringThreshold:对象从年轻代晋升到老年代经过GC次数的最大阈值

        4.老年代:存放生命周期较长的对象

        5.触发Full GC的条件

            1.老年代空间不足

            2.永久代空间不足

            3.Minor GC晋升到老年代的平均大小大于老年代的剩余空间

            4.调用System.gc()

        6.stop-the-world

            1.JVM由于要执行GC而停止了应用程序的执行

            2.任何一种GC算法中都会发生

            3.多数GC优化都是通过减少stop-the-world发生的时间来提高性能优化

        7.safepoint

            1.分析过程中对象引用关系不会发生变化的点

            2.产生safepoint的地方:方法调用、循环跳转、异常跳转等

            3.安全点的数量要适中

常见垃圾收集器

1.JVM的运行模式

    1.Server 启动较慢,启动之后程序运行较快

    2.Client 相反地

    提示:可以利用 java -version 命令来查看JVM的运行模式

2.年轻代常见的垃圾收集器

    1.Serial收集器(命令 -XX:UseSerialGC 命令可以让JVM在年轻代处理垃圾回收,是复制算法)

        1.单线程收集,进行垃圾收集时,必须暂停所有工作线程

        2.简单高效,Client模式下默认的年轻代收集器

    2.ParNew收集器(命令 -XX:UseParNewGC 命令可以让JVM在年轻代处理垃圾回收,复制算法)

        1.多线程回收,其余行为特点和Serial收集器一样

        2.单核执行效率不如Serial,在多核执行才有优势

    3.Parallel Scavenge收集器(命令 -XX:+UseParallelGC 命令...,复制算法)

        1.吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)

        2.比起关注用户线程停顿时间,更关注系统的吞吐量

        3.在多核下执行才有优势,Server模式下默认的年轻代收集器

3.老年代常用的垃圾收集器

    1.Serial Old收集器(命令 -XX:+UseSerialOldGC 命令...,标记-整理算法)

        1.单线程收集,进行垃圾收集时,必须暂停所有工作线程

        2.简单高效,Client模式下默认的老年代收集器

    2.Parallel Old收集器(命令 -XX:+UseParallelOldGC 命令...,标记-整理)

        1.多线程,吞吐量优先

    3.CMS收集器(命令 -XX:+UseConcMarkSweepGC 命令...,标记-清除)

        垃圾收集过程:

            1.初始标记:stop-the-world

            2.并发标记:并发追溯标记,程序不会停顿

            3.并发预清理:查找执行并发标记阶段从年轻代晋升到老年代的对象

            4.重新标记:暂停虚拟机,扫描CMS堆中的剩余对象

            5.并发清理:清理垃圾对象,程序不会停顿

            6.并发重置:重置CMS收集器的数据结构


4.年轻代和老年代通用

    1.G1垃圾收集器(-XX:+UseG1GC 复制+标记-整理算法)

        Garbage First 收集器的特点:

            1.并发和并行

            2.分代收集

            3.空间整合

            4.可预测的停顿

            5.将整个Java堆内存划分为多个大小相等的Region

            6.年轻代和老年代不再物理隔离

            7.

GC面试题

1.Object的finalize()方法的作用是否与C++的析构函数作用相同

提示
1.javap -c 对编译之后的.class文件作反汇编操作

2.javac 编译生成字节码 .class 文件

3.

本文标题:Java底层知识

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:12:11

原始链接:http://bangjinhu.github.io/undefined/Java底层知识/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.