Enquanto jogava esse quebra-cabeça (é um jogo de trivia de palavras-chave em Java), me deparei com a native
palavra - 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 native
palavra - chave.
Para que é usada a palavra-chave nativa em Java?
Respostas:
A native
palavra-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 _1
no 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 unzip
um .apk
NDK no Android O, é possível ver o pré-compilado .so
que 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.odex
diz 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 native
interface?
Exemplo no OpenJDK 8
Vamos encontrar onde Object#clone
é definido em jdk8u60-b27.
Concluiremos que é implementado com uma native
chamada.
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_Clone
sí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
native
método Java, o segundo parâmetro da função C ++ é do tipo jclass
e 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
currentTimeMillis
fazem parte do JDK e são anotados native
porque 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 GetSystemTime
no kernel32.dll. Em outro sistema operacional, ele terá uma implementação diferente. No entanto, ao usar native
um método que você está escrevendo (em oposição a um método JDK), é necessário fornecer a implementação usando JNI.
currentTimeMillis
está marcado como nativo java.lang.System
para usar JNI, não é?
Straight from a especificação Java Idioma :
Um método
native
implementado no código dependente da plataforma, normalmente escrito em outra linguagem de programação, como C, C ++, FORTRAN ou linguagem assembly. O corpo de umnative
mé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 native
mé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.class
arquivo 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.class
arquivo:
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 C
codificação é compilada no arquivo libjava.so
(Linux) ou libjava.dll
(Windows), localizado em JAVA_HOME/jmods/java.base.jmod/lib/libjava.so
:
Referência