主要是关于Hotspot部分文件区分
1./hotspot/src下的文件描述
文件夹名称 | 描述 |
---|---|
cpu | 硬件相关层 |
os | 软件相关层 |
os_cpu | 软硬相关层 |
share | 平台无关层:C++语言 |
2./hotspot/src下的文件描述
文件夹名称 | 描述 |
---|---|
tool | 工具包 |
vm | 虚拟机相关的 |
3./hotspot/src/share/vm下的文件描述
文件夹名称 | 描述 |
---|---|
c1 | JIT |
asm | 汇编器 |
classfile | 字节码相关 |
code | 平台无关层:用来做代码生成,把我们写的汇编代码生成机器能够执行的二进制的codeBlob然后放到codeCache里面,然后从codeCache里面去执行代码 |
compiler | 平台无关层:有编译器相关的代码,有汇编,有反汇编,有oopMap(内存对象映射,用来做safe,safe point扫描栈对象,描述当前栈里边有哪一部分是对象的引用) |
gc_interface | 平台无关层:gc接口 |
gc_implement | 平台无关层:gc实现 |
interpreter | 平台无关层:解释器,字节码运行就需要解释器,有c++解释器和模板解释器。c++解释器读取c++的代码运行。模板解释器是用来做汇编的。 |
memory | 平台无关层:内存相关的 |
oops | 平台无关层:普通java对象模型 |
prims | 平台无关层:primary, 首要的东西 |
runtime | 平台无关层:运行时相关的东西 |
services | 平台无关层:主要是jmm的services |
utilties | 平台无关层:工具包 |
jdk下的部分文件描述
1./jdk/make下的文件描述
文件夹名称 | 描述 |
---|---|
share | 包含jdk/bin目录下面的所有东西的源代码,javac.exe的源代码就是java.c,包含java代码所依赖的本地方法(/jdk/make/native文件夹下) |
2.Java Native Interface
JNI:用于java 代码 .class文件调用原生代码(C语言,C++的代码。
JVM解释器内的执行引擎读取各个字节码执行,如果发现需要调用c语言或c++的代码,即代码里面用了native,通过动态链接库关联(.dll)。
命名格式:JAVA_包名_方法名 需要 include “jni.h”
JNI简单示例.
ClassFileParser.hpp
实现层在classFileParser.cpp,在hostspot启动的时候要预先把java.lang包里面的类加载到内存里面,通过bootstrapclassloader加载。
Demo.java,通过javac Demo.java编译,再通过javap -V Demo.class查看
下面展示一些 内联代码片
。
public class Demo {
public static void main(String[] args) {
System.out.println("hello world");
}
}
javap -V Demo.class
Classfile /xx路径/Demo.class
Last modified 2021-7-22; size 413 bytes
MD5 checksum 895a18d39bd79b9f02c70a747802a2c4
Compiled from "Demo.java"
public class Demo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
// 解析常量池
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // hello world
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // Demo
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 Demo.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 hello world
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 Demo
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
// 解析方法名
public Demo();
// 解析方法的描述符
descriptor: ()V
// 方法的标志位
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
// aload_0 就是把this的引用加载过来,
0: aload_0
// 然后调用this里面的special
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
// 可以把main方法识别出来
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
// 遍历里面的code,里面的栈大小就是2,数组大小是1
Code:
stack=2, locals=1, args_size=1
// new 一个 局部变量表,类似hashMap
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
SourceFile: "Demo.java"
计算机中字符串如何表示?
在计算机中,寻址(即表示一个数据)的最小单元就是一个字节,字符串用byte[]表示。
JAVA中继承接口的向上转型和继承类的向上转型有什么不同的地方?
interface A{
void a();
}
class B implements A{
public void a(){
System.out.println("hello world");
}
}
public class Demo{
public static void main(String[] args){
A a = new B();
a.a();
}
}
javap -v -c -s A // 打印内部类,签名
Classfile /xx路径/A.class
Last modified 2021-7-23; size 104 bytes
MD5 checksum 9bf770e1b568b54f0e7d0f4f38c92beb
Compiled from "Demo.java"
interface A
minor version: 0
major version: 52
flags: ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
#1 = Class #7 // A
#2 = Class #8 // java/lang/Object
#3 = Utf8 a
#4 = Utf8 ()V
#5 = Utf8 SourceFile
#6 = Utf8 Demo.java
#7 = Utf8 A
#8 = Utf8 java/lang/Object
{
public abstract void a();
descriptor: ()V
flags: ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "Demo.java"
javap -v -c -s B
Classfile /xx路径/B.class
Last modified 2021-7-23; size 391 bytes
MD5 checksum ea8b59f2385f8d17109e985d644369e8
Compiled from "Demo.java"
class B implements A
minor version: 0
major version: 52
flags: ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // hello world
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // B
#6 = Class #22 // java/lang/Object
#7 = Class #23 // A
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 a
#13 = Utf8 SourceFile
#14 = Utf8 Demo.java
#15 = NameAndType #8:#9 // "<init>":()V
#16 = Class #24 // java/lang/System
#17 = NameAndType #25:#26 // out:Ljava/io/PrintStream;
#18 = Utf8 hello world
#19 = Class #27 // java/io/PrintStream
#20 = NameAndType #28:#29 // println:(Ljava/lang/String;)V
#21 = Utf8 B
#22 = Utf8 java/lang/Object
#23 = Utf8 A
#24 = Utf8 java/lang/System
#25 = Utf8 out
#26 = Utf8 Ljava/io/PrintStream;
#27 = Utf8 java/io/PrintStream
#28 = Utf8 println
#29 = Utf8 (Ljava/lang/String;)V
{
B();// 这个就是编译器自动生成的构造函数
descriptor: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 5: 0
public void a();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 7: 0
line 8: 8
}
SourceFile: "Demo.java"
invokevirtual说明
invokespecial说明
oopmap
用于记录oop的引用,从而找到gc root的引用
GC安全点
SystemDictionary
systemDictionary用于保存系统类所有加载的类型.
类加载器原理
java中类加载有双亲委派机制:bootstrap<-ext<-app.
通过findClass来查找类。
为什么bootstrap为null?
因为bootstrap是在jvm中的,用c++写的加载代码(但是他不是类加载器,他只是具有类加载功能),把类加载过来。
怎么优化并发hash
分段和分段锁,通过给每个线程一把分段的分段锁。
类和对象是什么关系?
类是对象的模板,对象是类的实例。