Java의 기본 키워드는 무엇입니까?


답변:


343

native키워드는 방법은 JNI (Java 원시 인터페이스)를 사용하여 네이티브 코드로 구현되는 것을 나타내는 방법에 적용된다.


3
실제 구현은 JNI를 사용할 필요가 없습니다. 특정 JRE 메소드는 본질적으로 JVM에 의해 처리됩니다. 실제로, 구현이 실제로 네이티브 코드 일 필요는 없습니다. 그냥 "Java 프로그래밍 언어 이외의 언어로 구현되었습니다" .
Holger

444

최소 실행 가능 예

Main.java

public class Main {
    public native int square(int i);
    public static void main(String[] args) {
        System.loadLibrary("Main");
        System.out.println(new Main().square(2));
    }
}

Main.c

#include <jni.h>
#include "Main.h"

JNIEXPORT jint JNICALL Java_Main_square(
    JNIEnv *env, jobject obj, jint i) {
  return i * i;
}

컴파일하고 실행하십시오.

sudo apt-get install build-essential openjdk-7-jdk
export JAVA_HOME='/usr/lib/jvm/java-7-openjdk-amd64'
javac Main.java
javah -jni Main
gcc -shared -fpic -o libMain.so -I${JAVA_HOME}/include \
  -I${JAVA_HOME}/include/linux Main.c
java -Djava.library.path=. Main

산출:

4

Ubuntu 14.04 AMD64에서 테스트되었습니다. Oracle JDK 1.8.0_45와 함께 작업했습니다.

GitHub의 예제 입니다.

Java 패키지 / 파일 이름의 밑줄은 다음에 _1언급 된대로 C 함수 이름으로 이스케이프되어야합니다 . 밑줄을 포함하는 Android 패키지 이름에서 JNI 함수 호출

해석

native 당신이 할 수 있습니다 :

  • Java에서 임의의 어셈블리 코드로 컴파일 된 동적으로로드 된 라이브러리 (여기서는 C로 작성) 호출
  • 결과를 Java로 다시 가져 오기

이것은 다음을 위해 사용될 수 있습니다 :

  • 더 나은 CPU 어셈블리 지침으로 CPU 섹션이 아닌 중요한 섹션에서 더 빠른 코드 작성
  • 직접 시스템 호출 (OS 휴대용이 아님)

휴대 성이 낮다는 단점이 있습니다.

C에서 Java를 호출 할 수도 있지만 먼저 C : C ++에서 Java 함수를 호출하는 방법 에서 JVM을 작성해야합니다 .

Python , Node.js , Ruby 와 같은 동일한 이유로 여러 가지 "VM 언어"에도 유사한 기본 확장 API가 있습니다 .

안드로이드 NDK

Android 상용구를 사용하여 설정해야한다는 점을 제외하면이 컨텍스트에서 개념은 동일합니다.

공식 NDK 저장소에는 hello-jni 앱과 같은 "표준"예제가 포함되어 있습니다.

당신에 안드로이드 O에 NDK를 사용하면 사전이 컴파일 볼 수 있다는에서 네이티브 코드에 해당합니다 .unzip.apk.solib/arm64-v8a/libnative-lib.so

TODO 확인 : 또한 file /data/app/com.android.appname-*/oat/arm64/base.odex공유 라이브러리라고 ART의 Java 파일에 해당하는 AOT 사전 컴파일 된 .dex라고 생각합니다 .Android의 ODEX 파일이란 무엇입니까? 아마 Java는 실제로native 인터페이스 됩니까?

OpenJDK 8의 예

Object#clonejdk8u60-b27에서 정의 된 위치를 찾으십시오 .

우리는 그것이 native호출 로 구현되었다는 결론을 내릴 것입니다 .

먼저 우리는 다음을 발견합니다.

find . -name Object.java

이는 리드 우리에게 JDK / SRC / 주 / 클래스 / 자바 / 랭 / Object.java # L212 :

protected native Object clone() throws CloneNotSupportedException;

이제 어려운 부분이 생겨 클론이 모든 간접 경로 가운데 어디에 있는지 찾는 것입니다. 나를 도운 쿼리는 다음과 같습니다.

find . -iname object.c

