واجهة جافا الأصلية

واجهة جافا الأصلية (أو واجهة الأساليب الأصلية) هي واجهة وظائف خارجية مصممة لأطر البرمجة غير المكتوبة بلغة جافا . تُمكّن JNI شيفرة جافا من استدعاء الشيفرة الأصلية (أي أي شيفرة تستخدم واجهة التطبيقات الثنائيةJNIEnv C وتتفاعل معها ) والتطبيقات الأصلية (البرامج الخاصة بمنصة أجهزة ونظام تشغيل ) والمكتبات المكتوبة بلغات أخرى مثل C و C++ ولغة التجميع ، كما تُمكّنها من أن تُستدعى من قبلها . [ 1 ] [ 2 ] [ 3 ]

يُقدّم الإصدار 22 من جافا واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة ، والتي يُمكن اعتبارها خليفةً لواجهة جافا الأصلية. [ 4 ] [ 5 ]

أهداف

تتيح JNI استخدام الدوال الأصلية لتمكين التطبيقات من إجراء استدعاءات خارج منصة Java، على سبيل المثال عندما لا تدعم مكتبة فئات Java القياسية ميزات خاصة بمنصة معينة أو مكتبة برمجية محددة. كما تُستخدم لتعديل تطبيق موجود (مكتوب بلغة برمجة أخرى) ليصبح متاحًا لتطبيقات Java. تعتمد العديد من فئات المكتبة القياسية على JNI لتوفير وظائف للمطور والمستخدم، مثل عمليات إدخال/إخراج الملفات وواجهات برمجة تطبيقات الصوت. يُسمح فقط للتطبيقات والتطبيقات المصغّرة الموقّعة باستدعاء JNI.

يُتيح إطار عمل JNI للبرامج الأصلية معالجة كائنات جافا واستخدامها . يمكن للدالة الأصلية (المُشار إليها بالكلمة المفتاحية nativeفي جافا) إنشاء كائنات جافا وفحصها واستخدامها لتنفيذ مهامها. كما يمكن للدالة الأصلية فحص واستخدام الكائنات التي أنشأها كود تطبيق جافا.

يفقد التطبيق الذي يعتمد على JNI قابلية نقل النظام الأساسي التي توفرها Java (الحل الجزئي هو كتابة تطبيق منفصل لرمز JNI لكل نظام أساسي وجعل Java تكتشف نظام التشغيل وتحمل النظام الصحيح في وقت التشغيل).

لا يقتصر الأمر على إمكانية تفاعل الكود الأصلي مع جافا، بل يمكنه أيضًا الرسم على جافا Canvas، وهو أمر ممكن باستخدام واجهة جافا الأصلية AWT ، المتوفرة منذ J2SE 1.3.

تتيح JNI أيضًا الوصول المباشر إلى لغة التجميع ، دون الحاجة إلى وسيط C. [ 6 ] كما يُمكن الوصول إلى تطبيقات Java من لغة التجميع بنفس الطريقة. [ 7 ]

JNI هي نقطة الدخول بين اللغات المستخدمة لبدء تشغيل JVM. [ 8 ] [ 9 ] [ 10 ] [ 11 ]

أنواع التعيين

أنواع جافا هي الأنواع الأولية الافتراضية المتوفرة في جافا، بينما تُستخدم توقيعات أنواع JVM كمعرفات من قِبل JVM لتحديد مطابقة الأنواع في جافا، أما الأنواع الأصلية فهي أنواع مُعرَّفة بواسطة JNI نفسه لربطها بالأنواع الأصلية. بالنسبة للأنواع الأولية، يتم توفير تعريفات الأنواع التالية: [ 12 ]

نوع جافا تعريف نوع أصلي وصف توقيع نوع JVM أقرب نوع أصلي
booleanjboolean8 بتات غير موقعةZbool
bytejbyteموقّع 8 بتبcharأوint8_t
charjcharعدد غير موقع 16 بتجchar16_t
shortjshortموقّع 16 بتSshortأوint16_t
intjintموقّع 32 بتأناintأوint32_t
longjlongموقّع 64 بتجlongأوint64_t
floatjfloat32 بتFfloatأوfloat32_t
doublejdouble64 بتدdoubleأوfloat64_t
voidvoidغير قابل للتطبيقVvoid

