
Интеграция виртуальных машин .NET и JAVA.pptx
- Количество слайдов: 35
ИНТЕГРАЦИЯ ВИРТУАЛЬНЫХ МАШИН. NET И JAVA. NET MEETUP Мария Телятникова Григорий Кошелев Екатеринбург, 28 февраля 2017
Дисклеймер • Руковожу командой разработки (Java) • > 5 лет пилю Java энтерпрайз • (но слежу за развитием платформы. NET)
Задача XML XML . NET XML
Задача XML XML . NET XML PDF
Решение Apache FOP
Apache FOP • • • Начало разработки – неизвестно Передана в ASF в 1999 году Apache FOP 1. 0 – 21. 07. 2010 Apache FOP 1. 1 – 20. 10. 2012 Apache FOP 2. 0 – 03. 06. 2015 Apache FOP 2. 1 – 14. 01. 2016
Как использовать? • Переписать всё на C# • Использовать кросс-компиляцию * • Использовать из Java (*) IKVM
Как использовать? • Переписать всё на C# • Использовать кросс-компиляцию • Использовать из. Java
Java <->. NET • HTTP REST • Protobuf • g. RPC
g. RPC • Библиотека для удалённого вызова процедур • Поддерживаются: C/C++, Node. js, Python, Ruby, Objective-C, PHP, C# и Java • Первый публичный релиз – 26. 02. 2015 • g. RPC 1. 0. 0 – 19. 08. 2016 • g. RPC 1. 1. 2 – 08. 02. 2017
g. RPC • Protobuf 3 – описание типов данных и сериализация • HTTP/2 в качестве транспорта • Кодогенерация плагином для Protobuf
Standalone Java-сервис JVM protobuf C# КЛИЕНТ PC GR Java сервер
JVM внутри. NET-процесса JVM . NET процесс protobuf C# КЛИЕНТ PC GR Java сервер
Java Native Interface Java. VM *jvm; JNIEnv *env; Java. VMInit. Args args; Java. VMOption* options = new Java. VMOption[1]; options[0]. option. String = params; args. n. Options = 1; args. options = options; args. version = JNI_VERSION_1_6; args. ignore. Unrecognized = 0; int result = JNI_Create. Java. VM(&jvm, (void**)&env, &args);
Java Native Interface jclass program. Class = env->Find. Class("ru/kontur/Program "); jmethod. ID do. Smth. Method = env->Get. Static. Method. ID(program. Class, "do. Smth", "(ILjava/lang/String; )I"); jint int. Param = …; jstring. Param = …; jint result = env->Call. Static. Int. Method(program. Class, do. Smth. Method, int. Param, string. Param); package ru. kontur; public class Program { public static int do. Smth(int x, String str) { return 0; } }
C#-обёртка вокруг JNI
C#-обёртка вокруг JNI Java. Vm. Wrapper vm; Jni. Env. Wrapper env; unsafe { Int. Ptr env. P; Int. Ptr vm. P; Create. Java. Vm(&vm. P, &env. P, vm. Args. P); vm = new Java. Vm. Wrapper(vm. P); env = new Jni. Env. Wrapper(env. P); } var class. Ptr = env. Find. Class("ru/kontur/fop/service/Fop. Service. Server"); var constructor = env. Get. Method. Id(class. Ptr, "
Тестирование • • • Intel Core i 7 -4771, 3. 5 ГГц 16 ГБ ОЗУ Windows 7 Professional x 64 Java 8 (1. 8. 0_121). NET 4. 5
Тестирование • 10000 XML-документов (~ 1. 53 ГБ) • 1000 * 5 – на разогрев • 9000 – на замеряемый прогон -Xmx 512 m -Xms 512 m -Xss 1 m -XX: -Tiered. Compilation
Тестирование. NET процесс Standalone Java 59 468 ± 533 мс . NET процесс Java 60 496 ± 716 мс
Больше про C#, C++ и Java • Как запустить • Что нужно знать
Импорт JVM. dll [Dll. Import("kernel 32. dll", Entry. Point = "Load. Library. W")] private static extern Int. Ptr Load. Library([Marshal. As(Unmanaged. Type. LPWStr)] string name); [Dll. Import("kernel 32. dll", Entry. Point = "Free. Library")] private static extern bool Free. Library(Int. Ptr h. Module); [Dll. Import("kernel 32. dll", Entry. Point = "Get. Proc. Address")] private static extern Int. Ptr Get. Proc. Address(Int. Ptr h. Module, [Marshal. As(Unmanaged. Type. LPStr)] string name);
Marshal • System. Runtime. Interop. Services • Предоставляет методы для работы с неуправляемой памятью и кодом
Процедура создания JVM protected T Get. Delegate
C# и struct [Struct. Layout(Layout. Kind. Sequential)] public struct Jni. Native. Interface { struct JNINative. Interface { /*. . . */ private readonly Int. Ptr Get. Version; jint (JNICALL *Get. Version)(JNIEnv *env); private readonly Int. Ptr Define. Class; Jni. Native. Interface obj = jclass (JNICALL *Define. Class) (JNIEnv *env, (Jni. Native. Interface)Marshal. Ptr. To. Structure( const char *name, struct. Ptr, typeof(Jni. Native. Interface)); jobject loader, const jbyte *buf, jsize len); private readonly Int. Ptr Find. Class; jclass (JNICALL *Find. Class ) (JNIEnv *env, const char *name); /*. . . */ }
C# и union [Struct. Layout(Layout. Kind. Explicit)] public struct JValue typedef union jvalue { { [Field. Offset(0)] private boolean. Value; [Field. Offset(0)] private byte. Value; jbyte b; [Field. Offset(0)] private char. Value; jchar c; [Field. Offset(0)] private short. Value; jshort s; [Field. Offset(0)] private integer. Value; jint i; [Field. Offset(0)] private long. Value; jlong j; [Field. Offset(0)] private float. Value; jfloat f; [Field. Offset(0)] private double. Value; jdouble d; [Field. Offset(0)] private Int. Ptr pointer. Vlaue; } jboolean z; jobject l; } jvalue;
C#, Java и «нативные строки» jclass (JNICALL *Find. Class) (JNIEnv *env, const char *name); delegate Int. Ptr Find. Class ( Int. Ptr env, [Marshal. As(Unmanaged. Type. LPTStr)] string str); delegate Int. Ptr Find. Class ( Int. Ptr env, [Marshal. As(Unmanaged. Type. LPArray)] byte[] utf); U+0073 U+041 A U+0 BF 5 U+26218 Encoding. UTF 8. Get. Bytes(str); Латинская буква «s» (0 x 73) Кириллическая буква «К» (0 x. D 0 0 x 9 A) Символ года на тамильском « » (0 x. E 0 0 x. AF 0 x. B 5) Китайский иероглиф « » (0 x. F 0 0 x. A 6 0 x 88 0 x 98)
Указатели в нативную память • Ручное управление объектами, • размещёнными в нативной памяти Оборачиваем в IDisposable-обёртки
Загрузка классов public void Inject. Class(string class. Name, byte[] class. Bytes) { var loader. Class = new Java. Class. Loader. Class(env); var loader = loader. Class. Get. System. Class. Loader (); var loaded. Class = env. Define. Class( class. Name, loader, class. Bytes. Length); loaded. Class. Dispose(); }
Итоги • Запустили виртуальную машину Java внутри • • . NET процесса Реализовали обмен данными между программами на Java и на C# Получили готовый работающий прототип решения задачи конвертации документов
Что дальше? • Загружать Java-библиотеки разных версий • Попробовать передачу данных через • • • нативную память напрямую Проанализировать поведение виртуальных машин. NET и Java в одном процессе Понять, куда это богатство ещё применить Сделать C#-обёртку удобнее
Загадка Посмотрели на Performance Counter сборки мусора по поколениям (разница между значением счётчика после прогона и перед прогоном) Поколение ? ? ? 0 159 157 1 10 157 2 3 3
Загадка Почему так – будем думать и разбираться Поколение Inside Standalone 0 159 157 1 10 157 2 3 3
ВОПРОСЫ? Мария Телятникова Григорий Кошелев
Ссылки • • Apache FOP https: //xmlgraphics. apache. org/fop/ IKVM https: //www. ikvm. net/ Protobuf https: //developers. google. com/protocol-buffers/ g. RPC http: //www. grpc. io/ JNI http: //docs. oracle. com/javase/8/docs/technotes/guides/jni/spec/jni. TOC. html Interop Marshalling https: //msdn. microsoft. com/ruru/library/eaw 10 et 3(v=vs. 110). aspx Marshal https: //msdn. microsoft. com/ruru/library/system. runtime. interopservices. marshal(v=vs. 110). aspx