public class T1_ClassLoaderLevel {
public static void main( String[] args) {
System.out.println(String.class.getClassLoader() );
System.out.println(sun.awt.HKSCS.class.getClassLoader() );
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
System.out.println(T1_ClassLoaderLevel.class.getClassLoader());
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader() .getClass().getClassLoader());
System.out .println(T1_ClassLoaderLevel.class.getClassLoader ().getClass().getClassLoader());
}
}
运行结果
null null sun.misc.Launcher$ExtClassLoader@6d6f6e28 sun.misc.Launcher$AppClassLoader@18b4aac2 null null
父加载器不是类加载器的加载器 也不是类加载器的父类加载器
public class T2_ParentAndChild {
public static void main( String[] args){
System.out.println(T2_ParentAndChild.class.getClassLoader());
System.out.println(T2_ParentAndChild.class.getClassLoader() .getClass().getClassLoader());
System.out.println(T2_ParentAndChild.class.getClassLoader( ).getParent());
System.out.println(T2_ParentAndChild.class.getClassLoader() .getParent() .getParent());
System.out.println(T2_ParentAndChild.class.getClassLoader ( ) . getParent().getParent ( ) .getParent());
}
}
运行结果
sun.misc.Launcher$AppClassLoader@18b4aac2 null sun.misc.Launcher$ExtClassLoader@4554617c null Exception in thread "main" java.lang.NullPointerException at com.jsxl.jvm.classload.T2_ParentAndChild.main(T2_ParentAndChild.java:10)
Launcher$AppClassLoader(代表AppClassLoader是Launcher下面的内部类,查源码自行了解)
public class T3_classLoaderScope {
public static void main( String[] args) {
String pathBoot = System.getProperty( "sun.boot.class.path");
System.out.println(pathBoot.replaceAll( ";",System.lineSeparator()));
System.out.println ("--------------------");
String pathExt = System.getProperty( "java.ext.dirs");
System.out.println(pathExt.replaceAll( ";",System.lineSeparator()));
System.out.println ( "--------------------");
String pathApp = System.getProperty("java.class.path");
System.out.println(pathApp.replaceAll( ";",System.lineSeparator()));
}
}
运行结果
D:javajava8jdk1.8.0_91jrelibresources.jar D:javajava8jdk1.8.0_91jrelibrt.jar D:javajava8jdk1.8.0_91jrelibsunrsasign.jar D:javajava8jdk1.8.0_91jrelibjsse.jar D:javajava8jdk1.8.0_91jrelibjce.jar D:javajava8jdk1.8.0_91jrelibcharsets.jar D:javajava8jdk1.8.0_91jrelibjfr.jar D:javajava8jdk1.8.0_91jreclasses -------------------- D:javajava8jdk1.8.0_91jrelibext C:WindowsSunJavalibext -------------------- D:javajava8jdk1.8.0_91jrelibcharsets.jar D:javajava8jdk1.8.0_91jrelibdeploy.jar D:javajava8jdk1.8.0_91jrelibextaccess-bridge-64.jar D:javajava8jdk1.8.0_91jrelibextcldrdata.jar D:javajava8jdk1.8.0_91jrelibextdnsns.jar D:javajava8jdk1.8.0_91jrelibextjaccess.jar D:javajava8jdk1.8.0_91jrelibextjfxrt.jar D:javajava8jdk1.8.0_91jrelibextlocaledata.jar D:javajava8jdk1.8.0_91jrelibextnashorn.jar D:javajava8jdk1.8.0_91jrelibextsunec.jar D:javajava8jdk1.8.0_91jrelibextsunjce_provider.jar D:javajava8jdk1.8.0_91jrelibextsunmscapi.jar D:javajava8jdk1.8.0_91jrelibextsunpkcs11.jar D:javajava8jdk1.8.0_91jrelibextzipfs.jar D:javajava8jdk1.8.0_91jrelibjavaws.jar D:javajava8jdk1.8.0_91jrelibjce.jar D:javajava8jdk1.8.0_91jrelibjfr.jar D:javajava8jdk1.8.0_91jrelibjfxswt.jar D:javajava8jdk1.8.0_91jrelibjsse.jar D:javajava8jdk1.8.0_91jrelibmanagement-agent.jar D:javajava8jdk1.8.0_91jrelibplugin.jar D:javajava8jdk1.8.0_91jrelibresources.jar D:javajava8jdk1.8.0_91jrelibrt.jar D:githubJVMtargetclasses D:toolsideaIntelliJ IDEA 2018.3.6libidea_rt.jar自定义类加载器
继承ClassLoader
重写模板方法findClass调用defineClass
自定义类加载器加载自加密的class
- 防止反编译
- 防止篡改
public class T4_LoadClassByHand {
public static void main(String[] args) throws ClassNotFoundException {
Class> clazz = T4_LoadClassByHand.class.getClassLoader().loadClass("com.jsxl.jvm.classload.T2_ParentAndChild");
System.out.println(clazz.getName());
//利用类加载器加载资源
// T4_LoadClassByHand.class.getClassLoader ( ). getResourceAsStream("");
}
}
loadClass源码
protected Class> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
ClassLoader源码解析
findClass
如果是AppClassLoader首先会执行URLClassLoader的findClass方法
思考这是一个什么设计模式?
public class T5_DefineClassLoad extends ClassLoader {
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
File f = new File("c:/test/", name.replaceAll(" .", "/").concat(".class"));
try {
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ((b = fis.read()) != 0) {
baos.write(b);
}
byte[] bytes = baos.toByteArray();
baos.close();
fis.close();//可以写的更加严谨
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name); //throws ClassNotFoundException
}
public static void main(String[] args) throws Exception {
ClassLoader l = new T5_DefineClassLoad();
Class clazz = l.loadClass("com.jsxl.jvm.classload.Hello");
Hello h = (Hello) clazz.newInstance();
h.m();
System.out.println(l.getClass().getClassLoader());
System.out.println(l.getParent());
}
}
public class Hello {
public void m(){
System.out.println("hello word");
}
}
运行结果
hello word sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$AppClassLoader@18b4aac2
加密
package com.jsxl.jvm.classload;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class T6_MSBClassLoaderwithEncription extends ClassLoader {
public static int seed = 0B10110110;
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
File f = new File("D:/test/", name.replaceAll("\.", "/").concat(".lhtclass"));
try {
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
while ((b = fis.read()) != 0) {
baos.write(b);
}
byte[] bytes = baos.toByteArray();
baos.close();
fis.close();//可以写的更加严谨
return defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name); //throws ClassNotFoundException
}
public static void main(String[] args) throws Exception {
encFile ("com.jsxl.jvm.classload.Hello" ) ;
ClassLoader l = new T6_MSBClassLoaderwithEncription();
Class clazz = l.loadClass("com.jsxl.jvm.classload.Hello");
Hello h = (Hello)clazz.newInstance();
h.m();
System.out.println(l.getClass().getClassLoader( ) );
System.out.println(l.getParent());
}
private static void encFile(String name) throws Exception {
File f = new File( "D:/test/",name.replace( "." ,"/" ).concat(".class"));
FileInputStream fis = new FileInputStream(f);
FileOutputStream fos = new FileOutputStream(new File("D:/test/",name.replaceAll( "\.","/" ).concat(".lhtclass")));
int b = 0;
while((b = fis.read()) != -1) {
fos.write(b^seed);
}
fis.close();
fos.close();
}
}
解释器(java是混合模式)
解释器
bytecode intepreter
JIT
Just ln-Time compiler
混合模式
- 混合使用解释器+热点代码编译
- 起始阶段采用解释执行
- 热点代码检测
- 多次被调用的方法(方法计数器:监测方法执行频率)
- 多次被调用的循环(循环计数器:检测循环执行频率)
- 进行编译
Xmixed 默认为混合模式
开始解释执行,启动速度较快对热点代码实行检测和编译
public class T7_WayToRun {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) m();
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) m();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public static void m() {
for (long i = 0; i < 100000L; i++) {
long j=i%3;}
}
}
输出:2541
Xint使用编译模式,启动很快执行稍慢
Xcomp使用纯编译模式,执行很快,启动很慢
- 严格讲应该叫lazylnitializing
- JVM规范并没有规定何时加载
- 但是严格规定了什么时候必须初始化
- new getstatic putstatic invokestatic指令,访问final变量除外
- java.lang.reflect对类进行反射调用时
- 初始化子类的时候,父类首先初始化-虚拟机启动时,被执行的主类必须初始化
- 动态语言支持java.lang.invoke.MethodHandle解析的结果为
- REFgetstatic REF putstatic REF_invokestatic的方法句柄时,该类必须初始化
public class Tc08_LazyLoading { //严格讲应该叫lazyinitialzing,因为java虚拟机规范并没有严格规定什么时候必须Lodding
public static void main(String[] args) throws Exception {
P p;
// X x = new X( );
// System.out.println(P.i);
// System.out.println(P.j);
// Class.forName("com.jsxl.jvm.classload.Tc08_LazyLoading$P");
}
public static class P {
final static int i = 8;
static int j = 9;
static {
System.out.println("P");
}
}
public static class X extends P {
static {
System.out.println("x");
}
}
public class T010_Parent {
private static T5_DefineClassLoad parent = new T5_DefineClassLoad();
private static class MyLoader extends ClassLoader {
public MyLoader(){
super(parent);
}
}
}
public class T02_ClassLoaderLevel {
public static void main( String[] args) {
System.out.println( String.class.getClassLoader());
System.out.println(sun.awt.HKSCS.class.getClassLoader() );
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
System.out.println(T02_ClassLoaderLevel.class.getClassLoader());
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
System.out.println(T02_ClassLoaderLevel.class.getClassLoader().getParent());
System.out.println(new T5_DefineClassLoad().getParent());
System.out.println(ClassLoader.getSystemClassLoader());
}
}
public class To11_classReloading {
public static void main(String[] args) throws Exception {
T5_DefineClassLoad ClassLoader = new T5_DefineClassLoad();
Class clazz = ClassLoader.loadClass("com.jsxl.jvm.classload.Hello");
ClassLoader = null;
System.out.println(clazz.hashCode());
ClassLoader = null;
ClassLoader = new T5_DefineClassLoad();
Class clazz1 = ClassLoader.loadClass("com.jsxl.jvm.classload.Hello");
System.out.println(clazz1.hashCode());
System.out.println(clazz == clazz1);
}
}
打破
public class To12_classReloading2 {
private static class MyLoader extends ClassLoader {
@Override
public Class> loadClass(String name) throws ClassNotFoundException {
File f = new File("D:/github/JVM/" + name.replaceAll("\.", "/").concat(".class"));
if (!f.exists()) return super.loadClass(name);
try {
InputStream is = new FileInputStream(f);
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.loadClass(name);
}
}
public static void main(String[] args) throws Exception {
MyLoader m = new MyLoader();
Class clazz = m.loadClass("com.jsxl.jvm.classload.Hello");
m = new MyLoader();
Class clazzNew = m.loadClass("com.jsxl.jvm.classload.Hello");
System.out.println(clazz == clazzNew);
}
}
JVM类加载过程
- 加载: Loading
- 连接: linking
- 验证: Verification(验证文件是否符合JVM规范)
- 准备: Preparation(静态成员变量赋默认值)
- 解析: Resolution(将类、方法、属性等符号引用解析为真接引用 ,常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用)
- 初始化:Initializing(调用类初始化代码)
- 卸载:Unloading
- 使用:Using
- 初始化:
public class T001_classLoadingProcedure {
public static void main(String[] args) {
System.out.println(T.count);
}
}
class T {
public static int count = 2; // 0
public static T t = new T(); // null
// private int m = 8;
// public static T t = new T(); //null
// public static int count = 2; // 0
private T() {
count++;
System.out.println("—-" + count);
}
}



