Java 코드를 DEX로 변환, 안드로이드 디바이스에서 실행

Java 코드를 DEX(Dalvik EXecutable)로 변환하고 이것을 안드로이드 디바이스에서 실행하는 방법에 대해서 알아봅니다.

정확하게 말하면, 다음 순서로 파일을 변환해야 디바이스에서 실행할 수 있습니다.

  1. Java 코드를 class 파일로 컴파일
  2. class 파일을 JAR 파일로 변환
  3. dx 툴을 이용하여 JAR 파일을 Dex로 변환
  4. classes.dex를 ZIP으로 압축
  5. ZIP 파일을 디바이스에서 실행

JVM vs DVM(or ART)

Java를 Dex로 변환하기 전에, JVM과 DVM의 차이에 대해서 알아보겠습니다.

JVM(Java Virtual Machine)은 .class 파일을 읽고 실행할 수 있습니다. Java 코드를 컴파일하면 bytecode로 변환되며, .class 파일에 저장이 됩니다. 즉, .class 파일은 bytecode들로 이루어져 있습니다. bytecode는 JVM(Java Virtual Machine)이 실행할 수 있는 명령어들입니다.

반면에 안드로이드는 JVM이 없고 DVM(Dalvik Virtual Machine)이 있습니다. DVM은 .class 파일을 읽지 못하고 .dex 파일을 읽고 실행할 수 있습니다. 안드로이드 스튜디오로 Java 코드를 컴파일하면 Dalvik bytecode로 변환되며 .dex 파일에 저장이 됩니다. 즉, .dex는 Dalvik bytecode로 이루어져 있습니다. Dalvik bytecode는 DVM이 실행할 수 있는 명령어들입니다.

Java 코드를 class 파일로 컴파일

다음과 같이 간단한 자바 프로그램을 작성합니다. 파일 이름은 HelloWorld.java로 만드시면 됩니다.

public class HelloWorld {
    public static void main(String[] args){
        System.out.println("This is my first program in java");
    }
}

먼저 다음과 같이 PC에서 javac로 컴파일할 수 있습니다. HelloWorld.class 파일이 생성되는 것을 볼 수 있습니다.

$ javac HelloWorld.java
$ ls
HelloWorld.class  HelloWorld.java

그리고 다음과 같이 실행할 수 있습니다.

$ java HelloWorld
This is my first program in java

class 파일을 JAR 파일로 변환

Android SDK에서 제공하는 dx라는 툴을 이용하면 JAR(Java ARchive) 파일을 dex파일로 변환할 수 있습니다. 그래서 먼저 .class로 컴파일된 파일들을 .jar 형태로 변환해야 합니다.

다음과 같이 jar cvf [output file name] [class file name] 명령어를 사용하면 .class파일을 .jar 파일로 변환할 수 있습니다. *.class는 현재 디렉토리에 있는 모든 .class 파일을 선택하기 위한 명령어입니다.

$ jar cvf HelloWorld.jar *.class
added manifest
adding: HelloWorld.class(in = 446) (out= 307)(deflated 31%)
$ ls
HelloWorld.class  HelloWorld.jar  HelloWorld.java

HelloWorld.jar 파일이 생성된 것을 확인할 수 있습니다.

dx 툴을 이용하여 JAR 파일을 Dex로 변환

이제 dx 툴을 이용하여 .jar 파일을 .dex로 변환해야 합니다.

dx는 Android SDK의 build-tools 아래에 있습니다. 저는 SDK 경로를 PATH에 추가했기 때문에 리눅스에서 which 명령어로 확인해보면 다음과 같은 디렉토리에 존재하는 것을 확인할 수 있습니다.

$ which dx
~/Android/Sdk/build-tools/29.0.0-rc3/dx

다음과 같은 명령어를 입력하면 .jar파일이 classes.dex 파일로 변환이 됩니다. .dex 파일의 이름은 classes.dex로 설정하시는 것이 좋습니다.

$ dx --dex --output=classes.dex HelloWorld.jar
$ ls
classes.dex  HelloWorld.class  HelloWorld.jar  HelloWorld.java

classes.dex를 ZIP으로 압축

안드로이드에서 classes.dex를 실행하려면 ZIP으로 압축해줘야 합니다.

다음과 같은 명령어를 사용하면 classes.dex를 ZIP으로 압축하여 HelloWorld.zip 파일로 만들어 줍니다.

$ zip HelloWorld.zip classes.dex
  adding: classes.dex (deflated 43%)
$ ls
HelloWorld.class  HelloWorld.jar  HelloWorld.java  HelloWorld.zip

ZIP 파일에서 classes.dex는 가장 최상위 디렉토리에 위치하면 됩니다. 다음과 같이 압축을 풀어서 상위에 위치하는지 확인할 수 있습니다.

$ unzip HelloWorld.zip -d out
$ tree out/
out/
└── classes.dex

ZIP 파일을 디바이스에서 실행

위에서 만든 HelloWorld.zip을 실행하려면 먼저 디바이스에 저장해야 합니다. 다음과 같이 adb 명령어로 /sdcard에 복사합니다.

$ adb push HelloWorld.zip /sdcard

그리고 다음과 같이 shell에서 dalvikvm을 이용하여 프로그램을 실행시킬 수 있습니다. 아래 명령어는 HelloWorld.zip에 있는 classes.dex에서 HelloWorld라는 클래스를 찾아서 실행시키라는 의미입니다.

$ adb shell dalvikvm -cp /sdcard/HelloWorld.zip HelloWorld
This is my first program in java

이 글에서는 dex파일을 HelloWorld.zip 라는 이름으로 압축했습니다. 사실 확장자는 중요하지 않습니다. .apk로 변경해도 됩니다.

또는 shell에서 app_process를 이용하여 프로그램을 실행시킬 수도 있습니다. 먼저 export로 클래스 패스를 설정하고 app_process으로 HelloWorld 클래스를 실행시킬 수 있습니다.

$ adb shell
generic_x86_arm:/ $ export CLASSPATH=/sdcard/HelloWorld.zip
generic_x86_arm:/ $ app_process / HelloWorld
This is my first program in java

정리

순수한 Java 코드를 .dex로 변환하여 Android에서 DVM으로 실행하는 방법을 알아보았습니다. 이런 작업은 Android Studio가 알아서 해주기 때문에 알 필요는 없습니다. 하지만 Android에서 Java 코드가 어떻게 컴파일되서 실행되는지 원리를 이해하는데 도움이 될 수 있습니다.

참고

Loading script...

Related Posts

codechachaCopyright ©2019 codechacha