LINUX.ORG.RU

передача данные между java и c++ без накладных расходов

 ,


2

3

у меня есть java-класс. объект этого класса обычно содержит ссылки на несколько десятков тысяч объектов более мелких классов и несколько длинных векторов. кроме того, есть расчетный модуль на с++, которому надо передать объект этого «толстого» класса.

посоветуйте, как лучше передать данные в с++, так чтобы на (де)сериализацию тратилось как можно меньше времени?

есть ли возможность передать данные в с++ код без копирования, без сериализации? так, чтобы с++ «разделял» ту же область памяти, что и java?

p.s. классы содержит векторы чисел и списки объектов (по ~10 числовых полей) что-то подобное, вроде бы, умеет cap'n'proto. но умеет ли он быстро сериализовать из java в c++ - я не понял


Ну я не знаю какие там у тебя типы конкретно в классах, но cap'n'proto вроде может работать только полностью копируя, создавая новую кросс языковую структуру.

Можно оставить все в Java формате и работать с этим в С++ используя JNI хедеры для работы с типами в С++. Еще есть JNA - тот же хрен, только более high-level

Можно просто создать Direct ByteBuffer из NIO, все данные в нем разложить, читать и писать в него из Java с помощью read/write в нужные места. В С++ делать то же самое как с голым void*

vertexua ★★★★★
()
Последнее исправление: vertexua (всего исправлений: 1)

есть ли возможность передать данные в с++ код без копирования, без сериализации? так, чтобы с++ «разделял» ту же область памяти, что и java?

передавай ссылки на объекты (jobject), и выдергивай данные из них через JNI API.

_совсем_ без накладных расходов не будет в любом случае. жаба - она такая. как минимум 1 лишнее копирование всегда есть.

waker ★★★★★
()
Последнее исправление: waker (всего исправлений: 1)

как лучше передать данные в с++

В виде указателя!

Вангую, что никак. Но я не спец в йаве если что. Может можно твои объекты как-нибудь в FileChannel.map засунусть? Или в какой-нибудь shm? Но я не знаю, умеет ли вм такое делать или нет.

nanoolinux ★★★★
()

http://google.github.io/flatbuffers/md__java_usage.html

насколько я понял, можно сгенерировать одну и ту же схему в c++ и java. создать объект в java, потом передать ссылку на этот массив байт в с++, а там уже «выдергивать» объекты по такой же схеме. такой сценарий выполним?

jcdr
() автор топика
Ответ на: комментарий от jcdr

т.е. вовсе без копирования данных, передавая ссылку на память в с++?

jcdr
() автор топика

У java есть ffi к С. Ты можешь использовать его. Накладные расходы будут небольшие и память разделяемая. Но этот ffi очень неудобный.

Aswed ★★★★★
()

Есть ещё unsafe, позволяет работать с указателями и всё такое

GblGbl ★★★★★
()

Засунуть объект в shared memory и работать через corba?

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от m0rph

Спасибо, не обратил внимания сперва.

Через JNI тогда, разве что.

Adonai ★★★
()

медетируй :3

stevejobs@icecrown:/tmp/jni/$ cat testPin.c
#include <jni.h>

