jvm 类加载器 和 tomcat类加载器
方法说明getParent() 返回该类加载器的父类加载器。loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。findClass(String name) 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为 final的。resolveClass(Class<?> c) 链接指定的 Java 类。
对于 表 1中给出的方法,表示类名称的 name参数的值是类的二进制名称。需要注意的是内部类的表示,如 com.example.Sample$1和 com.example.Sample$Inner等表示方式。这些方法会在下面介绍类加载器的工作机制时,做进一步的说明。下面介绍类加载器的树状组织结构。
?
代码清单 1演示了类加载器的树状组织结构。
清单 1. 演示类加载器的树状组织结构
????//要先加载相关实体资源(.jar) 再加载查找的资源本身
????protected ResourceEntry findResourceInternal(String name, String path) {
????????//先根据类名从缓存中查找对应资源 ,有则直接返回?
????????ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
????????if (entry != null)
????????????return entry;
????????int contentLength = -1;//资源二进制数据长度
????????InputStream binaryStream = null;//资源二进制输入流
????????int jarFilesLength = jarFiles.length;//classpath中的jar包个数
????????int repositoriesLength = repositories.length;//仓库数(classpath每一段称为repository仓库)
????????int i;
????????Resource resource = null;//加载的资源实体
????????boolean fileNeedConvert = false;
????????//对每个仓库迭代,直接找到相应的entry,如果查找的资源是一个独立的文件,在这个代码块可以查找到相应资源,
????????//如果是包含在jar包中的类,这段代码并不能找出其对应的资源
????????for (i = 0; (entry == null) && (i < repositoriesLength); i++) {
????????????try {
????????????????String fullPath = repositories[i] + path;//仓库路径 加资源路径得到全路径
????????????????Object lookupResult = resources.lookup(fullPath);//从资源库中查找资源
????????????????if (lookupResult instanceof Resource) {
????????????????????resource = (Resource) lookupResult;
????????????????}
????????????????//到这里没有抛出异常,说明资源已经找到,现在构造entry对象
?????????????????if (securityManager != null) {
????????????????????PrivilegedAction dp =
????????????????????????new PrivilegedFindResource(files[i], path);
????????????????????entry = (ResourceEntry)AccessController.doPrivileged(dp);
?????????????????} else {
????????????????????entry = findResourceInternal(files[i], path);//这个方式只是构造entry并给其codebase和source赋值
?????????????????}
?????????????????//获取资源长度和最后修改时间
????????????????ResourceAttributes attributes =
????????????????????(ResourceAttributes) resources.getAttributes(fullPath);
????????????????contentLength = (int) attributes.getContentLength();
????????????????entry.lastModified = attributes.getLastModified();
????????????????//资源找到,将二进制输入流赋给binaryStream
????????????????if (resource != null) {
????????????????????try {
????????????????????????binaryStream = resource.streamContent();
????????????????????} catch (IOException e) {
????????????????????????return null;
????????????????????}
????????????????????//将资源的最后修改时间加到列表中去,代码略去,参加源码?
????????????????}
????????????} catch (NamingException e) {
????????????}
????????}
????????if ((entry == null) && (notFoundResources.containsKey(name)))
????????????return null;
????????//开始从jar包中查找
????????JarEntry jarEntry = null;
????????synchronized (jarFiles) {
????????????if (!openJARs()) {
????????????????return null;
????????????}
????????????for (i = 0; (entry == null) && (i < jarFilesLength); i++) {
????????????????jarEntry = jarFiles[i].getJarEntry(path);//根据路径从jar包中查找资源
????????????????//如果jar包中找到资源,则定义entry并将二进制流等数据赋给entry,同时将jar包解压到workdir.
????????????????if (jarEntry != null) {
????????????????????entry = new ResourceEntry();
????????????????????try {
????????????????????????entry.codeBase = getURL(jarRealFiles[i], false);
????????????????????????String jarFakeUrl = getURI(jarRealFiles[i]).toString();
????????????????????????jarFakeUrl = "jar:" + jarFakeUrl + "!/" + path;
????????????????????????entry.source = new URL(jarFakeUrl);
????????????????????????entry.lastModified = jarRealFiles[i].lastModified();
????????????????????} catch (MalformedURLException e) {
????????????????????????return null;
????????????????????}
????????????????????contentLength = (int) jarEntry.getSize();
????????????????????try {
????????????????????????entry.manifest = jarFiles[i].getManifest();
????????????????????????binaryStream = jarFiles[i].getInputStream(jarEntry);
????????????????????} catch (IOException e) {
????????????????????????return null;
????????????????????}
????????????????????if (antiJARLocking && !(path.endsWith(".class"))) {
????????????????????????//解压jar包代码,参见源码
????????????????????}
????????????????}
????????????}
????????????if (entry == null) {
????????????????synchronized (notFoundResources) {
????????????????????notFoundResources.put(name, name);
????????????????}
????????????????return null;
????????????}
????????????//从二进制流将资源内容读出
????????????if (binaryStream != null) {
????????????????byte[] binaryContent = new byte[contentLength];
????????????????//读二进制流的代码,这里省去,参见源码
????????????????entry.binaryContent = binaryContent;
????????????}
????????}
????????// 将资源加到缓存中
????????synchronized (resourceEntries) {
????????????ResourceEntry entry2 = (ResourceEntry) resourceEntries.get(name);
????????????if (entry2 == null) {
????????????????resourceEntries.put(name, entry);
????????????} else {
????????????????entry = entry2;
????????????}
????????}
????????return entry;
????}
?
?


?
?