本系列基于JDK7
JVM体系结构
主要包含两个子系统和两个组件。
CAS(Compare And Swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与期望的值相等,就使用一个新值替换当前变量的值。
在程序和算法中一个经常出现的模式就是Check And Act模式。先检查后操作模式发生在代码中首先检查一个变量的值,然后再基于这个值做一些操作。
原子性就是说一个操作不可以被中途CPU暂停然后调度,即不能被中断,要不就执行完,要不就不执行。
是不能被线程调度机制中断的操作,一旦操作开始,那么它一定可以在可能发生中断之前执行完毕。
一个不正确的知识:“原子操作不需要进行同步控制”。
原子性可以应用于基本数据类型(64位的long
和double
不是原子性),对于写入和读取,可以把它们当作原子操作来操作内存。但是,JVM可以将64(long
和double
)的读取和写入当作两个分离的32位操作来执行,这个就产生在读取和写入操作中间发生上下文切换问题,导致不同的任务可以看到不正确结果。
1 | C:\Users\Administrator>java -version |
命令 | 说明
—|—
appletviewer | 用于运行并浏览applet小程序。
extcheck | 扩展检测工具,主要用于检测指定jar文件与当前已安装的Java SDK扩展之间是否存在版本冲突。
idlj | IDL转Java编译器(IDL-to-Java Compiler),用于为指定的IDL文件生成Java绑定。IDL意即接口定义语言(Interface Definition Language)。
jar | jar文件管理工具,主要用于打包压缩、解压jar文件。
jarsigner | jar密匙签名工具。
java | Java运行工具,用于运行.class字节码文件或.jar文件。
javac | Java编译工具(Java Compiler),用于编译Java源代码文件。
javadoc | Java文档工具,主要用于根据Java源代码中的注释信息生成HTML格式的API帮助文档。
javafxpackager | JavaFX包装器,用于执行与封装或签名JavaFX应用有关的任务。JDK 8u20已经迁移此工具到javapackager。
javah | Java头文件工具,用于根据Java类生成C/C++头文件和源文件(主要用于JNI开发领域)。
javap | Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件。
javapackager | 执行针对Java应用程序和JavaFX应用程序的打包和签名的任务。包含了javafxpackager的功能。
jcmd | Java 命令行(Java Command),用于向正在运行的JVM发送诊断命令请求。
jconsole | 图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息
jdeps | 用于分析Java class的依赖关系
jdb | Java调试工具(Java Debugger),主要用于对Java应用进行断点调试
jhat | Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。
jinfo | Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。
jjs | 对Nashorn引擎的调用。Nashorn是基于Java实现一个轻量级高性能的JavaScript运行环境。
jmap | Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
jmc | Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断。开发者可以使用jmc命令来创建JMC工具。
jps | JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上的HotSpot JVM的Java进程信息。
jrunscript | Java命令行脚本外壳工具(command line script shell),主要用于解释执行javascript、groovy、ruby等脚本语言。
jsadebugd | Java可用性代理调试守护进程(Java Serviceability Agent Debug Daemon),主要用于附加到指定的Java进程、核心文件,或充当一个调试服务器。
jstack | Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。
jstat | JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息,包括gc统计信息。
jstatd | jstatd(VM jstatd Daemon)工具是一个RMI服务器应用,用于监测HotSpot JVM的创建和终止,并提供一个接口,允许远程监测工具附加到运行于本地主机的JVM上。
jvisualvm | JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息。
keytool | 密钥和证书管理工具,主要用于密钥和证书的创建、修改、删除等。主要用于获取或缓存Kerberos协议的票据授权票据。允许用户查看本地凭据缓存和密钥表中的条目(用于Kerberos协议)。Kerberos密钥表管理工具,允许用户管理存储于本地密钥表中的主要名称和服务密钥。
native2ascii | 本地编码到ASCII编码的转换器(Native-to-ASCII Converter),用于”任意受支持的字符编码”和与之对应的”ASCII编码和(或)Unicode转义”之间的相互转换。
orbd | 对象请求代理守护进程(Object Request Broker Daemon),它使客户端能够透明地定位和调用位于CORBA环境的服务器上的持久对象。
pack200 | JAR文件打包压缩工具,它可以利用Java类特有的结构,对普通JAR文件进行高效压缩,以便于能够更快地进行网络传输。这是微软提供的对象包装程序,用于对象安装包。
policytool | 策略工具,用于管理用户策略文件(.java.policy)。
rmic | Java RMI 编译器,为使用JRMP或IIOP协议的远程对象生成stub、skeleton、和tie类,也用于生成OMG IDL。
rmid | Java RMI 激活系统守护进程,rmid启动激活系统守护进程,允许在虚拟机中注册或激活对象。
rmiregistry | Java 远程对象注册表,用于在当前主机的指定端口上创建并启动一个远程对象注册表。
schemagen | XML schema生成器,用于生成XML schema文件。
serialver | 序列版本命令,用于生成并返回serialVersionUID。
servertool | Java IDL 服务器工具,用于注册、取消注册、启动和终止持久化的服务器。
tnameserv | Java IDL瞬时命名服务。
unpack200 | JAR文件解压工具,将一个由pack200打包的文件解压提取为JAR文件。
wsgen | XML Web Service 2.0的Java API,生成用于JAX-WS Web Service的JAX-WS便携式产物。
wsimport | XML Web Service 2.0的Java API,主要用于根据服务端发布的wsdl文件生成客户端存根及框架。
xjc | 主要用于根据XML schema文件生成对应的Java类。
Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控:
jstat工具特别强大,它有众多的可选项,通过提供多种不同的监控维度,使我们可以从不同的维度来了解到当前JVM堆的使用情况。详细查看堆内各个部分的使用量,使用的时候必须加上待统计的Java进程号,可选的不同维度参数以及可选的统计频率参数。它主要是用来显示GC及PermGen相关的信息。
临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。当有线程进入临界区段时,其他线程或是进程必须等待(例如:bounded waiting等待法),有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用。只能被单一线程访问的设备,例如:打印机。
互斥量是一个可以处于两态之一的变量:解锁和加锁。
这样,只需要一个二进制位表示它,不过实际上,常常使用一个整型量,0表示解锁,而其他所有的值则表示加锁。互斥量使用两个过程。当一个线程(或进程)需要访问临界区时,它调用mutex_lock
。如果该互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可以自由进入该临界区。
另一方面,如果该互斥量已经加锁,调用线程被阻塞,直到在临界区中的线程完成并调用mutex_unlock
。如果多个线程被阻塞在该互斥量上,将随机选择一个线程并允许它获得锁。
Copy-On-Write简称COW,是一种用于程序设计中的优化策略。
开始都在共享同一个内容,当想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略。
CopyOnWrite容器即写时复制的容器。通俗的理解:往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。(但是读取的数据会有延迟)所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。目的是为了提高并发能力。
首先有一个TestClass类,代码如下。1
2
3
4
5
6
7
8
9
10
11
12
13
14package com.ejushang.TestClass;
public class TestClass implements Super {
private static final int staticVar = 0;
private int instanceVar = 0;
public int instanceMethod(int param) {
return param + 1;
}
}
interface Super {
}
通过jdk1.6.0_37的javac编译后的TestClass.java对应的TestClass.class的二进制结构如下。
TestClass.class
用WinHex工具查看字节码。
学习Java的朋友应该都知道Java从刚开始的时候就打着平台无关性的旗号,说“一次编写,到处运行”,其实说到无关性,Java平台还有另外一个无关性那就是语言无关性,要实现语言无关性,那么Java体系中的class的文件结构或者说是字节码就显得相当重要了,其实Java从刚开始的时候就有两套规范,一个是Java语言规范,另外一个是Java虚拟机规范,Java语言规范只是规定了Java语言相关的约束以及规则,而虚拟机规范则才是真正从跨平台的角度去设计的。今天我们就以一个实际的例子来看看,到底Java中一个Class文件对应的字节码应该是什么样子。 这篇文章将首先总体上阐述一下Class到底由哪些内容构成,然后再用一个实际的Java类入手去分析class的文件结构。
Update your browser to view this website correctly. Update my browser now