作用:文件查找的快速拒絕機制
public class MetaIndex {
private static volatile Map<File, MetaIndex> jarMap;
private String[] contents;
// 是否是隻包含 class 的 jar 包
private boolean isClassOnlyJar;
public static MetaIndex forJar(File jar) {
return getJarMap().get(jar);
}
public static synchronized void registerDirectory(File dir) {
// $JAVA_HOME/jre/lib/meta-index
File indexFile = new File(dir, "meta-index");
if (indexFile.exists()) {
try {
BufferedReader reader = new BufferedReader(new FileReader(indexFile));
String line = null;
String curJarName = null;
boolean isCurJarContainClassOnly = false;
List<String> contents = new ArrayList<String>();
Map<File, MetaIndex> map = getJarMap();
dir = dir.getCanonicalFile();
line = reader.readLine();
if (line == null || !line.equals("% VERSION 2")) {
reader.close();
return;
}
while ((line = reader.readLine()) != null) {
switch (line.charAt(0)) {
case '!':
case '#':
case '@': {
if ((curJarName != null) && (contents.size() > 0)) {
map.put(new File(dir, curJarName), new MetaIndex(contents, isCurJarContainClassOnly));
contents.clear();
}
// 當前處理的 jar 包
curJarName = line.substring(2);
// ! 代表當前 jar 只包含 class 文件
if (line.charAt(0) == '!') {
isCurJarContainClassOnly = true;
} else if (isCurJarContainClassOnly) {
isCurJarContainClassOnly = false;
}
break;
}
// % 代表註釋
case '%':
break;
default: {
contents.add(line);
}
}
}
// 處理最後一個 curJarName 對應的包名
if ((curJarName != null) && (contents.size() > 0)) {
map.put(new File(dir, curJarName), new MetaIndex(contents, isCurJarContainClassOnly));
}
reader.close();
} catch (IOException e) {
//
}
}
}
public boolean mayContain(String entry) {
// 從只有 class 的 jar 包查找非 class 文件返回 false
if (isClassOnlyJar && !entry.endsWith(".class")) {
return false;
}
String[] conts = contents;
for (int i = 0; i < conts.length; i++) {
// 可以看到是通過前綴匹配
if (entry.startsWith(conts[i])) {
return true;
}
}
return false;
}
// 私有構造方法
private MetaIndex(List<String> entries, boolean isClassOnlyJar) throws IllegalArgumentException {
if (entries == null) {
throw new IllegalArgumentException();
}
contents = entries.toArray(new String[0]);
this.isClassOnlyJar = isClassOnlyJar;
}
// dck
private static Map<File, MetaIndex> getJarMap() {
if (jarMap == null) {
synchronized (MetaIndex.class) {
if (jarMap == null) {
jarMap = new HashMap<File, MetaIndex>();
}
}
}
assert jarMap != null;
return jarMap;
}
}
cat /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre/lib/meta-index
For jar file containing only class file, we put '!' before the jar file name;
for jar file containing only resources file, we put '@' before the jar file name;
for jar file containing both resources and class file, we put '#' before the jar name.
% VERSION 2
% WARNING: this file is auto-generated; do not edit
% UNSUPPORTED: this file and its format may change and/or
% may be removed in a future release
# charsets.jar
sun/nio
sun/awt
# jce.jar
javax/crypto
sun/security
META-INF/ORACLE_J.RSA
META-INF/ORACLE_J.SF
# jfr.jar
oracle/jrockit/
jdk/jfr
com/oracle/jrockit/
! jsse.jar
sun/security
com/sun/net/
! management-agent.jar
@ resources.jar
com/sun/java/util/jar/pack/
META-INF/services/sun.util.spi.XmlPropertiesProvider
META-INF/services/javax.print.PrintServiceLookup
com/sun/corba/
META-INF/services/javax.sound.midi.spi.SoundbankReader
sun/print
META-INF/services/javax.sound.midi.spi.MidiFileReader
META-INF/services/sun.java2d.cmm.CMMServiceProvider
javax/swing
META-INF/services/javax.sound.sampled.spi.AudioFileReader
META-INF/services/javax.sound.midi.spi.MidiDeviceProvider
sun/net
META-INF/services/javax.sound.sampled.spi.AudioFileWriter
com/sun/imageio/
META-INF/services/sun.java2d.pipe.RenderingEngine
META-INF/mimetypes.default
META-INF/services/javax.sound.midi.spi.MidiFileWriter
sun/rmi
javax/sql
META-INF/services/com.sun.tools.internal.ws.wscompile.Plugin
com/sun/rowset/
META-INF/services/javax.print.StreamPrintServiceFactory
META-INF/mailcap.default
java/lang
sun/text
javax/xml
META-INF/services/javax.sound.sampled.spi.MixerProvider
com/sun/xml/
META-INF/services/com.sun.tools.internal.xjc.Plugin
com/sun/java/swing/
com/sun/jndi/
com/sun/org/
META-INF/services/javax.sound.sampled.spi.FormatConversionProvider
! rt.jar
com/sun/java/util/jar/pack/
java/
org/ietf/
com/sun/beans/
com/sun/tracing/
apple/launcher/
com/sun/java/browser/
com/sun/corba/
com/sun/media/
com/sun/awt/
com/sun/management/
sun/
apple/applescript/
com/sun/jmx/
com/sun/demo/
apple/security/
com/sun/imageio/
com/sun/rmi/
com/sun/net/
org/w3c/
com/sun/swing/
com/sun/activation/
apple/laf/
com/sun/nio/
com/sun/rowset/
org/jcp/
com/sun/istack/
jdk/
com/sun/naming/
org/xml/
org/omg/
com/sun/security/
com/sun/image/
com/sun/xml/
com/oracle/
com/sun/java/swing/
com/sun/java_cup/
com/sun/jndi/
com/apple/
com/sun/accessibility/
com/sun/org/
javax/