简体   繁体   English

从openjdk11访问com.sun。*类

[英]Access com.sun.* classes from openjdk11

I have a Spring Boot application and I want to use the class com.sun.management.ThreadMXBean , and the method getThreadAllocatedBytes to collect information about allocated bytes in my application. 我有一个Spring Boot应用程序,我想使用类com.sun.management.ThreadMXBean ,方法getThreadAllocatedBytes来收集有关我的应用程序中已分配字节的信息。 I dockerized it and used OpenJDK 11 in the dockerfile, because Oracle JDK cannot be dockerized. 我将它停靠并在dockerfile中使用OpenJDK 11,因为Oracle JDK无法进行停靠。 I'm using docker image jboss/base-jdk:11 and deploy the application in a Wildfly 16. 我正在使用docker image jboss/base-jdk:11并在Wildfly 16中部署该应用程序。

Unfortunately OpenJDK does not support the com.sun.* packages. 不幸的是,OpenJDK不支持com.sun.*包。 Is there any way I can work around this problem and use com.sun.management.ThreadMXBean.getThreadAllocatedBytes in an OpenJDK? 有什么方法可以解决这个问题,并在OpenJDK中使用com.sun.management.ThreadMXBean.getThreadAllocatedBytes

So, I just downloaded OpenJDK 11 and extracted its sources. 所以,我刚刚下载了OpenJDK 11并提取了它的来源。
Inside I found ThreadImpl , which implements java.lang.management.ThreadMXBean 在里面我找到了ThreadImpl ,它实现了java.lang.management.ThreadMXBean

在此输入图像描述

And infact you can find it under 事实上你可以找到它

在此输入图像描述

ThreadMXBean has indeed a getThreadAllocatedBytes method ThreadMXBean确实有一个getThreadAllocatedBytes方法

protected long[] getThreadAllocatedBytes(long[] ids) {
    boolean verified = verifyThreadAllocatedMemory(ids);

    long[] sizes = new long[ids.length];
    java.util.Arrays.fill(sizes, -1);

    if (verified) {
        getThreadAllocatedMemory1(ids, sizes);
    }
    return sizes;
}

So, this worked for me with AdoptJdk 11 (which is a build of OpenJdk): 所以,这对我有用AdoptJdk 11(这是OpenJdk的一个版本):

import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;

import java.lang.management.ThreadMXBean;

public class Test {
    public static void main(String[] args) {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); 
        try { 
            Method getBytes = threadMXBean.getClass().getMethod("getThreadAllocatedBytes", long.class); 
            getBytes.setAccessible(true); 

            long threadId = Thread.currentThread().getId();
            long bytes = (long)getBytes.invoke(threadMXBean, threadId);
            System.out.println(bytes);
        } catch (Throwable e) { 
            System.out.println(e);
        }
    }
}

Invoke with 调用

C:\workspaces\devtools\jdks\adoptjdk\jdk-11.0.2+9\bin\javac Test.java
C:\workspaces\devtools\jdks\adoptjdk\jdk-11.0.2+9\bin\java --add-exports jdk.management/com.sun.management.internal=ALL-UNNAMED Test

Also, in that docker image it works 此外,在该docker镜像中它可以工作

FROM jboss/base-jdk:11
COPY . /app/
WORKDIR /app
CMD java --add-exports jdk.management/com.sun.management.internal=ALL-UNNAMED Test

And run it in docker: 并在docker中运行它:

docker build -t openjdktest .
docker run -it openjdktest

EDIT 编辑

Oh, there seems to be an even simpler alternative. 哦,似乎有一个更简单的选择。 Just cast your ThreadMXBean object directly to com.sun.management.ThreadMXBean : 只需将ThreadMXBean对象直接转换为com.sun.management.ThreadMXBean

import java.lang.management.ManagementFactory;
import com.sun.management.ThreadMXBean;

public class Test {
    public static void main(String[] args) {
        ThreadMXBean threadMXBean = (ThreadMXBean)ManagementFactory.getThreadMXBean(); 
        long bytes = threadMXBean.getThreadAllocatedBytes(Thread.currentThread().getId());
        System.out.println(bytes);
    }
}

This can be run, even without the --add-exports JVM argument. 即使没有--add-exports JVM参数,也可以运行它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM