mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-29 22:56:42 +08:00
1239 lines
31 KiB
HTML
1239 lines
31 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
||
<head>
|
||
|
||
<head>
|
||
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
|
||
<link rel="icon" href="/static/favicon.png">
|
||
|
||
<title>02 环境准备:千里之行,始于足下.md.html</title>
|
||
|
||
<!-- Spectre.css framework -->
|
||
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
|
||
<!-- theme css & js -->
|
||
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
|
||
</head>
|
||
|
||
|
||
|
||
<body>
|
||
|
||
|
||
|
||
<div class="book-container">
|
||
|
||
<div class="book-sidebar">
|
||
|
||
<div class="book-brand">
|
||
|
||
<a href="/">
|
||
|
||
<img src="/static/favicon.png">
|
||
|
||
<span>技术文章摘抄</span>
|
||
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<div class="book-menu uncollapsible">
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="../">上一级</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/01 阅读此专栏的正确姿势.md.html">01 阅读此专栏的正确姿势.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
<a class="current-tab" href="/专栏/JVM 核心技术 32 讲(完)/02 环境准备:千里之行,始于足下.md.html">02 环境准备:千里之行,始于足下.md.html</a>
|
||
|
||
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/03 常用性能指标:没有量化,就没有改进.md.html">03 常用性能指标:没有量化,就没有改进.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/04 JVM 基础知识:不积跬步,无以至千里.md.html">04 JVM 基础知识:不积跬步,无以至千里.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/05 Java 字节码技术:不积细流,无以成江河.md.html">05 Java 字节码技术:不积细流,无以成江河.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/06 Java 类加载器:山不辞土,故能成其高.md.html">06 Java 类加载器:山不辞土,故能成其高.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/07 Java 内存模型:海不辞水,故能成其深.md.html">07 Java 内存模型:海不辞水,故能成其深.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/08 JVM 启动参数详解:博观而约取、厚积而薄发.md.html">08 JVM 启动参数详解:博观而约取、厚积而薄发.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/09 JDK 内置命令行工具:工欲善其事,必先利其器.md.html">09 JDK 内置命令行工具:工欲善其事,必先利其器.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/10 JDK 内置图形界面工具:海阔凭鱼跃,天高任鸟飞.md.html">10 JDK 内置图形界面工具:海阔凭鱼跃,天高任鸟飞.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/11 JDWP 简介:十步杀一人,千里不留行.md.html">11 JDWP 简介:十步杀一人,千里不留行.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/12 JMX 与相关工具:山高月小,水落石出.md.html">12 JMX 与相关工具:山高月小,水落石出.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/13 常见的 GC 算法(GC 的背景与原理).md.html">13 常见的 GC 算法(GC 的背景与原理).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/14 常见的 GC 算法(ParallelCMSG1).md.html">14 常见的 GC 算法(ParallelCMSG1).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/15 Java11 ZGC 和 Java12 Shenandoah 介绍:苟日新、日日新、又日新.md.html">15 Java11 ZGC 和 Java12 Shenandoah 介绍:苟日新、日日新、又日新.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/16 Oracle GraalVM 介绍:会当凌绝顶、一览众山小.md.html">16 Oracle GraalVM 介绍:会当凌绝顶、一览众山小.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/17 GC 日志解读与分析(基础配置).md.html">17 GC 日志解读与分析(基础配置).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/18 GC 日志解读与分析(实例分析上篇).md.html">18 GC 日志解读与分析(实例分析上篇).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/19 GC 日志解读与分析(实例分析中篇).md.html">19 GC 日志解读与分析(实例分析中篇).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/20 GC 日志解读与分析(实例分析下篇).md.html">20 GC 日志解读与分析(实例分析下篇).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/21 GC 日志解读与分析(番外篇可视化工具).md.html">21 GC 日志解读与分析(番外篇可视化工具).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/22 JVM 的线程堆栈等数据分析:操千曲而后晓声、观千剑而后识器.md.html">22 JVM 的线程堆栈等数据分析:操千曲而后晓声、观千剑而后识器.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/23 内存分析与相关工具上篇(内存布局与分析工具).md.html">23 内存分析与相关工具上篇(内存布局与分析工具).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/24 内存分析与相关工具下篇(常见问题分析).md.html">24 内存分析与相关工具下篇(常见问题分析).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/25 FastThread 相关的工具介绍:欲穷千里目,更上一层楼.md.html">25 FastThread 相关的工具介绍:欲穷千里目,更上一层楼.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/26 面临复杂问题时的几个高级工具:它山之石,可以攻玉.md.html">26 面临复杂问题时的几个高级工具:它山之石,可以攻玉.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/27 JVM 问题排查分析上篇(调优经验).md.html">27 JVM 问题排查分析上篇(调优经验).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/28 JVM 问题排查分析下篇(案例实战).md.html">28 JVM 问题排查分析下篇(案例实战).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/29 GC 疑难情况问题排查与分析(上篇).md.html">29 GC 疑难情况问题排查与分析(上篇).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/30 GC 疑难情况问题排查与分析(下篇).md.html">30 GC 疑难情况问题排查与分析(下篇).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/31 JVM 相关的常见面试问题汇总:运筹策帷帐之中,决胜于千里之外.md.html">31 JVM 相关的常见面试问题汇总:运筹策帷帐之中,决胜于千里之外.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/32 应对容器时代面临的挑战:长风破浪会有时、直挂云帆济沧海.md.html">32 应对容器时代面临的挑战:长风破浪会有时、直挂云帆济沧海.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
|
||
<div class="sidebar-toggle-inner"></div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
|
||
function add_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.add('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function remove_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function sidebar_toggle() {
|
||
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let content = document.querySelector('.off-canvas-content')
|
||
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
|
||
sidebar_toggle.classList.remove('extend')
|
||
|
||
sidebar.classList.remove('hide')
|
||
|
||
content.classList.remove('extend')
|
||
|
||
} else { // hide
|
||
|
||
sidebar_toggle.classList.add('extend')
|
||
|
||
sidebar.classList.add('hide')
|
||
|
||
content.classList.add('extend')
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
function open_sidebar() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.add('show')
|
||
|
||
overlay.classList.add('show')
|
||
|
||
}
|
||
|
||
function hide_canvas() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.remove('show')
|
||
|
||
overlay.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
<div class="off-canvas-content">
|
||
|
||
<div class="columns">
|
||
|
||
<div class="column col-12 col-lg-12">
|
||
|
||
<div class="book-navbar">
|
||
|
||
<!-- For Responsive Layout -->
|
||
|
||
<header class="navbar">
|
||
|
||
<section class="navbar-section">
|
||
|
||
<a onclick="open_sidebar()">
|
||
|
||
<i class="icon icon-menu"></i>
|
||
|
||
</a>
|
||
|
||
</section>
|
||
|
||
</header>
|
||
|
||
</div>
|
||
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
|
||
overflow-x: auto;
|
||
|
||
overflow-y: hidden;">
|
||
|
||
<div class="book-post">
|
||
|
||
<p id="tip" align="center"></p>
|
||
|
||
<div><h1>02 环境准备:千里之行,始于足下</h1>
|
||
|
||
<p>Java 语言编写代码非常简单,也很容易入门,非常适合开发各种企业级应用和业务系统。一个众所周知的事实是: 用起来越简单的系统, 其背后的原理和实现就越复杂。道理很容易理解, 系统的内部实现考虑了各种极端的情况,对用户屏蔽了各种复杂性。作为支撑庞大的 Java 生态系统的基石, JVM 内部实现是非常复杂的。据统计,OpenJDK 的实现代码已经超过 1000 万行。</p>
|
||
|
||
<p>JVM 难不难? 自然是 “难者不会,会者不难”。万丈高楼平地起, 没有掌握一定的基础知识, 学过的各种原理,了解相关技巧,也就会出现转眼即忘,书到用时方恨少的情况。</p>
|
||
|
||
<p>掌握好基础知识,学而时习之,经常使用各种工具并熟练运用,自然就能深入掌握一门技能。理论结合实践,掌握 JVM 相关知识,熟练各种工具的使用,是 Java 工程师职业进阶中不可或缺的。学就要学会理论,掌握实现原理。 理解了 Java 标准平台的 JVM,举一反三,稍微变通一下,碰到 Android 的 ART, Go 的虚拟机,以及各种语言的垃圾收集实现,都会很容易理解。</p>
|
||
|
||
<h3>1.1 JDK、JRE、JVM 的关系</h3>
|
||
|
||
<p><strong>JDK</strong></p>
|
||
|
||
<p>JDK(Java Development Kit) 是用于开发 Java 应用程序的软件开发工具集合,包括了 Java 运行时的环境(JRE)、解释器(Java)、编译器(javac)、Java 归档(jar)、文档生成器(Javadoc)等工具。简单的说我们要开发 Java 程序,就需要安装某个版本的 JDK 工具包。</p>
|
||
|
||
<p><strong>JRE</strong></p>
|
||
|
||
<p>JRE(Java Runtime Enviroment )提供 Java 应用程序执行时所需的环境,由 Java 虚拟机(JVM)、核心类、支持文件等组成。简单的说,我们要是想在某个机器上运行 Java 程序,可以安装 JDK,也可以只安装 JRE,后者体积比较小。</p>
|
||
|
||
<p><strong>JVM</strong></p>
|
||
|
||
<p>Java Virtual Machine(Java 虚拟机)有三层含义,分别是:</p>
|
||
|
||
<ul>
|
||
|
||
<li>JVM规范要求;</li>
|
||
|
||
<li>满足 JVM 规范要求的一种具体实现(一种计算机程序);</li>
|
||
|
||
<li>一个 JVM 运行实例,在命令提示符下编写 Java 命令以运行 Java 类时,都会创建一个 JVM 实例,我们下面如果只记到 JVM 则指的是这个含义;如果我们带上了某种 JVM 的名称,比如说是 Zing JVM,则表示上面第二种含义。</li>
|
||
|
||
</ul>
|
||
|
||
<p><strong>JDK 与 JRE、JVM 之间的关系</strong></p>
|
||
|
||
<p>就范围来说,JDK > JRE > JVM:</p>
|
||
|
||
<ul>
|
||
|
||
<li>JDK = JRE + 开发工具</li>
|
||
|
||
<li>JRE = JVM + 类库</li>
|
||
|
||
</ul>
|
||
|
||
<p><img src="assets/alvxv.png" alt="0.18346271077222331.png" /></p>
|
||
|
||
<p>三者在开发运行 Java 程序时的交互关系:</p>
|
||
|
||
<p>简单的说,就是通过 JDK 开发的程序,编译以后,可以打包分发给其他装有 JRE 的机器上去运行。而运行的程序,则是通过 Java 命令启动的一个 JVM 实例,代码逻辑的执行都运行在这个 JVM 实例上。</p>
|
||
|
||
<p><img src="assets/mbl7s.png" alt="0.9484384203409852.png" /></p>
|
||
|
||
<p>Java 程序的开发运行过程为:</p>
|
||
|
||
<p>我们利用 JDK (调用 Java API)开发 Java 程序,编译成字节码或者打包程序。然后可以用 JRE 则启动一个 JVM 实例,加载、验证、执行 Java 字节码以及依赖库,运行 Java 程序。而 JVM 将程序和依赖库的 Java 字节码解析并变成本地代码执行,产生结果。</p>
|
||
|
||
<h3>1.2 JDK 的发展过程与版本变迁</h3>
|
||
|
||
<p>说了这么多 JDK 相关的概念,我们再来看一下 JDK 的发展过程。 <strong>JDK 版本列表</strong></p>
|
||
|
||
<table>
|
||
|
||
<thead>
|
||
|
||
<tr>
|
||
|
||
<th align="left">JDK版本</th>
|
||
|
||
<th align="left">发布时间</th>
|
||
|
||
<th align="left">代号</th>
|
||
|
||
<th align="left">备注</th>
|
||
|
||
</tr>
|
||
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<tr>
|
||
|
||
<td align="left">1</td>
|
||
|
||
<td align="left">1996年1月23日</td>
|
||
|
||
<td align="left">Oak(橡树)</td>
|
||
|
||
<td align="left">初代版本,伟大的一个里程碑,但是是纯解释运行,使用JIT,性能比较差,速度慢</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">1.1</td>
|
||
|
||
<td align="left">1997年2月19日</td>
|
||
|
||
<td align="left">Sparkler(宝石)</td>
|
||
|
||
<td align="left">JDBC、支持内部类、RMI、反射等等</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">1.2</td>
|
||
|
||
<td align="left">1998年12月8日</td>
|
||
|
||
<td align="left">Playground(操场)</td>
|
||
|
||
<td align="left">集合框架、JIT等等</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">1.3</td>
|
||
|
||
<td align="left">2000年5月8日</td>
|
||
|
||
<td align="left">Kestrel(红隼)</td>
|
||
|
||
<td align="left">对Java的各个方面都做了大量优化和增强</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">1.4</td>
|
||
|
||
<td align="left">2004年2月6日</td>
|
||
|
||
<td align="left">Merlin(隼)</td>
|
||
|
||
<td align="left">XML处理、支持IPV6、正则表达式,引入nio和CMS垃圾回收器</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">5</td>
|
||
|
||
<td align="left">2004年9月30日</td>
|
||
|
||
<td align="left">Tiger(老虎)</td>
|
||
|
||
<td align="left">泛型、增强for语句、自动拆装箱、可变参数、静态导入、注解</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">6</td>
|
||
|
||
<td align="left">2006年12月11日</td>
|
||
|
||
<td align="left">Mustang(野马)</td>
|
||
|
||
<td align="left">支持脚本语言、JDBC4.0</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">7</td>
|
||
|
||
<td align="left">2011年7月28日</td>
|
||
|
||
<td align="left">Dolphin(海豚)</td>
|
||
|
||
<td align="left">switch支持String类型、泛型推断、nio 2.0开发包、数值类型可以用二进制字符串表示</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">8</td>
|
||
|
||
<td align="left">2014年3月18日</td>
|
||
|
||
<td align="left">Spider(蜘蛛)</td>
|
||
|
||
<td align="left">Lambda 表达式、接口默认方法、Stream API、新的日期API、Nashorn引擎 jjs,引入G1垃圾回收器</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">9</td>
|
||
|
||
<td align="left">2017年9月22日</td>
|
||
|
||
<td align="left">Modularity (模块化)</td>
|
||
|
||
<td align="left">模块系统、HTTP 2 客户端、多版本兼容 JAR 包、私有接口方法、改进Stream API、响应式流(Reactive Streams) API</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">10</td>
|
||
|
||
<td align="left">2018年3月21日</td>
|
||
|
||
<td align="left"></td>
|
||
|
||
<td align="left">引入关键字 var 局部变量类型推断、统一的垃圾回收接口</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">11</td>
|
||
|
||
<td align="left">2018年9月25日</td>
|
||
|
||
<td align="left"></td>
|
||
|
||
<td align="left">HTTP客户端(标准)、无操作垃圾收集器,支持ZGC垃圾回收器,首个LTS版本</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">12</td>
|
||
|
||
<td align="left">2019年3月19日</td>
|
||
|
||
<td align="left"></td>
|
||
|
||
<td align="left">新增一个名为 Shenandoah 的垃圾回收器、扩展switch语句的功能、改进 G1 垃圾回收器</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">13</td>
|
||
|
||
<td align="left">2019年9月17日</td>
|
||
|
||
<td align="left"></td>
|
||
|
||
<td align="left">改进了CDS内存共享,ZGC归还系统内存,SocketAPI和switch语句以及文本块表示</td>
|
||
|
||
</tr>
|
||
|
||
<tr>
|
||
|
||
<td align="left">14</td>
|
||
|
||
<td align="left">开发中</td>
|
||
|
||
<td align="left"></td>
|
||
|
||
<td align="left">继续对ZGC、G1改进,标记 ParallelScavenge + SerialOld组合为过时的 ,移除CMS垃圾回收器</td>
|
||
|
||
</tr>
|
||
|
||
</tbody>
|
||
|
||
</table>
|
||
|
||
<p><strong>Java 大事记</strong></p>
|
||
|
||
<ol>
|
||
|
||
<li>1995 年 5 月 23 日,Java 语言诞生</li>
|
||
|
||
<li>1996 年 1 月,第一个 JDK-JDK1.0 诞生</li>
|
||
|
||
<li>1997 年 2 月 18 日,JDK1.1 发布</li>
|
||
|
||
<li>1997 年 4 月 2 日,JavaOne 会议召开,参与者逾一万人,创当时全球同类会议规模之纪录</li>
|
||
|
||
<li>1997 年 9 月,Java 开发者社区成员超过十万</li>
|
||
|
||
<li>1998 年 2 月,JDK1.1 被下载超过 200 万次</li>
|
||
|
||
<li>1998 年 12 月 8 日,JAVA2 企业平台 J2EE 发布</li>
|
||
|
||
<li>1999 年 6 月,Sun 公司发布 Java 的三个版本:标准版、企业版和微型版(J2SE、J2EE、J2ME)</li>
|
||
|
||
<li>2000 年 5 月 8 日,JDK1.3 发布</li>
|
||
|
||
<li>2000 年 5 月 29 日,JDK1.4 发布</li>
|
||
|
||
<li>2002 年 2 月 26 日,J2SE1.4 发布,自此 Java 的计算能力有了大幅提升</li>
|
||
|
||
<li>2004 年 9 月 30 日,J2SE1.5 发布,是 Java 语言的发展史上的又一里程碑事件,Java 并发包 JUC 也是这个版本引入的。为了表示这个版本的重要性,J2SE1.5 更名为 J2SE5.0</li>
|
||
|
||
<li>2005 年 6 月,发布 Java SE 6,这也是一个比较长期使用的版本</li>
|
||
|
||
<li>2006 年 11 月 13 日,Sun 公司宣布 Java 全线采纳 GNU General Public License Version 2,从而公开了 Java 的源代码</li>
|
||
|
||
<li>2009 年 04 月 20 日,Oracle 公司 74 亿美元收购 Sun。取得 Java 的版权</li>
|
||
|
||
<li>2011 年 7 月 28 日,Oracle 公司发布 Java SE7.0 的正式版</li>
|
||
|
||
<li>2014 年 3 月 18 日,Oracle 公司发布 Java SE 8,这个版本是目前最广泛使用的版本</li>
|
||
|
||
<li>2017 年 9 月 22 日,JDK9 发布,API 有了较大的调整,添加了对 WebSocket 和 HTTP/2 的支持,此后每半年发布一个大版本</li>
|
||
|
||
<li>2018 年 3 月 21 日,JDK10 发布,最大的变化就是引入了 var,如果你熟悉 C# 或 JavaScript/NodeJS 就会知道它的作用</li>
|
||
|
||
<li>2018 年 9 月 25 日,JDK11 发布,引入 ZGC,这个也是第一个公布的长期维护版本 LTS</li>
|
||
|
||
<li>2019 年 3 月 19 日,JDK12 发布,引入毫秒级停顿的 Shenandoah GC</li>
|
||
|
||
<li>2019 年 9 月 17 日,JDK13 发布,改进了 CDS 内存共享,ZGC 归还系统内</li>
|
||
|
||
</ol>
|
||
|
||
<p>我们可以看到 JDK 发展的越来越多,越来越复杂,特别是被 Oracle 收购以后,近 2 年以来版本号快速膨胀,GC 算法也有了更快速的发展。目前最新的 JDK 是 JDK13,同时 JDK14 正在开发中,预计 2020 年 3 月份发布。很多朋友直呼,“不要再升级了,还在用 JDK8,已经学不过来了”。但是正是由于 Java 不断的发展和改进,才会持续具有生命力。</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>常规的 JDK,一般指 OpenJDK 或者 Oracle JDK,当然 Oracle 还有一个新的 JVM 叫 GraalVM,也非常有意思。除了 Sun/Oracle 的 JDK 以外,原 BEA 公司(已被 Oracle 收购)的 JRockit,IBM 公司的 J9,Azul 公司的 Zing JVM,阿里巴巴公司的分支版本 DragonWell 等等。</p>
|
||
|
||
</blockquote>
|
||
|
||
<h3>1.3 安装 JDK</h3>
|
||
|
||
<p>JDK 通常是从 <a href="https://www.oracle.com/">Oracle 官网</a>下载, 打开页面翻到底部,找 <code>Java for Developers</code> 或者 <code>Developers</code>, 进入 <a href="https://www.oracle.com/technetwork/java/index.html">Java 相应的页面</a> 或者 <a href="https://www.oracle.com/technetwork/java/javase/overview/index.html">Java SE 相应的页面</a>, 查找 Download, 接受许可协议,下载对应的 x64 版本即可。 <img src="assets/tzok8.jpg" alt="891e2fe6-e872-4aa9-b00d-d176e947f11f.jpg" /></p>
|
||
|
||
<p>建议安装比较新的 JDK8 版本, 如 <a href="https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html">JDK8u231</a>。 <img src="assets/igolf.png" alt="3bbdc5e9-149c-407d-b757-69a061581aae.png" /></p>
|
||
|
||
<blockquote>
|
||
|
||
<p>注意:从 Oracle 官方安装 JDK 需要注册和登录 Oracle 账号。现在流行将下载链接放到页面底部,很多工具都这样。当前推荐下载 JDK8。 今后 JDK11 可能成为主流版本,因为 Java11 是 LTS 长期支持版本,但可能还需要一些时间才会普及,而且 JDK11 的文件目录结构与之前不同, 很多工具可能不兼容其 JDK 文件的目录结构。</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>有的操作系统提供了自动安装工具,直接使用也可以,比如 yum, brew, apt 等等。例如在 MacBook 上,执行:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>brew cask install java8</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>而使用如下命令,会默认安装最新的 JDK13:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>brew cask install java</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>如果电脑上有 360 软件管家或者腾讯软件管家,也可以直接搜索和下载安装 JDK(版本不是最新的,但不用注册登录 Oracle 账号): <img src="assets/5rwjt.png" alt="035a0b3e-de33-4e97-946c-c9adb8b68ae7.png" /></p>
|
||
|
||
<p>如果网络不好,可以从我的百度网盘共享获取:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p><a href="https://pan.baidu.com/s/16WmRDZSiBD7a2PMjhSiGJw">https://pan.baidu.com/s/16WmRDZSiBD7a2PMjhSiGJw</a></p>
|
||
|
||
<p>提取码: e77s</p>
|
||
|
||
</blockquote>
|
||
|
||
<h3>1.4 设置环境变量</h3>
|
||
|
||
<p>如果找不到命令,需要设置环境变量: <code>JAVA_HOME</code> 和 <code>PATH</code> 。</p>
|
||
|
||
<blockquote>
|
||
|
||
<p><code>JAVA_HOME</code> 环境变量表示 JDK 的安装目录,通过修改 <code>JAVA_HOME</code> ,可以快速切换 JDK 版本 。很多工具依赖此环境变量。</p>
|
||
|
||
<p>另外, 建议不要设置 <code>CLASS_PATH</code> 环境变量,新手没必要设置,容易造成一些困扰。</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>Windows 系统, 系统属性 - 高级 - 设置系统环境变量。 如果没权限也可以只设置用户环境变量。</p>
|
||
|
||
<p>Linux 和 MacOSX 系统, 需要配置脚本。 例如:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>$ <code>cat ~/.bash_profile</code></p>
|
||
|
||
</blockquote>
|
||
|
||
<pre><code class="language-shell"># JAVA ENV
|
||
|
||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home
|
||
|
||
export PATH=$PATH:$JAVA_HOME/bin
|
||
|
||
|
||
|
||
</code></pre>
|
||
|
||
<p>让环境配置立即生效:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>$ <code>source ~/.bash_profile</code></p>
|
||
|
||
</blockquote>
|
||
|
||
<p>查看环境变量:</p>
|
||
|
||
<pre><code class="language-shell">echo $PATH
|
||
|
||
echo $JAVA_HOME
|
||
|
||
|
||
|
||
</code></pre>
|
||
|
||
<p>一般来说,<code>.bash_profile</code> 之类的脚本只用于设置环境变量。 不设置随机器自启动的程序。</p>
|
||
|
||
<p>如果不知道自动安装/别人安装的 JDK 在哪个目录怎么办?</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>最简单/最麻烦的查询方式是询问相关人员。</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>查找的方式很多,比如,可以使用 <code>which</code>, <code>whereis</code>, <code>ls -l</code> 跟踪软连接, 或者 <code>find</code> 命令全局查找(可能需要 sudo 权限), 例如:</p>
|
||
|
||
<pre><code class="language-shell">jps -v
|
||
|
||
whereis javac
|
||
|
||
ls -l /usr/bin/javac
|
||
|
||
find / -name javac
|
||
|
||
|
||
|
||
</code></pre>
|
||
|
||
<p>找到满足 <code>$JAVA_HOME/bin/javac</code> 的路径即可。</p>
|
||
|
||
<p>Windows 系统,安装在哪就是哪,默认在<code>C:\Program Files (x86)\Java</code>下。通过任务管理器也可以查看某个程序的路径,注意 <code>JAVA_HOME</code> 不可能是 <code>C:\Windows\System32</code> 目录。</p>
|
||
|
||
<p>然后我们就可以在 JDK 安装路径下看到很多 JVM 工具,例如在 Mac 上:</p>
|
||
|
||
<p><img src="assets/d5uc5.png" alt="54940291.png" /> 在后面的章节里,我们会详细解决其中一些工具的用法,以及怎么用它们来分析 JVM 情况。</p>
|
||
|
||
<h3>1.4 验证 JDK 安装完成</h3>
|
||
|
||
<p>安装完成后,Java 环境一般来说就可以使用了。 验证的脚本命令为:</p>
|
||
|
||
<pre><code class="language-shell">$ java -version
|
||
|
||
|
||
|
||
</code></pre>
|
||
|
||
<p>可以看到输出类似于以下内容,既证明成功完成安装:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>java version "1.8.0<em>65" Java(TM) SE Runtime Environment (build 1.8.0</em>65-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>然后我们就可以写个最简单的 Java 程序了,新建一个文本文件,输入以下内容:</p>
|
||
|
||
<pre><code>public class Hello {
|
||
|
||
public static void main(String[] args){
|
||
|
||
System.out.println("Hello, JVM!");
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
</code></pre>
|
||
|
||
<p>然后把文件名改成<code>Hello.java</code>,在命令行下执行:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>$ javac Hello.java</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>然后使用如下命令运行它:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>$ java Hello Hello, JVM!</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>即证明运行成功,我们的 JDK 环境可以用来开发了。</p>
|
||
|
||
<h3>参考材料</h3>
|
||
|
||
<ol>
|
||
|
||
<li>https://www.jianshu.com/p/7b99bd132470</li>
|
||
|
||
<li>https://blog.csdn.net/Phoenix_smf/article/details/79709592</li>
|
||
|
||
<li>https://www.iteye.com/blog/dasheng-727156</li>
|
||
|
||
<li>https://blog.csdn.net/lc11535/article/details/99776597</li>
|
||
|
||
<li>https://blog.csdn.net/damin112/article/details/84634041</li>
|
||
|
||
<li>https://blog.csdn.net/KamRoseLee/article/details/79440425</li>
|
||
|
||
<li>https://blog.csdn.net/j3T9Z7H/article/details/94592958</li>
|
||
|
||
<li>http://openjdk.java.net/projects/jdk/</li>
|
||
|
||
<li>http://openjdk.java.net/projects/jdk/13/</li>
|
||
|
||
</ol>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/01 阅读此专栏的正确姿势.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/JVM 核心技术 32 讲(完)/03 常用性能指标:没有量化,就没有改进.md.html">下一页</a>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
|
||
</div>
|
||
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70996fbfca313d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
|
||
</body>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
|
||
<script>
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
|
||
|
||
|
||
function gtag() {
|
||
|
||
dataLayer.push(arguments);
|
||
|
||
}
|
||
|
||
|
||
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'G-NPSEEVD756');
|
||
|
||
var path = window.location.pathname
|
||
|
||
var cookie = getCookie("lastPath");
|
||
|
||
console.log(path)
|
||
|
||
if (path.replace("/", "") === "") {
|
||
|
||
if (cookie.replace("/", "") !== "") {
|
||
|
||
console.log(cookie)
|
||
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
setCookie("lastPath", path)
|
||
|
||
}
|
||
|
||
|
||
|
||
function setCookie(cname, cvalue) {
|
||
|
||
var d = new Date();
|
||
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
|
||
var expires = "expires=" + d.toGMTString();
|
||
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
|
||
}
|
||
|
||
|
||
|
||
function getCookie(cname) {
|
||
|
||
var name = cname + "=";
|
||
|
||
var ca = document.cookie.split(';');
|
||
|
||
for (var i = 0; i < ca.length; i++) {
|
||
|
||
var c = ca[i].trim();
|
||
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
|
||
}
|
||
|
||
return "";
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
</html>
|
||
|