2011-09-01 29 views
8

Tôi có một chương trình yêu cầu động (tức là tại thời gian chạy) mở một ổ cắm có sẵn và bắt đầu một tác nhân JMX trên đó. Các tham số JMX này đang được đặt bên trong mã Java và không thông qua dòng lệnh. Điều này hoạt động tốt. Sau đó nó là cần thiết để giám sát (tức là vấn đề lệnh JMX vv) thông qua Java Visual VM từ xaLàm thế nào để thiết lập thông số môi trường hệ thống cổng từ xa JMX thông qua mã java để theo dõi từ xa?

Các đại lý máy chủ RMI trong chương trình là trên dòng ra khỏi quản lý hộp mô tả tại: http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html

Câu hỏi đặt ra Tôi có thể được tóm tắt là: Làm thế nào các thuộc tính dòng lệnh như vậy có thể được đặt ở mức hệ thống thông qua mã Java, để có thể sử dụng lược tả từ xa?

-Dcom.sun.management.jmxremote.port=1234 

Nếu thông số "jmxremote.port" và các thông số khác được đặt qua dòng lệnh, giám sát từ xa hoạt động tốt. Tôi đang cố gắng để tìm một cách để làm điều này thông qua Java và không thông qua dòng lệnh.

Chương trình không thể chỉ định cổng thông qua dòng lệnh vì cổng khả dụng mới phải được tìm ra tại thời gian chạy.

Quy trình cần theo dõi từ xa và hoạt động tốt tại địa phương. Nếu các thông số sau không được chỉ định tại dòng lệnh, Java Visual VM không kết nối với quy trình.

-Dcom.sun.management.jmxremote.port=1234 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Djava.rmi.server.hostname=10.0.0.128 

Tôi đã thử.

System.setProperty("com.sun.management.jmxremote.port",Integer.toString(port)); 

Đây là một trong những việc đầu tiên được thực hiện trong chương trình trước khi bắt đầu JMXConnectorServer. Thật không may nó không được công nhận. Chỉ các thuộc tính thời gian chạy (tức là được chỉ định thông qua dòng lệnh được công nhận cho kết nối JMX bởi Java Visual VM).

Cũng đi qua con đường đặc tính có thể được chiết xuất từ ​​các lớp học tập java nhưng không thể đạt được như thế nào để theo dõi tài sản "com.sun.management.jmxremote.port ="

public static void setEnv(Map<String, String> newenv) throws Exception { 
    Class[] classes = Collections.class.getDeclaredClasses(); 
    Map<String, String> env = System.getenv(); 

    for(Class cl : classes) { 

    if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { 

     Field field = cl.getDeclaredField("m"); 
     field.setAccessible(true); 

     Object obj = field.get(env); 
     Map<String, String> map = (Map<String, String>) obj; 

     //map.clear(); 
     map.putAll(newenv); 
    } 
    } 
} 

Bất kỳ trợ giúp sẽ được đánh giá cao !

+0

Bạn nên sửa câu hỏi ban đầu của bạn và bao gồm các mẫu mã mà bạn đã được đăng trong ý kiến. – Perception

Trả lời

0

System.setProperty() giống với tùy chọn dòng lệnh -D. Tuy nhiên rõ ràng bạn phải gọi nó đủ sớm để bạn thiết lập thuộc tính trước khi nó được đọc.

+0

Thuộc tính đang được đọc bởi trình lược tả cho lược tả từ xa là các thuộc tính mặc định được đặt tại thời điểm JVM bắt đầu. Trong trường hợp này khi mã java bắt đầu. Tôi bắt đầu trình bày vm java visual vm nhiều hơn sau đó và thiết lập thuộc tính trước khi JMXConnectorServer khởi động. Đang cố gắng tìm ra cách vượt qua tài sản để nó được phản ánh như một mức hệ thống jmx và có thể được phát hiện bởi vm visual java? Sẽ đánh giá cao bất kỳ đề xuất về cách gọi nó là "đủ sớm". – Devesh

+0

Chạy ứng dụng mà không có bất kỳ '-Dcom.sun.management.jmxremote' và thiết lập env này trong thời gian chạy sau đó là ý tưởng tồi vì JMX agent không được nạp, vì vậy nó không thể được sử dụng. – kbec

2

Nếu bạn không chỉ định bất kỳ jmxremote env làm thông số chạy thì nhân viên quản lý JMX không được tải. Bạn có thể thử này để tải động:

public static String loadJMXAgent(int port) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException { 
    System.setProperty("com.sun.management.jmxremote.port", Integer.toString(port)); 
    String name = ManagementFactory.getRuntimeMXBean().getName(); 
    VirtualMachine vm = VirtualMachine.attach(name.substring(0, name.indexOf('@'))); 

    String lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); 
    if (lca == null) { 
     Path p = Paths.get(System.getProperty("java.home")).normalize(); 
     if (!"jre".equals(p.getName(p.getNameCount()-1).toString().toLowerCase())) p = p.resolve("jre"); 
     File f = p.resolve("lib").resolve("management-agent.jar").toFile(); 
     if (!f.exists()) throw new IOException("Management agent not found"); 

     vm.loadAgent(f.getCanonicalPath(), "com.sun.management.jmxremote"); 
     lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); 
    } 
    vm.detach(); 
    return lca; 
} 

Bạn phải bao gồm jdk/lib/tools.jar

9

câu trả lời kbec cho thấy đường đi, nhưng đã không làm việc cho tôi - tuy nhiên bằng cách nhìn vào this post tôi đã có thể sửa đổi nó và có được một công việc dung dịch.

