JDK bulunan bir grafik arayüzü olan bir bilgisayarda jconsole'u çalıştırabilirsiniz.
Örneğin Windows'da aşağıdaki gibi JDK nın klasörüne komut satırı ile gidebilirsin ve bin klasörüne geçebilirsiniz. :
C:\Program Files\Java\jdk-11.0.15.1>
C:\Program Files\Java\jdk-11.0.15.1>cd bin
Bu klasörde jconsole yazıp enter'a basarsanız jconsole'ın grafik arayüzü açılacaktır :

Local Process bölümünde bilgisayarınızda çalışan Java uygulamalarına erişebilirsiniz. Remote kısmı ise uzaktaki bilgisayarlarının JMX portları üzerinden bağlanmak için kullanılmaktadır.
Resimde üsteki bazı uygulamaların silik yazıldığına dikkat ediniz. Bu uygulamalara JMX ile bağlanılamayacağı göstermektedir. Ancak jdk.jconsole/sun.tools.jconsole.JConsole a bağlanılabilir :

JConsole ile JDK nın memory, thread, cpu kullanımı, yüklenen sınıf bilgiler, mbean bilgilerine vb.. erişebilirsiniz.
Bir Java uygulamasına varsayılan olarak JMX (jconsole veya farklı bir araç ile) ile erişemezsiniz. JMX ile erişilebilir yapmak için uygulama çalıştırılırken aşağıdaki gibi VM parametrelerini vermek gerekmektedir :
-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Bir uygulamaya erişmek için bir JMX portu belirlemek gerekmektedir. Yukarıdaki örnekte 9999 portu seçilmiştir. JMX varsayılan olarak kullanıcı ve şifre kontrolünü istemektedir. Erişilmesi de güvenik nedeniyle TLS kullanılarak yapılmalıdır. Ancak çalışma ortamınızda buna ihtiyaç duymadığımız için yukarıdaki gibi hem authenticate hem de ssl false verilerek kapatılmıştır.
Bu VM argümanlarıyla uygulamayı açtığınızda JMX ile erişebilir hale gelmektedir. JConsole'u çalıştırıp localhost:9999 ile uygulamaya JMX ile bağlanabilirsiniz :

SSL kullanılmadığı için aşağıdaki gibi bir uyarı gelecektir :

