java 栈本地栈_Java本地方法栈

本地方法及实现

什么是本地方法

A native method is a Java method whose implementation is provided by non-java code.

本地方法的实现

在定义一个native method时,java中只提供定义,由非java语言提供实现。

JNI即Java Native Interface,它能在Java层实现对本地方法的调用,一般本地的实现语言主要是C/C++,JVM主要使用C/C++ 和少量汇编编写,在执行Java字节码时如果遇到有某个方法标明为Native的则从JVM中找到对应的C/C++函数,一般本地方法对应的函数会被注册到JVM中。

例子,编写Java类提供本地加密。

Java类

//编写Java类提供本地加密

package com.seaboat.bytecode;

public class ByteCodeEncryptor {

static{

System.loadLibrary("ByteCodeEncryptor");

}

public native static byte[] encrypt(byte[] text);

}

使用jni生成C语言头文件。

javah -jni com.seaboat.bytecode.ByteCodeEncryptor

生成的头文件

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_seaboat_bytecode_ByteCodeEncryptor */

#ifndef _Included_com_seaboat_bytecode_ByteCodeEncryptor

#define _Included_com_seaboat_bytecode_ByteCodeEncryptor

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_seaboat_bytecode_ByteCodeEncryptor

* Method: encrypt

* Signature: ([B)[B

*/

JNIEXPORT jbyteArray JNICALL Java_com_seaboat_bytecode_ByteCodeEncryptor_encrypt

(JNIEnv *, jclass, jbyteArray);

#ifdef __cplusplus

}

#endif

#endif

根据头文件编写源文件。

#include "com_seaboat_bytecode_ByteCodeEncryptor.h"

#include "jni.h"

void encode(char *str)

{

unsigned int m = strlen(str);

for (int i = 0; i < m; i++)

{

str[i] = str[i]+4;

}

}

extern"C" JNIEXPORT jbyteArray JNICALL

Java_com_seaboat_bytecode_ByteCodeEncryptor_encrypt(JNIEnv * env, jclass cla,jbyteArray text)

{

char* dst = (char*)env->GetByteArrayElements(text, 0);

encode(dst);

env->SetByteArrayRegion(text, 0, strlen(dst), (jbyte *)dst);

return text;

}

cl编译并生成动态库

cl /EHsc -ID:\Java\jdk1.8.0_73\include\ -ID:\Java\jdk1.8.0_73\include\win32 -LD com_seaboat_bytecode_ByteCodeEncryptor.cpp -FeByteCodeEncryptor.dll

Java中如何加载?

System.loadLibrary("ByteCodeEncryptor");加载动态库,而它其实是通过ClassLoader.loadLibrary()方法来加载,最终也是通过JVM的类加载器本地方法加载。

本地方法栈

2e7b40acb30b90230d145bbb328dc6ef.png

这俩都是JVM规范所规定的概念上的东西,并不是说具体的JVM实现真的要给每个Java线程开两个独立的栈。以Oracle JDK / OpenJDK的HotSpot VM为例,它使用所谓的“mixed stack”——在同一个调用栈里存放Java方法的栈帧与native方法的栈帧,所以每个Java线程其实只有一个调用栈,融合了JVM规范的JVM栈与native方法栈这俩概念。

本地方法栈和Java方法栈一样都是线程私有的。

当带有本地方法的Java类被加载时,相关的DLL并未被加载。当本地方法被调用时,这些DLL才会被加载并设置指向方法的指针,这是通过调用java.system.loadLibrary()实现的。

任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。当C程序调用一个C函数时,其栈操作都是确定的。传递给该函数的参数以某个确定的顺序压入栈,它的返回值也以确定的方式传回调用者。同样,这就是虚拟机实现中本地方法栈的行为。

很可能本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈。线程可以在Java方法栈和本地方法栈中跳转。

refs:

https://blog.csdn.net/wangyangzhizhou/article/details/74931733

本文地址:https://cheng-dp.github.io/2018/12/14/mative-method-stack/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值