Post

GraalVM Native + Base64 编解码命令行小工具开发

  • 初衷:
    • 浏览 V 站 帖子有很多 Base64 加密的信息,希望能够快速解密。
  • 实现:
    • v1:直接使用 JShell 命令行运行 Java 代码解密

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        ant@ant:~$ jshell 
        |  Welcome to JShell -- Version 17.0.9
        |  For an introduction type: /help intro
              
        jshell> var enc = "c2F2ZW9sZQ=="
        enc ==> "c2F2ZW9sZQ=="
              
        jshell> var decodedBytes = Base64.getDecoder().decode(enc.getBytes())
        decodedBytes ==> byte[8] { 115, 97, 118, 101, 95, 111, 108, 101 }
              
        jshell> new String(decodedBytes)
        $3 ==> "saveole"
      
    • v2:GraalVM Native 的方式将 Java 程序编译打包成可执行文件小工具

      • 原 Java 程序:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        
          import java.util.Base64;
                    
          public class Base64Tool {
              static String helpMsg = """
          		-e Encode input string
          		-d Decode input string 
                      """;;
                        
              public static void main(String[] args) {
                  if (args == null || args.length == 0) {
                      System.err.println(helpMsg);
                      System.exit(1);
                  }
                  var arg = args[0];
                  switch(arg) {
                    case "-help":
                        System.out.println(helpMsg);
                        break;
                    case "-e":
                        var toEncode = getAndCheckArg(args);
                        System.out.println(new String(Base64.getEncoder().encode(toEncode.getBytes())));
                        break;
                    case "-d":
                        var toDecode = getAndCheckArg(args);
                        System.out.println(new String(Base64.getDecoder().decode(toDecode.getBytes())));
                        break;
                    default:
                        System.err.println("Unknown command, use -help to see how to use this tool.");
                        break;
                  }
                  System.exit(1);
              }
                    
              static String getAndCheckArg(String[] args) {
                  if (args == null || args.length < 2) {
                      System.err.println("Please input valid string");
                      System.exit(0);
                  }
                  return args[1];
              }
          }
        
      • 使用 native-image 编译构建可执行程序

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        
          ant@ant:~/native$ javac Base64Tool.java 
          ant@ant:~/native$ native-image Base64Tool
          ========================================================================================================================
          GraalVM Native Image: Generating 'base64tool' (executable)...
          ========================================================================================================================
          [1/8] Initializing...                                                                                    (1.7s @ 0.14GB)
           Java version: 17.0.9+9, vendor version: GraalVM CE 17.0.9+9.1
           Graal compiler: optimization level: 2, target machine: x86-64-v3
           C compiler: gcc (linux, x86_64, 11.4.0)
           Garbage collector: Serial GC (max heap size: 80% of RAM)
          [2/8] Performing analysis...  [****]                                                                     (4.4s @ 0.27GB)
             2,912 (71.67%) of  4,063 types reachable
             3,536 (50.94%) of  6,942 fields reachable
            13,209 (43.86%) of 30,116 methods reachable
               907 types,     0 fields, and   348 methods registered for reflection
                58 types,    58 fields, and    52 methods registered for JNI access
                 4 native libraries: dl, pthread, rt, z
          [3/8] Building universe...                                                                               (0.9s @ 0.30GB)
          [4/8] Parsing methods...      [*]                                                                        (0.6s @ 0.32GB)
          [5/8] Inlining methods...     [***]                                                                      (0.5s @ 0.22GB)
          [6/8] Compiling methods...    [**]                                                                       (4.5s @ 0.35GB)
          [7/8] Layouting methods...    [*]                                                                        (0.7s @ 0.37GB)
          [8/8] Creating image...       [*]                                                                        (1.1s @ 0.38GB)
             4.42MB (36.75%) for code area:     7,506 compilation units
             7.04MB (58.46%) for image heap:   89,275 objects and 5 resources
           590.55kB ( 4.79%) for other data
            12.03MB in total
          ------------------------------------------------------------------------------------------------------------------------
          Top 10 origins of code area:                                Top 10 object types in image heap:
             3.37MB java.base                                         1009.70kB byte[] for code metadata
           795.13kB svm.jar (Native Image)                             889.53kB java.lang.String
           112.32kB java.logging                                       836.32kB byte[] for general heap data
            62.07kB org.graalvm.nativeimage.base                       671.94kB java.lang.Class
            24.15kB jdk.internal.vm.ci                                 665.65kB byte[] for java.lang.String
            23.14kB org.graalvm.sdk                                    347.48kB java.util.HashMap$Node
             6.11kB jdk.internal.vm.compiler                           250.25kB com.oracle.svm.core.hub.DynamicHubCompanion
             1.68kB Base64Tool                                         169.02kB java.lang.String[]
             1.35kB jdk.proxy1                                         165.57kB java.lang.Object[]
             1.27kB jdk.proxy3                                         148.84kB byte[] for embedded resources
             1.56kB for 2 more packages                                  1.20MB for 829 more object types
          ------------------------------------------------------------------------------------------------------------------------
          Recommendations:
           HEAP: Set max heap for improved and more predictable memory usage.
           CPU:  Enable more CPU features with '-march=native' for improved performance.
          ------------------------------------------------------------------------------------------------------------------------
                                  0.7s (4.3% of total time) in 164 GCs | Peak RSS: 0.84GB | CPU load: 8.21
          ------------------------------------------------------------------------------------------------------------------------
          Produced artifacts:
           /home/ant/native/base64tool (executable)
          ========================================================================================================================
          Finished generating 'base64tool' in 14.8s.
        
      • 使用

        1
        2
        3
        4
        5
        6
        7
        8
        9
        
          ant@ant:~/native$ ./base64tool -help
          -e Encode input string
          -d Decode input string
                    
          ant@ant:~/native$ ./base64tool -e saveole
          c2F2ZW9sZQ==
          ant@ant:~/native$ ./base64tool -d c2F2ZW9sZQ==
          saveole
          ant@ant:~/native$ 
        
  • 注意事项
    • 使用 native-image 构建可执行程序时,需要注意当前的执行目录。它默认会扫描当前目录及子目录下的所有文件(不能区分 Java 程序相关的文件),导致构建失败。建议在单独的文件夹中进行编译构建。
This post is licensed under CC BY 4.0 by the author.