Note : 如果源码中出现有native非访问控制修饰符时,那么说明其调用了非java实现的代码库,此时可以通过该网站进行查阅,由于oracle的jdk是部分闭源的,而openjdk是开源的,所以选择在openjdk看native lib
利用javac对.java文件进行compile,之后产生.class文件。.class文件包含了??? 。之后我们可以通过javap,也就是jdk自带的反汇编器,来查看.class文件的内容。
wong@MacBook-Pro Desktop % javap -c Test.class
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iconst_0
3: istore_2
4: iinc 1, 1
7: iinc 2, 1
10: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_1
14: invokevirtual #13 // Method java/io/PrintStream.println:(I)V
17: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
20: iload_2
21: invokevirtual #13 // Method java/io/PrintStream.println:(I)V
24: return
}
Java源码首先被编译成java字节码,再由不同平台的JVM进行解析。java语言在不同平台上运行不需要进行重新编译,java虚拟机在执行字节码的时候,再将字节码转换成平台对应的机器指令。
JVM如何加载.class文件
上图是JVM的架构图。
特定格式
,加载class文件到内存Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的方法和属性;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息和动态调用对象方法的功能成为Java的反射机制
Class rb = Class.forName("code1.Robot");
Robot r = (Robot)rb.newInstance();
System.out.println("Class name is " + rb.getName());
Method getHello = rb.getDeclaredMethod("throwHello", String.class);
getHello.setAccessible(true);
Object str = getHello.invoke(r, "Bob");
System.out.println("The name is " + str);
Field name = rb.getDeclaredField("name");
name.setAccessible(true);
name.set(r, "Obama");
Method sayHi = rb.getMethod("sayHi", String.class);
sayHi.invoke(r, "What");
类从编译到执行的过程
ClassLoader在Java中有着非常重要的地位。它主要工作在Class装载阶段,其主要作用是从系统外部获得Class字节码数据流。它是java的核心组件,所有的class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的字节码数据流装载进系统,然后交给Java虚拟机进行连接,初始化等操作。
public class MyClassLoader extends ClassLoader {
private String path;
private String classLoaderName;
public MyClassLoader(String path, String classLoaderName) {
this.path = path;
this.classLoaderName = classLoaderName;
}
// Find Class File
@SuppressWarnings("deprecation")
@Override
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(b, 0, b.length);
}
// Load Class File
private byte[] loadClassData(String name) {
name = path + name + ".class";
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(new File(name));
out = new ByteArrayOutputStream();
int i = 0;
while( (i = in.read()) != -1) {
out.write(i);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// TODO Auto-generated method stub
return out.toByteArray();
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
MyClassLoader mc = new MyClassLoader("/Users/wong/", "wali.class");
Class c = mc.loadClass("Wali");
System.out.println(c.getClassLoader());
c.newInstance();
}
ASM
& 字节码增强技术
& AOP的实现
类加载器的双亲委派机制
为何要使用双亲委派机制?因为避免同一个字节码文件加载多次,避免占用多余的内存空间
类的加载方式
酝酿中…
本文地址:https://blog.csdn.net/weixin_41741302/article/details/107335641
如对本文有疑问, 点击进行留言回复!!
集合框架——Map、泛型以及Collection算法常用方法
Elasticsearch 升级 7.x 版本后,我感觉掉坑里了
Mybatis的插件运行原理以及如何编写一个Mybatis的插件
网友评论