In diesem Eintrag werde ich eine Notiz hinterlassen, was ich versucht habe:
Was ich geschrieben habe, ist GitHub [https://github.com/hrkt/gohatto-j/releases/tag/0.0.1-qiita](https://github.com/hrkt/gohatto-j/releases/tag/ Ich habe es in 0.0.1-Qiita) gesetzt.
――Der Leser ist für die Programmierausbildung mit Java verantwortlich, und der Auszubildende muss eine JAR-Datei der Übung einreichen und den Vorgang überprüfen.
Es gibt eine Klasse namens JarFile, daher werde ich diese Kraft nutzen.
Die Aufzählung
try (JarFile jarFile = new JarFile(jarFilePath)) {
val e = jarFile.entries();
val urls = new URL[]{new URL("jar:file:" + jarFilePath + "!/")};
val ucl = URLClassLoader.newInstance(urls);
val repository = new ClassLoaderRepository(ucl);
return Collections.list(e).stream()
.filter(je -> !je.isDirectory())
.filter(je -> je.getName().endsWith(".class"))
.flatMap(je -> check(repository, je).stream())
BCEL
Die Java-Standardfunktion Reflection benötigt diese Zeit. Sie können keine Informationen wie die Klasse abrufen, auf die sich der Code in der Klassendatei bezieht (nachdem er in Bytecode kompiliert wurde).
Daher verwenden wir Apache Commons BCEL, eine Bibliothek für den Umgang mit Java-Bytecode.
Verwenden Sie die Commons JavaClass-Klasse, um die vom Java-Klassenladeprogramm oben erhaltene Klasse zu laden und den darin enthaltenen Bytecode anzuzeigen. Insbesondere BCELs "ConstantPool" (= analysierte Klassendatei) Untersuchen Sie die Zeichenfolge in der Liste der Konstanten in).
Ich habe den folgenden Code geschrieben, eine JAR-Datei erstellt und es versucht.
package io.hrkt;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("message", "Hello");
System.out.println(map.get("message"));
}
}
Wenn Sie zu diesem Zeitpunkt den konstanten Pool in BCEL ausschließen, können Sie die folgende Liste abrufen.
CONSTANT_Methodref[10](class_index=12,name_and_type_index=30)
CONSTANT_Class[7](name_index=31)
CONSTANT_Methodref[10](class_index=2,name_and_type_index=30)
CONSTANT_String[8](string_index=32)
CONSTANT_String[8](string_index=33)
CONSTANT_InterfaceMethodref[11](class_index=34,name_and_type_index=35)
CONSTANT_Fieldref[9](class_index=36,name_and_type_index=37)
CONSTANT_InterfaceMethodref[11](class_index=34,name_and_type_index=38)
CONSTANT_Class[7](name_index=39)
CONSTANT_Methodref[10](class_index=40,name_and_type_index=41)
CONSTANT_Class[7](name_index=42)
CONSTANT_Class[7](name_index=43)
CONSTANT_Utf8[1]("<init>")
CONSTANT_Utf8[1]("()V")
CONSTANT_Utf8[1]("Code")
CONSTANT_Utf8[1]("LineNumberTable")
CONSTANT_Utf8[1]("LocalVariableTable")
CONSTANT_Utf8[1]("this")
CONSTANT_Utf8[1]("Lio/hrkt/Main;")
CONSTANT_Utf8[1]("main")
CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
CONSTANT_Utf8[1]("args")
CONSTANT_Utf8[1]("[Ljava/lang/String;")
CONSTANT_Utf8[1]("map")
CONSTANT_Utf8[1]("Ljava/util/Map;")
CONSTANT_Utf8[1]("LocalVariableTypeTable")
CONSTANT_Utf8[1]("Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>;")
CONSTANT_Utf8[1]("SourceFile")
CONSTANT_Utf8[1]("Main.java")
CONSTANT_NameAndType[12](name_index=13,signature_index=14)
CONSTANT_Utf8[1]("java/util/HashMap")
CONSTANT_Utf8[1]("message")
CONSTANT_Utf8[1]("Hello")
CONSTANT_Class[7](name_index=44)
CONSTANT_NameAndType[12](name_index=45,signature_index=46)
CONSTANT_Class[7](name_index=47)
CONSTANT_NameAndType[12](name_index=48,signature_index=49)
CONSTANT_NameAndType[12](name_index=50,signature_index=51)
CONSTANT_Utf8[1]("java/lang/String")
CONSTANT_Class[7](name_index=52)
CONSTANT_NameAndType[12](name_index=53,signature_index=54)
CONSTANT_Utf8[1]("io/hrkt/Main")
CONSTANT_Utf8[1]("java/lang/Object")
CONSTANT_Utf8[1]("java/util/Map")
CONSTANT_Utf8[1]("put")
CONSTANT_Utf8[1]("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
CONSTANT_Utf8[1]("java/lang/System")
CONSTANT_Utf8[1]("out")
CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
CONSTANT_Utf8[1]("get")
CONSTANT_Utf8[1]("(Ljava/lang/Object;)Ljava/lang/Object;")
CONSTANT_Utf8[1]("java/io/PrintStream")
CONSTANT_Utf8[1]("println")
CONSTANT_Utf8[1]("(Ljava/lang/String;)V")
Von den in ConstantPool enthaltenen Zeichenfolgen werden diejenigen extrahiert, deren Tag eine Klassendatei angibt.
JavaClass clazz = null;
try {
clazz = repository.loadClass(fqcn);
val cp = clazz.getConstantPool();
int cpLength = cp.getLength();
val referencedClasses = new ArrayList<ConstantUtf8>();
IntStream.range(0, cpLength).forEach(i -> {
val constant = cp.getConstant(i);
if (null == constant || !(constant instanceof ConstantClass)) {
// do nothing
} else {
val constantClass = (ConstantClass) constant;
val referencedConstant = cp.getConstant(constantClass.getNameIndex());
referencedClasses.add((ConstantUtf8) referencedConstant);
}
});
val tc = referencedClasses.stream()
.map(c -> c.getBytes())
.map(s -> s.replace("/", "."))
.collect(Collectors.toList());
return tc;
} catch (ClassNotFoundException e) {
throw new GohattoApplicationException(e);
}
Dieses Mal wird es ermittelt, indem es mit dem Paketnamen abgeglichen wird, der in der Einstellungsdatei für das Textformat enthalten ist.
Wie Sie anhand des Codes sehen können, handelt es sich lediglich um einen Vergleich mit regulären Ausdrücken.
Wenn Sie eine solche Datei vorbereiten, wird sie als Fehler erkannt, wenn "java.util oder com.sun verwendet wird".
java.util
com.sun
Wenn Sie eine solche Datei vorbereiten, wird sie als Fehler erkannt, "wenn Sie etwas anderes als java.lang oder java.io verwenden".
^(?!java.lang|java.io)
Im folgenden Beispiel wird die Quelle im Repository verwendet.
Wenn bei der Ausführung als Befehl Code vorhanden ist, der keine Java-Paketreferenz zulässt, wird ein Fehlerprotokoll wie das unten gezeigte an die Standardausgabe ausgegeben.
$ java -jar build/libs/gohatto-j-0.0.1-SNAPSHOT-all.jar --jar src/test/resources/testproject.jar --forbiddenPackageList src/test/resources/rule_forbid_jav-util_and_com-sun.txt
[main] INFO io.hrkt.gohatto.Gohatto - ERROR DoNotUseForbiddenPackage java.util.HashMap violates rule
[main] INFO io.hrkt.gohatto.Gohatto - ERROR DoNotUseForbiddenPackage java.util.Map violates rule
[main] INFO io.hrkt.gohatto.Gohatto - rules applied to: 2
In der "Gohatto" -Klasse im oben genannten Repository, das der Eingang zur Prüffunktion ist,
String resDir = "src/test/resources/";
Gohatto gohatto = new Gohatto();
gohatto.init(resDir + "testproject.jar", resDir + "rule_forbid_jav-util_and_com-sun.txt");
List<Result> ret = gohatto.executeRules();
Assert.assertTrue(ret.size() == 0);
Ich habe Ihnen gezeigt, wie Sie die JAR-Datei lesen und das Paket der vorherigen Klasse überprüfen, auf die die Klasse darin verweist.
Der Arbeitscode wird im Repository gespeichert. Bitte beziehen Sie sich darauf.
Recommended Posts