بالإضافة إلى ذلك، يشير توقيع نوع JVM إلى الفئة المحددة بشكل فريد بهذا الاسم، على سبيل المثال، يشير التوقيع ( في ملفات الفئات ) إلى الفئة . يشير البادئة إلى التوقيع إلى مصفوفة من هذا النوع؛ على سبيل المثال، يشير إلى ، ويشير إلى ، بحد أقصى 255 بُعدًا.Lfully-qualified-class;Ljava.lang.String;Ljava/lang/String;java.lang.String[[Iint[][[Iint[][]

هذه الأنواع قابلة للتبديل. يمكنك استخدام النوع `string` jintحيث تستخدم النوع `string` عادةً int، والعكس صحيح، دون الحاجة إلى أي تحويل للأنواع . مع ذلك، يختلف الربط بين سلاسل Java النصية والمصفوفات والسلاسل النصية والمصفوفات الأصلية؛ على سبيل المثال، `string` jstringو`string` char*ليسا نوعين قابلين للتبديل، وكذلك `string` jintArrayو`string` int[].

يحتوي JNI أيضًا على التصريحات التالية لأنواع المراجع في Java في <jni.h>: [ 13 ]

#ifdef __cplusplus class _jobject {}; class _jclass : public _jobject {}; // ... typedef _jobject * jobject ; typedef _jclass * jclass ; // ... #else struct _jobject ; // ... typedef struct _jobject * jobject ; typedef jobject jclass ; // ... #endif

هنا، تُعرَّف جميع أنواع المراجع في جافا على أنها أنواع فارغة مبهمة تعمل كمقابض لكائنات جافا. لا ينبغي فك مرجعية هذه الأنواع. [ 14 ]

نوع جافا اسم المستخدم JNI
java.lang.Objectjobject
java.lang.Class(غير عام)jclass
java.lang.Throwablejthrowable
java.lang.Stringjstring
T[](لنوع معين T)jarray
boolean[]jbooleanArray
byte[]jbyteArray
char[]jcharArray
short[]jshortArray
int[]jintArray
long[]jlongArray
float[]jfloatArray
double[]jdoubleArray
java.lang.Object[]jobjectArray

بالإضافة إلى ذلك، تُستخدم الأنواع المعتمة التالية كمقابض:

كائن وصفي من فئة جافا اسم المستخدم JNI
حقل الفئةjfieldID
طريقة الفئةjmethodID

لاحظ مع ذلك أن jfieldIDو jmethodIDمجرد مقابض مبهمة، ولا تتوافق مع java.lang.reflect.Field/ java.lang.reflect.Method.

تصميم

يتم التوسط في الاتصال بين الكود الأصلي وكود جافا بواسطة JNI، الذي يعمل كواجهة تطبيق ثنائية (ABI) .

// ملف jni.hstruct JNINativeInterface_ ; struct JNIEnv_ ;#ifdef __cplusplus typedef JNIEnv_ JNIEnv ; #else typedef const struct JNINativeInterface_ * JNIEnv ; #endif

JNIEnvيُستخدم للوصول إلى بنية الدوال (مصفوفة من مؤشرات الدوال)، حيث يمكن تحديد كل دالة بواسطة مؤشر فريد. [ 15 ] قد يختلف التنفيذ قليلاً باختلاف لغة البرمجة، سواء كانت C أو C++. [ 16 ] على سبيل المثال، في لغة C:

// ملف jni.hstruct JNINativeInterface_ {jint ( JNICALL * GetVersion ) // تعريف مؤشر JNICALL لتحديد الدالة المحددة؛ ( JNIEnv * env ); // المعامل env هو مؤشر إلى مؤشر JNIEnv، أي مؤشر إلى مؤشر؛jclass ( JNICALL * DefineClass ) ( JNIEnv * env , const char * name );jclass ( JNICALL * FindClass ) ( JNIEnv * env , const char * name );// مؤشرات الدوال الأخرى... }

تطبيق

في إطار عمل JNI، تُنفَّذ الدوال الأصلية في ملفات .c أو .cpp منفصلة (توفر لغة C++ واجهة أبسط قليلاً مع JNI). عندما تستدعي JVM الدالة، فإنها تُمرِّر إليها وسيطًا من نوع `<div>` ، ووسيطًا من نوع `<div>` ، وأي وسيطات Java مُعلنة بواسطة دالة Java. على سبيل المثال، يُحوِّل الكود التالي إلى `<div>` :JNIEnv*jobjectjstringconst char*

خارجي "C" {JNIEXPORT void JNICALL Java_ClassName_MethodName ( JNIEnv * env , jobject obj , jstring javaString ) { const char * أصليString = env -> GetStringUTFChars ( javaString , 0 );// قم بتنفيذ إجراء ما باستخدام السلسلة الأصليةenv -> ReleaseStringUTFChars ( javaString , nativeString ); }}

المؤشر envهو بنية تحتوي على واجهة JVM. يتضمن جميع الدوال اللازمة للتفاعل مع JVM والتعامل مع كائنات Java. يمكن تنفيذ أي شيء يمكن لرمز Java فعله باستخدام المؤشر JNIEnv. الوسيط objهو مرجع إلى كائن Java الذي تم تعريف هذه الدالة الأصلية داخله.

يمكن ربط أنواع البيانات الأصلية بأنواع بيانات جافا أو العكس. أما بالنسبة للأنواع المركبة، مثل الكائنات والمصفوفات والسلاسل النصية ، فيجب على الكود الأصلي تحويل البيانات بشكل صريح عن طريق استدعاء الدوال في JNIEnv.

يُمرَّر مؤشر بيئة JNI JNIEnv*كوسيط لكل دالة أصلية مُرتبطة بطريقة Java، مما يسمح بالتفاعل مع بيئة JNI داخل الطريقة الأصلية. يمكن تخزين مؤشر واجهة JNI هذا، ولكنه يظل صالحًا فقط في الخيط الحالي. يجب على الخيوط الأخرى استدعاء دالة الربط أولاً AttachCurrentThread()لربط نفسها بالآلة الافتراضية والحصول على مؤشر واجهة JNI. بمجرد الربط، يعمل الخيط الأصلي كخيط Java عادي يعمل داخل طريقة أصلية. يبقى الخيط الأصلي مرتبطًا بالآلة الافتراضية حتى يستدعي DetachCurrentThread()دالة الفصل. [ 17 ]

لا يوفر إطار عمل JNI أي آلية لجمع البيانات المهملة تلقائيًا لموارد الذاكرة غير التابعة لـ JVM والمخصصة بواسطة التعليمات البرمجية التي تُنفذ على جانب النظام الأصلي. وبالتالي، فإن التعليمات البرمجية الأصلية هي المسؤولة عن تحرير جميع الموارد المكتسبة بشكل صريح.

في أنظمة لينكس وسولاريس، إذا سجل الكود الأصلي نفسه كمعالج إشارات، فإنه يستطيع اعتراض الإشارات الموجهة إلى آلة جافا الافتراضية (JVM). ويمكن استخدام سلسلة المسؤولية لتمكين الكود الأصلي من التفاعل مع آلة جافا الافتراضية. أما في أنظمة ويندوز، فيمكن استخدام معالجة الاستثناءات المهيكلة (SEH) لتغليف الكود الأصلي في كتل SEH try، catchوذلك لالتقاط مقاطعات البرامج التي يُولدها الجهاز (وحدة المعالجة المركزية/وحدة معالجة الفاصلة العائمة) (مثل عمليات فك مرجعية المؤشر الفارغ وعمليات القسمة على صفر)، ومعالجة هذه الحالات قبل أن تنتقل المقاطعة مرة أخرى إلى آلة جافا الافتراضية (أي كود جافا).

تستخدم الدوال و و و ترميز NewStringUTF()" GetStringUTFLength()UTF GetStringUTFChars()- 8 المعدل " [18]، وهو ترميز مختلفReleaseStringUTFChars() عن ترميز UTF-8 الصحيح لجميع المدخلات. يتم ترميز الحرف الفارغ (U+0000) ونقاط الترميز غير الموجودة على المستوى متعدد اللغات الأساسي (أكبر من أو تساوي U+10000، أي تلك المُمثلة كأزواج بديلة في UTF-16 ) بشكل مختلف في UTF-8 المعدل. تستخدم العديد من البرامج هذه الدوال بشكل خاطئ، حيث تتعامل مع سلاسل UTF-8 المُعادة أو المُمررة إليها كسلاسل UTF-8 قياسية بدلاً من سلاسل UTF-8 المعدلة. ينبغي على البرامج استخدام الدوال و و و و و و التي تستخدم ترميز UTF-16LE على معمارية little-endian وترميز UTF-16BE على معمارية big-endian ، ثم استخدام روتين تحويل من UTF-16 إلى UTF-8.GetStringUTFRegion()NewString()GetStringLength()GetStringChars()ReleaseStringChars()GetStringRegion()GetStringCritical()ReleaseStringCritical()

على سبيل المثال، يوضح ما يلي تطبيقًا أصليًا لطريقة جافا HelloJNI::sayHello():

#include <stdio.h> #include <jni.h>JNIEXPORT void JNICALL Java_HelloJNI_sayHello ( JNIEnv * env , jobject obj ) { printf ( "مرحباً من لغة C! \n " ); }

ثم، في لغة جافا، يتم استدعاء الدالة على النحو التالي:

public class HelloJNI { static { // "hello" يشير إلى libhello.so على نظام Linux System.loadLibrary ( "hello" ) ; // System.load() هي طريقة أخرى لتحميل مكتبة. }public native void sayHello ();public static void main ( String [] args ) { new HelloJNI (). sayHello (); } }

أداء

يتكبد JNI تكاليف إضافية كبيرة وخسائر في الأداء في ظل ظروف معينة: [ 19 ]

  • تُعد استدعاءات الدوال لأساليب JNI مكلفة، خاصة عند استدعاء أسلوب معين بشكل متكرر.
  • لا يتم تضمين الطرق الأصلية بواسطة JVM، ولا يمكن تجميع الطريقة في الوقت المناسب ، لأن الطريقة مجمعة بالفعل.
  • يمكن نسخ مصفوفة جافا للوصول إليها في الكود الأصلي، ثم نسخها مرة أخرى لاحقًا. وتتناسب التكلفة طرديًا مع حجم المصفوفة.
  • إذا تم تمرير كائن إلى الدالة، أو احتاجت إلى استدعاء دالة رد نداء، فمن المرجح أن تقوم الدالة الأصلية باستدعاءات خاصة بها إلى آلة جافا الافتراضية (JVM). يؤدي الوصول إلى حقول جافا، والدوال، والأنواع من الكود الأصلي إلى استدعاء انعكاس جافا . يتم تحديد التوقيعات كسلاسل نصية ويتم الاستعلام عنها من آلة جافا الافتراضية. هذا الأسلوب بطيء وعرضة للأخطاء.
  • تُعتبر سلاسل جافا كائنات، ولها طول، ويتم ترميزها. قد يتطلب الوصول إلى سلسلة أو إنشائها...يا(ن){\displaystyle O(n)}ينسخ.

واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة

قدمت Java 22 واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة (Foreign Function and Memory API)، والتي java.lang.foreignيمكن اعتبارها خليفةً لواجهة Java الأصلية (JNI). [ 20 ] تتميز بواجهة أبسط وتتطلب عادةً كتابة أكواد أقل من JNI، نظرًا لعدم الحاجة إلى تضمينها <jni.h>في المكتبة الخارجية لاستدعائها، كما أنها تُجرّد استخدام الكلمة nativeالمفتاحية تمامًا. تدعم هذه الواجهة إدارة الذاكرة القائمة على المناطق . يُمثل الصنف java.lang.foreign.MemorySegmentجزءًا متجاورًا من الذاكرة، والذي قد يقع داخل أو خارج كومة JVM، ويتم java.lang.foreign.MemorySegmentتخصيصه باستخدام java.lang.foreign.Arenaمُتحكم يتحكم في عمر منطقة الذاكرة التي تدعم الجزء المُخصص منها.

يقدم java.lang.foreign.Arenaأنواع الساحات التالية: [ 21 ]

نوع الساحة أسلوب المصنع عمر محدود قابل للإغلاق بشكل صريح يمكن الوصول إليه من عدة خيوط
عالميArena.global()لالانعم
معادلةArena.ofAuto()نعملانعم
محصورArena.ofConfined()نعمنعملا
مشتركArena.ofShared()نعمنعمنعم
package org.wikipedia.examples ;استيراد java.lang.foreign.Arena ؛ استيراد java.lang.foreign.MemorySegment ؛ استيراد java.lang.foreign.ValueLayout ؛public class ForeignMemoryExample { public static void main ( String [] args ) { try ( Arena arena = Arena . ofConfined ()) { MemorySegment segment = arena . allocate ( 5 * Double . BYTES ); for ( int i = 0 ; i < 5 ; ++ i ) { segment . setAtIndex ( ValueLayout . JAVA_DOUBLE , i , i * 1.1 ); }for ( int i = 0 ; i < 5 ; ++ i ) { double value = segment.getAtIndex ( ValueLayout.JAVA_DOUBLE , i ) ; System.out.printf ( " القيمة عند الفهرس % d: %d% n " , i , value ) ; } } } }

بمعنى ما، تسمح واجهة برمجة تطبيقات Java Foreign Function and Memory بتخصيص الذاكرة بشكل مباشر خارج كومة JVM (أي كومة نظام التشغيل)، من خلال Arena.allocate()و MemorySegment.allocateNative()التي تقوم بتخصيص الذاكرة الخام مباشرة، بينما يتم استخدام Arena.close()و MemorySegment.close()لإلغاء تخصيص / تحرير جزء الذاكرة.

باعتبارها واجهة وظيفة خارجية ، يتم توفير الفئات java.lang.foreign.Linkerللوصول بين الوظائف الخارجية من Java (من وإلى)، java.lang.foreign.SymbolLookupلاسترداد عنوان رمز في مكتبة، java.lang.foreign.FunctionDescriptorولنمذجة توقيع وظيفة خارجية.

package org.wikipedia.examples ;استيراد java.lang.foreign.Arena ؛ استيراد java.lang.foreign.FunctionDescriptor ؛ استيراد java.lang.foreign.Linker ؛ استيراد java.lang.foreign.MemorySegment ؛ استيراد java.lang.foreign.SymbolLookup ؛ استيراد java.lang.foreign.ValueLayout ؛ استيراد java.lang.invoke.MethodHandle ؛public class ForeignFunctionExample { public static void main ( String [] args ) throws Throwable { Linker linker = Linker . nativeLinker (); SymbolLookup stdlib = linker . defaultLookup (); MethodHandle printf = linker . downcallHandle ( stdlib . findOrThrow ( "printf" ), FunctionDescriptor . of ( ValueLayout . JAVA_INT , ValueLayout . ADDRESS ) );MethodHandle strlen = linker.downcallHandle ( stdlib.findOrThrow ( " strlen " ) , FunctionDescriptor.of ( ValueLayout.JAVA_LONG , ValueLayout.ADDRESS ) ) ;try ( Arena arena = Arena . ofConfined ()) { MemorySegment formatString = arena . allocateUtf8String ( "Hello, %s!\n" ); MemorySegment argString = arena . allocateUtf8String ( "World" ); printf . invokeExact ( formatString , argString ); // يطبع "Hello, World!" long len = ( long ) strlen . invokeExact ( formatString ); // len = 5 } } }

يتم تصميم التخطيطات بواسطة java.lang.foreign.ValueLayout، والتي تتكون من:

يكتب اسم وصف
java.lang.foreign.AddressLayoutADDRESSتخطيط عنوان بنفس حجمsize_t
java.lang.foreign.AddressLayoutADDRESS_UNALIGEDتخطيط عناوين غير محاذٍ بنفس الحجمsize_t
java.lang.foreign.ValueLayout.OfBooleanJAVA_BOOLEANثابت تخطيط القيمة بنفس حجم Javaboolean
java.lang.foreign.ValueLayout.OfByteJAVA_BYTEثابت تخطيط القيمة بنفس حجم Javabyte
java.lang.foreign.ValueLayout.OfCharJAVA_CHARثابت تخطيط القيمة بنفس حجم Javachar
java.lang.foreign.ValueLayout.OfCharJAVA_CHAR_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javachar
java.lang.foreign.ValueLayout.OfShortJAVA_SHORTثابت تخطيط القيمة بنفس حجم Javashort
java.lang.foreign.ValueLayout.OfShortJAVA_SHORT_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javashort
java.lang.foreign.ValueLayout.OfIntJAVA_INTثابت تخطيط القيمة بنفس حجم Javaint
java.lang.foreign.ValueLayout.OfIntJAVA_INT_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javaint
java.lang.foreign.ValueLayout.OfLongJAVA_LONGثابت تخطيط القيمة بنفس حجم Javalong
java.lang.foreign.ValueLayout.OfLongJAVA_LONG_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javalong
java.lang.foreign.ValueLayout.OfFloatJAVA_FLOATثابت تخطيط القيمة بنفس حجم Javafloat
java.lang.foreign.ValueLayout.OfFloatJAVA_FLOAT_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javafloat
java.lang.foreign.ValueLayout.OfDoubleJAVA_DOUBLEثابت تخطيط القيمة بنفس حجم Javadouble
java.lang.foreign.ValueLayout.OfDoubleJAVA_DOUBLE_UNALIGNEDتخطيط قيمة غير محاذٍ بنفس حجم Javadouble

تتلقى الأنواع الأولية ValueLayout.JAVA_*تخطيطات عند تعيينها لأنواعها الأصلية، بينما تستخدم أنواع المؤشرات ValueLayout.ADDRESS(على سبيل المثال char*، int**أو struct Point*).

بالإضافة إلى ذلك، فإن الثابت MemorySegment.NULL(من النوع java.lang.foreign.MemorySegment) هو مقطع أصلي بطول صفر يمثل عنوانًا فارغًا ( nullptr)، وهو ما يعادل MemorySegment.ofAddress(0).

توفر لغة جافا طرقًا إضافية للتعبير عن أنواع البيانات الأصلية الأكثر تعقيدًا. على سبيل المثال، أنواع البيانات الأصلية التالية [ 22 ]

struct Point { int x ; long y ; };اتحاد الاختيار { عدد عشري أ ; عدد صحيح ب ; };

استلم التصاميم التالية:

استيراد java.lang.foreign.MemoryLayout ؛ استيراد java.lang.foreign.StructLayout ؛ استيراد java.lang.foreign.UnionLayout ؛StructLayout pointLayout = MemoryLayout.structLayout ( ValueLayout.JAVA_INT.withName ( " x " ) , MemoryLayout.paddingLayout ( 4 ) , ValueLayout.JAVA_LONG.withName ( " y " ) } ;UnionLayout choiceLayout = MemoryLayout.unionLayout ( ValueLayout.JAVA_FLOAT.withName ( " a " ) ) , ValueLayout.JAVA_INT.withName ( " b " ) ) ;

البدائل

تم إنشاء واجهة وقت تشغيل جافا بواسطة نتسكيب كسابقة. [ 23 ]

كان لدى تطبيق مايكروسوفت الخاص لآلة جافا الافتراضية ( Visual J++ ) آلية مشابهة لاستدعاء التعليمات البرمجية الأصلية من جافا، تُسمى واجهة RNI (الواجهة الأصلية الخام). بالإضافة إلى ذلك، وفرت طريقة سهلة لاستدعاء التعليمات البرمجية الأصلية الموجودة التي لا تدعم جافا، مثل (على سبيل المثال لا الحصر) واجهة برمجة تطبيقات ويندوز (J/Direct). مع ذلك، وبعد الدعوى القضائية بين صن ومايكروسوفت بشأن هذا التطبيق، توقف دعم Visual J++ . كان استخدام RNI أسهل من JNI، لأنه لم يكن يتطلب إدارة مؤشر بيئة جافا؛ بل كان يتم الوصول إلى جميع كائنات جافا مباشرةً. ولتسهيل ذلك، استُخدمت أداة لإنشاء ملفات رأسية من فئات جافا. وبالمثل، كان استخدام J/Direct أسهل من استخدام المكتبة الأصلية الوسيطة اللازمة وJNI.

مكتبة Java Native Access (JNA) هي مكتبة طوّرها المجتمع، تُتيح لمبرمجي جافا الوصول بسهولة إلى المكتبات المشتركة الأصلية دون استخدام JNI. مع ذلك، يتطلب هذا إعادة توزيع مكتبة JAR التابعة. يكمن المقابل في كون JNI أكثر تعقيدًا وJNA أبطأ، بالإضافة إلى أنها ليست مدمجة مثل JNI. [ 24 ]

تاريخيًا، كان مُجمِّع GCC (حتى الإصدار 7) يُقدِّم مُجمِّع GNU للغة Java . وقدَّم هذا المُجمِّع واجهة Compiled Native Interface (CNI)، التي سمحت بالتوافق المباشر بين لغتي C++ و Java. كما وفَّر واجهة برمجة تطبيقات (API) تعتمد بشكل كبير على JNI نفسها. [ 25 ] وقد ادَّعى العديد من المزايا على JNI، حيثُ كان يُمثِّل فئات Java مباشرةً كفئات C++ . [ 26 ]

منذ إصدار Java 22، حلت واجهة برمجة التطبيقات للوظائف الخارجية والذاكرة محل JNI، وذلك بسبب تقليلها للرموز النمطية وتبسيط واجهتها. [ 20 ]

انظر أيضاً

مراجع

  1. "نظرة عامة على واجهة جافا الأصلية" . دليل ومواصفات مبرمج واجهة جافا الأصلية . تم الاطلاع عليه بتاريخ 27-12-2018 .
  2. "نظرة عامة على واجهة جافا الأصلية SE 7" .
  3. "استخدام JNIEnv الخاطئ" .
  4. "مشروع بنما (JDK 22)" .
  5. ^ "مواصفات JNI (Java SE 25)" .
  6. "استدعاء برامج لغة التجميع من جافا" . Java.net. 19-10-2006. مؤرشف من الأصل في 30-03-2008 . تم الاطلاع عليه في 06-10-2007 .
  7. "تشغيل تطبيقات جافا من برامج لغة التجميع" . Java.net. ١٩ أكتوبر ٢٠٠٦. مؤرشف من الأصل في ١١ أكتوبر ٢٠٠٧. تم الاطلاع عليه في ٤ أكتوبر ٢٠٠٧ .
  8. "إنشاء JVM" .
  9. "نظرة معمقة على بدء تشغيل JVM" .
  10. "إنشاء رأس JVM (شفرة المصدر)" .
  11. "إنشاء تطبيق JVM (شفرة المصدر)" .
  12. "أنواع JNI وهياكل البيانات" .
  13. ^ OpenJDK (13 نوفمبر 2024). "openjdk/jdk - jni.h" . جيثب.كوم . OpenJDK.
  14. بنجامين كروفورد بيرس. "برمجة JNI في لغة C++" . cis.upenn.edu . جامعة بنسلفانيا . تم الاطلاع عليه بتاريخ 12 يونيو 2026 .
  15. "نظرة عامة على تصميم JNI" .
  16. "شفرة مصدر JNI" .
  17. واجهة برمجة تطبيقات الاستدعاء. صن مايكروسيستمز. https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html
  18. "أنواع JNI وهياكل البيانات" .
  19. "جافا: ما الذي يجعل استدعاءات JNI بطيئة؟" . ستاك أوفر فلو .
  20. 1 2 "JEP 454: واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة" . OpenJDK. 7 أبريل 2025.
  21. شركة أوراكل (15 يونيو 2026). "ساحة الواجهة" . docs.oracle.com . شركة أوراكل.
  22. شركة أوراكل (15 يونيو 2026). "رابط الواجهة" . docs.oracle.com . شركة أوراكل.
  23. "الخلفية التاريخية" .
  24. زاكوسيلو، ألكسندر. "يُعدّ GitHub أيضًا المصدر الأصلي لـ JNA. اختبارات سرعة قياس أداء JNA مقابل JNI" . GitHub . تم الاطلاع عليه بتاريخ 30 مارس 2023 .
  25. مشروع جنو. "11.17 انعكاس" . gcc.gnu.org . مشروع جنو . تم الاسترجاع في 22 مايو 2026 .
  26. الأسئلة الشائعة حول مشروع جنو – مشروع جنو – مؤسسة البرمجيات الحرة (FSF)

فهرس