JDK etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
JDK etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

21 Ekim 2021 Perşembe

java komutu Module Seçenekleri

Giriş
Açıklaması şöyle. Eğer bir module içindeki reserved veya internal bir sınıfa erişmeye çalışırsak hata alırız.
Due to the new module system, Java 9 does not allow an application by default to see all classes from the JDK, unlike all previous versions of Java. If we try to access some reserved module, we obtain an error like this:
module <module-name> does not "opens <package-name>" to unnamed module.

Everyone knows that we can solve this exception by using the JVM parameters --add-exports or -add-opens ...
Çözüm
1. -add-modules ile module eklenir
2. --add-opens veya add-exports ile module içindeki sınıfa erişim açılır

Örnek - classpath
Şöyle yaparız. Burada module classpath içinde
java --add-modules java.se \
  --add-exports java.base/jdk.internal.ref=ALL-UNNAMED \
  --add-opens java.base/java.lang=ALL-UNNAMED \
  --add-opens java.base/java.nio=ALL-UNNAMED \
  --add-opens java.base/sun.nio.ch=ALL-UNNAMED \
  --add-opens java.management/sun.management=ALL-UNNAMED \
  --add-opens jdk.management/com.ibm.lang.management.internal=ALL-UNNAMED \
  --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED \
  -jar hazelcast-5.2.3.jar
Örnek - classpath
Şöyle yaparız. Burada --module-path ile module belirtiliyor
java --add-modules java.se \
  --add-exports java.base/jdk.internal.ref=com.hazelcast.core \
  --add-opens java.base/java.lang=com.hazelcast.core \
  --add-opens java.base/java.nio=com.hazelcast.core \
  --add-opens java.base/sun.nio.ch=com.hazelcast.core \
  --add-opens java.management/sun.management=com.hazelcast.core \
  --add-opens jdk.management/com.ibm.lang.management.internal=com.hazelcast.core \
  --add-opens jdk.management/com.sun.management.internal=com.hazelcast.core \
  --module-path lib \ 
  --module com.hazelcast.core/com.hazelcast.core.server.HazelcastMemberStarter
--add-exports vs --add-opens
Açıklaması şöyle. Yani --add-opens ile public olan olmayan her şeye erişiliyor. --add-exports ile sadece public olanlara erişiliyor.
- With --add-exports the package is exported, meaning all public types and members therein are accessible at compile and run time.
- With --add-opens the package is opened, meaning all types and members (not only public ones!) therein are accessible at run time.

So the main difference at run time is that --add-opens allows "deep reflection", meaning access of non-public members. You can typically identify this kind of access by the reflecting code making calls to setAccessible(true).
1. --add-exports seçeneği
reserved bir sınıfa erişmek için kullanılır
Örnek
Elimizde şöyle bir kod olsun. Burada reflection yok, sadece eskinde yazılmış bir kod, yeni Java ile çalıştırılıyor ve artık BuddhistCalendar sınıfın dışarıya açılmadığı için yani reserverd/internal olduğu için hata veriyor.
BuddhistCalendar calendar = new BuddhistCalendar();


// Output
error: package sun.util is not visible
  (package sun.util is declared in module java.base, which does not export it)
Düzeltmek için şöyle yaparız
javac --add-exports java.base/sun.util=ALL-UNNAMED Foo.java
Örnek
Şöyle yaparız.
java --add-exports java.security.jgss/sun.security.krb5.internal.ktab=ALL-UNNAMED
  your-class
2. --add-opens
reserved bir module'e erişmek için kullanılır

Örnek
Elimizde şöyle bir kod olsun. Burada reflection var ve yeni Java ile çalıştırılıyor.  Artık BuddhistCalendar  sınıfın dışarıya açılmadığı için yani reserverd/internal olduğu için hata veriyor.
Class.forName("sun.util.BuddhistCalendar").getConstructor().newInstance();

//Output
Exception in thread "main" java.lang.IllegalAccessException:
  class Internal cannot access class sun.util.BuddhistCalendar (in module java.base)
  because module java.base does not export sun.util to unnamed module @1f021e6c
    at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException
      at java.base/java.lang.reflect.AccessibleObject.checkAccess
      at java.base/java.lang.reflect.Constructor.newInstanceWithCaller
      at java.base/java.lang.reflect.Constructor.newInstance
Düzeltmek için şöyle yaparız
java \
  --add-opens java.base/sun.util=ALL-UNNAMED \
  --class-path com.bar.foo.jar \
  com.bar.foo.Foo