public static String loadJMXAgent(int port) throws IOException, 
     AttachNotSupportedException, AgentLoadException, 
     AgentInitializationException { 
    String name = ManagementFactory.getRuntimeMXBean().getName(); 
    VirtualMachine vm = VirtualMachine.attach(name.substring(0, 
      name.indexOf('@'))); 

    String lca = vm.getAgentProperties().getProperty(
      "com.sun.management.jmxremote.localConnectorAddress"); 
    if (lca == null) { 
     Path p = Paths.get(System.getProperty("java.home")).normalize(); 
     if (!"jre".equals(p.getName(p.getNameCount() - 1).toString() 
       .toLowerCase())) { 
      p = p.resolve("jre"); 
     } 
     File f = p.resolve("lib").resolve("management-agent.jar").toFile(); 
     if (!f.exists()) { 
      throw new IOException("Management agent not found"); 
     } 
     String options = String.format("com.sun.management.jmxremote.port=%d, " + 
       "com.sun.management.jmxremote.authenticate=false, " + 
       "com.sun.management.jmxremote.ssl=false", port); 
     vm.loadAgent(f.getCanonicalPath(), options); 
     lca = vm.getAgentProperties().getProperty(
       "com.sun.management.jmxremote.localConnectorAddress"); 
    } 
    vm.detach(); 
    return lca; 
} 

này hoạt động trong Eclipse tuy nhiên nhận được nó để làm việc tại các dòng lệnh là một vấn đề khác nhau - có một số cuộc thảo luận về đây này Why does using the Java Attach API fail on linux? (even though maven build completes) nhưng tôi tìm thấy thêm $ JAVA_HOME/lib/công cụ.jar để classpath của tôi giải quyết được vấn đề.

1

Tôi đã thử một số cách để xác định cổng jmxremote từ mã java để có một kết nối trên một cổng cụ thể và đã tìm ra những điều sau:

Trong trường hợp jmxremote arg được quy định: Nền tảng MBean máy chủ là bắt đầu bởi JVM, trước khi mã của tôi sửa đổi các jmxremote System.properties cần thiết. Mỗi máy chủ mbean có một đăng ký riêng của đậu. Các plaform và JVM mbeans không thể đăng ký bean của riêng chúng với nó theo cách khác.

Bạn có thể tạo máy chủ mbean thay thế sau khi bạn thiết lập thuộc tính cổng jmx. Điều đó sẽ lắng nghe trên cổng jmx chính xác, bạn đã chỉ định.

Bằng cách này bạn chọn máy chủ nền tảng:

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 

Bằng cách này của riêng:

System.setProperty("com.sun.management.jmxremote.port","9991"); 
//... 
MBeanServer mbsCustom=MBeanServerFactory.createMBeanServer(); 

cũng xem xét linux có nó loopback interface vì vậy bạn nên xác định đúng hostname một cách rõ ràng để lắng nghe.

Đây là không được đề xuất để sử dụng MBeanServer khác so với nền tảng, theo hướng dẫn sử dụng, nhưng tôi có thể tưởng tượng một số trường hợp tùy chọn dòng lệnh không phải là cách bạn có thể khởi chạy máy chủ.

0

Đây là những gì phù hợp với tôi. Tham chiếu Oracle JMX Tutorial. Tôi giả sử bạn đã biết làm thế nào để ngay SimpleMXBean được sử dụng trong ví dụ dưới đây.

package sample; 

import java.io.IOException; 
import java.lang.management.ManagementFactory; 
import java.rmi.registry.LocateRegistry; 
import java.util.HashMap; 
import java.util.Map; 

import javax.management.MBeanServer; 
import javax.management.ObjectName; 
import javax.management.remote.JMXConnectorServer; 
import javax.management.remote.JMXConnectorServerFactory; 
import javax.management.remote.JMXServiceURL; 

public class MBServerTest { 
    public static void loadJMXAgent(int port, MBeanServer mbs) throws IOException { 
     LocateRegistry.createRegistry(port); 
     System.out.println("Initialize the environment map"); 
     Map<String,Object> env = new HashMap<String,Object>(); 
     env.put("com.sun.management.jmxremote.authenticate", "false"); 
     env.put("com.sun.management.jmxremote.ssl", "false"); 
     System.out.println("Create an RMI connector server"); 
     JMXServiceURL url = 
      new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:"+port+"/jmxrmi"); 
     JMXConnectorServer cs = 
      JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); 

     // Start the RMI connector server. 
     // 
     System.out.println("Start the RMI connector server"); 
     cs.start(); 

    } 

    public static void main(String[] args) throws Exception { 
     MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
     loadJMXAgent(1199,mbs); 

     SimpleStandard cache = new SimpleStandard(); 

     ObjectName name = new ObjectName(
       "org.javalobby.tnt.jmx:type=ApplicationCacheMBean"); 
     mbs.registerMBean(cache, name); 
     imitateActivity(cache); 
    } 

    private static void imitateActivity(SimpleStandard cache) { 
     while (true) { 
      try { 
       cache.cacheObject("hello"); 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
      } 
     } 
    } 
} 
+0

Chăm sóc để giải thích bỏ phiếu tiêu cực? –

4

Bạn sẽ nói về điều này một cách không đúng. Vào thời điểm mã của bạn được gọi là bạn đã bỏ lỡ cơ hội cho các thuộc tính này có hiệu lực.

Bạn cần phải tạo một rmiregistry và sau đó tạo ra một JMXConnectorServer liên quan đến nền tảng MBeanServer như thế này:

private void createJmxConnectorServer() throws IOException { 
    LocateRegistry.createRegistry(1234); 
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost/jndi/rmi://localhost:1234/jmxrmi"); 
    JMXConnectorServer svr = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); 
    svr.start(); 
} 
Các vấn đề liên quan