跳转至

破解 Kotlin 编译器

一般的编译流程

编译器一般由以下几个部分组成:

  • 词法分析器(Lexical Analyzer):也称为扫描器(Scanner),它负责将源代码转化为一系列的记号(tokens)。每一个记号代表源代码中的最小有意义单元,如关键字、标识符、操作符、分隔符等。
  • 语法分析器(Syntax Analyzer):也称为解析器(Parser),它根据词法分析器生成的记号,按照一定的语法规则生成语法树(或称为解析树)。语法树表达了输入程序的语法结构。
  • 语义分析器(Semantic Analyzer):在这一步,编译器检查语法树中是否存在语义错误,比如类型检查、作用域检查等。语义分析可能会生成某种形式的中间表示(Intermediate Representation, IR)。
  • 中间代码生成器(Intermediate Code Generator):将高层的源代码转换为较低层的、机器无关的中间代码。这种中间代码便于优化和翻译成机器码。
  • 代码优化器(Code Optimizer):对中间代码进行优化,目的是提高程序的执行效率或减少代码的占用空间。优化方法包括移除无用代码、进行常量传播、循环优化等。
  • 目标代码生成器(Code Generator):将优化后的中间代码转换为目标机器代码或汇编代码(assembly code)。

Kotlin 编译器如何调试?

java_version="$(findJavaVersion)"
if [[ $java_version -ge 9 ]]; then
    # Workaround the illegal reflective access warning from ReflectionUtil to ResourceBundle.setParent, see IDEA-248785.
    java_args=("${java_args[@]}" "--add-opens" "java.base/java.util=ALL-UNNAMED")
fi

if [ -n "$KOTLIN_RUNNER" ]; then
    java_args=("${java_args[@]}" "-Dkotlin.home=${KOTLIN_HOME}")
    kotlin_app=("${KOTLIN_HOME}/lib/kotlin-runner.jar" "org.jetbrains.kotlin.runner.Main")
else
    [ -n "$KOTLIN_COMPILER" ] || KOTLIN_COMPILER=org.jetbrains.kotlin.cli.jvm.K2JVMCompiler

    if [[ $java_version < 13 ]]; then
        java_args=("${java_args[@]}" "-noverify")
    fi

    declare additional_classpath=""
    if [ -n "$KOTLIN_TOOL" ]; then
        additional_classpath=":${KOTLIN_HOME}/lib/${KOTLIN_TOOL}"
    fi

    kotlin_app=("${KOTLIN_HOME}/lib/kotlin-preloader.jar" "org.jetbrains.kotlin.preloading.Preloader" "-cp" "${KOTLIN_HOME}/lib/kotlin-compiler.jar${additional_classpath}" $KOTLIN_COMPILER)
fi

"${JAVACMD:=java}" $JAVA_OPTS "${java_args[@]}" -cp "${kotlin_app[@]}" "${kotlin_args[@]}"

通过查看 kotlinc 源码可知,org.jetbrains.kotlin.preloading.Preloader 类是编译器的预加载器,它会加载编译器的主类 org.jetbrains.kotlin.cli.jvm.K2JVMCompiler。因此我们修改Preloader类,运行它的main方法,即可启动与调试编译器,示例如下所示:

String[] testArgs = {"-cp",  "./dist/kotlinc/lib/kotlin-compiler.jar", "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler",
                    "./compilerTestData/Test.kt", "-include-runtime",
                    "-d", "./compilerTestData/Test.jar"
            };
            run(testArgs);

最后更新: November 17, 2024