Apache Commons BCEL에서 visit class 파일의 바이트 코드
18512 단어 Kotlinjvmapachecommonsbctech
샘플 코드
샘플 코드는 Kotlin 1.4로 작성되었습니다.다음 세 가지 파일을 소개합니다.
build.gralde.kts
Gradle의 dependencies에 추가Apache Commons BCEL.버전 6.5.0을 사용했습니다.
dependencies {
implementation("org.apache.bcel:bcel:6.5.0")
}
ExampleVisitor.kt
Visitor를 만들려면 커넥터org.apache.bcel.classfile.Visitor를 설치합니다.빈 방법으로 이 인터페이스org.apache.bcel.classfile.EmptyVisitor를 실현한 반을 준비했기 때문에 이 EmptyVisitor를 계승하는 것은 매우 쉽다.
import org.apache.bcel.classfile.*
import org.apache.bcel.generic.ConstantPoolGen
import org.apache.bcel.generic.InstructionList
import org.apache.bcel.generic.InvokeInstruction
class ExampleVisitor : EmptyVisitor() {
override fun visitJavaClass(jc: JavaClass) {
println("Class: ${jc.className}")
}
override fun visitField(field: Field) {
println("Field: ${field.name} ${field.signature}")
}
override fun visitMethod(method: Method) {
println("Method: ${method.name}${method.signature}")
}
override fun visitCode(code: Code) {
println("Code:")
// メソッドの中身を表すCodeより下の階層は、Visitorのメソッドとしては用意されていないようなので、InstructionListを使ってアクセスする。
val instructions = InstructionList(code.code)
// 名前を取得する処理ではConstantPoolGenオブジェクトが必要になる。
val constantPoolGen = ConstantPoolGen(code.constantPool)
instructions.forEach { instructionHandle ->
when (val instruction = instructionHandle.instruction) {
// instructionの型に応じて処理を分岐する。
is InvokeInstruction -> {
// 例: メソッド呼び出しの場合
println(" ${instruction.name}: ${instruction.getReferenceType(constantPoolGen)}.${instruction.getMethodName(constantPoolGen)}${instruction.getSignature(constantPoolGen)}")
}
else -> {
// その他の場合
println(" ${instruction.name}")
}
}
}
}
override fun visitInnerClasses(innerClasses: InnerClasses) {
innerClasses.innerClasses.forEach { innerClass ->
println("InnerClass: ${innerClass.toString(innerClasses.constantPool)}")
}
}
}
Main.kt
이 Visitor를 사용해 실제로 계층에 오른 것은org.apache.bcel.classfile.DescendingVisitor이다.org.apache.bcel.classfile.ClassParser 해석된 자바클래스와 Visitor 실례를 사용하여DescendingVisitor 실례를 만들고visit 방법으로 스캔합니다.
import org.apache.bcel.classfile.ClassParser
import org.apache.bcel.classfile.DescendingVisitor
fun main() {
val classParser = ClassParser("/path/to/build/classes/kotlin/main/target/TargetKt.class")
val javaClass = classParser.parse()
val descendingVisitor = DescendingVisitor(javaClass, ExampleVisitor())
descendingVisitor.visit()
}
대상 파일
예를 들어visit 이하 파일
Target.kt
의 구축 결과의class 파일TargetKt.class
.이 샘플 코드는 JDBC URL을 소스 코드에 쓰는 것을 추천하지 않습니다.package target
import org.jdbi.v3.core.Jdbi
import org.jdbi.v3.core.kotlin.mapTo
import java.time.LocalDate
fun main() {
val jdbcUrl = "jdbc:postgresql://localhost:5432/dvdrental?user=postgres&password="
val jdbi = Jdbi.create(jdbcUrl).installPlugins()
jdbi.useHandle<Exception> { handle ->
val sql = "SELECT * FROM customer"
val result = handle.createQuery(sql)
.mapTo<Result>()
.list()
println(result)
}
}
data class Result(
val customerId: Int,
val storeId: Int,
val firstName: String,
val lastName: String,
val createDate: LocalDate,
)
실행 결과
실행 결과는 다음과 같습니다.Kotlin에 정의된main 함수는 하나뿐이지만 TargetKt 클래스에는 두 가지 다른 서명 방법이 있습니다.
실행 결과의 마지막 줄부터 jdbi.useHandle 매개 변수에서 지정한 λ식은 InnerClass로 다른 클래스 파일에 존재합니다.같은 파일에 정의된 데이터classs의Result도 다른 클래스 파일에 있으며 이 실행 결과에 나타나지 않습니다.
Class: target.TargetKt
Method: main()V
Code:
ldc
astore_0
aload_0
invokestatic: org.jdbi.v3.core.Jdbi.create(Ljava/lang/String;)Lorg/jdbi/v3/core/Jdbi;
invokevirtual: org.jdbi.v3.core.Jdbi.installPlugins()Lorg/jdbi/v3/core/Jdbi;
astore_1
aload_1
getstatic
checkcast
invokevirtual: org.jdbi.v3.core.Jdbi.useHandle(Lorg/jdbi/v3/core/HandleConsumer;)V
return
Method: main([Ljava/lang/String;)V
Code:
invokestatic: target.TargetKt.main()V
return
InnerClass: static final (anonymous)=class target.TargetKt$main$1
최후
설치 후에야 비로소 class 파일의 바이트 코드에 존재하는 등급 구조가 유한하고 Visitor 모드를 사용하는 장점이 많지 않다는 것을 알게 되었다.하지만 참고 가치가 있을 수 있으니 남겨두세요.
참고 자료
Reference
이 문제에 관하여(Apache Commons BCEL에서 visit class 파일의 바이트 코드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/orangain/articles/apache-commons-bcel-visitor텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)