Jar 파일은 zip으로 압축이 되어있습니다. 이 압축을 풀면 많은 .class
파일들이 있습니다.
class 파일은 Java 파일을 바이트코드로 컴파일하면서 생성되는 산출물입니다.
class 파일을 열면 Java 코드가 보이지 않기 때문에, 보고 싶다면 Java로 다시 디컴파일해야 합니다.
decompile하는 방법은 여러가지가 있지만, 여기서는 다음 두가지 방법을 소개하겠습니다.
- IntelliJ IDE에서 디컴파일하는 방법
- jd-cli 툴을 이용하여 디컴파일하는 방법
1. IntelliJ IDE에서 디컴파일하는 방법
.class
파일을 Java 파일로 디컴파일 하는 가장 쉬운 방법 중 하나는 IntelliJ를 이용하는 방법입니다.
IntelliJ를 사용하는 경우 .class
파일을 Drag-and-drop 하여 IDE 창에 올려두기만 하면 자동으로 Java로 디컴파일됩니다.
2. jd-cli 툴을 이용하여 디컴파일하는 방법
class 파일을 Java로 decompile해주는 jd-cli
라는 툴이 있습니다. Jar 파일 안에 있는 모든 class 파일을 Java로 변환해주기 때문에 편리합니다.
jd-cli 툴은 GitHub - Jd-cmd에서 다운받을 수 있습니다.
저는 설치파일을 ~/apps/jd-cli-0.9.2-dist/
경로에 압축을 풀어 저장하였습니다.
그럼 다음과 같이 jd-cli.jar 명령어를 실행할 수 있습니다. 명령어의 인자로 디컴파일하고 싶은 jar 파일과 변환된 파일이 저장되는 위치를 입력하면 됩니다.
$ java -jar jd-cli.jar [jar file] -od [output folder]
저의 경우, 다음과 같은 명령어로 디컴파일 할 수 있습니다. output
폴더를 보시면 java 파일로 디컴파일된 것을 확인할 수 있습니다.
java -jar ~/apps/jd-cli-0.9.2-dist/jd-cli.jar android.jar -od output
$ jd-cli android.jar -od output
09:13:41.923 INFO jd.cli.Main - Decompiling android.jar
09:13:41.925 INFO jd.core.output.DirOutput - Directory output will be initialized for path output
09:13:46.225 INFO jd.core.output.DirOutput - Finished with 4751 class file(s) and 7594 resource file(s) written.
class 파일 1개만 디컴파일
jd-cli는 jar 뿐만 아니라 class파일을 Java로 변환해주는 명령어도 있습니다.
- java -jar jd-cli.jar [class file] : class파일을 java로 변환하여 화면에 출력합니다.
- java -jar jd-cli.jar [class file] -od [output folder] : class파일을 java로 변환하여 ouput folder에 저장합니다.
다음과 같이 사용할 수 있습니다.
$ java -jar jd-cli.jar AbstractCollection.class
09:32:37.885 INFO jd.cli.Main - Decompiling /home/mjs/Desktop/android/java/util/AbstractCollection.class
package java.util;
import androidx.annotation.RecentlyNonNull;
import androidx.annotation.RecentlyNullable;
public abstract class AbstractCollection<E>
....
alias (For linux user)
매번 명령어를 입력하면 번거롭기 때문에 ~/.bashrc
에 아래처럼 명령어를 alias로 등록할 수 있습니다.
$ alias jd-cli='java -jar ~/apps/jd-cli-0.9.2-dist/jd-cli.jar'
alias를 등록하면 다음과 같이 짧은 명령어로 디컴파일할 수 있습니다.
$ jd-cli android.jar -od output
Related Posts
- Java - 람다식(Lambda)과 함수형 인터페이스
- Java - 직렬화(Serialize), 역직렬화(Deserialize)
- Java - do while과 while의 차이점
- Java - List empty(null) 체크, 3가지 방법
- Java - ArrayList 초기화, 4가지 방법
- Java - HashSet.addAll()
- Java - HashSet.contains()
- Java - 2차원 배열 선언, 출력 방법
- Java - 리스트 정렬, 3가지 방법
- Java - HashSet 정렬, 3가지 방법
- Java - 리스트 (List, ArrayList)
- Java - 첫 글자만 대문자로 바꾸는 방법
- Java - hashCode(), 사용하는 이유? 구현 방법?
- Java8의 Stream reduce() 사용 방법 및 예제
- Java - filter, map, flatMap 사용 방법 및 예제
- Java - 2개의 Map 합치기 (merge, putAll)
- Java - ConcurrentModificationException 원인 및 해결 방법
- JUnit - @After와 @AfterClass의 차이점
- JUnit - @Before와 @BeforeClass의 차이점
- java와 javac의 차이점
- Java - 자바(JDK) 버전 확인 방법 (터미널, cmd 명령어)
- Java - java.util.Date를 java.sql.Date로 변환
- Java - 시스템 운영체제(OS) 정보 확인
- Java - 코드 실행 시간 측정
- Java - HashSet.retainAll() 사용 방법 및 예제
- Java - ArrayList.retainAll() 사용 방법 및 예제
- Java - ArrayList를 String으로 변환
- Java - float을 int로 변환
- Java - float을 String으로 변환
- Java - String을 boolean으로 변환
- Java - XML을 JSON으로 변환
- Java - ClassNotFoundException 발생 원인 및 해결 방법
- Java - private 생성자를 사용하는 이유
- Java - non-static method cannot be referenced from a static context
- Java - NoSuchMethodError 원인 및 해결 방법