loadClass:
|
|
|
findResouceInternal():
//要先加载相关实体资源(.jar) 再加载查找的资源本身
protected ResourceEntry findResourceInternal(String name, Stringpath) {
//先根据类名从缓存中查找对应资源 ,有则直接返回
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赋值
}
//获取资源长度和最后修改时间
ResourceAttributesattributes = (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);
StringjarFakeUrl = 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 = newbyte[contentLength]; //读二进制流的代码,这里省去,参见源码 entry.binaryContent =binaryContent; } } // 将资源加到缓存中 synchronized (resourceEntries) {ResourceEntry entry2 = (ResourceEntry) resourceEntries.get(name);if (entry2 == null) { resourceEntries.put(name, entry); } else {entry = entry2; } } return entry; }