• JVM学习笔记(一):JVM初探


    1 来源

    • 来源:《Java虚拟机 JVM故障诊断与性能优化》——葛一鸣
    • 章节:第一章

    本文是第一章的一些笔记整理。

    2 Java里程碑

    2.1 Java起源

    1990年Sun公司决定开发一门新的程序语言——Oak,已经具备安全性、网络通信、面向对象、垃圾回收、多线程等特性,由于Oak已被注册,于是改名为Java

    2.2 JDK 1.0

    1995年Sun发布了Java以及HotJava产品,1996年正式发布JDK 1.0,包括两部分:

    • 运行环境:JRE,包括核心API,用户界面API,发布技术、JVM
    • 开发环境:JDK,包括编译器javac

    1997年发布JDK1.1

    2.3 JDK 1.2-1.7

    1998年发布JDK 1.2JDK1.2兼容智能卡和小型消费类设备,还兼容大型服务器系统。同时Sun发布JSP/Servlet+EJB规范,将Java分成了J2EEJ2SEJ2ME

    2000年发布JDK 1.3,默认虚拟机改为Hotspot

    2002年发布JDK1.4Classic虚拟机退出舞台。

    2004年发布JDK 1.5,支持泛型、注解、自动装箱拆箱、枚举、可变长参数等。

    2006年发布JDK 1.6Java开源并建立了OpenJDK

    2011年发布JDK 1.7,启用了G1垃圾回收器,支持64位系统的压缩指针以及NIO 2.0

    2.4 JDK 1.8+

    2014年发布JDK 1.8JDK 1.8是一个LTS版,到目前还支持,引入了全新的Lambda

    2017年发布JDK 9

    2018年发布JDK 10

    2018年发布JDK 11,又一个LTS版,引入了字符串增强、Epsilon垃圾收集器、ZGC等。

    3 JVM种类简介

    Java发展初期,使用的是Classic虚拟机,之后在Solaris短暂地使用过Exact VM虚拟机,到现在被大规模部署和使用的是Hotspot虚拟机。

    另外,在IBM内部使用着一款叫J9的虚拟机,Apache也曾经推出过Apache Harmony,基于JDK 5以及JDK 6,于2011年停止开发。

    4 JVM简单编译调试实战

    下面以OpenJDK15为例,对OpenJDK 15 JVM进行源码编译。

    (注:由于笔者系统为Manjaro,这是一个滚更的系统,很多工具链都会更新到最新的状态,比如GCC 10.2,书籍中的例子是利用JDK8去编译JDK10,实际测试发现会报错,configure成功了但是make失败,然后就切换到最新的JDK,就编译成功了。对于不是滚更的系统,可以使用JDK10去编译JDK11等,而非采用目前最新的JDK15

    4.1 获取源码+BootJDK

    这里下载:

    在这里插入图片描述

    可以使用如下命令检测下载文件的完整性:

    echo "bb67cadee687d7b486583d03c9850342afea4593be4f436044d785fba9508fb7 openjdk-15+36_linux-x64_bin.tar.gz" | sha256sum --check
    echo "d07bf62b4b20fa6bcd4c8fcd635e5df20b7c090af291675b2bd99f8cea8760a0 openjdk-15+36_src.zip" | sha256sum --check
    

    另外需要准备一个BootJDK,根据BootJDK的规则:

    在这里插入图片描述

    建议使用当前版本号/版本号-1/版本号-2JDK,这里选用的是OpenJDK 15

    4.2 安装依赖库

    笔者系统Manajro,需要安装一些基础依赖:

    paru -S base-devel
    # 或
    pacman -S base-devel
    # 或
    yay -S base-devel
    

    如果依赖库安装不完整在配置阶段以及编译阶段会给出相应提示,再进行对应依赖安装即可。

    4.3 编译

    解压源码进入目录:

    unzip openjdk-15+36_src.zip
    tar -zxvf openjdk-15+36_linux-x64_bin.tar.gz
    cd openjdk
    

    配置:

    bash configure --with-debug-level=slowdebug --with-jvm-variants=server --with-target-bits=64 --with-memory-size=8000 --disable-warnings-as-errors --with-native-debug-symbols=internal --with-boot-jdk=../jdk-15
    

    参数说明:

    • --with-debug-level=slowdebug:编译DEBUG版本的JDK,选项可以是slowdebug/fastdebug/release/optimized
    • --with-jvm-variants=server:构建server变体的Hotspot,选项可以是server/client/minimal/core/zero/custom
    • --with-target-bits=64:编译64位的JDK,编译32位可以使用--with-target-bits=32
    • --with-memory-size=8000:编译的计算机至少需要8G内存,这个可以根据个人需要调整
    • --disable-warnings-as-errors:忽略警告的信息,注意该参数很重要,不加的话会显示配置成功但make失败
    • --with-native-debug-symbols=internal:生成symbol文件,便于后续调试,选项可以是internal/none/external/zipped
    • --with-boot-jdkBootJDK的目录

    结果:

    在这里插入图片描述

    配置后后进行编译:

    make images
    

    这个阶段需要一点时间,而且会把CPU拉满,好了之后会提示Finished building

    在这里插入图片描述

    笔者环境下编译出来的JDK占了3G:

    在这里插入图片描述

    进入对应目录可以查看版本:

    在这里插入图片描述

    4.4 调试

    调试需要gdb,先安装好gdb

    paru -S gdb
    

    进入bin目录(build/linux-x86_64-server-slowdebug/jdk/bin),输入:

    gdb -args ./java -version
    

    在这里插入图片描述

    main函数打断点:

    (gdb) b main
    

    再执行run,可以看到会停在java.base/share/native/launcher/main.c第98行:

    (gdb) run
    

    在这里插入图片描述

    再次输入n可进行单步调试:

    (gdb) n
    

    在这里插入图片描述

    这样就算完成了基础的调试操作,为进一步学习JVM准备好基本的环境。

    4.5 JVM下载

    如果编译失败的话,笔者这里提供了自己编译出来的JVM

  • 相关阅读:
    第三次作业
    最后一次作业
    第14.15周作业
    第七周作业
    第六周作业
    第四周作业
    第三周作业
    第二周作业
    第一周作业
    第0次作业
  • 原文地址:https://www.cnblogs.com/6b7b5fc3/p/14468390.html
Copyright © 2020-2023  润新知