1.Caused by: java.lang.NoClassDefFoundError: Failed resolution of:Lcom/tencent/ysdk/framework/hotfix
2.描述一下JVM加载class文件 的源码原理机制?
3.java å¦ä½ç解classloader
4.InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbinfo.properties");
Caused by: java.lang.NoClassDefFoundError: Failed resolution of:Lcom/tencent/ysdk/framework/hotfix
NoClassDefFoundError é®é¢åå 1ï¼ç¼ºå°jarå
é¦å æ常è§çåå æ¯classpathçé ç½®é®é¢ãä¾åç¨åºï¼
æ¬ä¾åç¨åºå°è¯å建ä¸ä¸ªæ°çCallerClassAå®ä¾ï¼ç¶åæ§è¡ä»çä¸ä¸ªæ¹æ³ï¼æ¤æ¹æ³å¼ç¨äºç±»ReferencingClassAï¼æ¬ä¾åæ¼ç¤ºäºclasspathé®é¢å¯¼è´çNoClassDefFoundError ï¼æ¬ä¾åè¿æå°äºå½åçclassloader chainçæ åµï¼ä»¥ä¾¿è¿ä¸æ¥çåæãè¿ä¸ªæå°ä¿¡æ¯å¯¹ä½ 以ååææ¤ç±»é®é¢ä¹å¾æ帮å©çï¼
ç¨åº
Java代ç æ¶è代ç
public class NoClassDefFoundErrorSimulator {
public static void main(String[] args) {
System.out
.println("java.lang.NoClassDefFoundError Simulator");
// Print current Classloader context
System.out.println("\nCurrent ClassLoader chain: "
+ ClassloaderUtil.getCurrentClassloaderDetail());
// 1. Create a new instance of CallerClassA
CallerClassA caller = new CallerClassA();
// 2. Execute method of the caller
caller.doSomething();
System.out.println("done!");
}
}
Java代ç æ¶è代ç
public class CallerClassA {
private final static String CLAZZ = CallerClassA.class.getName();
static {
System.out.println("Classloading of " + CLAZZ + " in progress..."
+ ClassloaderUtil.getCurrentClassloaderDetail());
}
public CallerClassA() {
System.out.println("Creating a new instance of "
+ CallerClassA.class.getName() + "...");
}
public void doSomething() {
// Create a new instance of ReferencingClassA
ReferencingClassA referencingClass = new ReferencingClassA();
}
}
Java代ç æ¶è代ç
public class ReferencingClassA {
private final static String CLAZZ = ReferencingClassA.class.getName();
static {
System.out.println("Classloading of " + CLAZZ + " in progress..."
+ ClassloaderUtil.getCurrentClassloaderDetail());
}
public ReferencingClassA() {
System.out.println("Creating a new instance of "
+ ReferencingClassA.class.getName() + "...");
Maps.newHashMap();
}
public void doSomething() {
// nothing to do...
}
}
æå°classloaderå·¥å ·ç±»ï¼
Java代ç æ¶è代ç
public class ClassloaderUtil {
public static String getCurrentClassloaderDetail() {
StringBuffer classLoaderDetail = new StringBuffer();
Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();
ClassLoader currentClassLoader = Thread.currentThread()
.getContextClassLoader();
classLoaderDetail
.append("\n-----------------------------------------------------------------\n");
// Build a Stack of the current ClassLoader chain
while (currentClassLoader != null) {
classLoaderStack.push(currentClassLoader);
currentClassLoader = currentClassLoader.getParent();
}
// Print ClassLoader parent chain
while (classLoaderStack.size() > 0) {
ClassLoader classLoader = classLoaderStack.pop();
// Print current
classLoaderDetail.append(classLoader);
if (classLoaderStack.size() > 0) {
classLoaderDetail.append("\n--- delegation ---\n");
} else {
classLoaderDetail.append(" **Current ClassLoader**");
}
}
classLoaderDetail
.append("\n-----------------------------------------------------------------\n");
return classLoaderDetail.toString();
}
}
æ£å¸¸è¿è¡ï¼
Java代ç æ¶è代ç
java -classpath .;../guava-.0.jar NoClassDefFoundError.NoClassDefFoundErrorSimulator
java.lang.NoClassDefFoundError Simulator
Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Creating a new instance of NoClassDefFoundError.CallerClassA...
Classloading of NoClassDefFoundError.ReferencingClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Creating a new instance of NoClassDefFoundError.ReferencingClassA...
done!
å¼å¸¸éç°ï¼
Java代ç æ¶è代ç
java -classpath . NoClassDefFoundError.NoCl
java.lang.NoClassDefFoundError Simulator
Current ClassLoader chain:
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Creating a new instance of NoClassDefFoundError.CallerClassA...
Classloading of NoClassDefFoundError.ReferencingClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-----------------------------------------------------------------
Creating a new instance of NoClassDefFoundError.ReferencingClassA...
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Maps
at NoClassDefFoundError.ReferencingClassA.<init>(ReferencingClassA.java:)
at NoClassDefFoundError.CallerClassA.doSomething(CallerClassA.java:)
at NoClassDefFoundError.NoClassDefFoundErrorSimulator.main(NoClassDefFoundErrorSimulator.jav
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps
at java.net.URLClassLoader$1.run(URLClassLoader.java:)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:)
at java.lang.ClassLoader.loadClass(ClassLoader.java:)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:)
at java.lang.ClassLoader.loadClass(ClassLoader.java:)
... 3 more
åçäºä»ä¹ï¼å½ä½ å¨classpathä¸ä¸å å«guavaçå¼ç¨çæ¶åï¼ç±äºReferencingClassAå¨è¿è¡æå¼ç¨äºæ¤ç±»ï¼å¯¼è´äºclassloaderæ¥åæ¾ä¸å°æ¤ç±»ï¼ä»èåºç°NoClassDefFoundErrorã
classloaderåæ
注æï¼
Java代ç æ¶è代ç
Classloading of NoClassDefFoundError.CallerClassA in progress...
-----------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader@addbf1
--- delegation ---
sun.misc.Launcher$AppClassLoader@f **Current ClassLoader
**-------------------------
sun.misc.Launcher$AppClassLoaderæ¯ç³»ç»çclassloaderï¼è´è´£æ ¹æ®classpath设置å¨å¯å¨çæ¶åå è½½åºç¨éè¦çclassã
sun.misc.Launcher$ExtClassLoaderæ¯æ©å±classloaderï¼è´è´£ä»java_home/lib/etc以åå ¶ä»ä½¿ç¨java.ext.dirsé ç½®çç®å½ä»å è½½æ©å±java classã
ä»æå°ç»æå¯ä»¥çåºï¼sun.misc.Launcher$ExtClassLoaderæ¯ç³»ç»classloaderçå®é ç¶ç±»ã
建议å¤ççç¥
åæå¼å¸¸å æ ï¼æ¾å°ç¼ºå°çjavaç±»å称ï¼å¨classpathä¸éªè¯ï¼ç¡®ä¿ç¼è¯åè¿è¡æé½è½æ¾å°æ¤ç±»ã
描述一下JVM加载class文件 的原理机制?
Java中的所有类,都需要由类加载器装载到JVM中才能运行。源码类加载器本身也是源码一个类,而它的源码工作就是把class文件从硬盘读取到内存中。在写程序的源码时候,我们几乎不需要关心类的源码信达支付源码加载,因为这些都是源码隐式装载的,除非我们有特殊的源码用法,像是源码反射,就需要显式的源码加载所需要的类。
类装载方式,源码有两种
1.隐式装载,源码 程序在运行过程中当碰到通过new 等方式生成对象时,源码arms 框架源码隐式调用类装载器加载对应的源码类到jvm中,
2.显式装载,源码 通过class.forname()等方法,显式加载需要的类
隐式加载与显式加载的区别:两者本质是一样?
Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是病毒源码查看保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。
Java的类加载器有三个,对应Java的三种类:(java中的类大致分为三种: 1.系统类 2.扩展类 3.由程序员自定义的类 )
Bootstrap Loader // 负责加载系统类 (指的是内置类,像是黄河团队源码String,对应于C#中的System类和C/C++标准库中的类)
|
- - ExtClassLoader // 负责加载扩展类(就是继承类和实现类)
|
- - AppClassLoader // 负责加载应用类(程序员自定义的类)
三个加载器各自完成自己的工作,但它们是如何协调工作呢?哪一个类该由哪个类加载器完成呢?为了解决这个问题,Java采用了委托模型机制。
委托模型机制的工作原理很简单:当类加载器需要加载类的时候,先请示其Parent(即上一层加载器)在其搜索路径载入,如果找不到,免费源码注册才在自己的搜索路径搜索该类。这样的顺序其实就是加载器层次上自顶而下的搜索,因为加载器必须保证基础类的加载。之所以是这种机制,还有一个安全上的考虑:如果某人将一个恶意的基础类加载到jvm,委托模型机制会搜索其父类加载器,显然是不可能找到的,自然就不会将该类加载进来。
我们可以通过这样的代码来获取类加载器:
ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();
注意一个很重要的问题,就是Java在逻辑上并不存在BootstrapKLoader的实体!因为它是用C++编写的,所以打印其内容将会得到null。
前面是对类加载器的简单介绍,它的原理机制非常简单,就是下面几个步骤:
1.装载:查找和导入class文件;
2.连接:
(1)检查:检查载入的class文件数据的正确性;
(2)准备:为类的静态变量分配存储空间;
(3)解析:将符号引用转换成直接引用(这一步是可选的)
3.初始化:初始化静态变量,静态代码块。
这样的过程在程序调用类的静态成员的时候开始执行,所以静态方法main()才会成为一般程序的入口方法。类的构造器也会引发该动作。
java å¦ä½ç解classloader
æ好å¤ä¸è¥¿é½æ¯ç¾ç§ä¸æçï¼æè§å¾æºå¥½ç解çï¼å¦ä¸ï¼
Javaç¨åºï¼classæ件ï¼å¹¶ä¸æ¯æ¬å°çå¯æ§è¡ç¨åºãå½è¿è¡Javaç¨åºæ¶ï¼é¦å è¿è¡JVMï¼Javaèææºï¼ï¼ç¶ååæJava classå è½½å°JVMé头è¿è¡ï¼è´è´£å è½½Java classçè¿é¨åå°±å«åClass Loader.
JVMæ¬èº«å å«äºä¸ä¸ªClassLoader称为Bootstrap ClassLoaderï¼åJVMä¸æ ·ï¼BootstrapClassLoaderæ¯ç¨æ¬å°ä»£ç å®ç°çï¼å®è´è´£å è½½æ ¸å¿JavaClassï¼å³ææjava.*å¼å¤´çç±»ï¼ãå¦å¤JVMè¿ä¼æä¾ä¸¤ä¸ªClassLoaderï¼å®ä»¬é½æ¯ç¨Javaè¯è¨ç¼åçï¼ç±BootstrapClassLoaderå è½½ï¼å ¶ä¸Extension ClassLoaderè´è´£å è½½æ©å±çJavaclassï¼ä¾å¦ææjavax.*å¼å¤´çç±»ååæ¾å¨JREçextç®å½ä¸çç±»ï¼ï¼ApplicationClassLoaderè´è´£å è½½åºç¨ç¨åºèªèº«çç±»ã ããå½è¿è¡ä¸ä¸ªç¨åºçæ¶åï¼JVMå¯å¨ï¼è¿è¡bootstrapclassloaderï¼è¯¥ClassLoaderå è½½javaæ ¸å¿APIï¼ExtClassLoaderåAppClassLoaderä¹å¨æ¤æ¶è¢«å è½½ï¼ï¼ç¶åè°ç¨ExtClassLoaderå è½½æ©å±APIï¼æåAppClassLoaderå è½½CLASSPATHç®å½ä¸å®ä¹çClassï¼è¿å°±æ¯ä¸ä¸ªç¨åºæåºæ¬çå è½½æµç¨ã
InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbinfo.properties");
1.ä¸æ®éç¨åºä¸åçæ¯ï¼Javaç¨åºï¼classæ件ï¼å¹¶ä¸æ¯æ¬å°çå¯æ§è¡ç¨åºãå½è¿è¡Javaç¨åºæ¶ï¼é¦å è¿è¡JVMï¼Javaèææºï¼ï¼ç¶ååæJava classå è½½å°JVMé头è¿è¡ï¼è´è´£å è½½Java classçè¿é¨åå°±å«åClass Loaderãä¸æå«åç±»å è½½å¨ã
Javaèææºä¸å¯ä»¥å®è£ å¤ä¸ªç±»å è½½å¨ï¼ç³»ç»é»è®¤ä¸ä¸ªä¸»è¦ç±»å è½½å¨ï¼æ¯ä¸ªç±»è´è´£å è½½ç¹å®ä½ç½®çç±»ï¼BootStrap,ExtClassLoader,AppClassLoader
ç±»å è½½å¨ä¹æ¯Javaç±»ï¼å ä¸ºå ¶ä»æ¯javaç±»çç±»å è½½å¨æ¬èº«ä¹è¦è¢«ç±»å è½½å¨å è½½ï¼æ¾ç¶å¿ é¡»æ第ä¸ä¸ªç±»å è½½å¨ä¸æ¯ä¸æ¯javaç±»ï¼è¿æ£æ¯BootStrapã
Javaèææºä¸çææç±»è£ è½½å¨éç¨å ·æç¶åå ³ç³»çæ å½¢ç»æè¿è¡ç»ç»ï¼å¨å®ä¾åæ¯ä¸ªç±»è£ è½½å¨å¯¹è±¡æ¶ï¼éè¦ä¸ºå ¶æå®ä¸ä¸ªç¶çº§ç±»è£ è½½å¨å¯¹è±¡æè é»è®¤éç¨ç³»ç»ç±»è£ è½½å¨ä¸ºå ¶ç¶çº§ç±»å è½½ã
2.ç±»å è½½æçæ¯å°ç±»çclassæä»¶è¯»å ¥å å,并为ä¹å建ä¸ä¸ªjava.lang.Class对象,èç³»ç»ä¸ææçç±»,å®ä»¬å®é ä¸ä¹æ¯å¯¹è±¡,称为类对象,å®ä»¬é½æ¯java.lang.Classçå®ä¾,èææºä¸ºæ¯ç§ç±»å管çä¸ä¸ªç¬ä¸æ äºçClass对象,ä¹å°±æ¯è¯´,æ¯ä¸ªç±»(å)é½æä¸ä¸ªClass对象.
3. javaä¸class.forNameåclassLoaderé½å¯ç¨æ¥å¯¹ç±»è¿è¡å è½½ãpropertiesä¸è¬æ¾é 置信æ¯ç,åæ¾çæ¯é®å¼å¯¹æ ¼å¼.å¦userName=root è¿æ ·ä¾¿äºç®¡ç!
jdbcUtil.class å¾å°çæ¯class JdbcUtil ,class对象æ¯java.lang.Class<T>è¿ä¸ªç±»çæç对象,æ¯ä¸ªç±»é½æä¸ä¸ªclass对象
getResourceAsStream(),è¿åçæ¯InputStream 对象,
Propertiesç±»æ¯ç¨æ¥æä½propertiesæ件ç
props.load(in) ,å è½½è¿æ¥,è¿è¡ä¸è¡ä¸è¡ç读å
ç±»å è½½å¨å±äºå¨æçè½½å ¥,å¯ä»¥æé«è¯»åæç.
è¿å¯ä»¥ç¨java.util.ResourceBundleçç±»æ¥è¯»åpropertiesæ件.ResourceBundle.getBundle("æ件å").getString("é®");