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

Hiç yorum yok:

Yorum Gönder