Run or debug with QEMU user mode - openjdk-riscv/jdk11u GitHub Wiki

使用QEMU用户模式执行Java二进制文件

由于目前riscv32g的linux系统暂时并不完善,同时为了便于增量调试,推荐采用QEMU的用户模式来运行benchmark及调试。

QEMU的安装过程可以参照交叉编译OpenJDK11 for RV32G(ZERO VM),这里不再赘述。

直接使用命令行执行

如果只是运行java -version ,可使用命令行:

$ /path/to/qemu/bin/qemu-riscv32 -L /path/to/riscv32/sysroot /path/to/jdk/bin/java -version

可以直接执行并正常输出。

但是在运行SPECjvm2008的时候会出现报错:

$ /path/to/qemu/bin/qemu-riscv32 -L /path/to/riscv32/sysroot /path/to/jdk/bin/java -jar SPECjvm2008.jar -ikv -ict -coe startup.helloworld

SPECjvm2008 Base
  Properties file:   none
  Benchmarks:        startup.helloworld

  WARNING: Run will not be compliant.
  Property specjvm.run.checksum.validation must be true for publication.
  Not a compliant sequence of benchmarks for publication.
  Property specjvm.run.initial.check must be true for publication.


--- --- --- --- --- --- --- --- ---

  Benchmark:   startup.helloworld
  Run mode:    static run
  Test type:   single
  Threads:     1
  Iterations:  1
  Run length:  1 operation

Iteration 1 (1 operation) begins: Fri Mar 12 09:34:53 CST 2021
java.lang.RuntimeException: INVALID: Error Running Startup Test
java.lang.RuntimeException: INVALID: Error Running Startup Test
	at spec.benchmarks.startup.Main.harnessMain(Main.java:115)
	at spec.harness.BenchmarkThread.runLoop(BenchmarkThread.java:170)
	at spec.harness.BenchmarkThread.executeIteration(BenchmarkThread.java:82)
	at spec.harness.BenchmarkThread.run(BenchmarkThread.java:59)
Iteration 1 (1 operation) ends:   Fri Mar 12 09:34:53 CST 2021
Iteration 1 (1 operation) result:  **NOT VALID**

Errors in benchmark: startup.helloworld
  [iter=1] Interrupted when joining benchmark thread 0: null
  [iter=1] java.lang.InterruptedException: null
java.base/java.lang.Object.wait(Native Method)
java.base/java.lang.Thread.join(Thread.java:1305)
java.base/java.lang.Thread.join(Thread.java:1380)
spec.harness.ProgramRunner.runIteration(ProgramRunner.java:504)
spec.harness.ProgramRunner.runBenchmark(ProgramRunner.java:348)
spec.harness.ProgramRunner.run(ProgramRunner.java:98)

  [iter=1] Iteration failed.
  [iter=1][bt:1|op:1] java.lang.RuntimeException: INVALID: Error Running Startup Test
Score on startup.helloworld:  **NOT VALID**
使用脚本包裹二进制文件

这里需要写一个shell脚本来包裹一下bin目录下面的二进制文件,并且手动填写里面包含qemu和sysroot,脚本如下:

#!/bin/sh

sysroot=/path/to/riscv32/sysroot
QEMU=/path/to/qemu/bin/qemu-riscv32
JAVA_HOME=/path/to/jdk

cd $JAVA_HOME/bin
for i in `ls|grep -v "\-bak$"`
do 
    if [ -f $i ]
    then
        if [ -f ${i}-bak ]
        then 
            continue
        fi
    echo $i
        mv $i ${i}-bak
        echo "#!/bin/sh" > ${i}
        echo "export JAVA_HOME=$JAVA_HOME" >> ${i}
        echo "$QEMU -L $sysroot \$JAVA_HOME/bin/${i}-bak \"\$@\"" >> ${i}
        chmod +x ${i}
    fi
done

将脚本中的 sysrootQEMU 以及 JAVA_HOME(此处为编译构建生成的的JDK镜像,非源码或者bootJDK)分别修改为具体的目录,随后保存(存储路径无要求)为prepare.sh

赋权并执行脚本:

$ chmod +x prepare.sh 
$ bash prepare.sh 

至此/path/to/jdk/bin/java -version可以直接运行无需在命令行中配置qemusysroot运行SPECjvm2008也可以顺利PASS:

# 先进入到SPECjvm2008目录下
$ cd /path/to/SPECjvm2008
$ /path/to/jdk/bin/java -jar SPECjvm2008.jar -ikv -ict -coe startup.helloworld

SPECjvm2008 Base
  Properties file:   none
  Benchmarks:        startup.helloworld

  WARNING: Run will not be compliant.
  Property specjvm.run.checksum.validation must be true for publication.
  Not a compliant sequence of benchmarks for publication.
  Property specjvm.run.initial.check must be true for publication.


--- --- --- --- --- --- --- --- ---

  Benchmark:   startup.helloworld
  Run mode:    static run
  Test type:   single
  Threads:     1
  Iterations:  1
  Run length:  1 operation

Iteration 1 (1 operation) begins: Fri Mar 12 06:12:15 UTC 2021
Iteration 1 (1 operation) ends:   Fri Mar 12 06:12:19 UTC 2021
Iteration 1 (1 operation) result: 13.91 ops/m

Valid run!
Score on startup.helloworld: 13.91 ops/m

生成报告部分可能会报错,是因为qemu对jdk图形化模块的支持问题,可以忽略。