Java JNI 를 활용하여 윈도우 운영체제 dll 동적 라이브러리 사용하기, 컴파일 방법 - Whitmem
Java JNI 를 활용하여 윈도우 운영체제 dll 동적 라이브러리 사용하기, 컴파일 방법
Java Language
2025-04-26 16:07 게시 c75c8c63cf061a44b831

0
0
15
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
Java 소프트웨어를 개발하다보면 윈도우 운영체제와 긴밀하게 소통해야 할 상황이 올 때가 존재한다. 특히 Java 는 아무래도 크로스 플랫폼이 가능한 소프트웨어이다 보니, 운영체제 저수준 단계의 조작이 불가능한 경우가 많다. 예를 들어 운영체제 자체의 API를 사용한다든지 등 자바 자체 머신에서 제공하지 않는 경우 시스템과 연동을 해야하는데 이 때 대표적으로 사용하는 것이 Java JNI 이다.
Java JNI 는 윈도우 운영체제나 특정 시스템의 DLL 라이브러리를 불러오도록 도와주는 도구인데, 안타깝게도 C/C++ 운영체제용 네이티브 dll 은 로드할 수 없다.
Java 가 제공하는 JNI 이라는 도구를 통해서 dll 헤더를 만들고, JNI 용 내부 헤더를 인클루드하여 빌드해야지 Java에서 사용할 수 있는 dll 이 완성된다.
JNI 헤더 생성 생성
먼저 JNI 헤더를 생성하기 위해서는 자바 컴파일러가 JNI 헤더를 생성할 수 있는 조건의 클래스 환경을 만들어줘야 한다.
public class TestMain { static { System.loadLibrary("lib"); } public native static int multiply(float a, float b); }
먼저 선언할 함수 명과 함께 native 함수를 선언한다. 그와 동시에 static 블럭 안에 System.loadLibrary 를 통해서 지금은 존재하지는 않지만 추후 생성할 라이브러리의 이름 lib을 지정한다.
그리고 이제 자바 컴파일러를 통해서 이 클래스를 컴파일함과 동시에 JNI 헤더를 생성해야 한다.
자바 컴파일러(javac)를 실행하기 위해서 Java가 설치된 디렉터리로 들어간다. 기본적으로 자바는 바이너리 제공사에 따라 위치가 제각각이다. 필자의 경우 Adoptium 을 사용하기 때문에, C:\Program Files\Eclipse Adoptium\jdk-21.0.7.6-hotspot\bin 에 javac.exe 가 있음을 확인했다.
이 javac 를 실행하기 위해 콘솔에 경로명\javac.exe 를 입력 해 본다.
특히 윈도우 터미널에서 띄어쓰기가 들어간 명령어의 경우 "로 감싸줘야 한다.
컴파일러가 정상적으로 실행된 것을 확인할 수 있다. 이제 이 명령 뒤에 -h 플래그와 함께 헤더가 생성될 위치, 헤더를 생성할 대상 java 파일을 입력해주면 된다.
"...\javac.exe" -h . TestMain.java
필자의 경우는 java 파일 명 및 클래스 명을 TestMain 으로 했기 때문에, TestMain.java 로 컴파일한다.
아무튼 이 작업이 완료되면 해당 디렉터리 안에 test_TestMain.h 과 같이 헤더 파일이 생긴다. 이제 이 파일을 C++ 헤더 파일에 등록하고 원하는 함수를 구현한 뒤에 dll 로 컴파일 하면 된다.
C/C++ 로 헤더 추가해서 컴파일하기
우리는 exe 응용 프로그램을 생성하는 것이 목표가 아니라, Dynamic-Link Library 인 DLL 을 생성하는 것이 목표이기 때문에 프로젝트를 생성할 때 DLL 프로젝트로 생성해야 한다.
프로젝트가 생성되면 Header Files 에는 방금 생성한 test_TestMain.h 를 넣고, 나머지 헤더는 모두 지운다. Source Files 에서도 dllmain.cpp 만 남기고 모두 지운다.
그리고 Visual Studio 에서 기본적으로 pch 와 같이 컴파일된 프리 헤더 기능이 켜져있는데,
필자의 경우는 프로젝트 속성에 들어가서 Configuration Properties -> C/C++ -> Precompiled Header 을 비활성화 하였다.
여기서 방금 만든 test_TestMain.h 는 절대 복사 붙여넣기로 넣어서는 안된다. 복사 붙여넣기로 넣으면 코드가 프로젝트에 들어가지는 것이 아니라 참조로 열리기 때문에 헤더로 include가 안된다. 그렇기에 필자는 Header Files 공간에 우클릭 -> 새 아이템 -> 원하는 헤더명.h 로 직접 헤더를 생성한 뒤 내용물을 붙여넣는식으로 하였다.
JNI 가 기본적으로 자체 생성해준 헤더는 우리가 Java 에서 처음 구성한 static native 함수와 똑같다. 여기서 헤더를 정의하고, Main.cpp 에서 구현한 뒤 빌드하면 Java에서 그 구현된 C/C++ 코드를 실행할 수 있는 것이다.
즉 필자는 dllmain.cpp 라는 파일을 하나 생성한 뒤 jfloat a, jfloat b 를 곱하여 반환하는 식으로 구현하였다. 즉 곱셈 함수가 된 것이다.
빌드를 하면 dll가 생성되어야 하지만, 막상 오류가 발생한다. 이는 인클루드 공간에 자바 자체 JNI 헤더를 등록해주지 않아서 그런데, 프로젝트 속성에 들어가 C/C++ Include 디렉터리에 자바 JDK 디렉터리 내부에 있는 include 디렉터리와 include/win32 디렉터리를 추가해야 한다.
프로젝트 속성에 들어간 뒤, VC++ Directories 항목에서 Include Directories 설정을 들어간다.
그리고 새 디렉터리 모양을 눌러 Java JDK 디렉터리 내부에 있는 include 디렉터리와 include 안에 있는 win32 디렉터리를 각각 등록해준다. 필자의 경우는 위 사진과 같다.
Rebuild started at 4:05 PM... 1>------ Rebuild All started: Project: Dll1, Configuration: Debug x64 ------ 1>dllmain.cpp 1>C:\Users\WhitmemHomeGame\source\repos\Dll1\Dll1\dllmain.cpp(8,10): warning C4244: 'return': conversion from 'jfloat' to 'jint', possible loss of data 1> Creating library C:\Users\WhitmemHomeGame\source\repos\Dll1\x64\Debug\Dll1.lib and object C:\Users\WhitmemHomeGame\source\repos\Dll1\x64\Debug\Dll1.exp 1>Dll1.vcxproj -> C:\Users\WhitmemHomeGame\source\repos\Dll1\x64\Debug\Dll1.dll 1>Done building project "Dll1.vcxproj". ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ========== ========== Rebuild completed at 4:05 PM and took 03.663 seconds ==========
그러면 제대로 컴파일이 되는 것을 확인할 수 있는데,
C/C++ 프로젝트의 최상단 컴파일된 디렉터리 (필자의 경우는 x64 컴파일을 했기 때문에 x64 디렉터리)/Debug에 들어가면 dll이 존재하는 것을 확인할 수 있다. 이제 이 Ddll 파일만 Java 프로젝트의 최상단 위치에 복사한다.
그리고 아까 System.loadLibrary("lib"); 으로 작성했기 때문에 파일 명을 lib.dll로 변경해준다. 즉 저 loadLibrary 의 인자로 들어가는 내용은 파일명*(확장자 제외)을 넣어주면 된다.
그리고 이제 생성된 함수를 실행해본다.
25okay
정상적으로 실행되는 것을 확인할 수 있다. 이 방법을 활용해서 윈도우 운영체제에서만 사용 가능한 API 들을 실행할 수 있다. 다음 게시글에서는 윈도우 자체 MessageBox 등을 자바에서 실행해보기로 한다.
댓글 0개
댓글은 일회용 패스워드가 발급되며 사이트 이용 약관에 동의로 간주됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.