insecure connection düğmesine basarsanız uygulamaya JMX ile bağlanmış olursunuz.
Bir uygulamayı JConsole gibi araçlarla erişebilecek şekide JMX desteği eklenebilir. Bu sayfada bu desteğin nasıl ekleneceği görülebilir :
www.fibiler.com/Bir-Java-Uygulamasini-JConsole-ile-Erisilebilir-Yapilmasi_Ipucu_148134Ancak bu durumda herkes JConsole ile uygulamanıza erişlebilir. Bunu engellemek için basit bir username, password kontrolü eklenebilir. Bunun için iki dosya yaratırlması gerekir. Örneğin şifre bilgisinin saklandığı dosya içeriği aşağıdaki gibi olsun :
admin Admin123.
Bu dosyayı bir yere jmxremote.password adıyla kaydedelim. Burada admin adlı bir kullanıcı tanımlıyoruz ve şifresi de Admin123. oluyor.
Bu kullanıcının yetkilerini tanımlamak içinse aşağıdaki gibi bir dosya yaratalım :
admin readwrite
Bu kullanıcıya read (okuma) ve write (yazma) yetkisi verildi.
Bu dosyaları uygulamanız çalıştırırken aşağıdaki gibi vermeniz gerekir :
-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=E:\jmxremote.password -Dcom.sun.management.jmxremote.access.file=E:\jmxremote.access -Dcom.sun.management.jmxremote.ssl=false
Görüldüğü gibi -Dcom.sun.management.jmxremote.authenticate değeri true olarak verilmiş ve username/şifre dosyası ile role tanımının yapıldığı dosya verilmiştir. Bu uygulamayı çalıştırdığınızda aşağıdaki hatayı alabilirsiniz:
Error: Password file read access must be restricted: Q:\jmx.password
sun.management.AgentConfigurationError
at sun.management.jmxremote.ConnectorBootstrap.checkPasswordFile(Unknown Source)
at sun.management.jmxremote.ConnectorBootstrap.startRemoteConnectorServer(Unknown Source)
at sun.management.Agent.startAgent(Unknown Source)
at sun.management.Agent.startAgent(Unknown Source)
Bu hata dosyaların yetkilerinin düzenlenmediği anlamına gelir. Yani jmx.password ve jmxremote.password dosyası Java uygulamasını çalıştıran uygulamlara okuma yetkisi verilmeli. Diğer tüm kullanıcılardan da yetkisi kaldırılmalıdır. Linux'da chmod 600
şeklinde bir dosyada sadece kullanıcıya rw yetkisi verilmesi sağlanabilir. Windows'da da Securty tabından yetkiler düzenlenebilir.
Bu işlemi yaptıktan sonra localhost:9999 sunucusuna bağlanırken username ve password girmeniz gerekir.
JConsole'u kullanırken uzak bir uygulamaya bağlanıldığında neler olup bittiğini görmek isteyebilirsiniz. Bunun için logger konfigürasyonu kullanarak debug modu açılabilir. Bunun için jconsole aşağıdaki gibi çalıştırılır :
jconsole -J-Djava.util.logging.config.file=Q:\log.properties
Log dosyasının içi de şu şekilde olabilir :
handlers=java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
javax.management.level=FINEST
javax.management.remote.level=FINEST
Tabi ki bir dosyaya vb.. loglama da yapılabilir. Ancak burada sadece console'a log basılması sağlanmaktadır:
.
Bir uygulamayı JConsole gibi araçlarla erişebilecek şekide JMX desteği eklenebilir. Bu sayfada bu desteğin nasıl ekleneceği görülebilir : www.fibiler.com/Bir-Java-Uygulamasini-JConsole-ile-Erisilebilir-Yapilmasi_Ipucu_148134
Yine kullanıcı adı ve şifre eklenerek güvenlik sağlanabilir : www.fibiler.com/JMX-ile-Erisime-Kullanici-Adi-ve-Sifre-Kontrolu-Koymak_Ipucu_148140
Buna ek olarak SSL desteği de eklenebilir. Ancak sertifikaya sahip olanlar JConsole ile uygulamanızı çağırabilir hale gelir.
Bunun için önce sunucu tarafı için bir JKS (Java Key Store) dosyası, client için (jconsole için) bir JKS (Java Key Store) dosyası yaratılır. İki dosya tek bir dosya da olabilir. JKS (Java Key Store) dosyası oluşturma işlemi keytool aracı ile yapılır. Üretilen dosyanın adı keystore.jks adı verilebilir. Sunucu tarafı aşağıdaki parametreler eklenerek açılır :
java .... -Djavax.net.ssl.keyStore=keystore.jks -Djavax.net.ssl.keyStorePassword=keystorepassword ...
Client (jconsole) tarafı ise aşağıdaki parametreler ile çalıştırılır :
jconsole -J-Djavax.net.ssl.trustStore=truststore -J-Djavax.net.ssl.trustStorePassword=truststorepassword
Jconsole bu şekilde çağrıldığında arada artık SSL şekilde konuşma olacaktır. Tam bir sunucu örneği şu şekilde olabilir :
-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=Q:\jmxremote.password -Dcom.sun.management.jmxremote.access.file=Q:\jmxremote.access -Dcom.sun.management.jmxremote.ssl=true -Djavax.net.ssl.keyStore=Q:\testjmx.jks -Djavax.net.ssl.keyStorePassword=mercury
Jconsole'un client örneği ise :
jconsole -J-Djavax.net.ssl.trustStore=Q:\testjmx.jks -J-Djavax.net.ssl.trustStorePassword=admin -J-Djava.util.logging.config.file=Q:\log.properties
Java'da JMX desteği olan bir uygulamaya Java kodu ile bağlanılbilir. Bunun için javax.management.remote paketi kullanılır. Aşağıda bir JMX desteği olan uygulamaya connection kuran örnek görülmektedir :
import java.io.IOException;
import java.net.MalformedURLException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class JMXClientTestApp {
public static final String JMX_URL_HEADER = "service:jmx:rmi:///jndi/rmi://";
public static final String JMX_URL_PATH = "/jmxrmi";
public static void main(String[] args)
throws MalformedURLException, IOException {
String url=JMX_URL_HEADER + "localhost:9999" + JMX_URL_PATH;
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(url));
System.out.println("Connected..." + connector.getConnectionId());
}
}
JMX URL service:jmx:rmi:///jndi/rmi://ip:port//jmxrmi şeklinde verilmektedir. Ekranda connected yazısı görülürse başarılı bağlantı kurulmuş demektir :
connected...rmi://10.1.35.12 1
10.1.35.12, local IP'dir.
Kullanıcı ve şifre kontrolü olan bir JMX uygulamasına da Java ile erişilebilir. Kod kısmı şu şekilde olur :
public class JMXClientTestApp {
public static final String JMX_URL_HEADER = "service:jmx:rmi:///jndi/rmi://";
public static final String JMX_URL_PATH = "/jmxrmi";
public static void main(String[] args)
throws MalformedURLException, IOException {
Map<String, Object> env = new HashMap<>();
env.put(JMXConnector.CREDENTIALS, new String[] { "admin", "Admin123." });
String url=JMX_URL_HEADER + "localhost:9999" + JMX_URL_PATH;
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(url), env);
System.out.println("Connected..." + connector.getConnectionId());
}
}
Görüldüğü gibi kullanıcı adı ve şifrenin verildiği bir Map yaratılıp connect() yöntemine aktarılmaktadır. Uygulama auth desteği ise şu şekilde eklenmiştir :
-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=E:\jmxremote.password -Dcom.sun.management.jmxremote.access.file=E:\jmxremote.access -Dcom.sun.management.jmxremote.ssl=false
Eğer uygulama SSL desteği ekli ise client çağırırken sertifika bilgisini göndermesi gerekir. Client açılırken şu paramterleleri vermelidir :
-Djavax.net.ssl.trustStore=Q:\testjmx.jks -Djavax.net.ssl.trustStorePassword=trustpassword
Bu iki parametre clietn uygulaması açılırken verilebilir. Bağlanma kodu şe şekilde olur :
public class JMXClientTestApp {
public static final String JMX_URL_HEADER = "service:jmx:rmi:///jndi/rmi://";
public static final String JMX_URL_PATH = "/jmxrmi";
public static void main(String[] args)
throws MalformedURLException, IOException {
Map<String, Object> env = new HashMap<>();
env.put(JMXConnector.CREDENTIALS, new String[] { "admin", "Admin123." });
env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());
String url=JMX_URL_HEADER + "localhost:9999" + JMX_URL_PATH;
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(url), env);
System.out.println("Connected with SSL" + connector.getConnectionId());
}
}
Map'e com.sun.jndi.rmi.factory.socket değerinin eklenmesi yeterlidir. Bu SSL ile konuşulacağını göstermektedir.