JNIEXPORT jclass JNICALL Java_TestPin_pinStringClass(JNIEnv * env, jclass clazz)
 {
     static jclass stringClass = NULL;

     if (stringClass == NULL) {
         jclass localRefCls =
             (*env)->FindClass(env, "java/lang/String");
         if (localRefCls == NULL) {
             return NULL; /* exception thrown */
         }
         /* Create a global reference */
         stringClass = (*env)->NewGlobalRef(env, localRefCls);

         /* The local reference is no longer useful */
         (*env)->DeleteLocalRef(env, localRefCls);

         /* Is the global reference created successfully? */
         if (stringClass == NULL) {
             return NULL; /* out of memory exception thrown */
         }
     }
stevejobs@icecrown:/tmp/jni/$ gcc -o libtestPin.so -shared -I/usr/lib/jvm/jdk/include -I/usr/lib/jvm/jdk/include/linux testPin.c -static
stevejobs@icecrown:/tmp/jni/$ cat TestPin.java
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import sun.misc.Unsafe;

public class TestPin
{
        public static native Class pinStringClass();
        static
        {
                System.loadLibrary("testPin");
        }

        public static void main(String[] args) throws Exception
        {
                Class foo = pinStringClass();
                System.out.println(getObjectAddress(foo));
                // Churn to force some GC.
                ArrayList<String> list = new ArrayList<String>();
                for (int i = 0; i < 1000000; i++)
                    list.add((String)foo.newInstance());
                System.out.println(getObjectAddress(foo));
        }

   private final static Unsafe   unsafe;
   private static final long     BITS;
   private static final long     OFF;
   private static final Object[] holder = new Object[1];

   static
   {
      try
      {
         ByteBuffer buffer = ByteBuffer.allocateDirect(1);
         Field unsafeField = buffer.getClass().getDeclaredField("unsafe");
         unsafeField.setAccessible(true);
         unsafe = (Unsafe) unsafeField.get(buffer);
         unsafeField.setAccessible(false);

         buffer.flip();
      }
      catch (Exception exc)
      {
         exc.printStackTrace();
         throw new InternalError();
      }

      BITS = unsafe.addressSize() * 8;
      OFF = unsafe.arrayBaseOffset(holder.getClass());
   }

   public static final synchronized long getObjectAddress(Object obj)
   {
      holder[0] = obj;
      if (BITS == 32)
         return unsafe.getInt(holder, OFF);
      if (BITS == 64)
         return unsafe.getLong(holder, OFF);
      throw new IllegalStateException();
   }

}
stevejobs@icecrown:/tmp/jni/$ javac TestPin.java
TestPin.java:4: warning: sun.misc.Unsafe is Sun proprietary API and may be removed in a future release
import sun.misc.Unsafe;
               ^
TestPin.java:25: warning: sun.misc.Unsafe is Sun proprietary API and may be removed in a future release
   private final static Unsafe   unsafe;
                        ^
TestPin.java:37: warning: sun.misc.Unsafe is Sun proprietary API and may be removed in a future release
         unsafe = (Unsafe) unsafeField.get(buffer);
                   ^
3 warnings

stevejobs@icecrown:/tmp/jni/$ LD_LIBRARY_PATH=. java -verbose:gc TestPin
-1321504640
[GC 896K->664K(5056K), 0.0059970 secs]
[GC 1560K->1456K(5056K), 0.0055870 secs]
[GC 2352K->2351K(5056K), 0.0064100 secs]
[GC 3247K->3247K(5056K), 0.0052960 secs]
[GC 4143K->4141K(5056K), 0.0060390 secs]
[GC 5037K->5036K(5960K), 0.0048390 secs]
[Full GC 5036K->4462K(5960K), 0.0485570 secs]
[GC 5358K->5356K(8400K), 0.0053860 secs]
[GC 6024K->6015K(8400K), 0.0046480 secs]
[GC 6911K->6911K(8400K), 0.0040350 secs]
[GC 7807K->7805K(8784K), 0.0063760 secs]
[Full GC 7805K->7288K(8784K), 0.0641510 secs]
[GC 8184K->8182K(13108K), 0.0054620 secs]
[GC 10241K->10240K(13108K), 0.0070920 secs]
[GC 11136K->11135K(13108K), 0.0062270 secs]
[GC 12031K->12029K(13108K), 0.0061340 secs]
[GC 12925K->12924K(13876K), 0.0064870 secs]
[Full GC 12924K->12149K(13876K), 0.0930100 secs]
[GC 15366K->15365K(21852K), 0.0107320 secs]
[GC 16837K->16836K(21852K), 0.0101650 secs]
[GC 18308K->18306K(21852K), 0.0291330 secs]
[GC 19778K->19778K(21852K), 0.0105530 secs]
[GC 20703K->20689K(22236K), 0.0078490 secs]
[Full GC 20689K->19304K(22236K), 0.1392640 secs]
[GC 24098K->24097K(34608K), 0.0165440 secs]
[GC 26273K->26272K(34608K), 0.0168730 secs]
[GC 28448K->28447K(34608K), 0.0402030 secs]
[GC 30623K->30622K(34608K), 0.0166760 secs]
[GC 30667K->30648K(34608K), 0.0016900 secs]
[Full GC 30648K->28903K(34608K), 0.1865680 secs]
[GC 36094K->36093K(51824K), 0.0243340 secs]
[GC 39357K->39355K(51824K), 0.0254730 secs]
[GC 42619K->42618K(51824K), 0.0263010 secs]
-1321504640
stevejobs@icecrown:/tmp/jni/$
stevejobs ★★★★☆
()
Ответ на: комментарий от migesok

Почему же не поверю? Реальность она такая, да. Когда нужно ехать на шашечки как правило плевать. И что это за названия такое „off-heap“? Если не в куче, то где)? Йависты совсем уже тютю.

By comparison, if your heap exceeds main memory size, your machine will become unusable, possibly requiring power cycling.

йависты, такие йависты)

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Эй чувак, я заметил, что тебе нравится управление памятью! Так что я добавил heap в твой heap чтобы ты мог управлять пока управляешь!

stevejobs ★★★★☆
()
Ответ на: комментарий от nanoolinux

Кое-кому кукушечку совсем от плюсов снесло. Ничего, пара месяцев на легаси Java EE проекте под строгим присмотром санитаров, и всё как рукой снимет.

migesok
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.