28

I want to pass a string into the JNI I am writing which have to be assigned to a const char*. The below mentioned is how I have done it:

JNI...(...,jstring jstr...){

const char* str = env->GetStringUTFChars(jstr,0);
env->ReleaseStringUTFChars(str,jstr,0);

}

But if i printf the const char* str after assigning to the jstring what I see is different as compared to when I assigned the str value directly in the JNI and printf from there.

Is this the correct way to do? Or is there any other way to assign a string from java to const char* in JNI ?

2
  • Can you provice the string before (java) and after (c)? Commented Nov 22, 2010 at 15:34
  • The arguments for your ReleaseStringUTFChars look wrong wrt the documentation. Commented Apr 13, 2021 at 17:30

6 Answers 6

41

java code

public static native double myMethod( String path);  

C Code

JNIEXPORT jdouble JNICALL Java_your_package_structure_className_myMethod
(JNIEnv * env, jobject jobj, jstring pathObj) {
     char * path;

    path = (*env)->GetStringUTFChars( env, pathObj, NULL ) ;
Sign up to request clarification or add additional context in comments.

8 Comments

multiple errors here. Firstly, if method is static, than no jobject is presented, but jclass. Secondly, (*env) is incorrect, need just env->Get... Thirdly, GetStringUTFChars doesn't get env as a parameter.
@Vladimir Ivano Check out documents, This is working code java.sun.com/developer/onlineTraining/Programming/JDCBook/…
@VladimirIvanov This: (*env)->Method(env, is correct for C, env-> is the C++ way of doing JNI.
you just made my day... trying it from 4 hours and all similar solutions were of no use, but this one..!! Thank you so much!!
The Reference link seems to be broken
|
2

All you do is correct. There is other way but to obtain wchar_t instead of char:

const wchar_t * utf16 = (wchar_t *)env->GetStringChars(bytes, NULL);
size_t length = (size_t)env->GetStringLength(bytes);        
...
env->ReleaseStringChars(bytes, (jchar *)utf16);

Comments

2
JNIEXPORT jstring JNICALL Java_Hello_sayHi(JNIEnv *env, jobject obj, jstring string) {
     const char *str = env->GetStringUTFChars(string, 0);
     printf("%s", str);
}

3 Comments

You should always provide an explanation to support your answer
Welcome to Stack Overflow! While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations!
You must release the string afterwards with ReleaseStringUTFChars(). This is a bad example of usage.
0

As #Jigar explained:

JNIEXPORT jdouble JNICALL Java_your_package_structure_className_myMethod
(JNIEnv * env, jobject jobj, jstring jstr) {


    const char *path = (*env)->GetStringUTFChars( env, jstr , NULL ) ;

in order to get a jstring from java, one should write c++ method as below

C++ code:

const char *path = env->GetStringUTFChars(jstr , NULL ) ;

UPDATE: As mentioned in comments, there was a mistake in the code. It's now fixed.

2 Comments

On your C version, path was char * and in you C++ version, path is const char* - I am confused - should the user free the char array, or is it a pointer to some internal jstring field, that will be treated by Java?
@SomethingSomething thank you for your attention. The problem is fixed.
0
there are several ways but the best i got by converting const char * to c++ string 
and then to jbyteArray, and its easy to conversion of byteArray to UTF-8 on java 
side.

C++ side:
const char* string = propertyValue;
std::string str = string;

jbyteArray array = env->NewByteArray(str.length());
env->SetByteArrayRegion(array,0,str.length(),(jbyte*)str.c_str());


return array;

java/kotlin side:

String((array), Charset.defaultCharset()))

Comments

-1

Actually, solution is simple: the last parameter of "GetStringUTFChars" is JNI_TRUE to send a copy. Since you are passing JNI_FALSE (0) and calling "ReleaseStringUTFChars", you are destroying the reference. What you see after "releasing" are random bytes from elsewhere in your application memory.

Calling "GetStringUTFChars" with JNI_TRUE or removing the "ReleaseStringUTFChars" call will solve your problem.

EDIT: Sorry about graveyard digging.

5 Comments

Really? How did the value of str magically change to point to a different address 'elsewhere in your application memory'?
AFAIK, he said the contents of the "const char *" changed, not the pointer itself.
I'm talking about what you said: 'random bytes from elsewhere in your application memory'. That would imply that the value of str changed, which isn't possible as it wasn't passed by reference.
It is a C pointer. Before releasing, it points to something useful. If you release and keep it, it's a pointer to something else in memory. If you make 'char a; char * b = &a + rand() % 10000; printf("%s\n", b);' in C, you get the same symptom he describes (and what I called "random", since you cannot predict what it is).
-1 The last parameters of "GetStringUTFChars" is an output value (pointer to a bool). It doesn't matter what you pass in, it simply tells you whether it is a copy (see documentation at docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/… ). Futhermore, if you remove the 'ReleaseStringUTFChars', you add a memory leak to your application. What should be done is to make full use of the data before calling the release function, or making a copy of the data before you release.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.