JNI DETECTED ERROR IN APPLICATION: use of invalid jobject - android-ndk

public class MyOpaqueBasedJSONDict implements IMyJSONDict {
private final long _myNativeCPPObj;
...
public IMyJSONDict getMyJSONObj(String keyName) {
long retVal = nativeGetJSOBObject(_myNativeCPPObj,keyName);
return (new MyOpaqueBasedJSONDict(retVal));
}
native implementation
NIEXPORT jlong JNICALL
Java_com_hexample_myndkapplication_MyOpaqueBasedJSONDict_nativeGetJSOBObject(JNIEnv *env,
jobject instance,
jlong myNativeCPPObj,
jstring keyName_) {
const char *keyName = env->GetStringUTFChars(keyName_, 0);
Json::Value* nativeCppJson_ptr = reinterpret_cast<Json::Value*> (myNativeCPPObj);
Json::Value& map = *nativeCppJson_ptr;
Json::Value& jsonVal = map[keyName];
env->ReleaseStringUTFChars(keyName_, keyName);
return (jlong) &jsonVal;
}
I am not able to understand why I am getting
JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xb4019a80
08-16 03:25:56.785 20537-20537/com.hexample.myndkapplication A/art:
art/runtime/java_vm_ext.cc:410] from long
com.hexample.myndkapplication.MyOpaqueBasedJSONDict.nativeGetJSOBObject
Any clue how to debug invalid memory errors in ndk. I am pretty new to Android and ndk development.

In my case,I used jobject in multi native thread:
javaCallBackObj = env->NewGlobalRef(jobj);
Note however that the jclass is a class reference and must be protected with a call to NewGlobalRef (see the next section).
Andorid Jni doc

For me it was the incoming const char * str parameter that was not playing ball with the CallStaticVoidMethod. To fix this we have to create a new jstring and pass that back to Java instead:
// str is a const char *
jstring x = env->NewStringUTF(str);
env->CallStaticVoidMethod(jclassMainClass, methodId, x);
env->DeleteLocalRef(x);
Makes sense really since JNI bridges C++ and Java and Java will only accept a Java string (jstring) not a const char *, despite passing the latter not causing a compile time error.

In my case the problem was that I was calling the native function with the rigth arguments but wrong return type

I got the similar problem in my android app. Further I found that the String argument is the "invalid jobject" mentioned by JNI. I tried input non-empty string as argument and the error gone. I don't know why it's that. I hope that it can help you as workaround.

I encountered this issue too,the situation is using wrong .so file .It should be x86 but I used x86_64.

Related

C++ no acceptable conversion for operator+ with class

I have some 15-year-old C++ code that I am trying to bring up to more modern times. At this stage, I'm trying to get code that compiled with Visual C++ 6.0 to now compile with VS 2003 (Microsoft Visual C++ .NET 69462-335-0000007-18915). If we can get this to compile cleanly & run properly, then we can take another step to get it into a more recent version of VS. But I'm having a number of problems...
Here is a snippet of the (simplified) code:
class toS
{
public:
toS() { buff[0] ='\0'; }
operator LPCTSTR() { return buff; }
protected:
void Append (TCHAR c)
{
LPTSTR p = buff + _tcslen(buff);
*p++ = c;
*p = '\0';
}
TCHAR buff[40];
};
class LtoS : public toS
{
public:
LtoS(LONG n, TCHAR c = '\0')
{
_ltot(n, buff, 10);
Append(c);
}
};
void WriteBool(const CString& Section, const CString& Key, bool Value);
CString Section;
int nLine = 0;
std::vector<bool> *BoolVect;
std::vector<bool>::iterator vi;
...
for (vi = BoolVect->begin(); vi != BoolVect->end(); vi++)
WriteBool(Section, "LineVis " + LtoS(nLine++), *vi);
...
From this I get the following error message:
error C2677: binary '+' : no global operator found which takes type 'LtoS' (or there is no acceptable conversion)
Any idea how this code ever worked? If I can find out what it did in the past, I can begin to define the overloaded operator+ to match the functionality.
Compiler error goes away when I make class tos inherit from CString with:
class tos : public CString { ... }
Hopefully this will not only compile, but will execute correctly...
Deriving from several of the comments, try adding a public conversion operator to class toS as follows:
operator LPCTSTR() const { return &buff[0]; }
You may need to explicitly construct the string in the for loop as well, e.g.:
WriteBool(Section, CString("LineVis ") + static_cast<LPCTSTR>(LtoS(nLine++)), *vi);
(Side note: As you probably know since you just extracted code for an example, there's a problem here:
std::vector<bool> BoolVect;
...
for (vi = BoolVect->begin(); vi != BoolVect->end(); vi++)
The notation you're using to access the BoolVect implies that it is a pointer, but it's not being declared as such in your example.)

wchar functions under Android NDK

