0

I have a Java-based Android app that uses two native submodules. I have them sharing a pointer by retrieving it from process A as a long and passing it to process B. I seem to encounter problems related to this memory region that are sporadic and depend upon the current build and not upon the changes I just made.

Do I need to use ashmem to accomplish this properly, or is my methodology (in principal) sound?

EntangledLoops
  • 1,706
  • 1
  • 18
  • 29

3 Answers3

1

There is no guarantee that memory in one process which be a) accessible to another, b) in the same virtual location, c) thread safe.

What I do is memory map the same file into multiple processes and use the Unsafe class to perform thread safe operations on this memory.

This work on Intel and should work on the latest ARM processors, however older versions of ARM processors which I believe are still in use have weaker memory consistency guarantees, and may be unreliable for shared memory.

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
  • Do you use `ashmem` to accomplish this? Are you essentially saying I need to use `mmap`? I realize I could use a slower, more memory intensive solution: 1) Do stuff on memory in proc A, 2) Copy memory up to Java via JNI 3) Copy memory to proc B via JNI, 4) repeat in reverse – EntangledLoops Jun 02 '15 at 16:37
  • If you use `Unsafe` to access `mmap` this doesn't use JNI on OpenJDK/Oracle JVM however on Android I think it might. I don't use an additional library although I wrote one to make doing this easier. When you have a ByteBuffer which points to a region of memory, it can be used in Java without additional copying, you are reading/writing to it. – Peter Lawrey Jun 02 '15 at 16:41
  • What do you mean by "it can be used in Java without additional copying"? In addition to what, exactly? I have to copy memory up from C where it is created, and back down to C where it is processed, and then shuffle the results back again. It seems to me that my choices are A) suffer through learning this `mmap`-style solution, or B) use the less efficient/robust copying procedure. Am I wrong there? – EntangledLoops Jun 02 '15 at 16:49
  • Where does `C` come into it? When you use shared memory, there is one copy of memory in both processes. You can read or write to that memory like two threads sharing any other native memory. – Peter Lawrey Jun 02 '15 at 16:54
  • I meant C the language, not a program "C" after A and B. – EntangledLoops Jun 02 '15 at 19:36
  • The shared memory can be accessed from C as well. A, B and C can use the same memory. – Peter Lawrey Jun 02 '15 at 19:37
0

It's impossible to share pointers between native apps since each (native) app has it's own memory space & mapping. Android does provide a mechanism to solve this problem, which is called Anonymous Shared Memory. This is actually based on linux's implementation for the same purpose. Checkout this document from android for more info on sharing memory in android.

Here are the scheme I used:
1) fd = ashmem_create_region("my_shm_region", size); if(fd < 0) return -1; unsigned char* dataptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(data == MAP_FAILED) goto out;

2)You can then pass fd to other native app and call:
unsigned char* dataptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

us_david
  • 3,308
  • 29
  • 25
0

Here is what I would suggest:
1) Allocate shared memory through ashm:

int fd = ashmem_create_region(name, size);
ashmem_pin_region(fd, 0, 0);
uint8_t *shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  

2) the fd can be shared with another native process using binder. For more info on binder please read this stack overflow answer.

3) In the other native code you can do:

uint8_t *shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fdclient, 0);   

where fdclient is acquired in step 2) above.

Community
  • 1
  • 1
us_david
  • 3,308
  • 29
  • 25