تسلسل
يدرس هذه المقالة بشكل أساسي بعض الاحتياطات للهجرة إلى Java9.
أنواع الهجرة
بعض الأشياء التي يجب ملاحظتها
فصول غير قابلة للقراءة
على سبيل المثال ، تم تصنيف Sun.Security.x509 في وحدة Java.base في Java9 ، لكن الوحدة لا تصدر الحزمة.
يمكنك تعديل إعدادات الصادرات عن طريق الإضافة-ADD-PEXPORTS
الطبقة الداخلية
على سبيل المثال ، أرادت Sun.Misc.Unsafe في الأصل استخدام فريق Oracle JDK ، ولكن نظرًا لأن هذه الفئات تستخدم على نطاق واسع للغاية ، فقد جعلت Java9 تنازلات من أجل التوافق المتخلف ، ولكن تصنف هذه الفصول فقط في الوحدة النمطية JDK.Unsupported ، ولم تحد من قابلية القراءة.
➜ ~ java -d jdk.unsupportedjdk.unsupported@9exports com.sun.nio.fileexports sun.miscexports sun.reflectrequires
فئة محذوفة
Java9 حذفت Sun.Misc.base64encoder ، في هذه الحالة ، يمكنك فقط استخدام واجهات برمجة التطبيقات الأخرى بدلاً من ذلك ، مثل java.util.base64
classpath vs module-path
قدمت Java9 نظام الوحدة النمطية ، وتم تعديل JDK الخاص به أيضًا ، وتم تقديم مسار الوحدة النمطية إلى Block ClassPath. وهذا يعني أن مسار الوحدة النمطية مفضل في Java9. بعد كل شيء ، JDK نفسه هو وحدات. إذا لم يكن التطبيق نفسه معياريًا ، فسيتم تعديل Java9 ضمنيًا من خلال وحدات غير مسموعة وآليات الوحدات التلقائية. بالطبع ، يمكن استخدام ClassPath على Java9 ، مثل استخدام المسار النمطية.
سيتم تصنيف جرة بدون وحدات على أنها وحدات لم تسمها في ClassPath ؛ في مسار الوحدة النمطية ، سيتم إنشاؤه تلقائيًا كوحدات تلقائية (سوف تعلن وحدة تلقائية أن الانتقال يعتمد على جميع الوحدات المسمى وغير المعلوم ، ثم تصدير الحزمة الخاصة بها)
لا يمكن أن يظهر اسم الحزمة في وحدات متعددة (حزم تقسيم)
نظرًا لأنه يمكن تحديد الصادرات إلى وحدات أخرى في الوحدات النمطية ، إذا كانت الوحدات النمطية المتعددة تصدر نفس اسم الحزمة ، فسيؤدي ذلك إلى حدوث ارتباك. خاصة إذا كانت هناك مكتبات فصول أخرى تتطلب هاتين الوحدات في نفس الوقت ، فأنت لا تعرف الوحدة التي يجب الرجوع إليها.
تبعيات متعدية
إذا استخدمت معلمات الواجهة أو نوع الإرجاع للوحدة النمطية فئات الوحدات الأخرى ، فمن المستحسن أن تتطلب وحدات متعدية يعتمد عليها.
كن حذرا من التبعيات الدائرية
عند تصميم الوحدات ، فكر فيما إذا كانت هناك تبعيات دائرية قدر الإمكان. إذا كان الأمر كذلك ، فأنت بحاجة إلى إعادة تصميمها.
استخدم الخدمات لتنفيذ تبعيات اختيارية
الخدمات مناسبة بشكل خاص لفصل تبعيات المتصلين وفئات التنفيذ. إذا كانت الواجهة تحتوي على فئات تنفيذ متعددة ، فلن يحتاج المتصل إلى طلب جميع فئات التنفيذ ، ولكنه يتطلب فقط واجهة المتطلبات ، واستخدام نوع الخدمات لتحميل مثيلات فئة التنفيذ. يتم تحقيق فك الارتباط عن طريق إضافة وحدات التنفيذ ديناميكيًا في مسار الوحدة النمطية.
إدارة إصدار الوحدة النمطية
لا يدعم Module-info.java أرقام الإصدار ، ولكن عند إنشاء حزم جرة ، يمكنك تعيينها من خلال-وحدة. ومع ذلك ، عندما يبحث نظام الوحدة النمطية عن الوحدات النمطية ، فإنه لا يزال يستخدم اسم الوحدة النمطية للبحث (إذا كانت هناك وحدات مكررة متعددة في مسار الوحدة النمطية ، فإن نظام الوحدة النمطية سيعرف استخدام الأول الموجود ويتجاهل تلقائيًا الوحدة النمطية اللاحقة بنفس الاسم). مشكلة التبعية في الإصدار ليست ضمن نطاق حل نظام الوحدة النمطية ، ويترك لأدوات إدارة التبعية مثل Maven لإدارتها.
وحدة الوصول إلى الموارد
بعد modularization ، يتم حماية ملف المورد أيضًا ، ويمكن للوحدة الوصول فقط إلى ملف المورد للوحدة نفسها. إذا كان الوصول عبر الوحدة المتقاطعة مطلوبًا ، فيجب عليك أيضًا استخدام ModuleLayer للعثور على الوحدة النمطية الهدف ، ثم اتصل بالوحدة النمطية المستهدفة لتحميل ملف المورد للوحدة.
استخدام الانعكاس
وهذا ينطوي على قضية الانعكاس العميق. ما يسمى الانعكاس العميق هو استدعاء العنصر غير العام للطبقة من خلال التفكير. تعلن صادرات الوحدة النمطية-java أن الحزمة تسمح فقط للفصل الذي تنتمي إليه الحزمة مباشرة للوصول إلى عنصرها العام ، ولا تسمح لمكالمات الانعكاس بالعناصر غير العامة.
يحتاج الانعكاس إلى إعلانات خاصة مسموح بها في نظام الوحدة النمطية (باستخدام إعلانات الفتح للسماح بالتفكير العميق) ، مما يؤدي إلى العديد من مكتبات الفصل التي تستخدم انعكاسًا مثل الربيع ، والتي تتطلب ترحيل تكوين إضافي إلى Java9. هناك حلان: أحدهما هو فتح اسم الحزمة للوحدات النمطية التي تحتاج إلى انعكاس ، مثل Spring.beans ، إلخ ؛ والآخر هو فتح الوحدة بالكامل مباشرة.
الافتراضي-illegal-access = تصريح ، وهذا الإعداد ينطبق فقط على الحزم قبل Java9 التي لا يُسمح بالوصول إليها في Java9 ، ولا تنطبق على الحزم الجديدة التي لا يُسمح للوصول إليها في Java9. (يوصى بتعيينه على رفضه عند الترحيل إلى نظام معياري)
ومع ذلك ، في نظام الوحدة النمطية ، تختلف أسماء الحزم ، ولا توجد علاقة ميراث. على سبيل المثال ، com.service.func1 و com.service.func2 هي حزم مختلفة. لا يمكنك فتح com.service فقط ، ولكن يجب عليك تحديدها بشكل منفصل ، مما يؤدي إلى المزيد من الحزم التي تتطلب الفتح. لذلك ، قد يكون فتح الوحدة بأكملها أسهل في الاستخدام ، لكنها أيضًا نهج تقريبي نسبيًا.
الطريقة أعلاه هي إجراء تغييرات في الوحدة الأصلية info.java. هناك طريقة أخرى تتمثل في تعديل العلاقة الأصلية من خلال الأمر المحدد عند تنفيذ Java أو Javac. على سبيل المثال
Java ...-Mode-Add-Opens Module/Source-Package = وحدة الهدف
إذا كنت بحاجة إلى التصدير إلى وحدات لم يتم تحديد اسمها ، فإن الوحدة المستهدفة غير مسموح بها
بالطبع ، إذا كان نظامًا جديدًا ، فلا يوصى باستخدام التفكير. يمكن استخدام MethodHandles و Varhandles.
الأسئلة الشائعة والتدابير
classnotfoundException/noclassDeffounderror
على سبيل المثال ، javax.xml.bind.jaxbexception ، تم تصنيف JaxB في وحدة Java.xml.bind ويتم إضافته بعد تسمية Java.
-مضغوطة modules java.xml.bind
إذا كنت ترغب في حفظ المتاعب ، فأضف $ java_home وجميع مكتبة الطرف الثالث إلى مسار الوحدة النمطية ، ثم افعلها
-عوامل مضغوطة جميع الوحدة
وصول عاكس غير قانوني من قبل xxx إلى طريقة java.lang.classloader.defineclass
أسباب الانعكاس ، لأن النظام القديم لا يحتوي على وحدة نمطية ، أضف معلمات إلى تسمية Java وتعديلها.
-add-opens java.base/java.lang = all-unnamed
تحديد وحدة التبعية
التحليل عبر IDE أو JDEPS
jdeps -chlass -path 'classes/lib/*' -App.jar app.jar
JDEPS هو مجرد تحليل رمز ثابت. إذا كان هناك فئة تستخدم الانعكاس ، فلا يمكنك تحليله. تحتاج إلى طلبها يدويًا. إذا كانت التبعية اختيارية ، فيمكنك أن تتطلب ثابتًا.
مشكلات قابلية القراءة لاختبارات وحدة الوحدة النمطية
إذا تم استخدام وحدة نمطية لاختبار الوحدة ، يمكن منح وحدة اختبار الوحدة إمكانيات القراءة والانعكاس للوحدة المستهدفة من خلال-تصدير مضافة أو-فتحات مضافة في وقت التشغيل. بالإضافة إلى ذلك ، بسبب مشكلات الحزم المقسمة ، لا يمكن تكرار اسم حزمة فئة اختبار الوحدة باستخدام اسم حزمة الوحدة الهدف. اتضح أن اختبار مشروع Maven
ملخص
يمكنك الانتقال إلى Java9 في خطوتين. أولاً ، أنت لست معيارًا أولاً ، فأنت تعمل فقط على JDK9 أولاً ؛ إذن أنت معياري.