我在Java中有一个byte[]
,它将其长度报告为256字节,我将其传递给C中的本机函数。
当我试图从这个数组中取出数据时,这是完全错误的,当我将其打印出来时,它与我在传递给C之前打印出的数据不匹配。
我尝试了几种方法来访问数据,包括GetByteArrayRegion
和GetByteArrayElements
,但似乎没有任何方法可以提供我期望的数据。
当我调查这个时,我试着看看JNI认为jbyteArray
的长度与GetArrayLength
有什么关系 - 它报告的长度为1079142960,远远超过我预期的256个字节。每次调用函数时,值也不同,例如,另一个时间GetArrayLength
返回1079145720。
以下是我用来访问数组的代码:
JNIEXPORT jbyteArray function(JNIEnv* env, jbyteArray array) {
int length = (*env)->GetArrayLength(env, array);
jbyte data[256];
(*env)->GetByteArrayRegion(env, array, 0, 256, data);
//also tried
//jbyte *data = (jbyte*) (*env)->GetByteArrayElements(env, array, NULL);
}
这看起来非常简单,所以我不确定发生了什么。 Java中的数组看起来很好,但它是在C中生成并传回来的,所以我想在Java不关心的情况下可能会出现问题,但在返回C时会破坏数组。
以下是我用来生成数组并将其传递回Java的代码:
//there is some openSSL stuff here that sets up a pointer to an RSA struct called keys that is size bytes large
jbyteArray result = (*env)->NewByteArray(env, size);
(*env)->SetByteArrayRegion(env, result, 0, size, (jbyte*)keys;
我错过了什么吗?
由于
答案 0 :(得分:12)
此函数原型不正确:
JNIEXPORT jbyteArray function(JNIEnv* env, jbyteArray array)
第二个参数是jclass
或jobject
。如果您的方法是静态的,那么它应该是:
JNIEXPORT jbyteArray function(JNIEnv* env, jclass cls, jbyteArray array)
如果它不是静态的:
JNIEXPORT jbyteArray function(JNIEnv* env, jobject obj, jbyteArray array)
您将类或对象视为数组,这可以解释您获得的意外结果。
答案 1 :(得分:1)
我认为主要问题是你将OpenSSL结构强制转换为字节数组。很可能这个结构会随着时间的推移而被释放。这可以解释当你返回C时向你报告的奇怪和不同的长度。给Java一个RSA*
也不会对你有所帮助 - Java不知道那个特定的结构并且不会是能够识别它。
你应该尝试使用
中的一个取决于您是要将公钥信息还是私有信息传递给Java(see also here)。这样你就可以确保从一开始就处理一个字节数组。
一旦这对你有用(使用你已经尝试过的技术),在Java中你可以将字节数组解析成有意义的东西。这在公钥案例中是直截了当的:在您的数组中使用X509EncodedKeySpec并使用KeyFactory#generatePublic生成公钥。
私钥中的情况稍微复杂一些。 Java只能理解PKCS#8 format,而OpenSSL默认根据PKCS#1格式对其私有RSA密钥进行编码。但您可以使用i2d_PKCS8PrivateKey_bio将密钥转换为PKCS#8。您需要首先将RSA*
包裹为EVP_PKEY*
:
EVP_pkey *pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);
不要加密密钥并使用in-memory BIO
,然后将生成的字节数组传递给Java,然后传递给PKCS8EncodedKeySpec
的构造函数,最后使用KeyFactory
生成私钥
答案 2 :(得分:0)
尝试使用'\ 0'字符附加字符串。可能它无法识别字符串的结尾。