Enquanto jogava esse quebra-cabeça (é um jogo de trivia de palavras-chave em Java), me deparei com a nativepalavra - chave.
Para que é usada a palavra-chave nativa em Java?
Enquanto jogava esse quebra-cabeça (é um jogo de trivia de palavras-chave em Java), me deparei com a nativepalavra - chave.
Para que é usada a palavra-chave nativa em Java?
Respostas:
A nativepalavra-chave é aplicada a um método para indicar que o método é implementado no código nativo usando JNI (Java Native Interface).
Exemplo mínimo executável
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;
}
Compile e execute:
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
Resultado:
4
Testado no Ubuntu 14.04 AMD64. Também trabalhou com o Oracle JDK 1.8.0_45.
Exemplo no GitHub para você brincar.
Os sublinhados nos nomes de pacotes / arquivos Java devem ser escapados _1no nome da função C, conforme mencionado em: Chamando Funções JNI no nome do pacote Android que contém sublinhado
Interpretação
native permite que você:
Isso pode ser usado para:
com a troca de menor portabilidade.
Também é possível chamar Java de C, mas você deve primeiro criar uma JVM em C: Como chamar funções Java de C ++?
APIs de extensão nativas análogas também estão presentes em muitas outras "linguagens de VM" pelos mesmos motivos, por exemplo , Python , Node.js , Ruby .
Android NDK
O conceito é exatamente o mesmo neste contexto, exceto que você precisa usar o clichê do Android para configurá-lo.
O repositório oficial do NDK contém exemplos "canônicos", como o aplicativo hello-jni:
Em unzipum .apkNDK no Android O, é possível ver o pré-compilado .soque corresponde ao código nativo em lib/arm64-v8a/libnative-lib.so.
TODO confirma: além disso, file /data/app/com.android.appname-*/oat/arm64/base.odexdiz que é uma biblioteca compartilhada, que eu acho que é o .dex pré-compilado AOT correspondente aos arquivos Java no ART, veja também: O que são arquivos ODEX no Android? Talvez o Java também seja executado através de uma nativeinterface?
Exemplo no OpenJDK 8
Vamos encontrar onde Object#cloneé definido em jdk8u60-b27.
Concluiremos que é implementado com uma nativechamada.
Primeiro encontramos:
find . -name Object.java
o que nos leva a jdk / src / share / classes / java / lang / Object.java # l212 :
protected native Object clone() throws CloneNotSupportedException;
Agora vem a parte difícil, descobrir onde o clone está em meio a toda a indireção. A consulta que me ajudou foi:
find . -iname object.c
que encontraria arquivos C ou C ++ que podem implementar os métodos nativos do Object. Isso nos leva ao jdk / share / native / java / lang / 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]));
}
o que nos leva ao JVM_Clonesímbolo:
grep -R JVM_Clone
o que nos leva ao hotspot / src / share / vm / prims / jvm.cpp # l580 :
JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
JVMWrapper("JVM_Clone");
Depois de expandir um monte de macros, chegamos à conclusão de que esse é o ponto de definição.
static nativemétodo Java, o segundo parâmetro da função C ++ é do tipo jclasse não jobject.
Ele marca um método, que será implementado em outras linguagens, não em Java. Ele trabalha em conjunto com o JNI (Java Native Interface).
Métodos nativos foram usados no passado para escrever seções críticas de desempenho, mas com o Java ficando mais rápido, isso agora é menos comum. Atualmente, métodos nativos são necessários quando
Você precisa chamar uma biblioteca de Java escrita em outra linguagem.
Você precisa acessar os recursos do sistema ou hardware acessíveis somente a partir de outro idioma (normalmente C). Na verdade, muitas funções do sistema que interagem com o computador real (E / S de disco e rede, por exemplo) só podem fazer isso porque chamam código nativo.
Consulte também Especificação da interface nativa Java
currentTimeMillisfazem parte do JDK e são anotados nativeporque a implementação está no próprio código-fonte do JDK. É muito improvável que a implementação use linguagem assembly; provavelmente chama um método API do sistema operacional no qual a JVM está sendo executada. Por exemplo, no Windows, ele pode chamar um método DLL GetSystemTimeno kernel32.dll. Em outro sistema operacional, ele terá uma implementação diferente. No entanto, ao usar nativeum método que você está escrevendo (em oposição a um método JDK), é necessário fornecer a implementação usando JNI.
currentTimeMillisestá marcado como nativo java.lang.Systempara usar JNI, não é?
Straight from a especificação Java Idioma :
Um método
nativeimplementado no código dependente da plataforma, normalmente escrito em outra linguagem de programação, como C, C ++, FORTRAN ou linguagem assembly. O corpo de umnativemétodo é fornecido apenas como ponto e vírgula, indicando que a implementação foi omitida, em vez de um bloco.
funções que implementam código nativo são declaradas nativas.
A Java Native Interface (JNI) é uma estrutura de programação que permite que o código Java em execução em uma Java Virtual Machine (JVM) chame e seja chamado por aplicativos nativos (programas específicos para uma plataforma de hardware e sistema operacional) e bibliotecas escritas em outras linguagens como C, C ++ e assembly.
native é uma palavra-chave em java, usada para tornar a estrutura (método) não implementada como abstrata, mas seria dependente da plataforma, como código nativo, e executada a partir da pilha nativa e não da pilha java.
O nativemétodo Java fornece um mecanismo para o código Java chamar o código nativo do SO, devido a razões funcionais ou de desempenho.
Exemplo:
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();
No Runtime.classarquivo correspondente no OpenJDK, localizado em JAVA_HOME/jmods/java.base.jmod/classes/java/lang/Runtime.class, contém esses métodos e os marcou com ACC_NATIVE( 0x0100), e esses métodos não contêm o atributo Code , o que significa que esse método não possui nenhuma lógica de codificação real no Runtime.classarquivo:
availableProcessors: marcado como atributo nativo e sem códigofreeMemory: marcado como atributo nativo e sem códigototalMemory: marcado como atributo nativo e sem códigomaxMemory: marcado como atributo nativo e sem códigogc: marcado como atributo nativo e sem códigoA lógica de codificação de fato está no arquivo Runtime.c correspondente :
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 }
E essa Ccodificação é compilada no arquivo libjava.so(Linux) ou libjava.dll(Windows), localizado em JAVA_HOME/jmods/java.base.jmod/lib/libjava.so:
Referência