Object의 기본 메소드를 구현할 수있는 C 또는 C ++ 파일을 찾습니다. 그것은 우리를 인도 JDK / 주 / 기본 / 자바 / 랭 / Object.c # L47 :

static JNINativeMethod methods[] = {
    ...
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

그것은 우리를 JVM_Clone상징으로 인도합니다 .

grep -R JVM_Clone

그러면 핫스팟 /src/share/vm/prims/jvm.cpp#l580으로 연결됩니다 .

JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
    JVMWrapper("JVM_Clone");

많은 매크로를 확장 한 후에는 이것이 정의 지점이라는 결론에 도달합니다.


1
훌륭한 답변입니다. 각주 : static nativeJava 메소드의 경우 C ++ 함수의 두 번째 매개 변수는 유형이 jclass아닙니다 jobject.
SR_

정보를 주셔서 감사합니다. 내 답변에 실수가 있었습니까, 아니면 추가 정보입니까?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
@Ciro 그것은 당신의 모범으로 시작하는 사람들을위한 여분의 정보입니다 (SO에 대한 약 300의 답변은 참조로 사용될 수 있습니다). 스택에 엉망으로 호출 된 잘못된 서명이있는 함수가 있었고 오류가 없습니다 (컴파일, 링크 또는 런타임시). 따라서이 단계에서주의를 기울이는 것이 중요하다고 생각합니다.
SR_

419

Java가 아닌 다른 언어로 구현되도록 메소드를 표시합니다. JNI (Java Native Interface)와 함께 작동합니다.

과거에는 기본 메소드를 사용하여 성능이 중요한 섹션을 작성했지만 Java가 더 빨라짐에 따라 이제는 일반적이지 않습니다. 기본 방법은 현재 필요한 경우

  • 다른 언어로 작성된 Java에서 라이브러리를 호출해야합니다.

  • 다른 언어 (일반적으로 C)에서만 접근 할 수있는 시스템 또는 하드웨어 리소스에 액세스해야합니다. 실제로 실제 컴퓨터 (예 : 디스크 및 네트워크 IO)와 상호 작용하는 많은 시스템 기능은 기본 코드를 호출하기 때문에이 작업 만 수행 할 수 있습니다.

Java Native Interface 사양 도 참조하십시오.


3
이것은 내 이해입니다 .Java 파일에 System.currentTimeMillis () (기본)를 작성하면 작동합니다 .JNI는 라이브러리 또는 C 또는 C ++ 또는 어셈블리 언어로 작성된 일부 함수를 호출 한 다음 일부 값을 내 Java 코드로 반환합니다. . ex : here currentTimeMillis 메소드는 JNI의 도움으로 네이티브 코드를 호출하고 네이티브 코드는 시스템 리소스와 통신합니다. 예 : 마더 보드에있는 타이머와 반환 값 (시스템 시간). 제발, 제발?
MKod

4
@MKod 메소드 currentTimeMillis는 JDK의 일부이며 native구현은 JDK 소스 코드 자체에 있기 때문에 주석이 달린다 . 구현이 어셈블리 언어를 사용하는 경우는 거의 없습니다. 아마도 JVM이 실행되는 운영 체제의 API 메소드를 호출합니다. 예를 들어 Windows GetSystemTime에서는 kernel32.dll에서 DLL 메서드 를 호출 할 수 있습니다 . 다른 OS에서는 다른 구현이 있습니다. 그러나 native메소드에 사용할 때는 (JDK 메소드와 달리) JNI를 사용하여 구현을 제공해야합니다.
Adam Burley

이 문장은 Native 키워드의 중요한 문장입니다 ... '다른 언어 (일반적으로 C)에서만 접근 할 수있는 시스템 또는 하드웨어 자원에 액세스해야합니다.'
atiqkhaled

@Kidburla "구현은 JDK 소스 코드 자체에있다"는 말의 의미를 물어봐도 될까요? JNI를 사용하므로 currentTimeMillis네이티브로 표시되어 java.lang.System있습니까?
flow2k

1
@ flow2k 그렇습니다, 당신이 말한 것이 아마도 사실 일 것입니다. 왜 내가 2 년 이상 전에 내 의견에서 그렇게 말했는지 잘 모르겠습니다.
Adam Burley

59

에서 직선 Java 언어 사양 :

native플랫폼 종속 코드로 구현되는 방법 으로, 일반적으로 C, C ++, FORTRAN 또는 어셈블리 언어와 같은 다른 프로그래밍 언어로 작성됩니다. native메소드 의 본문은 세미콜론으로 만 제공되며, 블록 대신 구현이 생략되었음을 나타냅니다.


19

SLaks가 대답했듯이 native키워드는 기본 코드를 호출하는 것입니다.

또한 자바 스크립트 메소드를 구현하기 위해 GWT 에서 사용 합니다.


13

네이티브 코드를 구현하는 함수는 네이티브로 선언됩니다.

JNI (Java Native Interface)는 JVM (Java Virtual Machine)에서 실행되는 Java 코드가 원시 애플리케이션 (하드웨어 및 운영 체제 플랫폼에 특정한 프로그램) 및 작성된 라이브러리를 호출하고 호출 할 수 있도록하는 프로그래밍 프레임 워크입니다. C, C ++ 및 어셈블리와 같은 다른 언어

http://en.wikipedia.org/wiki/Java_Native_Interface


8

NATIVE는 비 액세스 수정 자이며 METHOD에만 적용 할 수 있습니다. 메소드 또는 코드의 PLATFORM-DEPENDENT 구현을 나타냅니다.


6

native는 java의 키워드로 추상과 같이 구현되지 않은 구조 (메서드)를 만드는 데 사용되지만 네이티브 코드와 같은 플랫폼 종속적이며 Java 스택이 아닌 네이티브 스택에서 실행됩니다.


6
  • native java의 키워드이며 플랫폼에 따라 다릅니다.
  • native메소드는 Java ( JNI )와 다른 프로그래밍 언어 사이의 인터페이스 역할을 합니다.

3

Java native메소드는 기능 또는 성능상의 이유로 Java 코드가 OS 고유 코드를 호출하는 메커니즘을 제공합니다.

예:

606  public native int availableProcessors();
617  public native long freeMemory();
630  public native long totalMemory();
641  public native long maxMemory();
664  public native void gc();

Runtime.class있는 OpenJDK 의 해당 파일 JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class에서이 메소드를 포함하고 ACC_NATIVE( 0x0100)로 태그를 지정 하고이 메소드에는 Code 속성이 포함되어 있지 않습니다. 즉,이 메소드에는 Runtime.class파일 에 실제 코딩 논리가 없습니다 .

  • 방법 13 availableProcessors: 네이티브로 태그가 지정되고 코드 속성이 없음
  • 방법 14 freeMemory: 네이티브로 태그되고 코드 속성이 없음
  • 방법 15 totalMemory: 고유 속성으로 태그가 지정되고 코드 속성이 없음
  • 방법 16 maxMemory: 네이티브로 태그되고 코드 속성이 없음
  • 방법 17 gc: 네이티브로 태그되고 코드 속성이 없음

여기에 이미지 설명을 입력하십시오

실제로 코딩 로직은 해당 Runtime.c 파일에 있습니다.

42  #include "java_lang_Runtime.h"
43
44  JNIEXPORT jlong JNICALL
45  Java_java_lang_Runtime_freeMemory(JNIEnv *env, jobject this)
46  {
47      return JVM_FreeMemory();
48  }
49
50  JNIEXPORT jlong JNICALL
51  Java_java_lang_Runtime_totalMemory(JNIEnv *env, jobject this)
52  {
53      return JVM_TotalMemory();
54  }
55
56  JNIEXPORT jlong JNICALL
57  Java_java_lang_Runtime_maxMemory(JNIEnv *env, jobject this)
58  {
59      return JVM_MaxMemory();
60  }
61
62  JNIEXPORT void JNICALL
63  Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
64  {
65      JVM_GC();
66  }
67  
68  JNIEXPORT jint JNICALL
69  Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this)
70  {
71      return JVM_ActiveProcessorCount();
72  }

이러한 C코딩은 다음 위치 에있는 libjava.so(Linux) 또는 libjava.dll(Windows) 파일 로 컴파일됩니다 JAVA_HOME/jmods/java.base.jmod/lib/libjava.so.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

참고

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.