learn.lianglianglee.com/专栏/JVM 核心技术 32 讲(完)/02 环境准备:千里之行,始于足下.md.html
2022-05-11 18:57:05 +08:00

1239 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>JDKJava Development Kit 是用于开发 Java 应用程序的软件开发工具集合,包括了 Java 运行时的环境JRE、解释器Java、编译器javac、Java 归档jar、文档生成器Javadoc等工具。简单的说我们要开发 Java 程序,就需要安装某个版本的 JDK 工具包。</p>
<p><strong>JRE</strong></p>
<p>JREJava Runtime Enviroment )提供 Java 应用程序执行时所需的环境,由 Java 虚拟机JVM、核心类、支持文件等组成。简单的说我们要是想在某个机器上运行 Java 程序,可以安装 JDK也可以只安装 JRE后者体积比较小。</p>
<p><strong>JVM</strong></p>
<p>Java Virtual MachineJava 虚拟机)有三层含义,分别是:</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 &gt; JRE &gt; 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 收购)的 JRockitIBM 公司的 J9Azul 公司的 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 &quot;1.8.0<em>65&quot; 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(&quot;Hello, JVM!&quot;);
}
}
</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>