Làm thế nào để có được các đối số VM từ bên trong ứng dụng Java?


162

Tôi cần kiểm tra xem một số tùy chọn có thể được truyền cho JVM được đặt rõ ràng hay có giá trị mặc định của nó.

Để cụ thể hơn: Tôi cần tạo một luồng cụ thể với kích thước ngăn xếp gốc cao hơn so với luồng mặc định, nhưng trong trường hợp người dùng muốn tự mình xử lý những thứ đó bằng cách chỉ định -Xsstùy chọn tôi muốn tạo tất cả các luồng với kích thước ngăn xếp mặc định (sẽ được chỉ định bởi người dùng trong tùy chọn -Xss).

Tôi đã kiểm tra các lớp như java.lang.Systemjava.lang.Runtime, nhưng chúng không cung cấp cho tôi bất kỳ thông tin hữu ích nào về các đối số VM.

Có cách nào để có được thông tin tôi cần không?

Câu trả lời:


183

Với mã này, bạn có thể nhận được các đối số JVM:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();

Đáng buồn thay, bạn không thể lấy Tên của lớp chính nếu nó được đưa ra trên dòng lệnh.
Daniel

@Daniel, điều này sẽ giúp bạn có được tên của lớp chính: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz

3
Nếu bạn được đảm bảo chạy trên JVM của Oracle và có mã để phân tích các đối số có thể hữu ích.
laz

2
@Vulcan Điều đó không nhận được đối số VM. Nó chứa tên lớp chính và mảng args cho phương thức chính.
dacongy

@dacongy Chưa bao giờ tôi ngụ ý rằng các đối số VM được đặt trong thuộc tính sun.java.commandhệ thống; Tôi đã nói rằng thuộc tính có thể được sử dụng để có được tên lớp chính (mặc dù tôi không đề cập đến, như @laz chỉ ra, thuộc tính đó chỉ có trên JVM của Oracle).
FThndry

206

Khi khởi động vượt qua điều này -Dname=value

và sau đó trong mã của bạn, bạn nên sử dụng

value=System.getProperty("name");

để có được giá trị đó


4
Tôi không thể sử dụng điều này để có được -Xdebug
petertc

20
Không chắc chắn tại sao câu trả lời này đã được nâng cấp như vậy, điều này chỉ lấy ra các tham số ứng dụng (được chỉ định bằng -D), chứ không phải tham số VM (được chỉ định bằng -X). Câu hỏi cụ thể là về thông số -X.
cleberz

4
Tôi đến đây vì tôi tin rằng các tham số kiểu -Dname=valuelà các đối số JVM và rằng không có sự khác biệt nội tại so với các -Xđối số. Trên thực tế, cả hai đều được truyền cho java chứ không phải ứng dụng tại dòng lệnh và bằng chứng là ví dụ, trong maven bạn có thể truyền cả hai như -Drun.jvmArguments=.... Tôi tin rằng đó là lý do tại sao nó được nâng cấp.
kap

Điều này không trả lời các nhu cầu áp phích ban đầu ở tất cả.
dan.m là người dùng 2331368

4
Có thể là ! nhưng nó googles trên đỉnh khi tìm kiếm "cách đọc các tùy chọn VM trong mã" và đó là lý do tại sao nó có liên quan)
62mkv

4

Tôi thấy rằng HotSpot liệt kê tất cả các đối số VM trong bean quản lý ngoại trừ -client và -server. Do đó, nếu bạn suy ra đối số -client / -server từ tên VM và thêm nó vào danh sách của bean quản lý thời gian chạy, bạn sẽ có được danh sách đầy đủ các đối số.

Đây là SSCCE:

import java.util.*;
import java.lang.management.ManagementFactory;

class main {
  public static void main(final String[] args) {
    System.out.println(fullVMArguments());
  }

  static String fullVMArguments() {
    String name = javaVmName();
    return (contains(name, "Server") ? "-server "
      : contains(name, "Client") ? "-client " : "")
      + joinWithSpace(vmArguments());
  }

  static List<String> vmArguments() {
    return ManagementFactory.getRuntimeMXBean().getInputArguments();
  }

  static boolean contains(String s, String b) {
    return s != null && s.indexOf(b) >= 0;
  }

  static String javaVmName() {
    return System.getProperty("java.vm.name");
  }

  static String joinWithSpace(Collection<String> c) {
    return join(" ", c);
  }

  public static String join(String glue, Iterable<String> strings) {
    if (strings == null) return "";
    StringBuilder buf = new StringBuilder();
    Iterator<String> i = strings.iterator();
    if (i.hasNext()) {
      buf.append(i.next());
      while (i.hasNext())
        buf.append(glue).append(i.next());
    }
    return buf.toString();
  }
}

Có thể được thực hiện ngắn hơn nếu bạn muốn các đối số trong a List<String>.

Lưu ý cuối cùng: Chúng tôi cũng có thể muốn mở rộng điều này để xử lý trường hợp hiếm gặp có khoảng trắng trong các đối số dòng lệnh.


Yup, vừa mới làm. Chúc mừng :)
Stefan Reich


0

Nếu bạn muốn toàn bộ dòng lệnh của quy trình java của mình, bạn có thể sử dụng: JvmArgument.java (sử dụng kết hợp JNA + / Proc để bao quát hầu hết các triển khai unix)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.