目录

Java 开发流程

Java 运行原理

半编译半解释

平台无关性

JVM 规范(Specification)

Runtime data area 运行时数据区域

Sun JVM 规范实现


当年 sun 公司是这么定义 Java 的:Java 是一种 简单、面向对象、分布式、跨平台、半编译半解释、健壮、安全、高性能、多线程的动态语言。

Java 开发流程

java项目实例的步骤 java项目的流程和实现思路_java

1、如下所示在 E:/Study_Note/test 目录下新建一个 HelloWorld.java 源文件。HelloWorld.java 源文件中输出一句话,同时引用了 JDK 的 API java.util.Date() 打印一下日期。

2、使用 javac *.java 编译源代码,此时如果源代码正确,则默认会在当前目录下自动生成编译好的二进制文件 *.class

java项目实例的步骤 java项目的流程和实现思路_java项目实例的步骤_02

import java.util.Date;
/**
 * Created by Administrator on 2019/3/29 0029.
 */
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World "+ new Date());
    }
}

注意事项:

1、java 命令后面接的是字节码文件(*.class)的类名,且不能带后缀名 .class,否则会报错,*.class 可以放到任意其它位置使用 java 命令执行,不再与 *.java 源码有关

2、java 、javac 命令不是凭空出来的,而是安装好 Java JDK 后,在 %JAVA_HOME%/bin 目录下提供的,而且其中还提供了其它很多命令,如常用的还有 javaw.exe、javafxpackager.exe 等等。

3、所以要想在 cmd 中直接调用 java、javac 等命令,必须先配置好 Java 环境变量,否则只能输命令的全路径。

java项目实例的步骤 java项目的流程和实现思路_Java_03

3、这里所说的开发流程是 Java 开发的底层流程,实际中显然不会这么写 java 源代码,也不会到 cmd 中自己来 javac 编译源文件,然后 java 命令执行字节码文件,而是使用 IDEA 、Eclipse 等工具编写,但需要明白的是这些工具底层也是这么操作的。

Java 运行原理

java项目实例的步骤 java项目的流程和实现思路_JVM_04

java项目实例的步骤 java项目的流程和实现思路_Java_05

JVM(Java Virtual Machine)-Java 虚拟机:

1、JVM 是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。

2、Java 虚拟机有自己完善的硬件架构,如处理器、寄存器、堆栈等,还具有相应的指令系统

半编译半解释

java项目实例的步骤 java项目的流程和实现思路_java项目实例的步骤_06

 1、系统(编译器)先将用户输入的指令翻译成一种通用的,比较规则的中间形式的代码(*.class),保密性强,运行时则由所在机器(JVM)的解释器进行解释执行。

 2、java 语言的开发效率高,但执行效率低。(相当于c++的55%)

平台无关性

1、所谓平台:即一套特定的硬件再加上运行的操作系统(硬件+软件)。编程语言对不同平台的支持有所不同。(如 VB、C/C++、Java...)

2、Java 完全不用修改任何源代码,也不用重新编译就可以将 Java 应用从一个平台直接移植到其它平台。

3、不同平台的内存管理模式和CPU的指令集等都有很大的差别,为了让 Java 实现平台无关性,Sun 公司在不同平台上用软件模拟出虚拟目标机(JVM),虚拟出CPU指令集和内存。

4、Java 平台无关性的关键在于 JVM,所有的字节码(*.class)就是在虚拟出的目标机(JVM)上运行,不会和平台的底层直接打交道。

5、JVM 根据平台的不同,把字节码解释成不同的本地代码(如上图),JVM 就像翻译,把通用的普通话翻译成不同地方的特色方言。

6、Java 的平台无关性给程序的部署带来了很大的灵活性,节约开发和升级成本。但是也有一个缺点:Java代码必须经过JVM解释才能运行,使得Java运行效率相比C++等语言要低很多。

7、WORA:Write Once,Run Anyhere(一次编写,到处运行)

JVM 规范(Specification)

1、JVM Specification(规范)中的 JVM 整体架构如下图:


java项目实例的步骤 java项目的流程和实现思路_java项目实例的步骤_07

运行时数据区域中的方法区、heap:所有线程共享使用

其余3个白色的则各个线程独有,互补干扰


 

1、主要包括两个子系统和两个组件:Class Loader(类加载器)子系统,Execution Engine(执行引擎)子系统;Runtime data area(运行时数据区域)组件,Native interface(本地接口)组件。

2、Class loader 子系统:根据给定的全限定类名(如 java.lang.Object)来装载 class 文件的内容到 Runtime data area 中的方法区。Java 程序员可以 extends java.lang.ClassLoader 类来自定义 Class loader。

