استفاده از کلاس های جاوا در .NET با کمک IKVM.NET

جاوا، پایتون، C، C# و ... همگی زبان های برنامه نویسی مختلفی هستند که کاربرد های خاص خود را دارند. یکی در حوزه ی برنامه های Enterprise برگ برنده را دارد و آن یکی در حوزه ی امنیت. یکی راحتی کار با آن تیم های برنامه نویسی را ترغیب به استفاده میکند و آن یکی Community بزرگتر و لایبراری های open source بیشتر. از این بحث ها که بگذریم، در عمل در برخی موارد با شرایطی مواجه میشویم که نیاز داریم قطعه کدی را به زبان دیگری پیاده سازی کنیم و در کد برنامه مان از آن استفاده کنیم. این امر ممکن است به هر دلیلی باشد؛ بعنوان مثال ممکن است به یک متد رمزنگاری خاصی نیاز پیدا کنید که هر چه تلاش میکنید و در اینترنت بدنبال sample code آن میگردید اثری از آن در زبان برنامه نویسی target تان از آن نمی بینید در حالیکه پکیج های آن به زبان های دیگر براحتی در دسترس شما قرا دارند. در این حال شما دو راه در پیش رو دارید. یا اینکه شروع کنید و این متد رمز نگاری را با رجوع به مستندات RFC آن از اول پیاده سازی کنید که نیاز است اگر کارشناس حوزه ی رمزنگاری را در تیم توسعه تان ندارید حداقل یکی دو نفر از آنها را استخدام کنید و زمان لازم را هم به آنها بدهید تا متد مورد نظرتان را از اول پیاده سازی کنند. یا اینکه از اول بشینید و پروژه تان را به زبان دیگری توسعه دهید:D. البته ممکن نیست روش دوم را انتخاب کنید. درسته؟!اما نگران نباشید روش سومی هم وجود دارد. ابزارهایی هستند که به شما این امکان را میدهند که بتوانید قطعه کد نوشته شده به زبان دیگر را در محیط توسعه ی زبان دیگری استفاده نمایید. با اینکار شما قادر خواهید بود متد مورد نظر خود را به زبانی که سریعتر به نتیجه می رسید پیاده سازی کرده و بدون هیچ مشکلی در پروژه اصلیتان که بکلی بر روی محیط، زبان و فریم ورک دیگری ایجاد شده است استفاده نمایید. مثلا متدتان را به زبان جاوا بنویسید و در پروژه ی .NET خود از آن استفاده نمایید. و یا بالعکس.البته این مسئله در زندگی روزمره ما انسان ها هم وجود دارد. مثلا ممکن است برای یک تیم ورزشی خاصی از یک مربی خارجی استفاده شود. در اینصورت از آنجا که زبان مربی با زبان بازیکنان متفاوت است لازم است شخصی بعنوان مترجم به مجموعه اضافه شود که کار رابط بین بازیکنان و مربی را بر عهده بگیرد. در دنیای نرم افزار هم یک همچین شرایطی وجود دارد. ابزار هایی هستند که میتوانند بعنوان واسط(مترجم) بین دو زبان قرار گیرند.یکی از این ابزار ها، IKVM نام دارد. IKVM نام یک پروژه ی Open Source است که بمنظور فراهم کردن امکان اجرای کدهای Java در .NET و بالعکس ایجاد شده است. سورس این پروژه را میتوانید در گیت هاب در آدرس https://github.com/gluck/ikvm به آن دسترسی داشته باشید.IKVM در واقع شامل یک ماشین مجازی جاوایی ست که با C# پیاده سازی شده است. با استفاده از آن می توانید کد نوشته شده به زبان جاوایتان را در برنامه های .NET استفاده کنید. و یا بالعکس. واقعاً عالی نیست!!!بدین منظور این ابزار کاری که انجام میدهد آن است که از فایل های حاوی کد جاوا با پسوند های .class و یا .jar، یک فایل .dll ایجاد میکند. و شما قادر خواهید بود از این dll در برنامه ی .NET خود استفاده نمایید؛ مثلا در ویژوال استودیو آنرا import نمایید و از آن استفاده کنید.برای دانلود IKVM.NET به این آدرس رجوع نمایید. نصب خاصی ندارد و فقط با یک copy/paste ساده در مسیر دلخواهتان شما قادر خواهید بود از این برنامه استفاده نمایید.(تصویر زیر)تبدیل کلاس جاوا به dll های .NETمراحل انجام این کار در ادامه توضیح داده شده است:ابتدا کد جاوایتان را بنویسید. من در مثال خود کد های جاوای خود را با استفاده از Intellij در فایلی به نام SkEncyptor.java نوشته ام. نکته ای که لازم است بدان توجه نمایید این است که متدی که قرار است از آن در .NET استفاده نمایید را حتما public تعریف نمایید؛ چرا که بعدا می خواهید از داخل برنامه ی .NET تان آنرا فراخوانی کنید. پس باید Accessor آن Public باشد. شکل زیر نمایی کلی از فایل SkEncyptor.class را نشان می دهد:در شکل فوق از متد های encrypt و decrypt میخواهم بعدا در برنامه ی .NET استفاده نمایم. از اینرو این دو متد را public تعریف کرده ام. سایر متد ها صرفا یک سری utility هستند که در دو متد encrypt و decrypt مورد استفاده قرار گرفته اند و قرار نیست مستقیم از داخل برنامه ی .NET بدانها فراخوانی ای صورت گیرد؛ لذا آنها را private در نظر گرفته ام.اگر شما هم مثل من از intellij استفاده میکنید، با یک build ساده از برنامه، معادل فایل .class کد جاوایتان ساخته شده و در مسیر projectname]\target\classes میتوانید آنرا مشاهده نمایید.(شکل زیر)2. حال با استفاده از Utility به نام ikvmc که در لایبراری ikvm وجود دارد میتوانیم این کلاس جاوایی را به یک dll دات نتی تبدیل کنیم. برای این منظور برای راحتی کار ابتدا فایل .class جاوایتان را به مسیر نصب ikvm و در فولدری به نام bin قرار می دهد.(شکل زیر)سپس cmd را اجرا کرده و خط فرمان را به همین آدرسی که فایل جاوا را در آن قرار داده ایم تغییر دهید:حال با اجرای دستور ikvmc SkEncyptor.class فایل SkEncyptor.dll در همین مسیر ساخته خواهد شد(شکل زیر)خروجی این دستور را در شکل زیر می توانید مشاهده کنید:توجه: چنانچه کلاس جاوایتان شامل متد main نیز باشد، با اجرای دستور ikvmc SkEncyptor.class بجای ایجاد فایل dll، فایل اجرایی .exe ساخته خواهد شد. اما فایل .exe را نمیتوانید در پروژه ی .NET اضافه کنید. برای حل این مشکل دو راه دارید؛ یا متد main را از کد جاوایتان حذف کنید و دوباره مرحله ی 2 را انجام دهید؛ و یا از پارامتر target در ikvmc بصورت زیر استفاده نمایید:ikvmc -target:library SkEncyptor.classبا این فرمان چنانچه متد main هم در کد جاوایتان وجود داشته باشد، باز هم فایل ایجاد شده از نوع لایبراری(با پسوند .dll) خواهد بود و شما می توانید در برنامه ی .NET از آن استفاده نمایید.نحوه ی Add کردن dll ساخته شده در ویژوال استودیوحال که توانسته اید کد جاوایتان را به dll دات نتی تبدیل کنید، کافیست dll ایجاد شده را به پروژه دات نت تان Add کنید و از آن استفاده کنید. بدین منظور در ویژوال استودیو بر روی نام پروژه کلیک راست کرده و در قسمت Add بر روی گزینه ی Reference کلیک نمایید. در پنجره ی Reference Manager بر روی دکمه ی Browse کلیک نموده و به مسیری که dll ایجاد شده را در آن قرار داده اید رفته و آنرا انتخاب کرده و بر روی دکمه ی Add کلیک نماییدپس از add شدن dll به reference های پروژه میتوانید از متد های آن استفاده نمایید. در شکل زیر متد های encrypt و decrypt را که در جاوا پیاده سازی شده اند مشاهده می نمایید که میتوانیم در کد C# مان آنها را فراخوانی کرده و از آنها استفاده نماییمنکته مهم: در هنگام اجرای(run) برنامه ی .NET ممکن است به خطاهایی مبنی بر وابستگی به dll های دیگر بر بخورید که در reference های پروژه تان موجود نیست. قضیه از این قرار است که برای اجرای صحیح dll های ساخته شده به این روش، شما به یک سری dll های دیگر که خود ikvm آنها را آماده کرده است وابسته خواهید بود که باید به لیست reference های پروژه تان اضافه گردند. این dll ها در فولدر bin مسیر نصب ikvm موجود هستند.(شکل زیر)از بین این dll ها برخی ضروری هستند همانند IKVM.Runtime.dll و IKVM.OpenJDK.Core.dll و برخی دیگر بستگی به کد جاوایتان دارد که ممکن است بدانها نیاز داشته باشید یا خیر. برای add کردن این reference ها دو روش وجود دارد که میتوانید یکی از آنها را انجام دهید. یا یکجا همه ی این dll ها را به پروژه تان add نمایید که در اینصورت، حین اجرا مطمئن خواهید بود که با خطایی مواجه نخواهید شد. یا اینکه اگر مثل من به کر و کثیف نبودن لیست reference های پروژه تان اهمیت می دهید و نمی خواهید dll هایی در لیست refenrece های پروژه تان وجود داشته باشد که هرگز از آنها استفاده نمیکنید میتوانید با چند بار اجرای برنامه و add کردن dll هایی که برای اجرای متدتان، runtime دات نت بدانها نیاز دارد ولی آنها را پیدا نمیکند، دقیقا dll هایی را اضافه کنید که باید باشند. من در مثال خود از آنجا که کد های جاوای من مربوط به متد های encryption و decryption یکی از الگوریتم های RSA بوده به dll های زیر نیاز داشتم و باید به پروژه ی .NETاضافه میکردم:IKVM.OpenJDK.CoreIKVM.OpenJDK.SecurityIKVM.OpenJDK.XML.BindIKVM.Runtimeنکات پایانی:نکته اول: همانطور که پیشتر هم اشاره شد، نه تنها برای تبدیل کد های جاوایی با پسوند .class به معادل dll آن می توانید از برنامه ی ikvm استفاده نمایید، بلکه برای تبدیل jar فایل های جاوا نیز میتوانید از این ابزار استفاده کنید. فقط کافیست در همین مستند هر جا در خط فرمان از .class استفاده کرده ایم، .jar قرار دهید. مثلا ikvmc SkEncyptor.jarنکته دوم: پروژه هایی همانند ikvm به این خاطر ایجاد نشده اند که ما فارغ از نوع محصولی که میخواهیم تولید کنیم و ویژگی هایی که محصول مان دارد، بتوانیم با هر زبان و محیطی شروع به توسعه کنیم؛ با این خیال که هر جا به بن بستی برخوردیم با ابزارهای این چنینی میتوانیم براحتی بن بست ها را از سر راه برداریم. ابزار هایی نظیر ikvm هزینه ی سربار کمی ندارند. بی دلیل نبود که در این مثال ما مجبور شدیم علاوه بر dll اصلی مان، 4 تا dll دیگر نیز که در موقع اجرا، runtime بدانها نیاز داشت به پروژه اضافه کنیم. این را با شرایطی مقایسه کنید که بجای اضافه کردن dll های مختلف به پروژه میتوانستیم دو متد مورد نظر را با زبان اصلی خود پروژه(در اینجا یعنی C#) پیاده سازی می کردیم. قطعا از نظر performance و سربار اجرا، برتری با حالت دوم بود. بنابراین هیچگاه از ابزارهایی نظیر ikvm بعنوان پوششی برای انتخاب غلط مان استفاده نمی کنیم. قطعا هر زبان برنامه نویسی ای ویژگی هایی دارد و از آنطرف هم هر محصولی خصوصیت هایی. این دو باید با هم سازگار باشند. با بررسی های دقیق و پس از مشورت با اهل فن بهترین و مناسب ترین محیط و زبان را برای پروژه انتخاب کنیم تا در چنین مخمصه هایی قرار نگیریم. اما اگر پس از انجام تمام این مراحل باز هم در چنین شرایطی قرار گرفتیم میتوانیم از ikvm و ابزارهای مشابه آن استفاده کنیم. در مثال ما اگر این متد encryption و decryption خاص مربوط به یک سوئیچ بانکی بوده باشد، بهتر نبود این سوئیچ بانکی به زبان جاوا نوشته میشد؟! اساسا جاوا برای محیط های enterprise نظیر بانک ها انتخاب بهتری ست. یک دلیل این ادعا هم همین است که جاوا از community خیلی بزرگتری بهره میبرد و پیاده سازی های زیادی از سخت ترین و نوترین متد های رمزنگاری میتوانید در آن بیابید.