Here is my simplified code:
static void WriteToFile(const wchar_t* msg) {
FILE* f = fopen("/sdcard/mytest.txt", "w");
fprintf(f, "%ls\n", msg);
fclose(f);
}
// Somewhere else in the code
const wchar_t* msg = L"Hello world";
WriteToFile(msg);
Using %ls to format a wchar string seems to work fine in Windows and Ubuntu. However, on Android, it writes only the first character H in the file.
I even tried to convert wchar to mbs:
char buf[100];
wcstombs(buf, msg, 100);
However, buf still ends up having just one character H in it.
I have a feeling that it is happening because wchar is four bytes long on Android. However, I would think the NDK must be aware of this.
How do I fix this? Regards.
Instead of using wcstombs, etc., use APIs from libiconv (https://www.gnu.org/software/libiconv/). You may have to build libiconv library for Android.

"Xpressive leak" fixed, but not understood

I know. Xpressive is (probably) not at fault here, but I've put a lot of effort into finding the memory leaks and I had to adapt the code layout to fix the haemorrhage.
Can someone explain to me why the change in layout fixed it? I don't see why the (correct/improved) use of "static const" fixes the leaks.
BTW, the leaks were occurring on a MIPs core, using boost version 1.49, and cross compiled with GCC 4.3.3.
Original "sieve" code:
// source.cpp
#include <boost/...
cregex token = keep(+set[ alnum|'!'|'%'|'_'|'*'|'+'|'.'|'\''|'`'|'~'|'-']);
cregex more = ...
bool foo(const char * begin, const char * end, size_t& length, std::string& dest)
{
mark_tag name_t(1);
cregex regx = bos >>
icase("name:") >>
(name_t= token) >> eos;
cmatch what;
bool ok = regex_search( begin, end, what, regx );
...
return ok;
}
Fixed "non-leaky" code:
// header.hpp
#include <boost/...
class Xpr {
public:
static const cregex token;
static const cregex more;
};
// source.cpp
#include "header.hpp"
const cregex Xpr::token = keep(+set[ alnum|'!'|'%'|'_'|'*'|'+'|'.'|'\''|'`'|'~'|'-']);
const cregex Xpr::more = ...
bool foo(const char * begin, const char * end, size_t& length, std::string& dest)
{
mark_tag name_t(1);
static const cregex regx = bos >>
icase("name:") >>
(name_t= Xpr::token) >> eos;
cmatch what;
bool ok = regex_search( begin, end, what, regx );
...
return ok;
}
The leaks seemed to be occurring upon every call of foo!
EDIT: After writing the below response, I tried to reproduce your problem and was unable to. Here is the code I'm using.
#include <boost/xpressive/xpressive.hpp>
using namespace boost;
using namespace xpressive;
cregex token = keep(+set[ alnum|'!'|'%'|'_'|'*'|'+'|'.'|'\''|'`'|'~'|'-']);
//cregex more = ...
bool foo(const char * begin, const char * end)
{
mark_tag name_t(1);
cregex regx = bos >>
icase("name:") >>
(name_t= token) >> eos;
cmatch what;
bool ok = regex_search( begin, end, what, regx );
//...
return ok;
}
int main()
{
char const buf[] = "name:value";
while(true)
foo(buf, buf + sizeof(buf) - 1);
}
This code doesn't leak. Is it possible you're using an earlier version of xpressive? Could you post a complete, self-contained example so I can investigate? Even better, file a bug and attach the code there. Thanks,
Eric
-----Begin Original Response-----
I suspect that you're running afoul of xpressive's cycle tracking code. See here for a warning against nesting global regex objects in function-local ones. I think what's happening is that, in order to prevent dangling references, the function-local regx must hold a reference to token, and token must hold a (weak) reference back to regx. What is growing is token's map of weak references. This isn't a leak in the strict technical sense, since the memory will get reclaimed when token gets destroyed. But it's obviously not ideal.
I fixed a similar "leak" in xpressive a while back by adding an opportunistic purge of the map to clear out weak references to expired regexes. I have to look into why it's not happening in this case. Please file a bug here. Thanks.
In the mean time, your fix is plenty good. Declaring the function-local regx static means it will only get constructed once, so token's weak-reference map will never grow beyond size 1.

char pointer argument value is not getting updated when i get the response back from my c++ dll to c#

i have imported a c++ native dll method in c#. below is how the c++ method look
extern "C" declspec(dllexport) int __stdcall temp(char *value)
{
value="hksdhfs";
return 1;
}
this how i imported in c#
[DllImport("check.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "temp")]
public static extern int temp(string value);
the problem is that i am able to send the data thorough the "value" char pointer to the c++ dll, but the value is not being changed when i get "value" char pointer back in c#. Can any one please help.
As the argument is not working in this case so i changed the return type of the c++ dll method like below and getting the string in the written format
extern "C" declspec(dllexport) char* __stdcall temp(char *value)
{
value="hksdhfs";
return value;
}
and the dll import is like this
[DllImport("check.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "temp")]
[return:MarshalAs(UnmanagedType.LPStr)]
public static extern string temp(string value);
doing strcpy() will also work but if i am using the class this pointer character value to be passed that it will not work so i preferred the above way and that worked... Thanks Every one.

Varargs not working in 64bit with managed objects?

I'm trying to migrate some managed c++ code to 64bits.
I have a function that gets varargs, and when I pass a System::String variable to it, it appears not to pass correctly.
Here is a simplification of the code that shows the problem:
#include <stdio.h>
#include <stdarg.h>
void test(char* formatPtr, ...)
{
va_list args;
int bufSize;
char buffer[2600];
/////////////////////////////////////
//parse arguments from function stack
/////////////////////////////////////
va_start(args, formatPtr);
bufSize = vsprintf(buffer, (const char*) formatPtr, args);
printf(buffer);
va_end(args);
}
void main() {
System::String^ s;
s = "Shahar";
test("Hello %s", s);
getchar();
}
When this code runs in 32 bits, it displays Hello Shahar.
When it runs in 64 bits, it displays Hello Çz∟⌠■.
Assuming I want to make the least amount of changes to the code, how should I fix this?
It looks as though the problem is in the mix between managed code and varargs. It appears that they are not compatible with each other.
I don't know why this works in 32-bits, but it looks like the wrong thing to do.
I changed the code, so as to be only managed code, with no varargs.
The %s specifier expects a C-style null-terminated string, not a System::String^. C++/CLI headers provide some methods that can convert System::String^ to std::string, which can be converted to a C-string, and can probably just convert straight to a C-string.
You have other problems too. void main()? Assigning a literal to a char*? Fixed-size buffer?

Resources