3、Execution engine 子系统:执行 classes 中的指令。任何 JVM 规范的实现(JDK),其核心就是 Execution engine。目前 JVM 规范的实现主要有 sun 公司的 JDK、JRE(现在是Oracle的了),以及 IBM 的 JDK、JRE,因为都遵循 JVM 规范,所以功能上基本无异,好坏程度主要取决于它们各自实现的 Execution engine。每个运行中的线程都有一个 Executon engine 的实例。

4、Native interface 组件:与 Native libraries 交互,是与其它编程语言交互的接口。

5、Runtime data area 组件:这个组件是 JVM 中的内存,也是核心部分,下面将对它进行详细介绍。

Runtime data area 运行时数据区域

1、Runtime data area 组件是 JVM 中的内存,整体架构图如下:

java项目实例的步骤 java项目的流程和实现思路_Java_08

2、Runtime data area 主要包括五个部分:Heap (堆)、Method Area(方法区域)、Java Stack(java的栈)、Program Counter(程序计数器)、Native method stack(本地方法栈)。

3、Heap 和 Method Area 是被所有线程的共享使用的;而 Java stack, Program counter 和Native method stack 是以线程为粒度的,每个线程独自拥有。

Heap(堆)

1、Java 程序在运行时创建的所有类实例或数组都放在同一个堆中。

2、一个 Java 程序独占一个 JVM 实例,互补干扰,一个 JVM 实例只存在一个堆空间,同一 Java 程序中的所有线程都共享这个堆,所以得考虑多线程访问对象(堆数据)的同步问题。

3、可能出现的异常为:java.lang.OutOfMemoryError:Java heap space

Method area(方法区)

1、Java 虚拟机中,被装载的 class 的信息存储在 Method area 的内存中。

2、当虚拟机装载某个类型时,它使用类装载器定位相应的 class 文件,然后读入这个 class 文件的内容,并把它传输到虚拟机中。然后虚拟机提取其中的类型信息,同时将它存储到方法区。该类型中的类(静态)变量同样也存储在方法区中。

3、与 heap 一样,method area 也是多线程共享的,需要考虑多线程访问的同步问题。比如:两个线程都企图访问一个名为 HelloWorld 的类,而这个类还没有装载入虚拟机,那么这时应该只有一个线程去装载它,另一个线程只能等待。

4、可能出现的异常:java.lang.OutOfMemoryError:PermGen full(permanent generation full)

Java Stack(虚拟机栈)

1、Java stack 以帧为单位保存线程的运行状态。

2、虚拟机只会直接对 Java stack 执行两种操作;以帧为单位的压栈或出栈。每当线程调用一个方法时,就对当前状态作为一个帧保存到 Java stack 中(压栈);当一个方法返回时,从 Java stack 弹出一个帧(出栈)。

3、栈的大小是有一定的限制的,可能出现的问题为:StackOverFlow

Program counter(程序计数器)

1、每个运行中的 Java 程序,每一个线程都有它自己的 PC寄存器,在线程启动时创建的。(延伸:寄存器是 CPU 的组成部分,是一个容量有限的高速存储部件,它们可用来暂存指令、数据和地址)

2、PC寄存器的内容总是指向下一条将被执行指令的"地址",这里的"地址"可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。

Native method stack(本地方法栈)

1、对于一个运行中的 Java 程序而言,它可能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。

2、本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,不止与此,它还可以做任何它想做的事情。比如,可以调用寄存器,或在操作系统中分配内存等。

3、总之,本地方法具有和 JVM 相同的能力和权限。 (这里可能出现 JVM 无法控制的内存溢出问题native heap OutOfMemory )

Sun JVM 规范实现

1、本节主要介绍 Sun JVM 中对 JVM Specification 的实现(内存部分)。

2、已经说过 JVM Specification(规范)只是抽象的说明了 JVM 实例按照子系统、内存区、数据类型以及指令这几个术语来描述,规范并非是要强制规定 Java 虚拟机实现内部的体系结构,更多的是为了严格地定义这些实现的外部特征。所以如 Sun JVM 实现与 IMB JVM 实现细节上略有不同。

3、Sun JVM 实现中:Runtime data area(JVM 内存) 五个部分中的 Java Stack , Program Counter, Native method stack 三部分和规范中的描述基本一致;但对 Heap 和 Method Area 进行了自己独特的实现。这个实现和 Sun JVM 的 Garbage collector(垃圾回收)机制有关。下面的"垃圾分代回收算法"会进行详细描述。