لینوکس، عشق، برنامه نویسی

لینوکس، عشق، برنامه نویسی

در این وبلاگ مطالبی درباره سیستم عامل لینوکس و همچنین درمورد برنامه نویسی و کامپیوتر مینویسم.

 

فصل هفتم

 

نحوه ی اجرای پروژه ی کامپایل شده ی جاوا با مفسر جاوا (یا همان  java)

 

در فصل قبل یاد گرفتیم که چگونه پروژه ی خود را کامپایل کنیم و فایل های بایت کد (یعنی همان فایل های class.) را تولید کنیم.

بعد از اینکه فایل های بایت کد توسط javac تولید شد، حالا باید این فایل ها را توسط مفسر جاوا (یعنی ابزار java  که در jdk

هست)، اجرا کنیم.

 

 

 

ابتدا باید نگاهی به فلگ های java بندازیم. دستور java -help را در ترمینال وارد می کنیم.

 
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)
where options include:
    -d32      use a 32-bit data model if available
    -d64      use a 64-bit data model if available
    -server      to select the "server" VM
                  The default VM is server,
                  because you are running on a server-class machine.

    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A : separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -D<name>=<value>
                  set a system property
    -verbose:[class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -version:<value>
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  require the specified version to run
    -showversion  print product version and continue
    -jre-restrict-search | -no-jre-restrict-search
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  include/exclude user private JREs in the version search
    -? -help      print this help message
    -X            print help on non-standard options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions with specified granularity
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions with specified granularity
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions
    -agentlib:<libname>[=<options>]
                  load native agent library <libname>, e.g. -agentlib:hprof
                  see also, -agentlib:jdwp=help and -agentlib:hprof=help
    -agentpath:<pathname>[=<options>]
                  load native agent library by full pathname
    -javaagent:<jarpath>[=<options>]
                  load Java programming language agent, see java.lang.instrument
    -splash:<imagepath>
                  show splash screen with specified image
See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.
 

 

 

از بین این فلگ ها، فلگ cp- یا همان  classpath- برای ما خیلی مهم است. در واقع ما باید آدرس پکیج روت دایرکتوری رو بدیم به این فلگ.

به عبارت دیگر، زمانی که مفسر جاوا فایل Main.class را اجرا می کند، اگر در کلاس Main، کلاس هایی دیگری نیز import شده باشند، در آن صورت، مفسر، در ادرس پکیج روت دایرکتوری، شروع به گشتن به دنبال بایت کد آن کلاس ها می کند.

 

فرض کنید در فایل Main.class،  یک کلاسی import شده به نام Util و فایل Util.class نیز در پکیج com.blog قرار دارد و پوشه ی com نیز روی دسکتاپ قرار دارد. در آن صورت، "پکیج روت دایرکتوری" ما می شود home/linuxgeek/Desktop/

 

به عبارت دیگر، زمانی که مفسر جاوا فایل Main.class را اجرا می کند، به دنبال فایل Util.class می گردد (چون در کلاس مین import شده)، بنابراین، کامپایلر در پکیج روت دایرکتوری (  home/linuxgeek/Desktop/  )  شروع به گشتن به دنبال پکیج com.blog و فایل Util.class می کند.

 

 

نکته: اگر پکیج های ما در آدرس های مختلفی پراکنده باشند، در آن صورت ما چندین پکیج روت دایرکتوری داریم و باید آدرس همه ی آنها را بدهیم به classpath تا مفسر بتواند بایت کدها را پیدا کند. آدرس ها را نیز با علامت   :   از هم جدا می کنیم (در لینوکس با ; )

 

 

ببینید دوستان، زمان اجرای برنامه های جاوا، ممکن است سناریو های مختلفی پیش بیاید. مهمترین نکته ای که باید بدونید این هست که مفسر جاوا به دنبال فایل های class. می گردد برای اجرا کردن آنها. (حالا این فایل class. ممکن است درون یک فایل zip باشند، ممکن است درون یک فایل jar باشند و یا درون یک پوشه ی معمولی در سیستم فایل شما). این فایل ها در هر کجا که باشند، باید آدرس آن را بدهید به classpath تا مفسر بتواند آنها را پیدا کند.  اگر فقط همین نکته را به ذهن بسپرید تمومه.


 

 

طبق آنچه که از دستور java -help بدست آوردیم،  با ۲ روش کلی میشه پروژه های جاوا رو اجرا کرد. این دو روش رو در زیر می بینید.

 

 
Usage: 

java [-options] class [args...] (to execute a class)

 or 

java [-options] -jar jarfile [args...] (to execute a jar file)
 

 

 

در هر دوی این روش ها، بجای options-  می تونیم فلگ های مختلف رو قرار بدیم و برای ما فقط فلگ classpath مهمه. پس بجای option، فلگ cp را قرار می دهیم.

 

 

روش اول:

 

 
java -classpath path1;path2;file.zip;file.jar        path/to/Main.class          args  
 

 

path1: ادرس پکیج روت دایرکتوری

path2: ادرس پکیج روت دایرکتوری

file.zip: فایل زیپ که می تواند حاوی پکیج ها و فایل های class.  باشد.

file.jar: فایل جار که می تواند حاوی پکیج ها و فایل های class.  باشد.

path/to/Main.class: ادرس فایل Main.class

args: آرگومان هایی که می خواهیم به متد main ارسال شوند

 

 

توجه:  به classpath باید آدرس پکیج روت دایرکتوری رو بدید تا مفسر جاوا بتونه در اون ادرس ها جستجو کنه و فایل های class. رو پیدا کنه  (حالا این فایل های class. میتونن داخل فایل زیپ باشن، یا داخل فایل جار، و یا در یک پوشه در سیستم فایل)

 

توجه: اگر classpath رو ندید به مفسر، بطور پیش فرض، current working directory به عنوان classpath تعیین میشه. به عبارت دیگر، زمانی که مفسر جاوا بخواهد دنبال پکیج ها و بایت کد ها بگردد، از ادرس فعلی  شروع می کند به گشتن.

 

 

روش دوم:

 

 
java     -classpath  path1;path2;file.zip;file.jar         -jar file.jar     args 
 

 

این دستور رو زمانی اجرا می کنیم که پروژه رو کامپایل کردیم، و فایل های class. رو داخل یک فایل jar قرار دادیم و حالا می خواهیم که فایل jar رو اجرا کنیم.

 

در اینجا هم باید آدرس پکیج روت دایرکتوری رو بدیم به classpath تا مفسر جاوا بتونه فایل های class. رو پیدا کنه. در اینجا اگرچه ما پروژه ی خودمون رو به jar تبدیل کردیم، ولی ممکنه از کلاس هایی استفاده کنیم که خود اون کلاس ها در یک فایل jar دیگه قرار داشته باشند. در آن صورت، باید آدرس اون فایل jar رو بدیم به classpath

 

(ما حتی می تونستیم اون فایل jar رو که به عنوان لایبرری استفاده کردیم، در فایل jar خودمون embed کنیم)

 

پس میبینید که سناریو های مختلف و عجیب غریبی ممکنه پیش بیاد. در هر صورت یادتون باشه، مفسر جاوا باید بتونه فایل های  class. رو پیدا کنه.

در کجا سرچ میکنه؟ در پکیج روت دایرکتوری.

آدرس پکیج روت دایرکتوری رو به کجا باید بدیم؟ به classpath

 

 

خب، من فکر میکنم هر انچه لازم بود رو درباره مفسر جاوا به شما گفتم. در فصل سناریو های مختلفی رو بررسی میکنم.

 

 

بازگشت به فهرست اصلی

 

 

 

۰ نظر ۰۲ اسفند ۰۰ ، ۰۱:۰۳
Linux-Geek

 

فصل ششم

 

نحوه ی کامپایل سورس کد های جاوا با کامپایلر ( javac )

 

خب همانطور که در فصل های گذشته دیدیم، ابزار javac یکی از ابزار های jdk هست که برای کامپایل سورس کدهای جاوا به کار می رود. چون نرم افزار javac، رابط گرافیکی یا همان GUI ندارد بنابراین باید از طریق ترمینال ان را اجرا کنیم تا برنامه را کامپایل کنیم. اما ابتدا باید نگاهی به فلگ های (flag) ان داشته باشیم.

 

توجه: jdk من ورژن 1.8 هست، jdk 9 یه مقدار تفاوت کرده که بعدا توضیح میدم.

 

ابتدا در ترمینال دستور javac -help رو می زنیم تا ببینیم چه فلگ هایی داره

 

 
Usage: javac <options> <source files>

where possible options include:

  -g                         Generate all debugging info
  -g:none                    Generate no debugging info
  -g:{lines,vars,source}     Generate only some debugging info
  -nowarn                    Generate no warnings
  -verbose                   Output messages about what the compiler is doing
  -deprecation               Output source locations where deprecated APIs are used
  -classpath <path>          Specify where to find user class files and annotation processors
  -cp <path>                 Specify where to find user class files and annotation processors
  -sourcepath <path>         Specify where to find input source files
  -bootclasspath <path>      Override location of bootstrap class files
  -extdirs <dirs>            Override location of installed extensions
  -endorseddirs <dirs>       Override location of endorsed standards path
  -proc:{none,only}          Control whether annotation processing and/or compilation is done.
  -processor <class1>[,<class2>,<class3>...] Names of the annotation processors to run; bypasses default discovery process
  -processorpath <path>      Specify where to find annotation processors
  -parameters                Generate metadata for reflection on method parameters
  -d <directory>             Specify where to place generated class files
  -s <directory>             Specify where to place generated source files
  -h <directory>             Specify where to place generated native header files
  -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files
  -encoding <encoding>       Specify character encoding used by source files
  -source <release>          Provide source compatibility with specified release
  -target <release>          Generate class files for specific VM version
  -profile <profile>         Check that API used is available in the specified profile
  -version                   Version information
  -help                      Print a synopsis of standard options
  -Akey[=value]              Options to pass to annotation processors
  -X                         Print a synopsis of nonstandard options
  -J<flag>                   Pass <flag> directly to the runtime system
  -Werror                    Terminate compilation if warnings occur
  @<filename>                Read options and filenames from file
 

 

همانطور که می بینید، در خط اول، نحوه ی استفاده از کامپایلر جاوا را توضیح داده.

 
<javac <options> <source files
 

 

بجای <options> ما می توانیم چندین تا از فلگ های بالا رو بزاریم.

 

اما ۳ تا از فلگ ها برای ما خیلی مهم هستن.

۱- فلگ sourcepath-

۲- فلگ classpath-

۳- فلگ d-

 

فلگ sourcepath

فلگ sourcepath-  همانطور که از اسمش پیداست، ادرس سورس کدهای پروژه را مشخص می کند. به عبارت دقیق تر، ادرس "پکیج روت دایرکتوری" پروژه را. و به عبارت دیگر، javac از این ادرس شروع میکنه به گشتن پکیج ها و فایل های java.

 

به فرض اگر تمام پکیج های پروژه داخل پوشه ی src باشند، مقدار sourcepath می شود آدرس پوشه ی src

 

 

نکته ی بسیار مهم۱: در جاوا این امکان وجود دارد که همه، (یا برخی) از پکیج های  پروژه ی ما، داخل فایل jar یا حتی داخل فایل zip باشد. به عبارت دیگر ما می توانیم یک فایل zip داشته باشیم که برخی از  پکیج ها و سورس کد ما (فایل های java.) داخل آن باشد. بنابراین ادرس فایل های زیپ و جار رو هم باید بدیم به sourcepath

 

حالا اگر پکیج های ما هر کدام در یک ادرسی باشند (فرض کنید یک پکیج در درایو F و دیگری در درایو D باشد و یک پکیج ما نیز در داخل یک فایل zip باشد)، در آن صورت، سه تا پکیج روت دایرکتوری داریم، و مقدار sourcepath میشه آدرس هر سه تای آنها ( که با علامت : از هم جدا شده اند) (در لینوکس با علامت ; از هم جدا  می شوند). به عبارت دیگر، زمانی که javac بخواهد دنبال پکیج ها و سورس کدها بگردد، باید ۲ تا ادرس را جستجو کند به اضافه محتویات یک فایل zip را.

 

نکته ی بسیار مهم۲: زمانی که شما فلگ sourcepath رو به javac ندهید،  javac مقدار sourcepath را معادل current working directory در نظر می گیرد. به عبارت دیگر، اگر شما فلگ sourcepath را به javac ندهید، javac از ادرس فعلی شروع می کند به گشتن پکیج ها و کلاس ها

 

 

فلگ classpath

فلگ classpath-  نیز همانطور که از اسمش پیداست، ادرس کلاس های کامپایل شده را مشخص می کند. به عبارت دقیق تر، ادرس "پکیج روت دایرکتوری" فایل های class. را

و به عبارت دیگر، زمانی که javac بخواهد دنبال پکیج ها و فایل های کامپایل شده بگردد، از این ادرس شروع می کند به گشتن

 

فرض کنید کسی قبلا در جاوا کلاس Util را نوشته و آن را کامپایل کرده، و فایل Util.class را به شما داده

 

(هر چند که مرسوم نیست فایل کامپایل شده ی جاوا رو همینجوری بدیم به کسی، روش بهتر این هست که بزاریم داخل یک فایل jar و فایل jar رو بدیم به طرف. این فایل jar در واقع میشه همان لایببری)

 

ولی حالا بیاید فرض کنیم که این اتفاق افتاده و کلاس کامپایل شده (فایل Util.class)  رو از دوستتون گرفتید، و ازش در پروژه استفاده کردید. حالا زمانی که بخواهید پروژه ی خودتون رو کامپایل کنید، باید ادرس "پکیج روت دایرکتوری" اون فایل class. رو، بدید به فلگ classpath

 

به فرض اگر کلاس Util در پکیج com.lib باشد، معنیش این هست که فایل Util.class  داخل پوشه ی lib و پوشه ی lib داخل پوشه ی com هست. درسته؟

 

حالا اگر پوشه ی com در ادرس  home/linuxgeek/  باشد، این ادرس می شود پکیج روت دایرکتوری فایل Util.class

 

به عبارت دیگر، زمانی که javac بخواهد دنبال پکیج com.lib و فایل Util.class بگردد، از ادرس home/linuxgeek/ شروع می کند به جستجو

 

 

 

نکته ی بسیار مهم۱: در جاوا این امکان وجود دارد که همه، (یا برخی) از پکیج های  پروژه ی ما، داخل فایل jar یا حتی داخل فایل zip باشد. به عبارت دیگر، فایل zip می تواند حاوی پکیج ها و کلاس های کامپایل شده باشد. بنابراین آدرس فایل zip و jar رو هم باید بدیم به classpath

 

حالا اگر فایل های کامپایل شده ی ما، هر کدام در یک ادرسی باشند (فرض کنید یک پکیج در درایو F و دیگری در درایو D باشد و یک پکیج ما نیز در داخل یک فایل zip باشد)، در آن صورت، سه تا پکیج روت دایرکتوری داریم، و مقدار classpath میشه آدرس هر سه تای آنها ( که با علامت : از هم جدا شده اند) (در لینوکس با علامت ; از هم جدا  می شوند). به عبارت دیگر، زمانی که javac بخواهد دنبال bytecode ها بگردد، باید ۲ تا ادرس را جستجو کند به اضافه محتویات یک فایل zip را.

 

نکته ی بسیار مهم۲: زمانی که شما فلگ classpath رو به javac ندهید،  javac مقدار classpath را معادل current working directory در نظر می گیرد. به عبارت دیگر، اگر شما فلگ sourcepath را به javac ندهید، javac از ادرس فعلی شروع می کند به گشتن پکیج ها و کلاس ها  (دقیقا مثل sourcepath)

 

 

 

فلگ d-

زمانی که javac فایل های سورس را کامپایل می کند، به طور پیش فرض، فایل بایت کد را (class.) کنار همان سورس کد ایجاد می کند.  اگر بخواهیم فایل های بایت کد، به طور کلی در یک ادرس دیگر ایجاد شوند، از فلگ d- استفاده می کنیم. در این صورت، کامپایلر ابتدا پکیج های مربوطه را بصورت خودکار ساخته، و فایل های بایت کد را در پکیج های مربوط به خودشان قرار می دهد.

 

به عبارت دیگر، ما باید ادرس "پکیج روت دایرکتوری" مد نظر خودمان را بدهیم به فلگ d- تا کامپایلر  در آن ادرس پکیج ها و بایت کد ها را بسازد

 

اکلیپس نیز با استفاده از فلگ d- در کنار پوشه ی src یک پوشه می سازد به نام bin و پکیج ها را داخل آن قرار می دهد (به همراه فایل های کامپایل شده)

 

دستور کامپایل در جاوا

تا اینجا همه چیز رو درباره javac و فلگ های اون گفتم. برای اینکه صحبت هارو جمع بندی کنم، دستور کلی کامپایل در جاوا رو در زیر می نویسم

 
 javac -sourcepath     path1;path2;file.zip;file.jar          -classpath     path1;path2;file.zip;file.jar    path/to/Main.java
 

 

path1: ادرس پکیج روت دایرکتوری

path2: ادرس پکیج روت دایرکتوری

file.zip: فایل زیپ که می تواند حاوی پکیج ها و فایل های class. یا java. باشد.

file.jar: فایل جار که می تواند حاوی پکیج ها و فایل های class. و یا java. باشد.

path/to/Main.java: ادرس فایل Main.java

 

 

و نکته ی پایانی اینکه، زمانی که شما فقط ادرس فایل Main.java رو به کامپایلر میدید،  کامپایلر به طور اتوماتیک، تمام کلاس هایی که در Main.java ایمپورت شدن رو پیدا میکنه و انها رو هم کامپایل میکنه. چجوری پیدا میکنه؟ با گشتن درون پکیج روت دایرکتوری و فایل های zip و jar

 

 

بازگشت به فهرست اصلی

 

 

۰ نظر ۰۲ اسفند ۰۰ ، ۰۱:۰۲
Linux-Geek