Örnek
Şöyle yaparız.
set JAVA_OPTS=--add-modules jdk.unsupported --add-opens=java.base/java.nio=ALL-UNNAMED
3. -add-modules seçeneği
Bazı module isimleri şöyle
- java.se
- jdk.unsupported
- java.xml.bind

Örnek
Java 9 ile geçilen modül sisteminden sonra Java EE jar'larını classpath'e dahil edebilmek için şöyle yaparız.
java --add-modules java.xml.bind <class file>
Örnek
Şöyle yaparız.
java --add-modules java.se.ee -jar myspringbootproject.jar
4. --module-path veya -p seçeneği
-p ile aynıdır. Açıklaması şöyle. Yani --module-path modulepath veya -p modulepath şeklindedir.
Searches for directories from a semicolon-separated (;) list of directories. Each directory is a directory of modules.
Örnek
Şöyle yaparız.
java --module-path mymods -m com.test/com.test.HelloWorld
Örnek
jar dosyasındaki modülleri listelemek için şöyle yaparız.
java -p yourModular.jar --list-modules

29 Eylül 2020 Salı

java komutu - Uygulamayı Çalıştırır

Giriş
Söz dizimi şöyle.
java [optionsclassname [args]
Bu komutu çalıştırmak için JAVA_HOME Ortam Değişkeni'nin tanımlı olması gerekir.

java.library.path Ortam Değişkeni
Bu ortam değişkeni eğer java kodundan DLL kullanılıyorsa, DLL dosyalarının bulunduğu dizini gösterir. Linux'ta DLL yerine Shared Object (.so) dosyaları var

Linux Yöntemleri
Yöntemler şöyle
1. Call System.load to load the shared library from an explicitly specified absolute path.
Yapmayın

2. Copy the shared library to one of the paths already listed in java.library.path
Açıklaması şöyle. Yapmayın
The java.library.path is initialized from the LD_LIBRARY_PATH environment variable.
3. Modify the LD_LIBRARY_PATH environment variable to include the path where the shared library is located.
Bence en makul çözüm bu

4. Specify the java.library.path on the command line by using the -D option.
Bence en makul ikinci çözüm bu

JEP 330
JEP 330 - Running Java Files Directly  yazısına taşıdım

-add-exports seçeneği
java komutu Module Seçenekleri yazısına taşıdım

-add-modules seçeneği
java komutu Module Seçenekleri yazısına taşıdım

-classpath (ya da -cp ) seçeneği
Açıklaması şöyle.
$ java -help
    …
    -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.
Örnek
Şöyle yaparız.
bash$ java -classpath path/to/jars/directory MyMainClass
Örnek
Şöyle yaparız.
"%JAVA_HOME%\jre\bin\java.exe" -classpath bind MyMainClass
Örnek - Birden fazla dizin
Windows'ta tek tırnak ile şöyle yaparız. Dizinler ; karakteri ile ayrılır
java -verbose -classpath '../lib;.' bt_sim <args>
Linux'ta dizinler : karakteri ile ayrılır.

Bu seçeneği kullanmak yerine CLASSPATH ortam değişkenini kullanmak daha iyi.
bash$ export CLASSPATH="path/to/jars/directory1:path/tojars/directory2"
bash$ javac MyMainClass.java
Örnek - wildcard
Açıklaması şöyle.
Class path entries can contain the basename wildcard character *, which is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR. For example, the class path entry foo/* specifies all JAR files in the directory named foo. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.
Bir dizindeki tüm jar'ları dahil etmek için şöyle yaparız.
java -cp /home/acelya/*: MyMainClass
-de seçeneği
Açıklaması şöyle. disable assertions anlamına gelir.
-da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions with specified granularity
Assertleri kapatır.

-ea seçeneği
Açıklaması şöyle enables assertions anlamına gelir.
-ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions with specified granularity
Kod içindeki assertlerin çalışması için gerekir. Uzun hali -enableassertions seçeneğidir. Kod derleyici tarafından şu hale getirilir.
if (!cond)
    throw new AssertionError();
Eğer assert için mesaj kullanılırsa
assert d != null : "d is null";
Kod derleyici tarafından şu hale getirilir.
if ($assertionsEnabled && !(Expression1))
    throw new AssertionError(Expression2);
-D seçeneği
Parametre Geçme Seçenekleri yazısına taşıdım

-jar seçeneği - Executable Jar çalıştırmak
Açıklaması şöyle.
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)
jar dosyasında Manifest varsa şöyle ve bu dosyada Main-Class satırı varsa şöyle yaparız.
java -jar path/to/jar/file
Eğer Manifest dosyası yoksa başlangıç sınıfını vermek gerekir.
java -cp path/to/jar/file MainClass
Elimizde şöyle bir dizin yapısı olsun
jar_root/
├── executable.jar
├── folder1/
    └── required_file1.txt

├── folder2/
    └── required_file2.txt

├── other_folder/
   └── ...
└── other_file.txt
executable.jar dosyasını çalıştırınca folder1/required_file1.txt dosyasını okumak istiyor olsun. Bu durumda harici bir dosya okuduğumuz için jar dosyası şöyle çalıştırılır. Önce jar'ın olduğu dizine gideriz. Sonra -jar seçeneği ile executable jar'ı çalıştırırız.
cd /path/to/jar_root/ 
java -jar executable.jar <options>
jar içindeki java kodu dosyayı muhtemelen şöyle açıyordur.
File file = new File("folder1", "required_file1")
-javaagent seçeneği
Dynamic Agent Loading yeteneği Java 21 ile deprecate ediliyor.

Örnek
Şöyle yaparız.
java -javaagent:agent.jar -jar myApp.jar
-help seçeneği
Şöyle yaparız.
$ java -help
Usage: java [options] <mainclass> [args...]
           (to execute a class)
   or  java [options] -jar <jarfile> [args...]
           (to execute a jar file)
   or  java [options] -m <module>[/<mainclass>] [args...]
       java [options] --module <module>[/<mainclass>] [args...]
           (to execute the main class in a module)
   or  java [options] <sourcefile> [args]
           (to execute a single source-file program)
--illegal-access seçeneği
Açıklaması şöyle
Since Java 16, the --illegal-access flag is set to deny by default, resulting in some calls (mainly related to reflection) being treated as illegal and throwing a beautiful java.lang.reflect.InaccessibleObjectException. In our case, we found out that the libraries Kryo (through Chill) and Aeron use low-level JDK APIs and now trigger illegal access exceptions.

We immediately spotted this issue with our test battery and fixed it by simply allowing access to these internal APIs with a set of extra parameters passed at runtime — --add-opens {package}=ALL-UNNAMED. After a session of trial and error, we came up with the correct list of packages to open. To go further on this topic we recommend looking into JEP 396 and JEP 403.
-m seçeneği
Çalıştırılacak ana sınıfı beliritr.
--module modulename[/mainclass] veya -m module[/mainclass] şeklindedir.
Örnek
Şöyle yaparız.
java --module-path mods    -m     com.test/com.test.HelloWorld
                   ^               ^         ^
           module directory  module name   main class
--module-path veya -p seçeneği
-p ile aynıdır. Açıklaması şöyle. Yani --module-path modulepath veya -p modulepath şeklindedir.
Searches for directories from a semicolon-separated (;) list of directories. Each directory is a directory of modules.
Örnek
Şöyle yaparız.
java --module-path mymods -m com.test/com.test.HelloWorld
Örnek
Moduler jar dosyasındaki modülleri listelemek için şöyle yaparız.
java -p yourModular.jar --list-modules
-noverify seçeneği
Açıklaması şöyle. Bytecode'un değişmediğini değil, zarar vermeyeceğini doğrulamaya çalışır.
When a class loader presents the bytecodes of a newly loaded Java platform class to the virtual machine, these bytecodes are first inspected by a verifier. The verifier checks that the instructions cannot perform actions that are obviously damaging. All classes except for system classes are verified. You can, however, deactivate verification with the undocumented -noverify option.
-server seçeneği
Açıklaması şöyle
-server       to select the "server" VM
                  The default VM is server.
--source seçeneği
java komutu normalde derlenmiş .class dosyalarını çalıştırır. Java 11 ile tek dosyadan oluşan (dosya içinde birden fazla class kodu olabilir) kaynak kodu çalıştırmak için de kullanılabiliyor.

-X seçeneği
-X Seçenekleri yazısına taşıdım.

-XX seçenekleri
XX Seçenekleri yazısına taşıdım.

-verbose seçeneği
Açıklaması şöyle
-verbose:[class|gc|jni]
                  enable verbose output
Daha detaylı çıktı üretir. Şöyle yaparız.
java -verbose ...
-version seçeneği
-version seçeneği yazısına taşıdım.